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

563680 views
1
#include "typedef.h"
2
#include "longtools.h"
3
#include "matrix.h"
4
#include "sort.h"
5
6
/**************************************************************************\
7
@---------------------------------------------------------------------------
8
@---------------------------------------------------------------------------
9
@ FILE: orbit_alg.c
10
@---------------------------------------------------------------------------
11
@---------------------------------------------------------------------------
12
@
13
\**************************************************************************/
14
15
16
/**************************************************************************\
17
@---------------------------------------------------------------------------
18
@ matrix_TYP **orbit_alg(M, G, S, option, length)
19
@ bravais_TYP *G, *S;
20
@ matrix_TYP *M;
21
@ int *option, *length;
22
@
23
@ 'orbit_alg calculates the orbit of the matrix M under the group G.
24
@
25
@ The length of the orbit is returned by the pointer 'length'.
26
@ It is possible to calculate the stabiliser of M in G.
27
@ It is returned in the pointer 'S' which has to be allocated as '*bravais_TYP'
28
@ before calling the function.
29
@
30
@ 'option' is an array of size 5.
31
@ The following options are possible:
32
@
33
@ option[0] = 0: the group operates from the left: x->gx
34
@ option[0] = 1: the group operates from the right: x->xg
35
@ option[0] = 2: the group operates via x-> g x g^(tr) (from the left)
36
@ option[0] = 3: the group operates via x-> g^(tr) x g (from the right)
37
@ option[0] = 4: the group operates by conjugation: x-> g x g^(-1)
38
@ (from the left)
39
@ option[0] = 5: the group operates by conjugation: x-> g^(-1) x g
40
@ (from the right)
41
@
42
@ option[1] = 1: the group operates on the pairs {M, -M}
43
@ option[1] = 2: the group caluluates the orbit of the set of rows of M;
44
@ option[1] = 3: combination of 1 and 2.
45
@ option[1] = 4: the group operates on sublattices of Z^n.
46
@
47
@ option[2] = 0: the whole orbit is calculated
48
@ option[2] = n: only the first n elements of the orbit are calculated
49
@
50
@ option[3] = 1: the stabiliser is calculated.
51
@
52
@ option[4] = 0: the full stabiliser is calculated.
53
@ option[4] = n: only the first n elements of the stabiliser are calculated
54
@ option[4] = -n: only the first n elements of the stabiliser are calculated,
55
@ afterwards the algorithm is stopped.
56
@
57
@ option[5] = 1: Also the inverse of the generators are used in the algorithmn.
58
@
59
@---------------------------------------------------------------------------
60
@
61
\**************************************************************************/
62
63
/*****************************************
64
orbit_alg bestimmt die Bahn der Matrix M unter der Gruppe G
65
66
Die Bahnlaenge wird ueber den Zeiger length zurueckgegeben.
67
Soll der Stabilisator von M in G berechnet werden, so muessen
68
die Inversen der Erzeuger von G in Ginv angegeben werden.
69
In diesem Fall wird der Stabilisator ueber den Zeiger S zurueckgegeben.
70
Der Zeiger S muss aber bereits als *bravais_TYP allokiert sein.
71
72
option ist ein array der Groesse 5.
73
Folgende Optionen sind moeglich:
74
75
option[0] = 0: die Gruppe operiert durch Linksmultiplikation: x->gx
76
option[0] = 1: die Gruppe operiert durch Rechtsmultiplikation: x->xg
77
option[0] = 2: die Gruppe operiert durch x-> g x g^(tr) (von links)
78
option[0] = 3: die Gruppe operiert durch x-> g^{tr} x g (von rechts)
79
option[0] = 4: die Gruppe operiert durch Konjugationation: x-> g x g^(-1)
80
(von links)
81
option[0] = 5: die Gruppe operiert durch Konjugationation: x-> g^(-1) x g
82
(von rechts)
83
84
option[1] = 1: die Gruppe operiert auf den Paaren {M, -M}
85
option[1] = 2: die Gruppe berechnet die Bahn der Menge der Zeilen von M;
86
option[1] = 3: Kombination von 1 und 2.
87
option[1] = 4: die Gruppe operiert auf Teilgittern von Z^n.
88
89
option[2] = 0: die volle Bahn wird berechnet
90
option[2] = n: die ersten n Elemente der Bahn werden berechnet
91
92
option[3] = 1: der Stabilisator wird berechnet
93
94
option[4] = 0: der volle Stabilisator wird berechnet
95
option[4] = n: die ersten n Elemente des Stabilisators werden berechnet
96
option[4] = -n: die ersten n Elemente des Stabilisators werden berechnet,
97
dannach wird der Algorthmus abgebrochen.
98
99
option[5] = 1: Auch die Inversen der Erzeuger werden im Algorithmus
100
angewendet.
101
******************************************/
102
103
104
static matrix_TYP **Erz;
105
static matrix_TYP **Erz_inv;
106
static int *orbit_opt;
107
static matrix_TYP *hash_mat;
108
static int hash_prime = 130003;
109
110
111
static void matrix_speichern(mat, L, listsize, anz)
112
matrix_TYP *mat;
113
matrix_TYP ***L;
114
int *listsize, *anz;
115
{
116
int i, j, k;
117
118
extern matrix_TYP *init_mat();
119
if((*anz) == 0)
120
if ((*L=(matrix_TYP **)malloc((*listsize)*sizeof(matrix_TYP *)))==NULL)
121
{
122
fprintf (stderr, "malloc failed\n");
123
exit (2);
124
}
125
if ((*anz) >= (*listsize))
126
{
127
*listsize += EXT_SIZE;
128
if ((*L=(matrix_TYP **)realloc(*L,(*listsize)*sizeof(matrix_TYP *)))==NULL)
129
{
130
fprintf (stderr, "realloc failed\n");
131
exit (2);
132
}
133
}
134
(*L)[(*anz)] = mat;
135
(*anz) ++;
136
}
137
138
139
140
static struct baum *addbaum(mat, L, anz, verz, schonda)
141
matrix_TYP *mat;
142
matrix_TYP **L;
143
int anz;
144
struct baum *verz;
145
int *schonda;
146
{
147
int vergleich;
148
*schonda = -1;
149
if(verz == NULL)
150
{
151
verz = (struct baum *) malloc(sizeof(struct baum));
152
verz->no = anz;
153
verz->left = verz->right = NULL;
154
}
155
else
156
{
157
vergleich = mat_comp(mat, L[verz->no]);
158
if(vergleich<0)
159
verz->left = addbaum(mat, L, anz, verz->left, schonda);
160
if(vergleich > 0)
161
verz->right = addbaum(mat, L, anz, verz->right, schonda);
162
if(vergleich == 0)
163
*schonda = verz->no;
164
}
165
return(verz);
166
}
167
168
169
struct baum *hash_addbaum(mat, L, anz, verz, schonda, hashnumber, hashverz)
170
matrix_TYP *mat;
171
matrix_TYP **L;
172
int anz;
173
struct baum *verz;
174
int *schonda, hashnumber, *hashverz;
175
{
176
int vergleich;
177
*schonda = -1;
178
if(verz == NULL)
179
{
180
verz = (struct baum *) malloc(sizeof(struct baum));
181
verz->no = anz;
182
verz->left = verz->right = NULL;
183
}
184
else
185
{
186
if(hashnumber != hashverz[verz->no])
187
{
188
if(hashnumber < hashverz[verz->no])
189
verz->left = hash_addbaum(mat, L, anz, verz->left, schonda, hashnumber, hashverz);
190
else
191
verz->right = hash_addbaum(mat, L, anz, verz->right, schonda, hashnumber, hashverz);
192
}
193
else
194
{
195
vergleich = mat_comp(mat, L[verz->no]);
196
if(vergleich<0)
197
verz->left = hash_addbaum(mat, L, anz, verz->left, schonda, hashnumber, hashverz);
198
if(vergleich > 0)
199
verz->right = hash_addbaum(mat, L, anz, verz->right, schonda, hashnumber, hashverz);
200
if(vergleich == 0)
201
*schonda = verz->no;
202
}
203
}
204
return(verz);
205
}
206
207
208
209
210
int *make_orbit_options()
211
{
212
int *option;
213
214
option = (int *)malloc(6 *sizeof(int));
215
option[0] = 0;
216
if(is_option('l') == TRUE)
217
option[0] = 0;
218
if(is_option('r') == TRUE)
219
option[0] = 1;
220
if(is_option('t') == TRUE)
221
option[0] = 2;
222
if(is_option('t') == TRUE && is_option('r') == TRUE)
223
option[0] = 3;
224
if(is_option('k') == TRUE)
225
option[0] = 4;
226
if(is_option('k') == TRUE && is_option('r') == TRUE)
227
option[0] = 5;
228
229
option[1] = 0;
230
if(is_option('p') == TRUE)
231
option[1] = 1;
232
if(is_option('u') == TRUE)
233
option[1] = 2;
234
if(is_option('p') == TRUE && is_option('u') == TRUE)
235
option[1] = 3;
236
if(is_option('g') == TRUE)
237
option[1] = 4;
238
239
option[2] = optionnumber('L');
240
option[3] = is_option('S');
241
option[4] = optionnumber('S');
242
if (option[4] == -1) option[4] = 0;
243
option[5] = is_option('i');
244
return(option);
245
}
246
247
static void qswap (mat, k, l)
248
matrix_TYP *mat;
249
int k,l;
250
{ int *temp;
251
252
temp = mat->array.SZ[k];
253
mat->array.SZ[k] = mat->array.SZ[l];
254
mat->array.SZ[l] = temp;
255
temp = NULL;
256
}
257
258
259
260
261
static void orbit_qsort (mat, left, right, orbit_comp)
262
matrix_TYP *mat;
263
int left, right;
264
int (*orbit_comp)();
265
{
266
int i, last;
267
void qswap ();
268
269
if ( left >= right )
270
return;
271
qswap (mat, left, (left + right) / 2);
272
last = left;
273
for ( i = left+1;
274
i <= right ;
275
i ++ )
276
if ( (*orbit_comp)(mat, i, left) < 0 )
277
qswap (mat, ++last, i);
278
qswap (mat, left, last);
279
orbit_qsort (mat, left, last - 1, orbit_comp);
280
orbit_qsort (mat, last + 1, right, orbit_comp);
281
}
282
283
static int orbit_comp (mat, k, l)
284
matrix_TYP *mat;
285
int k,l;
286
{ int i;
287
int **M;
288
int cM;
289
290
M = mat->array.SZ;
291
cM = mat->cols;
292
for ( i = 0 ; i<cM; i++)
293
{
294
if( M[k][i] > M[l][i])
295
return (-1);
296
else
297
if( M[k][i] < M[l][i])
298
return (1);
299
}
300
return (0);
301
}
302
303
304
305
static void standartisieren(mat)
306
matrix_TYP *mat;
307
{
308
int i,
309
j,
310
k;
311
312
if(orbit_opt[1] == 3)
313
{
314
for(i=0; i<mat->rows; i++)
315
{
316
k=0;
317
while(k<mat->cols && mat->array.SZ[i][k] == 0)
318
k++;
319
if(k<mat->cols && mat->array.SZ[i][k] <0)
320
{
321
for(j=k; j<mat->cols; j++)
322
mat->array.SZ[i][j] = -mat->array.SZ[i][j];
323
}
324
}
325
}
326
if(orbit_opt[1] == 1)
327
{
328
k = 0; i = 0;
329
while(i<mat->rows && k == 0)
330
{
331
j=0;
332
while(j<mat->cols && k==0)
333
{
334
if(mat->array.SZ[i][j] < 0)
335
k= -1;
336
if(mat->array.SZ[i][j] > 0)
337
k= 1;
338
j++;
339
}
340
i++;
341
}
342
if(k == -1)
343
{
344
for(i=0;i<mat->rows;i++)
345
for(j=0;j<mat->cols;j++)
346
mat->array.SZ[i][j] = -mat->array.SZ[i][j];
347
}
348
}
349
if(orbit_opt[1] == 2 || orbit_opt[1] == 3)
350
orbit_qsort(mat, 0, mat->rows-1, orbit_comp);
351
if(orbit_opt[1] == 4)
352
{
353
if(orbit_opt[0] == 0 || orbit_opt[0] == 2 || orbit_opt[0] == 4){
354
long_col_hnf(mat);
355
}
356
if(orbit_opt[0] == 1 || orbit_opt[0] == 3 || orbit_opt[0] == 5)
357
long_row_hnf(mat);
358
}
359
}
360
361
362
static matrix_TYP *tr_mul(A, B)
363
matrix_TYP *A, *B;
364
{
365
int i, j, k;
366
matrix_TYP *erg;
367
368
extern matrix_TYP *init_mat();
369
erg = init_mat(A->rows, B->rows, "");
370
for(i=0; i<erg->rows; i++)
371
{
372
for(j=0; j<erg->cols; j++)
373
{
374
erg->array.SZ[i][j] = 0;
375
for(k=0; k<A->cols; k++)
376
erg->array.SZ[i][j] += A->array.SZ[i][k] * B->array.SZ[j][k];
377
}
378
}
379
erg->kgv = A->kgv *B->kgv;
380
return(erg);
381
}
382
383
static matrix_TYP *grp_mul(A,B)
384
matrix_TYP *A, *B;
385
{
386
matrix_TYP *erg;
387
extern matrix_TYP *mat_mul();
388
if(orbit_opt[0] == 0 || orbit_opt[0] == 2 || orbit_opt[0] == 4)
389
erg = mat_mul(B,A);
390
if(orbit_opt[0] == 1 || orbit_opt[0] == 3 || orbit_opt[0] == 5)
391
erg = mat_mul(A,B);
392
return(erg);
393
}
394
395
static matrix_TYP *operation(M, i)
396
matrix_TYP *M;
397
int i;
398
{
399
matrix_TYP *erg, *waste, *waste1;
400
401
extern matrix_TYP *mat_mul();
402
extern matrix_TYP *tr_mul();
403
404
if(orbit_opt[0] == 0)
405
erg = mat_mul(Erz[i], M);
406
if(orbit_opt[0] == 1)
407
erg = mat_mul(M, Erz[i]);
408
if(orbit_opt[0] == 2)
409
{
410
waste = tr_mul(M, Erz[i]);
411
erg = mat_mul(Erz[i], waste);
412
free_mat(waste);
413
}
414
if(orbit_opt[0] == 3)
415
{
416
waste = tr_pose(Erz[i]);
417
waste1 = mat_mul(M, Erz[i]);
418
erg = mat_mul(waste, waste1);
419
free_mat(waste); free_mat(waste1);
420
}
421
if(orbit_opt[0] == 4)
422
{
423
waste = mat_mul(Erz[i], M);
424
erg = mat_mul(waste ,Erz_inv[i]);
425
free_mat(waste);
426
}
427
if(orbit_opt[0] == 5)
428
{
429
waste = mat_mul(Erz_inv[i], M);
430
erg = mat_mul(waste ,Erz[i]);
431
free_mat(waste);
432
}
433
return(erg);
434
}
435
436
static void make_hash_mat(M)
437
matrix_TYP *M;
438
{
439
int i,j;
440
extern matrix_TYP *init_mat();
441
442
hash_mat = init_mat(M->rows, M->cols, "");
443
for(i=0; i<M->rows;i++)
444
for(j=0;j<M->cols;j++)
445
{
446
hash_mat->array.SZ[i][j] = rand();
447
hash_mat->array.SZ[i][j] %= 1301;
448
}
449
}
450
451
452
static int hash_number(M)
453
matrix_TYP *M;
454
{
455
int i,j,h;
456
h = 0;
457
for(i=0;i<M->rows;i++)
458
for(j=0;j<M->cols;j++)
459
h = (h + M->array.SZ[i][j] * hash_mat->array.SZ[i][j])%hash_prime;
460
return(h);
461
}
462
463
extern void free_baum(struct baum *p)
464
{
465
466
if (p!= NULL){
467
if (p->left != NULL){
468
free_baum(p->left);
469
}
470
if (p->right != NULL){
471
free_baum(p->right);
472
}
473
free(p);
474
}
475
476
477
return;
478
}
479
480
matrix_TYP **orbit_alg(M, G, S, option, length)
481
bravais_TYP *G, *S;
482
matrix_TYP *M;
483
int *option, *length;
484
{
485
int i,j,k;
486
matrix_TYP **erg;
487
matrix_TYP **hist, **histinv;
488
matrix_TYP *I, *A, *K1, *K2;
489
int *hashnumbers;
490
int h, *hashverz;
491
int ergsize, histsize, histinvsize, Ssize;
492
int erganz, histanz, histinvanz;
493
int schonda, sch, abbruch;
494
int num, erzj, erz_anz;
495
int sopt;
496
struct baum *Sverz;
497
struct baum *ergverz;
498
499
extern matrix_TYP *init_mat();
500
extern matrix_TYP *mat_inv();
501
extern matrix_TYP *einheitsmatrix();
502
extern void matrix_speichern();
503
504
ergsize = 0;
505
histsize = 0;
506
histinvsize = 0;
507
erganz = 0;
508
histanz = 0;
509
histinvanz = 0;
510
Ssize = 0;
511
ergverz = NULL;
512
Sverz = NULL;
513
orbit_opt = option;
514
erzj = 0;
515
if(orbit_opt[5] == 1)
516
erz_anz = 2 * G->gen_no;
517
else
518
erz_anz = G->gen_no;
519
Erz = (matrix_TYP **) malloc(erz_anz *sizeof(matrix_TYP *));
520
for(i=0;i< G->gen_no;i++)
521
Erz[i] = G->gen[i];
522
if(orbit_opt[5] == 1)
523
{
524
for(i=0;i<G->gen_no;i++)
525
Erz[G->gen_no + i] = mat_inv(G->gen[i]);
526
}
527
if(orbit_opt[3] == TRUE || orbit_opt[0] == 4 || orbit_opt[0] == 5)
528
{
529
Erz_inv = (matrix_TYP **) malloc(erz_anz *sizeof(matrix_TYP *));
530
for(i=0;i<erz_anz;i++)
531
Erz_inv[i] = mat_inv(Erz[i]);
532
}
533
make_hash_mat(M);
534
535
536
standartisieren(M);
537
h = hash_number(M);
538
ergverz = hash_addbaum(M, erg, erganz, ergverz, &schonda, h, NULL);
539
erg = (matrix_TYP **)malloc(EXT_SIZE *sizeof(matrix_TYP));
540
erg[0] = init_mat(M->rows, M->cols, "");
541
hashverz = (int *)malloc(EXT_SIZE *sizeof(int));
542
hashverz[0] = h;
543
for(i=0; i<M->rows; i++)
544
for(j=0; j<M->cols; j++)
545
erg[0]->array.SZ[i][j] = M->array.SZ[i][j];
546
erg[0]->kgv = M->kgv;
547
erganz = 1;
548
ergsize = 100;
549
if(orbit_opt[3] == 1)
550
{
551
I = einheitsmatrix(Erz[0]->cols);
552
matrix_speichern(I, &hist, &histsize, &histanz);
553
matrix_speichern(I, &histinv, &histinvsize, &histinvanz);
554
S->gen_no = 0;
555
S->dim = Erz[0]->cols;
556
}
557
sopt = orbit_opt[3];
558
559
abbruch = FALSE;
560
num = 0;
561
while(abbruch == FALSE)
562
{
563
for(erzj=0; erzj<erz_anz && abbruch == FALSE; erzj++)
564
{
565
A = operation(erg[num], erzj);
566
standartisieren(A);
567
h = hash_number(A);
568
ergverz = hash_addbaum(A, erg, erganz, ergverz, &schonda, h, hashverz);
569
if(schonda != -1 && sopt == TRUE)
570
{
571
K1 = grp_mul(hist[num], Erz[erzj]);
572
K2 = grp_mul(K1, histinv[schonda]);
573
if(mat_comp(K2, I) != 0)
574
{
575
Sverz = addbaum(K2, S->gen, S->gen_no, Sverz, &sch);
576
if(sch == -1)
577
matrix_speichern(K2, &S->gen, &Ssize, &S->gen_no);
578
}
579
else{
580
/* inserted this case on 21 Oct 98 tilman */
581
free_mat(K2);
582
K2 = NULL;
583
}
584
if ((schonda == -1 || (schonda != -1 && sch != -1)) && K2 != NULL)
585
free_mat(K2);
586
free_mat(K1); K2 = NULL;
587
}
588
if(schonda == -1)
589
{
590
if(erganz == ergsize)
591
{
592
if((hashverz = (int *)realloc(hashverz, (ergsize+EXT_SIZE)*sizeof(int))) == NULL)
593
{
594
printf("realloc failed\n");
595
exit(2);
596
}
597
}
598
hashverz[erganz] = h;
599
matrix_speichern(A, &erg, &ergsize, &erganz);
600
A = NULL;
601
if(sopt == TRUE)
602
{
603
K1 = grp_mul(hist[num], Erz[erzj]);
604
matrix_speichern(K1, &hist, &histsize, &histanz);
605
K1 = NULL;
606
K1 = grp_mul(Erz_inv[erzj], histinv[num]);
607
matrix_speichern(K1, &histinv, &histinvsize, &histinvanz);
608
K1 = NULL;
609
}
610
}
611
if(schonda != -1)
612
free_mat(A);
613
if(orbit_opt[2] > 0 && erganz == orbit_opt[2])
614
abbruch = TRUE;
615
if(orbit_opt[4] <0 && -orbit_opt[4] == S->gen_no)
616
abbruch = TRUE;
617
if(orbit_opt[4] > 0 && orbit_opt[4] == S->gen_no)
618
sopt = FALSE;
619
}
620
num++;
621
if(num == erganz)
622
abbruch = TRUE;
623
}
624
*length = erganz;
625
if(orbit_opt[3] == TRUE)
626
{
627
for(i=1; i<histanz; i++)
628
{
629
free_mat(hist[i]);
630
free_mat(histinv[i]);
631
}
632
free(hist); free(histinv);
633
free_mat(I);
634
}
635
636
/* changed tilman 11/3/97 from
637
if(orbit_opt[3] == TRUE || orbit_opt[0] == 3)
638
to : */
639
if(orbit_opt[3] == TRUE || orbit_opt[0] == 4)
640
{
641
for(i=0;i<erz_anz;i++)
642
free_mat(Erz_inv[i]);
643
free(Erz_inv);
644
}
645
if(orbit_opt[5] == 1)
646
{
647
for(i=0;i<G->gen_no;i++)
648
free_mat(Erz[G->gen_no + i]);
649
}
650
free(Erz);
651
free_mat(hash_mat);
652
653
/* inserted 16/1/07 tilman */
654
free(hashverz);
655
free_baum(ergverz);
656
free_baum(Sverz);
657
658
/* inserted 16/07/97 tilman */
659
for (i=0;i<length[0];i++)
660
Check_mat(erg[i]);
661
662
return(erg);
663
}
664
665
666