/****************************************************************************
**
*A isom_options.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 "constants.h"
#include "pq_defs.h"
#include "pretty_filterfns.h"
#include "standard.h"
#include "menus.h"
#include "pcp_vars.h"
#include "pga_vars.h"
#include "pq_functions.h"
#include "word_types.h"
#if defined(GROUP)
#if defined(STANDARD_PCP)
static Logical setup_start_info(Logical identity_map,
Logical status,
FILE *file,
int format,
struct pga_vars *pga,
struct pcp_vars *pcp);
static Logical compare_sequences(int *s, int *t, int length);
static char FileBuffer[1024];
static void copy_file(const char *from, const char *to)
{
FILE *in;
FILE *out;
int n;
in = fopen(from, "r");
if (in == NULL) {
perror(from);
exit(FAILURE);
}
out = fopen(to, "w");
if (out == NULL) {
perror(to);
exit(FAILURE);
}
do {
n = fread(FileBuffer, 1, 1024, in);
if (0 < n)
fwrite(FileBuffer, 1, n, out);
if (ferror(in)) {
perror(from);
exit(FAILURE);
}
if (ferror(out)) {
perror(to);
exit(FAILURE);
}
} while (!feof(in));
fclose(in);
fclose(out);
}
static void append_file(const char *from, const char *to)
{
FILE *in;
FILE *out;
int n;
in = fopen(from, "r");
if (in == NULL) {
perror(from);
exit(FAILURE);
}
out = fopen(to, "a");
if (out == NULL) {
perror(to);
exit(FAILURE);
}
do {
n = fread(FileBuffer, 1, 1024, in);
if (0 < n)
fwrite(FileBuffer, 1, n, out);
if (ferror(in)) {
perror(from);
exit(FAILURE);
}
if (ferror(out)) {
perror(to);
exit(FAILURE);
}
} while (!feof(in));
fclose(in);
fclose(out);
}
#define ISOM_OPTION 8
#define MAXOPTION 9 /* maximum number of menu options */
void list_isom_menu(void);
/* control routine for computing standard presentation */
void isom_options(int format, struct pcp_vars *pcp)
{
register int *y = y_address;
FILE *Status = 0;
FILE *FileName = 0;
FILE *Subgroup = 0;
struct pga_vars pga;
Logical user_supplied = FALSE;
Logical group_present = FALSE;
Logical identity_map;
Logical finished;
Logical valid;
Logical equal;
int output = DEFAULT_STANDARD_PRINT;
int start_class, final_class;
int option;
int t;
int status;
int complete;
int iteration;
int *seq1;
int *seq2;
int len1, len2;
int nmr_items;
int ***auts;
int x_dim, y_dim;
FILE *GAP_library = 0;
char *name = 0;
int nmr_of_exponents;
StandardPresentation = TRUE;
pga.nmr_soluble = 0;
list_isom_menu();
do {
option = read_option(MAXOPTION);
switch (option) {
case -1:
list_isom_menu();
break;
case START_INFO:
t = runTime();
group_present = setup_start_info(FALSE, 0, stdin, format, &pga, pcp);
handle_error(group_present);
user_supplied = TRUE;
t = runTime() - t;
/* it is possible that the p-quotient is trivial */
if (pcp->cc == 0) {
group_present = FALSE;
break;
}
printf("Class %d %d-quotient and its %d-covering group computed in "
"%.2f seconds\n",
pcp->cc - 1,
pcp->p,
pcp->p,
t * CLK_SCALE);
break;
case CONSTRUCT:
if (!user_supplied) {
name = GetString("Enter input file name for group information: ");
FileName = OpenFile(name, "r");
if (FileName == NULL)
break;
}
name = GetString("Enter output file name for group information: ");
read_value(
TRUE, "Standardise presentation to what class? ", &final_class, 0);
if (user_supplied && final_class < pcp->cc) {
printf("Value supplied for end class must be at least %d\n",
pcp->cc);
}
/* read in data from file and set up group to end of start_class
and compute its p-covering group */
if (!user_supplied) {
group_present =
setup_start_info(FALSE, 0, FileName, FILE_INPUT, &pga, pcp);
handle_error(group_present);
if (final_class < pcp->cc) {
CloseFile(FileName);
printf("Value supplied for end class must be at least %d\n",
pcp->cc);
}
}
if (pcp->cc == 0) {
printf("%d-quotient is trivial\n", pcp->p);
break;
}
complete = (pcp->newgen == 0) ? TERMINAL : CAPABLE;
iteration = 0;
for (start_class = pcp->cc;
start_class <= final_class && complete != TERMINAL;
++start_class) {
t = runTime();
identity_map = FALSE;
Subgroup = OpenFile("ISOM_Subgroup", "w");
do {
++iteration;
set_defaults(&pga);
/*
pga.space_efficient = TRUE;
*/
/* either prompt for information or read it from file */
if (user_supplied) {
auts = read_auts(STANDARDISE, &pga.m, &nmr_of_exponents, pcp);
pga.fixed = 0;
query_solubility(&pga);
user_supplied = FALSE;
#ifdef HAVE_GMP
autgp_order(&pga, pcp);
#endif
} else {
auts = read_auts_from_file(FileName, &pga.m, pcp);
nmr_items = fscanf(FileName, "%d", &pga.fixed);
verify_read(nmr_items, 1);
nmr_items = fscanf(FileName, "%d", &pga.soluble);
verify_read(nmr_items, 1);
#ifdef HAVE_GMP
fscanf(FileName, "\n");
mpz_init(&pga.aut_order);
mpz_inp_str(&pga.aut_order, FileName, 10);
#endif
CloseFile(FileName);
}
x_dim = pga.m;
y_dim = pcp->lastg;
/* construct standard presentation relative to smallest
permissible characteristic subgroup in p-multiplicator */
standard_presentation(&identity_map, output, auts, &pga, pcp);
free_array(auts, x_dim, y_dim, 1);
/* was the characteristic subgroup chosen in this iteration
the whole of the p-multiplicator? */
Status = OpenFile("ISOM_Status", "r");
fscanf(Status, "%d", &status);
fscanf(Status, "%d", &complete);
CloseFile(Status);
/* have we finished the construction? */
finished =
(status == END_OF_CLASS &&
(start_class == final_class || complete == TERMINAL));
/* organise to write modified presentation + automorphisms
to file ISOM_PP */
if (!identity_map || finished) {
copy_file("ISOM_present", "ISOM_PP");
append_file("ISOM_NextClass", "ISOM_PP");
} else
copy_file("ISOM_NextClass", "ISOM_PP");
if (finished)
break;
/* if necessary, set up new presentation + other information */
FileName = OpenFile("ISOM_PP", "r");
group_present = setup_start_info(
identity_map, status, FileName, FILE_INPUT, &pga, pcp);
handle_error(group_present);
/* if appropriate, factor subgroup from p-multiplicator */
if (status != END_OF_CLASS)
factor_subgroup(pcp);
/* reinitialise pga structure */
initialise_pga(&pga, pcp);
pga.m = 0;
pga.ndgen = y[pcp->clend + 1];
set_values(&pga, pcp);
} while (status != END_OF_CLASS && complete != TERMINAL);
CloseFile(Subgroup);
/* the group may have completed only when relations are enforced;
this is an attempt to determine this case */
if (pga.nuclear_rank != 0 && pcp->complete)
break;
t = runTime() - t;
printf("Computing standard presentation for class %d took %.2f "
"seconds\n",
start_class,
t * CLK_SCALE);
}
/* we currently may have presentation for p-covering group;
or is the starting group terminal? if so, we may want to
use last_class to revert to group presentation */
if (!user_supplied && iteration == 0 && !pcp->complete)
last_class(pcp);
/* is the group terminal? */
if (complete == TERMINAL)
printf("The largest %d-quotient of the group has class %d\n",
pcp->p,
pcp->cc);
if (iteration == 0)
break;
/* rename file ISOM_PP containing iteration info to nominated file */
rename("ISOM_PP", name);
break;
case PRINT_PCP:
if (group_present)
print_presentation(TRUE, pcp);
break;
case SAVE_PRES:
name = GetString("Enter output file name: ");
FileName = OpenFileOutput(name);
if (group_present && FileName != NULL) {
save_pcp(FileName, pcp);
CloseFile(FileName);
printf("Presentation written to file\n");
}
break;
case COMPARE:
valid = get_description(
"Enter file name storing first presentation: ", &len1, &seq1, pcp);
if (!valid)
break;
valid =
get_description("Enter file name storing second presentation: ",
&len2,
&seq2,
pcp);
if (!valid)
break;
equal = (len1 == len2) ? compare_sequences(seq1, seq2, len1) : FALSE;
printf("Identical presentations? %s\n",
equal == TRUE ? "True" : "False");
free_vector(seq1, 1);
free_vector(seq2, 1);
break;
case STANDARD_PRINT_LEVEL:
read_value(
TRUE, "Input print level for construction (0-2): ", &output, 0);
/* allow user to supply same max print level as for
p-quotient calculations */
if (output == MAX_STANDARD_PRINT + 1)
--output;
if (output > MAX_STANDARD_PRINT) {
printf("Print level must lie between %d and %d\n",
MIN_STANDARD_PRINT,
MAX_STANDARD_PRINT);
output = DEFAULT_STANDARD_PRINT;
}
break;
case PQ_MENU:
options(ISOM_MENU, format, pcp);
break;
case ISOM_OPTION:
assert(name);
FileName = OpenFile(name, "r");
group_present =
setup_start_info(FALSE, 0, FileName, FILE_INPUT, &pga, pcp);
pcp->multiplicator_rank = pcp->lastg - y[pcp->clend + pcp->cc - 1];
last_class(pcp);
auts = read_auts_from_file(FileName, &pga.m, pcp);
nmr_items = fscanf(FileName, "%d", &pga.fixed);
verify_read(nmr_items, 1);
nmr_items = fscanf(FileName, "%d", &pga.soluble);
verify_read(nmr_items, 1);
printf("Images of user-supplied generators are listed last below\n");
print_map(pcp);
#ifdef HAVE_GMP
fscanf(FileName, "\n");
mpz_init(&pga.aut_order);
mpz_inp_str(&pga.aut_order, FileName, 10);
#endif
CloseFile(FileName);
GAP_library = OpenFile("GAP_library", "a+");
write_GAP_library(GAP_library, pcp);
pga.nmr_centrals = pga.m;
pga.nmr_stabilisers = 0;
GAP_auts(GAP_library, auts, auts, &pga, pcp);
CloseFile(GAP_library);
printf("Presentation listing images of user-supplied generators "
"written to GAP_library\n");
break;
case EXIT:
case MAXOPTION:
unlink("ISOM_present");
unlink("ISOM_Subgroup");
unlink("ISOM_cover_file");
unlink("ISOM_group_file");
unlink("ISOM_XX");
unlink("ISOM_NextClass");
unlink("ISOM_Status");
printf("Exiting from ANU p-Quotient Program\n");
break;
} /* switch */
} while (option != 0 && option != MAXOPTION);
}
/* list available menu options */
void list_isom_menu(void)
{
printf("\nStandard Presentation Menu\n");
printf("-----------------------------\n");
printf("%d. Supply start information\n", START_INFO);
printf("%d. Compute standard presentation to supplied class\n", CONSTRUCT);
printf("%d. Save presentation to file\n", SAVE_PRES);
printf("%d. Display presentation\n", PRINT_PCP);
printf("%d. Set print level for construction\n", STANDARD_PRINT_LEVEL);
printf("%d. Compare two presentations stored in files\n", COMPARE);
printf("%d. Call basic menu for p-Quotient program\n", PQ_MENU);
printf("%d. Compute the isomorphism\n", ISOM_OPTION);
printf("%d. Exit from program\n", MAXOPTION);
}
/* set up the group to the desired class and its p-covering group;
identity_map indicates whether standard automorphism applied
was the identity; status indicates whether we are end of class;
the presentation is read from file using indicated format */
static Logical setup_start_info(Logical identity_map,
Logical status,
FILE *file,
int format,
struct pga_vars *pga,
struct pcp_vars *pcp)
{
register int *y = y_address;
FILE *FileName;
FILE *presentation_file;
Logical group_present = FALSE;
int exit_value;
int *list, *head;
int i;
#if defined(TIME)
int t;
t = runTime();
#endif
if (!identity_map) {
/* we must recompute the presentation since generators and
relations have been altered by applying the standard map */
/* memory leak September 1996 */
if (user_gen_name != NULL) {
num_gens = user_gen_name[0].first;
for (i = 1; i <= num_gens; ++i) {
free_vector(user_gen_name[i].g, 0);
}
free(user_gen_name);
user_gen_name = NULL;
free_vector(inv_of, 0);
free_vector(pairnumber, 0);
}
exit_value = pquotient(0, 0, file, format, pcp);
if (exit_value == SUCCESS)
group_present = TRUE;
#if defined(TIME)
printf("Time to recompute pcp is %.2f\n", (runTime() - t) * CLK_SCALE);
#endif
} else {
/* generators and relations of presentation have not changed --
we can restore presentation for either full p-covering group
or class c + 1 quotient */
if (status == END_OF_CLASS)
presentation_file = OpenFile("ISOM_group_file", "r");
else
presentation_file = OpenFile("ISOM_cover_file", "r");
restore_pcp(presentation_file, pcp);
CloseFile(presentation_file);
group_present = TRUE;
}
#if defined(DEBUG)
pcp->diagn = TRUE;
printf("The modified presentation is \n");
print_presentation(TRUE, pcp);
pcp->diagn = FALSE;
#endif
if (!group_present || pcp->cc == 0)
return group_present;
/* do we need to compute the full p-covering group? */
if (!identity_map || status == END_OF_CLASS) {
pcp->multiplicator = TRUE;
next_class(FALSE, &head, &list, pcp);
pga->exponent_law = pcp->extra_relations;
pga->metabelian = pcp->metabelian;
enforce_laws(pga, pga, pcp);
pcp->multiplicator = FALSE;
FileName = OpenFile("ISOM_cover_file", "w");
save_pcp(FileName, pcp);
CloseFile(FileName);
}
initialise_pga(pga, pcp);
pga->m = 0;
pga->ndgen = y[pcp->clend + 1];
set_values(pga, pcp);
return group_present;
}
/* factor subgroup whose generators are listed in Subgroup file
from p-multiplicator to give reduced p-multiplicator */
void factor_subgroup(struct pcp_vars *pcp)
{
register int *y = y_address;
FILE *Subgroup;
int flag;
int cp;
int i;
Subgroup = fopen("ISOM_Subgroup", "r");
if (Subgroup == (FILE *)NULL)
return;
while (!feof(Subgroup)) {
if (fscanf(Subgroup, "%d", &flag) == -1)
continue;
/* should we eliminate (in order to renumber the generators)? */
if (flag == ELIMINATE)
eliminate(FALSE, pcp);
if (fscanf(Subgroup, "%d", &flag) == -1)
continue;
setup_symbols(pcp);
cp = pcp->lused;
setup_word_to_collect(Subgroup, PRETTY, WORD, cp, pcp);
for (i = 1; i <= pcp->lastg; ++i)
y[cp + pcp->lastg + i] = 0;
echelon(pcp);
}
CloseFile(Subgroup);
}
void handle_error(Logical group_present)
{
if (group_present == FALSE) {
printf("Error in Standard Presentation Program\n");
exit(FAILURE);
}
}
/* compare two sequences, s and t, of length length */
static Logical compare_sequences(int *s, int *t, int length)
{
/* TODO: Replace this by memcmp? */
register int i;
Logical equal = TRUE;
for (i = 1; i <= length && (equal = (s[i] == t[i])); ++i)
;
return equal;
}
/* read group from file and set up its compact description
as sequence seq of length len */
int get_description(char *string, int *len, int **seq, struct pcp_vars *pcp)
{
char *name;
FILE *file;
name = GetString(string);
file = OpenFile(name, "r");
if (file == NULL) {
if (isatty(0))
return FALSE;
else
exit(FAILURE);
}
restore_pcp(file, pcp);
CloseFile(file);
/* length of sequence */
*len = choose(pcp->lastg + 1, 3);
/* sequence of exponents */
*seq = compact_description(FALSE, pcp);
return TRUE;
}
#endif
#endif
¤ Dauer der Verarbeitung: 0.10 Sekunden
¤
*© Formatika GbR, Deutschland
|
|