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

563637 views
1
#include "typedef.h"
2
#include "voronoi.h"
3
#include "reduction.h"
4
#include "autgrp.h"
5
#include "bravais.h"
6
#include "symm.h"
7
#include "getput.h"
8
#include "matrix.h"
9
#include "longtools.h"
10
#include "polyeder.h"
11
#include "tools.h"
12
#include "sort.h"
13
#include "longtools.h"
14
15
extern int INFO_LEVEL;
16
17
int max_diagonal_entry(matrix_TYP *A)
18
/* returns the entry |A[i][i]| such that |A[i][i]| >= |A[j][j]| for all j */
19
{
20
int max=0,
21
i;
22
23
if (A->cols != A->rows){
24
printf("error in max_diagonal_entry\n");
25
exit(3);
26
}
27
28
for (i=0;i<A->cols;i++){
29
if ((max==0) || (max < abs(A->array.SZ[i][i]))){
30
max = abs(A->array.SZ[i][i]);
31
}
32
}
33
34
return max;
35
}
36
37
matrix_TYP *extends_to_isometry(
38
matrix_TYP **hforms,matrix_TYP *HSV,int anz_hneighbours,
39
matrix_TYP **gforms,matrix_TYP *GSV,int anz_gneighbours,
40
int fdim,int offset)
41
/* the situation is as follows:
42
the matrices hform and gform are isometric, now looks whther
43
we can find an isometry which transforms the set hneighbours
44
do the set gneighbours */
45
{
46
matrix_TYP *erg=NULL,
47
*tmp;
48
49
int i=offset;
50
51
if (INFO_LEVEL & 12){
52
fprintf(stderr,"entering extends_to_isometry\n");
53
}
54
if (anz_hneighbours != anz_gneighbours){
55
fprintf(stderr,"WARNING IN extends_to_isometry: different number\n");
56
fprintf(stderr," of forms.\n");
57
}
58
59
while ((erg==NULL) && (i<anz_hneighbours)){
60
/* swap the i-th entry of gneighbours to the offset-th entry */
61
tmp = gforms[offset];
62
gforms[offset] = gforms[i];
63
gforms[i] = tmp;
64
65
/* test whether this setting is possible at all */
66
tmp = isometry(hforms,gforms,offset+1,HSV,GSV,NULL,0,NULL);
67
68
if (tmp!=NULL){
69
/* changed 16.10.01 tilman: the first condition is wrong, because
70
it uses properties of the direction (i.e. to be a base of the
71
space of invariant form) which they do not fullfill */
72
/* if ((offset<(fdim-1)) && (offset < (anz_hneighbours - 2))){*/
73
if (offset < (anz_hneighbours - 2)){
74
/* do the recursion */
75
free_mat(tmp);
76
erg = extends_to_isometry(hforms,HSV,anz_hneighbours,
77
gforms,GSV,anz_gneighbours,fdim,offset+1);
78
}
79
else{
80
erg = tmp;
81
}
82
}
83
84
/* swap back */
85
tmp = gforms[i];
86
gforms[i] = gforms[offset];
87
gforms[offset] = tmp;
88
i++;
89
}
90
91
return erg;
92
}
93
94
95
int neighbours(matrix_TYP ***perf,bravais_TYP *G,matrix_TYP **Ftr,
96
matrix_TYP *tr_bifo,matrix_TYP *SV,int min)
97
{
98
int i,j,k,l, Fdim, Gdim;
99
int lc, rc, g,
100
min_x;
101
int Pmin, Vanz, Wanz;
102
103
matrix_TYP **V,
104
*N,
105
*P, /* the G-perfect form */
106
*X;
107
polyeder_TYP *pol;
108
wall_TYP **W;
109
int *ww, *pw;
110
111
/* initial settings */
112
P = perf[0][0];
113
114
Fdim = G->form_no;
115
Gdim = G->form[0]->cols;
116
/**********************************************************************\
117
| calculate the vertices of the Voronoidomain in F(G^{tr})
118
| and the forms in F(G) corresponding to the walls of the Voronoidomain.
119
| The coordinates of these forms with respect to the basis given in G->form
120
| are obtained as the coordinates of the vetrices of the polyeder_TYP *pol.
121
\**********************************************************************/
122
V = voronoi_vertices(P, G, &Vanz, &Pmin, &i);
123
Wanz = Vanz;
124
if( (W = (wall_TYP **)malloc(Wanz *sizeof(wall_TYP *))) == NULL)
125
{
126
printf("malloc of W failed in neighbours\n");
127
exit(2);
128
}
129
if( (ww = (int *)malloc(Fdim *sizeof(int))) == NULL)
130
{
131
printf("malloc of ww failed in neighbours\n");
132
exit(2);
133
}
134
if( (pw = (int *)malloc(Fdim *sizeof(int))) == NULL)
135
{
136
printf("malloc of pw failed in neighbours\n");
137
exit(2);
138
}
139
for(i=0;i<Vanz;i++)
140
{
141
W[i] = init_wall(Fdim);
142
form_to_vec(ww, V[i], Ftr, Fdim, &k);
143
for(j=0;j<Fdim; j++)
144
for(k=0;k<Fdim; k++)
145
W[i]->gl[j] += ww[k] * tr_bifo->array.SZ[j][k];
146
normal_wall(W[i]);
147
free_mat(V[i]);
148
}
149
free(V);
150
pol = first_polyeder(W, Wanz);
151
if(pol == NULL)
152
{
153
printf("Error in neighbours: P not G-perfekt\n");
154
exit(3);
155
}
156
for(i=0;i<Wanz;i++)
157
{
158
refine_polyeder(pol, W[i]);
159
free_wall(&W[i]);
160
}
161
free(W);
162
163
/*
164
put_polyeder(pol);
165
*/
166
167
/******************************************************************\
168
| Each G-perfect form A, that is a neighbour of P, is (up to
169
| multiplication with a positive scalar) given by
170
| N = lc *P + rc * X,
171
| where X is a form defined by a vertex of the polyeder pol.
172
| The coefficients are calculated with the function 'voronoi_neighbour'.
173
\******************************************************************/
174
form_to_vec(pw, P, G->form, Fdim, &k);
175
176
/* getting memory for the result */
177
perf[0] = (matrix_TYP **) realloc(perf[0],(pol->vert_no + 1)
178
* sizeof(matrix_TYP *));
179
180
X = init_mat(Gdim, Gdim, "");
181
X->flags.Integral = X->flags.Symmetric = TRUE;
182
X->flags.Diagonal = FALSE;
183
184
for(i=0;i<pol->vert_no;i++)
185
{
186
/******************************************************\
187
| Calculate X
188
\******************************************************/
189
for(j=0;j<Gdim;j++)
190
for(k=0;k<=j;k++)
191
{
192
X->array.SZ[j][k] = 0;
193
for(l=0;l<Fdim;l++)
194
X->array.SZ[j][k] +=pol->vert[i]->v[l] * G->form[l]->array.SZ[j][k];
195
X->array.SZ[k][j] = X->array.SZ[j][k];
196
}
197
N = voronoi_neighbour(P, X, Pmin, &lc, &rc);
198
199
if(N != NULL){
200
perf[0][i+1] = N;
201
}
202
else{
203
/* we got a blind direction here */
204
/* so the neighbour in this sense is the intersection of the
205
boundary of the cone with the line through P with slope
206
X */
207
N = scal_pr(SV,X,TRUE);
208
min_x = N->array.SZ[0][0];
209
for (j=0;j<N->rows;j++){
210
if (N->array.SZ[j][j] < min_x) min_x = N->array.SZ[j][j];
211
}
212
perf[0][i+1] = imat_add(P,X,min_x,min);
213
free_mat(N);
214
}
215
216
/* divide this result by the gcd of all entries */
217
g = perf[0][i+1]->array.SZ[0][0];
218
for (j=0;j<perf[0][i+1]->rows;j++){
219
for (k=0;k<perf[0][i+1]->cols;k++){
220
g = GGT(perf[0][i+1]->array.SZ[j][k],g);
221
}
222
}
223
for (j=0;j<perf[0][i+1]->rows;j++){
224
for (k=0;k<perf[0][i+1]->cols;k++){
225
perf[0][i+1]->array.SZ[j][k] = perf[0][i+1]->array.SZ[j][k]/g;
226
}
227
}
228
}
229
230
free_mat(X);
231
free(pw);
232
free(ww);
233
/*********************************
234
put_polyeder(pol);
235
***********************************/
236
237
/* changed 14.04.99 to save this variable from being freed, it
238
causes trouble on some machines */
239
i = pol->vert_no;
240
free_polyeder(pol);
241
242
/* return the number of neighbours */
243
return i;
244
245
}
246
247
void transform_pair(bravais_TYP *H,bravais_TYP *Htr,matrix_TYP *x)
248
{
249
int i;
250
251
matrix_TYP *xi,
252
*xitr,
253
*xtr,
254
*tmp;
255
256
Check_mat(x);
257
xi=long_mat_inv(x);
258
xitr=tr_pose(xi);
259
xtr=tr_pose(x);
260
261
if (INFO_LEVEL & 4){
262
put_mat(x,NULL,"x",2);
263
put_mat(xtr,NULL,"xtr",2);
264
put_mat(xi,NULL,"xi",2);
265
put_mat(xitr,NULL,"xitr",2);
266
}
267
268
/* firstly transform H->gen */
269
for (i=0;i<H->gen_no;i++){
270
tmp = mat_mul(xitr,H->gen[i]);
271
free_mat(H->gen[i]);
272
H->gen[i] = mat_mul(tmp,xtr);
273
free_mat(tmp);
274
}
275
276
/* now transform Htr->gen */
277
for (i=0;i<Htr->gen_no;i++){
278
tmp = mat_mul(x,Htr->gen[i]);
279
free_mat(Htr->gen[i]);
280
Htr->gen[i] = mat_mul(tmp,xi);
281
free_mat(tmp);
282
}
283
284
/* now transform H->form */
285
for (i=0;i<H->form_no;i++){
286
tmp = mat_mul(x,H->form[i]);
287
free_mat(H->form[i]);
288
H->form[i] = mat_mul(tmp,xtr);
289
free_mat(tmp);
290
}
291
292
/* now transform Htr->form */
293
for (i=0;i<Htr->form_no;i++){
294
tmp = mat_mul(xitr,Htr->form[i]);
295
free_mat(Htr->form[i]);
296
Htr->form[i] = mat_mul(tmp,xi);
297
free_mat(tmp);
298
}
299
300
/* old version
301
tmp = konj_bravais(Htr,x);
302
tmp = konj_bravais(H,xitr); */
303
304
/* inserted: tilman 26.08.98 to get a better
305
basis for the formspace of H,Htr */
306
long_rein_formspace(H->form,H->form_no,1);
307
long_rein_formspace(Htr->form,Htr->form_no,1);
308
309
free_mat(xtr);
310
free_mat(xi);
311
free_mat(xitr);
312
313
return;
314
315
}
316
317
matrix_TYP *is_z_equivalent(bravais_TYP *G,bravais_TYP *G_tr,
318
bravais_TYP *H,bravais_TYP *H_tr)
319
/* IMPORTANT: G,H HAVE TO BE BRAVAIS-GROUPS!!!!,
320
AND G_tr, H_tr HAVE TO BE THE TRANSPOSED GROUPS OF G,H RESP.
321
This function returns an integral matrix A such that G^A = H, if
322
such a matrix exists. Otherwise NULL is returned */
323
{
324
int i,
325
j,
326
dim,
327
epsilon = 101,
328
ming,
329
minh,
330
prime = 1949,
331
anz_gperfect,
332
anz_hneighbours,
333
anz_gneighbours,
334
max; /* will hold the maximal diagonal entry of a form */
335
336
voronoi_TYP **gp; /* normalizer returns a list of all
337
perfect forms via a voronoi_TYP */
338
339
bravais_TYP *GB; /* the bravais group of G, for temporary purposes */
340
341
matrix_TYP *gtrbifo, /* the tracebifo of G,G_tr */
342
*htrbifo, /* the tracebifo of H,H_tr */
343
*tmp,
344
*tmp2,
345
*id,
346
*gperfect, /* will hold ONE G-perfect form modulo the
347
operation of the normalizer */
348
*hperfect, /* will hold ONE H-perfect form */
349
*HSV, /* will hold the short vectors of hperfect */
350
*GSV,
351
**hneighbours, /* holds all neighbours of hperfect */
352
**gneighbours,
353
*h_pair=NULL, /* h will be transformed in a way such that
354
we get a "nice" basis of the formspace */
355
*conj; /* the matrix that conjugates these both groups,
356
if this exists */
357
358
if (INFO_LEVEL & 4){
359
fprintf(stderr,"Entered is_z_equivalent\n");
360
}
361
362
dim = G->dim;
363
364
/* checking all the trivialities */
365
if (G->dim != H->dim){
366
conj = NULL;
367
if (INFO_LEVEL & 4){
368
fprintf(stderr,"the groups don't even live in the same universe\n");
369
}
370
}
371
else if(G->form_no != H->form_no){
372
conj = NULL;
373
if (INFO_LEVEL & 4){
374
fprintf(stderr,"the groups are not conjugated\n");
375
fprintf(stderr,"Dimension of the Formspace of G: %d\n",G->form_no);
376
fprintf(stderr,"Dimension of the Formspace of H: %d\n",H->form_no);
377
}
378
}
379
/* the order is an criterion if it's known */
380
else if((G->order != H->order) && (G->order !=0) && (H->order !=0)){
381
conj = NULL;
382
if (INFO_LEVEL & 4){
383
fprintf(stderr,"the groups are not conjugated\n");
384
fprintf(stderr,"Order of G: %d\n",G->order);
385
fprintf(stderr,"Order of H: %d\n",H->order);
386
}
387
}
388
else{
389
/* now start the real bussiness */
390
391
/* firstly calculate the trace_bifo for G,H */
392
gtrbifo = trace_bifo(G->form,G_tr->form,G->form_no);
393
htrbifo = trace_bifo(H->form,H_tr->form,H->form_no);
394
395
/* inserted tilman 30.5.97 */
396
for (i=0;i<G->form_no;i++){
397
Check_mat(G->form[i]);
398
Check_mat(H->form[i]);
399
}
400
401
/* output for debugging
402
put_mat(gtrbifo,NULL,"gtrbifo",2);
403
put_mat(htrbifo,NULL,"htrbifo",2); */
404
405
/* the two trace bifos should have the same elementary devisors */
406
tmp = long_elt_mat(NULL,gtrbifo,NULL);
407
tmp2 = long_elt_mat(NULL,htrbifo,NULL);
408
409
if (mat_comp(tmp,tmp2) == 0){
410
free_mat(tmp);
411
free_mat(tmp2);
412
413
id = init_mat(dim,dim,"1");
414
415
if (INFO_LEVEL & 4){
416
fprintf(stderr,"\n");
417
}
418
419
/* now calculate one G-perfect form */
420
tmp = rform(G->gen,G->gen_no,id,epsilon);
421
gperfect = first_perfect(tmp,G,G_tr->form,gtrbifo,&ming);
422
free_mat(tmp);
423
424
/* now calculate one H-perfect form, and the short vectors
425
of it */
426
tmp = rform(H->gen,H->gen_no,id,epsilon);
427
hperfect = first_perfect(tmp,H,H_tr->form,htrbifo,&minh);
428
free_mat(tmp);
429
430
/* reduce H by pair_reduction, and transform H_tr accordingly */
431
h_pair = init_mat(H->dim,H->dim,"1");
432
tmp = pair_red(hperfect,h_pair);
433
free_mat(hperfect);
434
435
transform_pair(H,H_tr,h_pair);
436
437
free_mat(htrbifo);
438
htrbifo = trace_bifo(H->form,H_tr->form,H->form_no);
439
hperfect = first_perfect(tmp,H,H_tr->form,htrbifo,&minh);
440
free_mat(tmp);
441
442
max = max_diagonal_entry(hperfect);
443
HSV = short_vectors(hperfect,max,0,0,0,&i);
444
445
if (INFO_LEVEL & 4){
446
fprintf(stderr,"Got perfect forms for G and H.\n");
447
}
448
449
/* output for debugging */
450
if (INFO_LEVEL & 4){
451
put_mat(hperfect,NULL,"hperfect",2);
452
put_mat(htrbifo,NULL,"htrbifo",2);
453
printf("maximaler diagonaleintrag von hperfect %d\n",max);
454
}
455
456
/* now calculate all perfect neigbours of hperfect */
457
hneighbours = (matrix_TYP **) malloc(sizeof(matrix_TYP *));
458
hneighbours[0] = hperfect;
459
anz_hneighbours = neighbours(&hneighbours,H,H_tr->form,htrbifo,
460
HSV,minh);
461
462
if (INFO_LEVEL & 4){
463
fprintf(stderr,"Calculated the neighbours of hperfect.\n");
464
}
465
466
GB = bravais_group(G,TRUE);
467
/* and calculate all G-perfect forms which represent the orbit
468
of the normalizer on them, i.e. the quotient graph */
469
gp = normalizer(gperfect,GB,G_tr,prime,&anz_gperfect);
470
G->normal = GB->normal; G->normal_no = GB->normal_no;
471
GB->normal = NULL; GB->normal_no = 0;
472
free_bravais(GB);
473
474
if (INFO_LEVEL & 4){
475
fprintf(stderr,"Calculated the normalizer of G.\n");
476
}
477
478
/* now search for a G-perfect form which is isometric to the
479
H-perfect form and all of its neighbours are also */
480
conj = NULL;
481
i = 0;
482
while ((i<anz_gperfect) && (conj == NULL)){
483
484
/* calculate the short vectors of the G-perfect form in question */
485
GSV = short_vectors(gp[i]->gram,max,0,0,0,&j);
486
487
/* let's see whether there is an isometry between this form
488
and hperfect */
489
conj = isometry(&hperfect,&gp[i]->gram,1,HSV,GSV,NULL,0,NULL);
490
491
if (INFO_LEVEL & 4){
492
fprintf(stderr,"calculating isometries\n");
493
fprintf(stderr,"%d-th of %d\n",i+1,anz_gperfect);
494
if (conj!=NULL){
495
fprintf(stderr,"found a new isometry.\n");
496
put_mat(conj,NULL,"conj",2);
497
put_mat(hperfect,NULL,"hperfect",2);
498
put_mat(gp[i]->gram,NULL,"gp[i]->gram",2);
499
}
500
}
501
502
/* output for debugging
503
put_mat(hperfect,NULL,"hperfect",2);
504
put_mat(gp[i]->gram,NULL,"gp[i]->gram",2);
505
put_mat(conj,NULL,"conj",2);
506
put_mat(HSV,NULL,"HSV",2);
507
put_mat(GSV,NULL,"GSV",2); */
508
509
if (conj != NULL){
510
/* there is an isometry, let's see whether it respects the
511
neighbours also */
512
/* now calculate all perfect neigbours of hperfect */
513
gneighbours = (matrix_TYP **) malloc(sizeof(matrix_TYP));
514
gneighbours[0] = gp[i]->gram;
515
anz_gneighbours = neighbours(&gneighbours,G,G_tr->form,gtrbifo,
516
GSV,ming);
517
518
free_mat(conj);
519
conj = NULL;
520
521
if (anz_hneighbours == anz_gneighbours){
522
523
if (INFO_LEVEL & 4){
524
printf("anz_hneighbours %d\n",anz_hneighbours);
525
for (j=0;j<=anz_hneighbours;j++){
526
put_mat(hneighbours[j],NULL,"hneighbours[j]",2);
527
put_mat(gneighbours[j],NULL,"gneighbours[j]",2);
528
}
529
}
530
531
conj = extends_to_isometry(hneighbours,HSV,
532
anz_hneighbours+1,gneighbours,GSV,
533
anz_gneighbours+1,H->form_no,1);
534
535
536
}
537
/* cleaning up memory */
538
for (j=0;j<anz_gneighbours;j++){
539
free_mat(gneighbours[j+1]);
540
}
541
free(gneighbours);
542
543
}
544
545
free_mat(GSV);
546
i++;
547
}
548
549
/* clean up memory used only here */
550
free_mat(id);
551
free_mat(hperfect);
552
free_mat(gperfect);
553
free_mat(HSV);
554
for (i=0;i<anz_gperfect;i++){
555
clear_voronoi(gp[i]);
556
free(gp[i]);
557
}
558
free(gp);
559
for (i=0;i<anz_hneighbours;i++){
560
free_mat(hneighbours[i+1]);
561
}
562
free(hneighbours);
563
564
}
565
else{
566
/* the groups are not conjugated, so clean up the memory used
567
so far and return NULL */
568
if (INFO_LEVEL & 4){
569
put_mat(tmp,NULL,"tmp",2);
570
put_mat(tmp2,NULL,"tmp2",2);
571
fprintf(stderr,
572
"The groups are not conjugated: elementary divisors\n");
573
}
574
free_mat(tmp);
575
free_mat(tmp2);
576
conj = NULL;
577
}
578
579
/* clean up memory used only in this stage */
580
free_mat(gtrbifo);
581
free_mat(htrbifo);
582
}
583
584
/* retransform H, H_tr to the original value, and fiddle around with
585
conj a bit */
586
if (h_pair != NULL){
587
tmp = long_mat_inv(h_pair);
588
transform_pair(H,H_tr,tmp);
589
if (conj != NULL){
590
mat_muleq(conj,h_pair);
591
}
592
free_mat(tmp);
593
free_mat(h_pair);
594
}
595
596
/* we will return the transposed matrix if there was one at all */
597
if (conj != NULL){
598
tmp = tr_pose(conj);
599
free_mat(conj);
600
conj = tmp;
601
}
602
603
return conj;
604
}
605
606