/*****************************************************************************
**
** nq.c NQ Werner Nickel
** nickel@mathematik.tu-darmstadt.de
*/
#include <unistd.h>
#include <ctype.h>
#include "nq.h"
#include "engel.h"
#include "glimt.h"
#include "presentation.h"
#include "relations.h"
#include "time.h"
int Debug = 0;
int Gap = 0;
int AbelianInv = 0;
int NilpMult;
int Verbose = 0;
extern int RawMatOutput;
const char *InputFile;
static char *ProgramName;
static int Cl;
static
void usage(
const char *error) {
int i;
if (error != 0) fprintf(stderr,
"%s\n", error);
fprintf(stderr,
"usage: %s", ProgramName);
fprintf(stderr,
" [-a] [-M] [-d] [-g] [-v] [-s] [-f] [-c] [-m]\n");
for (i = strlen(ProgramName) + 7; i > 0; i--) fputc(
' ', stderr);
fprintf(stderr,
" [-t ] [-l ] [-r ] [-n ] [-e ]\n");
for (i = strlen(ProgramName) + 7; i > 0; i--) fputc(
' ', stderr);
fprintf(stderr,
" [-y] [-o] [-p] [-E] [] []\n");
exit(1);
}
static int leftEngel = 0,
rightEngel = 0,
revEngel = 0,
engel = 0,
nrEngelGens = 1;
static int trmetab = 0;
static const char *Ordinal(
int n) {
switch (n) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
static
void printHeader(
void) {
printf(
"#\n");
printf(
"# The ANU Nilpotent Quotient Program (Version %s)\n",
PACKAGE_VERSION);
printf(
"# Calculating a nilpotent quotient\n");
printf(
"# Input: %s", InputFile);
if (leftEngel) {
if (nrEngelGens > 1)
printf(
" & the first %d generators are", nrEngelGens);
else
printf(
" &");
printf(
" %d%s left Engel", leftEngel, Ordinal(leftEngel));
}
if (rightEngel) {
if (nrEngelGens > 1)
printf(
" & the first %d generators are", nrEngelGens);
else
printf(
" &");
printf(
" %d%s right Engel", rightEngel, Ordinal(rightEngel));
}
if (engel) {
printf(
" %d%s Engel", engel, Ordinal(engel));
}
printf(
"\n");
if (Cl != 666) printf(
"# Nilpotency class: %d\n", Cl);
printf(
"# Program: %s\n", ProgramName);
printf(
"# Size of exponents: %d bytes\n#\n", (
int)
sizeof(expo));
}
int main(
int argc,
char *argv[]) {
FILE *fp;
long t, time;
long begin, printEpim = 1;
gen g;
CatchSignals();
begin = RunTime();
ProgramName = argv[0];
argc--;
argv++;
setbuf(stdout, NULL);
while (argc > 0 && argv[0][0] ==
'-') {
if (argv[0][2] !=
'\0') {
fprintf(stderr,
"unknown option: %s\n", argv[0]);
usage((
char *)0);
}
switch (argv[0][1]) {
case 'h':
usage((
char *)0);
break;
case 'r':
if (--argc < 1) usage(
"-r requires an argument");
argv++;
if ((rightEngel = atoi(argv[0])) <= 0) {
fprintf(stderr,
"%s\n", argv[0]);
usage(
" must be positive.");
}
break;
case 'l':
if (--argc < 1) usage(
"-l requires an argument.");
argv++;
if ((leftEngel = atoi(argv[0])) <= 0) {
fprintf(stderr,
"%s\n", argv[0]);
usage(
" must be positive.");
}
break;
case 'n':
if (--argc < 1) usage(
"-n requires an argument.");
argv++;
if ((nrEngelGens = atoi(argv[0])) <= 0) {
fprintf(stderr,
"%s\n", argv[0]);
usage(
" must be positive.");
}
break;
case 'e':
if (--argc < 1) usage(
"-e requires an argument");
argv++;
if ((engel = atoi(argv[0])) <= 0) {
fprintf(stderr,
"%s\n", argv[0]);
usage(
" must be positive.");
}
break;
case 't':
if (--argc < 1) usage(
"-t requires an argument");
argv++;
if ((t = atoi(argv[0])) <= 0) {
fprintf(stderr,
"%s\n", argv[0]);
usage(
" must be positive.");
}
switch (argv[0][strlen(argv[0]) - 1]) {
case 'd' :
t *= 24;
case 'h' :
t *= 60;
case 'm' :
t *= 60;
}
SetTimeOut(t);
break;
case 'p':
printEpim = !printEpim;
break;
case 'g':
Gap = !Gap;
break;
case 'a':
AbelianInv = !AbelianInv;
break;
case 'M':
NilpMult = !NilpMult;
break;
case 'v':
Verbose = !Verbose;
break;
case 'd':
Debug = !Debug;
break;
case 's':
SemigroupOnly = !SemigroupOnly;
break;
case 'c':
CheckFewInstances = !CheckFewInstances;
break;
case 'f':
SemigroupFirst = !SemigroupFirst;
break;
case 'o':
ReverseOrder = !ReverseOrder;
break;
case 'm':
RawMatOutput = !RawMatOutput;
break;
case 'y':
trmetab = 1;
break;
case 'E':
revEngel = !revEngel;
break;
case 'C':
UseCombiCollector = !UseCombiCollector;
break;
case 'S':
UseSimpleCollector = !UseSimpleCollector;
break;
default :
fprintf(stderr,
"unknown option: %s\n", argv[0]);
usage((
char *)0);
break;
}
argc--;
argv++;
}
/*
** The default is to read from stdin and have no (almost no)
** class bound.
*/
InputFile =
"";
Cl = 666;
/* Parse the remaining arguments. */
switch (argc) {
case 0:
break;
case 1:
if (!isdigit(argv[0][0]))
/* The only argument left is a file name. */
InputFile = argv[0];
else
/* The only argument left is the class. */
Cl = atoi(argv[0]);
/* TODO: Use strtol instead of atoi */
break;
case 2:
/* Two arguments left. */
InputFile = argv[0];
Cl = atoi(argv[1]);
/* TODO: Use strtol instead of atoi */
break;
default:
usage((
char *)0);
break;
}
if (Cl <= 0) usage(
" must be positive.");
/* Open the input stream. */
if (strcmp(InputFile,
"") == 0) {
fp = stdin;
}
else {
if ((fp = fopen(InputFile,
"r")) == NULL) {
perror(InputFile);
exit(1);
}
}
/* Read in the finite presentation. */
Presentation(fp, InputFile);
/* Set the number of generators. */
WordInit(Epimorphism);
InitEngel(leftEngel, rightEngel, revEngel, engel, nrEngelGens);
InitTrMetAb(trmetab);
InitPrint(stdout);
printHeader();
time = RunTime();
if (Gap) printf(
"NqLowerCentralFactors := [\n");
if (Gap & Verbose) fprintf(stderr,
"#I Class 1:");
printf(
"# Calculating the abelian quotient ...\n");
InitEpim();
EvalAllRelations();
EvalEngel();
EvalTrMetAb();
ElimEpim();
if (NrCenGens == 0) {
printf(
"# trivial abelian quotient\n");
goto end;
}
/* if( Cl == 1 ) goto end;
*/
InitPcPres();
if (Gap & Verbose) {
fprintf(stderr,
" %d generators with relative orders ",
Dimension[
Class]);
for (g = NrPcGens - Dimension[
Class] + 1; g <= NrPcGens; g++)
fprintf(stderr,
" %d", (
int)(Exponent[g]));
fprintf(stderr,
"\n");
}
printf(
"# The abelian quotient");
printf(
" has %d generators\n", Dimension[
Class]);
printf(
"# with the following exponents:");
for (g = NrPcGens - Dimension[
Class] + 1; g <= NrPcGens; g++)
printf(
" %d", (
int)(Exponent[g]));
printf(
"\n");
if (Verbose) {
printf(
"# runtime : %ld msec\n", RunTime() - time);
printf(
"# total runtime : %ld msec\n", RunTime() - begin);
}
printf(
"#\n");
while (
Class < Cl) {
time = RunTime();
if (Gap & Verbose) {
fprintf(stderr,
"#I Class %d:",
Class + 1);
}
printf(
"# Calculating the class %d quotient ...\n",
Class + 1);
AddGenerators();
Tails();
Consistency();
if (NilpMult) OutputMatrix(
"nilp");
EvalAllRelations();
EvalEngel();
EvalTrMetAb();
if (NilpMult) OutputMatrix(
"mult");
ElimGenerators();
if (NrCenGens == 0)
goto end;
ExtPcPres();
if (Gap & Verbose) {
fprintf(stderr,
" %d generators", Dimension[
Class]);
fprintf(stderr,
" with relative orders:");
for (g = NrPcGens - Dimension[
Class] + 1; g <= NrPcGens; g++)
fprintf(stderr,
" %d", (
int)(Exponent[g]));
fprintf(stderr,
"\n");
}
printf(
"# Layer %d of the lower central series",
Class);
printf(
" has %d generators\n", Dimension[
Class]);
printf(
"# with the following exponents:");
for (g = NrPcGens - Dimension[
Class] + 1; g <= NrPcGens; g++)
printf(
" %d", (
int)(Exponent[g]));
printf(
"\n");
if (Verbose) {
printf(
"# runtime : %ld msec\n", RunTime() - time);
printf(
"# total runtime : %ld msec\n", RunTime() - begin);
}
printf(
"#\n");
}
end:
TimeOutOff();
if (printEpim) {
printf(
"\n\n# The epimorphism :\n");
PrintEpim();
printf(
"\n\n# The nilpotent quotient :\n");
PrintPcPres();
printf(
"\n\n# The definitions:\n");
PrintDefs();
}
printf(
"# total runtime : %ld msec\n", RunTime() - begin);
if (Gap) printf(
"];\n");
if (Gap) { PrintRawGapPcPres(); }
if (Gap & Verbose)
fprintf(stderr,
"\n");
TimeOutOn();
PrintCollectionTimes();
return 0;
}