Callbacks
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
@@ -10,8 +8,6 @@
|
||||
#include "coxeter.h"
|
||||
#include "queue.h"
|
||||
|
||||
#define BV_QWORD_RANK 10
|
||||
#include "bitvec.h"
|
||||
|
||||
char *alphabetize(int *word, int len, const char *alphabet, char *buffer)
|
||||
{
|
||||
@@ -568,30 +564,27 @@ void graph_free(semisimple_type_t type, node_t *graph)
|
||||
|
||||
typedef struct {
|
||||
int size; // the size of the weyl group. We store however only the first size/2 elements
|
||||
FILE *outfile;
|
||||
bitvec_t *principal_pos;
|
||||
bitvec_t *principal_neg;
|
||||
int *principal_is_slim;
|
||||
void (*callback)(const bitvec_t *, int, void*);
|
||||
void *callback_data;
|
||||
} enumeration_info_t;
|
||||
|
||||
/*
|
||||
This function enumerates all balanced ideals satisfying certain constraints, given by its arguments pos, neg and next_neg
|
||||
|
||||
pos and neg are bitvectors of size info.size/2
|
||||
they stand for the first (shortest) info.size/2 elements of the weyl group
|
||||
the least siginficant bit is the identity
|
||||
- info: constant information which just gets passed on to recursive calls, mainly contains the principal ideals
|
||||
- pos: a set of elements which have to be positive (that is, in the ideal)
|
||||
- neg: a set of elements which have to be negative (not in the ideal)
|
||||
- next_neg: this element has to be the first negative one not already contained in neg; if next_neg is info.size/2, then everything not in neg has to be positive
|
||||
- already_known: not a constraint, but just a hint to speed things up; tells the function that the first already_known elements are set either in neg or in pos; must be less or equal to next_neg
|
||||
- returns number of balanced ideals found
|
||||
|
||||
at the beginning they are cleared, meaning everything is undecided
|
||||
uses the bitvector functions bv_union, bv_copy, bv_set_range_except, bv_disjoint, bv_next_zero
|
||||
*/
|
||||
|
||||
|
||||
// enumerate all balanced ideals which contain everything in pos and everything strictly between known_until and next_neg, and which do not contain everything in neg, as well as next_neg
|
||||
// assuming all bits up to known_until are set either in pos or in neg, but not in both
|
||||
// returns number of found balanced ideals
|
||||
// next_neg can be info.size/2; in that case, everything between known_until and info.size/2 is required to be in the ideal, but it does not mean that next_neg is really not contained in the ideal
|
||||
// next_neg must be strictly greater than known_until, and less or equal to info.size/2
|
||||
// we use bv_union, bv_copy, bv_set_range_except, bv_disjoint, bv_next_zero
|
||||
|
||||
static long enumerate_tree(const enumeration_info_t *info, const bitvec_t *pos, const bitvec_t *neg, int first_unknown, int next_neg)
|
||||
static long enumerate_tree(const enumeration_info_t *info, const bitvec_t *pos, const bitvec_t *neg, int next_neg, int already_known)
|
||||
{
|
||||
static long totcount = 0;
|
||||
bitvec_t newpos, newneg, known;
|
||||
@@ -601,7 +594,8 @@ static long enumerate_tree(const enumeration_info_t *info, const bitvec_t *pos,
|
||||
// the omission of next_neg means inclusion of info->size - 1 - next_neg
|
||||
// add its principal ideal to pos and the opposite to neg
|
||||
if(next_neg != info->size/2) {
|
||||
// if(!info->principal_is_slim[info->size - 1 - next_neg]) // if the principal ideal we want to add is not slim by itself, we don't even have to try; but there is not really a performance benefit
|
||||
// if the principal ideal we want to add is not slim by itself, we don't even have to try; but there is not really a performance benefit, it rather makes it slower
|
||||
// if(!info->principal_is_slim[info->size - 1 - next_neg])
|
||||
// return 0;
|
||||
bv_union(&info->principal_pos[info->size - 1 - next_neg], pos, &newpos);
|
||||
bv_union(&info->principal_neg[info->size - 1 - next_neg], neg, &newneg);
|
||||
@@ -610,8 +604,8 @@ static long enumerate_tree(const enumeration_info_t *info, const bitvec_t *pos,
|
||||
bv_copy(neg, &newneg);
|
||||
}
|
||||
|
||||
// everything before next_neg which was unknown should be set to positive; to speed this up, we can start with first_unknown
|
||||
bv_set_range_except(&newpos, neg, first_unknown, next_neg);
|
||||
// everything before next_neg which was unknown should be set to positive; to speed this up, we can start with already_known
|
||||
bv_set_range_except(&newpos, neg, already_known, next_neg);
|
||||
|
||||
// check if this leads to any conflicts (equivalently, violates slimness)
|
||||
if(!bv_disjoint(&newpos, &newneg))
|
||||
@@ -623,25 +617,32 @@ static long enumerate_tree(const enumeration_info_t *info, const bitvec_t *pos,
|
||||
next_next_neg = bv_next_zero(&known, next_neg + 1);
|
||||
|
||||
if(next_next_neg >= info->size/2) {
|
||||
|
||||
if((++totcount) % 100000000 == 0) {
|
||||
fprintf(stderr, "Found balanced ideal: ");
|
||||
bv_print(stderr, &newpos, info->size/2);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
// there is no unknown left, so we found a balanced ideal
|
||||
if(info->callback)
|
||||
info->callback(&newpos, info->size, info->callback_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
do {
|
||||
count += enumerate_tree(info, &newpos, &newneg, next_neg + 1, next_next_neg);
|
||||
count += enumerate_tree(info, &newpos, &newneg, next_next_neg, next_neg + 1);
|
||||
next_next_neg = bv_next_zero(&known, next_next_neg + 1);
|
||||
} while(next_next_neg <= info->size/2);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
long enumerate_balanced_thickenings(semisimple_type_t type, node_t *graph, int size, const char *alphabet, FILE *outfile)
|
||||
/*
|
||||
enumerates all balanced ideals
|
||||
|
||||
- graph: hasse diagram of the bruhat order (of double cosets) with opposition pairing
|
||||
- size: number of nodes in graph
|
||||
- callback to call when a balanced ideal was found
|
||||
- arbitrary data for callback function
|
||||
|
||||
returns the number of balanced ideals
|
||||
*/
|
||||
|
||||
long enumerate_balanced_thickenings(node_t *graph, int size, void (*callback) (const bitvec_t *, int, void*), void *callback_data)
|
||||
{
|
||||
signed char *level;
|
||||
long count = 0;
|
||||
@@ -651,22 +652,19 @@ long enumerate_balanced_thickenings(semisimple_type_t type, node_t *graph, int s
|
||||
edgelist_t *edge;
|
||||
|
||||
info.size = size;
|
||||
info.outfile = outfile;
|
||||
info.callback = callback;
|
||||
info.callback_data = callback_data;
|
||||
info.principal_pos = (bitvec_t*)malloc(info.size*sizeof(bitvec_t));
|
||||
info.principal_neg = (bitvec_t*)malloc(info.size*sizeof(bitvec_t));
|
||||
info.principal_is_slim = (int*)malloc(info.size*sizeof(int));
|
||||
|
||||
// info.printstep = 0;
|
||||
// if(getenv("PRINTSTEP"))
|
||||
// info.printstep = atoi(getenv("PRINTSTEP"));
|
||||
|
||||
// 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 < info.size; i++)
|
||||
if(graph[i].opposite == i)
|
||||
return 0;
|
||||
|
||||
// we can only handle bitvectors up to 64*BV_QWORD_RANK bits, but we only store half of the weyl group
|
||||
// we can only handle bitvectors up to 64*BV_QWORD_RANK bits, but we only store half of the weyl group
|
||||
if(info.size > 128*BV_QWORD_RANK)
|
||||
return -1;
|
||||
|
||||
@@ -705,7 +703,7 @@ long enumerate_balanced_thickenings(semisimple_type_t type, node_t *graph, int s
|
||||
bv_clear(&pos);
|
||||
bv_clear(&neg);
|
||||
for(int i = 0; i <= info.size/2; i++)
|
||||
count += enumerate_tree(&info, &pos, &neg, 0, i);
|
||||
count += enumerate_tree(&info, &pos, &neg, i, 0);
|
||||
|
||||
free(info.principal_is_slim);
|
||||
free(info.principal_pos);
|
||||
|
||||
Reference in New Issue
Block a user