1 /****************************************************************************
2 **
3 *A map_relations.c ANUPQ source Eamonn O'Brien
4 **
5 *Y Copyright 1995-2001, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
6 *Y Copyright 1995-2001, School of Mathematical Sciences, ANU, Australia
7 **
8 */
9
10 #include "pq_defs.h"
11 #include "pcp_vars.h"
12 #include "pga_vars.h"
13 #include "menus.h"
14 #include "constants.h"
15 #include "pq_functions.h"
16
17 #if defined(STANDARD_PCP)
18
19 #define POWER -100
20 #undef COMMUTATOR
21 #define COMMUTATOR -200
22
23
24 static Logical is_ident(int *map, int i, int lastg);
25 static Logical is_identity_map(int **map, int ndgen, int lastg);
26 static int
27 length_of_image(int gen, Logical *defn, int **map, struct pcp_vars *pcp);
28 static void print_image_under_aut(FILE *present,
29 int *preimage,
30 int gen,
31 Logical *defn,
32 int **map,
33 struct pcp_vars *pcp);
34 static void print_definition(FILE *present,
35 int *preimage,
36 int gen,
37 int *definition,
38 struct pcp_vars *pcp);
39
40
41 /* modify the stored relations under the action of the standard
42 automorphism and print out the result -- this code is complex
43 as a result of two problems:
44
45 a. the "strange" form in which definitions of group generators
46 are returned -- see note on "commutator" below;
47
48 b. the need to meet the limitations imposed by the input routines of pq */
49
50 /* find the structure of pcp generator gen and store it in definition */
51
find_structure(int gen,int * definition,struct pcp_vars * pcp)52 static void find_structure(int gen, int *definition, struct pcp_vars *pcp)
53 {
54 register int *y = y_address;
55
56 register int structure = pcp->structure;
57 register int lastg = pcp->lastg;
58 /* register int u; */
59 register int v;
60 register int i;
61 int weight;
62 int pointer;
63
64 #include "access.h"
65
66 pointer = y[structure + gen];
67 weight = WT(pointer);
68
69 for (i = 1; i <= lastg; ++i)
70 y[pcp->lused + i] = 0;
71
72 /*u = PART2(pointer);*/
73 v = PART3(pointer);
74 find_definition(gen, pcp->lused, weight, pcp);
75
76 if (v == 0) {
77 definition[0] = POWER;
78 #if defined(DEBUG)
79 printf("%d is defined on %d^%d = ", gen, u, pcp->p);
80 #endif
81 } else {
82 #if defined(DEBUG)
83 printf("%d is defined on [%d, %d] = ", gen, u, v);
84 #endif
85 definition[0] = COMMUTATOR;
86 }
87
88 for (i = 1; i <= weight; ++i)
89 definition[i] = y[pcp->lused + i];
90
91 #if defined(DEBUG)
92 for (i = 1; i <= weight; ++i)
93 if (definition[i] != 0)
94 printf("%d ", definition[i]);
95 printf("\n");
96 #endif
97 }
98
99 /* print the defining relations of the group after applying
100 the standard automorphism described in map */
101
map_relations(int ** map,struct pga_vars * pga,struct pcp_vars * pcp)102 void map_relations(int **map, struct pga_vars *pga, struct pcp_vars *pcp)
103 {
104 register int *y = y_address;
105
106 register int ndgen = pcp->ndgen;
107 register int ndrel = pcp->ndrel;
108 register int lastg = pcp->lastg;
109 register int relp = pcp->relp;
110 register int dgen = pcp->dgen;
111 register int generator;
112 int *definition;
113 register int i, j, k, l;
114 register int pointer, length;
115 int exp, absgen;
116 FILE *present;
117 Logical *defn;
118 int *preimage = 0;
119 int *image;
120 Logical identity_map;
121
122 /* write out the basic information */
123 present = OpenFile("ISOM_present", "w+");
124 fprintf(present, "1\n");
125 fprintf(present, "prime %d\n", pcp->p);
126 fprintf(present, "class %d\n", pcp->cc);
127 fprintf(present, "output %d\n", MIN_PRINT);
128 if (pcp->extra_relations != 0)
129 fprintf(present, "exponent %d\n", pcp->extra_relations);
130 if (pcp->metabelian == TRUE)
131 fprintf(present, "metabelian\n");
132
133 fprintf(present, "generators {");
134
135 /* if the map is the identity, then we need only
136 the existing generators and relations */
137
138 if ((identity_map = is_identity_map(map, pga->ndgen, lastg))) {
139 #if defined(DEBUG)
140 printf("map is the identity map\n");
141 #endif
142 for (i = 1; i <= ndgen; ++i)
143 fprintf(present, "x%d, ", i);
144 } else {
145 defn = allocate_vector(lastg, 1, TRUE);
146 preimage = allocate_vector(lastg, 1, TRUE);
147 image = allocate_vector(ndgen, 1, TRUE);
148
149 /* identify which defining generators map to which pcp generators
150 of the Frattini quotient; two arrays are stored as follows --
151
152 preimage[i] = defining generator j
153 image[k] = pcp generator l */
154
155 for (i = 1; i <= pga->ndgen; ++i) {
156 for (j = 1; j <= ndgen && y[dgen + j] != i; ++j)
157 ;
158 if (j > ndgen) {
159 printf("Error in map_relations\n");
160 exit(FAILURE);
161 }
162 preimage[i] = j;
163 image[j] = i;
164 }
165
166 /* do we need to introduce new generators? */
167
168 for (i = 1; i <= pga->ndgen; ++i) {
169 fprintf(present, "y%d, ", i);
170 preimage[i] = 0;
171 /*
172 if (is_ident (map[i], i, lastg)) {
173 fprintf (present, "x%d, ", preimage[i]);
174 image[ preimage[i] ] = -i;
175 }
176 else {
177 fprintf (present, "y%d, ", i);
178 preimage[i] = 0;
179 }
180 */
181 }
182
183 #if defined(DEBUG)
184 printf("The correspondences are \n");
185 print_array(preimage, 1, pcp->lastg + 1);
186 print_array(image, 1, ndgen + 1);
187 #endif
188
189 /* which pcp generators turn up in the image of the
190 pcp generators of the Frattini quotient? */
191 for (i = 1; i <= pga->ndgen; ++i)
192 length_of_image(i, defn, map, pcp);
193
194 /* what are the new defining generators needed for new presentation? */
195
196 for (i = y[pcp->clend + 1] + 1; i <= lastg; ++i)
197 if (defn[i] == TRUE)
198 fprintf(present, "y%d, ", i);
199
200 /* print the remaining defining generators for the new presentation */
201 for (i = 1; i <= ndgen; ++i) {
202 if (image[i] >= 0)
203 fprintf(present, "x%d, ", i);
204 }
205 }
206
207 fprintf(present, "}\n");
208
209 #if defined(DEBUG)
210 printf("First the generators\n");
211 printf("\nNow the relations\n");
212 #endif
213
214 /* print the existing relations */
215
216 if (ndrel == 0)
217 fprintf(present, " ;\n");
218 else
219 fprintf(present, "relations {\n");
220
221 for (k = 1; k <= ndrel; ++k) {
222 for (l = 1; l <= 2; ++l) {
223 i = (k - 1) * 2 + l;
224 pointer = y[relp + i];
225 length = y[pointer];
226 if (length > 1) {
227 if (l == 2)
228 fprintf(present, " = ");
229 exp = y[pointer + 1];
230 if (exp != 1)
231 fprintf(present, "(");
232 for (i = 2; i <= length; ++i) {
233 generator = y[pointer + i];
234 absgen = abs(generator);
235 fprintf(present, "x%d", absgen);
236 if (absgen != generator)
237 fprintf(present, "^-1");
238 if (i != length)
239 fprintf(present, " * ");
240 }
241 if (exp != 1)
242 fprintf(present, ")^%d", exp);
243 } else if ((length = abs(length)) > 1) {
244 if (l == 2)
245 fprintf(present, " = ");
246 fprintf(present, "[");
247 for (i = 2; i <= length; ++i) {
248 generator = y[pointer + i];
249 generator = y[pointer + i];
250 absgen = abs(generator);
251 fprintf(present, "x%d", absgen);
252 if (absgen != generator)
253 fprintf(present, "^-1");
254 if (i != length)
255 fprintf(present, ", ");
256 }
257 fprintf(present, "]");
258 if ((exp = y[pointer + 1]) != 1)
259 fprintf(present, "^%d", exp);
260 }
261 if (l == 2) {
262 fprintf(present, ",\n");
263 }
264 }
265 }
266
267 /* now print the mappings of the defining generators */
268
269 if (identity_map == FALSE) {
270 for (i = 1; i <= pga->ndgen; ++i) {
271 /*
272 if (!is_ident (map[i], i, lastg)) {
273 */
274 /* j = preimage[i]; */
275 for (j = 1; j <= ndgen && y[dgen + j] != i; ++j)
276 ;
277
278 fprintf(present, "x%d = ", j);
279 print_image_under_aut(present, preimage, i, defn, map, pcp);
280 fprintf(present, ",\n");
281 /*
282 }
283 */
284 }
285
286 #if defined(DEBUG)
287 printf("the required pcp definitions are ");
288 print_array(defn, 1, 1 + lastg);
289 #endif
290
291 definition = allocate_vector(pcp->cc + 1, 0, FALSE);
292 for (i = y[pcp->clend + 1] + 1; i <= lastg; ++i)
293 if (defn[i] == TRUE) {
294 /* look up and print the structure of the pcp generator i */
295 find_structure(i, definition, pcp);
296 print_definition(present, preimage, i, definition, pcp);
297 }
298
299 free_vector(definition, 0);
300 free_vector(preimage, 1);
301 free_vector(image, 1);
302 free_vector(defn, 1);
303 }
304
305 if (ndrel != 0)
306 fprintf(present, "};\n");
307
308 CloseFile(present);
309 }
310
311 /* is pcp generator i mapped to the identity? its image is supplied as map */
312
is_ident(int * map,int i,int lastg)313 static Logical is_ident(int *map, int i, int lastg)
314 {
315 register int j;
316 Logical identity = TRUE;
317
318 j = 1;
319 while (j <= lastg && identity) {
320 identity = (i == j) ? map[j] == 1 : map[j] == 0;
321 ++j;
322 }
323 return identity;
324 }
325
326 /* is the map the identity on the pcp generators of the Frattini quotient */
327
is_identity_map(int ** map,int ndgen,int lastg)328 static Logical is_identity_map(int **map, int ndgen, int lastg)
329 {
330 Logical identity = TRUE;
331 register int i;
332
333 i = 1;
334 while (i <= ndgen && (identity = is_ident(map[i], i, lastg)))
335 ++i;
336
337 return identity;
338 }
339
340 /* find length of image of gen under map */
341
342 static int
length_of_image(int gen,Logical * defn,int ** map,struct pcp_vars * pcp)343 length_of_image(int gen, Logical *defn, int **map, struct pcp_vars *pcp)
344 {
345 register int lastg = pcp->lastg;
346 register int i;
347 int non_zero = 0;
348
349 for (i = 1; i <= lastg; ++i) {
350 if (map[gen][i] != 0) {
351 defn[i] = TRUE;
352 ++non_zero;
353 }
354 }
355
356 return non_zero;
357 }
358
359 /* print image of gen under map */
360
print_image_under_aut(FILE * present,int * preimage,int gen,Logical * defn,int ** map,struct pcp_vars * pcp)361 static void print_image_under_aut(FILE *present,
362 int *preimage,
363 int gen,
364 Logical *defn,
365 int **map,
366 struct pcp_vars *pcp)
367 {
368 register int lastg = pcp->lastg;
369 register int i;
370 int non_zero;
371 int nmr_printed = 0;
372 int preim, value;
373 char *s;
374
375 non_zero = length_of_image(gen, defn, map, pcp);
376
377 assert(preimage);
378 assert(defn);
379 assert(map);
380
381 for (i = 1; i <= lastg; ++i) {
382 if (map[gen][i] == 0)
383 continue;
384 ++nmr_printed;
385
386 preim = preimage[i];
387 s = (preim != 0) ? "x" : "y";
388 value = (preim != 0) ? preim : i;
389
390 fprintf(present, "%s%d", s, value);
391 if (map[gen][i] != 1)
392 fprintf(present, "^%d", map[gen][i]);
393
394 if (nmr_printed != non_zero)
395 fprintf(present, " * ");
396 }
397 }
398
399 /* print definition of pcp generator, gen */
400
print_definition(FILE * present,int * preimage,int gen,int * definition,struct pcp_vars * pcp)401 static void print_definition(FILE *present,
402 int *preimage,
403 int gen,
404 int *definition,
405 struct pcp_vars *pcp)
406 {
407 register int *y = y_address;
408
409 register int start = y[pcp->clend + 1] + 1;
410 register int exponent;
411 register int limit;
412 register int i;
413 int power, m, root = 0;
414 Logical first;
415 char *s;
416 int r;
417 #include "access.h"
418
419 fprintf(present, "y%d = ", gen);
420
421 if (gen < start) {
422 fprintf(present, "y%d", gen);
423 } else {
424 /* replace generator by its definition */
425 if (definition[0] == POWER) {
426 power = 0;
427 first = TRUE;
428 limit = WT(y[pcp->structure + gen]);
429 for (m = 1; m <= limit; ++m) {
430 if (definition[m] != 0) {
431 ++power;
432 if (first) {
433 root = definition[m];
434 first = FALSE;
435 }
436 }
437 }
438 exponent = int_power(pcp->p, power - 1);
439
440 s = preimage[root] != 0 ? "x" : "y";
441 r = preimage[root] != 0 ? preimage[root] : root;
442 fprintf(present, "%s%d^%d", s, r, exponent);
443 }
444 if (definition[0] == COMMUTATOR) {
445
446 /* a "commutator" definition may be of the sort
447 [b, ..., b, a, a, a] where there are k occurrences
448 of the first term, b; in fact, this corresponds to
449 a definition [b^(p^(k - 1)), a, a, a]; we must first
450 check to see if this is the case */
451
452 power = 1;
453 root = definition[1];
454 limit = WT(y[pcp->structure + gen]);
455 for (i = 2; i < limit && root == definition[i]; ++i)
456 ++power;
457 exponent = int_power(pcp->p, power - 1);
458 fprintf(present, "[");
459 s = preimage[root] != 0 ? "x" : "y";
460 r = preimage[root] != 0 ? preimage[root] : root;
461 if (exponent != 1)
462 fprintf(present, "%s%d^%d,", s, r, exponent);
463 else
464 fprintf(present, "%s%d,", s, r);
465
466 for (m = i; m <= limit; ++m) {
467 root = definition[m];
468 s = preimage[root] != 0 ? "x" : "y";
469 r = preimage[root] != 0 ? preimage[root] : root;
470 fprintf(present, " %s%d", s, r);
471 if (m != limit)
472 fprintf(present, ",");
473 else
474 fprintf(present, "]");
475 }
476 }
477 fprintf(present, ",\n");
478 }
479 }
480 #endif
481