/****************************************************************************
**
*A standard.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 "constants.h"
#include "pcp_vars.h"
#include "pga_vars.h"
#include "exp_vars.h"
#include "constants.h"
#include "pq_functions.h"
#include "menus.h"
#include "standard.h"
#if defined(GROUP) && defined(STANDARD_PCP)
static int map_array_size;
static int output;
static void enforce_exp_law(struct pcp_vars *pcp);
static int **start_pga_run(Logical *identity_map,
int ***auts,
struct pga_vars *pga,
struct pcp_vars *pcp);
static int **
group_completed(int ***auts, struct pga_vars *pga, struct pcp_vars *pcp);
static int **finish_pga_run(Logical *identity_map,
FILE *cover_tmp_file,
FILE *group_file,
int ***auts,
struct pga_vars *pga,
struct pcp_vars *pcp);
static int **find_stabiliser(Logical *identity_map,
int non_standard,
int ***auts,
int **perms,
int *a,
int *b,
char *c,
int *orbit_length,
struct pga_vars *pga,
struct pcp_vars *pcp);
static void
trace(char *word_map, int *depth, int label, int *backptr, char *schreier);
static char *find_word(int *word_length,
Logical soluble_group,
int **perms,
int rep,
int non_standard,
int orbit_length,
int *b,
char *c,
struct pga_vars *pga);
static int **standard_map(char *word_map,
int word_length,
Logical *identity_map,
int rep,
int ***auts,
struct pga_vars *pga,
struct pcp_vars *pcp);
static int inverse_image(int l, int *perms, struct pga_vars *pga);
static void list_subgroup(int rep, struct pga_vars *pga, struct pcp_vars *pcp);
/* compute a standard presentation for a group;
this procedure assumes that
-- an arbitrary finite presentation has been
supplied;
-- a standard presentation has been computed
for the class c p-quotient;
-- a presentation for the p-covering group
computed using this standard presentation has
been set up before the call to this procedure;
we will now compute the standard presentation for the
class c + 1 p-quotient */
void standard_presentation(Logical *identity_map,
int standard_output,
int ***auts,
struct pga_vars *pga,
struct pcp_vars *pcp)
{
int i;
int **map;
#if defined(TIME)
int t;
#endif
output = standard_output;
#if defined(TIME)
t = runTime();
#endif
map = start_pga_run(identity_map, auts, pga, pcp);
if (map == NULL)
return;
#if defined(TIME)
printf("time in start_pga is %.2f\n", (runTime() - t) * CLK_SCALE);
#endif
if (output == MAX_STANDARD_PRINT) {
printf("The standard automorphism is:\n");
for (i = 1; i <= pga->ndgen; ++i) {
printf("%d ---> ", i);
print_array(map[i], 1, pcp->lastg + 1);
}
}
#if defined(DEBUG)
printf("Map identity? %d\n", *identity_map);
#endif
map_relations(map, pga, pcp);
/* memory leakage September 1996 -- originally pcp->lastg */
free_matrix(map, map_array_size, 1);
}
/* enforce the exponent law, if any, on the group */
static void enforce_exp_law(struct pcp_vars *pcp)
{
register int *y = y_address;
struct exp_vars exp_flag;
if (pcp->extra_relations != 0) {
initialise_exponent(&exp_flag, pcp);
extra_relations(&exp_flag, pcp);
/* are there redundant defining generators? if so, be careful
about elimination -- see next_class for further information */
if (pcp->ndgen > y[pcp->clend + 1])
eliminate(TRUE, pcp);
else
eliminate(FALSE, pcp);
}
}
/* commence a partial run of p-group generation in order
to determine the standard presentation for this class */
static int **start_pga_run(Logical *identity_map,
int ***auts,
struct pga_vars *pga,
struct pcp_vars *pcp)
{
FILE *cover_file; /* store complete p-cover of group */
FILE *cover_tmp_file; /* store (reduced) p-cover of group */
FILE *group_file; /* store class c + 1 quotient of group */
int **map; /* automorphism to apply to presentation */
#if defined(TIME)
int t = runTime();
#endif
/* save (reduced) p-covering group presentation to temporary file */
cover_tmp_file = TemporaryFile();
save_pcp(cover_tmp_file, pcp);
RESET(cover_tmp_file);
/* we need compute the class c + 1 quotient only on the first
time through or if the map applied to the previous presentation
was not the identity; in these cases, before
computing class c + 1 quotient, restore complete p-cover;
we cannot use the reduced p-cover because a presentation having
redundant generators can cause difficulties with interaction
between update_generators and eliminate */
if (*identity_map == FALSE) {
cover_file = OpenFile("ISOM_cover_file", "r");
restore_pcp(cover_file, pcp);
CloseFile(cover_file);
/* enforce exponent law on complete p-cover */
enforce_exp_law(pcp);
/* now compute the presentation for the class c + 1 quotient */
pcp->multiplicator = FALSE;
update_generators(pcp);
collect_relations(pcp);
eliminate(FALSE, pcp);
if (pcp->overflow || !pcp->valid)
exit(FAILURE);
/* when relations are enforced, the group may complete */
if (pcp->complete) {
map = group_completed(auts, pga, pcp);
*identity_map = TRUE;
CloseFile(cover_tmp_file);
return map;
}
/* save presentation for class c + 1 quotient to file */
group_file = OpenFile("ISOM_group_file", "w+");
save_pcp(group_file, pcp);
} else {
/* we must restore the presentation to correctly determine step size */
group_file = OpenFile("ISOM_group_file", "r");
restore_pcp(group_file, pcp);
}
RESET(group_file);
#if defined(TIME)
t = runTime() - t;
printf("Time to compute class c + 1 is %.2f seconds\n", t * CLK_SCALE);
#endif
/* note step size required for p-group generation */
pga->step_size = pcp->lastg - pcp->ccbeg + 1;
map =
finish_pga_run(identity_map, cover_tmp_file, group_file, auts, pga, pcp);
CloseFile(group_file);
CloseFile(cover_tmp_file);
return map;
}
/* the group has completed when the relations are imposed; we write
necessary files in order to have consistent behaviour pattern */
static int **
group_completed(int ***auts, struct pga_vars *pga, struct pcp_vars *pcp)
{
FILE *NextClass;
FILE *Status;
int i, j, k;
int **standard;
NextClass = OpenFile("ISOM_NextClass", "w+");
fprintf(NextClass, "%d\n", pga->m);
fprintf(NextClass, "%d\n", pcp->lastg);
for (i = 1; i <= pga->m; ++i) {
for (j = 1; j <= pga->ndgen; ++j) {
for (k = 1; k <= pcp->lastg; ++k)
fprintf(NextClass, "%d ", auts[i][j][k]);
fprintf(NextClass, "\n");
}
}
fprintf(NextClass, "%d\n", pga->fixed);
fprintf(NextClass, "%d\n", pga->soluble);
#ifdef HAVE_GMP
mpz_out_str(NextClass, 10, &pga->aut_order);
fprintf(NextClass, "\n");
#endif
CloseFile(NextClass);
Status = OpenFile("ISOM_Status", "w");
fprintf(Status, "%d ", END_OF_CLASS);
fprintf(Status, "%d ", TERMINAL);
CloseFile(Status);
map_array_size = pcp->lastg;
standard = allocate_matrix(pcp->lastg, pcp->lastg, 1, FALSE);
for (i = 1; i <= pga->ndgen; ++i)
for (j = 1; j <= pcp->lastg; ++j)
standard[i][j] = (i == j) ? 1 : 0;
return standard;
}
/* complete pga run to compute standard presentation for this class */
static int **finish_pga_run(Logical *identity_map,
FILE *cover_tmp_file,
FILE *group_file,
int ***auts,
struct pga_vars *pga,
struct pcp_vars *pcp)
{
int **perms;
FILE *LINK_input = 0;
int k;
int upper_step;
Logical soluble_group;
#if defined(GAP_LINK)
Logical process_fork = FALSE; /* has GAP process forked? */
#endif
int *a;
int *b;
char *c;
int *orbit_length;
int **subgroup_matrix;
int K; /* bit string representation of definition set */
int *subset; /* definition set */
int non_standard; /* label for allowable subgroup defining
non-standard presentation */
int **map; /* automorphism to apply to presentation */
#if defined(TIME)
int t;
#endif
restore_pcp(cover_tmp_file, pcp);
RESET(cover_tmp_file);
#if defined(DEBUG)
printf("Now restore p-covering group\n");
print_presentation(FALSE, pcp);
#endif
pga->exponent_law = pcp->extra_relations;
/*
enforce_laws (pga, pga, pcp);
*/
extend_automorphisms(auts, pga->m, pcp);
/* critical */
/*
read_subgroup_rank (&k);
*/
/* if you want something other than default, change value of k */
k = 0;
step_range(k, &pga->s, &upper_step, auts, pga, pcp);
if (pga->s != upper_step) {
pga->s = upper_step;
/* first, find the valid relative step size, pga->s */
find_allowable_subgroup(
RELATIVE, cover_tmp_file, group_file, &K, &subset, pga, pcp);
}
/* now find allowable subgroup which determines the class c + 1 quotient */
subgroup_matrix = find_allowable_subgroup(
2, cover_tmp_file, group_file, &K, &subset, pga, pcp);
restore_pcp(cover_tmp_file, pcp);
RESET(cover_tmp_file);
#if defined(DEBUG)
printf("Now restore p-covering group\n");
print_presentation(FALSE, pcp);
#endif
#if defined(DEBUG)
printf("Rank of characteristic subgroup is %d\n", pga->q);
#endif
store_definition_sets(pga->r, pga->s, pga->s, pga);
get_definition_sets(pga);
#if defined(DEBUG)
pga->print_degree = TRUE;
#endif
compute_degree(pga);
pga->print_degree = FALSE;
non_standard = subgroup_to_label(subgroup_matrix, K, subset, pga);
/* memory leakage September 1996 */
free_vector(subset, 0);
free_matrix(subgroup_matrix, pga->s, 0);
if (output == MAX_STANDARD_PRINT) {
printf("Non-standard label is %d\n", non_standard);
printf("Required step size is %d\n", pga->step_size);
printf("Relative step size is %d\n", pga->s);
printf("Rank of characteristic subgroup is %d\n", pga->q);
}
strip_identities(auts, pga, pcp);
soluble_group = (pga->soluble || pga->Degree == 1 || pga->nmr_of_perms == 0);
if (!soluble_group) {
#if defined(GAP_LINK)
if (!process_fork) {
start_GAP_file(auts, pga, pcp);
process_fork = TRUE;
}
StartGapFile(pga);
#elif defined(GAP_LINK_VIA_FILE)
start_GAP_file(&LINK_input, auts, pga, pcp);
#endif
}
#if defined(DEBUG)
/*
pga->print_permutation = TRUE;
*/
#endif
#if defined(TIME)
t = runTime();
#endif
perms = permute_subgroups(LINK_input, &a, &b, &c, auts, pga, pcp);
#if defined(TIME)
t = runTime() - t;
printf("Time to compute permutations is %.2f seconds\n", t * CLK_SCALE);
#endif
orbit_option(STANDARDISE, perms, &a, &b, &c, &orbit_length, pga);
/*
printf ("orbit length is %d \n", orbit_length);
*/
#if defined(GAP_LINK_VIA_FILE)
if (!soluble_group) {
CloseFile(LINK_input);
}
#endif
map = find_stabiliser(identity_map,
non_standard,
auts,
perms,
a,
b,
c,
orbit_length,
pga,
pcp);
if (pga->final_stage && output >= DEFAULT_STANDARD_PRINT) {
printf("\nThe standard presentation for the class %d %d-quotient is\n",
pcp->cc,
pcp->p);
print_presentation(TRUE, pcp);
#ifdef HAVE_GMP
char *s = pga->upper_bound ? "at most " : "";
/* Originally pq checked the whole automorphism group.
* Now it checks only coset reps. of inner automorphisms
* i.e. those auts that are in 1-1 correspondence with outer auts. */
printf("Subset of automorphism group to check has order bound %s", s);
mpz_out_str(stdout, 10, &(pga->aut_order));
printf("\n");
#endif
}
#if defined(GAP_LINK)
if (process_fork)
QuitGap();
#endif
free_space(TRUE, perms, orbit_length, a, b, c, pga);
/* memory leakage September 1996 */
free_vector(pga->list, 0);
free_vector(pga->available, 0);
free_vector(pga->offset, 0);
return map;
}
/* find the stabiliser of the representative of the orbit which
contains the non-standard allowable subgroup */
static int **find_stabiliser(Logical *identity_map,
int non_standard,
int ***auts,
int **perms,
int *a,
int *b,
char *c,
int *orbit_length,
struct pga_vars *pga,
struct pcp_vars *pcp)
{
FILE *Status;
FILE *OutputFile;
Logical soluble_group;
int rep[2];
int length[2];
int **map;
int i;
int word_length = 0;
char *word_map;
#if defined(TIME)
int t = runTime();
#endif
soluble_group = (pga->soluble || pga->Degree == 1 || pga->nmr_of_perms == 0);
/* what is the orbit representative of non_standard? */
if (soluble_group)
rep[1] = abs(a[non_standard]);
else {
if (a[non_standard] < 0)
rep[1] = pga->rep[abs(a[non_standard])];
else
rep[1] = abs(a[non_standard]);
}
/* find the length of the orbit having this representative */
for (i = 1; i <= pga->nmr_orbits && pga->rep[i] != rep[1]; ++i)
;
if (pga->rep[i] == rep[1]) {
length[1] = orbit_length[i];
if (output == MAX_STANDARD_PRINT)
printf("The non-standard subgroup %d has orbit representative %d\n",
non_standard,
pga->rep[i]);
} else {
printf("%d is not an orbit representative\n", rep[1]);
exit(FAILURE);
}
/*
printf ("True Orbit length is %d\n", length[1]);
*/
word_map = find_word(&word_length,
soluble_group,
perms,
rep[1],
non_standard,
length[1],
b,
c,
pga);
/* now process this representative and find its stabiliser */
OutputFile = OpenFile("ISOM_XX", "w+");
pga->final_stage = (pga->q == pga->multiplicator_rank);
pga->nmr_of_descendants = 0;
pga->nmr_of_capables = 0;
pga->terminal = TRUE;
setup_reps(
rep, 1, length, perms, a, b, c, auts, OutputFile, OutputFile, pga, pcp);
/* now evaluate the action of standard map on pcp */
map = standard_map(
word_map, word_length, identity_map, rep[1], auts, pga, pcp);
#if defined(TIME)
t = runTime() - t;
printf("Time to process representative is %.2f seconds\n", t * CLK_SCALE);
#endif
RESET(OutputFile);
restore_pcp(OutputFile, pcp);
if (!pcp->complete)
last_class(pcp);
Status = OpenFile("ISOM_Status", "w");
if (pga->final_stage)
fprintf(Status, "%d ", END_OF_CLASS);
else
fprintf(Status, "%d ", MIDDLE_OF_CLASS);
if (pcp->newgen == 0)
fprintf(Status, "%d ", TERMINAL);
else
fprintf(Status, "%d ", CAPABLE);
CloseFile(Status);
CloseFile(OutputFile);
return map;
}
void trace(char *word_map, int *depth, int label, int *backptr, char *schreier)
{
if (schreier[label] != 0) {
word_map[++*depth] = schreier[label];
trace(word_map, depth, backptr[label], backptr, schreier);
}
}
/* find word in defining permutations which maps orbit representative to label;
store each component of the word of length word_length in array word */
static char *find_word(int *word_length,
Logical soluble_group,
int **perms,
int rep,
int non_standard,
int orbit_length,
int *b,
char *c,
struct pga_vars *pga)
{
int perm_number;
char *word_map;
char *word_perm;
int i, l;
char *d;
char temp;
word_map = allocate_char_vector(orbit_length, 1, FALSE);
/* we store word which maps non-standard label to orbit representative;
in image_of_generator, the word is evaluated starting from the
last letter -- hence after computing the word, we reverse it */
if (soluble_group) {
d = find_permutation(b, c, pga);
l = non_standard;
while (l != rep) {
word_map[++*word_length] = d[l];
if ((perm_number = pga->map[(int)d[l]]) != 0)
l = inverse_image(l, perms[perm_number], pga);
}
/* reverse word */
for (i = 1; i <= *word_length / 2; ++i) {
temp = word_map[i];
word_map[i] = word_map[*word_length - i + 1];
word_map[*word_length - i + 1] = temp;
}
free_char_vector(d, 1);
} else {
word_perm = allocate_char_vector(orbit_length, 1, FALSE);
trace(word_perm, word_length, non_standard, b, c);
for (i = 1; i <= *word_length; ++i)
word_map[i] = preimage(word_perm[*word_length - i + 1], pga);
free_char_vector(word_perm, 1);
}
return word_map;
}
/* compute the automorphism which maps the non-standard subgroup,
non_standard, to the orbit representative, rep; the word and
its length are supplied as word_map and word_length */
static int **standard_map(char *word_map,
int word_length,
Logical *identity_map,
int rep,
int ***auts,
struct pga_vars *pga,
struct pcp_vars *pcp)
{
register int *y = y_address;
int nmr_of_generators = y[pcp->clend + pcp->cc - 1] + pga->s;
register int pointer = pcp->lused + 1;
int cp = pcp->lused;
int **standard;
int i, j;
/* copy the word into y */
for (i = 1; i <= word_length; ++i)
y[pointer + i] = word_map[i];
free_char_vector(word_map, 1);
y[pointer] = word_length;
#if defined(DEBUG)
printf("The word is ");
print_array(y, pointer, pointer + word_length + 1);
#endif
pcp->lused += word_length + 1;
cp = pcp->lused;
map_array_size = pcp->lastg;
standard = allocate_matrix(pcp->lastg, nmr_of_generators, 1, FALSE);
if (word_length == 0) {
for (i = 1; i <= pga->ndgen; ++i)
for (j = 1; j <= nmr_of_generators; ++j)
standard[i][j] = (i == j) ? 1 : 0;
*identity_map = TRUE;
} else {
for (i = 1; i <= pga->ndgen; ++i) {
/* compute image of defining generator i under standard map */
image_of_generator(i, pointer, auts, pga, pcp);
/* copy restriction of result into standard array */
for (j = 1; j <= nmr_of_generators; ++j) {
standard[i][j] = y[cp + j];
}
}
*identity_map = FALSE;
}
y[pointer] = 0;
if (!pga->final_stage)
list_subgroup(rep, pga, pcp);
return standard;
}
/* find the image of l under the inverse of the supplied permutation */
static int inverse_image(int l, int *perms, struct pga_vars *pga)
{
register int i;
for (i = 1; i <= pga->Degree && perms[i] != l; ++i)
;
return i;
}
/* write a description of the automorphism group of the
group presented by the standard presentation to file */
void print_aut_description(int ***central,
int ***stabiliser,
struct pga_vars *pga,
struct pcp_vars *pcp)
{
FILE *NextClass;
int i, j, k;
NextClass = OpenFile("ISOM_NextClass", "w+");
fprintf(NextClass, "%d\n", pga->nmr_centrals + pga->nmr_stabilisers);
fprintf(NextClass, "%d\n", pcp->lastg);
for (i = 1; i <= pga->nmr_centrals; ++i) {
for (j = 1; j <= pga->ndgen; ++j) {
for (k = 1; k <= pcp->lastg; ++k)
fprintf(NextClass, "%d ", central[i][j][k]);
fprintf(NextClass, "\n");
}
}
for (i = 1; i <= pga->nmr_stabilisers; ++i)
for (j = 1; j <= pga->ndgen; ++j) {
for (k = 1; k <= pcp->lastg; ++k)
fprintf(NextClass, "%d ", stabiliser[i][j][k]);
fprintf(NextClass, "\n");
}
fprintf(NextClass, "%d\n", pga->fixed);
fprintf(NextClass, "%d\n", pga->soluble);
#ifdef HAVE_GMP
mpz_out_str(NextClass, 10, &pga->aut_order);
fprintf(NextClass, "\n");
#endif
CloseFile(NextClass);
}
/* list orbit representative as generators of subgroup to
factor from p-covering group */
static void list_subgroup(int rep, struct pga_vars *pga, struct pcp_vars *pcp)
{
register int lastg = pcp->lastg;
register int i, j, k;
FILE *Subgroup;
int word[MAXWORD];
int *subset;
int **S;
int index;
int length = 0;
if (pga->s == pga->q)
return;
Subgroup = OpenFile("ISOM_Subgroup", "a+");
S = label_to_subgroup(&index, &subset, rep, pga);
#if defined(DEBUG)
printf("The standard matrix is\n");
print_matrix(S, pga->s, pga->q);
#endif
for (i = 0; i < pga->q; ++i) {
if (1 << i & pga->list[index])
continue;
for (j = 1; j <= lastg; ++j)
word[j] = 0;
for (j = 0; j < pga->s; ++j)
if (S[j][i] != 0)
word[pcp->ccbeg + subset[j]] = pga->p - S[j][i];
word[pcp->ccbeg + i] = 1;
#if defined(DEBUG)
printf("The subgroup generator is ");
print_array(word, pcp->ccbeg, pcp->ccbeg + pga->q);
#endif
length = 0;
for (k = pcp->ccbeg; k <= lastg; ++k)
if (word[k] != 0)
++length;
fprintf(Subgroup, "%d\n", COLLECT);
for (k = pcp->ccbeg; k <= lastg; ++k) {
if (word[k] != 0) {
fprintf(Subgroup, "x%d^%d", k, word[k]);
if (--length != 0)
fprintf(Subgroup, " * ");
}
}
fprintf(Subgroup, ";\n");
}
/* memory leakage September 1996 */
free_matrix(S, pga->s, 0);
free_vector(subset, 0);
/* write out flag to indicate that we should now eliminate
redundant generators */
fprintf(Subgroup, "%d\n", ELIMINATE);
CloseFile(Subgroup);
}
/* for each automorphism in turn, read its actions on each
of the pcp generators of the Frattini quotient */
int ***read_auts_from_file(FILE *file, int *nmr_of_auts, struct pcp_vars *pcp)
{
register int *y = y_address;
register int i, j, k;
int ***auts;
int nmr_of_exponents, nmr_of_generators;
int nmr_items;
nmr_items = fscanf(file, "%d", nmr_of_auts);
verify_read(nmr_items, 1);
nmr_items = fscanf(file, "%d", &nmr_of_exponents);
verify_read(nmr_items, 1);
nmr_of_generators = y[pcp->clend + 1];
auts = allocate_array(*nmr_of_auts, pcp->lastg, pcp->lastg, TRUE);
for (i = 1; i <= *nmr_of_auts; ++i) {
for (j = 1; j <= nmr_of_generators; ++j) {
for (k = 1; k <= nmr_of_exponents; ++k)
nmr_items = fscanf(file, "%d", &auts[i][j][k]);
verify_read(nmr_items, 1);
}
}
return auts;
}
#endif
¤ Dauer der Verarbeitung: 0.12 Sekunden
¤
*© Formatika GbR, Deutschland
|
|