From d3336bab0092a2c45da324cd864983c0da4f77cf Mon Sep 17 00:00:00 2001 From: Florian Stecker Date: Sat, 1 Dec 2018 20:56:23 -0800 Subject: [PATCH] specialized routine to generate cosets for \ D2n --- D2n.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 10 +++- thickenings.c | 14 +++--- 3 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 D2n.c diff --git a/D2n.c b/D2n.c new file mode 100644 index 0000000..7dbb112 --- /dev/null +++ b/D2n.c @@ -0,0 +1,133 @@ +#include "thickenings.h" +#include "weyl.h" +#include "queue.h" + +#include +#include +#include + +int main(int argc, const char *argv[]) +{ + if(argc < 2) { + fprintf(stderr, "Rank argument required.\n"); + return 1; + } + int rank = atoi(argv[1]); + if(rank <= 0 || rank > 1000) { + fprintf(stderr, "Rank must be a small positive integer.\n"); + return 1; + } + if(rank % 2) { + fprintf(stderr, "Rank must be even.\n"); // opposition involution not trivial otherwise + return 1; + } + + doublequotient_t *dq = (doublequotient_t*)malloc(sizeof(doublequotient_t)); + simple_type_t type; + type.series = 'D'; + type.rank = rank; + dq->type.n = 1; + dq->type.factors = &type; + dq->left_invariance = (1<right_invariance = 0; + dq->group = 0; + dq->grouplists = 0; + dq->groupletters = 0; + dq->count = 1 << (rank - 1); + dq->cosets = (doublecoset_t*)malloc(dq->count*sizeof(doublecoset_t)); + dq->lists = (doublecoset_list_t*)malloc(2*dq->count*rank*sizeof(doublecoset_list_t)); // conservative estimate + int nlists = 0; + + int *bitmask = malloc((1<<(rank-1)) * sizeof(int)); + int *bitmask_reverse = malloc((1<count; i++) { + dq->cosets[i].index = i; + dq->cosets[i].bruhat_lower = (doublecoset_list_t*)0; + dq->cosets[i].bruhat_higher = (doublecoset_list_t*)0; + dq->cosets[i].min = (weylgroup_element_t*)0; + dq->cosets[i].max = (weylgroup_element_t*)0; + } + + LOG("Create bitmasks.\n"); + + for(uint64_t i = 0; i < (1 << rank); i++) { + if(__builtin_popcountll(i) % 2 == 1) + bitmask_reverse[i] = -1; + else { + bitmask[index] = i; + bitmask_reverse[i] = index++; + } + } + + LOG("Generate bruhat order.\n"); + + for(int i = 0; i < dq->count; i++) { + for(int j = 0; j < rank - 1; j++) { + if(!(bitmask[i] & BIT(j)) && (bitmask[i] & BIT(j+1))) { + int lowerind = bitmask_reverse[bitmask[i] ^ (BIT(j) | BIT(j+1))]; + dq->lists[nlists].next = dq->cosets[i].bruhat_lower; + dq->cosets[i].bruhat_lower = &dq->lists[nlists]; + dq->cosets[i].bruhat_lower->to = &dq->cosets[lowerind]; + nlists++; + } + } + if((bitmask[i] & BIT(0)) && (bitmask[i] & BIT(1))) { + int lowerind = bitmask_reverse[bitmask[i] & ~(BIT(0) | BIT(1))]; + dq->lists[nlists].next = dq->cosets[i].bruhat_lower; + dq->cosets[i].bruhat_lower = &dq->lists[nlists]; + dq->cosets[i].bruhat_lower->to = &dq->cosets[lowerind]; + nlists++; + } + } + + LOG("Revert bruhat order.\n"); + + for(int i = 0; i < dq->count; i++) { + for(doublecoset_list_t *cur = dq->cosets[i].bruhat_lower; cur; cur = cur->next) { + dq->lists[nlists].next = cur->to->bruhat_higher; + cur->to->bruhat_higher = &dq->lists[nlists]; + cur->to->bruhat_higher->to = &dq->cosets[i]; + nlists++; + } + } + + LOG("Find opposites.\n"); + + for(int i = 0; i < dq->count; i++) { + int oppind = bitmask_reverse[~bitmask[i] & ((1<cosets[i].opposite = &dq->cosets[oppind]; + } + + /* + printf("\n"); + printf("digraph test123 {\n"); + + for(int i = 0; i < dq->count; i++) { + for(doublecoset_list_t *cur = dq->cosets[i].bruhat_lower; cur; cur = cur->next) { + printf("\"0x%02x\" -> \"0x%02x\";\n", bitmask[i], bitmask[cur->to->index]); + } + } + + printf("}\n\n"); + + printf("Opposites:\n"); + for(int i = 0; i < dq->count; i++) + printf("0x%02x <-> %d 0x%02x\n", bitmask[i], dq->cosets[i].opposite->index, bitmask[dq->cosets[i].opposite->index]); + printf("\n"); + */ + + long count = enumerate_balanced_thickenings(dq, 0, 0); + printf("Found %ld balanced ideals.\n", count); + + free(bitmask); + free(bitmask_reverse); + free(dq->lists); + free(dq->cosets); + free(dq); + + return 0; +} diff --git a/Makefile b/Makefile index 58d0a19..f31c3c8 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SPECIAL_OPTIONS=-O3 -flto -funroll-loops -Winline OPTIONS=-m64 -march=native -mtune=native -std=gnu99 -D_GNU_SOURCE $(SPECIAL_OPTIONS) NAME=enumerate-balanced-ideals -all: enumerate graph +all: enumerate graph D2n $(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 @@ -21,12 +21,18 @@ enumerate: enumerate.o weyl.o thickenings.o graph: graph.o weyl.o gcc $(OPTIONS) -o graph graph.o weyl.o +D2n: D2n.o weyl.o thickenings.o + gcc $(OPTIONS) -o D2n D2n.o weyl.o thickenings.o + enumerate.o: enumerate.c $(HEADERS) gcc $(OPTIONS) -c enumerate.c thickenings.o: thickenings.c $(HEADERS) gcc $(OPTIONS) -c thickenings.c +D2n.o: D2n.c $(HEADERS) + gcc $(OPTIONS) -c D2n.c + weyl.o: weyl.c $(HEADERS) gcc $(OPTIONS) -c weyl.c @@ -34,4 +40,4 @@ graph.o: graph.c $(HEADERS) gcc $(OPTIONS) -c graph.c clean: - rm -f enumerate graph thickenings.o weyl.o enumerate.o graph.o $(NAME) $(NAME).tar.bz2 + rm -f enumerate graph D2n thickenings.o weyl.o enumerate.o graph.o D2n.o $(NAME) $(NAME).tar.bz2 diff --git a/thickenings.c b/thickenings.c index 7e6fe86..b8b8856 100644 --- a/thickenings.c +++ b/thickenings.c @@ -110,12 +110,12 @@ static void generate_principal_ideals(doublequotient_t *dq, bitvec_t *pos, bitve } #ifdef _DEBUG - if(is_slim[i]) { - fprintf(stderr, " ids: [0"); - for(int j = 1; j < size; j++) - if(principal[j]) - fprintf(stderr, ", %d", dq->cosets[j].min->id); - fprintf(stderr, "]\n"); + if(is_slim[i] && dq->cosets[0].min) { // sometimes we don't want to define min and max + fprintf(stderr, " ids: [0"); + for(int j = 1; j < size; j++) + if(principal[j]) + fprintf(stderr, ", %d", dq->cosets[j].min->id); + fprintf(stderr, "]\n"); } #endif @@ -160,7 +160,7 @@ long enumerate_balanced_thickenings(doublequotient_t *dq, enumeration_callback c // the algorithm only works if the opposition pairing does not stabilize any element // if this happens, there can be no balanced thickenings for(int i = 0; i < dq->count; i++) - if(dq->cosets[i].opposite->min->id == dq->cosets[i].min->id) + if(dq->cosets[i].opposite->index == i) return 0; // we can only handle bitvectors up to BV_BLOCKSIZE*BV_RANK bits, but we only store half of the weyl group