Compare commits

...

1 Commits

Author SHA1 Message Date
Florian Stecker
93207ff694 .gitignore pdf files and list length profile 2022-06-13 11:19:54 +02:00
3 changed files with 291 additions and 276 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.o *.o
*.pdf
enumerate enumerate
idealbounds idealbounds
graph graph

View File

@ -7,7 +7,7 @@ SPECIAL_OPTIONS=-O3 -flto -funroll-loops -Winline
OPTIONS=-m64 -march=native -std=gnu99 -D_GNU_SOURCE $(SPECIAL_OPTIONS) OPTIONS=-m64 -march=native -std=gnu99 -D_GNU_SOURCE $(SPECIAL_OPTIONS)
NAME=enumerate-balanced-ideals NAME=enumerate-balanced-ideals
all: enumerate graph D2n dominant_weights all: enumerate graph
$(NAME).tar.bz2: $(NAME) $(HEADERS) enumerate.c weyl.c thickenings.c $(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 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

View File

@ -9,353 +9,367 @@ char stringbuffer[100];
char stringbuffer2[100]; char stringbuffer2[100];
typedef struct { typedef struct {
doublequotient_t *dq; doublequotient_t *dq;
int rank; int rank;
int order; int order;
int positive; int positive;
int *buffer; int *buffer;
int level; int level;
} info_t; } info_t;
static char* alphabetize(weylgroup_element_t *e, char *str) static char* alphabetize(weylgroup_element_t *e, char *str)
{ {
if(e->wordlength == 0) if(e->wordlength == 0)
sprintf(str, "1"); sprintf(str, "1");
else { else {
for(int j = 0; j < e->wordlength; j++) for(int j = 0; j < e->wordlength; j++)
str[j] = e->word[j] + 'a'; str[j] = e->word[j] + 'a';
str[e->wordlength] = 0; 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; int other, shorter = i;
do { do {
i = shorter; i = shorter;
for(int j = 0; j < rank; j++) { for(int j = 0; j < rank; j++) {
other = graph[shorter].left[j]; other = graph[shorter].left[j];
if(left & (1 << j) && if(left & (1 << j) &&
graph[other].wordlength < graph[shorter].wordlength) graph[other].wordlength < graph[shorter].wordlength)
shorter = other; shorter = other;
other = graph[shorter].right[j]; other = graph[shorter].right[j];
if(right & (1 << j) && if(right & (1 << j) &&
graph[other].wordlength < graph[shorter].wordlength) graph[other].wordlength < graph[shorter].wordlength)
shorter = other; shorter = other;
} }
} while(shorter != i); } while(shorter != i);
return shorter; return shorter;
} }
*/ */
void balanced_thickening_callback(const bitvec_t *pos, int size, const enumeration_info_t *ei) 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) { if(ei->callback_data) {
info_t *info = (info_t*)ei->callback_data; info_t *info = (info_t*)ei->callback_data;
unsigned long right_invariance = FIRSTBITS(info->rank); unsigned long right_invariance = FIRSTBITS(info->rank);
unsigned long left_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++) { for(int i = 0; i < size; i++) {
bit1 = i < size/2 ? bv_get_bit(pos, i) : !bv_get_bit(pos, size - 1 - 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++) { for(int j = 0; j < info->rank; j++) {
left = info->dq->cosets[i].min->left[j]->coset->index; left = info->dq->cosets[i].min->left[j]->coset->index;
right = info->dq->cosets[i].min->right[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); 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); bit2right = right < size/2 ? bv_get_bit(pos, right) : !bv_get_bit(pos, size - 1 - right);
if(bit1 != bit2left) if(bit1 != bit2left)
left_invariance &= ~BIT(j); left_invariance &= ~BIT(j);
if(bit1 != bit2right) if(bit1 != bit2right)
right_invariance &= ~BIT(j); right_invariance &= ~BIT(j);
} }
} }
printf("%4d left: ", totcount++); printf("%4d left: ", totcount++);
for(int j = 0; j < info->rank; j++) for(int j = 0; j < info->rank; j++)
printf("%c", left_invariance & (1 << j) ? j + 'a' : ' '); printf("%c", left_invariance & (1 << j) ? j + 'a' : ' ');
printf(" right: "); printf(" right: ");
for(int j = 0; j < info->rank; j++) for(int j = 0; j < info->rank; j++)
printf("%c", right_invariance & (1 << j) ? j + 'a' : ' '); printf("%c", right_invariance & (1 << j) ? j + 'a' : ' ');
if(info->buffer) { int length_profile[65]; // can't handle more that 64 positive roots anyway
bitvec_t low, high;
bv_copy(pos, &low);
bv_negate(pos, &high);
// printf(" set: "); memset(length_profile, 0, (info->positive+1)*sizeof(int));
// bv_print(stdout, &low, size/2);
// printf(" ");
// bv_print(stdout, &high, size/2);
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++) { for(int i = 0; i < size/2; i++) {
if(!bv_get_bit(&high, i)) if(!bv_get_bit(&high, i))
continue; 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(&high, &ei->principal_neg[size-1-i], &high);
bv_difference(&low, &ei->principal_pos[size-1-i], &low); bv_difference(&low, &ei->principal_pos[size-1-i], &low);
} }
for(int i = size/2 - 1; i >= 0; i--) { for(int i = size/2 - 1; i >= 0; i--) {
if(!bv_get_bit(&low, i)) if(!bv_get_bit(&low, i))
continue; 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; int max_length = 0;
for(int i = 0; i < size/2; i++) { for(int i = 0; i < size/2; i++) {
if(bv_get_bit(pos, i)) { if(bv_get_bit(pos, i)) {
if(info->dq->cosets[i].max->wordlength > max_length) if(info->dq->cosets[i].max->wordlength > max_length)
max_length = info->dq->cosets[i].max->wordlength; max_length = info->dq->cosets[i].max->wordlength;
} else { } else {
if(info->dq->cosets[size-i-1].max->wordlength > max_length) if(info->dq->cosets[size-i-1].max->wordlength > max_length)
max_length = info->dq->cosets[size-i-1].max->wordlength; max_length = info->dq->cosets[size-i-1].max->wordlength;
} }
} }
// printf(" max length: %d", max_length); // printf(" max length: %d", max_length);
/* /*
if(info->buffer) { if(info->buffer) {
printf(" generators:"); printf(" generators:");
queue_t queue; queue_t queue;
int cur, left, right; int cur, left, right;
int *buffer = info->buffer; int *buffer = info->buffer;
for(int i = 0; i < size/2; i++) { for(int i = 0; i < size/2; i++) {
buffer[i] = bv_get_bit(pos, i); buffer[i] = bv_get_bit(pos, i);
buffer[size-1-i] = !buffer[i]; buffer[size-1-i] = !buffer[i];
} }
for(int i = size-1; i >= 0; i--) { for(int i = size-1; i >= 0; i--) {
if(buffer[i]) { if(buffer[i]) {
weylgroup_element_t *shortest = shorten(i, left_invariance, right_invariance, info->dq); weylgroup_element_t *shortest = shorten(i, left_invariance, right_invariance, info->dq);
printf(" %s", alphabetize(shortest, stringbuffer)); printf(" %s", alphabetize(shortest, stringbuffer));
buffer[i] = 0; buffer[i] = 0;
queue_init(&queue); queue_init(&queue);
queue_put(&queue, i); queue_put(&queue, i);
while((cur = queue_get(&queue)) != -1) { while((cur = queue_get(&queue)) != -1) {
for(doublecoset_list_t *current = info->dq->coset[cur].bruhat_lower; current; current = current->next) { for(doublecoset_list_t *current = info->dq->coset[cur].bruhat_lower; current; current = current->next) {
int idx = current->to - info->dq->cosets; int idx = current->to - info->dq->cosets;
if(buffer[idx]) { if(buffer[idx]) {
buffer[idx] = 0; buffer[idx] = 0;
queue_put(&queue, idx); queue_put(&queue, idx);
} }
} }
for(int j = 0; j < info->rank; j++) { for(int j = 0; j < info->rank; j++) {
left = info->dq->coset[cur].min.left[j] - info->dq->cosets; left = info->dq->coset[cur].min.left[j] - info->dq->cosets;
if(left_invariance & (1 << j) && if(left_invariance & (1 << j) &&
info->graph[left].wordlength < info->graph[cur].wordlength && info->graph[left].wordlength < info->graph[cur].wordlength &&
buffer[left]) { buffer[left]) {
buffer[left] = 0; buffer[left] = 0;
queue_put(&queue, left); queue_put(&queue, left);
} }
right = info->graph[cur].left[j]; right = info->graph[cur].left[j];
if(right_invariance & (1 << j) && if(right_invariance & (1 << j) &&
info->graph[right].wordlength < info->graph[cur].wordlength && info->graph[right].wordlength < info->graph[cur].wordlength &&
buffer[right]) { buffer[right]) {
buffer[right] = 0; buffer[right] = 0;
queue_put(&queue, right); 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) 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) { if((++(*count)) % 100000000 == 0) {
bv_print(stderr, pos, size/2); bv_print(stderr, pos, size/2);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
} }
int main(int argc, const char *argv[]) int main(int argc, const char *argv[])
{ {
semisimple_type_t type; semisimple_type_t type;
unsigned long right_invariance, left_invariance; unsigned long right_invariance, left_invariance;
int rank, order, positive; int rank, order, positive;
int fixpoints; 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; type.n = 0;
for(int i = 0; i < argc - 1; i++) { for(int i = 0; i < argc - 1; i++) {
if(argv[i+1][0] < 'A' || argv[i+1][0] > 'G') if(argv[i+1][0] < 'A' || argv[i+1][0] > 'G')
break; break;
type.n++; type.n++;
} }
type.factors = (simple_type_t*)malloc(type.n*sizeof(simple_type_t)); type.factors = (simple_type_t*)malloc(type.n*sizeof(simple_type_t));
for(int i = 0; i < type.n; i++) { for(int i = 0; i < type.n; i++) {
type.factors[i].series = argv[i+1][0]; type.factors[i].series = argv[i+1][0];
type.factors[i].rank = argv[i+1][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"); 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(argc - type.n >= 3) {
if(strcmp(argv[type.n + 1], "-") != 0) if(strcmp(argv[type.n + 1], "-") != 0)
for(int i = 0; i < strlen(argv[type.n + 1]); i++) for(int i = 0; i < strlen(argv[type.n + 1]); i++)
left_invariance |= (1 << (argv[type.n + 1][i] - 'a')); left_invariance |= (1 << (argv[type.n + 1][i] - 'a'));
if(strcmp(argv[type.n + 2], "-") != 0) if(strcmp(argv[type.n + 2], "-") != 0)
for(int i = 0; i < strlen(argv[type.n + 2]); i++) for(int i = 0; i < strlen(argv[type.n + 2]); i++)
right_invariance |= (1 << (argv[type.n + 2][i] - 'a')); 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; int output_level = 2;
if(getenv("OUTPUT_LEVEL")) if(getenv("OUTPUT_LEVEL"))
output_level = atoi(getenv("OUTPUT_LEVEL")); output_level = atoi(getenv("OUTPUT_LEVEL"));
rank = weyl_rank(type); // number of simple roots rank = weyl_rank(type); // number of simple roots
order = weyl_order(type); // number of Weyl group elements order = weyl_order(type); // number of Weyl group elements
positive = weyl_positive(type); // number of positive roots positive = weyl_positive(type); // number of positive roots
if(output_level >= 1) { if(output_level >= 1) {
if(left_invariance) { if(left_invariance) {
printf("<"); printf("<");
for(int j = 0; j < rank; j++) for(int j = 0; j < rank; j++)
if(left_invariance & BIT(j)) if(left_invariance & BIT(j))
fputc(alphabet[j], stdout); fputc(alphabet[j], stdout);
printf("> \\ "); printf("> \\ ");
} }
for(int i = 0; i < type.n; i++) for(int i = 0; i < type.n; i++)
printf("%s%c%d", i == 0 ? "" : " x ", type.factors[i].series, type.factors[i].rank); printf("%s%c%d", i == 0 ? "" : " x ", type.factors[i].series, type.factors[i].rank);
if(right_invariance) { if(right_invariance) {
printf(" / <"); printf(" / <");
for(int j = 0; j < rank; j++) for(int j = 0; j < rank; j++)
if(right_invariance & BIT(j)) if(right_invariance & BIT(j))
fputc(alphabet[j], stdout); fputc(alphabet[j], stdout);
printf(">"); printf(">");
} }
fprintf(stdout, "\n"); 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) { if(output_level >= 3) {
fprintf(stdout, "Shortest coset representatives: \n"); fprintf(stdout, "Shortest coset representatives: \n");
for(int i = 0, wl = 0; i < dq->count; i++) { for(int i = 0, wl = 0; i < dq->count; i++) {
if(dq->cosets[i].min->wordlength > wl) { if(dq->cosets[i].min->wordlength > wl) {
printf("\n"); printf("\n");
wl = dq->cosets[i].min->wordlength; wl = dq->cosets[i].min->wordlength;
} }
// fprintf(stdout, "%s(%d) ", alphabetize(dq->cosets[i].min, stringbuffer), dq->cosets[i].max->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, "%s ", alphabetize(dq->cosets[i].min, stringbuffer));
} }
fprintf(stdout, "\n\n"); fprintf(stdout, "\n\n");
} }
if(output_level >= 4) { if(output_level >= 4) {
fprintf(stdout, "Bruhat order in graphviz format:\n"); fprintf(stdout, "Bruhat order in graphviz format:\n");
fprintf(stdout, "digraph test123 {\n"); fprintf(stdout, "digraph test123 {\n");
for(int i = 0; i < dq->count; i++) for(int i = 0; i < dq->count; i++)
for(doublecoset_list_t *current = dq->cosets[i].bruhat_lower; current; current = current->next) for(doublecoset_list_t *current = dq->cosets[i].bruhat_lower; current; current = current->next)
fprintf(stdout, "%s -> %s;\n", fprintf(stdout, "%s -> %s;\n",
alphabetize(dq->cosets[i].min, stringbuffer), alphabetize(dq->cosets[i].min, stringbuffer),
alphabetize(current->to->min, stringbuffer2)); alphabetize(current->to->min, stringbuffer2));
fprintf(stdout, "}\n\n"); fprintf(stdout, "}\n\n");
} }
if(output_level >= 4) { if(output_level >= 4) {
fprintf(stdout, "Opposites:\n"); fprintf(stdout, "Opposites:\n");
for(int i = 0; i < dq->count; i++) for(int i = 0; i < dq->count; i++)
fprintf(stdout, "%s <-> %s\n", fprintf(stdout, "%s <-> %s\n",
alphabetize(dq->cosets[i].min, stringbuffer), alphabetize(dq->cosets[i].min, stringbuffer),
alphabetize(dq->cosets[i].opposite->min, stringbuffer2)); alphabetize(dq->cosets[i].opposite->min, stringbuffer2));
fprintf(stdout, "\n"); fprintf(stdout, "\n");
} }
fixpoints = 0; fixpoints = 0;
for(int i = 0; i < dq->count; i++) for(int i = 0; i < dq->count; i++)
if(dq->cosets[i].opposite == &dq->cosets[i]) { if(dq->cosets[i].opposite == &dq->cosets[i]) {
if(output_level >= 1) { if(output_level >= 1) {
if(fixpoints == 0) if(fixpoints == 0)
fprintf(stdout, "No balanced ideals since the longest element fixes the following cosets:"); fprintf(stdout, "No balanced ideals since the longest element fixes the following cosets:");
fprintf(stdout, " %s", alphabetize(dq->cosets[i].min, stringbuffer)); fprintf(stdout, " %s", alphabetize(dq->cosets[i].min, stringbuffer));
} }
fixpoints++; fixpoints++;
} }
if(output_level >= 1 && fixpoints) if(output_level >= 1 && fixpoints)
fprintf(stdout, "\n\n"); fprintf(stdout, "\n\n");
if(!fixpoints) { if(!fixpoints) {
int *buffer = (int*)malloc(dq->count*sizeof(int)); int *buffer = (int*)malloc(dq->count*sizeof(int));
info_t info; info_t info;
info.dq = dq; info.dq = dq;
info.rank = weyl_rank(type); info.rank = weyl_rank(type);
info.order = weyl_order(type); info.order = weyl_order(type);
info.positive = weyl_positive(type); info.positive = weyl_positive(type);
info.buffer = buffer; info.buffer = buffer;
info.level = output_level; 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; long count;
if(output_level >= 2) { if(output_level >= 2) {
fprintf(stdout, "Balanced ideals:\n"); fprintf(stdout, "Balanced ideals:\n");
count = enumerate_balanced_thickenings(dq, balanced_thickening_callback, &info); count = enumerate_balanced_thickenings(dq, balanced_thickening_callback, &info);
fprintf(stdout, "\n"); fprintf(stdout, "\n");
} else { } else {
long outputcount = 0; long outputcount = 0;
count = enumerate_balanced_thickenings(dq, balanced_thickening_simple_callback, &outputcount); count = enumerate_balanced_thickenings(dq, balanced_thickening_simple_callback, &outputcount);
} }
if(output_level >= 1) if(output_level >= 1)
fprintf(stdout, "Found %ld balanced ideal%s\n", count, count == 1 ? "" : "s"); fprintf(stdout, "Found %ld balanced ideal%s\n", count, count == 1 ? "" : "s");
} }
weyl_destroy_bruhat(dq); weyl_destroy_bruhat(dq);
free(type.factors); free(type.factors);
return 0; return 0;
} }