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
/***** This file includes those routines for the isometry program which
3
differ from the routines for the automorphism program *****/
4
5
6
/*****************************************************************\
7
| tests, whether x[0],...,x[I-1] is a partial
8
| isometry, 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
14
| (should be fp.diag[I])
15
\*****************************************************************/
16
static int isocand(CI, I, x, V, F, FF, fp, comb, bach, flags)
17
veclist V;
18
invar F, FF;
19
fpstruct fp;
20
scpcomb *comb;
21
bachpol *bach;
22
flagstruct flags;
23
int *CI, I, *x;
24
{
25
int i, j, k, dim, okp, okm, sign, nr, fail, num;
26
int *vec, *scpvec, **xvec, **xbase, **Fxbase, DEP, len, rank, n;
27
int *Vvj, *FAiI, **Fvi, *xnum, xk, *comtri, *comcoi, xbij, vj;
28
scpcomb com;
29
int test;
30
31
dim = F.dim;
32
DEP = flags.DEPTH;
33
len = F.n * DEP;
34
35
if(normal_option == TRUE && I >0)
36
{
37
test = normal_aut_test(x, I-1, V);
38
if(test == FALSE)
39
return(0);
40
}
41
if (I-1 >= 0 && I-1 < flags.BACHDEP)
42
{
43
if (flags.BACH[2] == 0)
44
flags.BACHSCP = V.v[abs(x[I-1])][dim] / 2;
45
if (bachcomp(bach[I-1], x[I-1], flags.BACHSCP, V, FF.v[0]) == 0)
46
return(0);
47
}
48
if ((vec = (int*)malloc(dim * sizeof(int))) == 0)
49
exit (2);
50
if ((scpvec = (int*)malloc(len * sizeof(int))) == 0)
51
exit (2);
52
if (I-1 >= 0 && DEP > 0)
53
{
54
com = comb[I-1];
55
rank = com.rank;
56
n = com.list.n;
57
/* xvec is the list of vector sums which are computed with respect to the
58
partial basis in x */
59
if ((xvec = (int**)malloc((n+1) * sizeof(int*))) == 0)
60
exit (2);
61
for (i = 0; i <= n; ++i)
62
{
63
if ((xvec[i] = (int*)malloc(dim * sizeof(int))) == 0)
64
exit (2);
65
for (j = 0; j < dim; ++j)
66
xvec[i][j] = 0;
67
}
68
/* xbase should be a basis for the lattice generated by the vectors in xvec,
69
it is obtained via the transformation matrix comb[I-1].trans */
70
if ((xbase = (int**)malloc(rank * sizeof(int*))) == 0)
71
exit (2);
72
for (i = 0; i < rank; ++i)
73
{
74
if ((xbase[i] = (int*)malloc(dim * sizeof(int))) == 0)
75
exit (2);
76
}
77
/* Fxbase is the product of a form F with the base xbase */
78
if ((Fxbase = (int**)malloc(rank * sizeof(int*))) == 0)
79
exit (2);
80
for (i = 0; i < rank; ++i)
81
{
82
if ((Fxbase[i] = (int*)malloc(dim * sizeof(int))) == 0)
83
exit (2);
84
}
85
}
86
/* CI is the list for the candidates */
87
for (i = 0; i < fp.diag[I]; ++i)
88
CI[i] = 0;
89
nr = 0;
90
fail = 0;
91
for (j = 1; j <= V.n && fail == 0; ++j)
92
{
93
Vvj = V.v[j];
94
okp = 0;
95
okm = 0;
96
for (k = 0; k < len; ++k)
97
scpvec[k] = 0;
98
for (i = 0; i < F.n; ++i)
99
{
100
FAiI = F.A[i][fp.per[I]];
101
Fvi = FF.v[i];
102
/* vec is the vector of scalar products of V.v[j] with the first I base vectors
103
x[0]...x[I-1] with respect to the forms in FF */
104
for (k = 0; k < I; ++k)
105
{
106
if ((xk = x[k]) > 0)
107
vec[k] = sscp(Vvj, Fvi[xk], dim);
108
else
109
vec[k] = -sscp(Vvj, Fvi[-xk], dim);
110
}
111
for (k = 0; k < I && vec[k] == FAiI[fp.per[k]]; ++k);
112
if (k == I && Vvj[dim+i] == FAiI[fp.per[I]])
113
/* V.v[j] is a candidate for x[I] with respect to the form F.A[i] */
114
++okp;
115
for (k = 0; k < I && vec[k] == -FAiI[fp.per[k]]; ++k);
116
if (k == I && Vvj[dim+i] == FAiI[fp.per[I]])
117
/* -V.v[j] is a candidate for x[I] with respect to the form F.A[i] */
118
++okm;
119
if (I-1 >= 0 && DEP > 0)
120
{
121
for (k = I-1; k >= 0 && k > I-1-DEP; --k)
122
scpvec[i*DEP+I-1-k] = vec[k];
123
}
124
}
125
if (I-1 >= 0 && DEP > 0)
126
/* check, whether the scalar product combination scpvec is contained in the
127
list comb[I-1].list */
128
{
129
for (i = 0; i < len && scpvec[i] == 0; ++i);
130
if (i == len)
131
num = 0;
132
else
133
{
134
num = numberof(scpvec, com.list);
135
sign = num > 0 ? 1 : -1;
136
num *= sign;
137
}
138
if (num > n)
139
/* scpvec is not found, hence x[0]...x[I-1] is not a partial isometry */
140
fail = 1;
141
else if (num > 0)
142
/* scpvec is found and the vector is added to the corresponding vector sum */
143
{
144
xnum = xvec[num];
145
for (k = 0; k < dim; ++k)
146
xnum[k] += sign * Vvj[k];
147
}
148
}
149
if (okp == F.n)
150
/* V.v[j] is a candidate for x[I] */
151
{
152
if (nr < fp.diag[I])
153
{
154
CI[nr] = j;
155
++nr;
156
}
157
else
158
/* there are too many candidates */
159
fail = 1;
160
}
161
if (okm == F.n)
162
/* -V.v[j] is a candidate for x[I] */
163
{
164
if (nr < fp.diag[I])
165
{
166
CI[nr] = -j;
167
++nr;
168
}
169
else
170
/* there are too many candidates */
171
fail = 1;
172
}
173
}
174
if (fail == 1)
175
nr = 0;
176
if (nr == fp.diag[I] && I-1 >= 0 && DEP > 0)
177
/* compute the basis of the lattice generated by the vectors in xvec via the
178
transformation matrix comb[I-1].trans */
179
{
180
for (i = 0; i < rank; ++i)
181
{
182
comtri = com.trans[i];
183
for (j = 0; j < dim; ++j)
184
{
185
xbij = 0;
186
for (k = 0; k <= n; ++k)
187
xbij += comtri[k] * xvec[k][j];
188
xbase[i][j] = xbij;
189
}
190
}
191
}
192
if (nr == fp.diag[I] && I-1 >= 0 && DEP > 0)
193
/* check, whether the base xbase has the right scalar products */
194
{
195
for (i = 0; i < F.n && nr > 0; ++i)
196
{
197
for (j = 0; j < rank; ++j)
198
{
199
for (k = 0; k < dim; ++k)
200
Fxbase[j][k] = sscp(FF.A[i][k], xbase[j], dim);
201
}
202
for (j = 0; j < rank && nr > 0; ++j)
203
{
204
for (k = 0; k <= j && nr > 0; ++k)
205
{
206
if (sscp(xbase[j], Fxbase[k], dim) != com.F[i][j][k])
207
/* a scalar product is wrong */
208
nr = 0;
209
}
210
}
211
}
212
}
213
if (nr == fp.diag[I] && I-1 >= 0 && DEP > 0)
214
/* check, whether comb[I-1].coef * xbase = xvec */
215
{
216
for (i = 0; i <= n && nr > 0; ++i)
217
{
218
comcoi = com.coef[i];
219
for (j = 0; j < dim; ++j)
220
{
221
vj = 0;
222
for (k = 0; k < rank; ++k)
223
vj += comcoi[k] * xbase[k][j];
224
if (vj != xvec[i][j])
225
/* an entry is wrong */
226
nr = 0;
227
}
228
}
229
}
230
if (I-1 >= 0 && DEP > 0)
231
{
232
for (i = 0; i <= n; ++i)
233
free(xvec[i]);
234
free(xvec);
235
for (i = 0; i < rank; ++i)
236
{
237
free(xbase[i]);
238
free(Fxbase[i]);
239
}
240
free(xbase);
241
free(Fxbase);
242
}
243
free(scpvec);
244
free(vec);
245
return(nr);
246
}
247
248
/*****************************************************\
249
| search for an isometry
250
\*****************************************************/
251
static matrix_TYP *bs_isometry(V, F, FF, fp, G, nG, comb, bach, flags)
252
veclist V;
253
invar F, FF;
254
fpstruct fp;
255
int ***G, nG;
256
scpcomb *comb;
257
bachpol *bach;
258
flagstruct flags;
259
{
260
int i,j, dim, *x, **C, **X, found;
261
matrix_TYP *erg;
262
263
dim = F.dim;
264
if ((C = (int**)malloc(dim * sizeof(int*))) == 0)
265
exit (2);
266
/* C[i] is the list of candidates for the image of the i-th base-vector */
267
for (i = 0; i < dim; ++i)
268
{
269
if ((C[i] = (int*)malloc(fp.diag[i] * sizeof(int))) == 0)
270
exit (2);
271
}
272
/* x is the new base, i.e. x[i] is the index in V.v of the i-th base-vector */
273
if ((x = (int*)malloc(dim * sizeof(int))) == 0)
274
exit (2);
275
/* compute the candidates for x[0] */
276
isocand(C[0], 0, x, V, F, FF, fp, comb, bach, flags);
277
found = 0;
278
/* go into the recursion */
279
found = iso(0, x, C, V, F, FF, fp, G, nG, comb, bach, flags);
280
/***********************************
281
for(i=0;i<nG;i++)
282
{
283
for(j=0;j<dim;j++)
284
free(G[i][j]);
285
free(G[i]);
286
}
287
*****************************/
288
if (found == 1)
289
{
290
if ((X = (int**)malloc(dim * sizeof(int*))) == 0)
291
exit (2);
292
for (i = 0; i < dim; ++i)
293
{
294
if ((X[i] = (int*)malloc(dim * sizeof(int))) == 0)
295
exit (2);
296
}
297
matgen(x, X, dim, fp.per, V.v);
298
/* print the isometry */
299
erg = putiso(X, flags, dim);
300
for (i = 0; i < dim; ++i)
301
free(X[i]);
302
free(X);
303
}
304
else
305
erg = NULL;
306
for (i = 0; i < dim; ++i)
307
free(C[i]);
308
free(C);
309
free(x);
310
return(erg);
311
}
312
313
/**********************************************************\
314
| the heart of the program: the recursion
315
\**********************************************************/
316
static int iso(step, x, C, V, F, FF, fp, G, nG, comb, bach, flags)
317
veclist V;
318
invar F, FF;
319
fpstruct fp;
320
scpcomb *comb;
321
bachpol *bach;
322
flagstruct flags;
323
int step, *x, **C, ***G, nG;
324
{
325
FILE *outfile;
326
int i, j, dim, ***H, nH, *orb, orblen, found, Maxfail;
327
328
dim = F.dim;
329
found = 0;
330
while (C[step][0] != 0 && found == 0)
331
{
332
if (step < dim-1)
333
{
334
/* choose the image of the base-vector nr. step */
335
x[step] = C[step][0];
336
/* check, whether x[0]...x[step] is a partial automorphism and compute the
337
candidates for x[step+1] */
338
if (isocand(C[step+1], step+1, x, V, F, FF, fp, comb, bach, flags) == fp.diag[step+1])
339
{
340
/* go deeper into the recursion */
341
Maxfail = 0;
342
/* determine the heuristic value of Maxfail for the break condition in
343
isostab */
344
for (i = 0; i <= step; ++i)
345
{
346
if (fp.diag[i] > 1)
347
Maxfail += 1;
348
}
349
for (i = step+1; i < dim; ++i)
350
{
351
if (fp.diag[i] > 1)
352
Maxfail += 2;
353
}
354
/* compute the stabilizer H of x[step] in G */
355
nH = isostab(&H, x[step], G, nG, V, Maxfail);
356
found = iso(step+1, x, C, V, F, FF, fp, H, nH, comb, bach, flags);
357
/* inserted 16/1/97 tilman */
358
free(H);
359
360
}
361
if (found == 1)
362
{
363
for (i = 0; i < nG; ++i)
364
{
365
for (j = 0; j < dim; ++j)
366
free(G[i][j]);
367
free(G[i]);
368
}
369
return(found);
370
}
371
orblen = orbit(&(x[step]), 1, G, nG, V, &orb);
372
/* delete the orbit of the chosen vector from the list of candidates */
373
delete(C[step], fp.diag[step], orb, orblen);
374
free(orb);
375
if (step == 0 && flags.PRINT == 1)
376
/* if the -P option is given, print on top level the number of excluded
377
candidates on ISOM.tmp */
378
{
379
outfile = fopen("ISOM.tmp", "a");
380
fprintf(outfile, "excluded %d vectors on top level\n", orblen);
381
fclose(outfile);
382
}
383
}
384
else
385
{
386
/* an isomorphism is found */
387
if(normal_option == TRUE)
388
{
389
found = 0;
390
for(i=0;i<fp.diag[step] && C[step][0] != 0 && found == 0;i++)
391
{
392
x[step] = C[step][0];
393
found = normal_aut_test(x, step, V);
394
if(found == 0)
395
{
396
for(j=0;j<fp.diag[step]-1;j++)
397
C[step][j] = C[step][j+1];
398
C[step][fp.diag[step]-1] = 0;
399
}
400
}
401
}
402
else
403
{
404
x[dim-1] = C[dim-1][0];
405
found = 1;
406
}
407
}
408
}
409
for (i = 0; i < nG; ++i)
410
{
411
for (j = 0; j < dim; ++j)
412
free(G[i][j]);
413
free(G[i]);
414
}
415
416
return(found);
417
}
418
419
/*********************************************************************\
420
| computes the orbit of V.v[pt] under the generators
421
| G[0],...,G[nG-1] and elements stabilizing V.v[pt], which are
422
| stored in H, returns the number of generators in H
423
\*********************************************************************/
424
static int isostab(H, pt, G, nG, V, Maxfail)
425
int ****H, pt, ***G, nG, Maxfail;
426
veclist V;
427
{
428
int *orb, len, cnd, orblen, tmplen, rpt;
429
int ***w, *flag, **A, **B;
430
int i, j, k, dim, im, nH, fail;
431
432
/* a heuristic break condition for the computation of stabilizer elements:
433
it would be too expensive to calculate all the stabilizer generators, which
434
are obtained from the orbit, since this is highly redundant,
435
on the other hand every new generator which enlarges the group reduces the
436
number of orbits and hence the number of candidates to be tested,
437
after Maxfail subsequent stabilizer elements, that do not enlarge the group,
438
the procedure stops,
439
increasing Maxfail will possibly decrease the number of tests,
440
but will increase the running time of the stabilizer computation
441
there is no magic behind the heuristic, tuning might be appropriate */
442
dim = V.dim;
443
/* H are the generators of the stabilizer of V.v[pt] */
444
if ((*H = (int***)malloc(1 * sizeof(int**))) == 0)
445
exit (2);
446
if (((*H)[0] = (int**)malloc(dim * sizeof(int*))) == 0)
447
exit (2);
448
for (i = 0; i < dim; ++i)
449
{
450
if (((*H)[0][i] = (int*)malloc(dim * sizeof(int))) == 0)
451
exit (2);
452
}
453
nH = 0;
454
/* w[i+V.n] is a matrix that maps V.v[pt] on V.v[i] */
455
if ((w = (int***)malloc((2*V.n+1) * sizeof(int**))) == 0)
456
exit (2);
457
/* orb contains the orbit of V.v[pt] */
458
if ((orb = (int*)malloc(2*V.n * sizeof(int))) == 0)
459
exit (2);
460
/* orblen is the length of the orbit of a random vector in V.v */
461
orblen = 1;
462
for (i = 0; i < 2*V.n; ++i)
463
orb[i] = 0;
464
/* if flag[i+V.n] = 1, then the point i is already in the orbit */
465
if ((flag = (int*)malloc((2*V.n+1) * sizeof(int))) == 0)
466
exit (2);
467
for (i = 0; i <= 2*V.n; ++i)
468
flag[i] = 0;
469
orb[0] = pt;
470
flag[orb[0]+V.n] = 1;
471
/* w[pt+V.n] is the Identity */
472
if ((w[orb[0]+V.n] = (int**)malloc(dim * sizeof(int*))) == 0)
473
exit (2);
474
for (i = 0; i < dim; ++i)
475
{
476
if ((w[orb[0]+V.n][i] = (int*)malloc(dim * sizeof(int))) == 0)
477
exit (2);
478
for (j = 0; j < dim; ++j)
479
w[orb[0]+V.n][i][j] = 0;
480
w[orb[0]+V.n][i][i] = 1;
481
}
482
/* A and B are matrices for temporary use */
483
if ((A = (int**)malloc(dim * sizeof(int*))) == 0)
484
exit (2);
485
for (i = 0; i < dim; ++i)
486
{
487
if ((A[i] = (int*)malloc(dim * sizeof(int))) == 0)
488
exit (2);
489
}
490
if ((B = (int**)malloc(dim * sizeof(int*))) == 0)
491
exit (2);
492
for (i = 0; i < dim; ++i)
493
{
494
if ((B[i] = (int*)malloc(dim * sizeof(int))) == 0)
495
exit (2);
496
}
497
cnd = 0;
498
len = 1;
499
/* fail is the number of successive failures */
500
fail = 0;
501
while (len > cnd && fail < Maxfail)
502
{
503
for (i = 0; i < nG && fail < Maxfail; ++i)
504
{
505
im = operate(orb[cnd], G[i], V);
506
if (flag[im+V.n] == 0)
507
/* a new element is found, appended to the orbit and an element mapping
508
V.v[pt] to im is stored in w[im+V.n] */
509
{
510
orb[len] = im;
511
flag[im+V.n] = 1;
512
if ((w[im+V.n] = (int**)malloc(dim * sizeof(int*))) == 0)
513
exit (2);
514
for (j = 0; j < dim; ++j)
515
{
516
if ((w[im+V.n][j] = (int*)malloc(dim * sizeof(int))) == 0)
517
exit (2);
518
}
519
matmul(w[orb[cnd]+V.n], G[i], dim, w[im+V.n]);
520
++len;
521
}
522
else
523
/* the image was already in the orbit */
524
{
525
matmul(w[orb[cnd]+V.n], G[i], dim, B);
526
/* check, whether the old and the new element mapping pt on im differ */
527
for (j = 0; j < dim && comp(B[j], w[im+V.n][j], dim) == 0; ++j);
528
if (j < dim)
529
{
530
/* w[im+V.n] is copied to A, since psolve changes the matrices */
531
for (j = 0; j < dim; ++j)
532
{
533
for (k = 0; k < dim; ++k)
534
A[j][k] = w[im+V.n][j][k];
535
}
536
/* new stabilizer element H[nH] = w[orb[cnd]+V.n] * G[i] * (w[im+V.n])^-1 */
537
psolve((*H)[nH], A, B, dim, V.prime);
538
rpt = rand() % V.n + 1;
539
tmplen = orbitlen(rpt, 2*V.n, *H, nH+1, V);
540
while (tmplen < orblen)
541
/* the orbit of this vector is shorter than a previous one, hence choose a new
542
random vector */
543
{
544
rpt = rand() % V.n + 1;
545
tmplen = orbitlen(rpt, 2*V.n, *H, nH+1, V);
546
}
547
if (tmplen > orblen)
548
/* the new stabilizer element H[nH] enlarges the group generated by H */
549
{
550
orblen = tmplen;
551
++nH;
552
/* allocate memory for the new generator */
553
if ((*H = (int***)realloc(*H, (nH+1) * sizeof(int**))) == 0)
554
exit (2);
555
if (((*H)[nH] = (int**)malloc(dim * sizeof(int*))) == 0)
556
exit (2);
557
for (k = 0; k < dim; ++k)
558
{
559
if (((*H)[nH][k] = (int*)malloc(dim * sizeof(int))) == 0)
560
exit (2);
561
}
562
fail = 0;
563
}
564
else
565
/* the new stabilizer element does not enlarge the orbit of a random vector */
566
++fail;
567
}
568
/* if H[nH] is the identity, nothing is done */
569
}
570
}
571
++cnd;
572
}
573
for (i = 0; i <= 2*V.n; ++i)
574
{
575
if (flag[i] == 1)
576
{
577
for (j = 0; j < dim; ++j)
578
free(w[i][j]);
579
free(w[i]);
580
}
581
}
582
free(w);
583
for (i = 0; i < dim; ++i)
584
{
585
free(A[i]);
586
free(B[i]);
587
free((*H)[nH][i]);
588
}
589
free(A);
590
free(B);
591
free((*H)[nH]);
592
free(orb);
593
free(flag);
594
595
return(nH);
596
}
597
598