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

563604 views
1
/***** This file contains some routines for orbit calculations *****/
2
#include"typedef.h"
3
4
/**********************************************************************\
5
| V.v is a sorted list of length V.n of vectors
6
| of dimension V.dim, the number of V.v[nr]*A in
7
| the list is returned, where a negative number
8
| indicates the negative of a vector
9
\**********************************************************************/
10
static int operate(nr, A, V)
11
veclist V;
12
int nr, **A;
13
{
14
int i, im, *w;
15
16
if ((w = (int*)malloc(V.dim * sizeof(int))) == 0)
17
exit (2);
18
vecmatmul(V.v[abs(nr)], A, V.dim, w);
19
if (nr < 0)
20
{
21
for (i = 0; i < V.dim; ++i)
22
w[i] *= -1;
23
}
24
im = numberof(w, V);
25
if (abs(im) > V.n)
26
/* the vector is not in the list */
27
{
28
fprintf(stderr, "Error: image of vector %d not found\n", nr);
29
exit (3);
30
}
31
free(w);
32
return(im);
33
}
34
35
/**********************************************************************\
36
| computes the orbit of npt points in pt
37
| under the nG matrices in G and puts the
38
| orbit in orb, allocates the memory for
39
| orb, returns the length of the orbit,
40
| the points are the indices in the list V.v
41
\**********************************************************************/
42
static int orbit(pt, npt, G, nG, V, orb)
43
veclist V;
44
int *pt, npt, ***G, nG, **orb;
45
{
46
int i, norb, cnd, im, *flag;
47
48
if ((*orb = (int*)malloc(npt * sizeof(int))) == 0)
49
exit (2);
50
/* if flag[i + V.n] = 1, then the point i is already in the orbit */
51
if ((flag = (int*)malloc((2*V.n + 1) * sizeof(int))) == 0)
52
exit (2);
53
for (i = 0; i <= 2*V.n; ++i)
54
flag[i] = 0;
55
for (i = 0; i < npt; ++i)
56
{
57
(*orb)[i] = pt[i];
58
flag[pt[i]+V.n] = 1;
59
}
60
norb = npt;
61
cnd = 0;
62
while (cnd < norb)
63
{
64
for (i = 0; i < nG; ++i)
65
{
66
im = operate((*orb)[cnd], G[i], V);
67
if (flag[im+V.n] == 0)
68
/* the image is a new point in the orbit */
69
{
70
++norb;
71
if ((*orb = (int*)realloc(*orb, norb * sizeof(int))) == 0)
72
exit (2);
73
(*orb)[norb-1] = im;
74
flag[im+V.n] = 1;
75
}
76
}
77
++cnd;
78
}
79
free(flag);
80
return(norb);
81
}
82
83
/**********************************************************************\
84
| checks, whether the orbit of pt under
85
| the nG matrices in G has at least length orblen
86
\**********************************************************************/
87
static int orbitlen(pt, orblen, G, nG, V)
88
veclist V;
89
int pt, orblen, ***G, nG;
90
{
91
int i, len, cnd, im, *orb, *flag;
92
93
if ((orb = (int*)malloc(orblen * sizeof(int))) == 0)
94
exit(2);
95
/* if flag[i + V.n] = 1, then the point i is already in the orbit */
96
if ((flag = (int*)malloc((2*V.n + 1) * sizeof(int))) == 0)
97
exit(2);
98
for (i = 0; i <= 2*V.n; ++i)
99
flag[i] = 0;
100
orb[0] = pt;
101
flag[pt+V.n] = 1;
102
for (i = 1; i < orblen; ++i)
103
orb[i] = 0;
104
len = 1;
105
cnd = 0;
106
while (cnd < len && len < orblen)
107
{
108
for (i = 0; i < nG && len < orblen; ++i)
109
{
110
im = operate(orb[cnd], G[i], V);
111
if (flag[im+V.n] == 0)
112
/* the image is a new point in the orbit */
113
{
114
orb[len] = im;
115
++len;
116
flag[im+V.n] = 1;
117
}
118
}
119
++cnd;
120
}
121
free(orb);
122
free(flag);
123
return(len);
124
}
125
126
/**********************************************************************\
127
| deletes the elements in orb2 from orb1,
128
| an entry 0 marks the end of the list, returns the length of orb1
129
\**********************************************************************/
130
static int delete(orb1, l1, orb2, l2)
131
int *orb1, l1, *orb2, l2;
132
{
133
int i, j, len, o2i;
134
135
/* the true length of orb1 is len, hence orb1[len-1] != 0 */
136
for (i = 0; i < l1 && orb1[i] != 0; ++i);
137
len = i;
138
for (i = 0; i < l2 && orb2[i] != 0; ++i)
139
{
140
o2i = orb2[i];
141
for (j = 0; j < len && orb1[j] != o2i; ++j);
142
/* orb1[j] = orb2[i], hence delete orb1[j] from orb1 */
143
if (j < len)
144
{
145
orb1[j] = orb1[len-1];
146
orb1[len-1] = 0;
147
--len;
148
}
149
}
150
return(len);
151
}
152
153
/**********************************************************************\
154
| computes the orbit of fp.e[I] under the
155
| generators in G->g[I]...G->g[n-1] and elements
156
| stabilizing fp.e[I],
157
| has some heuristic break conditions,
158
| the generators in G->g[i] stabilize
159
| fp.e[0]...fp.e[i-1] but not fp.e[i],
160
| G->ng[i] is the number of generators in G->g[i],
161
| the first G->nsg[i] of which are elements which
162
| are obtained as stabilizer elements in
163
| <G->g[0],...,G->g[i-1]>, G->ord[i] is the orbit
164
| length of fp.e[i] under <G->g[i],...,G->g[n-1]>
165
\**********************************************************************/
166
static void stab(I, G, fp, V)
167
group *G;
168
fpstruct fp;
169
veclist V;
170
{
171
int *orb, len, cnd, tmplen;
172
int **w, *flag, ***H, ***Hj, **S, **tmp, ***Ggj;
173
int i, j, k, l, dim, im, nH, nHj, fail;
174
int Maxfail, Rest;
175
176
/* some heuristic break conditions for the computation of stabilizer elements:
177
it would be too expensive to calculate all the stabilizer generators, which
178
are obtained from the orbit, since this is highly redundant,
179
on the other hand every new generator which enlarges the group is much
180
cheaper than one obtained from the backtrack,
181
after Maxfail subsequent stabilizer elements, that do not enlarge the group,
182
Rest more elements are calculated even if they leave the group unchanged,
183
since it turned out that this is often useful in the following steps,
184
increasing the parameters will possibly decrease the number of generators
185
for the group, but will increase the running time,
186
there is no magic behind this heuristic, tuning might be appropriate */
187
dim = V.dim;
188
Rest = 0;
189
for (i = I; i < dim; ++i)
190
{
191
if (fp.diag[i] > 1 && G->ord[i] < fp.diag[i])
192
++Rest;
193
}
194
Maxfail = Rest;
195
for (i = 0; i < dim; ++i)
196
{
197
if (fp.diag[i] > 1)
198
++Maxfail;
199
}
200
nH = 0;
201
for (i = I; i < dim; ++i)
202
nH += G->ng[i];
203
/* H are the generators of the group in which the stabilizer is computed */
204
if ((H = (int***)malloc(nH * sizeof(int**))) == 0)
205
exit (2);
206
if ((Hj = (int***)malloc((nH+1) * sizeof(int**))) == 0)
207
exit (2);
208
k = 0;
209
for (i = I; i < dim; ++i)
210
{
211
for (j = 0; j < G->ng[i]; ++j)
212
{
213
H[k] = G->g[i][j];
214
++k;
215
}
216
}
217
/* in w[V.n+i] an element is stored that maps fp.e[I] on v[i] */
218
if ((w = (int**)malloc((2*V.n+1) * sizeof(int*))) == 0)
219
exit (2);
220
/* orb contains the orbit of fp.e[I] */
221
if ((orb = (int*)malloc(2*V.n * sizeof(int))) == 0)
222
exit (2);
223
for (i = 0; i < 2*V.n; ++i)
224
orb[i] = 0;
225
/* if flag[i + V.n] = 1, then the point i is already in the orbit */
226
if ((flag = (int*)malloc((2*V.n+1) * sizeof(int))) == 0)
227
exit (2);
228
for (i = 0; i <= 2*V.n; ++i)
229
flag[i] = 0;
230
/* S is a matrix to hold a stabilizer element temporarily */
231
if ((S = (int**)malloc(dim * sizeof(int*))) == 0)
232
exit (2);
233
for (i = 0; i < dim; ++i)
234
{
235
if ((S[i] = (int*)malloc(dim * sizeof(int))) == 0)
236
exit (2);
237
}
238
orb[0] = fp.e[I];
239
flag[orb[0]+V.n] = 1;
240
if ((w[orb[0]+V.n] = (int*)malloc(dim * sizeof(int))) == 0)
241
exit (2);
242
for (i = 0; i < dim; ++i)
243
w[orb[0]+V.n][i] = fp.e[i];
244
cnd = 0;
245
len = 1;
246
/* fail is the number of successive failures */
247
fail = 0;
248
while (len > cnd && fail < Maxfail+Rest)
249
{
250
for (i = 0; i < nH && fail < Maxfail+Rest; ++i)
251
{
252
if (fail >= Maxfail)
253
/* there have already been Maxfail successive failures, now a random generator
254
is applied to a random point of the orbit to get Rest more stabilizer
255
elements */
256
{
257
cnd = rand() % len;
258
if (cnd < 0)
259
cnd += len;
260
i = rand() % nH;
261
if (i < 0)
262
i += nH;
263
}
264
im = operate(orb[cnd], H[i], V);
265
if (flag[im+V.n] == 0)
266
/* a new element is found, appended to the orbit and an element mapping
267
fp.e[I] to im is stored in w[im+V.n] */
268
{
269
orb[len] = im;
270
flag[im+V.n] = 1;
271
if ((w[im+V.n] = (int*)malloc(dim * sizeof(int))) == 0)
272
exit (2);
273
for (j = 0; j < dim; ++j)
274
w[im+V.n][j] = operate(w[orb[cnd]+V.n][j], H[i], V);
275
++len;
276
}
277
else
278
/* the image was already in the orbit */
279
{
280
/* j is the first index where the images of the old and the new element
281
mapping e[I] on im differ */
282
for (j = I; j < dim && operate(w[orb[cnd]+V.n][j], H[i], V) == w[im+V.n][j]; ++j);
283
if (j < dim &&
284
(G->ord[j] < fp.diag[j] || fail >= Maxfail))
285
{
286
/* new stabilizer element S = w[orb[cnd]+V.n] * H[i] * (w[im+V.n])^-1 */
287
stabil(S, w[orb[cnd]+V.n], w[im+V.n], fp.per, H[i], V);
288
Hj[0] = S;
289
nHj = 1;
290
for (k = j; k < dim; ++k)
291
{
292
for (l = 0; l < G->ng[k]; ++l)
293
{
294
Hj[nHj] = G->g[k][l];
295
++nHj;
296
}
297
}
298
tmplen = orbitlen(fp.e[j], fp.diag[j], Hj, nHj, V);
299
if (tmplen > G->ord[j] || fail >= Maxfail)
300
/* the new stabilizer element S enlarges the orbit of e[j] */
301
{
302
++G->ng[j];
303
++G->nsg[j];
304
/* allocate memory for the new generator */
305
if ((G->g[j] = (int***)realloc(G->g[j], G->ng[j] * sizeof(int**))) == 0)
306
exit (2);
307
if ((G->g[j][G->ng[j]-1] = (int**)malloc(dim * sizeof(int*))) == 0)
308
exit (2);
309
for (k = 0; k < dim; ++k)
310
{
311
if ((G->g[j][G->ng[j]-1][k] = (int*)malloc(dim * sizeof(int))) == 0)
312
exit (2);
313
}
314
Ggj = G->g[j];
315
/* the new generator is inserted as stabilizer element nr. nsg[j]-1 */
316
for (k = G->ng[j]-1; k >= G->nsg[j]; --k)
317
{
318
tmp = Ggj[k];
319
Ggj[k] = Ggj[k-1];
320
Ggj[k-1] = tmp;
321
}
322
for (k = 0; k < dim; ++k)
323
{
324
for (l = 0; l < dim; ++l)
325
Ggj[G->nsg[j]-1][k][l] = S[k][l];
326
}
327
G->ord[j] = tmplen;
328
++nH;
329
if ((H = (int***)realloc(H, nH * sizeof(int**))) == 0)
330
exit (2);
331
if ((Hj = (int***)realloc(Hj, (nH+1) * sizeof(int**))) == 0)
332
exit (2);
333
/* the new generator is appended to H */
334
H[nH-1] = Ggj[G->nsg[j]-1];
335
/* the number of failures is reset to 0 */
336
if (fail < Maxfail)
337
fail = 0;
338
else
339
++fail;
340
}
341
else
342
/* the new stabilizer element S does not enlarge the orbit of e[j] */
343
++fail;
344
}
345
else if (j < dim && fail < Maxfail ||
346
j == dim && fail >= Maxfail)
347
++fail;
348
/* if S is the identity and fail < Maxfail, nothing is done */
349
}
350
}
351
if (fail < Maxfail)
352
++cnd;
353
}
354
for (i = 0; i <= 2*V.n; ++i)
355
{
356
if (flag[i] == 1)
357
free(w[i]);
358
}
359
free(w);
360
for (i = 0; i < dim; ++i)
361
free(S[i]);
362
free(S);
363
free(orb);
364
free(flag);
365
free(H);
366
free(Hj);
367
}
368
369
/**********************************************************************\
370
| generates the matrix X which has as row
371
| per[i] the vector nr. x[i] from the list v
372
\**********************************************************************/
373
static void matgen(x, X, dim, per, v)
374
int *x, **X, dim, *per, **v;
375
{
376
int i, j, xi, *Xperi;
377
378
for (i = 0; i < dim; ++i)
379
{
380
Xperi = X[per[i]];
381
if ((xi = x[i]) > 0)
382
{
383
for (j = 0; j < dim; ++j)
384
Xperi[j] = v[xi][j];
385
}
386
else
387
{
388
for (j = 0; j < dim; ++j)
389
Xperi[j] = -v[-xi][j];
390
}
391
}
392
}
393
394
/**********************************************************************\
395
| x1 corresponds to an element X1 mapping some vector e on p1,
396
| x2 to an element X2 mapping e on p2 and G is a generator mapping
397
| p1 on p2, then S = X1*G*X2^-1 stabilizes e
398
\**********************************************************************/
399
static void stabil(S, x1, x2, per, G, V)
400
veclist V;
401
int **S, *x1, *x2, *per, **G;
402
{
403
int i, dim, *x, **XG, **X2;
404
405
dim = V.dim;
406
if ((XG = (int**)malloc(dim * sizeof(int*))) == 0)
407
exit (2);
408
if ((X2 = (int**)malloc(dim * sizeof(int*))) == 0)
409
exit (2);
410
for (i = 0; i < dim; ++i)
411
{
412
if ((XG[i] = (int*)malloc(dim * sizeof(int))) == 0)
413
exit (2);
414
if ((X2[i] = (int*)malloc(dim * sizeof(int))) == 0)
415
exit (2);
416
}
417
if ((x = (int*)malloc(dim * sizeof(int))) == 0)
418
exit (2);
419
for (i = 0; i < dim; ++i)
420
x[i] = operate(x1[i], G, V);
421
/* XG is the composite mapping of the matrix corresponding to x1 and G */
422
matgen(x, XG, dim, per, V.v);
423
matgen(x2, X2, dim, per, V.v);
424
/* S = XG * X2^-1 */
425
psolve(S, X2, XG, dim, V.prime);
426
free(x);
427
for (i = 0; i < dim; ++i)
428
{
429
free(XG[i]);
430
free(X2[i]);
431
}
432
free(XG);
433
free(X2);
434
}
435
436