Callbacks
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
HEADERS=coxeter.h thickenings.h queue.h bitvec.h
 | 
			
		||||
OPTIONS=-O3 -m64 -march=native -flto -funroll-loops -std=gnu99 -Winline
 | 
			
		||||
OPTIONS=-O3 -m64 -march=native -flto -funroll-loops -std=gnu99 -D_GNU_SOURCE -Winline
 | 
			
		||||
#OPTIONS=-m64 -march=native -O0 -g -std=gnu99
 | 
			
		||||
#OPTIONS=-O3 -m64 -march=native -funroll-loops -fno-inline -std=gnu99 -pg
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								bitvec.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								bitvec.h
									
									
									
									
									
								
							@@ -12,11 +12,9 @@
 | 
			
		||||
 * See the file LICENSE for details.
 | 
			
		||||
 ********************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef __BITVEC_H__
 | 
			
		||||
#define __BITVEC_H__ 1
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								generate.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								generate.c
									
									
									
									
									
								
							@@ -1,9 +1,20 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "thickenings.h"
 | 
			
		||||
#include "coxeter.h"
 | 
			
		||||
#include "queue.h"
 | 
			
		||||
#include "thickenings.h"
 | 
			
		||||
 | 
			
		||||
#include <strings.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
void balanced_thickening_callback(const bitvec_t *pos, int size, void *data)
 | 
			
		||||
{
 | 
			
		||||
  static long totcount = 0;
 | 
			
		||||
 | 
			
		||||
  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[])
 | 
			
		||||
{
 | 
			
		||||
@@ -63,6 +74,8 @@ int main(int argc, const char *argv[])
 | 
			
		||||
 | 
			
		||||
  fprintf(stderr, "Rank: %d\tOrder: %d\tPositive Roots: %d\tCosets: %d\n", rank, order, hyperplanes, cosets);
 | 
			
		||||
  fprintf(stderr, "\n");
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
  fprintf(stderr, "Shortest coset representatives: \n");
 | 
			
		||||
  for(int i = 0, wl = 0; i < cosets; i++) {
 | 
			
		||||
    if(i == 0) {
 | 
			
		||||
@@ -74,6 +87,7 @@ int main(int argc, const char *argv[])
 | 
			
		||||
      fprintf(stderr, "%s ", alphabetize(graph[i].word, graph[i].wordlength, alphabet, string_buffer1));
 | 
			
		||||
  }
 | 
			
		||||
  fprintf(stderr, "\n\n");
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  fixpoints = 0;
 | 
			
		||||
  for(int i = 0; i < cosets; i++)
 | 
			
		||||
@@ -88,14 +102,12 @@ int main(int argc, const char *argv[])
 | 
			
		||||
  if(fixpoints > 0) {
 | 
			
		||||
    fprintf(stderr, "\n\n");
 | 
			
		||||
  } else {
 | 
			
		||||
 | 
			
		||||
    // enumerate balanced thickenings
 | 
			
		||||
    fwrite(&type.n, sizeof(int), 1, stdout);
 | 
			
		||||
    fwrite(type.factors, sizeof(simple_type_t), type.n, stdout);
 | 
			
		||||
    fwrite(&left_invariance, sizeof(unsigned long), type.n, stdout);
 | 
			
		||||
    fwrite(&right_invariance, sizeof(unsigned long), type.n, stdout);
 | 
			
		||||
 | 
			
		||||
    long count = enumerate_balanced_thickenings(type, graph, cosets, alphabet, stdout);
 | 
			
		||||
    long count = enumerate_balanced_thickenings(graph, cosets, balanced_thickening_callback, (void*)0);
 | 
			
		||||
 | 
			
		||||
    fprintf(stderr, "Found %ld balanced thickenings\n\n", count);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
#ifndef THICKENINGS_H
 | 
			
		||||
#define THICKENINGS_H
 | 
			
		||||
 | 
			
		||||
#define BV_QWORD_RANK 10
 | 
			
		||||
#include "bitvec.h"
 | 
			
		||||
 | 
			
		||||
#include "coxeter.h"
 | 
			
		||||
 | 
			
		||||
#define DEBUG(msg, ...) do{fprintf(stderr, msg, ##__VA_ARGS__); }while(0)
 | 
			
		||||
@@ -30,13 +33,13 @@ char *alphabetize(int *word, int len, const char *alphabet, char *buffer);
 | 
			
		||||
void print_thickening(int rank, int order, const signed char *thickening, int level, const char *alphabet, FILE *f);
 | 
			
		||||
 | 
			
		||||
// generating the graph of the bruhat order
 | 
			
		||||
node_t *graph_alloc(semisimple_type_t type);
 | 
			
		||||
void graph_free(semisimple_type_t type, node_t *graph);
 | 
			
		||||
void prepare_graph(semisimple_type_t type, node_t *graph);
 | 
			
		||||
int prepare_simplified_graph(semisimple_type_t type, unsigned long left, unsigned long right, node_t *simplified_graph);
 | 
			
		||||
 | 
			
		||||
// enumerate balanced thickenings
 | 
			
		||||
long enumerate_balanced_thickenings(semisimple_type_t type, node_t *graph, int size, const char *alphabet, FILE *outfile);
 | 
			
		||||
node_t *graph_alloc(semisimple_type_t type);
 | 
			
		||||
void graph_free(semisimple_type_t type, node_t *graph);
 | 
			
		||||
// enumerating balanced thickenings
 | 
			
		||||
long enumerate_balanced_thickenings(node_t *graph, int size, void (*callback) (const bitvec_t *, int, void*), void *callback_data);
 | 
			
		||||
 | 
			
		||||
// various helper functions
 | 
			
		||||
static int compare_wordlength(const void *a, const void *b, void *gr);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user