Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563580 views
1
/***************************************************************************
2
@
3
@ --------------------------------------------------------------------------
4
@
5
@ FILE: base.h
6
@
7
@ some algorithms connected with the schreier-sims algorithm are collected.
8
@
9
@ --------------------------------------------------------------------------
10
@
11
****************************************************************************/
12
13
#include <typedef.h>
14
#include <longtools.h>
15
#include <getput.h>
16
#include <matrix.h>
17
#include <tools.h>
18
#include <sort.h>
19
20
extern int INFO_LEVEL;
21
22
void free_tree(struct tree *p)
23
{
24
if (p!=NULL){
25
free_tree(p->left);
26
free_tree(p->right);
27
free(p);
28
}
29
}
30
31
32
int hash_mat(struct tree *p,matrix_TYP **v,matrix_TYP *x,int pos)
33
{
34
int cmp;
35
36
if ((p==NULL) || (p->no <0)){
37
fprintf(stderr,"fehler in hash_mat\n");
38
}
39
40
cmp = mat_comp(v[p->no],x);
41
if (cmp < 0){
42
if (p->left == NULL){
43
if (pos != -1){
44
p->left = (struct tree *) calloc(1,sizeof(struct tree));
45
p->left->no = pos;
46
}
47
return -1;
48
}
49
else{
50
return hash_mat(p->left,v,x,pos);
51
}
52
}
53
else if (cmp > 0){
54
if (p->right == NULL){
55
if (pos != -1){
56
p->right = (struct tree *) calloc(1,sizeof(struct tree));
57
p->right->no = pos;
58
}
59
return -1;
60
}
61
else{
62
return hash_mat(p->right,v,x,pos);
63
}
64
}
65
else{
66
return p->no;
67
}
68
69
}
70
71
/**************************************************************************
72
@
73
@ --------------------------------------------------------------------------
74
@
75
@ void init_bahn(bahn *a)
76
@ initialises the struct bahn, i.e. get's memory for the pointers, and
77
@ sets all other values to zero.
78
@
79
@ --------------------------------------------------------------------------
80
@
81
***************************************************************************/
82
extern void init_bahn(bahn *a)
83
{
84
a->length = 0;
85
a->speicher = MIN_SPEICHER;
86
a->orbit = (matrix_TYP **) calloc(MIN_SPEICHER , sizeof(matrix_TYP *));
87
a->representatives = (matrix_TYP **) calloc(MIN_SPEICHER
88
, sizeof(matrix_TYP *));
89
a->rep_invs = (matrix_TYP **) calloc(MIN_SPEICHER
90
, sizeof(matrix_TYP *));
91
a->words = (int **) calloc(MIN_SPEICHER, sizeof(int *));
92
a->generators = (matrix_TYP **) calloc(MIN_SPEICHER
93
, sizeof(matrix_TYP *));
94
a->hash = (struct tree *) malloc(1*sizeof(struct tree));
95
a->hash->left = NULL;
96
a->hash->right = NULL;
97
a->hash->no = -1;
98
99
}
100
101
102
/**************************************************************************
103
@
104
@ --------------------------------------------------------------------------
105
@
106
@ extern void extend_bahn(bahn **a)
107
@
108
@ bahn **a
109
@
110
@ reallocated the pointers a[0]->orbit, a[0]->generators and
111
@ a[0]->representatives by the amount MIN_SPEICHER, and increases
112
@ a[0]->speicher by this ammount.
113
@
114
@ --------------------------------------------------------------------------
115
@
116
***************************************************************************/
117
extern void extend_bahn(bahn **a)
118
{
119
if (a[0]->speicher == 0){
120
printf("error in extend_bahn\n");
121
exit(3);
122
}
123
a[0]->speicher = a[0]->speicher+MIN_SPEICHER;
124
a[0]->orbit = (matrix_TYP **) realloc(a[0]->orbit,
125
sizeof(matrix_TYP *) * a[0]->speicher);
126
a[0]->representatives = (matrix_TYP **) realloc(a[0]->representatives,
127
sizeof(matrix_TYP *) * a[0]->speicher);
128
a[0]->rep_invs = (matrix_TYP **) realloc(a[0]->rep_invs,
129
sizeof(matrix_TYP *) * a[0]->speicher);
130
a[0]->words = (int **) realloc(a[0]->words,sizeof(int*));
131
a[0]->generators = (matrix_TYP **) realloc(a[0]->generators,
132
sizeof(matrix_TYP *) * a[0]->speicher);
133
}
134
135
/***************************************************************************
136
@
137
@ --------------------------------------------------------------------------
138
@
139
@ void free_bahn(bahn *a)
140
@
141
@ --------------------------------------------------------------------------
142
@
143
***************************************************************************/
144
extern void free_bahn(bahn *a)
145
{
146
int i;
147
148
for (i=0;i<a->length;i++){
149
if (a->orbit[i] != NULL){
150
free_mat(a->orbit[i]);
151
}
152
if (a->representatives[i] != NULL){
153
free_mat(a->representatives[i]);
154
}
155
if (a->rep_invs[i] != NULL){
156
free_mat(a->rep_invs[i]);
157
}
158
if (a->words[i] != NULL){
159
free(a->words[i]);
160
}
161
}
162
a->length =0;
163
a->gen_no = 0;
164
a->speicher = 0;
165
free(a->orbit);
166
free(a->representatives);
167
free(a->rep_invs);
168
free(a->words);
169
free(a->generators);
170
a->orbit = NULL;
171
a->representatives = NULL;
172
a->generators = NULL;
173
174
free_tree(a->hash);
175
a->hash = NULL;
176
}
177
178
static int position(matrix_TYP **a,matrix_TYP *x,int n)
179
/* returns the first index i<n such that a[i] == x, and
180
-1 if none exists */
181
{
182
int i=0;
183
184
while (i<n){
185
if (mat_comp(a[i],x) == 0){
186
return i;
187
}
188
i++;
189
}
190
return -1;
191
}
192
193
static void inv_word(int *w,
194
int *w_to_inv)
195
{
196
int i,
197
j;
198
199
for (i=1,j=w_to_inv[0];i<=w_to_inv[0];i++,j--)
200
w[i] = -w_to_inv[j];
201
202
w[0] = w_to_inv[0];
203
204
return;
205
} /* inv_word */
206
207
static int *get_word_to_generator(bahn *A,
208
matrix_TYP *h)
209
{
210
211
int i,
212
*w;
213
214
for (i=0;i<A->length && mat_comp(A->representatives[i],h) ; i++);
215
216
w = (int *) malloc((A->words[i][0]+1)*sizeof(int));
217
memcpy(w,A->words[i],(A->words[i][0]+1)*sizeof(int));
218
219
return w;
220
221
} /* get_word_to_generator */
222
223
224
225
/***************************************************************************
226
@
227
@ --------------------------------------------------------------------------
228
@
229
@ int einordnen(bahn** erg,
230
@ matrix_TYP *h,
231
@ matrix_TYP *new_vec,
232
@ int *w,
233
@ int l,
234
@ int flag)
235
@
236
@ bahn **erg : the set of base/strong generators for a finite
237
@ group G. it's the ONLY variable to be changed.
238
@ matrix_TYP *h :
239
@ matrix_TYP *new_vec : this value is not asked for in the case
240
@ described here, so any variable with the right
241
@ type will do.
242
@ int l : -1 ALLWAYS
243
@ int flag : TRUE ALLWAYS!!!!!
244
@
245
@ Inserts a new generator h into the list of strong generators for
246
@ any FINITE group G.
247
@ Therefore erg has to be the result of a call of strong_generators(..)
248
@ for some bravais_TYP *G.
249
@ The function calls itself recursively, and therefore the convention to
250
@ use it is somewhat cryptical. In all cases for the 'end user' l has to
251
@ be -1, and flag has to be TRUE (no garanties otherwise).
252
@ THE FUNCTION DOES NOT COPY THE VARIABLE h INTO erg[0]->generators,
253
@ (IT JUST STORES THE POINTER THERE), THEREFORE THE USER IS ASKED TO
254
@ ASSURE THAT h STAY'S IN THE SAME PLACE WHILE USING erg !!!!!!!!!!
255
@ The function does not check whether the new generator h is really needed,
256
@ so better check is out before calling this function by a call of is_element!
257
@ --------------------------------------------------------------------------
258
@
259
***************************************************************************/
260
static int einordnen(bahn** erg,
261
matrix_TYP *h,
262
matrix_TYP *new_vec,
263
int *w,
264
int l,
265
int flag)
266
{
267
int tmp = erg[0]->representatives[0]->cols,
268
tmp2,
269
i,
270
*wn;
271
272
matrix_TYP *hinv,
273
*nv,
274
*nh;
275
276
if (INFO_LEVEL & 2){
277
fprintf(stderr,"entering einordnen with l = %d\n",l);
278
}
279
280
if (l>=tmp){
281
return FALSE;
282
}
283
else{
284
285
if (l!=(-1)){
286
tmp2 = hash_mat(erg[l]->hash,erg[l]->orbit,new_vec,erg[l]->length);
287
}
288
else{
289
tmp2 = (-1);
290
}
291
292
if (tmp2!= (-1)){
293
/* we got an element of the stabilizer, */
294
/* calculate it then! */
295
free_mat(new_vec);
296
297
/* in the last stage we won't need an element of
298
the stabilizer anymore, so we won't calculate it */
299
if (((l+1)<tmp) && (mat_comp(h,erg[l]->representatives[tmp2])!=0)){
300
/* hinv = mat_inv(h);
301
free_mat(h);
302
mat_muleq(hinv,erg[l]->representatives[tmp2]);
303
h = hinv;
304
new_vec = mat_mul(h,erg[l+1]->orbit[0]); */
305
hinv = mat_mul(erg[l]->rep_invs[tmp2],h);
306
free_mat(h);
307
h = hinv;
308
new_vec = mat_mul(h,erg[l+1]->orbit[0]);
309
310
if (w){
311
wn = (int *) malloc((erg[l]->words[tmp2][0]+w[0]+1)
312
*sizeof(int));
313
inv_word(wn,erg[l]->words[tmp2]);
314
memcpy(wn+wn[0]+1,w+1,w[0]*sizeof(int));
315
wn[0] = wn[0] + w[0];
316
free(w);
317
}
318
else{
319
wn = NULL;
320
}
321
}
322
else{
323
/* only clean up memory */
324
free_mat(h);
325
if (w) free(w);
326
return FALSE;
327
}
328
329
/* enter the next stage */
330
flag = einordnen(erg,h,new_vec,wn,++l,TRUE);
331
}
332
else{
333
if (l != (-1)){
334
if (erg[l]->speicher<=erg[l]->length){
335
extend_bahn(erg+l);
336
337
/* this is so seldom used that we might as well check wheter
338
the group is infinite, find a solution later !! */
339
}
340
erg[l]->orbit[erg[l]->length]=new_vec;
341
erg[l]->representatives[erg[l]->length]=h;
342
/* inserted to reduce the number of mat_inv s */
343
erg[l]->rep_invs[erg[l]->length] = mat_inv(h);
344
345
if (w){
346
/* deal with the words */
347
erg[l]->words[erg[l]->length]
348
= (int *) malloc((w[0]+1) * sizeof(int));
349
memcpy(erg[l]->words[erg[l]->length],w,(w[0]+1) * sizeof(int));
350
free(w);
351
}
352
erg[l]->length++;
353
354
if (INFO_LEVEL & 1){
355
fprintf(stderr,"l = %d, lenght in this stage %d\n"
356
,l,erg[l]->length);
357
}
358
}
359
360
if (flag){
361
362
if (l == (-1)) l =0;
363
364
/* firstly put this element on the generator list */
365
erg[l]->generators[erg[l]->gen_no] = h;
366
erg[l]->gen_no++;
367
368
}
369
370
}
371
}
372
373
if (flag){
374
/* do a new orbit-calculation */
375
/* apply all generators to the previous orbit elements */
376
for(tmp=0;tmp<erg[l]->length;tmp++){
377
for (tmp2=l;tmp2<erg[0]->representatives[0]->cols;tmp2++){
378
for (i=erg[tmp2]->gen_no-1;i>=0;i--){
379
h = erg[tmp2]->generators[i];
380
nv = mat_mul(h,erg[l]->orbit[tmp]);
381
nh = mat_mul(h,erg[l]->representatives[tmp]);
382
if (w){
383
wn = get_word_to_generator(erg[tmp2],h);
384
wn = (int *) realloc(wn,
385
(wn[0]+erg[l]->words[tmp][0]+1) * sizeof(int));
386
memcpy(wn+wn[0]+1,erg[l]->words[tmp]+1,
387
erg[l]->words[tmp][0] * sizeof(int));
388
wn[0] = wn[0] + erg[l]->words[tmp][0];
389
}
390
else{
391
wn = NULL;
392
}
393
einordnen(erg,nh,nv,wn,l,FALSE);
394
}
395
}
396
}
397
}
398
399
return flag;
400
} /* einordnen(..........) */
401
402
/***********************************************************************
403
@
404
@-----------------------------------------------------------------------
405
@
406
@ bahn **strong_generators(matrix_TYP **base,bravais_TYP *U)
407
@
408
@ matrix_TYP **base:
409
@ bravais_TYP *U :
410
@
411
@ Calculates a strong generating set according to the sims algorithm
412
@ for the FINITE group U and the given base.
413
@ This function initialises the result according to the conventions
414
@ made in this file. It doesn't change neither **base nor *U.
415
@ for U only the entries U->dim, U->gen and U->gen_no are used.
416
@-----------------------------------------------------------------------
417
@
418
************************************************************************/
419
bahn **strong_generators(matrix_TYP **base,bravais_TYP *U,int OPT)
420
{
421
bahn **erg;
422
423
int i,
424
j,
425
k,
426
m,
427
dim = U->dim,
428
*w;
429
430
matrix_TYP **gen=U->gen,
431
*new_vec,
432
*g,
433
*h;
434
435
436
/* geting the memory for the result */
437
erg = (bahn **) calloc(dim,sizeof(bahn *));
438
for (i=0;i<dim;i++){
439
erg[i] = (bahn *) calloc(1,sizeof(bahn));
440
init_bahn(erg[i]);
441
}
442
443
for (i=0;i<dim;i++){
444
erg[i]->representatives[0] = init_mat(U->dim,U->dim,"1");
445
erg[i]->rep_invs[0] = init_mat(U->dim,U->dim,"1");
446
erg[i]->words[0] = (int *) malloc(sizeof(int));
447
erg[i]->words[0][0] = 0;
448
erg[i]->orbit[0] = copy_mat(base[i]);
449
erg[i]->length = 1;
450
erg[i]->hash->no = 0;
451
}
452
453
/* doing the orbit-calculation */
454
for (j=0;j<erg[0]->length;j++){
455
for (k=0;k<U->gen_no;k++){
456
457
if (INFO_LEVEL & 4){
458
/* printing all results for debugging */
459
for (i=0;i<dim;i++){
460
for (m=0;m<erg[i]->length;m++){
461
printf("i=%d m=%d\n",i,m);
462
if (erg[i]->representatives[m]->rows != dim ||
463
erg[i]->orbit[m]->rows != dim){
464
printf("fehler in strong_generators\n");
465
exit(3);
466
}
467
put_mat(erg[i]->representatives[m],NULL,"represe",2);
468
put_mat(erg[i]->orbit[m],NULL,"orbit",2);
469
}
470
}
471
}
472
473
/* decide which group element will act */
474
g=gen[k];
475
476
if (INFO_LEVEL & 4 ){
477
put_mat(g,NULL,"angewandter erzeuger",2);
478
}
479
480
h = mat_mul(g,erg[0]->representatives[j]);
481
new_vec = mat_mul(g,erg[0]->orbit[j]);
482
483
484
if (OPT){
485
w = (int *) malloc((erg[0]->words[j][0] + 2) * sizeof(int));
486
w[0] = erg[0]->words[j][0] + 1;
487
w[1] = k+1;
488
memcpy(w+2,erg[0]->words[j]+1,erg[0]->words[j][0] * sizeof(int));
489
}
490
else{
491
w = NULL;
492
}
493
einordnen(erg,h,new_vec,w,0,FALSE);
494
495
}
496
}
497
498
return erg;
499
} /* strong_generators */
500
501
extern matrix_TYP **get_base(bravais_TYP *U)
502
/* will only return a standart basis */
503
{
504
matrix_TYP **erg;
505
506
int dim=U->dim,
507
i;
508
509
erg = (matrix_TYP **) malloc(dim * sizeof(matrix_TYP *));
510
511
for (i=0;i<dim;i++){
512
erg[i] = init_mat(dim,1,"i");
513
erg[i]->array.SZ[i][0] = 1;
514
}
515
516
return erg;
517
} /* get_base */
518
519
/*************************************************************************
520
@
521
@ --------------------------------------------------------------------------
522
@
523
@ int is_element(matrix_TYP *x,bravais_TYP *G,bahn **strong,int **w)
524
@
525
@ matrix_TYP *x: the matrix in question
526
@ bravais_TYP *G: actually the only thing asked for is G->dim!
527
@ bahn **strong: the result of a call of strong_generators(..)
528
@ for the group G.
529
@
530
@ Decides whether the matrix represented by *x is contained in the
531
@ group described by **strong and *G respectively.
532
@ strong has to be the result of a call of strong_generators(..)
533
@ for the group G.
534
@ The function returns TRUE if x in G, and FALSE otherwise.
535
@ None of the given variables is changed.
536
@
537
@ --------------------------------------------------------------------------
538
@
539
***************************************************************************/
540
extern int is_element(matrix_TYP *x,bravais_TYP *G,bahn **strong,int **w)
541
{
542
int erg=TRUE,
543
dim = G->dim,
544
i=0,
545
pos,
546
*w2;
547
548
matrix_TYP *g_neu,
549
*bild,
550
*h;
551
552
g_neu = copy_mat(x);
553
554
while (erg && (i<dim)){
555
556
/* map the basepoint by the element which got to be in
557
the pointwise stabilizer of the basepoints b_0,..b_{i-1} */
558
bild = mat_mul(g_neu,strong[i]->orbit[0]);
559
560
/* test whether this image is an image also produced by G */
561
pos = hash_mat(strong[i]->hash,strong[i]->orbit,bild,-1);
562
563
if (pos == (-1)){
564
erg = FALSE;
565
free_mat(bild);
566
}
567
else{
568
/* h = mat_inv(g_neu);
569
free_mat(g_neu);
570
free_mat(bild);
571
g_neu = mat_mul(h,strong[i]->representatives[pos]);
572
free_mat(h); */
573
free_mat(bild);
574
h = mat_mul(strong[i]->rep_invs[pos],g_neu);
575
free_mat(g_neu);
576
g_neu = h;
577
578
if (w){
579
if (w[0]){
580
w2 = (int *) calloc(w[0][0]+strong[i]->words[pos][0]+1,
581
sizeof(int));
582
w2[0] = w[0][0]+strong[i]->words[pos][0];
583
memcpy(w2+1,w[0]+1,w[0][0] * sizeof(int));
584
memcpy(w2+w[0][0]+1,(strong[i]->words[pos])+1,
585
strong[i]->words[pos][0]* sizeof(int));
586
free(w[0]);
587
}
588
else{
589
w2 = (int *) calloc(strong[i]->words[pos][0]+1,sizeof(int));
590
w2[0] = strong[i]->words[pos][0];
591
memcpy(w2+1,strong[i]->words[pos]+1,strong[i]->words[pos][0]*
592
sizeof(int));
593
}
594
w[0] = w2;
595
}
596
i++;
597
598
}
599
}
600
601
free_mat(g_neu);
602
603
return erg;
604
} /* is_element */
605
606
/**************************************************************************
607
@
608
@ --------------------------------------------------------------------------
609
@
610
@ int size(bahn **a)
611
@
612
@ bahn **a: the result of a call strong_generators(...) for some
613
@ bravais_TYP *G.
614
@
615
@ Under this condition, the function will return the order of the group G.
616
@ Actually calculated is the product of a[i]->length in some ranges.
617
@
618
@ --------------------------------------------------------------------------
619
@
620
**************************************************************************/
621
extern int size(bahn **a)
622
{
623
int i,
624
size = 1;
625
626
for (i=0;i<a[0]->representatives[0]->cols;i++){
627
size = size*a[i]->length;
628
}
629
630
return size;
631
}
632
633
/**************************************************************************
634
@
635
@ --------------------------------------------------------------------------
636
@
637
@ matrix_TYP **normalizer_in_N(bravais_TYP *U,bravais_TYP *N,int *anz,
638
@ int finite)
639
@
640
@ calculates a generating set for the normalizer of the FINITE group
641
@ U in the group N, and N is interpreted as generated by N->gen, N->cen and
642
@ N->normal. The assumption is, that U^N is FINITE.
643
@ bravais_TYP *U
644
@ bravais_TYP *N
645
@ int *anz
646
@ int finite
647
@ It returns the elements of the normalizer via return, and the
648
@ number of these via anz[0].
649
@ no global variables nor U or N are changed.
650
@ If finite == true the program assumes that the calculated normalizer
651
@ is finite, and tries to get hold of a set of base/strong generators
652
@ for it. THIS WILL WORK IFF THE CALCULATED NORMALIZER IS INDEED FINITE.
653
@ The program will get the record U->order and U->divisors!
654
@
655
@ --------------------------------------------------------------------------
656
@
657
***************************************************************************/
658
extern matrix_TYP **normalizer_in_N(bravais_TYP *U,bravais_TYP *N,int *anz,
659
int finite)
660
{
661
matrix_TYP **erz_N,
662
**erg,
663
**orbit,
664
*test_subgroup,
665
**base,
666
*tmp,
667
*tmp2,
668
*tmp3,
669
*stab_element;
670
671
bravais_TYP BN;
672
673
bahn **strong,
674
**strong_N;
675
676
int i,
677
j,
678
k,
679
l,
680
flag,
681
gefunden,
682
gen_no,
683
dim = U->dim,
684
speicher,
685
erg_speicher;
686
687
/* getting the standart basis for the vectorspace */
688
base = get_base(U);
689
strong = strong_generators(base,U,FALSE);
690
691
/* set the order of U */
692
U->order = size(strong);
693
factorize_new(U->order,U->divisors);
694
695
if (INFO_LEVEL & 4){
696
printf("calculated the base for U\n");
697
}
698
699
/* we are going to need the inverse of each generator anyway
700
for conjugation, so calculate them now and stick them
701
in the right position */
702
gen_no = N->gen_no + N->normal_no + N->cen_no;
703
704
erz_N = (matrix_TYP **) malloc(gen_no * sizeof(matrix_TYP *));
705
706
for (i=0;i<gen_no;i++){
707
if (i<N->gen_no){
708
erz_N[i] = copy_mat(N->gen[i]);
709
}
710
else if(i<N->gen_no + N->cen_no){
711
erz_N[i] = copy_mat(N->cen[i - N->gen_no]);
712
}
713
else {
714
erz_N[i] = copy_mat(N->normal[i-N->gen_no-N->cen_no]);
715
}
716
}
717
718
/* the subgroups will be represented by the element that
719
conjugates them */
720
orbit = (matrix_TYP **) malloc(MIN_SPEICHER * sizeof(matrix_TYP *));
721
speicher = MIN_SPEICHER;
722
orbit[0] = init_mat(dim,dim,"1");
723
gefunden = 1;
724
725
/* getting memory for the result */
726
erg = (matrix_TYP **) malloc(MIN_SPEICHER * sizeof(matrix_TYP *));
727
erg_speicher = MIN_SPEICHER;
728
anz[0] = 0;
729
730
/* strong orbit calculation yields the normalizer */
731
for (i=0;i<gefunden;i++){
732
733
if (INFO_LEVEL & 1){
734
fprintf(stderr,"found %d conjugated subgroups,\n",gefunden);
735
fprintf(stderr,"dealt with %d of these.\n",i);
736
}
737
738
for (j=0;j<(gen_no);j++){
739
740
/* we only have do deal with the generators, because, we
741
assume that the orbits are finite */
742
test_subgroup = mat_mul(erz_N[j],orbit[i]);
743
744
/* now look, whether we already got this subgroup */
745
/* it's a fiddly part, because I can't think of a */
746
/* ordering for these subgroups */
747
k=0;
748
flag = FALSE;
749
tmp = mat_inv(test_subgroup);
750
751
while (!flag && (k<gefunden)){
752
753
if (INFO_LEVEL & 4){
754
put_mat(tmp,NULL,"tmp",2);
755
put_mat(orbit[k],NULL,"orbit[k]",2);
756
printf("k= %d\n",k);
757
}
758
stab_element = mat_mul(tmp,orbit[k]);
759
760
if (INFO_LEVEL & 4){
761
put_mat(stab_element,NULL,NULL,2);
762
}
763
764
/* calculate the conjugates of the generators of U
765
and decide whether they are in U */
766
l=0;
767
while (l<U->gen_no){
768
if (INFO_LEVEL & 4){
769
put_mat(stab_element,NULL,"stab_el",2);
770
}
771
tmp2 = mat_inv(stab_element);
772
tmp3 = mat_mul(tmp2,U->gen[l]);
773
free_mat(tmp2);
774
tmp2 = mat_mul(tmp3,stab_element);
775
free_mat(tmp3);
776
777
if (INFO_LEVEL & 4){
778
printf("l= %d\n",l);
779
}
780
781
if (!is_element(tmp2,U,strong,NULL)){
782
l = U->gen_no + 1;
783
}
784
l++;
785
free_mat(tmp2);
786
}
787
788
if (l==U->gen_no){
789
flag=TRUE;
790
}
791
else{
792
free_mat(stab_element);
793
stab_element = NULL;
794
}
795
k++;
796
797
}/* while (!flag .. */
798
799
free_mat(tmp);
800
801
/* so now we see whether the element was really in the
802
stabilizer */
803
if (flag){
804
free_mat(test_subgroup);
805
806
/* we might already got this element of the normalizer,
807
so better check it out */
808
if ((position(erg,stab_element,anz[0])> (-1)) &&
809
(stab_element != NULL)){
810
free_mat(stab_element);
811
}
812
else if (finite){
813
/* if we assume the normalizer to be finite, we will
814
have an even better test for a new element */
815
if (anz[0] == 0){
816
erg[0] = stab_element;
817
anz[0]++;
818
BN.gen = erg;
819
BN.gen_no = 1;
820
BN.dim = dim;
821
strong_N = strong_generators(base,&BN,FALSE);
822
strong_N[0]->generators[0] = stab_element;
823
strong_N[0]->gen_no = 1;
824
}
825
else{
826
/* we might already got this element in our stabilizer */
827
if (is_element(stab_element,&BN,strong_N,NULL)){
828
free_mat(stab_element);
829
stab_element = NULL;
830
}
831
else{
832
/* this element is new */
833
anz[0]++;
834
if (erg_speicher <= anz[0]){
835
erg_speicher = erg_speicher+MIN_SPEICHER;
836
erg = (matrix_TYP **) realloc(erg,
837
erg_speicher*sizeof(matrix_TYP *));
838
}
839
erg[anz[0]-1] = stab_element;
840
einordnen(strong_N,stab_element,
841
stab_element,NULL,-1,TRUE);
842
}
843
}
844
}
845
else{
846
anz[0]++;
847
if (erg_speicher<=anz[0]){
848
erg_speicher = erg_speicher+MIN_SPEICHER;
849
erg = (matrix_TYP **) realloc(erg,
850
erg_speicher*sizeof(matrix_TYP *));
851
}
852
erg[anz[0]-1] = stab_element;
853
}
854
}
855
else{
856
if (INFO_LEVEL & 4){
857
put_mat(stab_element,NULL,NULL,2);
858
}
859
860
if (stab_element != NULL) free_mat(stab_element);
861
862
gefunden++;
863
864
if (speicher<=gefunden){
865
speicher = speicher+MIN_SPEICHER;
866
orbit = (matrix_TYP **) realloc(orbit,
867
speicher*sizeof(matrix_TYP *));
868
}
869
orbit[gefunden-1] = test_subgroup;
870
}
871
872
}/* for (j=0 .. */
873
}/* for (i=0 .., ie the orbit calculation */
874
875
/* cleaning up the memory */
876
for (i=0;i<dim;i++){
877
free_mat(base[i]);
878
free_bahn(strong[i]);
879
free(strong[i]);
880
if (finite){
881
free_bahn(strong_N[i]);
882
free(strong_N[i]);
883
}
884
}
885
if ((INFO_LEVEL & 1) && finite){
886
fprintf(stderr,"Order of the normalizer: %d\n",size(strong_N));
887
}
888
free(base);
889
free(strong);
890
if (finite) free(strong_N);
891
892
for (i=0;i<gen_no;i++){
893
free_mat(erz_N[i]);
894
}
895
free(erz_N);
896
897
for (i=0;i<gefunden;i++){
898
free_mat(orbit[i]);
899
}
900
free(orbit);
901
902
return erg;
903
} /* normalizer_in_N */
904
905
/**************************************************************************
906
@
907
@--------------------------------------------------------------------------
908
@
909
@ int red_gen(bravais_TYP *G,matrix_TYP **base,bahn ***strong,int i)
910
@
911
@ Tries to reduce the number of generators for the group G, and returns
912
@ |G|.
913
@
914
@ bravais_TYP *G: the group in question
915
@ matrix_TYP **base: a basis for the vectorspace on which G is acting
916
@ bahn ***strong: after the call of this function strong[0] will
917
@ contain a set of base/strong generating set for
918
@ the group G.
919
@ There are two cases for the call of this function
920
@ 1st: strong[0] == NULL
921
@ the pfunction reduces the number of generators
922
@ for G.
923
@ 2nd: strong[0] != NULL
924
@ the function assummes strong[0] to contain a set
925
@ of base/strong generators for the group generated
926
@ by the first i generators of G, and kills
927
@ those of the other generators which does not
928
@ give a bigger group.
929
@ int i: see above
930
@
931
@ SIDEEFFECTS: the entries of G->gen may be changed, and they
932
@ may be shuffled. G->gen_no may be changed to
933
@ the number of relevant matrices.
934
@ strong[0] returns a set of base/strong generators
935
@ for G, NO OTHER GLOBAL VARIABLE IS CHANGED.
936
@
937
@--------------------------------------------------------------------------
938
@
939
***************************************************************************/
940
extern int red_gen(bravais_TYP *G,matrix_TYP **base,bahn ***strong,int i)
941
{
942
int G_gen_no= G->gen_no;
943
944
if (strong[0] == NULL){
945
G->gen_no = 1;
946
i=1;
947
strong[0] = strong_generators(base,G,FALSE);
948
strong[0][0]->gen_no = 1;
949
strong[0][0]->generators[0] = G->gen[0];
950
}
951
952
/* this will free all irrelevant generators */
953
while (i<G_gen_no){
954
if (!is_element(G->gen[i],G,strong[0],NULL)){
955
einordnen(strong[0],G->gen[i],G->gen[i],NULL,-1,TRUE);
956
}
957
else{
958
free_mat(G->gen[i]);
959
G->gen[i] = NULL;
960
}
961
i++;
962
}
963
964
G->gen_no = G_gen_no;
965
for (i=0;i<G->gen_no;i++){
966
if (G->gen[i] == NULL){
967
G->gen[i] = G->gen[G->gen_no-1];
968
G->gen_no--;
969
i--;
970
}
971
}
972
973
/* just for sanity */
974
G->gen = (matrix_TYP **) realloc(G->gen, G->gen_no * sizeof(matrix_TYP *));
975
976
return size(strong[0]);
977
}
978
979