From a17c6fb06e05dd288f6c7edee41ad5b1388d38ae Mon Sep 17 00:00:00 2001 From: Florian Stecker Date: Tue, 26 Jul 2016 10:09:34 +0200 Subject: [PATCH] Generate + Process --- Makefile | 27 ++++-- generate.c | 88 ++++++++++++++++++ process.c | 179 +++++++++++++++++++++++++++++++++++++ thickenings.c | 243 +++++++++++++++++--------------------------------- thickenings.h | 32 +++++++ 5 files changed, 400 insertions(+), 169 deletions(-) create mode 100644 generate.c create mode 100644 process.c create mode 100644 thickenings.h diff --git a/Makefile b/Makefile index c7857df..37d9b50 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,25 @@ +HEADERS=coxeter.h thickenings.h queue.h +OPTIONS=-O0 -g -std=gnu99 -all: thickenings +all: generate process -thickenings: thickenings.o coxeter.o - gcc -O3 -o thickenings thickenings.o coxeter.o -lgsl -lcblas +generate: generate.o coxeter.o thickenings.o + gcc $(OPTIONS) -o generate generate.o thickenings.o coxeter.o -lgsl -lcblas -thickenings.o: thickenings.c coxeter.h - gcc -O3 -c thickenings.c -std=gnu99 +process: process.o coxeter.o thickenings.o + gcc $(OPTIONS) -o process process.o thickenings.o coxeter.o -lgsl -lcblas -coxeter.o: coxeter.c coxeter.h - gcc -O3 -c coxeter.c -std=gnu99 +generate.o: generate.c $(HEADERS) + gcc $(OPTIONS) -c generate.c + +process.o: process.c $(HEADERS) + gcc $(OPTIONS) -c process.c + +thickenings.o: thickenings.c $(HEADERS) + gcc $(OPTIONS) -c thickenings.c + +coxeter.o: coxeter.c $(HEADERS) + gcc $(OPTIONS) -c coxeter.c clean: - rm -f thickenings thickenings.o coxeter.o + rm -f generate thickenings.o coxeter.o generate.o process.o diff --git a/generate.c b/generate.c new file mode 100644 index 0000000..37ab7eb --- /dev/null +++ b/generate.c @@ -0,0 +1,88 @@ +#include +#include + +#include "coxeter.h" +#include "queue.h" +#include "thickenings.h" + +int main(int argc, const char *argv[]) +{ + semisimple_type_t type; + + // heap stuff + node_t *graph; + int *left, *right; + edgelist_t *edgelists; + int *words; + + int rank, order; + + char string_buffer1[1000]; + const char *alphabet = "abcdefghijklmnopqrstuvwxyz"; + + ERROR(argc < 2, "Too few arguments!\n"); + + type.n = argc - 1; + type.factors = (simple_type_t*)malloc((argc-1)*sizeof(simple_type_t)); + for(int i = 0; i < argc - 1; i++) { + type.factors[i].series = argv[i+1][0]; + type.factors[i].rank = argv[i+1][1] - '0'; + ERROR(argv[i+1][0] < 'A' || argv[i+1][0] > 'I' || argv[i+1][1] < '1' || argv[i+1][1] > '9', "Arguments must be Xn with X out of A-I and n out of 0-9\n"); + } + + rank = coxeter_rank(type); + order = coxeter_order(type); + + ERROR(strlen(alphabet) < rank, "The alphabet has too few letters\n"); + + // initialize + + graph = (node_t*)malloc(order*sizeof(node_t)); + left = (int*)malloc(order*rank*sizeof(int)); + right = (int*)malloc(order*rank*sizeof(int)); + + for(int i = 0; i < order; i++) { + graph[i].left = &left[rank*i]; + graph[i].right = &right[rank*i]; + } + + // generate graph + + prepare_graph(type, graph, &edgelists, &words); + + // print stuff + + int hyperplane_count = 0; + for(int i = 0; i < order; i++) + if(graph[i].is_hyperplane_reflection) + hyperplane_count++; + + fprintf(stderr, "Rank: %d\t\tOrder: %d\t\tHyperplanes: %d\n", rank, order, hyperplane_count); + fprintf(stderr, "\n"); + fprintf(stderr, "Group elements: \n"); + for(int i = 0, wl = 0; i < order; i++) { + if(i == 0) { + fprintf(stderr, "1"); + } else if(graph[i].wordlength > wl) { + fprintf(stderr, "\n%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1)); + wl = graph[i].wordlength; + } else + fprintf(stderr, "%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1)); + } + fprintf(stderr, "\n\n"); + + // enumerate balanced thickenings + + fwrite(&type.n, sizeof(int), 1, stdout); + fwrite(type.factors, sizeof(simple_type_t), type.n, stdout); + enumerate_balanced_thickenings(type, graph, alphabet, stdout); + + free(graph); + free(left); + free(right); + free(edgelists); + free(words); + free(type.factors); + + return 0; +} diff --git a/process.c b/process.c new file mode 100644 index 0000000..9c68df8 --- /dev/null +++ b/process.c @@ -0,0 +1,179 @@ +#include +#include +#include + +#include "thickenings.h" +#include "coxeter.h" +#include "queue.h" + +#define SWAP(t, a, b) do {t tmp = a; a = b; b = tmp;} while(0) + +char *stringify_SLn1_permutation(int *word, int wordlength, int rank, char *str) +{ + for(int i = 0; i <= rank; i++) + str[i] = '1' + i; + str[rank+1] = 0; + + for(int i = 0; i < wordlength; i++) { + char tmp = str[word[i]]; + str[word[i]] = str[word[i]+1]; + str[word[i]+1] = tmp; + } + return str; +} + + +char *stringify_Onn1_permutation(int *word, int wordlength, int rank, char *str) +{ + for(int i = 0; i <= rank*2; i++) + str[i] = '1' + i; + str[2*rank+1] = 0; + + for(int i = 0; i < wordlength; i++) { + if(word[i] == 0) + SWAP(char, str[rank-1], str[rank+1]); + else { + SWAP(char, str[rank-word[i]], str[rank-word[i]-1]); + SWAP(char, str[rank+word[i]], str[rank+word[i]+1]); + } + } + return str; +} + +int main(int argc, const char *argv[]) +{ + FILE *infile; + struct stat st; + int rank, order; + semisimple_type_t type; + int n; + int *thickenings, *level; + node_t *graph; + int *left, *right; + int *left_invariant, *right_invariant; + edgelist_t *edgelists; + int *words; + + queue_t queue; + int current; + int *seen; + int *generators; + int ngens; + + char string_buffer1[1000]; + const char *alphabet = "abcdefghijklmnopqrstuvwxyz"; + + // parse arguments + + if(argc < 2) + infile = stdin; + else + infile = fopen(argv[1], "rb"); + + fread(&type.n, sizeof(int), 1, infile); // we completely trust the input data + type.factors = malloc(type.n * sizeof(simple_type_t)); + fread(type.factors, sizeof(simple_type_t), type.n, infile); + + // get graph + + rank = coxeter_rank(type); + order = coxeter_order(type); + ERROR(strlen(alphabet) < rank, "The alphabet has too few letters\n"); + graph = (node_t*)malloc(order*sizeof(node_t)); + left = (int*)malloc(order*rank*sizeof(int)); + right = (int*)malloc(order*rank*sizeof(int)); + left_invariant = (int*)malloc(rank*sizeof(int)); + right_invariant = (int*)malloc(rank*sizeof(int)); + seen = (int*)malloc(order*sizeof(int)); + generators = (int*)malloc(order*sizeof(int)); + level = (int*)malloc(order*sizeof(int)); + for(int i = 0; i < order; i++) { + graph[i].left = &left[i*rank]; + graph[i].right = &right[i*rank]; + } + prepare_graph(type, graph, &edgelists, &words); + + // finally do stuff + + while(fread(level, sizeof(int), order, infile) == order) { + + for(int j = 0; j < rank; j++) { + left_invariant[j] = 1; + right_invariant[j] = 1; + } + for(int j = 0; j < order; j++) { + for(int k = 0; k < rank; k++) { + if(level[j] == 0 && level[graph[j].left[k]] != 0 || level[j] != 0 && level[graph[j].left[k]] == 0) + left_invariant[k] = 0; + if(level[j] == 0 && level[graph[j].right[k]] != 0 || level[j] != 0 && level[graph[j].right[k]] == 0) + right_invariant[k] = 0; + } + } + + ngens = 0; + memset(generators, 0, order*sizeof(int)); + for(int j = 0; j < order; j++) { + if(level[j] == -1 && generators[j] == 0) { // ignore the generator, if it is equivalent to one already seen + ngens++; + queue_init(&queue); + queue_put(&queue, j); + while((current = queue_get(&queue)) != -1) { + if(generators[current] == 0) { // visit everyone only once + generators[current] = ngens; + for(int k = 0; k < rank; k++) { + if(left_invariant[k]) + queue_put(&queue, graph[current].left[k]); + if(right_invariant[k]) + queue_put(&queue, graph[current].right[k]); + } + } + } + } + } + + printf("left: "); + for(int j = 0; j < rank; j++) + printf("%c", left_invariant[j] ? alphabet[j] : ' '); + printf(" right: "); + for(int j = 0; j < rank; j++) + printf("%c", right_invariant[j] ? alphabet[j] : ' '); + printf(" generators: "); + + memset(seen, 0, order*sizeof(int)); + for(int i = 0; i < order; i++) { + if(generators[i] != 0 && seen[generators[i]-1] == 0) { + seen[generators[i]-1] = 1; + // if(type.n == 1 && type.factors[0].series == 'A') + // printf("%s ", stringify_SLn1_permutation(graph[i].word, graph[i].wordlength, rank, string_buffer1)); + // else if(type.n == 1 && (type.factors[0].series == 'B' || type.factors[0].series == 'C')) + // printf("%s ", stringify_Onn1_permutation(graph[i].word, graph[i].wordlength, rank, string_buffer1)); + // else + if(i == 0) + printf("1 "); + else + printf("%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1)); + } + } + + printf("\n"); + } + + if(infile != stdin) + fclose(infile); + + // cleanup + + free(thickenings); + free(edgelists); + free(words); + free(graph); + free(left); + free(right); + free(right_invariant); + free(left_invariant); + free(seen); + free(generators); + free(type.factors); + + return 0; +} diff --git a/thickenings.c b/thickenings.c index 86396e1..9f0530a 100644 --- a/thickenings.c +++ b/thickenings.c @@ -6,30 +6,11 @@ #include #include +#include "thickenings.h" #include "coxeter.h" #include "queue.h" -#define DEBUG(msg, ...) do{fprintf(stderr, msg, ##__VA_ARGS__); }while(0) - -#define MAX_THICKENINGS 10000 - -typedef struct _edgelist { - int to; - struct _edgelist *next; -} edgelist_t; - -typedef struct { - int *word; - int wordlength; - int *left; - int *right; - int opposite; - edgelist_t *bruhat_lower; - edgelist_t *bruhat_higher; - int is_hyperplane_reflection; // boolean value -} node_t; - -static char *alphabetize(int *word, int len, const char *alphabet, char *buffer) +char *alphabetize(int *word, int len, const char *alphabet, char *buffer) { int i = 0; for(i = 0; i < len; i++) @@ -39,30 +20,30 @@ static char *alphabetize(int *word, int len, const char *alphabet, char *buffer) return buffer; } -static void print_balanced_thickening(int rank, int order, const int *thickening, const int *left_invariant, const int *right_invariant, const char *alphabet) +void print_balanced_thickening(int rank, int order, const int *thickening, const int *left_invariant, const int *right_invariant, const char *alphabet, FILE *f) { for(int i = 0; i < order; i++) { if(thickening[i]) - printf("x"); + fprintf(f, "x"); else - printf("0"); + fprintf(f, "0"); } - printf(" left: "); + fprintf(f, " left: "); for(int j = 0; j < rank; j++) if(left_invariant[j]) - printf("%c", alphabet[j]); + fprintf(f, "%c", alphabet[j]); else - printf(" "); + fprintf(f, " "); - printf(" right: "); + fprintf(f, " right: "); for(int j = 0; j < rank; j++) if(right_invariant[j]) - printf("%c", alphabet[j]); + fprintf(f, "%c", alphabet[j]); else - printf(" "); + fprintf(f, " "); - printf("\n"); + fprintf(f, "\n"); } static int compare_wordlength(const void *a, const void *b, void *gr) @@ -74,72 +55,34 @@ static int compare_wordlength(const void *a, const void *b, void *gr) return graph[i].wordlength - graph[j].wordlength; } -int main(int argc, const char *argv[]) +void prepare_graph(semisimple_type_t type, node_t *graph, edgelist_t **edgelists_pointer, int **words_pointer) // the edgelists_pointer and words_pointer arguments are just for freeing afterwards { queue_t queue; - // heap stuff - node_t *graph, *graph_unsorted; - int *graph_data; - int *wordlength_order, *reverse_wordlength_order, *seen, *level; - int *words; - edgelist_t *edgelists; - int *left, *right; - int *left_invariant, *right_invariant; - - edgelist_t *edge, *previous; int rank, order; - semisimple_type_t type; - int edgelist_count, hyperplane_count, max_wordlength; - int current, head, i, current_level; - int is_fat, is_slim; - int thickenings_count, fat_count, slim_count, balanced_count; + edgelist_t *edge, *previous; + int edgelist_count, max_wordlength, hyperplane_count; + int current; - int *balanced_thickenings; + int *graph_data; + node_t *graph_unsorted; + int *wordlength_order, *reverse_wordlength_order, *seen, *words; + edgelist_t *edgelists; - char *string_buffer1, *string_buffer2; - - const char *alphabet = "abcdefghijklmnopqrstuvwxyz"; - - ERROR(argc < 2, "Too few arguments!\n"); - - type.n = argc - 1; - type.factors = (simple_type_t*)malloc((argc-1)*sizeof(simple_type_t)); - for(int i = 0; i < argc - 1; i++) { - type.factors[i].series = argv[i+1][0]; - type.factors[i].rank = argv[i+1][1] - '0'; - ERROR(argv[i+1][0] < 'A' || argv[i+1][0] > 'I' || argv[i+1][1] < '1' || argv[i+1][1] > '9', "Arguments must be Xn with X out of A-I and n out of 0-9\n"); - } + // initialize rank = coxeter_rank(type); order = coxeter_order(type); - ERROR(strlen(alphabet) < rank, "The alphabet has too few letters\n"); - - // DEBUG("The group has rank %d and order %d\n", rank, order); - - graph = (node_t*)malloc(order*sizeof(node_t)); - graph_unsorted = (node_t*)malloc(order*sizeof(node_t)); graph_data = (int*)malloc(order*rank*sizeof(int)); + graph_unsorted = (node_t*)malloc(order*sizeof(node_t)); wordlength_order = (int*)malloc(order*sizeof(int)); reverse_wordlength_order = (int*)malloc(order*sizeof(int)); seen = (int*)malloc(order*sizeof(int)); - level = (int*)malloc(order*sizeof(int)); - left = (int*)malloc(order*rank*sizeof(int)); - right = (int*)malloc(order*rank*sizeof(int)); - left_invariant = (int*)malloc(rank*sizeof(int)); - right_invariant = (int*)malloc(rank*sizeof(int)); - balanced_thickenings = (int*)malloc(MAX_THICKENINGS*order*sizeof(int)); - - // DEBUG("Generate Cayley graph\n"); - - generate_coxeter_graph(type, graph_data); for(int i = 0; i < order; i++) { - graph_unsorted[i].left = &left[i*rank]; - graph_unsorted[i].right = &right[i*rank]; - for(int j = 0; j < rank; j++) - graph_unsorted[i].left[j] = graph_data[i*rank + j]; + graph_unsorted[i].left = graph[i].left; + graph_unsorted[i].right = graph[i].right; graph_unsorted[i].word = 0; graph_unsorted[i].wordlength = INT_MAX; graph_unsorted[i].bruhat_lower = 0; @@ -147,7 +90,15 @@ int main(int argc, const char *argv[]) graph_unsorted[i].is_hyperplane_reflection = 0; } - // DEBUG("Find wordlengths\n"); + // get coxeter graph + + generate_coxeter_graph(type, graph_data); + + for(int i = 0; i < order; i++) + for(int j = 0; j < rank; j++) + graph_unsorted[i].left[j] = graph_data[i*rank + j]; + + // find wordlengths graph_unsorted[0].wordlength = 0; queue_init(&queue); @@ -167,10 +118,7 @@ int main(int argc, const char *argv[]) if(graph_unsorted[i].wordlength > max_wordlength) max_wordlength = graph_unsorted[i].wordlength; - string_buffer1 = (char*)malloc((max_wordlength+1)*sizeof(char)); - string_buffer2 = (char*)malloc((max_wordlength+1)*sizeof(char)); - - // DEBUG("Sort by wordlength\n"); + // sort by wordlength for(int i = 0; i < order; i++) wordlength_order[i] = i; @@ -183,7 +131,7 @@ int main(int argc, const char *argv[]) graph[i].left[j] = reverse_wordlength_order[graph[i].left[j]]; // rewrite references } - // DEBUG("Find words\n"); + // find words words = (int*)malloc(order*max_wordlength*sizeof(int)); memset(words, 0, order*max_wordlength*sizeof(int)); @@ -202,7 +150,7 @@ int main(int argc, const char *argv[]) } } - // DEBUG("Generate right edges\n"); + // generate right edges for(int i = 0; i < order; i++) { for(int j = 0; j < rank; j++) { @@ -214,7 +162,7 @@ int main(int argc, const char *argv[]) } } - // DEBUG("Find opposites\n"); + // find opposites node_t *longest = &graph[order-1]; for(int i = 0; i < order; i++) { @@ -224,7 +172,7 @@ int main(int argc, const char *argv[]) graph[i].opposite = current; } - // DEBUG("Enumerate hyperplanes\n"); // every right edge is a reflection along a hyperplane; calculate what this reflection does to the identity + // enumerate hyperplanes hyperplane_count = 0; for(int i = 0; i < order; i++) { @@ -245,10 +193,10 @@ int main(int argc, const char *argv[]) } } - // DEBUG("The Weyl chambers are bounded by %d hyperplanes\n", hyperplane_count); - // DEBUG("Generate folding order\n"); + // generate folding order edgelists = (edgelist_t*)malloc(order*hyperplane_count*sizeof(edgelist_t)); + edgelist_count = 0; for(int i = 0; i < order; i++) { if(graph[i].is_hyperplane_reflection) { for(int j = 0; j < order; j++) { @@ -270,7 +218,7 @@ int main(int argc, const char *argv[]) } } - // DEBUG("Remove redundant edges\n"); + // remove redundant edges for(int i = 0; i < order; i++) { memset(seen, 0, order*sizeof(int)); @@ -280,7 +228,7 @@ int main(int argc, const char *argv[]) previous = (edgelist_t*)0; while(edge) { if(seen[edge->to] && graph[i].wordlength - graph[edge->to].wordlength == len) { - // printf("deleting from %d to %d\n", i, edge->to); + // fprintf(stderr, "deleting from %d to %d\n", i, edge->to); if(previous) previous->next = edge->next; else @@ -308,7 +256,7 @@ int main(int argc, const char *argv[]) } } - // DEBUG("Reverse folding order\n"); + // reverse folding order for(int i = 0; i < order; i++) { edge = graph[i].bruhat_lower; @@ -321,21 +269,35 @@ int main(int argc, const char *argv[]) } } - printf("Rank: %d\t\tOrder: %d\t\tHyperplanes: %d\n", rank, order, hyperplane_count); - printf("\n"); - printf("Group elements: \n"); - for(int i = 0, wl = 0; i < order; i++) { - if(i == 0) { - printf("1"); - } else if(graph[i].wordlength > wl) { - printf("\n%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1)); - wl = graph[i].wordlength; - } else - printf("%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1)); - } - printf("\n\n"); + *edgelists_pointer = edgelists; + *words_pointer = words; - // DEBUG("Enumerate thickenings\n"); + free(graph_data); + free(graph_unsorted); + free(wordlength_order); + free(reverse_wordlength_order); + free(seen); +} + +void enumerate_balanced_thickenings(semisimple_type_t type, node_t *graph, const char *alphabet, FILE *outfile) +{ + int rank, order; + int *level; + int *left_invariant, *right_invariant; + long thickenings_count, fat_count, slim_count, balanced_count; + int is_fat, is_slim; + int current_level, head, current; + int i; + edgelist_t *edge; + + queue_t queue; + + rank = coxeter_rank(type); + order = coxeter_order(type); + + level = (int*)malloc(order*sizeof(int)); + left_invariant = (int*)malloc(rank*sizeof(int)); + right_invariant = (int*)malloc(rank*sizeof(int)); thickenings_count = fat_count = slim_count = balanced_count = 0; memset(level, 0, order*sizeof(int)); @@ -357,6 +319,8 @@ int main(int argc, const char *argv[]) } } + // we have a thickening, do something with it! + is_fat = is_slim = 1; for(int i = 0; i < order; i++) { if(level[graph[i].opposite] != 0) { @@ -376,10 +340,12 @@ int main(int argc, const char *argv[]) slim_count++; if(is_slim && is_fat) { ERROR(balanced_count >= MAX_THICKENINGS, "Too many balanced thickenings! Increase MAX_THICKENINGS\n"); - memcpy(&balanced_thickenings[balanced_count*order], level, order*sizeof(int)); + //memcpy(&balanced_thickenings[balanced_count*order], level, order*sizeof(int)); + fwrite(level, sizeof(int), order, outfile); balanced_count++; } + // print out the thickening if(is_fat && is_slim) { // check for invariances for(int j = 0; j < rank; j++) { @@ -394,9 +360,12 @@ int main(int argc, const char *argv[]) right_invariant[j] = 0; } } - print_balanced_thickening(rank, order, level, left_invariant, right_invariant, alphabet); + print_balanced_thickening(rank, order, level, left_invariant, right_invariant, alphabet, stderr); } + + // now find the next one! + // try to find empty spot to the left of "head" for(i = head - 1; i >= 0; i--) if(level[i] == 0) @@ -433,58 +402,10 @@ int main(int argc, const char *argv[]) level[i] = 0; } - printf("\n"); - printf("Found %d thickenings, %d fat, %d slim, %d balanced\n\n", thickenings_count, fat_count, slim_count, balanced_count); + fprintf(stderr, "\n"); + fprintf(stderr, "Found %ld thickenings, %ld fat, %ld slim, %ld balanced\n\n", thickenings_count, fat_count, slim_count, balanced_count); - - - /* - for(int i = 0; i < balanced_count; i++) { - // figure out invariances - for(int j = 0; j < rank; j++) { - left_invariant[j] = 1; - right_invariant[j] = 1; - } - - int *current_thickening = balanced_thickenings + i*order; - - for(int k = 0; k < order; k++) { - for(int j = 0; j < rank; j++) { - if(current_thickening[k] == 0 && current_thickening[graph[k].left[j]] != 0 || current_thickening[k] != 0 && current_thickening[graph[k].left[j]] == 0) - left_invariant[j] = 0; - if(current_thickening[k] == 0 && current_thickening[graph[k].right[j]] != 0 || current_thickening[k] != 0 && current_thickening[graph[k].right[j]] == 0) - right_invariant[j] = 0; - } - } - - printf("left: "); - for(int k = 0; k < rank; k++) - printf("%c", left_invariant[k] ? alphabet[k] : ' '); - printf(" right: "); - for(int k = 0; k < rank; k++) - printf("%c", right_invariant[k] ? alphabet[k] : ' '); - printf("\n"); - } - */ - - - free(edgelists); - free(words); - free(string_buffer1); - free(string_buffer2); - free(graph); - free(graph_unsorted); - free(graph_data); - free(wordlength_order); - free(reverse_wordlength_order); - free(seen); free(level); - free(left); - free(right); free(left_invariant); free(right_invariant); - free(type.factors); - free(balanced_thickenings); - - return 0; } diff --git a/thickenings.h b/thickenings.h new file mode 100644 index 0000000..89d387f --- /dev/null +++ b/thickenings.h @@ -0,0 +1,32 @@ +#ifndef THICKENINGS_H +#define THICKENINGS_H + +#include "coxeter.h" + +#define DEBUG(msg, ...) do{fprintf(stderr, msg, ##__VA_ARGS__); }while(0) + +#define MAX_THICKENINGS 1000000 + +typedef struct _edgelist { + int to; + struct _edgelist *next; +} edgelist_t; + +typedef struct { + int *word; + int wordlength; + int *left; + int *right; + int opposite; + edgelist_t *bruhat_lower; + edgelist_t *bruhat_higher; + int is_hyperplane_reflection; // boolean value +} node_t; + +char *alphabetize(int *word, int len, const char *alphabet, char *buffer); +void print_balanced_thickening(int rank, int order, const int *thickening, const int *left_invariant, const int *right_invariant, const char *alphabet, FILE *f); +static int compare_wordlength(const void *a, const void *b, void *gr); +void prepare_graph(semisimple_type_t type, node_t *graph, edgelist_t **edgelists_pointer, int **words_pointer); +void enumerate_balanced_thickenings(semisimple_type_t type, node_t *graph, const char *alphabet, FILE *outfile); + +#endif