enumerate-balanced-ideals/generate.c

310 lines
8.7 KiB
C

#include "thickenings.h"
#include "weyl.h"
#include "queue.h"
#include <strings.h>
#include <stdio.h>
char stringbuffer[100];
char stringbuffer2[100];
typedef struct {
node_t *graph;
int cosets;
int rank;
int order;
int hyperplanes;
semisimple_type_t type;
unsigned long left_invariance;
unsigned long right_invariance;
const char *alphabet;
int *buffer;
} info_t;
int shorten(int i, unsigned long left, unsigned long right, node_t *graph, 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;
}
} while(shorter != i);
return shorter;
}
void balanced_thickening_callback(const bitvec_t *pos, int size, void *data)
{
static long totcount = 0;
if(data) {
info_t *info = (info_t*)data;
unsigned long right_invariance = FIRSTBITS(info->rank);
unsigned long left_invariance = FIRSTBITS(info->rank);
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->graph[i].left[j];
right = info->graph[i].right[j];
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("left: ");
for(int j = 0; j < info->rank; j++)
printf("%c", left_invariance & (1 << j) ? info->alphabet[j] : ' ');
printf(" right: ");
for(int j = 0; j < info->rank; j++)
printf("%c", right_invariance & (1 << j) ? info->alphabet[j] : ' ');
if(info->buffer) {
printf(" generators:");
queue_t queue;
int current, left, right, shortest;
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]) {
int shortest = shorten(i, left_invariance, right_invariance, info->graph, info-> rank);
printf(" %s", alphabetize(info->graph[shortest].word,
info->graph[shortest].wordlength,
info->alphabet,
stringbuffer));
buffer[i] = 0;
queue_init(&queue);
queue_put(&queue, i);
while((current = queue_get(&queue)) != -1) {
for(edgelist_t *edge = info->graph[current].bruhat_lower; edge != (edgelist_t*)0; edge = edge->next) {
if(buffer[edge->to]) {
buffer[edge->to] = 0;
queue_put(&queue, edge->to);
}
}
for(int j = 0; j < info->rank; j++) {
left = info->graph[current].left[j];
if(left_invariance & (1 << j) &&
info->graph[left].wordlength < info->graph[current].wordlength &&
buffer[left]) {
buffer[left] = 0;
queue_put(&queue, left);
}
right = info->graph[current].left[j];
if(right_invariance & (1 << j) &&
info->graph[right].wordlength < info->graph[current].wordlength &&
buffer[right]) {
buffer[right] = 0;
queue_put(&queue, right);
}
}
}
}
}
}
printf("\n");
}
/*
if((++totcount) % 100000000 == 0) {
fprintf(stderr, "Found balanced ideal: ");
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, hyperplanes, cosets;
int fixpoints;
node_t *graph;
char string_buffer1[1000];
const char *alphabet = "abcdefghijklmnopqrstuvwxyz";
// read arguments
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] > 'I')
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] > '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");
}
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'));
}
// generate graph
graph = graph_alloc(type);
cosets = prepare_simplified_graph(type, left_invariance, right_invariance, graph);
ERROR(cosets < 0, "The left invariance is not preserved by the opposition involution!\n");
// print stuff
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
hyperplanes = weyl_hyperplanes(type); // number of positive roots
if(output_level >= 1) {
printf("Poset: ");
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);
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, hyperplanes, cosets);
}
if(output_level >= 3) {
fprintf(stdout, "Shortest coset representatives: \n");
for(int i = 0, wl = 0; i < cosets; i++) {
if(i == 0) {
fprintf(stdout, "1");
} else if(graph[i].wordlength > wl) {
fprintf(stdout, "\n%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1));
wl = graph[i].wordlength;
} else
fprintf(stdout, "%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1));
}
fprintf(stdout, "\n\n");
}
if(output_level >= 4) {
edgelist_t *edge;
fprintf(stdout, "Bruhat order in graphviz format:\n");
fprintf(stdout, "digraph test123 {\n");
for(int i = 0; i < cosets; i++) {
edge = graph[i].bruhat_lower;
while(edge) {
fprintf(stdout, "%s -> %s;\n",
alphabetize(graph[i].word, graph[i].wordlength, alphabet, stringbuffer),
alphabetize(graph[edge->to].word, graph[edge->to].wordlength, alphabet, stringbuffer2));
edge = edge->next;
}
}
fprintf(stdout, "}\n\n");
}
if(output_level >= 4) {
fprintf(stdout, "Opposites:\n");
for(int i = 0; i < cosets; i++) {
fprintf(stdout, "%s <-> %s\n",
alphabetize(graph[i].word, graph[i].wordlength, alphabet, stringbuffer),
alphabetize(graph[graph[i].opposite].word, graph[graph[i].opposite].wordlength, alphabet, stringbuffer2));
}
fprintf(stdout, "\n");
}
fixpoints = 0;
for(int i = 0; i < cosets; i++)
if(graph[i].opposite == i) {
if(output_level >= 1) {
if(fixpoints == 0)
fprintf(stdout, "No thickenings since the longest element fixes the following cosets: %s", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1));
else
fprintf(stdout, " %s", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1));
}
fixpoints++;
}
if(output_level >= 1 && fixpoints)
fprintf(stdout, "\n\n");
if(!fixpoints) {
int *buffer = (int*)malloc(cosets*sizeof(int));
info_t info;
info.graph = graph;
info.cosets = cosets;
info.rank = rank;
info.order = order;
info.hyperplanes = hyperplanes;
info.type = type;
info.left_invariance = left_invariance;
info.right_invariance = right_invariance;
info.alphabet = alphabet;
info.buffer = buffer;
long count;
if(output_level >= 2) {
fprintf(stdout, "Balanced ideals:\n", count);
count = enumerate_balanced_thickenings(graph, cosets, balanced_thickening_callback, &info);
fprintf(stdout, "\n", count);
}
else
count = enumerate_balanced_thickenings(graph, cosets, 0, 0);
if(output_level >= 1)
fprintf(stdout, "Found %ld balanced ideal%s\n", count, count == 1 ? "" : "s");
}
graph_free(type, graph);
free(type.factors);
return 0;
}