diff --git a/.gitignore b/.gitignore index 9f47d23..3e9f59e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o +*.pdf enumerate idealbounds graph diff --git a/Makefile b/Makefile index 00946a3..5ffc62c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SPECIAL_OPTIONS=-O3 -flto -funroll-loops -Winline OPTIONS=-m64 -march=native -std=gnu99 -D_GNU_SOURCE $(SPECIAL_OPTIONS) NAME=enumerate-balanced-ideals -all: enumerate graph D2n dominant_weights +all: enumerate graph $(NAME).tar.bz2: $(NAME) $(HEADERS) enumerate.c weyl.c thickenings.c tar cjhf $(NAME).tar.bz2 $(NAME)/enumerate.c $(NAME)/weyl.c $(NAME)/thickenings.c $(NAME)/weyl.h $(NAME)/thickenings.h $(NAME)/queue.h $(NAME)/bitvec.h $(NAME)/Makefile $(NAME)/graph.c diff --git a/enumerate.c b/enumerate.c index 17243fc..0829754 100644 --- a/enumerate.c +++ b/enumerate.c @@ -9,353 +9,367 @@ char stringbuffer[100]; char stringbuffer2[100]; typedef struct { - doublequotient_t *dq; - int rank; - int order; - int positive; - int *buffer; - int level; + doublequotient_t *dq; + int rank; + int order; + int positive; + int *buffer; + int level; } info_t; static char* alphabetize(weylgroup_element_t *e, char *str) { - if(e->wordlength == 0) - sprintf(str, "1"); - else { - for(int j = 0; j < e->wordlength; j++) - str[j] = e->word[j] + 'a'; - str[e->wordlength] = 0; - } + if(e->wordlength == 0) + sprintf(str, "1"); + else { + for(int j = 0; j < e->wordlength; j++) + str[j] = e->word[j] + 'a'; + str[e->wordlength] = 0; + } - return str; + return str; } /* -int shorten(int i, unsigned long left, unsigned long right, doublequotient_t *dq, int rank) -{ + int shorten(int i, unsigned long left, unsigned long right, doublequotient_t *dq, int rank) + { int other, shorter = i; do { - i = shorter; - for(int j = 0; j < rank; j++) { - other = graph[shorter].left[j]; - if(left & (1 << j) && - graph[other].wordlength < graph[shorter].wordlength) - shorter = other; - other = graph[shorter].right[j]; - if(right & (1 << j) && - graph[other].wordlength < graph[shorter].wordlength) - shorter = other; - } + i = shorter; + for(int j = 0; j < rank; j++) { + other = graph[shorter].left[j]; + if(left & (1 << j) && + graph[other].wordlength < graph[shorter].wordlength) + shorter = other; + other = graph[shorter].right[j]; + if(right & (1 << j) && + graph[other].wordlength < graph[shorter].wordlength) + shorter = other; + } } while(shorter != i); return shorter; -} + } */ void balanced_thickening_callback(const bitvec_t *pos, int size, const enumeration_info_t *ei) { - static long totcount = 0; + static long totcount = 0; - if(ei->callback_data) { - info_t *info = (info_t*)ei->callback_data; + if(ei->callback_data) { + info_t *info = (info_t*)ei->callback_data; - unsigned long right_invariance = FIRSTBITS(info->rank); - unsigned long left_invariance = FIRSTBITS(info->rank); + unsigned long right_invariance = FIRSTBITS(info->rank); + unsigned long left_invariance = FIRSTBITS(info->rank); - int bit1, bit2left, bit2right, left, right; + int bit1, bit2left, bit2right, left, right; - for(int i = 0; i < size; i++) { - bit1 = i < size/2 ? bv_get_bit(pos, i) : !bv_get_bit(pos, size - 1 - i); - for(int j = 0; j < info->rank; j++) { - left = info->dq->cosets[i].min->left[j]->coset->index; - right = info->dq->cosets[i].min->right[j]->coset->index; - bit2left = left < size/2 ? bv_get_bit(pos, left) : !bv_get_bit(pos, size - 1 - left); - bit2right = right < size/2 ? bv_get_bit(pos, right) : !bv_get_bit(pos, size - 1 - right); - if(bit1 != bit2left) - left_invariance &= ~BIT(j); - if(bit1 != bit2right) - right_invariance &= ~BIT(j); - } - } + for(int i = 0; i < size; i++) { + bit1 = i < size/2 ? bv_get_bit(pos, i) : !bv_get_bit(pos, size - 1 - i); + for(int j = 0; j < info->rank; j++) { + left = info->dq->cosets[i].min->left[j]->coset->index; + right = info->dq->cosets[i].min->right[j]->coset->index; + bit2left = left < size/2 ? bv_get_bit(pos, left) : !bv_get_bit(pos, size - 1 - left); + bit2right = right < size/2 ? bv_get_bit(pos, right) : !bv_get_bit(pos, size - 1 - right); + if(bit1 != bit2left) + left_invariance &= ~BIT(j); + if(bit1 != bit2right) + right_invariance &= ~BIT(j); + } + } - printf("%4d left: ", totcount++); - for(int j = 0; j < info->rank; j++) - printf("%c", left_invariance & (1 << j) ? j + 'a' : ' '); - printf(" right: "); - for(int j = 0; j < info->rank; j++) - printf("%c", right_invariance & (1 << j) ? j + 'a' : ' '); + printf("%4d left: ", totcount++); + for(int j = 0; j < info->rank; j++) + printf("%c", left_invariance & (1 << j) ? j + 'a' : ' '); + printf(" right: "); + for(int j = 0; j < info->rank; j++) + printf("%c", right_invariance & (1 << j) ? j + 'a' : ' '); - if(info->buffer) { - bitvec_t low, high; - bv_copy(pos, &low); - bv_negate(pos, &high); + int length_profile[65]; // can't handle more that 64 positive roots anyway - // printf(" set: "); - // bv_print(stdout, &low, size/2); - // printf(" "); - // bv_print(stdout, &high, size/2); + memset(length_profile, 0, (info->positive+1)*sizeof(int)); - printf(" gen: "); + for(int i = 0; i < size; i++) { + bit1 = i < size/2 ? bv_get_bit(pos, i) : !bv_get_bit(pos, size - 1 - i); + if(bit1) + length_profile[info->dq->cosets[i].min->wordlength]++; + } + + printf(" length profile:"); + for(int i = 0; i <= info->positive; i++) + printf(" %d", length_profile[i]); + + if(info->buffer) { + bitvec_t low, high; + bv_copy(pos, &low); + bv_negate(pos, &high); + + // printf(" set: "); + // bv_print(stdout, &low, size/2); + // printf(" "); + // bv_print(stdout, &high, size/2); + + printf(" gen: "); - for(int i = 0; i < size/2; i++) { - if(!bv_get_bit(&high, i)) - continue; + for(int i = 0; i < size/2; i++) { + if(!bv_get_bit(&high, i)) + continue; - printf("%s ", alphabetize(info->dq->cosets[size-1-i].min, stringbuffer)); + printf("%s ", alphabetize(info->dq->cosets[size-1-i].min, stringbuffer)); - bv_difference(&high, &ei->principal_neg[size-1-i], &high); - bv_difference(&low, &ei->principal_pos[size-1-i], &low); - } + bv_difference(&high, &ei->principal_neg[size-1-i], &high); + bv_difference(&low, &ei->principal_pos[size-1-i], &low); + } - for(int i = size/2 - 1; i >= 0; i--) { - if(!bv_get_bit(&low, i)) - continue; + for(int i = size/2 - 1; i >= 0; i--) { + if(!bv_get_bit(&low, i)) + continue; - printf("%s ", alphabetize(info->dq->cosets[i].min, stringbuffer)); + printf("%s ", alphabetize(info->dq->cosets[i].min, stringbuffer)); - bv_difference(&low, &ei->principal_pos[i], &low); - } - } + bv_difference(&low, &ei->principal_pos[i], &low); + } + } - int max_length = 0; - for(int i = 0; i < size/2; i++) { - if(bv_get_bit(pos, i)) { - if(info->dq->cosets[i].max->wordlength > max_length) - max_length = info->dq->cosets[i].max->wordlength; - } else { - if(info->dq->cosets[size-i-1].max->wordlength > max_length) - max_length = info->dq->cosets[size-i-1].max->wordlength; - } - } - // printf(" max length: %d", max_length); + int max_length = 0; + for(int i = 0; i < size/2; i++) { + if(bv_get_bit(pos, i)) { + if(info->dq->cosets[i].max->wordlength > max_length) + max_length = info->dq->cosets[i].max->wordlength; + } else { + if(info->dq->cosets[size-i-1].max->wordlength > max_length) + max_length = info->dq->cosets[size-i-1].max->wordlength; + } + } + // printf(" max length: %d", max_length); - /* - if(info->buffer) { - printf(" generators:"); - queue_t queue; - int cur, left, right; - int *buffer = info->buffer; + /* + if(info->buffer) { + printf(" generators:"); + queue_t queue; + int cur, left, right; + int *buffer = info->buffer; - for(int i = 0; i < size/2; i++) { - buffer[i] = bv_get_bit(pos, i); - buffer[size-1-i] = !buffer[i]; - } - for(int i = size-1; i >= 0; i--) { - if(buffer[i]) { - weylgroup_element_t *shortest = shorten(i, left_invariance, right_invariance, info->dq); - printf(" %s", alphabetize(shortest, stringbuffer)); - buffer[i] = 0; - queue_init(&queue); - queue_put(&queue, i); - while((cur = queue_get(&queue)) != -1) { - for(doublecoset_list_t *current = info->dq->coset[cur].bruhat_lower; current; current = current->next) { - int idx = current->to - info->dq->cosets; - if(buffer[idx]) { - buffer[idx] = 0; - queue_put(&queue, idx); - } - } - for(int j = 0; j < info->rank; j++) { - left = info->dq->coset[cur].min.left[j] - info->dq->cosets; - if(left_invariance & (1 << j) && - info->graph[left].wordlength < info->graph[cur].wordlength && - buffer[left]) { - buffer[left] = 0; - queue_put(&queue, left); - } - right = info->graph[cur].left[j]; - if(right_invariance & (1 << j) && - info->graph[right].wordlength < info->graph[cur].wordlength && - buffer[right]) { - buffer[right] = 0; - queue_put(&queue, right); - } - } - } + for(int i = 0; i < size/2; i++) { + buffer[i] = bv_get_bit(pos, i); + buffer[size-1-i] = !buffer[i]; + } + for(int i = size-1; i >= 0; i--) { + if(buffer[i]) { + weylgroup_element_t *shortest = shorten(i, left_invariance, right_invariance, info->dq); + printf(" %s", alphabetize(shortest, stringbuffer)); + buffer[i] = 0; + queue_init(&queue); + queue_put(&queue, i); + while((cur = queue_get(&queue)) != -1) { + for(doublecoset_list_t *current = info->dq->coset[cur].bruhat_lower; current; current = current->next) { + int idx = current->to - info->dq->cosets; + if(buffer[idx]) { + buffer[idx] = 0; + queue_put(&queue, idx); + } + } + for(int j = 0; j < info->rank; j++) { + left = info->dq->coset[cur].min.left[j] - info->dq->cosets; + if(left_invariance & (1 << j) && + info->graph[left].wordlength < info->graph[cur].wordlength && + buffer[left]) { + buffer[left] = 0; + queue_put(&queue, left); + } + right = info->graph[cur].left[j]; + if(right_invariance & (1 << j) && + info->graph[right].wordlength < info->graph[cur].wordlength && + buffer[right]) { + buffer[right] = 0; + queue_put(&queue, right); + } + } + } + } + } + if(info->level >= 5) { + printf(" ids: [0"); + for(int i = 1; i < size/2; i++) + if(bv_get_bit(pos, i)) + printf(", %d", info->graph[i].id); + for(int i = 0; i < size/2; i++) + if(!bv_get_bit(pos, i)) + printf(", %d", info->graph[size-1-i].id); + printf("]"); + } + } + */ + + printf("\n"); } - } - if(info->level >= 5) { - printf(" ids: [0"); - for(int i = 1; i < size/2; i++) - if(bv_get_bit(pos, i)) - printf(", %d", info->graph[i].id); - for(int i = 0; i < size/2; i++) - if(!bv_get_bit(pos, i)) - printf(", %d", info->graph[size-1-i].id); - printf("]"); - } - } - */ - - printf("\n"); - } } void balanced_thickening_simple_callback(const bitvec_t *pos, int size, const enumeration_info_t *ei) { - long *count = (long*)ei->callback_data; + long *count = (long*)ei->callback_data; - if((++(*count)) % 100000000 == 0) { - bv_print(stderr, pos, size/2); - fprintf(stderr, "\n"); - } + if((++(*count)) % 100000000 == 0) { + bv_print(stderr, pos, size/2); + fprintf(stderr, "\n"); + } } int main(int argc, const char *argv[]) { - semisimple_type_t type; - unsigned long right_invariance, left_invariance; - int rank, order, positive; - int fixpoints; + semisimple_type_t type; + unsigned long right_invariance, left_invariance; + int rank, order, positive; + int fixpoints; - doublequotient_t *dq; + doublequotient_t *dq; - const char *alphabet = "abcdefghijklmnopqrstuvwxyz"; + const char *alphabet = "abcdefghijklmnopqrstuvwxyz"; - // read arguments + // read arguments - ERROR(argc < 2, "Too few arguments!\n"); + ERROR(argc < 2, "Too few arguments!\n"); - type.n = 0; - for(int i = 0; i < argc - 1; i++) { - if(argv[i+1][0] < 'A' || argv[i+1][0] > 'G') - break; - type.n++; - } + type.n = 0; + for(int i = 0; i < argc - 1; i++) { + if(argv[i+1][0] < 'A' || argv[i+1][0] > 'G') + break; + type.n++; + } - type.factors = (simple_type_t*)malloc(type.n*sizeof(simple_type_t)); - for(int i = 0; i < type.n; 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] > 'G' || argv[i+1][1] < '1' || argv[i+1][1] > '9', "Arguments must be Xn with X out of A-G and n out of 1-9\n"); - } + type.factors = (simple_type_t*)malloc(type.n*sizeof(simple_type_t)); + for(int i = 0; i < type.n; 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] > 'G' || argv[i+1][1] < '1' || argv[i+1][1] > '9', "Arguments must be Xn with X out of A-G and n out of 1-9\n"); + } - left_invariance = right_invariance = 0; + left_invariance = right_invariance = 0; - if(argc - type.n >= 3) { - if(strcmp(argv[type.n + 1], "-") != 0) - for(int i = 0; i < strlen(argv[type.n + 1]); i++) - left_invariance |= (1 << (argv[type.n + 1][i] - 'a')); - if(strcmp(argv[type.n + 2], "-") != 0) - for(int i = 0; i < strlen(argv[type.n + 2]); i++) - right_invariance |= (1 << (argv[type.n + 2][i] - 'a')); - } + if(argc - type.n >= 3) { + if(strcmp(argv[type.n + 1], "-") != 0) + for(int i = 0; i < strlen(argv[type.n + 1]); i++) + left_invariance |= (1 << (argv[type.n + 1][i] - 'a')); + if(strcmp(argv[type.n + 2], "-") != 0) + for(int i = 0; i < strlen(argv[type.n + 2]); i++) + right_invariance |= (1 << (argv[type.n + 2][i] - 'a')); + } - // generate graph + // generate graph - dq = weyl_generate_bruhat(type, left_invariance, right_invariance); + dq = weyl_generate_bruhat(type, left_invariance, right_invariance); - // print stuff + // print stuff - int output_level = 2; - if(getenv("OUTPUT_LEVEL")) - output_level = atoi(getenv("OUTPUT_LEVEL")); + int output_level = 2; + if(getenv("OUTPUT_LEVEL")) + output_level = atoi(getenv("OUTPUT_LEVEL")); - rank = weyl_rank(type); // number of simple roots - order = weyl_order(type); // number of Weyl group elements - positive = weyl_positive(type); // number of positive roots + rank = weyl_rank(type); // number of simple roots + order = weyl_order(type); // number of Weyl group elements + positive = weyl_positive(type); // number of positive roots - if(output_level >= 1) { - if(left_invariance) { - printf("<"); - for(int j = 0; j < rank; j++) - if(left_invariance & BIT(j)) - fputc(alphabet[j], stdout); - printf("> \\ "); - } + if(output_level >= 1) { + if(left_invariance) { + printf("<"); + for(int j = 0; j < rank; j++) + if(left_invariance & BIT(j)) + fputc(alphabet[j], stdout); + printf("> \\ "); + } - for(int i = 0; i < type.n; i++) - printf("%s%c%d", i == 0 ? "" : " x ", type.factors[i].series, type.factors[i].rank); + for(int i = 0; i < type.n; i++) + printf("%s%c%d", i == 0 ? "" : " x ", type.factors[i].series, type.factors[i].rank); - if(right_invariance) { - printf(" / <"); - for(int j = 0; j < rank; j++) - if(right_invariance & BIT(j)) - fputc(alphabet[j], stdout); - printf(">"); - } - fprintf(stdout, "\n"); + if(right_invariance) { + printf(" / <"); + for(int j = 0; j < rank; j++) + if(right_invariance & BIT(j)) + fputc(alphabet[j], stdout); + printf(">"); + } + fprintf(stdout, "\n"); - fprintf(stdout, "Rank: %d\tOrder: %d\tPositive Roots: %d\tCosets: %d\n\n", rank, order, positive, dq->count); - } + fprintf(stdout, "Rank: %d\tOrder: %d\tPositive Roots: %d\tCosets: %d\n\n", rank, order, positive, dq->count); + } - if(output_level >= 3) { - fprintf(stdout, "Shortest coset representatives: \n"); - for(int i = 0, wl = 0; i < dq->count; i++) { - if(dq->cosets[i].min->wordlength > wl) { - printf("\n"); - wl = dq->cosets[i].min->wordlength; - } - // fprintf(stdout, "%s(%d) ", alphabetize(dq->cosets[i].min, stringbuffer), dq->cosets[i].max->wordlength); - fprintf(stdout, "%s ", alphabetize(dq->cosets[i].min, stringbuffer)); - } - fprintf(stdout, "\n\n"); - } + if(output_level >= 3) { + fprintf(stdout, "Shortest coset representatives: \n"); + for(int i = 0, wl = 0; i < dq->count; i++) { + if(dq->cosets[i].min->wordlength > wl) { + printf("\n"); + wl = dq->cosets[i].min->wordlength; + } + // fprintf(stdout, "%s(%d) ", alphabetize(dq->cosets[i].min, stringbuffer), dq->cosets[i].max->wordlength); + fprintf(stdout, "%s ", alphabetize(dq->cosets[i].min, stringbuffer)); + } + fprintf(stdout, "\n\n"); + } - if(output_level >= 4) { - fprintf(stdout, "Bruhat order in graphviz format:\n"); - fprintf(stdout, "digraph test123 {\n"); - for(int i = 0; i < dq->count; i++) - for(doublecoset_list_t *current = dq->cosets[i].bruhat_lower; current; current = current->next) - fprintf(stdout, "%s -> %s;\n", - alphabetize(dq->cosets[i].min, stringbuffer), - alphabetize(current->to->min, stringbuffer2)); - fprintf(stdout, "}\n\n"); - } + if(output_level >= 4) { + fprintf(stdout, "Bruhat order in graphviz format:\n"); + fprintf(stdout, "digraph test123 {\n"); + for(int i = 0; i < dq->count; i++) + for(doublecoset_list_t *current = dq->cosets[i].bruhat_lower; current; current = current->next) + fprintf(stdout, "%s -> %s;\n", + alphabetize(dq->cosets[i].min, stringbuffer), + alphabetize(current->to->min, stringbuffer2)); + fprintf(stdout, "}\n\n"); + } - if(output_level >= 4) { - fprintf(stdout, "Opposites:\n"); - for(int i = 0; i < dq->count; i++) - fprintf(stdout, "%s <-> %s\n", - alphabetize(dq->cosets[i].min, stringbuffer), - alphabetize(dq->cosets[i].opposite->min, stringbuffer2)); - fprintf(stdout, "\n"); - } + if(output_level >= 4) { + fprintf(stdout, "Opposites:\n"); + for(int i = 0; i < dq->count; i++) + fprintf(stdout, "%s <-> %s\n", + alphabetize(dq->cosets[i].min, stringbuffer), + alphabetize(dq->cosets[i].opposite->min, stringbuffer2)); + fprintf(stdout, "\n"); + } - fixpoints = 0; - for(int i = 0; i < dq->count; i++) - if(dq->cosets[i].opposite == &dq->cosets[i]) { - if(output_level >= 1) { - if(fixpoints == 0) - fprintf(stdout, "No balanced ideals since the longest element fixes the following cosets:"); - fprintf(stdout, " %s", alphabetize(dq->cosets[i].min, stringbuffer)); - } - fixpoints++; - } - if(output_level >= 1 && fixpoints) - fprintf(stdout, "\n\n"); + fixpoints = 0; + for(int i = 0; i < dq->count; i++) + if(dq->cosets[i].opposite == &dq->cosets[i]) { + if(output_level >= 1) { + if(fixpoints == 0) + fprintf(stdout, "No balanced ideals since the longest element fixes the following cosets:"); + fprintf(stdout, " %s", alphabetize(dq->cosets[i].min, stringbuffer)); + } + fixpoints++; + } + if(output_level >= 1 && fixpoints) + fprintf(stdout, "\n\n"); - if(!fixpoints) { - int *buffer = (int*)malloc(dq->count*sizeof(int)); + if(!fixpoints) { + int *buffer = (int*)malloc(dq->count*sizeof(int)); - info_t info; - info.dq = dq; - info.rank = weyl_rank(type); - info.order = weyl_order(type); - info.positive = weyl_positive(type); - info.buffer = buffer; - info.level = output_level; + info_t info; + info.dq = dq; + info.rank = weyl_rank(type); + info.order = weyl_order(type); + info.positive = weyl_positive(type); + info.buffer = buffer; + info.level = output_level; - ERROR(dq->count > 2*BV_BLOCKSIZE*BV_RANK, "We can handle at most %d cosets. Increase BV_RANK if more is needed.\n", 2*BV_BLOCKSIZE*BV_RANK); + ERROR(dq->count > 2*BV_BLOCKSIZE*BV_RANK, "We can handle at most %d cosets. Increase BV_RANK if more is needed.\n", 2*BV_BLOCKSIZE*BV_RANK); - long count; - if(output_level >= 2) { - fprintf(stdout, "Balanced ideals:\n"); - count = enumerate_balanced_thickenings(dq, balanced_thickening_callback, &info); - fprintf(stdout, "\n"); - } else { - long outputcount = 0; - count = enumerate_balanced_thickenings(dq, balanced_thickening_simple_callback, &outputcount); - } + long count; + if(output_level >= 2) { + fprintf(stdout, "Balanced ideals:\n"); + count = enumerate_balanced_thickenings(dq, balanced_thickening_callback, &info); + fprintf(stdout, "\n"); + } else { + long outputcount = 0; + count = enumerate_balanced_thickenings(dq, balanced_thickening_simple_callback, &outputcount); + } - if(output_level >= 1) - fprintf(stdout, "Found %ld balanced ideal%s\n", count, count == 1 ? "" : "s"); - } + if(output_level >= 1) + fprintf(stdout, "Found %ld balanced ideal%s\n", count, count == 1 ? "" : "s"); + } - weyl_destroy_bruhat(dq); - free(type.factors); + weyl_destroy_bruhat(dq); + free(type.factors); - return 0; + return 0; }