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