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
/***************************************************************************
2
@
3
@ --------------------------------------------------------------------------
4
@
5
@ FILE: base2.c
6
@
7
@ some algorithms connected with the schreier-sims algorithm are collected.
8
@ in contrast to the functions in base.c these functions operate mod 2,
9
@ so these functions are able to calculate the kernel of the minkowski
10
@ homomorphism as well.
11
@
12
@ --------------------------------------------------------------------------
13
@
14
****************************************************************************/
15
16
#include <typedef.h>
17
#include <longtools.h>
18
#include <orbit.h>
19
#include <getput.h>
20
#include <matrix.h>
21
#include <sort.h>
22
#include <base.h>
23
24
extern int INFO_LEVEL;
25
26
/***************************************************************************
27
@
28
@ --------------------------------------------------------------------------
29
@
30
@ int einordnen_2(bahn** erg,matrix_TYP *h, matrix_TYP *new_vec,int l,
31
@ int flag, matrix_TYP ***K,int *anz)
32
@
33
@ bahn **erg : the set of base/strong generators (mod 2) for a
34
@ (possibly infinite) group G. this variable will
35
@ be changed!
36
@ matrix_TYP *h :
37
@ matrix_TYP *new_vec : this value is not asked for in the case
38
@ described here, so any variable with the right
39
@ type will do.
40
@ int l : -1 ALLWAYS
41
@ int flag : TRUE ALLWAYS!!!!!
42
@ matrix_TYP ***K : this list of matrices might already contain
43
@ generators for the kernel of the minkowski
44
@ homomorphism. All newly found generators
45
@ will be stucked in K[0][anz[0]],K[0][anz[0]+1]..
46
@ and anz[0] will be changed accordingly.
47
@ int *anz[0] : see above
48
@
49
@ Inserts a new generator h into the list of strong generators (mod 2) for
50
@ any (possible infinite) group G.
51
@ The function calls itself recursively, and therefore the convention to
52
@ use it is somewhat cryptical. In all cases for the 'end user' l has to
53
@ be -1, and flag has to be TRUE (no garanties otherwise).
54
@ THE FUNCTION DOES NOT COPY THE VARIABLE h INTO erg[0]->generators,
55
@ (IT JUST STORES THE POINTER THERE), THEREFORE THE USER IS ASKED TO
56
@ ASSURE THAT h STAY'S IN THE SAME PLACE WHILE USING erg !!!!!!!!!!
57
@ The function does not check whether the new generator h is really needed,
58
@ so better check is out before calling this function by a call of is_element!
59
@ --------------------------------------------------------------------------
60
@
61
***************************************************************************/
62
int einordnen_2(bahn** erg,matrix_TYP *h, matrix_TYP *new_vec,int l,
63
int flag,matrix_TYP ***K,int *anz)
64
{
65
int tmp = erg[0]->representatives[0]->cols,
66
tmp2,
67
i,
68
finite_flag = TRUE;
69
70
matrix_TYP *hinv,
71
*nv,
72
*nh;
73
74
if (INFO_LEVEL & 2){
75
fprintf(stderr,"entering einordnen_2 with l = %d\n",l);
76
}
77
78
if (l>=tmp){
79
/* this is the stage to memorize the kernel of
80
the minkowski homomorphism */
81
for (l=0;l<anz[0] && mat_comp(K[0][l],h) != 0;l++);
82
83
if (anz[0] == 0 || l == anz[0]){
84
/* get more memory if needed */
85
if (anz[0]>0 && (anz[0] % MIN_SPEICHER) == 0){
86
K[0] = (matrix_TYP **) realloc(K[0],
87
(anz[0]+MIN_SPEICHER)*sizeof(matrix_TYP *));
88
}
89
K[0][anz[0]] = h;
90
anz[0]++;
91
92
/* check if the group stay's finite */
93
/* the new generator should be of order 1 or 2 */
94
nh = mat_mul(K[0][anz[0]-1],K[0][anz[0]-1]);
95
Check_mat(nh);
96
if (!nh->flags.Symmetric ||
97
!nh->flags.Diagonal ||
98
nh->array.SZ[0][0] != 1){
99
finite_flag = FALSE;
100
}
101
free_mat(nh);
102
103
/* the new generator should commute with all the other generators.
104
(it suffices to check only those which have smaller index)
105
(bare in mind that all of these have order at most 2) */
106
for (i=0;i<anz[0]-1 && finite_flag;i++){
107
nh = mat_kon(K[0][anz[0]-1],K[0][i],K[0][anz[0]-1]);
108
if (mat_comp(nh,K[0][i]) != 0){
109
finite_flag = FALSE;
110
}
111
free_mat(nh);
112
}
113
114
if (finite_flag == FALSE){
115
return -1;
116
}
117
118
}
119
else{
120
free_mat(h);
121
}
122
123
return FALSE;
124
}
125
else{
126
127
if (l!=(-1)){
128
tmp2 = hash_mat(erg[l]->hash,erg[l]->orbit,new_vec,erg[l]->length);
129
}
130
else{
131
tmp2 = (-1);
132
}
133
134
if (tmp2!= (-1)){
135
/* we got an element of the stabilizer, */
136
/* calculate it then! */
137
free_mat(new_vec);
138
139
if (mat_comp(h,erg[l]->representatives[tmp2])!=0){
140
/* hinv = mat_inv(h);
141
mat_muleq(hinv,erg[l]->representatives[tmp2]);
142
free_mat(h);
143
h = hinv; */
144
hinv = mat_mul(erg[l]->rep_invs[tmp2],h);
145
free_mat(h);
146
h = hinv;
147
if (l+1 < tmp){
148
new_vec = mat_mul(h,erg[l+1]->orbit[0]);
149
modp_mat(new_vec,2);
150
}
151
}
152
else{
153
/* only clean up memory */
154
free_mat(h);
155
return FALSE;
156
}
157
158
/* enter the next stage */
159
flag = einordnen_2(erg,h,new_vec,++l,TRUE,K,anz);
160
}
161
else{
162
if (l != (-1)){
163
if (erg[l]->speicher<=erg[l]->length){
164
extend_bahn(erg+l);
165
}
166
erg[l]->orbit[erg[l]->length]=new_vec;
167
erg[l]->representatives[erg[l]->length]=h;
168
/* inserted to reduce the number of mat_inv's */
169
erg[l]->rep_invs[erg[l]->length] = mat_inv(h);
170
erg[l]->length++;
171
172
if (INFO_LEVEL & 1){
173
fprintf(stderr,"l = %d, lenght in this stage %d\n"
174
,l,erg[l]->length);
175
}
176
}
177
178
if (flag){
179
180
if (l == (-1)) l =0;
181
182
/* firstly put this element on the generator list */
183
erg[l]->generators[erg[l]->gen_no] = h;
184
erg[l]->gen_no++;
185
186
}
187
188
}
189
}
190
191
if (flag == (-1)){
192
return (-1);
193
}
194
195
if (flag){
196
/* do a new orbit-calculation */
197
/* apply all generators to the previous orbit elements */
198
for(tmp=0;tmp<erg[l]->length;tmp++){
199
for (tmp2=l;tmp2<erg[0]->representatives[0]->cols;tmp2++){
200
for (i=erg[tmp2]->gen_no-1;i>=0;i--){
201
h = erg[tmp2]->generators[i];
202
nv = mat_mul(h,erg[l]->orbit[tmp]);
203
modp_mat(nv,2);
204
nh = mat_mul(h,erg[l]->representatives[tmp]);
205
if (einordnen_2(erg,nh,nv,l,FALSE,K,anz) == -1){
206
return -1;
207
}
208
}
209
}
210
}
211
}
212
213
return flag;
214
} /* einordnen_2(..........) */
215
216
/***********************************************************************
217
@
218
@-----------------------------------------------------------------------
219
@
220
@ int strong_generators_2(matrix_TYP **base,bravais_TYP *U,
221
@ matrix_TYP ***K,int *anz,MP_INT *mp)
222
@
223
@ This function decides whether or not the integral group generated
224
@ by the matrices in U->gen[i], 0<= i< U->gen_no, is finite.
225
@ If so, it will return TRUE and the order of the group via the multiple
226
@ precision integer mp. Otherwise the function will return FALSE immediately
227
@ if infiniteness can be proven.
228
@ In the case the given group is finite it will return a generating set
229
@ for the kernel of the Minkowski homomorphim (g -> g mod 2) via K,
230
@ and the number of matrices via anz[0].
231
@ In case the function proves the group to be infinite, it will return
232
@ at least one element in K, which proves the group to ge infinite.
233
@
234
@ matrix_TYP **base: a set of U->dim integral column vectors. there are
235
@ two conditions to these vectors, which are not checked:
236
@ 1. the vectors entries 0,1 only,
237
@ 2. the vectors form a basis of Z^U->dim/(2Z)^U->dim.
238
@ bravais_TYP *U : the group in question. It is in no way changed.
239
@ matrix_TYP ***K : the function returns elements of the minkowski kernel
240
@ via this pointer.
241
@ int *anz : anz[0] is the number of returned elements in K
242
@ MP_INT *mp : a multiple precesion integer. Call the function with
243
@ strong_generators_2(....,&x) for an MP_INT x, which
244
@ has been initialized via mpz_init(&x) before.
245
@
246
@ SIDEEFECT: none are known.
247
@-----------------------------------------------------------------------
248
@
249
************************************************************************/
250
int strong_generators_2(matrix_TYP **base,bravais_TYP *U,
251
matrix_TYP ***K,int *anz,MP_INT *mp)
252
{
253
bahn **erg;
254
255
int i,
256
j,
257
k,
258
m,
259
old_anz,
260
dim = U->dim,
261
finite_flag, /* indicates whether the kernel K stays finite */
262
opt[6]; /* options for orbit_alg */
263
264
bravais_TYP G;
265
266
matrix_TYP **gen=U->gen,
267
**con,
268
*new_vec,
269
*g,
270
*h,
271
*tmp;
272
273
274
/* geting the memory for the result */
275
erg = (bahn **) calloc(dim,sizeof(bahn *));
276
for (i=0;i<dim;i++){
277
erg[i] = (bahn *) calloc(1,sizeof(bahn));
278
init_bahn(erg[i]);
279
}
280
281
/* initialise the minkowski kernel: to avoid trouble 1 is allways
282
a generator */
283
K[0] = (matrix_TYP **) malloc(MIN_SPEICHER*sizeof(matrix_TYP *));
284
anz[0] = 0;
285
finite_flag = TRUE;
286
287
for (i=0;i<dim;i++){
288
erg[i]->representatives[0] = init_mat(U->dim,U->dim,"1");
289
erg[i]->rep_invs[0] = init_mat(U->dim,U->dim,"1");
290
erg[i]->orbit[0] = copy_mat(base[i]);
291
erg[i]->length = 1;
292
erg[i]->hash->no = 0;
293
}
294
295
/* doing the orbit-calculation */
296
for (j=0;j<erg[0]->length && finite_flag;j++){
297
for (k=0;k<U->gen_no && finite_flag;k++){
298
299
if (INFO_LEVEL & 4){
300
/* printing all results for debugging */
301
for (i=0;i<dim;i++){
302
for (m=0;m<erg[i]->length;m++){
303
printf("i=%d m=%d\n",i,m);
304
if (erg[i]->representatives[m]->rows != dim ||
305
erg[i]->orbit[m]->rows != dim){
306
printf("fehler in strong_generators_2\n");
307
exit(3);
308
}
309
put_mat(erg[i]->representatives[m],NULL,"represe",2);
310
put_mat(erg[i]->orbit[m],NULL,"orbit",2);
311
}
312
}
313
}
314
315
/* decide which group element will act */
316
g=gen[k];
317
318
if (INFO_LEVEL & 4 ){
319
put_mat(g,NULL,"angewandter erzeuger",2);
320
}
321
322
h = mat_mul(g,erg[0]->representatives[j]);
323
new_vec = mat_mul(g,erg[0]->orbit[j]);
324
modp_mat(new_vec,2);
325
326
old_anz = anz[0];
327
if (einordnen_2(erg,h,new_vec,0,FALSE,K,anz) == -1){
328
finite_flag = FALSE;
329
}
330
331
/* we got new generators for the kernel, so see
332
whether we can prove the group to be infinite
333
for (i=old_anz;i<anz[0] && finite_flag;i++){ */
334
335
/* the new generator should be of order 1 or 2
336
tmp = mat_mul(K[0][i],K[0][i]);
337
Check_mat(tmp);
338
if (!tmp->flags.Symmetric ||
339
!tmp->flags.Diagonal ||
340
tmp->array.SZ[0][0] != 1){
341
finite_flag = FALSE;
342
}
343
free_mat(tmp); */
344
345
/* the new generator should commute with all the other generators.
346
(it suffices to check only those which have smaller index)
347
(bare in mind that all of these have order at most 2)
348
for (m=0;m<i && finite_flag;m++){
349
tmp = mat_kon(K[0][i],K[0][m],K[0][i]);
350
if (mat_comp(tmp,K[0][m]) != 0){
351
finite_flag = FALSE;
352
}
353
free_mat(tmp);
354
}
355
} */
356
}
357
}
358
359
/* if the kernel K is trivial, we won't have generators at all,
360
which causes trouble afterwards */
361
if (anz[0] == 0){
362
anz[0] = 1;
363
K[0][0] = init_mat(U->dim,U->dim,"1");
364
}
365
366
/* this is the time to calculate the order of the group modulo
367
the minkowski kernel */
368
mpz_set_si(mp,1);
369
for (i=0;i<dim;i++){
370
mpz_mul_ui(mp,mp,(unsigned long) erg[i]->length);
371
}
372
373
/* bare in mind to free erg, which sounds crazy but is this
374
way because the function was used in a different way before */
375
for (i=0;i<dim;i++){
376
free_bahn(erg[i]);
377
free(erg[i]);
378
}
379
free(erg);
380
381
/* we now decided whether nor not the group is finite,
382
because if we still got the finite_flag, the kernel K
383
is finitely generated, abelian, of exponent 2.
384
bare in mind that we only got an generating system for
385
K which generates K as normal subgroup of U */
386
opt[0] = 4; opt[2] = 1; opt[1] = opt[3] = opt[4] = opt[5] = 0;
387
for (i=0;i<dim;i++) opt[2] *= 2;
388
if (finite_flag){
389
/* make the normal closure */
390
old_anz = anz[0];
391
for (i=0;i<old_anz && finite_flag;i++){
392
con = orbit_alg(K[0][i],U,NULL,opt,&k);
393
for (j=0;j<k;j++){
394
for (m=0;m<anz[0] && mat_comp(K[0][m],con[j]) != 0;m++);
395
if (m==anz[0]){
396
if ((anz[0] % MIN_SPEICHER == 0) && anz[0] != 0)
397
K[0] = (matrix_TYP **) realloc(K[0],
398
(anz[0]+MIN_SPEICHER) * sizeof(matrix_TYP *));
399
K[0][anz[0]] = con[j];
400
Check_mat(K[0][anz[0]]);
401
/* look whether it stays finite */
402
if (finite_flag){
403
/* the new generator is of order 1 or 2 because it's
404
a conjugate of such an element, and the new generator
405
should commute with all the other generators. */
406
for (m=0;m<anz[0] && finite_flag;m++){
407
tmp = mat_kon(K[0][anz[0]],K[0][m],K[0][anz[0]]);
408
if (mat_comp(tmp,K[0][m]) != 0){
409
finite_flag = FALSE;
410
}
411
free_mat(tmp);
412
}
413
}
414
anz[0]++;
415
}
416
else{
417
free_mat(con[j]);
418
}
419
420
}
421
free(con);
422
}
423
}
424
425
/* the finite_flag might be changed since we last checked it */
426
if (finite_flag){
427
erg = NULL;
428
G.gen = K[0];
429
G.gen_no = anz[0];
430
G.dim = dim;
431
i = red_gen(&G,base,&erg,0);
432
anz[0] = G.gen_no;
433
K[0] = G.gen;
434
mpz_mul_ui(mp,mp,(unsigned long) i);
435
for (i=0;i<dim;i++){
436
free_bahn(erg[i]);
437
free(erg[i]);
438
}
439
free(erg);
440
}
441
442
return finite_flag;
443
} /* strong_generators_2 */
444
445