#include #include #include "thickenings.h" #include "queue.h" #define SWAP(t, a, b) do {t tmp = a; a = b; b = tmp;} while(0) int edgelist_contains(edgelist_t *list, int needle) { while(list) { if(list->to == needle) return 1; list = list->next; } return 0; } edgelist_t *edgelist_add(edgelist_t *list, int new, edgelist_t *storage, int *storage_index) { edgelist_t *new_link = &storage[*storage_index]; new_link->next = list; new_link->to = new; (*storage_index)++; return new_link; } int main(int argc, const char *argv[]) { unsigned long left_invariance = atoi(argv[2]); unsigned long right_invariance = atoi(argv[3]); semisimple_type_t type; type.n = 1; type.factors = (simple_type_t*)malloc(type.n*sizeof(simple_type_t)); type.factors[0].series = 'B'; type.factors[0].rank = atoi(argv[1]); char alphabet[] = "abcdefghijklmnopqrstuvwxyz"; char buffer[1024], buffer2[1024]; node_t *graph; int *leftbuf, *rightbuf; edgelist_t *edgelists; int *words; int rank, order, hyperplanes, cosets; // initialize rank = coxeter_rank(type); order = coxeter_order(type); hyperplanes = coxeter_hyperplanes(type); graph = (node_t*)malloc(order*sizeof(node_t)); leftbuf = (int*)malloc(order*rank*sizeof(int)); rightbuf = (int*)malloc(order*rank*sizeof(int)); edgelists = (edgelist_t*)malloc(4*order*hyperplanes*sizeof(edgelist_t)); words = (int*)malloc(order*hyperplanes*sizeof(int)); for(int i = 0; i < order; i++) { graph[i].left = &leftbuf[rank*i]; graph[i].right = &rightbuf[rank*i]; } // generate graph cosets = prepare_simplified_graph(type, left_invariance, right_invariance, graph, edgelists, words); // do something fprintf(stderr, "There are %d double cosets.\n", cosets); // cleanup free(leftbuf); free(rightbuf); free(graph); free(edgelists); free(words); } /* int main(int argc, const char *argv[]) { semisimple_type_t type; node_t *graph; int *leftbuf, *rightbuf; edgelist_t *edgelists; edgelist_t *edgelists_simplified; int edgelists_simplified_used; int *words; int rank, order, max_wordlength; int *reduced, *group, *simplified; int *seen; int current; edgelist_t *edge, *previous; queue_t queue; char alphabet[] = "abcdefghijklmnopqrstuvwxyz"; char buffer[1024], buffer2[1024]; int ncosets; node_t *simplified_graph; // left and right invariances as bitmasks // int left = ~(1 << (atoi(argv[1]) - atoi(argv[3]))); // int right = ~(1 << (atoi(argv[1]) - atoi(argv[2]))); int left = atoi(argv[2]); int right = atoi(argv[3]); type.n = 1; type.factors = (simple_type_t*)malloc(type.n*sizeof(simple_type_t)); type.factors[0].series = 'B'; type.factors[0].rank = atoi(argv[1]); rank = coxeter_rank(type); order = coxeter_order(type); graph = (node_t*)malloc(order*sizeof(node_t)); leftbuf = (int*)malloc(rank*order*sizeof(int)); rightbuf = (int*)malloc(rank*order*sizeof(int)); for(int i = 0; i < order; i++) { graph[i].left = &leftbuf[i*rank]; graph[i].right = &rightbuf[i*rank]; } prepare_graph(type, graph, &edgelists, &words); reduced = (int*)malloc(order*sizeof(int)); group = (int*)malloc(order*sizeof(int)); simplified = (int*)malloc(order*sizeof(int)); for(int i = 0; i < order; i++) { group[i] = -1; reduced[i] = i; } // step 1: group for(int i = 0; i < order; i++) { if(group[i] != -1) continue; queue_init(&queue); queue_put(&queue, i); while((current = queue_get(&queue)) != -1) { if(group[current] != -1) continue; group[current] = i; for(int j = 0; j < rank; j++) { if(left & (1 << j)) queue_put(&queue, graph[current].left[j]); if(right & (1 << j)) queue_put(&queue, graph[current].right[j]); } } } // step 2: find minimum for(int i = 0; i < order; i++) if(graph[i].wordlength < graph[reduced[group[i]]].wordlength) reduced[group[i]] = i; // step 3: assign minimum to all for(int i = 0; i < order; i++) reduced[i] = reduced[group[i]]; // step 4: assign indices to cosets ncosets = 0; for(int i = 0; i < order; i++) if(reduced[i] == i) simplified[i] = ncosets++; for(int i = 0; i < order; i++) simplified[i] = simplified[reduced[i]]; fprintf(stderr, "Number of double cosets: %d\n\n", ncosets); max_wordlength = coxeter_hyperplanes(type); simplified_graph = (node_t*) malloc(ncosets*sizeof(node_t)); edgelists_simplified = (edgelist_t*) malloc(2*max_wordlength*order*sizeof(edgelist_t)); seen = (int*) malloc(ncosets*sizeof(int)); edgelists_simplified_used = 0; // step 5: set up nodes from minima current = 0; for(int i = 0; i < order; i++) if(reduced[i] == i) { // is minimum simplified_graph[simplified[i]].word = graph[i].word; simplified_graph[simplified[i]].wordlength = graph[i].wordlength; simplified_graph[simplified[i]].opposite = simplified[graph[i].opposite]; simplified_graph[simplified[i]].bruhat_lower = (edgelist_t*)0; simplified_graph[simplified[i]].bruhat_higher = (edgelist_t*)0; } // some output for(int i = 0; i < ncosets; i++) fprintf(stderr, "%s <=> %s\n", simplified_graph[i].wordlength == 0 ? "1" : alphabetize(simplified_graph[i].word, simplified_graph[i].wordlength, alphabet, buffer), simplified_graph[simplified_graph[i].opposite].wordlength == 0 ? "1" : alphabetize(simplified_graph[simplified_graph[i].opposite].word, simplified_graph[simplified_graph[i].opposite].wordlength, alphabet, buffer2)); // step 6: find order relations for(int i = 0; i < order; i++) { edge = graph[i].bruhat_lower; while(edge) { int this = simplified[i]; int that = simplified[edge->to]; if(this != that) { // found something if(!edgelist_contains(simplified_graph[this].bruhat_lower, that)) simplified_graph[this].bruhat_lower = edgelist_add(simplified_graph[this].bruhat_lower, that, edgelists_simplified, &edgelists_simplified_used); ERROR(simplified_graph[this].wordlength <= simplified_graph[that].wordlength, "The order assumption is being violated!\n"); } edge = edge->next; } } fprintf(stderr, "\nAdded %d edges.\n\n", edgelists_simplified_used); // step 7: remove redundant edges for(int i = 0; i < ncosets; i++) { memset(seen, 0, ncosets*sizeof(int)); queue_init(&queue); for(int len = 1; len <= simplified_graph[i].wordlength; len++) { edge = simplified_graph[i].bruhat_lower; previous = (edgelist_t*)0; while(edge) { // only look at edges of this length now if(simplified_graph[i].wordlength - simplified_graph[edge->to].wordlength != len) { // we only consider edges of length len in this pass previous = edge; } else if(seen[edge->to]) { // this edge is redundant, remove it // fprintf(stderr, "removing edge from %d to %d\n", i, edge->to); if(previous) previous->next = edge->next; else simplified_graph[i].bruhat_lower = edge->next; } else { // this edge was not redundant, add to seen previous = edge; seen[edge->to] = 1; queue_put(&queue, edge->to); } edge = edge->next; } // calculate transitive closure of seen nodes while((current = queue_get(&queue)) != -1) { edge = simplified_graph[current].bruhat_lower; while(edge) { if(!seen[edge->to]) { seen[edge->to] = 1; queue_put(&queue, edge->to); } edge = edge->next; } } } } // step 8: revert order for(int i = 0; i < ncosets; i++) { edge = simplified_graph[i].bruhat_lower; while(edge) { simplified_graph[edge->to].bruhat_higher = edgelist_add(simplified_graph[edge->to].bruhat_higher, i, edgelists_simplified, &edgelists_simplified_used); edge = edge->next; } } // output as graphviz dot file fprintf(stdout, "digraph test123 {\n"); for(int i = 0; i < ncosets; i++) { edge = simplified_graph[i].bruhat_lower; while(edge) { fprintf(stdout, "%s -> %s;\n", alphabetize(simplified_graph[i].word, simplified_graph[i].wordlength, alphabet, buffer), alphabetize(simplified_graph[edge->to].word, simplified_graph[edge->to].wordlength, alphabet, buffer2)); edge = edge->next; } } fprintf(stdout, "}\n"); long nthickenings = enumerate_balanced_thickenings(type, simplified_graph, ncosets, alphabet, stdout); fprintf(stderr, "Found %ld balanced thickenings.\n", nthickenings); free(seen); free(simplified_graph); free(edgelists_simplified); free(type.factors); free(graph); free(edgelists); free(words); free(reduced); free(group); free(simplified); free(leftbuf); free(rightbuf); return 0; } */