/****************************************************************************
**
*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
¤ Dauer der Verarbeitung: 0.6 Sekunden
¤
*© Formatika GbR, Deutschland
|
|