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

563665 views
1
#include"typedef.h"
2
#include"voronoi.h"
3
#include"longtools.h"
4
#include"symm.h"
5
#include"bravais.h"
6
#include"autgrp.h"
7
#include"polyeder.h"
8
#include"matrix.h"
9
#include"reduction.h"
10
#include"orbit.h"
11
#include"datei.h"
12
#include"tools.h"
13
14
/**************************************************************************\
15
@---------------------------------------------------------------------------
16
@---------------------------------------------------------------------------
17
@ FILE: calc_voronoi_data.c
18
@---------------------------------------------------------------------------
19
@---------------------------------------------------------------------------
20
@
21
\**************************************************************************/
22
23
24
/**************************************************************************\
25
@---------------------------------------------------------------------------
26
@ void calc_voronoi_basics(V, G, Gtr, prime)
27
@ voronoi_TYP *V;
28
@ bravais_TYP *G, *Gtr;
29
@ int prime;
30
@
31
@ For using this function V->gram must be a G-perfect form
32
@ The function calculates:
33
@
34
@ V->SV_no: the number of shortest vectors of V->gram.
35
@ V->min: the minimum of V->gram.
36
@ V->pdet: the determinante of V->gram modulo prime.
37
@ V->prime: = prime.
38
@ V->vert: the coordinates of the voronoi vertices with
39
@ respect to the Z-basis of the space of invariant
40
@ symmetric matrices of G^{tr} given in Gtr->form.
41
@ V->vert_no: the number of voronoi_vertices.
42
@ V->red_inv: the pair-reduced of (V->gram)^{-1} (with kgv = 1).
43
@ V->T: the matrix such that
44
@ T *(V->gram)^{-1} * T^{tr} = V->red_inv
45
@ V->Ti: the inverse matrix of V->T
46
@ V->Gtrred: the bravais_TYP obtained by konjugating Gtr with
47
@ the transposed of V->Ti with the function
48
@ 'konj_bravais'
49
@---------------------------------------------------------------------------
50
@
51
\**************************************************************************/
52
void calc_voronoi_basics(V, G, Gtr, prime)
53
voronoi_TYP *V;
54
bravais_TYP *G, *Gtr;
55
int prime;
56
{
57
int i,k;
58
int anz;
59
matrix_TYP **XX, *TTri;
60
61
XX = voronoi_vertices(V->gram, G, &anz, &V->min, &V->SV_no);
62
if(V->vert_no != 0 && V->vert != NULL)
63
{
64
for(i=0;i<V->vert_no;i++)
65
free_wall(&V->vert[i]);
66
free(V->vert);
67
}
68
V->vert_no = anz;
69
if( (V->vert = (wall_TYP **)malloc(anz *sizeof(wall_TYP *))) == NULL)
70
{
71
printf("malloc of 'V->vert' in 'calc_voronoi_data1' failed\n");
72
exit(2);
73
}
74
for(i=0; i<anz;i++)
75
{
76
V->vert[i] = init_wall(G->form_no);
77
form_to_vec(V->vert[i]->gl, XX[i], Gtr->form, Gtr->form_no, &k);
78
free_mat(XX[i]);
79
}
80
free(XX);
81
82
V->pdet = p_mat_det(V->gram, prime);
83
84
V->prime = prime;
85
if(V->red_inv == NULL)
86
{
87
V->T = init_mat(V->gram->cols, V->gram->cols, "");
88
for(i=0;i<V->gram->cols;i++)
89
V->T->array.SZ[i][i] = 1;
90
V->red_inv = pair_red_inv(V->gram, V->T);
91
V->Ti = long_mat_inv(V->T);
92
TTri = tr_pose(V->Ti);
93
V->Gtrred = konj_bravais(Gtr, TTri);
94
free_mat(TTri);
95
}
96
}
97
98
99
100
101
/**************************************************************************\
102
@---------------------------------------------------------------------------
103
@ void calc_voronoi_pol(V, bifo)
104
@ voronoi_TYP *V;
105
@
106
@ calculates the polyeder_TYP V->pol where the walls of V->pol
107
@ are the walls in 'V->vert' multiplied with the transposed of bifo,
108
@ i.e. V->vert[i] * bifo^{tr} 0 <= i <V->vert_no
109
@ is the input for 'first_polyeder' and 'refine_polyeder' used
110
@ to calculate 'V->pol'.
111
@---------------------------------------------------------------------------
112
@
113
\**************************************************************************/
114
void calc_voronoi_pol(V, bifo)
115
voronoi_TYP *V;
116
matrix_TYP *bifo;
117
{
118
int i,j,k;
119
int dim, fdim;
120
wall_TYP **W;
121
122
dim = V->gram->cols;
123
fdim = bifo->cols;
124
125
if( (W = (wall_TYP **)malloc(V->vert_no *sizeof(wall_TYP *))) == NULL)
126
{
127
printf("malloc of 'W' in 'calc_voronoi_full' failed\n");
128
exit(2);
129
}
130
for(i=0;i<V->vert_no;i++)
131
{
132
W[i] = init_wall(fdim);
133
for(j=0;j<fdim;j++)
134
for(k=0;k<fdim;k++)
135
W[i]->gl[j] += V->vert[i]->gl[k] * bifo->array.SZ[j][k];
136
}
137
V->pol = first_polyeder(W, V->vert_no);
138
for(i=0;i<V->vert_no;i++)
139
{
140
j = refine_polyeder(V->pol, W[i]);
141
142
/* tilman : changed 17/1/97 from
143
if(j == FALSE){
144
free_wall(&W[i]);
145
} to: */
146
free_wall(&W[i]);
147
}
148
free(W);
149
}
150
151
152
153
154
/**************************************************************************\
155
@---------------------------------------------------------------------------
156
@ void calc_voronoi_good_inv(V, Gtr)
157
@ voronoi_TYP *V;
158
@ bravais_TYP *Gtr;
159
@
160
@ applies 'short_red' and 'mink_red' to V->red_inv to obtain a better
161
@ form.
162
@ V->T, V->Ti and V->Gtrred are changed in the same manner as described
163
@ for 'calc_voronoi_basics'
164
@
165
@ Furthermore the shortest vectors of the better reduced form are
166
@ calculated up to the norm that equals the maximal diagonal entry
167
@ of V->red_inv.
168
@---------------------------------------------------------------------------
169
@
170
\**************************************************************************/
171
void calc_voronoi_good_inv(V, Gtr)
172
voronoi_TYP *V;
173
bravais_TYP *Gtr;
174
{
175
int i,j,maxd;
176
int dim, mr;
177
matrix_TYP *A, *T, *T1;
178
int has_changed;
179
180
dim = V->gram->cols;
181
has_changed = FALSE;
182
183
T = init_mat(dim, dim, "");
184
for(i=0;i<dim;i++)
185
T->array.SZ[i][i] = 1;
186
A = pr_short_red(V->red_inv, T);
187
maxd = V->red_inv->array.SZ[0][0];
188
for(i=1;i<dim;i++)
189
{ if(V->red_inv->array.SZ[i][i] > maxd)
190
maxd = V->red_inv->array.SZ[i][i];
191
}
192
j = A->array.SZ[0][0];
193
for(i=1;i<dim;i++)
194
{ if(A->array.SZ[i][i] > j)
195
j = A->array.SZ[i][i];
196
}
197
if(j<=maxd)
198
{
199
has_changed = TRUE;
200
T1 = mat_mul(T, V->T);
201
free_mat(V->T);
202
V->T = T1;
203
T1 = NULL;
204
free_mat(T);
205
T = NULL;
206
maxd = j;
207
free_mat(V->red_inv);
208
V->red_inv = A;
209
A = NULL;
210
}
211
else
212
free_mat(A);
213
mr = TRUE;
214
for(i=0;i<dim;i++)
215
{
216
if(V->red_inv->array.SZ[i][i] < maxd)
217
mr = FALSE;
218
}
219
if(mr == FALSE)
220
{
221
if(T == NULL)
222
T = init_mat(dim, dim, "1");
223
for(i=0;i<dim;i++)
224
{
225
for(j=0;j<dim;j++)
226
T->array.SZ[i][j] = 0;
227
T->array.SZ[i][i] = 1;
228
}
229
/* put_mat(V->red_inv, NULL, "veredinv vor minkred", 2); */
230
A = mink_red(V->red_inv, T);
231
/* put_mat(V->red_inv, NULL, "veredinv nach minkred", 2);
232
put_mat(A, NULL, "A nach minkred", 2); */
233
j = A->array.SZ[0][0];
234
for(i=1;i<dim;i++)
235
{ if(A->array.SZ[i][i] > j)
236
j = A->array.SZ[i][i];
237
}
238
if(j<=maxd)
239
{
240
has_changed = TRUE;
241
T1 = mat_mul(T, V->T);
242
free_mat(V->T);
243
V->T = T1;
244
T1 = NULL;
245
maxd = j;
246
free_mat(V->red_inv);
247
V->red_inv = A;
248
A = NULL;
249
}
250
else
251
free_mat(A);
252
}
253
254
/* changed on 14/1/97 tilman: (inserted if (..)) */
255
if (T!=NULL){
256
free_mat(T);
257
}
258
259
if(has_changed == TRUE)
260
{
261
free_mat(V->Ti);
262
V->Ti = long_mat_inv(V->T);
263
T = tr_pose(V->Ti);
264
free_bravais(V->Gtrred);
265
V->Gtrred = konj_bravais(Gtr, T);
266
free_mat(T);
267
}
268
maxd = V->red_inv->array.SZ[0][0];
269
for(i=0;i<dim;i++)
270
{
271
if(V->red_inv->array.SZ[i][i] > maxd)
272
maxd = V->red_inv->array.SZ[i][i];
273
}
274
V->SVi = short_vectors(V->red_inv, maxd, 0, 0, 0, &i);
275
}
276
277
278
279
/**************************************************************************\
280
@---------------------------------------------------------------------------
281
@ void calc_voronoi_stab(V, G, Gtr, bifo)
282
@ voronoi_TYP *V;
283
@ bravais_TYP *G, *Gtr;
284
@ matrix_TYP *bifo;
285
@
286
@ calculates a generating set for
287
@ H = { h\in GL_n(Z) | h^{tr} * V->gram * h = V->gram and
288
@ h G h^{-1} = G }
289
@
290
@ Furthermore the bravais_TYP* V->linstab is calculated, that
291
@ describes the linear action for H on the space of G-invariant
292
@ symmetric matrices with respect to the Z-basis given in
293
@ G->form (c.f. the function 'nomlin' in directory 'Bravais'
294
@---------------------------------------------------------------------------
295
@
296
\**************************************************************************/
297
void calc_voronoi_stab(V, G, Gtr, bifo)
298
voronoi_TYP *V;
299
bravais_TYP *G, *Gtr;
300
matrix_TYP *bifo;
301
{
302
303
int i,j;
304
int dim,fdim, Vanz;
305
matrix_TYP *M, **bas, *M1, **W;
306
bravais_TYP *S;
307
308
dim = V->gram->cols;
309
fdim = bifo->cols;
310
311
if(V->prime == 0)
312
calc_voronoi_basics(V, G, Gtr, 101);
313
Vanz = V->vert_no;
314
if(V->SVi == NULL)
315
calc_voronoi_good_inv(V, Gtr);
316
/*******************************************************************\
317
| calculate 'bas', a consisting of vertices given as symetric matrices
318
\*******************************************************************/
319
M = init_mat(Vanz, fdim, "");
320
for(i=0;i<Vanz;i++)
321
for(j=0;j<fdim;j++)
322
M->array.SZ[i][j] = V->vert[i]->gl[j];
323
M1 = long_qbase(M);
324
free_mat(M);
325
if(M1->rows != fdim)
326
{
327
printf("error in 'calc_voronoi_stab': form not G-perfect\n");
328
exit(3);
329
}
330
if( (bas = (matrix_TYP **)malloc(fdim *sizeof(matrix_TYP *))) == NULL)
331
{
332
printf("malloc of 'bas' in 'calc_voronoi_stab' failed\n");
333
exit(2);
334
}
335
for(i=0;i<fdim;i++)
336
bas[i] = vec_to_form(M1->array.SZ[i], V->Gtrred->form, fdim);
337
free_mat(M1);
338
339
/*******************************************************************\
340
| calculate 'W', the symmetric matrices given by the vertices in V->vert
341
\*******************************************************************/
342
if( (W = (matrix_TYP **) malloc(Vanz *sizeof(matrix_TYP *))) == NULL)
343
{
344
printf("malloc of 'W' in 'calc_voronoi_stab' failed\n");
345
exit(2);
346
}
347
for(i=0;i<Vanz;i++)
348
W[i] = vec_to_form(V->vert[i]->gl, V->Gtrred->form, fdim);
349
350
/*******************************************************************\
351
| calculate the stabilizer
352
\*******************************************************************/
353
S = perfect_normal_autgrp(V->red_inv, V->SVi, V->Gtrred->gen, Gtr->gen_no, NULL, W, Vanz, bas, fdim);
354
for(i=0;i<fdim;i++)
355
free_mat(bas[i]);
356
free(bas);
357
for(i=0;i<Vanz;i++)
358
free_mat(W[i]);
359
free(W);
360
361
V->stab = init_bravais(dim);
362
V->stab->gen_no = S->gen_no;
363
if( (V->stab->gen = (matrix_TYP **)malloc(S->gen_no *sizeof(matrix_TYP *))) == NULL)
364
{
365
printf("malloc of 'V->stab->gen' in 'cal_voronoi_stab' failed\n");
366
exit(2);
367
}
368
for(i=0;i<S->gen_no;i++)
369
{
370
M = tr_pose(S->gen[i]);
371
M1 = mat_mul(V->Ti, M);
372
V->stab->gen[i] = mat_mul(M1, V->T);
373
free_mat(M); free_mat(M1);
374
}
375
V->stab->order = S->order;
376
for(i=0;i<100;i++)
377
V->stab->divisors[i] = S->divisors[i];
378
free_bravais(S);
379
V->linstab = init_bravais(fdim);
380
if( (V->linstab->gen = (matrix_TYP **)malloc(V->stab->gen_no *sizeof(matrix_TYP *))) == NULL)
381
{
382
printf("malloc of 'V->linstab->gen' in 'calc_voronoi_stab' failed\n");
383
exit(2);
384
}
385
V->linstab->gen_no = V->stab->gen_no;
386
for(i=0;i<V->stab->gen_no;i++)
387
V->linstab->gen[i] = normlin(G->form, V->stab->gen[i], fdim);
388
}
389
390
391
392
393
/**************************************************************************\
394
@---------------------------------------------------------------------------
395
@ matrix_TYP *calc_voronoi_isometry(V1, V2, G, Gtr, bifo)
396
@ voronoi_TYP *V1, *V2;
397
@ bravais_TYP *G, *Gtr;
398
@ matrix_TYP *bifo;
399
@
400
@ calculates a matrix X in GL_N(Z) such that
401
@ X * V1->gram * X^{tr} = V2->gram and X * G * X^{-1} = G
402
@---------------------------------------------------------------------------
403
@
404
\**************************************************************************/
405
matrix_TYP *calc_voronoi_isometry(V1, V2, G, Gtr, bifo)
406
voronoi_TYP *V1, *V2;
407
bravais_TYP *G, *Gtr;
408
matrix_TYP *bifo;
409
{
410
411
int i,j;
412
int dim,fdim, Vanz;
413
matrix_TYP *M, **bas, *M1, **W;
414
matrix_TYP *SV1, *SV2;
415
matrix_TYP *X, *E;
416
voronoi_TYP *Vn1, *Vn2;
417
int md1, md2, md, permute;
418
419
dim = V1->gram->cols;
420
fdim = bifo->cols;
421
422
if(V1->prime == 0)
423
calc_voronoi_basics(V1, G, Gtr, 101);
424
if(V2->prime == 0)
425
calc_voronoi_basics(V2, G, Gtr, 101);
426
/****************************************************************\
427
| make first easy tests, if an isiometry can exist
428
\****************************************************************/
429
if(V1->prime == V2->prime && V1->pdet != V2->pdet)
430
return(NULL);
431
if(V1->min != V2->min)
432
return(NULL);
433
if(V1->SV_no != V2->SV_no)
434
return(NULL);
435
if(V1->vert_no != V2->vert_no)
436
return(NULL);
437
438
Vanz = V1->vert_no;
439
if(V1->SVi == NULL)
440
calc_voronoi_good_inv(V1, Gtr);
441
442
/*******************************************************************\
443
| Check which 'red_inv' has the smaller maximal diagonal entry
444
\*******************************************************************/
445
md1 = V1->red_inv->array.SZ[0][0];
446
md2 = V2->red_inv->array.SZ[0][0];
447
for(i=1;i<dim;i++)
448
{
449
if(V1->red_inv->array.SZ[i][i] > md1)
450
md1 = V1->red_inv->array.SZ[i][i];
451
if(V2->red_inv->array.SZ[i][i] > md2)
452
md2 = V2->red_inv->array.SZ[i][i];
453
}
454
if(md2 < md1)
455
{ permute = TRUE; md = md2; Vn1 = V2; Vn2 = V1;}
456
else
457
{ permute = FALSE; md = md1; Vn1 = V1; Vn2 = V2;}
458
459
/*******************************************************************\
460
| calculate the shortest_vectors
461
\*******************************************************************/
462
if(Vn1->SVi != NULL)
463
SV1 = Vn1->SVi;
464
else
465
SV1 = short_vectors(Vn1->red_inv, md, 0, 0, 0, &i);
466
SV2 = short_vectors(Vn2->red_inv, md, 0, 0, 0, &j);
467
if(SV1->rows != SV2->rows)
468
{
469
if(Vn1->SVi == NULL)
470
free_mat(SV1);
471
free_mat(SV2);
472
/* printf("HIER\n"); */
473
return(NULL);
474
}
475
476
477
/*******************************************************************\
478
| calculate 'bas', a basis consisting of vertices of Vn2
479
| given as symmetric matrices
480
\*******************************************************************/
481
M = init_mat(Vanz, fdim, "");
482
for(i=0;i<Vanz;i++)
483
for(j=0;j<fdim;j++)
484
M->array.SZ[i][j] = Vn2->vert[i]->gl[j];
485
M1 = long_qbase(M);
486
free_mat(M);
487
if(M1->rows != fdim)
488
{
489
printf("error in 'calc_voronoi_stab': form not G-perfect\n");
490
exit(3);
491
}
492
if( (bas = (matrix_TYP **)malloc(fdim *sizeof(matrix_TYP *))) == NULL)
493
{
494
printf("malloc of 'bas' in 'calc_voronoi_stab' failed\n");
495
exit(2);
496
}
497
for(i=0;i<fdim;i++)
498
bas[i] = vec_to_form(M1->array.SZ[i], Vn2->Gtrred->form, fdim);
499
free_mat(M1);
500
501
/*******************************************************************\
502
| calculate 'W', the symmetric matrices given by the vertices
503
| in Vn1->vert
504
\*******************************************************************/
505
if( (W = (matrix_TYP **) malloc(Vanz *sizeof(matrix_TYP *))) == NULL)
506
{
507
printf("malloc of 'W' in 'calc_voronoi_stab' failed\n");
508
exit(2);
509
}
510
for(i=0;i<Vanz;i++)
511
W[i] = vec_to_form(Vn1->vert[i]->gl, Vn1->Gtrred->form, fdim);
512
513
/*******************************************************************\
514
| calculate an isometry
515
\*******************************************************************/
516
517
/* output for debugging
518
put_mat(Vn1->red_inv,NULL,"Vn1->redinv",2);
519
put_mat(Vn2->red_inv,NULL,"Vn2->redinv",2);
520
put_mat(SV1,NULL,"SV1",2);
521
put_mat(SV2,NULL,"SV2",2); */
522
523
524
X = perfect_normal_isometry(Vn1->red_inv, Vn2->red_inv, SV1, SV2,
525
NULL, 0, NULL, W, Vanz, bas, fdim);
526
for(i=0;i<fdim;i++)
527
free_mat(bas[i]);
528
free(bas);
529
for(i=0;i<Vanz;i++)
530
free_mat(W[i]);
531
free(W);
532
if(Vn1->SVi == NULL)
533
free_mat(SV1);
534
free_mat(SV2);
535
536
if(X != NULL)
537
{
538
M = long_mat_inv(X);
539
M1 = mat_mul(Vn1->Ti, M);
540
E = mat_mul(M1, Vn2->T);
541
free_mat(M1); free_mat(M);
542
if(permute == TRUE)
543
{
544
M = long_mat_inv(E);
545
free_mat(E);
546
E = M;
547
M = NULL;
548
}
549
free_mat(X);
550
}
551
else
552
E = NULL;
553
return(E);
554
}
555
556
557
558
/**************************************************************************\
559
@---------------------------------------------------------------------------
560
@ void calc_voronoi_dir_reps(V, G, Gtr, bifo)
561
@ voronoi_TYP *V;
562
@ bravais_TYP *G, *Gtr;
563
@ matrix_TYP *bifo;
564
@
565
@ calculates representatives of the orbits of V->stab on the
566
@ Voronoi-directions given in V->pol->vert.
567
@ The representatives are stored in V->dir_reps in the following way
568
@ V->dir_reps->cols is the number of representatives.
569
@ Each column discribes a representatives
570
@ The integer in the first row describs the number of the representative,
571
@ i.e. V->dir_reps->array.SZ[0][i] = k means that V->pol->vert[k]
572
@ is a representative of the i-th orbit.
573
@ The entry in the second row is the length of the orbit.
574
@ The third row is allocated in 'normalizer', where repesentatives
575
@ V[0],...,V[t] of the G-perfect forms are calculated
576
@ V->dir_reps->array.SZ[2][i] = k means, that V is a neighbour of
577
@ V[k] and the Voronoi-direction from V to V[k] is the one
578
@ given in the first row.
579
@---------------------------------------------------------------------------
580
@
581
\**************************************************************************/
582
void calc_voronoi_dir_reps(V, G, Gtr, bifo)
583
voronoi_TYP *V;
584
bravais_TYP *G, *Gtr;
585
matrix_TYP *bifo;
586
{
587
int i,j;
588
matrix_TYP **M;
589
int fdim;
590
int opt[5], orb_no;
591
592
fdim = G->form_no;
593
opt[0] = 1;
594
for(i=1;i<5;i++)
595
opt[i] = 0;
596
if(V->prime == 0)
597
calc_voronoi_basics(V, G, Gtr, 101);
598
if(V->stab == NULL)
599
calc_voronoi_stab(V, G, Gtr, bifo);
600
if(V->pol == NULL)
601
calc_voronoi_pol(V, bifo);
602
if( (M = (matrix_TYP **) malloc(V->pol->vert_no *sizeof(matrix_TYP *))) == NULL)
603
{
604
printf("malloc of 'M' in 'calc_voronoi_dir_reps' failed\n");
605
exit(2);
606
}
607
for(i=0;i<V->pol->vert_no;i++)
608
{
609
M[i] = init_mat(1, fdim, "");
610
for(j=0;j<fdim;j++)
611
M[i]->array.SZ[0][j] = V->pol->vert[i]->v[j];
612
}
613
V->dir_reps = orbit_representatives(M, V->pol->vert_no, V->linstab, opt, &orb_no, 0);
614
for(i=0;i<V->pol->vert_no;i++)
615
free_mat(M[i]);
616
free(M);
617
}
618
619
620
621
/**************************************************************************\
622
@---------------------------------------------------------------------------
623
@ void calc_voronoi_complete(V, G, Gtr, bifo, prime)
624
@ voronoi_TYP *V;
625
@ bravais_TYP *G, *Gtr;
626
@ matrix_TYP *bifo;
627
@ int prime;
628
@
629
@ applies:
630
@ calc_voronoi_basics(V, G, Gtr, prime);
631
@ calc_voronoi_pol(V, bifo);
632
@ calc_voronoi_good_inv(V, Gtr);
633
@ calc_voronoi_stab(V, G, Gtr, bifo);
634
@ calc_voronoi_dir_reps(V, G, Gtr, bifo);
635
@---------------------------------------------------------------------------
636
@
637
\**************************************************************************/
638
void calc_voronoi_complete(V, G, Gtr, bifo, prime)
639
voronoi_TYP *V;
640
bravais_TYP *G, *Gtr;
641
matrix_TYP *bifo;
642
int prime;
643
{
644
calc_voronoi_basics(V, G, Gtr, prime);
645
calc_voronoi_pol(V, bifo);
646
calc_voronoi_good_inv(V, Gtr);
647
calc_voronoi_stab(V, G, Gtr, bifo);
648
calc_voronoi_dir_reps(V, G, Gtr, bifo);
649
}
650
651