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

563667 views
1
/***** Main program for the automorphism program AUTO *****/
2
3
#include "typedef.h"
4
#include "types.h"
5
#include "sort.h"
6
7
/**************************************************************************\
8
@---------------------------------------------------------------------------
9
@---------------------------------------------------------------------------
10
@ FILE: autgrp.c
11
@---------------------------------------------------------------------------
12
@---------------------------------------------------------------------------
13
@
14
\**************************************************************************/
15
16
static int normal_option;
17
static int perp_no;
18
static int ***perp;
19
static int perpdim;
20
static int ***perpbase;
21
static int ***perpprod;
22
static int *perpvec;
23
24
#include "auttools.c"
25
#include "bachtools.c"
26
#include "iotools.c"
27
#include "lattools.c"
28
#include "mattools.c"
29
#include "orbtools.c"
30
#include "preproc.c"
31
#include "sorttools.c"
32
#include "perfecttools.c"
33
34
/*************************************************************************\
35
@-------------------------------------------------------------------------
36
@ bravais_TYP *autgrp(Fo, Foanz, SV, Erz, Erzanz, options)
37
@ matrix_TYP **Fo, **Erz, *SV;
38
@ int Foanz, Erzanz, *options;
39
@
40
@ The functions 'autgrp' calculates generators and the order of the group
41
@ G := {g in GL_n(Z) | g^{tr} * Fo[i] * g = Fo[i], 1<= i<= Foanz}
42
@ returned via a pointer to 'bravais_TYP'.
43
@
44
@ The arguments of autgrp are:
45
@ matrix_TYP **Fo: a set of n times n matrices,
46
@ the first must be positiv definite
47
@ int Foanz: the number of the matrices given in 'Fo'.
48
@ matrix_TYP **Erz: if already element of G are known,
49
@ they can be used for calculating generators
50
@ for the whole group.
51
@ The matrices of known elements can be given
52
@ to the function by the pointer 'Erz'.
53
@ int Erzanz: The number of matrices given in 'Erz"
54
@ matrix_TYP *SV: The rows of the matrix 'SV' must be the vectors
55
@ x in Z^n with x * F[0] * x^{tr} <= m, where
56
@ m is the maximal diagonal entry of the Matrix
57
@ F[0]
58
@ int *options: see below.
59
@
60
@ options is a pointer to integer (of length 6)
61
@ The possible options are encoded in the following way:
62
@ options[0]: The depth, up to wich scalar product combinations
63
@ shall be calculated. The value should be small.
64
@ options[0] > 0 should be used only, if the automorphismn
65
@ group is expected to be small (with respect to the number
66
@ of shortest vectors).
67
@ options[1]: The n-point stabiliser with respect to different basis
68
@ will be calculated.
69
@ options[2]: If options[2] = 1, additional output is written to the
70
@ file AUTO.tmp
71
@ options[3]: If options[3] = 1, Bacher polynomials are used.
72
@ If options[3] = 2, Bacher polynomial are used up to a deepth
73
@ specified in options[4].
74
@ If options[3] = 3, Bacher polynomials are used, using
75
@ combinations of vectors having the scalar
76
@ product specified in options[5]
77
@ options[3] = 4 is the combination of options[3] = 2 and
78
@ options[3] = 3.
79
@ options[4]: A natural number number or zero (if options[3] = 2 or 4)
80
@ options[5]: An integral number (if options[3] = 3 or 4)
81
@
82
@ It is possible to use NULL for options,
83
@ in this case option is assumed to be [0,0,0,0,0,0]
84
@-------------------------------------------------------------------------
85
\*************************************************************************/
86
87
88
bravais_TYP *autgrp(Fo, Foanz, SV, Erz, Erzanz, options)
89
matrix_TYP **Fo, **Erz, *SV;
90
int Foanz, Erzanz, *options;
91
{
92
FILE *outfile;
93
bachpol *bach;
94
flagstruct flags;
95
scpcomb *comb;
96
group G;
97
invar F;
98
veclist V, norm;
99
fpstruct fp;
100
int dim, max, fail, *vec;
101
int ***H, nH, ngen, **sumveclist, **sumvecbase;
102
int i, j, k, l, n, *Vvi, *Vvj, **Fvi, *Fvij, **FAi;
103
bravais_TYP *B;
104
105
normal_option = FALSE;
106
/* get the flags from the command line */
107
getflags(&flags, options);
108
if(Erzanz > 0)
109
flags.GEN = 1;
110
else
111
flags.GEN = 0;
112
/* F.n is the number of invariant forms */
113
F.n = Foanz;
114
if ((F.A = (int***)malloc(F.n * sizeof(int**))) == 0)
115
exit (2);
116
/* read the invariant forms */
117
F.dim = Fo[0]->cols;
118
dim = F.dim;
119
for(i=0;i<F.n;i++)
120
{
121
if(Fo[i]->cols != F.dim || Fo[i]->rows != F.dim)
122
{
123
printf("forms in autgrp have different dimension\n");
124
exit(3);
125
}
126
}
127
for(i=0;i<F.n;i++)
128
{
129
if ((F.A[i] = (int**)malloc(dim * sizeof(int*))) == 0)
130
exit (2);
131
for(j=0;j<F.dim;j++)
132
{
133
if ((F.A[i][j] = (int*)malloc(dim * sizeof(int))) == 0)
134
exit (2);
135
for(k=0;k<F.dim;k++)
136
F.A[i][j][k] = Fo[i]->array.SZ[j][k];
137
}
138
}
139
if (flags.GEN == 1)
140
/* some automorphisms are already known */
141
{
142
ngen = Erzanz;
143
if ((H = (int***)malloc(ngen * sizeof(int**))) == 0)
144
exit (2);
145
nH = 0;
146
fail = 0;
147
for(i=0;i<ngen;i++)
148
{
149
if(Erz[i]->cols != dim || Erz[i]->rows != dim)
150
{
151
printf("Elements 'Erz' have wrong dimension\n");
152
exit(3);
153
}
154
}
155
i = 0;
156
while (nH+fail < ngen)
157
{
158
if ((H[nH] = (int**)malloc(dim * sizeof(int*))) == 0)
159
exit (2);
160
for(j=0;j<dim;j++)
161
{
162
if ((H[nH][j] = (int*)malloc(dim * sizeof(int))) == 0)
163
exit (2);
164
for(k=0;k<dim;k++)
165
H[nH][j][k] = Erz[i]->array.SZ[k][j];
166
}
167
/* check whether the matrix is really an automorphism, i.e. fixes the forms */
168
if (checkgen(H[nH], F) == 0)
169
/* the matrix is not an automorphism */
170
{
171
++fail;
172
for (j = 0; j < dim; ++j)
173
free(H[nH][j]);
174
free(H[nH]);
175
}
176
else
177
/* the matrix fixes all forms in F */
178
++nH;
179
i++;
180
}
181
}
182
else
183
nH = 0;
184
185
186
187
V.dim = dim;
188
V.len = dim + F.n;
189
/* get the short vectors */
190
V.n = SV->rows;
191
if ((V.v = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
192
exit (2);
193
for(i=0;i<=V.n;i++)
194
{
195
if ((V.v[i] = (int*)malloc(V.len * sizeof(int))) == 0)
196
exit (2);
197
}
198
for(i=1;i<= V.n;i++)
199
{
200
for(j=0;j<=dim;j++)
201
V.v[i][j] = SV->array.SZ[i-1][j];
202
}
203
/* the first nonzero entry of each vector is made positive and the maximal
204
entry of the vectors is determined */
205
max = 1;
206
for (i = 1; i <= V.n; ++i)
207
{
208
Vvi = V.v[i];
209
for (j = 0; j < dim && Vvi[j] == 0; ++j);
210
if (j < dim && Vvi[j] < 0)
211
{
212
for (k = j; k < dim; ++k)
213
Vvi[k] *= -1;
214
}
215
for (k = j; k < dim; ++k)
216
{
217
if (abs(Vvi[k]) > max)
218
max = abs(Vvi[k]);
219
}
220
}
221
if (max > MAXENTRY)
222
/* there is an entry, which is bigger than MAXENTRY, which might cause overflow,
223
since the program doesn't use long integer arithmetic */
224
{
225
fprintf(stderr, "Error: Found entry %d in short vectors.\nTo avoid overflow, the entries should not exceed %d.\n", max, MAXENTRY);
226
exit (3);
227
}
228
/* V.prime is a prime p, such that every entry x in the short vectors remains
229
unchanged under reduction mod p in symmetric form, i.e. -p/2 < x <= p/2 */
230
for (V.prime = 2*max + 1; isprime(V.prime) == 0; ++V.prime);
231
/* sort the vectors and delete doublets */
232
sortvecs(&V);
233
/* the norm-vector (i.e. the vector of the norms with respect to the different
234
invariant forms) of each vector must be equal to the norm-vector of one
235
of the vectors from the standard-base */
236
if ((norm.v = (int**)malloc((dim+1) * sizeof(int*))) == 0)
237
exit (2);
238
norm.n = dim;
239
norm.dim = F.n;
240
norm.len = F.n;
241
for (i = 1; i <= norm.n; ++i)
242
{
243
/* norm.v[i] is the norm combination of the (i-1)-th base-vector */
244
if ((norm.v[i] = (int*)malloc(norm.dim * sizeof(int))) == 0)
245
exit (2);
246
for (k = 0; k < norm.dim; ++k)
247
norm.v[i][k] = F.A[k][i-1][i-1];
248
}
249
sortvecs(&norm);
250
/* delete those vectors, which can not be the image of any of the standard-base
251
vectors */
252
checkvecs(&V, F, norm);
253
for (i = 1; i <= norm.n; ++i)
254
free(norm.v[i]);
255
free(norm.v);
256
/* print the invariant forms, if output is in ASCII-format */
257
/*********************************************
258
printf("#%d\n", F.n);
259
for (i = 0; i < F.n; ++i)
260
putform(F.A[i], dim);
261
**********************************************/
262
/* F.v[i][j] is the transposed of the product of the Gram-matrix F.A[i] with the
263
transposed of the vector v[j], hence the scalar product of v[j] and v[k] with
264
respect to the Gram-matrix F.A[i] can be computed as standard scalar product
265
of v[j] and F.v[i][k] */
266
if ((F.v = (int***)malloc(F.n * sizeof(int**))) == 0)
267
exit (2);
268
/* the product of the maximal entry in the short vectors with the maximal entry
269
in F.v[i] should not exceed MAXNORM to avoid overflow */
270
max = MAXNORM / max;
271
for (i = 0; i < F.n; ++i)
272
{
273
FAi = F.A[i];
274
if ((F.v[i] = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
275
exit (2);
276
Fvi = F.v[i];
277
for (j = 1; j <= V.n; ++j)
278
{
279
Vvj = V.v[j];
280
if ((Fvi[j] = (int*)malloc(dim * sizeof(int))) == 0)
281
exit (2);
282
Fvij = Fvi[j];
283
for (k = 0; k < dim; ++k)
284
{
285
Fvij[k] = sscp(FAi[k], Vvj, dim);
286
if (abs(Fvij[k]) > max)
287
/* some entry in F.v[i] is too large */
288
{
289
fprintf(stderr, "Error: Found entry %d in F.v.\nTo avoid overflow, the entries should not exceed %d.\n", Fvij[k], max);
290
exit (3);
291
}
292
}
293
}
294
}
295
/* fp.per is the order in which the images of the base-vectors are set */
296
if ((fp.per = (int*)malloc(dim * sizeof(int))) == 0)
297
exit (2);
298
/* fp.e[i] is the index in V.v of the i-th vector of the standard-base in the
299
new order */
300
if ((fp.e = (int*)malloc(dim * sizeof(int))) == 0)
301
exit (2);
302
/* fp.diag is the diagonal of the fingerprint in the new order, fp.diag[i] is
303
an upper bound for the length of the orbit of the i-th base-vector under
304
the stabilizer of the preceding ones */
305
if ((fp.diag = (int*)malloc(dim * sizeof(int))) == 0)
306
exit (2);
307
/* compute the fingerprint */
308
fingerprint(&fp, F, V);
309
if (flags.PRINT == 1)
310
/* if the -P option is given, print the diagonal fp.diag and the number of short
311
vectors on AUTO.tmp */
312
{
313
outfile = fopen("AUTO.tmp", "a");
314
fprintf(outfile, "%d short vectors\n", 2*V.n);
315
fprintf(outfile, "fingerprint diagonal:\n");
316
for (i = 0; i < dim; ++i)
317
fprintf(outfile, " %2d", fp.diag[i]);
318
fprintf(outfile, "\n");
319
fclose(outfile);
320
}
321
/* get the standard basis in the new order */
322
if ((vec = (int*)malloc(dim * sizeof(int))) == 0)
323
exit (2);
324
for (i = 0; i < dim; ++i)
325
{
326
for (j = 0; j < dim; ++j)
327
vec[j] = 0;
328
vec[fp.per[i]] = 1;
329
fp.e[i] = numberof(vec, V);
330
if (abs(fp.e[i]) > V.n)
331
/* the standard-base must occur in the set of short vectors, since Id is
332
certainly an automorphism */
333
{
334
fprintf(stderr, "Error: standard basis vector nr. %d not found\n", i);
335
exit (2);
336
}
337
}
338
free(vec);
339
/* if the -D option is given, the scalar product combinations and the
340
corresponding vector sums are computed for the standard-basis */
341
if (flags.DEPTH > 0)
342
{
343
if ((comb = (scpcomb*)malloc(dim * sizeof(scpcomb))) == 0)
344
exit (2);
345
for (i = 0; i < dim; ++i)
346
{
347
/* compute the list of scalar product combinations and the corresponding
348
vector sums */
349
scpvecs(&comb[i].list, &sumveclist, i, fp.e, flags.DEPTH, V, F);
350
/* compute a basis for the lattice that is generated by the vector sums and
351
a transformation matrix that expresses the basis in terms of the
352
vector sums */
353
base(&comb[i], &sumvecbase, sumveclist, F.A[0], dim);
354
if (flags.PRINT == 1)
355
/* if the -P option is given, print the rank of the lattice generated by the
356
vector sums on level i on AUTO.tmp */
357
{
358
outfile = fopen("AUTO.tmp", "a");
359
fprintf(outfile, "comb[%d].rank = %d\n", i, comb[i].rank);
360
fclose(outfile);
361
}
362
/* compute the coefficients of the vector sums in terms of the basis */
363
coef(&comb[i], sumvecbase, sumveclist, F.A[0], dim);
364
for (j = 0; j <= comb[i].list.n; ++j)
365
free(sumveclist[j]);
366
free(sumveclist);
367
/* compute the scalar products of the base-vectors */
368
scpforms(&comb[i], sumvecbase, F);
369
for (j = 0; j < comb[i].rank; ++j)
370
free(sumvecbase[j]);
371
free(sumvecbase);
372
}
373
}
374
/* the Bacher-polynomials for the first BACHDEP base-vectors are computed,
375
if no scalar product was given as an argument, the scalar product is set
376
to 1/2 the norm of the base-vector (with respect to the first form) */
377
if (flags.BACH[0] == 1)
378
{
379
if ((bach = (bachpol*)malloc(flags.BACHDEP * sizeof(bachpol))) == 0)
380
exit (2);
381
for (i = 0; i < flags.BACHDEP; ++i)
382
{
383
if (flags.BACH[2] == 0)
384
/* no scalar product was given as an option */
385
flags.BACHSCP = V.v[fp.e[i]][dim] / 2;
386
/* compute the Bacher-polynomial */
387
bacher(&bach[i], fp.e[i], flags.BACHSCP, V, F.v[0]);
388
if (flags.PRINT == 1)
389
/* if the -P option is given, print the Bacher-polynomial on AUTO.tmp */
390
{
391
outfile = fopen("AUTO.tmp", "a");
392
fprintf(outfile, "Bacher-polynomial of base vector fp.e[%d]:\n", i);
393
fputbach(outfile, bach[i]);
394
fclose(outfile);
395
}
396
}
397
}
398
/* set up the group: the generators in G.g[i] are matrices that fix the
399
first i base-vectors but do not fix fp.e[i] */
400
if ((G.g = (int****)malloc(dim * sizeof(int***))) == 0)
401
exit (2);
402
/* G.ng is the number of generators in G.g[i] */
403
if ((G.ng = (int*)malloc(dim * sizeof(int))) == 0)
404
exit (2);
405
/* the first G.nsg[i] generators in G.g[i] are obtained as stabilizer elements
406
and are not necessary to generate the group */
407
if ((G.nsg = (int*)malloc(dim * sizeof(int))) == 0)
408
exit (2);
409
/* G.ord[i] is the orbit length of fp.e[i] under the generators in
410
G.g[i] ... G.g[dim-1] */
411
if ((G.ord = (int*)malloc(dim * sizeof(int))) == 0)
412
exit (2);
413
for (i = 0; i < dim; ++i)
414
{
415
if ((G.g[i] = (int***)malloc(1 * sizeof(int**))) == 0)
416
exit (2);
417
G.ng[i] = 0;
418
G.nsg[i] = 0;
419
}
420
G.dim = dim;
421
if ((G.g[0][0] = (int**)malloc(dim * sizeof(int*))) == 0)
422
exit (2);
423
/* -Id is always an automorphism */
424
for (i = 0; i < dim; ++i)
425
{
426
if ((G.g[0][0][i] = (int*)malloc(dim * sizeof(int))) == 0)
427
exit (2);
428
for (j = 0; j < dim; ++j)
429
G.g[0][0][i][j] = 0;
430
G.g[0][0][i][i] = -1;
431
G.ng[0] = 1;
432
}
433
/* fill in the generators which were given as input */
434
for (i = 0; i < nH; ++i)
435
{
436
for (j = 0; j < dim && operate(fp.e[j], H[i], V) == fp.e[j]; ++j);
437
if (j < dim)
438
/* the generator is not Id and fixes fp.e[0],...,fp.e[j-1] but not fp.e[j] */
439
{
440
++G.ng[j];
441
if ((G.g[j] = (int***)realloc(G.g[j], G.ng[j] * sizeof(int**))) == 0)
442
exit (2);
443
if ((G.g[j][G.ng[j]-1] = (int**)malloc(dim * sizeof(int*))) == 0)
444
exit (2);
445
for (k = 0; k < dim; ++k)
446
{
447
if ((G.g[j][G.ng[j]-1][k] = (int*)malloc(dim * sizeof(int))) == 0)
448
exit (2);
449
for (l = 0; l < dim; ++l)
450
G.g[j][G.ng[j]-1][k][l] = H[i][k][l];
451
}
452
}
453
for (k = 0; k < dim; ++k)
454
free(H[i][k]);
455
free(H[i]);
456
}
457
if (nH > 0)
458
free(H);
459
nH = 0;
460
for (i = 0; i < dim; ++i)
461
nH += G.ng[i];
462
if ((H = (int***)malloc(nH * sizeof(int**))) == 0)
463
exit (2);
464
/* calculate the orbit lengths under the automorphisms known so far */
465
for (i = 0; i < dim; ++i)
466
{
467
if (G.ng[i] > 0)
468
{
469
nH = 0;
470
for (j = i; j < dim; ++j)
471
{
472
for (k = 0; k < G.ng[j]; ++k)
473
{
474
H[nH] = G.g[j][k];
475
++nH;
476
}
477
}
478
G.ord[i] = orbitlen(fp.e[i], fp.diag[i], H, nH, V);
479
}
480
else
481
G.ord[i] = 1;
482
}
483
free(H);
484
/* compute the full automorphism group */
485
autom(&G, V, F, fp, comb, bach, flags);
486
/* print the generators of the group, which are necessary for generating */
487
B = putgens(G, flags);
488
n = 0;
489
for (i = flags.STAB; i < dim; ++i)
490
{
491
if (G.ord[i] > 1)
492
++n;
493
}
494
/* print a base to AUTO.tmp if the print-flag is set */
495
if (flags.PRINT == 1)
496
{
497
outfile = fopen("AUTO.tmp", "a");
498
fprintf(outfile, "%dx%d\n", n, dim);
499
for (i = flags.STAB; i < dim; ++i)
500
{
501
if (G.ord[i] > 1)
502
{
503
for (j = 0; j < dim; ++j)
504
fprintf(outfile, " %d", V.v[fp.e[i]][j]);
505
fprintf(outfile, "\n");
506
}
507
}
508
fclose(outfile);
509
}
510
/* print the order of the group */
511
putord(G, flags, B);
512
513
514
if (flags.BACH[0] == 1)
515
{
516
for (i = 0; i < flags.BACHDEP; ++i)
517
free(bach[i].coef);
518
free(bach);
519
}
520
if (flags.DEPTH > 0)
521
{
522
for(i=0;i<dim;i++)
523
{
524
for(j=0;j<=comb[i].list.n;j++)
525
free(comb[i].coef[j]);
526
free(comb[i].coef);
527
for(j=0;j<=comb[i].list.n;j++)
528
free(comb[i].list.v[j]);
529
free(comb[i].list.v);
530
for(j=0;j<comb[i].rank;j++)
531
free(comb[i].trans[j]);
532
free(comb[i].trans);
533
for(j=0;j<F.n;j++)
534
{
535
for(k=0;k<comb[i].rank;k++)
536
free(comb[i].F[j][k]);
537
free(comb[i].F[j]);
538
}
539
free(comb[i].F);
540
}
541
free(comb);
542
}
543
for(i=0;i<F.n;i++)
544
{
545
for(j=1;j<=V.n;j++)
546
free(F.v[i][j]);
547
free(F.v[i]);
548
for(j=0;j<dim;j++)
549
free(F.A[i][j]);
550
free(F.A[i]);
551
}
552
free(F.A); free(F.v);
553
for(i=0;i<=V.n;i++)
554
free(V.v[i]);
555
free(V.v);
556
free(fp.diag); free(fp.per); free(fp.e);
557
for(i=0;i<dim;i++)
558
{
559
for(j=0;j<G.ng[i];j++)
560
{
561
for(k=0;k<dim;k++)
562
free(G.g[i][j][k]);
563
free(G.g[i][j]);
564
}
565
free(G.g[i]);
566
}
567
free(G.g); free(G.ord); free(G.ng); free(G.nsg);
568
569
return(B);
570
}
571
572
573
/**************************************************************************\
574
@---------------------------------------------------------------------------
575
@ bravais_TYP *perfect_normal_autgrp(Fo, SV, Erz, Erzanz, options,
576
@ P, Panz, Pbase, Pdim)
577
@ matrix_TYP *Fo, **Erz, *SV, **P, **Pbase;
578
@ int Erzanz, *options, Panz, Pdim;
579
@
580
@ The function 'perfect_normal_autgrp' calculates generators for
581
@ G = {g in GL_n(Z)| g^{tr} * Fo * g = Fo and
582
@ g^{tr} Pbase[i] g is a matrix in P for 0<=i<Pdim}
583
@
584
@ The arguments are:
585
@ Fo: a symmetric positive definite n by n-matrix.
586
@ SV: the vectors x in GL_n(Z) (up to sign) with x Fo x^{tr} < k,
587
@ where k is the maximal diagonal entry of 'Fo'.
588
@ Erz: matrices of elements of G (if known).
589
@ Erzanz: the number of matrices in 'Erz'.
590
@ options: the same as for the function 'autgrp'.
591
@ P: a set of matrices
592
@ Panz: the number of matrices given in 'P'.
593
@ Pbase: a set of matrices
594
@ Pdim: the number of matrices given in 'Pbase'.
595
@
596
@ This function is designed to calculate the stabilizer of a perfect
597
@ form 'Fo' in the normalizer of the group generated by the matrices
598
@ given in 'Erz'.
599
@ Then 'P' is the set of matrices given by the Voronoi-directions of 'Fo'
600
@ and 'Pbase' a maximal linearly independent subset of 'P'.
601
@
602
@---------------------------------------------------------------------------
603
@
604
\**************************************************************************/
605
606
607
bravais_TYP *perfect_normal_autgrp(Fo, SV, Erz, Erzanz, options, P, Panz, Pbase, Pdim)
608
matrix_TYP *Fo, **Erz, *SV, **P, **Pbase;
609
int Erzanz, *options, Panz, Pdim;
610
{
611
FILE *outfile;
612
bachpol *bach;
613
flagstruct flags;
614
scpcomb *comb;
615
group G;
616
invar F;
617
veclist V, norm;
618
fpstruct fp;
619
int dim, max, fail, *vec;
620
int ***H, nH, ngen, **sumveclist, **sumvecbase;
621
int i, j, k, l, n, *Vvi, *Vvj, **Fvi, *Fvij, **FAi;
622
bravais_TYP *B;
623
624
extern matrix_TYP *init_mat();
625
extern int pointer_lower_triangular_mat_comp();
626
627
normal_option = TRUE;
628
perp_no = Panz;
629
perpdim = Pdim;
630
/* get the flags from the command line */
631
getflags(&flags, options);
632
if(Erzanz > 0)
633
flags.GEN = 1;
634
else
635
flags.GEN = 0;
636
/* F.n is the number of invariant forms */
637
F.n = 1;
638
if ((F.A = (int***)malloc(1 *sizeof(int**))) == 0)
639
exit (2);
640
/* read the invariant forms */
641
F.dim = Fo->cols;
642
dim = F.dim;
643
if(Fo->cols != F.dim || Fo->rows != F.dim)
644
{
645
printf("error form 'Fo' in autgrp must be a square matrix\n");
646
exit(3);
647
}
648
if ((F.A[0] = (int**)malloc(dim * sizeof(int*))) == 0)
649
exit (2);
650
for(j=0;j<F.dim;j++)
651
{
652
if ((F.A[0][j] = (int*)malloc(dim * sizeof(int))) == 0)
653
exit (2);
654
for(k=0;k<F.dim;k++)
655
F.A[0][j][k] = Fo->array.SZ[j][k];
656
}
657
if (flags.GEN == 1)
658
/* some automorphisms are already known */
659
{
660
ngen = Erzanz;
661
if ((H = (int***)malloc(ngen * sizeof(int**))) == 0)
662
exit (2);
663
nH = 0;
664
fail = 0;
665
for(i=0;i<ngen;i++)
666
{
667
if(Erz[i]->cols != dim || Erz[i]->rows != dim)
668
{
669
printf("Elements 'Erz' have wrong dimension\n");
670
exit(2);
671
}
672
}
673
i = 0;
674
while (nH+fail < ngen)
675
{
676
if ((H[nH] = (int**)malloc(dim * sizeof(int*))) == 0)
677
exit (2);
678
for(j=0;j<dim;j++)
679
{
680
if ((H[nH][j] = (int*)malloc(dim * sizeof(int))) == 0)
681
exit (2);
682
for(k=0;k<dim;k++)
683
H[nH][j][k] = Erz[i]->array.SZ[k][j];
684
}
685
/* check whether the matrix is really an automorphism, i.e. fixes the forms */
686
if (checkgen(H[nH], F) == 0)
687
/* the matrix is not an automorphism */
688
{
689
++fail;
690
for (j = 0; j < dim; ++j)
691
free(H[nH][j]);
692
free(H[nH]);
693
}
694
else
695
/* the matrix fixes all forms in F */
696
++nH;
697
i++;
698
}
699
}
700
else
701
nH = 0;
702
703
704
705
V.dim = dim;
706
V.len = dim + F.n;
707
/* get the short vectors */
708
V.n = SV->rows;
709
if ((V.v = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
710
exit (2);
711
if ((V.v[0] = (int*)malloc(V.len * sizeof(int))) == 0)
712
exit (2);
713
/* tilman 9/1/97 changed these lines
714
for(i=1;i<= V.n;i++)
715
{
716
V.v[i] = SV->array.SZ[i-1];
717
} to (next 5 lines): */
718
for(i=1;i<= V.n;i++)
719
{
720
V.v[i] = (int *) malloc((SV->rows+1) * sizeof(int));
721
for (j=0;j<SV->cols;j++){
722
V.v[i][j] = SV->array.SZ[i-1][j];
723
}
724
}
725
726
/* the first nonzero entry of each vector is made positive and the maximal
727
entry of the vectors is determined */
728
max = 1;
729
for (i = 1; i <= V.n; ++i)
730
{
731
Vvi = V.v[i];
732
for (j = 0; j < dim && Vvi[j] == 0; ++j);
733
if (j < dim && Vvi[j] < 0)
734
{
735
for (k = j; k < dim; ++k)
736
Vvi[k] *= -1;
737
}
738
for (k = j; k < dim; ++k)
739
{
740
if (abs(Vvi[k]) > max)
741
max = abs(Vvi[k]);
742
}
743
}
744
if (max > MAXENTRY)
745
/* there is an entry, which is bigger than MAXENTRY, which might cause overflow,
746
since the program doesn't use long integer arithmetic */
747
{
748
fprintf(stderr, "Error: Found entry %d in short vectors.\nTo avoid overflow, the entries should not exceed %d.\n", max, MAXENTRY);
749
exit (3);
750
}
751
/* V.prime is a prime p, such that every entry x in the short vectors remains
752
unchanged under reduction mod p in symmetric form, i.e. -p/2 < x <= p/2 */
753
for (V.prime = 2*max + 1; isprime(V.prime) == 0; ++V.prime);
754
/* sort the vectors and delete doublets */
755
sortvecs(&V);
756
/* the norm-vector (i.e. the vector of the norms with respect to the different
757
invariant forms) of each vector must be equal to the norm-vector of one
758
of the vectors from the standard-base */
759
if ((norm.v = (int**)malloc((dim+1) * sizeof(int*))) == 0)
760
exit (2);
761
norm.n = dim;
762
norm.dim = F.n;
763
norm.len = F.n;
764
for (i = 1; i <= norm.n; ++i)
765
{
766
/* norm.v[i] is the norm combination of the (i-1)-th base-vector */
767
if ((norm.v[i] = (int*)malloc(norm.dim * sizeof(int))) == 0)
768
exit (2);
769
for (k = 0; k < norm.dim; ++k)
770
norm.v[i][k] = F.A[k][i-1][i-1];
771
}
772
sortvecs(&norm);
773
/* delete those vectors, which can not be the image of any of the standard-base
774
vectors */
775
checkvecs(&V, F, norm);
776
for (i = 1; i <= norm.n; ++i)
777
free(norm.v[i]);
778
free(norm.v);
779
/* print the invariant forms, if output is in ASCII-format */
780
/*********************************************
781
printf("#%d\n", F.n);
782
for (i = 0; i < F.n; ++i)
783
putform(F.A[i], dim);
784
**********************************************/
785
/* F.v[i][j] is the transposed of the product of the Gram-matrix F.A[i] with the
786
transposed of the vector v[j], hence the scalar product of v[j] and v[k] with
787
respect to the Gram-matrix F.A[i] can be computed as standard scalar product
788
of v[j] and F.v[i][k] */
789
if ((F.v = (int***)malloc(F.n * sizeof(int**))) == 0)
790
exit (2);
791
/* the product of the maximal entry in the short vectors with the maximal entry
792
in F.v[i] should not exceed MAXNORM to avoid overflow */
793
max = MAXNORM / max;
794
for (i = 0; i < F.n; ++i)
795
{
796
FAi = F.A[i];
797
if ((F.v[i] = (int**)malloc((V.n+1) * sizeof(int*))) == 0)
798
exit (2);
799
Fvi = F.v[i];
800
for (j = 1; j <= V.n; ++j)
801
{
802
Vvj = V.v[j];
803
if ((Fvi[j] = (int*)malloc(dim * sizeof(int))) == 0)
804
exit (2);
805
Fvij = Fvi[j];
806
for (k = 0; k < dim; ++k)
807
{
808
Fvij[k] = sscp(FAi[k], Vvj, dim);
809
if (abs(Fvij[k]) > max)
810
/* some entry in F.v[i] is too large */
811
{
812
fprintf(stderr, "Error: Found entry %d in F.v.\nTo avoid overflow, the entries should not exceed %d.\n", Fvij[k], max);
813
exit (3);
814
}
815
}
816
}
817
}
818
/* fp.per is the order in which the images of the base-vectors are set */
819
if ((fp.per = (int*)malloc(dim * sizeof(int))) == 0)
820
exit (2);
821
/* fp.e[i] is the index in V.v of the i-th vector of the standard-base in the
822
new order */
823
if ((fp.e = (int*)malloc(dim * sizeof(int))) == 0)
824
exit (2);
825
/* fp.diag is the diagonal of the fingerprint in the new order, fp.diag[i] is
826
an upper bound for the length of the orbit of the i-th base-vector under
827
the stabilizer of the preceding ones */
828
if ((fp.diag = (int*)malloc(dim * sizeof(int))) == 0)
829
exit (2);
830
/* compute the fingerprint */
831
fingerprint(&fp, F, V);
832
mach_perp_matrices(fp, P, Pbase, dim);
833
pointer_mat_quicksort(perp, 0, perp_no-1, dim, dim, pointer_lower_triangular_mat_comp);
834
if (flags.PRINT == 1)
835
/* if the -P option is given, print the diagonal fp.diag and the number of short
836
vectors on AUTO.tmp */
837
{
838
outfile = fopen("AUTO.tmp", "a");
839
fprintf(outfile, "%d short vectors\n", 2*V.n);
840
fprintf(outfile, "fingerprint diagonal:\n");
841
for (i = 0; i < dim; ++i)
842
fprintf(outfile, " %2d", fp.diag[i]);
843
fprintf(outfile, "\n");
844
fclose(outfile);
845
}
846
/* get the standard basis in the new order */
847
if ((vec = (int*)malloc(dim * sizeof(int))) == 0)
848
exit (2);
849
for (i = 0; i < dim; ++i)
850
{
851
for (j = 0; j < dim; ++j)
852
vec[j] = 0;
853
vec[fp.per[i]] = 1;
854
fp.e[i] = numberof(vec, V);
855
if (abs(fp.e[i]) > V.n)
856
/* the standard-base must occur in the set of short vectors, since Id is
857
certainly an automorphism */
858
{
859
fprintf(stderr, "Error: standard basis vector nr. %d not found\n", i);
860
exit (3);
861
}
862
}
863
free(vec);
864
/* if the -D option is given, the scalar product combinations and the
865
corresponding vector sums are computed for the standard-basis */
866
if (flags.DEPTH > 0)
867
{
868
if ((comb = (scpcomb*)malloc(dim * sizeof(scpcomb))) == 0)
869
exit (3);
870
for (i = 0; i < dim; ++i)
871
{
872
/* compute the list of scalar product combinations and the corresponding
873
vector sums */
874
scpvecs(&comb[i].list, &sumveclist, i, fp.e, flags.DEPTH, V, F);
875
/* compute a basis for the lattice that is generated by the vector sums and
876
a transformation matrix that expresses the basis in terms of the
877
vector sums */
878
base(&comb[i], &sumvecbase, sumveclist, F.A[0], dim);
879
if (flags.PRINT == 1)
880
/* if the -P option is given, print the rank of the lattice generated by the
881
vector sums on level i on AUTO.tmp */
882
{
883
outfile = fopen("AUTO.tmp", "a");
884
fprintf(outfile, "comb[%d].rank = %d\n", i, comb[i].rank);
885
fclose(outfile);
886
}
887
/* compute the coefficients of the vector sums in terms of the basis */
888
coef(&comb[i], sumvecbase, sumveclist, F.A[0], dim);
889
for (j = 0; j <= comb[i].list.n; ++j)
890
free(sumveclist[j]);
891
free(sumveclist);
892
/* compute the scalar products of the base-vectors */
893
scpforms(&comb[i], sumvecbase, F);
894
for (j = 0; j < comb[i].rank; ++j)
895
free(sumvecbase[j]);
896
free(sumvecbase);
897
}
898
}
899
/* the Bacher-polynomials for the first BACHDEP base-vectors are computed,
900
if no scalar product was given as an argument, the scalar product is set
901
to 1/2 the norm of the base-vector (with respect to the first form) */
902
if (flags.BACH[0] == 1)
903
{
904
if ((bach = (bachpol*)malloc(flags.BACHDEP * sizeof(bachpol))) == 0)
905
exit (2);
906
for (i = 0; i < flags.BACHDEP; ++i)
907
{
908
if (flags.BACH[2] == 0)
909
/* no scalar product was given as an option */
910
flags.BACHSCP = V.v[fp.e[i]][dim] / 2;
911
/* compute the Bacher-polynomial */
912
bacher(&bach[i], fp.e[i], flags.BACHSCP, V, F.v[0]);
913
if (flags.PRINT == 1)
914
/* if the -P option is given, print the Bacher-polynomial on AUTO.tmp */
915
{
916
outfile = fopen("AUTO.tmp", "a");
917
fprintf(outfile, "Bacher-polynomial of base vector fp.e[%d]:\n", i);
918
fputbach(outfile, bach[i]);
919
fclose(outfile);
920
}
921
}
922
}
923
/* set up the group: the generators in G.g[i] are matrices that fix the
924
first i base-vectors but do not fix fp.e[i] */
925
if ((G.g = (int****)malloc(dim * sizeof(int***))) == 0)
926
exit (2);
927
/* G.ng is the number of generators in G.g[i] */
928
if ((G.ng = (int*)malloc(dim * sizeof(int))) == 0)
929
exit (2);
930
/* the first G.nsg[i] generators in G.g[i] are obtained as stabilizer elements
931
and are not necessary to generate the group */
932
if ((G.nsg = (int*)malloc(dim * sizeof(int))) == 0)
933
exit (2);
934
/* G.ord[i] is the orbit length of fp.e[i] under the generators in
935
G.g[i] ... G.g[dim-1] */
936
if ((G.ord = (int*)malloc(dim * sizeof(int))) == 0)
937
exit (2);
938
for (i = 0; i < dim; ++i)
939
{
940
if ((G.g[i] = (int***)malloc(1 * sizeof(int**))) == 0)
941
exit (2);
942
G.ng[i] = 0;
943
G.nsg[i] = 0;
944
}
945
G.dim = dim;
946
if ((G.g[0][0] = (int**)malloc(dim * sizeof(int*))) == 0)
947
exit (2);
948
/* -Id is always an automorphism */
949
for (i = 0; i < dim; ++i)
950
{
951
if ((G.g[0][0][i] = (int*)malloc(dim * sizeof(int))) == 0)
952
exit (2);
953
for (j = 0; j < dim; ++j)
954
G.g[0][0][i][j] = 0;
955
G.g[0][0][i][i] = -1;
956
G.ng[0] = 1;
957
}
958
/* fill in the generators which were given as input */
959
for (i = 0; i < nH; ++i)
960
{
961
for (j = 0; j < dim && operate(fp.e[j], H[i], V) == fp.e[j]; ++j);
962
if (j < dim)
963
/* the generator is not Id and fixes fp.e[0],...,fp.e[j-1] but not fp.e[j] */
964
{
965
++G.ng[j];
966
if ((G.g[j] = (int***)realloc(G.g[j], G.ng[j] * sizeof(int**))) == 0)
967
exit (2);
968
if ((G.g[j][G.ng[j]-1] = (int**)malloc(dim * sizeof(int*))) == 0)
969
exit (2);
970
for (k = 0; k < dim; ++k)
971
{
972
if ((G.g[j][G.ng[j]-1][k] = (int*)malloc(dim * sizeof(int))) == 0)
973
exit (2);
974
for (l = 0; l < dim; ++l)
975
G.g[j][G.ng[j]-1][k][l] = H[i][k][l];
976
}
977
}
978
for (k = 0; k < dim; ++k)
979
free(H[i][k]);
980
free(H[i]);
981
}
982
if (nH > 0)
983
free(H);
984
nH = 0;
985
for (i = 0; i < dim; ++i)
986
nH += G.ng[i];
987
if ((H = (int***)malloc(nH * sizeof(int**))) == 0)
988
exit (2);
989
/* calculate the orbit lengths under the automorphisms known so far */
990
for (i = 0; i < dim; ++i)
991
{
992
if (G.ng[i] > 0)
993
{
994
nH = 0;
995
for (j = i; j < dim; ++j)
996
{
997
for (k = 0; k < G.ng[j]; ++k)
998
{
999
H[nH] = G.g[j][k];
1000
++nH;
1001
}
1002
}
1003
G.ord[i] = orbitlen(fp.e[i], fp.diag[i], H, nH, V);
1004
}
1005
else
1006
G.ord[i] = 1;
1007
}
1008
free(H);
1009
/* compute the full automorphism group */
1010
autom(&G, V, F, fp, comb, bach, flags);
1011
/* print the generators of the group, which are necessary for generating */
1012
B = putgens(G, flags);
1013
n = 0;
1014
for (i = flags.STAB; i < dim; ++i)
1015
{
1016
if (G.ord[i] > 1)
1017
++n;
1018
}
1019
/* print a base to AUTO.tmp if the print-flag is set */
1020
if (flags.PRINT == 1)
1021
{
1022
outfile = fopen("AUTO.tmp", "a");
1023
fprintf(outfile, "%dx%d\n", n, dim);
1024
for (i = flags.STAB; i < dim; ++i)
1025
{
1026
if (G.ord[i] > 1)
1027
{
1028
for (j = 0; j < dim; ++j)
1029
fprintf(outfile, " %d", V.v[fp.e[i]][j]);
1030
fprintf(outfile, "\n");
1031
}
1032
}
1033
fclose(outfile);
1034
}
1035
/* print the order of the group */
1036
putord(G, flags, B);
1037
1038
1039
if (flags.BACH[0] == 1)
1040
{
1041
for (i = 0; i < flags.BACHDEP; ++i)
1042
free(bach[i].coef);
1043
free(bach);
1044
}
1045
if (flags.DEPTH > 0)
1046
{
1047
for(i=0;i<dim;i++)
1048
{
1049
for(j=0;j<=comb[i].list.n;j++)
1050
free(comb[i].coef[j]);
1051
free(comb[i].coef);
1052
for(j=0;j<=comb[i].list.n;j++)
1053
free(comb[i].list.v[j]);
1054
free(comb[i].list.v);
1055
for(j=0;j<comb[i].rank;j++)
1056
free(comb[i].trans[j]);
1057
free(comb[i].trans);
1058
for(j=0;j<F.n;j++)
1059
{
1060
for(k=0;k<comb[i].rank;k++)
1061
free(comb[i].F[j][k]);
1062
free(comb[i].F[j]);
1063
}
1064
free(comb[i].F);
1065
}
1066
free(comb);
1067
}
1068
for(i=0;i<F.n;i++)
1069
{
1070
for(j=1;j<=V.n;j++)
1071
free(F.v[i][j]);
1072
free(F.v[i]);
1073
for(j=0;j<dim;j++)
1074
free(F.A[i][j]);
1075
free(F.A[i]);
1076
}
1077
free(F.A); free(F.v);
1078
1079
/* inserted the next 3 lines 9/1/97 tilman */
1080
for (j=0;j<=V.n;j++){
1081
free(V.v[j]);
1082
}
1083
1084
free(V.v);
1085
free_perp_matrices(dim);
1086
free(fp.diag); free(fp.per); free(fp.e);
1087
for(i=0;i<dim;i++)
1088
{
1089
for(j=0;j<G.ng[i];j++)
1090
{
1091
for(k=0;k<dim;k++)
1092
free(G.g[i][j][k]);
1093
free(G.g[i][j]);
1094
}
1095
free(G.g[i]);
1096
}
1097
free(G.g); free(G.ord); free(G.ng); free(G.nsg);
1098
1099
return(B);
1100
}
1101
1102