/**************************************************************************** ** *A map_relations.c ANUPQ source Eamonn O'Brien ** *Y Copyright 1995-2001, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany *Y Copyright 1995-2001, School of Mathematical Sciences, ANU, Australia ** */ #include "pq_defs.h" #include "pcp_vars.h" #include "pga_vars.h" #include "menus.h" #include "constants.h" #include "pq_functions.h" #if defined(STANDARD_PCP) #define POWER -100 #undef COMMUTATOR #define COMMUTATOR -200 static Logical is_ident(int *map, int i, int lastg); static Logical is_identity_map(int **map, int ndgen, int lastg); static int length_of_image(int gen, Logical *defn, int **map, struct pcp_vars *pcp); static void print_image_under_aut(FILE *present, int *preimage, int gen, Logical *defn, int **map, struct pcp_vars *pcp); static void print_definition(FILE *present, int *preimage, int gen, int *definition, struct pcp_vars *pcp); /* modify the stored relations under the action of the standard automorphism and print out the result -- this code is complex as a result of two problems: a. the "strange" form in which definitions of group generators are returned -- see note on "commutator" below; b. the need to meet the limitations imposed by the input routines of pq */ /* find the structure of pcp generator gen and store it in definition */ static void find_structure(int gen, int *definition, struct pcp_vars *pcp) { register int *y = y_address; register int structure = pcp->structure; register int lastg = pcp->lastg; /* register int u; */ register int v; register int i; int weight; int pointer; #include "access.h" pointer = y[structure + gen]; weight = WT(pointer); for (i = 1; i <= lastg; ++i) y[pcp->lused + i] = 0; /*u = PART2(pointer);*/ v = PART3(pointer); find_definition(gen, pcp->lused, weight, pcp); if (v == 0) { definition[0] = POWER; #if defined(DEBUG) printf("%d is defined on %d^%d = ", gen, u, pcp->p); #endif } else { #if defined(DEBUG) printf("%d is defined on [%d, %d] = ", gen, u, v); #endif definition[0] = COMMUTATOR; } for (i = 1; i <= weight; ++i) definition[i] = y[pcp->lused + i]; #if defined(DEBUG) for (i = 1; i <= weight; ++i) if (definition[i] != 0) printf("%d ", definition[i]); printf("\n"); #endif } /* print the defining relations of the group after applying the standard automorphism described in map */ void map_relations(int **map, struct pga_vars *pga, struct pcp_vars *pcp) { register int *y = y_address; register int ndgen = pcp->ndgen; register int ndrel = pcp->ndrel; register int lastg = pcp->lastg; register int relp = pcp->relp; register int dgen = pcp->dgen; register int generator; int *definition; register int i, j, k, l; register int pointer, length; int exp, absgen; FILE *present; Logical *defn; int *preimage = 0; int *image; Logical identity_map; /* write out the basic information */ present = OpenFile("ISOM_present", "w+"); fprintf(present, "1\n"); fprintf(present, "prime %d\n", pcp->p); fprintf(present, "class %d\n", pcp->cc); fprintf(present, "output %d\n", MIN_PRINT); if (pcp->extra_relations != 0) fprintf(present, "exponent %d\n", pcp->extra_relations); if (pcp->metabelian == TRUE) fprintf(present, "metabelian\n"); fprintf(present, "generators {"); /* if the map is the identity, then we need only the existing generators and relations */ if ((identity_map = is_identity_map(map, pga->ndgen, lastg))) { #if defined(DEBUG) printf("map is the identity map\n"); #endif for (i = 1; i <= ndgen; ++i) fprintf(present, "x%d, ", i); } else { defn = allocate_vector(lastg, 1, TRUE); preimage = allocate_vector(lastg, 1, TRUE); image = allocate_vector(ndgen, 1, TRUE); /* identify which defining generators map to which pcp generators of the Frattini quotient; two arrays are stored as follows -- preimage[i] = defining generator j image[k] = pcp generator l */ for (i = 1; i <= pga->ndgen; ++i) { for (j = 1; j <= ndgen && y[dgen + j] != i; ++j) ; if (j > ndgen) { printf("Error in map_relations\n"); exit(FAILURE); } preimage[i] = j; image[j] = i; } /* do we need to introduce new generators? */ for (i = 1; i <= pga->ndgen; ++i) { fprintf(present, "y%d, ", i); preimage[i] = 0; /* if (is_ident (map[i], i, lastg)) { fprintf (present, "x%d, ", preimage[i]); image[ preimage[i] ] = -i; } else { fprintf (present, "y%d, ", i); preimage[i] = 0; } */ } #if defined(DEBUG) printf("The correspondences are \n"); print_array(preimage, 1, pcp->lastg + 1); print_array(image, 1, ndgen + 1); #endif /* which pcp generators turn up in the image of the pcp generators of the Frattini quotient? */ for (i = 1; i <= pga->ndgen; ++i) length_of_image(i, defn, map, pcp); /* what are the new defining generators needed for new presentation? */ for (i = y[pcp->clend + 1] + 1; i <= lastg; ++i) if (defn[i] == TRUE) fprintf(present, "y%d, ", i); /* print the remaining defining generators for the new presentation */ for (i = 1; i <= ndgen; ++i) { if (image[i] >= 0) fprintf(present, "x%d, ", i); } } fprintf(present, "}\n"); #if defined(DEBUG) printf("First the generators\n"); printf("\nNow the relations\n"); #endif /* print the existing relations */ if (ndrel == 0) fprintf(present, " ;\n"); else fprintf(present, "relations {\n"); for (k = 1; k <= ndrel; ++k) { for (l = 1; l <= 2; ++l) { i = (k - 1) * 2 + l; pointer = y[relp + i]; length = y[pointer]; if (length > 1) { if (l == 2) fprintf(present, " = "); exp = y[pointer + 1]; if (exp != 1) fprintf(present, "("); for (i = 2; i <= length; ++i) { generator = y[pointer + i]; absgen = abs(generator); fprintf(present, "x%d", absgen); if (absgen != generator) fprintf(present, "^-1"); if (i != length) fprintf(present, " * "); } if (exp != 1) fprintf(present, ")^%d", exp); } else if ((length = abs(length)) > 1) { if (l == 2) fprintf(present, " = "); fprintf(present, "["); for (i = 2; i <= length; ++i) { generator = y[pointer + i]; generator = y[pointer + i]; absgen = abs(generator); fprintf(present, "x%d", absgen); if (absgen != generator) fprintf(present, "^-1"); if (i != length) fprintf(present, ", "); } fprintf(present, "]"); if ((exp = y[pointer + 1]) != 1) fprintf(present, "^%d", exp); } if (l == 2) { fprintf(present, ",\n"); } } } /* now print the mappings of the defining generators */ if (identity_map == FALSE) { for (i = 1; i <= pga->ndgen; ++i) { /* if (!is_ident (map[i], i, lastg)) { */ /* j = preimage[i]; */ for (j = 1; j <= ndgen && y[dgen + j] != i; ++j) ; fprintf(present, "x%d = ", j); print_image_under_aut(present, preimage, i, defn, map, pcp); fprintf(present, ",\n"); /* } */ } #if defined(DEBUG) printf("the required pcp definitions are "); print_array(defn, 1, 1 + lastg); #endif definition = allocate_vector(pcp->cc + 1, 0, FALSE); for (i = y[pcp->clend + 1] + 1; i <= lastg; ++i) if (defn[i] == TRUE) { /* look up and print the structure of the pcp generator i */ find_structure(i, definition, pcp); print_definition(present, preimage, i, definition, pcp); } free_vector(definition, 0); free_vector(preimage, 1); free_vector(image, 1); free_vector(defn, 1); } if (ndrel != 0) fprintf(present, "};\n"); CloseFile(present); } /* is pcp generator i mapped to the identity? its image is supplied as map */ static Logical is_ident(int *map, int i, int lastg) { register int j; Logical identity = TRUE; j = 1; while (j <= lastg && identity) { identity = (i == j) ? map[j] == 1 : map[j] == 0; ++j; } return identity; } /* is the map the identity on the pcp generators of the Frattini quotient */ static Logical is_identity_map(int **map, int ndgen, int lastg) { Logical identity = TRUE; register int i; i = 1; while (i <= ndgen && (identity = is_ident(map[i], i, lastg))) ++i; return identity; } /* find length of image of gen under map */ static int length_of_image(int gen, Logical *defn, int **map, struct pcp_vars *pcp) { register int lastg = pcp->lastg; register int i; int non_zero = 0; for (i = 1; i <= lastg; ++i) { if (map[gen][i] != 0) { defn[i] = TRUE; ++non_zero; } } return non_zero; } /* print image of gen under map */ static void print_image_under_aut(FILE *present, int *preimage, int gen, Logical *defn, int **map, struct pcp_vars *pcp) { register int lastg = pcp->lastg; register int i; int non_zero; int nmr_printed = 0; int preim, value; char *s; non_zero = length_of_image(gen, defn, map, pcp); assert(preimage); assert(defn); assert(map); for (i = 1; i <= lastg; ++i) { if (map[gen][i] == 0) continue; ++nmr_printed; preim = preimage[i]; s = (preim != 0) ? "x" : "y"; value = (preim != 0) ? preim : i; fprintf(present, "%s%d", s, value); if (map[gen][i] != 1) fprintf(present, "^%d", map[gen][i]); if (nmr_printed != non_zero) fprintf(present, " * "); } } /* print definition of pcp generator, gen */ static void print_definition(FILE *present, int *preimage, int gen, int *definition, struct pcp_vars *pcp) { register int *y = y_address; register int start = y[pcp->clend + 1] + 1; register int exponent; register int limit; register int i; int power, m, root = 0; Logical first; char *s; int r; #include "access.h" fprintf(present, "y%d = ", gen); if (gen < start) { fprintf(present, "y%d", gen); } else { /* replace generator by its definition */ if (definition[0] == POWER) { power = 0; first = TRUE; limit = WT(y[pcp->structure + gen]); for (m = 1; m <= limit; ++m) { if (definition[m] != 0) { ++power; if (first) { root = definition[m]; first = FALSE; } } } exponent = int_power(pcp->p, power - 1); s = preimage[root] != 0 ? "x" : "y"; r = preimage[root] != 0 ? preimage[root] : root; fprintf(present, "%s%d^%d", s, r, exponent); } if (definition[0] == COMMUTATOR) { /* a "commutator" definition may be of the sort [b, ..., b, a, a, a] where there are k occurrences of the first term, b; in fact, this corresponds to a definition [b^(p^(k - 1)), a, a, a]; we must first check to see if this is the case */ power = 1; root = definition[1]; limit = WT(y[pcp->structure + gen]); for (i = 2; i < limit && root == definition[i]; ++i) ++power; exponent = int_power(pcp->p, power - 1); fprintf(present, "["); s = preimage[root] != 0 ? "x" : "y"; r = preimage[root] != 0 ? preimage[root] : root; if (exponent != 1) fprintf(present, "%s%d^%d,", s, r, exponent); else fprintf(present, "%s%d,", s, r); for (m = i; m <= limit; ++m) { root = definition[m]; s = preimage[root] != 0 ? "x" : "y"; r = preimage[root] != 0 ? preimage[root] : root; fprintf(present, " %s%d", s, r); if (m != limit) fprintf(present, ","); else fprintf(present, "]"); } } fprintf(present, ",\n"); } } #endif