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

563603 views
1
#include"typedef.h"
2
/***** This file contains some routines to compute automorphisms of a lattice
3
and to determine candidates for the image of a base vector *****/
4
5
6
/***************************************************************\
7
| tests, whether x[0],...,x[I-1] is a partial
8
| automorphism, using scalar product combinations
9
| and Bacher-polynomials depending on the chosen
10
| options, puts the candidates for x[I] (i.e. the
11
| vectors vec such that the scalar products of
12
| x[0],...,x[I-1],vec are correct) on CI,
13
| returns their number (should be fp[I])
14
\***************************************************************/
15
static int cand(CI, I, x, V, F, fp, comb, bach, flags)
16
veclist V;
17
invar F;
18
fpstruct fp;
19
scpcomb *comb;
20
bachpol *bach;
21
flagstruct flags;
22
int *CI, I, *x;
23
{
24
int i, j, k, dim, okp, okm, sign, nr, fail, num;
25
int *vec, *scpvec, **xvec, **xbase, **Fxbase, DEP, len, rank, n;
26
int *Vvj, *FAiI, **Fvi, *xnum, xk, *comtri, *comcoi, xbij, vj;
27
scpcomb com;
28
int test;
29
30
dim = F.dim;
31
DEP = flags.DEPTH;
32
len = F.n * DEP;
33
34
if(normal_option == TRUE && I >0)
35
{
36
test = normal_aut_test(x, I-1, V);
37
if(test == FALSE)
38
return(0);
39
}
40
if (I-1 >= 0 && I-1 < flags.BACHDEP)
41
{
42
if (flags.BACH[2] == 0)
43
flags.BACHSCP = V.v[abs(x[I-1])][dim] / 2;
44
if (bachcomp(bach[I-1], x[I-1], flags.BACHSCP, V, F.v[0]) == 0)
45
return(0);
46
}
47
if ((vec = (int*)malloc(dim * sizeof(int))) == 0)
48
exit (2);
49
if ((scpvec = (int*)malloc(len * sizeof(int))) == 0)
50
exit (2);
51
if (I-1 >= 0 && DEP > 0)
52
{
53
com = comb[I-1];
54
rank = com.rank;
55
n = com.list.n;
56
/* xvec is the list of vector sums which are computed with respect to the
57
partial basis in x */
58
if ((xvec = (int**)malloc((n+1) * sizeof(int*))) == 0)
59
exit (2);
60
for (i = 0; i <= n; ++i)
61
{
62
if ((xvec[i] = (int*)malloc(dim * sizeof(int))) == 0)
63
exit (2);
64
for (j = 0; j < dim; ++j)
65
xvec[i][j] = 0;
66
}
67
/* xbase should be a basis for the lattice generated by the vectors in xvec,
68
it is obtained via the transformation matrix comb[I-1].trans */
69
if ((xbase = (int**)malloc(rank * sizeof(int*))) == 0)
70
exit (2);
71
for (i = 0; i < rank; ++i)
72
{
73
if ((xbase[i] = (int*)malloc(dim * sizeof(int))) == 0)
74
exit (2);
75
}
76
/* Fxbase is the product of a form F with the base xbase */
77
if ((Fxbase = (int**)malloc(rank * sizeof(int*))) == 0)
78
exit (2);
79
for (i = 0; i < rank; ++i)
80
{
81
if ((Fxbase[i] = (int*)malloc(dim * sizeof(int))) == 0)
82
exit (2);
83
}
84
}
85
/* CI is the list for the candidates */
86
for (i = 0; i < fp.diag[I]; ++i)
87
CI[i] = 0;
88
nr = 0;
89
fail = 0;
90
for (j = 1; j <= V.n && fail == 0; ++j)
91
{
92
Vvj = V.v[j];
93
okp = 0;
94
okm = 0;
95
for (k = 0; k < len; ++k)
96
scpvec[k] = 0;
97
for (i = 0; i < F.n; ++i)
98
{
99
FAiI = F.A[i][fp.per[I]];
100
Fvi = F.v[i];
101
/* vec is the vector of scalar products of V.v[j] with the first I base vectors
102
x[0]...x[I-1] */
103
for (k = 0; k < I; ++k)
104
{
105
if ((xk = x[k]) > 0)
106
vec[k] = sscp(Vvj, Fvi[xk], dim);
107
else
108
vec[k] = -sscp(Vvj, Fvi[-xk], dim);
109
}
110
for (k = 0; k < I && vec[k] == FAiI[fp.per[k]]; ++k);
111
if (k == I && Vvj[dim+i] == FAiI[fp.per[I]])
112
/* V.v[j] is a candidate for x[I] with respect to the form F.A[i] */
113
++okp;
114
for (k = 0; k < I && vec[k] == -FAiI[fp.per[k]]; ++k);
115
if (k == I && Vvj[dim+i] == FAiI[fp.per[I]])
116
/* -V.v[j] is a candidate for x[I] with respect to the form F.A[i] */
117
++okm;
118
if (I-1 >= 0 && DEP > 0)
119
{
120
for (k = I-1; k >= 0 && k > I-1-DEP; --k)
121
scpvec[i*DEP+I-1-k] = vec[k];
122
}
123
}
124
if (I-1 >= 0 && DEP > 0)
125
/* check, whether the scalar product combination scpvec is contained in the
126
list comb[I-1].list */
127
{
128
for (i = 0; i < len && scpvec[i] == 0; ++i);
129
if (i == len)
130
num = 0;
131
else
132
{
133
num = numberof(scpvec, com.list);
134
sign = num > 0 ? 1 : -1;
135
num *= sign;
136
}
137
if (num > n)
138
/* scpvec is not found, hence x[0]...x[I-1] is not a partial automorphism */
139
fail = 1;
140
else if (num > 0)
141
/* scpvec is found and the vector is added to the corresponding vector sum */
142
{
143
xnum = xvec[num];
144
for (k = 0; k < dim; ++k)
145
xnum[k] += sign * Vvj[k];
146
}
147
}
148
if (okp == F.n)
149
/* V.v[j] is a candidate for x[I] */
150
{
151
if (nr < fp.diag[I])
152
{
153
CI[nr] = j;
154
++nr;
155
}
156
else
157
/* there are too many candidates */
158
fail = 1;
159
}
160
if (okm == F.n)
161
/* -V.v[j] is a candidate for x[I] */
162
{
163
if (nr < fp.diag[I])
164
{
165
CI[nr] = -j;
166
++nr;
167
}
168
else
169
/* there are too many candidates */
170
fail = 1;
171
}
172
}
173
if (fail == 1)
174
nr = 0;
175
if (nr == fp.diag[I] && I-1 >= 0 && DEP > 0)
176
/* compute the basis of the lattice generated by the vectors in xvec via the
177
transformation matrix comb[I-1].trans */
178
{
179
for (i = 0; i < rank; ++i)
180
{
181
comtri = com.trans[i];
182
for (j = 0; j < dim; ++j)
183
{
184
xbij = 0;
185
for (k = 0; k <= n; ++k)
186
xbij += comtri[k] * xvec[k][j];
187
xbase[i][j] = xbij;
188
}
189
}
190
}
191
if (nr == fp.diag[I] && I-1 >= 0 && DEP > 0)
192
/* check, whether the base xbase has the right scalar products */
193
{
194
for (i = 0; i < F.n && nr > 0; ++i)
195
{
196
for (j = 0; j < rank; ++j)
197
{
198
for (k = 0; k < dim; ++k)
199
Fxbase[j][k] = sscp(F.A[i][k], xbase[j], dim);
200
}
201
for (j = 0; j < rank && nr > 0; ++j)
202
{
203
for (k = 0; k <= j && nr > 0; ++k)
204
{
205
if (sscp(xbase[j], Fxbase[k], dim) != com.F[i][j][k])
206
/* a scalar product is wrong */
207
nr = 0;
208
}
209
}
210
}
211
}
212
if (nr == fp.diag[I] && I-1 >= 0 && DEP > 0)
213
/* check, whether comb[I-1].coef * xbase = xvec */
214
{
215
for (i = 0; i <= n && nr > 0; ++i)
216
{
217
comcoi = com.coef[i];
218
for (j = 0; j < dim; ++j)
219
{
220
vj = 0;
221
for (k = 0; k < rank; ++k)
222
vj += comcoi[k] * xbase[k][j];
223
if (vj != xvec[i][j])
224
/* an entry is wrong */
225
nr = 0;
226
}
227
}
228
}
229
if (I-1 >= 0 && DEP > 0)
230
{
231
for (i = 0; i <= n; ++i)
232
free(xvec[i]);
233
free(xvec);
234
for (i = 0; i < rank; ++i)
235
{
236
free(xbase[i]);
237
free(Fxbase[i]);
238
}
239
free(xbase);
240
free(Fxbase);
241
}
242
free(scpvec);
243
free(vec);
244
return(nr);
245
}
246
247
/**************************************************\
248
| search new automorphisms until on all
249
| levels representatives for all orbits
250
| have been tested
251
\**************************************************/
252
static void autom(G, V, F, fp, comb, bach, flags)
253
group *G;
254
veclist V;
255
invar F;
256
fpstruct fp;
257
scpcomb *comb;
258
bachpol *bach;
259
flagstruct flags;
260
{
261
FILE *outfile;
262
int i, j, dim, step, im, **C, nC, ***H, nH, **Ggng, found, try;
263
int *x, *orb, *oc, noc, *bad, nbad;
264
265
dim = F.dim;
266
if ((C = (int**)malloc(dim * sizeof(int*))) == 0)
267
exit (2);
268
/* C[i] is the list of candidates for the image of the i-th base-vector */
269
for (i = 0; i < dim; ++i)
270
{
271
if ((C[i] = (int*)malloc(fp.diag[i] * sizeof(int))) == 0)
272
exit (2);
273
}
274
/* x is the new base, i.e. x[i] is the index in V.v of the i-th base-vector */
275
if ((x = (int*)malloc(dim * sizeof(int))) == 0)
276
exit (2);
277
if ((bad = (int*)malloc(2*V.n * sizeof(int))) == 0)
278
exit (2);
279
for (step = flags.STAB; step < dim; ++step)
280
{
281
nH = 0;
282
for (i = step; i < dim; ++i)
283
nH += G->ng[i];
284
if ((H = (int***)malloc(nH * sizeof(int**))) == 0)
285
exit (2);
286
nH = 0;
287
for (i = step; i < dim; ++i)
288
{
289
for (j = 0; j < G->ng[i]; ++j)
290
{
291
H[nH] = G->g[i][j];
292
++nH;
293
}
294
}
295
for (i = 0; i < 2*V.n; ++i)
296
bad[i] = 0;
297
nbad = 0;
298
/* the first step base-vectors are fixed */
299
for (i = 0; i < step; ++i)
300
x[i] = fp.e[i];
301
/* compute the candidates for x[step] */
302
if (fp.diag[step] > 1)
303
/* if fp.diag[step] compute the candidates for x[step] */
304
nC = cand(C[step], step, x, V, F, fp, comb, bach, flags);
305
else
306
/* if fp.diag[step] == 1, fp.e[step] is the only candidate */
307
{
308
C[step][0] = fp.e[step];
309
nC = 1;
310
}
311
G->ord[step] = orbit(&(fp.e[step]), 1, H, nH, V, &orb);
312
/* delete the orbit of the step-th base-vector from the candidates */
313
nC = delete(C[step], nC, orb, G->ord[step]);
314
free(orb);
315
while (nC > 0 && (im = C[step][0]) != 0)
316
{
317
found = 0;
318
/* try vector V.v[im] as image of the step-th base-vector */
319
x[step] = im;
320
if (step < dim-1)
321
{
322
/* check, whether x[0]...x[step] is a partial basis and compute the candidates
323
for x[step+1] */
324
if (cand(C[step+1], step+1, x, V, F, fp, comb, bach, flags) == fp.diag[step+1])
325
/* go into the recursion */
326
found = aut(step+1, x, C, G, V, F, fp, comb, bach, flags);
327
else
328
found = 0;
329
}
330
else
331
{
332
found = 1;
333
if(normal_option == TRUE)
334
{
335
found = 0;
336
for(i=0;i<fp.diag[step] && C[step][0] != 0 && found == 0; i++)
337
{
338
x[step] = C[step][0];
339
found = normal_aut_test(x, step, V);
340
if(found == 0)
341
{
342
for(j=0;j<fp.diag[step]-1;j++)
343
C[step][j] = C[step][j+1];
344
C[step][fp.diag[step]-1] = 0;
345
}
346
}
347
}
348
}
349
if (found == 0)
350
/* x[0]...x[step] can not be continued to an automorphism */
351
{
352
noc = orbit(&im, 1, H, nH, V, &oc);
353
/* delete the orbit of im from the candidates for x[step] */
354
nC = delete(C[step], nC, oc, noc);
355
free(oc);
356
bad[nbad] = im;
357
++nbad;
358
}
359
else
360
/* a new generator has been found */
361
{
362
++G->ng[step];
363
if ((G->g[step] = (int***)realloc(G->g[step], G->ng[step] * sizeof(int**))) == 0)
364
exit (2);
365
if ((G->g[step][G->ng[step]-1] = (int**)malloc(dim * sizeof(int*))) == 0)
366
exit (2);
367
for (i = 0; i < dim; ++i)
368
{
369
if ((G->g[step][G->ng[step]-1][i] = (int*)malloc(dim * sizeof(int))) == 0)
370
exit (2);
371
}
372
Ggng = G->g[step][G->ng[step]-1];
373
/* append the new generator to G->g[step] */
374
matgen(x, Ggng, dim, fp.per, V.v);
375
++nH;
376
if ((H = (int***)realloc(H, nH * sizeof(int**))) == 0)
377
exit (2);
378
nH = 0;
379
for (i = step; i < dim; ++i)
380
{
381
for (j = 0; j < G->ng[i]; ++j)
382
{
383
H[nH] = G->g[i][j];
384
++nH;
385
}
386
}
387
if (flags.PRINT == 1)
388
/* if the -P option is given, print the new generator on AUTO.tmp */
389
{
390
outfile = fopen("AUTO.tmp", "a");
391
fprintf(outfile, "%d\n", dim);
392
for (i = 0; i < dim; ++i)
393
{
394
for (j = 0; j < dim; ++j)
395
fprintf(outfile, " %2d", Ggng[i][j]);
396
fprintf(outfile, "\n");
397
}
398
fclose(outfile);
399
}
400
/* compute the new orbit of fp.e[step] */
401
G->ord[step] = orbit(&(fp.e[step]), 1, H, nH, V, &orb);
402
/* delete the orbit from the candidates for x[step] */
403
nC = delete(C[step], nC, orb, G->ord[step]);
404
free(orb);
405
/* compute the new orbit of the vectors, which could not be continued to an
406
automorphism */
407
noc = orbit(bad, nbad, H, nH, V, &oc);
408
/* delete the orbit from the candidates */
409
nC = delete(C[step], nC, oc, noc);
410
free(oc);
411
}
412
}
413
/* test, whether on step flags.STAB some generators may be omitted */
414
if (step == flags.STAB)
415
{
416
for (try = G->nsg[step]; try < G->ng[step]; ++try)
417
{
418
nH = 0;
419
for (j = 0; j < try; ++j)
420
{
421
H[nH] = G->g[step][j];
422
++nH;
423
}
424
for (j = try+1; j < G->ng[step]; ++j)
425
{
426
H[nH] = G->g[step][j];
427
++nH;
428
}
429
for (i = step+1; i < dim; ++i)
430
{
431
for (j = 0; j < G->ng[i]; ++j)
432
{
433
H[nH] = G->g[i][j];
434
++nH;
435
}
436
}
437
if (orbitlen(fp.e[step], G->ord[step], H, nH, V) == G->ord[step])
438
/* the generator g[step][try] can be omitted */
439
{
440
for (i = 0; i < dim; ++i)
441
free(G->g[step][try][i]);
442
free(G->g[step][try]);
443
for (i = try; i < G->ng[step]-1; ++i)
444
G->g[step][i] = G->g[step][i+1];
445
--G->ng[step];
446
--try;
447
}
448
}
449
}
450
free(H);
451
if (step < dim-1 && G->ord[step] > 1)
452
/* calculate stabilizer elements fixing the basis-vectors
453
fp.e[0]...fp.e[step] */
454
stab(step, G, fp, V);
455
if (flags.PRINT == 1)
456
/* if the -P option is given, print G.ord[step] AUTO.tmp */
457
{
458
outfile = fopen("AUTO.tmp", "a");
459
fprintf(outfile, "G.ord[%d] = %d\n", step, G->ord[step]);
460
fclose(outfile);
461
}
462
}
463
for (i = 0; i < dim; ++i)
464
free(C[i]);
465
free(C);
466
free(x);
467
free(bad);
468
}
469
470
/***************************************************************\
471
| the heart of the program: the recursion
472
\***************************************************************/
473
static int aut(step, x, C, G, V, F, fp, comb, bach, flags)
474
group *G;
475
veclist V;
476
invar F;
477
fpstruct fp;
478
scpcomb *comb;
479
bachpol *bach;
480
flagstruct flags;
481
int step, *x, **C;
482
{
483
int i, j, dim, orb[1], found;
484
485
dim = F.dim;
486
found = 0;
487
while (C[step][0] != 0 && found == 0)
488
{
489
if (step < dim-1)
490
{
491
/* choose the image of the base-vector nr. step */
492
x[step] = C[step][0];
493
/* check, whether x[0]...x[step] is a partial automorphism and compute the
494
candidates for x[step+1] */
495
if (cand(C[step+1], step+1, x, V, F, fp, comb, bach, flags) == fp.diag[step+1])
496
/* go deeper into the recursion */
497
found = aut(step+1, x, C, G, V, F, fp, comb, bach, flags);
498
if (found == 1)
499
return(found);
500
/* delete the chosen vector from the list of candidates */
501
orb[0] = x[step];
502
delete(C[step], fp.diag[step], orb, 1);
503
}
504
else
505
{
506
if(normal_option == TRUE)
507
{
508
found = 0;
509
for(i=0;i<fp.diag[step] && C[step][0] != 0 && found == 0;i++)
510
{
511
x[step] = C[step][0];
512
found = normal_aut_test(x, step, V);
513
if(found == 0)
514
{
515
for(j=0;j<fp.diag[step]-1;j++)
516
C[step][j] = C[step][j+1];
517
C[step][fp.diag[step]-1] = 0;
518
}
519
}
520
}
521
else
522
{
523
/* a new automorphism is found */
524
x[dim-1] = C[dim-1][0];
525
found = 1;
526
}
527
}
528
}
529
return(found);
530
}
531
532