/* File generate.c. */
/* Copyright (C) 1992 by Jeffrey S. Leon. This software may be used freely
for educational and research purposes. Any other use requires permission
from the author. */
/* Main program for generate command, which may be used
to find a base and strong generating set for a permutation group using
the random Schreier and/or Schreier-Todd-Coxeter-Sims methods. The format
of the command is:
generate <options> <permGroup> <generatedPermGroup>
where the meaning of the parameters is as follows:
<permGroup>: the permutation group G for which a base and strong
generating set is to be found.
<generatedPermGroup>: the same permutation group G with a base and strong
generating set, depending on options, possibly a
strong presentation.
The general options are as follows:
-nr Omit random-Schreier phase.
-ns Omit Schreier-Todd-Coxeter-Sims phase (automatically
omitted if order is known in advance and random-Schreier
phases generates full order, unless the -p option is given.
-p Find a presentation.
-q Don't write status information to standard output.
-in:<group> Group G is contained in <group>. Only base of <group> is
used; <group> need not be valid as long as its base ,
base size, and degree fields are filled in correctly.
-overwrite Overwrite, rather than append to, the output file.
-i Image format for output group.
-c Cycle format for output group.
-gn:<name>
Options applicable specifically to the random-Schreier phase are:
-s:<integer> Seed for random number generator.
-tr:<integer> Random Schreier phase terminates after this many
consecutive "successes" (quasi-random elements that
are factorable).
-ti:<integer> This many consecutive non-involutory generators will
be rejected in an attempt to choose involutory generators.
-th:k This many consecutive generators will be rejected in
an attempt to choose a generator of order 3 (or less).
-nro Suppress normal attempt to reduce generator order by
replacing generators with powers.
-wi:w,x Here w and x are integers with w <= x. The word length
increment will be random between w and x.
-z Redundant strong generators will be removed after the
algorithm completes..
Options applicable to the STCS phase are:
-go:m Automatically include the order of each generator as a
relator when the generator order does not exceed m
(default 15).
-po:m Automatically include the order of each product of
generators as a relator when the product order does
not exceed m (default 5).
-x2:m If the STCS phase terminates with more than
m generators (excluding inverses), redundant generators
are removed.
-pr:a,b,c,d,e Determines priority for relator selection. The priority
of a relator r is a - b * (len+symLen)/2. Relators are
selected if their priority exceeds
c + d * chosen - e * omitted, where chosen represents the
number of relators chosen at this level and omitted
represents the number not chosen.
-sh:i1,k1,i2.. Specifies which cyclic shifts of relators will be
used in the Felsch enumeration. Specifies that an
i1 position shift will be used if the relator
priority exceeds the selection priority by at least
k1, etc. By default, all shifts are always used.
-x:k Specifies use of up to k extra cosets during enumeration
(default 0). When k > 0, a different procedure is
used to check point stabilizers.
-y:m The number of extra cosets used will be
m/100 * degree (rounded up), but in no case more than
k, as above (default 10). */
#include <stddef.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define MAIN
#include "group.h"
#include "groupio.h"
#include "enum.h"
#include "storage.h"
#include "chbase.h"
#include "inform.h"
#ifdef ALT_TIME_HEADER
#include "cputime.h"
#endif
#ifdef TICK
#undef CLK_TCK
#define CLK_TCK TICK
#endif
#include "errmesg.h"
#include "new.h"
#include "readgrp.h"
#include "randschr.h"
#include "stcs.h"
#include "util.h"
static void nameGenerators(
PermGroup *const H,
char genNamePrefix[]);
static void informGenerateTime(
clock_t startTime,
clock_t randSchrTime,
clock_t optGroupTime,
clock_t stcsTime);
static void verifyOptions(void);
GroupOptions options;
STCSOptions sOptions;
Unsigned relatorSelection[5] = {1000,0,800,0,0};
Unsigned shiftSelection[11] = {UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
UNKNOWN};
Unsigned shiftPriority[11];
int main( int argc, char *argv[])
{
char groupFileName[MAX_FILE_NAME_LENGTH] = "",
genGroupFileName[MAX_FILE_NAME_LENGTH] = "",
containingGroupFileName[MAX_FILE_NAME_LENGTH] = "";
char groupLibraryName[MAX_NAME_LENGTH+1] = "",
genGroupLibraryName[MAX_NAME_LENGTH+1] = "",
genGroupObjectName[MAX_NAME_LENGTH+1] = "",
containingGroupLibraryName[MAX_NAME_LENGTH+1] = "",
prefix[MAX_FILE_NAME_LENGTH],
suffix[MAX_NAME_LENGTH];
Unsigned i, j, optionCountPlus1, level;
BOOLEAN omitRandomSchreierOption, omitStcsOption, presentationOption,
quietOption, cycleFormatFlag, imageFormatFlag, removeRedunStrGens,
noBackupFlag;
Unsigned trimStrGenSet1, trimStrGenSet2;
PermGroup *G, *containingGroup;
char comment[1024] = "";
UnsignedS *pointList = allocIntArrayBaseSize();
char tempStr[12];
char *strPtr, *commaPtr;
Unsigned *knownBase = allocIntArrayBaseSize();
RandomSchreierOptions rOptions = {47,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN};
clock_t startTime, randSchrTime, optGroupTime, stcsTime;
/* Provide usage info if no arguments are specified. */
if ( argc == 1 ) {
printf( "\nUsage: generate [options] originalPermGroup permGroupWithBaseSGS\n");
freeIntArrayBaseSize( pointList);
freeIntArrayBaseSize( knownBase);
return 0;
}
/* Check for limits option. If present in position 1 give limits and
return. */
if ( strcmp( argv[1], "-l") == 0 || strcmp( argv[1], "-L") == 0 ) {
showLimits();
freeIntArrayBaseSize( pointList);
freeIntArrayBaseSize( knownBase);
return 0;
}
/* Check for verify option. If present, perform verify (Note verifyOptions
terminates program). */
if ( strcmp( argv[1], "-v") == 0 || strcmp( argv[1], "-V") == 0 )
verifyOptions();
/* Check for 1 or 2 parameters following options. */
for ( optionCountPlus1 = 1 ; optionCountPlus1 <= argc-1 &&
argv[optionCountPlus1][0] == '-' ; ++optionCountPlus1 )
;
if ( argc - optionCountPlus1 < 1 || argc - optionCountPlus1 > 2 ) {
printf( "\n\nError: 1 or 2 non-option parameters are required.\n");
exit(ERROR_RETURN_CODE);
}
/* Process options. */
prefix[0] = '\0';
suffix[0] = '\0';
options.maxBaseSize = DEFAULT_MAX_BASE_SIZE;
sOptions.maxDeducQueueSize = UNKNOWN;
sOptions.genOrderLimit = 13;
sOptions.prodOrderLimit = 3;
sOptions.maxExtraCosets = 0;
sOptions.percentExtraCosets = 10;
omitRandomSchreierOption = FALSE;
omitStcsOption = TRUE;
presentationOption = FALSE;
rOptions.reduceGenOrder = TRUE;
rOptions.rejectNonInvols = 0;
removeRedunStrGens = FALSE;
quietOption = FALSE;
options.genNamePrefix[0] = '\0';
trimStrGenSet1 = 20;
trimStrGenSet2 = 20;
cycleFormatFlag = FALSE;
imageFormatFlag = FALSE;
noBackupFlag = FALSE;
strcpy( options.outputFileMode, "w");
strcpy( options.genNamePrefix, "");
for ( i = 1 ; i < optionCountPlus1 ; ++i )
/* General options. */
if ( strcmp( argv[i], "-a") == 0 )
strcpy( options.outputFileMode, "a");
else if ( strcmp( argv[i], "-c") == 0 )
cycleFormatFlag = TRUE;
else if ( strcmp( argv[i], "-i") == 0 )
imageFormatFlag = TRUE;
else if ( strncmp( argv[i], "-mb:", 4) == 0 ) {
errno = 0;
options.maxBaseSize = (Unsigned) strtol(argv[i]+4,NULL,0);
if ( errno )
ERROR( "main (cent)", "Invalid syntax for -mb option")
}
else if ( strncmp( argv[i], "-mw:", 4) == 0 ) {
errno = 0;
options.maxWordLength = (Unsigned) strtol(argv[i]+4,NULL,0);
if ( errno )
ERROR( "main (cent)", "Invalid syntax for -mw option")
}
else if ( strncmp(argv[i],"-n:",3) == 0 )
strcpy( genGroupObjectName, argv[i]+3);
else if ( strcmp( argv[i], "-nb") == 0 )
noBackupFlag = TRUE;
else if ( strcmp( argv[i], "-overwrite") == 0 )
strcpy( options.outputFileMode, "w");
else if ( strncmp( argv[i], "-p:", 3) == 0 ) {
strcpy( prefix, argv[i]+3);
}
else if ( strcmp( argv[i], "-q") == 0 )
quietOption = TRUE;
else if ( strncmp( argv[i], "-t:", 3) == 0 ) {
strcpy( suffix, argv[i]+3);
}
else if ( strcmp( argv[i], "-z") == 0 ) {
removeRedunStrGens = TRUE;
}
/* Method selection options. */
else if ( strcmp( argv[i], "-nr") == 0 )
omitRandomSchreierOption = TRUE;
else if ( strcmp( argv[i], "-stcs") == 0 )
omitStcsOption = FALSE;
/* Random Schreier options. */
else if ( strcmp( argv[i], "-nro") == 0 )
rOptions.reduceGenOrder = FALSE;
else if ( strncmp(argv[i],"-s:",3) == 0 ) {
errno = 0;
rOptions.initialSeed = (unsigned long) strtol( argv[i]+3, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else if ( strncmp(argv[i],"-ti:",4) == 0 ) {
errno = 0;
rOptions.rejectNonInvols = (unsigned long) strtol( argv[i]+4, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else if ( strncmp(argv[i],"-tr:",4) == 0 ) {
errno = 0;
rOptions.stopAfter = (unsigned long) strtol( argv[i]+4, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else if ( strncmp( argv[i], "-wi:", 4) == 0 ) {
errno = 0;
rOptions.minWordLengthIncrement = (unsigned long) strtol( argv[i]+4, &commaPtr, 0);
if ( errno || *commaPtr != ',' )
ERROR1s( "main (generate command)", "Invalid syntax in option ",
argv[i], ".")
rOptions.maxWordLengthIncrement = (unsigned long) strtol( commaPtr+1, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid syntax in option ",
argv[i], ".")
}
/* STCS options. */
else if ( strncmp( argv[i], "-in:", 4) == 0 ) {
parseLibraryName( argv[i]+4, "", "", containingGroupFileName,
containingGroupLibraryName);
}
else if ( strncmp(argv[i],"-pr:",4) == 0 ) {
errno = 0;
commaPtr = argv[i]+3;
for ( j = 0 ; j <= 4 ; ++j ) {
strPtr = commaPtr + 1;
relatorSelection[j] = (Unsigned) (unsigned long) strtol( strPtr, &commaPtr, 0);
if ( errno || ( j < 4 && *commaPtr != ',') )
ERROR1s( "main (generate command)", "Invalid option ", argv[i],
".")
}
}
else if ( strncmp(argv[i],"-sh:",4) == 0 ) {
errno = 0;
commaPtr = argv[i]+3;
for ( j = 0 ; j < 10 && *commaPtr != '\0' ; ++j ) {
strPtr = commaPtr + 1;
shiftSelection[j] = (Unsigned) (unsigned long) strtol( strPtr, &commaPtr, 0);
if ( errno || *commaPtr != ',' )
ERROR1s( "main (generate command)", "Invalid option ", argv[i],
".")
strPtr = commaPtr + 1;
shiftPriority[j] = (Unsigned) (unsigned long) strtol( strPtr, &commaPtr, 0);
if ( errno || (*commaPtr != ',' && *commaPtr != '\0') )
ERROR1s( "main (generate command)", "Invalid option ", argv[i],
".")
}
}
else if ( strncmp(argv[i],"-th:",4) == 0 ) {
errno = 0;
rOptions.rejectHighOrder = (unsigned long) strtol( argv[i]+4, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else if ( strncmp(argv[i],"-go:",4) == 0 ) {
errno = 0;
sOptions.genOrderLimit = (unsigned long) strtol( argv[i]+4, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else if ( strncmp(argv[i],"-po:",4) == 0 ) {
errno = 0;
sOptions.prodOrderLimit = (unsigned long) strtol( argv[i]+4, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else if ( strncmp(argv[i],"-x:",3) == 0 ) {
errno = 0;
sOptions.maxExtraCosets = (unsigned long) strtol( argv[i]+3, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else if ( strncmp(argv[i],"-y:",3) == 0 ) {
errno = 0;
sOptions.percentExtraCosets = (unsigned long) strtol( argv[i]+3, NULL, 0);
if ( errno )
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
}
else
ERROR1s( "main (generate command)", "Invalid option ", argv[i], ".")
/* Compute maximum degree and word length. */
options.maxWordLength = 200 + 5 * options.maxBaseSize;
options.maxDegree = MAX_INT - 2 - options.maxBaseSize;
/* Compute names for input and output groups. */
parseLibraryName( argv[optionCountPlus1], prefix, suffix, groupFileName,
groupLibraryName);
if ( argc - optionCountPlus1 == 2 )
parseLibraryName( argv[optionCountPlus1+1], "", "", genGroupFileName,
genGroupLibraryName);
else {
strcpy( genGroupFileName, groupFileName);
strcpy( genGroupLibraryName, groupLibraryName);
}
/* Set initialize option for STCS. */
sOptions.initialize = omitRandomSchreierOption;
/* Set default generator name prefix, if not specified. */
if ( options.genNamePrefix[0] == ' ' )
strncpy( options.genNamePrefix, genGroupLibraryName, 4);
/* Read in input group, and base for containing group, if requested. */
G = readPermGroup( groupFileName, groupLibraryName, 0, "");
if ( containingGroupFileName[0] ) {
containingGroup = readPermGroup( containingGroupFileName,
containingGroupLibraryName, G->degree, "");
for ( i = 1 ; i <= containingGroup->baseSize ; ++i )
knownBase[i] = containingGroup->base[i];
knownBase[containingGroup->baseSize+1] = 0;
deletePermGroup( containingGroup);
}
startTime = CPU_TIME();
/* Apply random Schreier algorithm. */
if ( !omitRandomSchreierOption ) {
/* SETUP OPTIONS STRING */
randomSchreier( G, rOptions);
if ( removeRedunStrGens )
removeRedunSGens( G, 1);
}
randSchrTime = CPU_TIME();
optGroupTime = CPU_TIME();
/* Apply Schreier-Todd-Coxeter-Sims algorithm, if appropriate. */
if ( !omitStcsOption /* FIX THIS */ )
schreierToddCoxeterSims( G, knownBase);
stcsTime = CPU_TIME();
if ( !quietOption ) {
informGroup(G);
printf( "\n Base: ");
for ( level = 1 ; level <= G->baseSize ; ++level )
printf( " %5u", G->base[level]);
printf( "\n Basic orbit lengths:");
for ( level = 1 ; level <= G->baseSize ; ++level )
printf( " %5u", G->basicOrbLen[level]);
printf( "\n");
informGenerateTime( startTime, randSchrTime, optGroupTime, stcsTime);
}
/* Write out the generated group. */
sprintf( comment, "The group %s, base and strong generating set constucted.",
G->name);
if ( cycleFormatFlag )
G->printFormat = cycleFormat;
if ( imageFormatFlag )
G->printFormat = imageFormat;
if ( genGroupObjectName[0] )
strcpy( G->name, genGroupObjectName);
if ( argc - optionCountPlus1 == 1 && !noBackupFlag )
if ( rename(groupFileName,"oldgroup") == -1 )
ERROR1s( "main (generate command)", "Original group ", groupFileName,
" could not be renamed as oldgroup.")
writePermGroup( genGroupFileName, genGroupLibraryName, G, comment);
/* Free pseudo-stack storage. */
freeIntArrayBaseSize( pointList);
freeIntArrayBaseSize( knownBase);
return 0;
}
/*-------------------------- nameGenerators ------------------------------*/
static void nameGenerators(
PermGroup *const H,
char genNamePrefix[])
{
Unsigned i;
Permutation *gen;
if ( genNamePrefix[0] == '\0' ) {
strncpy( genNamePrefix, H->name, 4);
genNamePrefix[4] = '\0';
}
for ( gen = H->generator , i = 1 ; gen ; gen = gen->next , ++i ) {
strcpy( gen->name, genNamePrefix);
sprintf( gen->name + strlen(gen->name), "%02d", i);
}
}
/*-------------------------- verifyOptions -------------------------------*/
static void verifyOptions(void)
{
CompileOptions mainOpts = { DEFAULT_MAX_BASE_SIZE, MAX_NAME_LENGTH,
MAX_PRIME_FACTORS,
MAX_REFINEMENT_PARMS, MAX_FAMILY_PARMS,
MAX_EXTRA, XLARGE, SGND, NFLT};
extern void xaddsge( CompileOptions *cOpts);
extern void xbitman( CompileOptions *cOpts);
extern void xchbase( CompileOptions *cOpts);
extern void xcopy ( CompileOptions *cOpts);
extern void xcstbor( CompileOptions *cOpts);
extern void xerrmes( CompileOptions *cOpts);
extern void xessent( CompileOptions *cOpts);
extern void xfactor( CompileOptions *cOpts);
extern void xinform( CompileOptions *cOpts);
extern void xnew ( CompileOptions *cOpts);
extern void xoldcop( CompileOptions *cOpts);
extern void xpermgr( CompileOptions *cOpts);
extern void xpermut( CompileOptions *cOpts);
extern void xprimes( CompileOptions *cOpts);
extern void xrandgr( CompileOptions *cOpts);
extern void xrandsc( CompileOptions *cOpts);
extern void xreadgr( CompileOptions *cOpts);
extern void xrelato( CompileOptions *cOpts);
extern void xstcs ( CompileOptions *cOpts);
extern void xstorag( CompileOptions *cOpts);
extern void xtoken ( CompileOptions *cOpts);
extern void xutil ( CompileOptions *cOpts);
xaddsge( &mainOpts);
xbitman( &mainOpts);
xchbase( &mainOpts);
xcopy ( &mainOpts);
xcstbor( &mainOpts);
xerrmes( &mainOpts);
xessent( &mainOpts);
xfactor( &mainOpts);
xinform( &mainOpts);
xnew ( &mainOpts);
xoldcop( &mainOpts);
xpermgr( &mainOpts);
xpermut( &mainOpts);
xprimes( &mainOpts);
xrandgr( &mainOpts);
xrandsc( &mainOpts);
xreadgr( &mainOpts);
xrelato( &mainOpts);
xstcs ( &mainOpts);
xstorag( &mainOpts);
xtoken ( &mainOpts);
xutil ( &mainOpts);
}
/*-------------------------- informGenerateTime ----------------------------*/
static void informGenerateTime(
clock_t startTime,
clock_t randSchrTime,
clock_t optGroupTime,
clock_t stcsTime)
{
clock_t totalTime;
#ifdef NOFLOAT
unsigned long secs, hSecs;
#endif
stcsTime -= optGroupTime;
optGroupTime -= randSchrTime;
randSchrTime -= startTime;
totalTime = randSchrTime + optGroupTime + stcsTime;
#ifndef NOFLOAT
printf( "\nTime: Random Schreier: %6.2lf sec",
(double) randSchrTime / CLK_TCK);
printf( "\n Gen optimization: %6.2lf sec",
(double) optGroupTime / CLK_TCK);
printf( "\n Schr-Todd-Cox-Sims: %6.2lf sec",
(double) stcsTime / CLK_TCK);
printf( "\n TOTAL: %6.2lf sec",
(double) totalTime / CLK_TCK);
#endif
#ifdef NOFLOAT
secs = randSchrTime / CLK_TCK;
hSecs = (randSchrTime - secs * CLK_TCK) * 100;
hSecs /= CLK_TCK;
printf( "\nTime: Random Schreier: %4lu.%02lu sec", secs, hSecs);
secs = optGroupTime / CLK_TCK;
hSecs = (optGroupTime - secs * CLK_TCK) * 100;
hSecs /= CLK_TCK;
printf( "\n Gen optimization: %4lu.%02lu sec", secs, hSecs);
secs = stcsTime / CLK_TCK;
hSecs = (stcsTime - secs * CLK_TCK) * 100;
hSecs /= CLK_TCK;
printf( "\n Schr-Todd-Cox-Sims: %4lu.%02lu sec", secs, hSecs);
secs = totalTime / CLK_TCK;
hSecs = (totalTime - secs * CLK_TCK) * 100;
hSecs /= CLK_TCK;
printf( "\n TOTAL: %4lu.%02lu sec", secs, hSecs);
#endif
printf( "\n");
}
¤ Dauer der Verarbeitung: 0.14 Sekunden
¤
*© Formatika GbR, Deutschland
|
|