GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
####
##
#W anupqopt.gi ANUPQ package Werner Nickel
#W Greg Gamble
##
## Install file for functions to do with option manipulation.
##
#Y Copyright (C) 2001 Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
##
#############################################################################
##
#V PQ_FUNCTION . . . . . . . . . internal functions called by user functions
##
## A record whose fields are (function) names and whose values are the
## internal functions called by the functions with those names.
##
InstallValue( PQ_FUNCTION,
rec( Pq := PQ_EPI_OR_PCOVER,
PqDescendants := PQ_DESCENDANTS,
StandardPresentation := PQ_EPIMORPHISM_STANDARD_PRESENTATION,
PqDescendantsTreeCoclassOne := PqDescendantsTreeCoclassOne
)
);
#############################################################################
##
#V ANUPQoptions . . . . . . . . . . . . . . . . . . . . admissible options
##
## is a record of lists of names of admissible {\ANUPQ} options, such that
## each field is either the name of a (``key'') {\ANUPQ} function and the
## corresponding value is the list of option names that are admissible for
## the function.
##
InstallValue( ANUPQoptions,
rec( # options for `Pq' and `PqEpimorphism'
Pq := [ "Prime",
"ClassBound",
"Exponent",
"Metabelian",
"OutputLevel",
"Relators",
"Identities",
"GroupName",
"SetupFile",
"PqWorkspace",
"RedoPcp" ],
# options for `PqDescendants'
PqDescendants
:= [ "ClassBound",
"OrderBound",
"Relators",
"GroupName",
"StepSize",
"PcgsAutomorphisms",
"RankInitialSegmentSubgroups",
"SpaceEfficient",
"CapableDescendants",
"AllDescendants",
"Exponent",
"Metabelian",
"SubList",
"BasicAlgorithm",
"CustomiseOutput",
"SetupFile",
"PqWorkspace" ],
# options for `[Epimorphism][Pq]StandardPresentation'
StandardPresentation
:= [ "Prime",
"pQuotient",
"ClassBound",
"Relators",
"GroupName",
"PcgsAutomorphisms",
"Exponent",
"Metabelian",
"OutputLevel",
"StandardPresentationFile",
"SetupFile",
"PqWorkspace" ],
# options for `PqDescendantsTreeCoclassOne'
PqDescendantsTreeCoclassOne
:= [ "ClassBound",
"OrderBound",
"Relators",
"GroupName",
"StepSize",
"PcgsAutomorphisms",
"RankInitialSegmentSubgroups",
"SpaceEfficient",
"CapableDescendants",
"AllDescendants",
"Exponent",
"Metabelian",
"SubList",
"BasicAlgorithm",
"CustomiseOutput",
"TreeDepth",
"SetupFile",
"PqWorkspace" ],
PqList
:= [ "SubList" ],
PqPcPresentation
:= [ "Prime",
"ClassBound",
"Exponent",
"Metabelian",
"OutputLevel",
"Relators",
"Identities",
"GroupName" ],
PqNextClass
:= [ "QueueFactor" ],
PqEvaluateIdentities
:= [ "Identities" ],
PqDoExponentChecks
:= [ "Bounds" ],
PqDisplayStructure
:= [ "Bounds" ],
PqDisplayAutomorphisms
:= [ "Bounds" ],
PqSPComputePcpAndPCover
:= [ "Prime",
"ClassBound",
"Exponent",
"Metabelian",
"OutputLevel",
"Relators",
"GroupName" ],
PqSPSavePresentation
:= [ "ClassBound",
"PcgsAutomorphisms",
"StandardPresentationFile" ],
PqPGSetDescendantToPcp
:= [ "Filename" ],
PqPGSupplyAutomorphisms
:= [ "NumberOfSolubleAutomorphisms",
"RelativeOrders" ],
PqPGConstructDescendants
:= [ "ClassBound",
"OrderBound",
"StepSize",
"PcgsAutomorphisms",
"RankInitialSegmentSubgroups",
"SpaceEfficient",
"CapableDescendants",
"AllDescendants",
"Exponent",
"Metabelian",
"BasicAlgorithm",
"CustomiseOutput" ],
PqAPGDegree
:= [ "Exponent" ],
PqAPGPermutations
:= [ "PcgsAutomorphisms",
"SpaceEfficient",
"PrintAutomorphisms",
"PrintPermutations" ],
PqAPGOrbits
:= [ "PcgsAutomorphisms",
"SpaceEfficient",
"CustomiseOutput" ],
PqAPGOrbitRepresentatives
:= [ "PcgsAutomorphisms",
"SpaceEfficient",
"CapableDescendants",
"AllDescendants",
"Exponent",
"Metabelian",
"CustomiseOutput",
"Filename" ],
PqAPGSingleStage
:= [ "StepSize",
"PcgsAutomorphisms",
"RankInitialSegmentSubgroups",
"SpaceEfficient",
"CapableDescendants",
"AllDescendants",
"Exponent",
"Metabelian",
"BasicAlgorithm",
"CustomiseOutput" ]
)
);
#############################################################################
##
#F AllANUPQoptions() . . . . . . . . lists all options of the ANUPQ package
##
## lists all the {\GAP} options defined for functions of the {\ANUPQ}
## package.
##
InstallGlobalFunction( AllANUPQoptions, function()
return Set( Concatenation(
List( RecNames(ANUPQoptions), fld -> ANUPQoptions.(fld) )
) );
end );
#############################################################################
##
#V ANUPQGlobalOptions . . . . . options that can be set globally by PqStart
##
## A list of the options that `PqStart' can set and thereby make available
## to any function interacting with the {\ANUPQ} process initiated by
## `PqStart'.
##
InstallValue( ANUPQGlobalOptions, [ "Prime", "Exponent", "Relators" ] );
#############################################################################
##
#V ANUPQoptionChecks . . . . . . . . . . . the checks for admissible options
##
## A record whose fields are the names of admissible ANUPQ options and whose
## values are one-argument functions that return `true' when given a value
## that is a valid value for the option, and `false' otherwise.
##
InstallValue( ANUPQoptionChecks,
rec( Prime := x -> IsInt(x) and IsPrimeInt(x),
pQuotient := IsPcGroup and IsPGroup,
ClassBound := IsPosInt,
OrderBound := IsPosInt,
Exponent := IsPosInt,
Metabelian := IsBool,
GroupName := IsString,
Identities := x -> IsList(x) and ForAll(x, IsFunction),
OutputLevel := x -> x in [0..3],
Relators := x -> IsList(x) and ForAll(x, IsString),
StandardPresentationFile := IsString,
SetupFile := IsString,
PqWorkspace := IsPosInt,
StepSize := x -> IsPosInt(x) or
(IsList(x) and ForAll(x, IsPosInt)),
PcgsAutomorphisms := IsBool,
BasicAlgorithm := IsBool,
RankInitialSegmentSubgroups := x -> x = 0 or IsPosInt(x),
SpaceEfficient := IsBool,
CapableDescendants := IsBool,
AllDescendants := IsBool,
SubList := x -> IsPosInt(x) or
(IsSet(x) and ForAll(x, IsInt)
and IsPosInt(x[1])),
CustomiseOutput := IsRecord,
Bounds := x -> IsSet(x) and 2 = Length(x) and
ForAll(x, IsPosInt),
QueueFactor := IsPosInt,
RedoPcp := IsBool,
PrintAutomorphisms := IsBool,
PrintPermutations := IsBool,
NumberOfSolubleAutomorphisms := x -> x = 0 or IsPosInt(x),
RelativeOrders := x -> IsList(x) and ForAll(x, IsPosInt),
Filename := IsString,
TreeDepth := IsPosInt
)
);
#############################################################################
##
#V ANUPQoptionTypes . . . . . . the types (in words) for admissible options
##
## A record whose fields are the names of admissible ANUPQ options and whose
## values are valid types of the options in plain words.
##
InstallValue( ANUPQoptionTypes,
rec( Prime := "prime integer",
pQuotient := "pc p-group",
ClassBound := "positive integer",
OrderBound := "positive integer",
Exponent := "positive integer",
Metabelian := "boolean",
GroupName := "string",
Identities := "list of functions",
OutputLevel := "integer in [0..3]",
Relators := "list of strings",
StandardPresentationFile := "string",
SetupFile := "string",
PqWorkspace := "positive integer",
StepSize := "positive integer or positive integer list",
PcgsAutomorphisms := "boolean",
BasicAlgorithm := "boolean",
RankInitialSegmentSubgroups := "nonnegative integer",
SpaceEfficient := "boolean",
CapableDescendants := "boolean",
AllDescendants := "boolean",
SubList
:= "pos've integer or increasing pos've integer list",
CustomiseOutput := "record",
Bounds := "pair of increasing positive integers",
QueueFactor := "positive integer",
RedoPcp := "boolean",
PrintAutomorphisms := "boolean",
PrintPermutations := "boolean",
NumberOfSolubleAutomorphisms := "nonnegative integer",
RelativeOrders := "list of positive integers",
Filename := "string",
TreeDepth := "positive integer"
)
);
#############################################################################
##
#F PQ_OTHER_OPTS_CHK( <funcname>, <interactive> ) . check opts belong to f'n
##
## checks the `OptionsStack' only has recognised options for (generic)
## function <funcname> and if not and if `ANUPQWarnOfOtherOptions = true'
## (see~"ANUPQWarnOfOtherOptions") `Info's the non-<funcname> options at
## `InfoANUPQ' level 1.
##
## The argument <interactive> is only relevant for those functions that have
## both an interactive and non-interactive form, namely those with fields in
## `PQ_FUNCTION', for which some options need to be excluded.
##
InstallGlobalFunction(PQ_OTHER_OPTS_CHK, function(funcname, interactive)
local optnames, excopts, generic, interactivestr;
if ANUPQWarnOfOtherOptions and ValueOption("recursive") = fail and
not IsEmpty(OptionsStack) then
excopts := [];
if funcname in RecNames(PQ_FUNCTION) then
if interactive then
excopts := ["PqWorkspace", "SetupFile"];
interactivestr := "interactive";
else
interactivestr := "non-interactive";
if funcname = "Pq" then
excopts := ["RedoPcp"];
fi;
fi;
generic := "generic ";
else
generic := "";
fi;
optnames := Difference( RecNames( OptionsStack[ Length(OptionsStack) ] ),
Difference( ANUPQoptions.(funcname), excopts ) );
if funcname = "Pq" then
optnames := Difference( optnames, ["PqEpiOrPCover"] );
fi;
if not IsEmpty(optnames) then
Info( InfoANUPQ + InfoWarning, 1,
"ANUPQ Warning: Options: ", optnames, " ignored" );
if IsSubset(excopts, optnames) then
Info( InfoANUPQ + InfoWarning, 1,
"(invalid for ", interactivestr, " call of generic function: `",
funcname, "')." );
else
Info( InfoANUPQ + InfoWarning, 1,
"(invalid for ", generic, "function: `", funcname, "')." );
fi;
fi;
fi;
end);
#############################################################################
##
#F VALUE_PQ_OPTION( <optname> ) . . . . . . . . . enhancement of ValueOption
#F VALUE_PQ_OPTION( <optname>, <defaultval> )
#F VALUE_PQ_OPTION( <optname>, <datarec> )
#F VALUE_PQ_OPTION( <optname>, <defaultval>, <datarec> )
##
## If the value <optval> of <optname> is not `fail' and it is an ok value
## for <optname> then <optval> is returned; if <optval> is not an ok value
## an error is signalled. If <optval> is `fail' and <datarec> is given and
## <datarec>.(<optname>) is already bound then that value is returned;
## otherwise, if <optval> is `fail' and a default value <defaultval>
## different from `fail' is supplied then <defaultval> is returned.
## Supplying a <defaultval> of `fail' is special; it indicates that option
## <optname> must have a value i.e. <optval> is not allowed to be `fail' and
## if it is an error is signalled. If a <datarec> argument is supplied,
## which must be a record, then the return value, if not `fail' and a legal
## value, is also stored in `<datarec>.(<optname>)'.
##
## *Note:* <defaultval> cannot be a record.
##
InstallGlobalFunction(VALUE_PQ_OPTION, function(arg)
local optname, optval, len;
optname := arg[1];
optval := ValueOption(optname);
len := Length(arg);
if optval = fail then
if 1 = len then
return optval;
elif IsRecord( arg[len] ) and IsBound( arg[len].(optname) ) then
# return the previously recorded value
return arg[len].(optname);
elif not IsRecord(arg[2]) then
if arg[2] = fail then
Error("you must supply a value for option: \"", optname, "\"\n");
fi;
optval := arg[2];
fi;
elif not ANUPQoptionChecks.(optname)(optval) then
Error("\"", optname, "\" value must be a ",
ANUPQoptionTypes.(optname), "\n");
fi;
if (optval <> fail) and (2 <= len) and IsRecord(arg[len]) then
arg[len].(optname) := optval;
fi;
return optval;
end);
#############################################################################
##
#F PQ_OPTION_CHECK(<basefn>,<datarec>) . check optns present/setable if nec.
##
## If `<basefn> = "Pq"' (i.e. this check is carried out if the function
## called is `Pq', `PqEpimorphism' or `PqPCover') check that the option
## `Prime' has been passed or, in a special `PqPCover' case, can be
## determined from the `<datarec>.group' which must be present. In the
## special `PqPCover' case, the options `Prime' and `ClassBound' determined
## are saved in <datarec>. If `Prime' is not supplied in the cases where it
## needs to be, an error is emitted.
##
InstallGlobalFunction(PQ_OPTION_CHECK, function(basefn, datarec)
local optname, out;
if basefn = "Pq" then
if datarec.calltype = "interactive" then
if VALUE_PQ_OPTION("RedoPcp", false) then
PQ_UNBIND(datarec, ["Prime", "ClassBound", "Exponent", "Metabelian",
"pCover", "pQuotient", "pQepi"] );
fi;
fi;
if ValueOption("PqEpiOrPCover") = "pCover" and
HasIsPGroup(datarec.group) and IsPGroup(datarec.group) then
if VALUE_PQ_OPTION("Prime", datarec) = fail then
if not HasPrimePGroup(datarec.group) then
Error( "supplied group is not known to be a p-group or p unknown.\n",
"Option `Prime' must be supplied" );
else
datarec.Prime := PrimePGroup(datarec.group);
fi;
fi;
if VALUE_PQ_OPTION("ClassBound", datarec) = fail and
HasPClassPGroup(datarec.group) then
datarec.ClassBound := PClassPGroup(datarec.group);
fi;
else
VALUE_PQ_OPTION("Prime", fail, datarec);
fi;
VALUE_PQ_OPTION("ClassBound", 63, datarec);
elif basefn = "StandardPresentation" then
if VALUE_PQ_OPTION("Prime", datarec) = fail and
VALUE_PQ_OPTION("pQuotient", datarec) = fail then
if IsPcGroup(datarec.group) and IsPGroup(datarec.group) then
datarec.Prime := PrimePGroup(datarec.group);
else
Error( "since group of process is not a pc p-group, a prime or\n",
"p-quotient (pc group) of the group of the process ",
"must be supplied\n" );
fi;
fi;
fi;
end);
#############################################################################
##
#F PQ_CUSTOMISE_OUTPUT(<datarec>, <subopt>, <suboptstring>, <suppstrings>)
##
## writes the required output to the `pq' binary for the sub-option <subopt>
## of the option `CustomiseOutput', the value of that option having
## previously been stored in `<datarec>.des.CustomiseOutput'; <suboptstring>
## is part of the comment written to the `pq' binary for the sub-option and
## <suppstrings> is a list of such comments for the supplementary questions
## asked by the `pq' binary for the sub-option <subopt>.
##
InstallGlobalFunction( PQ_CUSTOMISE_OUTPUT,
function(datarec, subopt, suboptstring, suppstrings)
local optrec, isOptionSet, i;
optrec := datarec.des.CustomiseOutput;
if IsEmpty(suppstrings) then
isOptionSet := IsBound( optrec.(subopt) ) and optrec.(subopt) in [1, true];
ToPQ_BOOL(datarec, isOptionSet, suboptstring);
elif IsBound( optrec.(subopt) ) and IsList( optrec.(subopt) ) then
ToPQ(datarec, [ 0 ], [ " #customise ", suboptstring ]);
for i in [1 .. Length(suppstrings)] do
isOptionSet := IsBound( optrec.(subopt)[i] ) and
optrec.(subopt)[i] in [1, true];
ToPQ_BOOL(datarec, isOptionSet, suppstrings[i]);
od;
else
ToPQ(datarec, [ 1 ], [ " #default ", suboptstring ]);
fi;
end);
#############################################################################
##
#F PQ_APG_CUSTOM_OUTPUT(<datarec>, <subopt>, <suboptstring>, <suppstrings>)
##
## writes the required output to the `pq' binary for the sub-option <subopt>
## of the option `CustomiseOutput', as required by an Advanced p-Group
## Generation Menu item, the value of that option having previously been
## stored in `<datarec>.des.CustomiseOutput'; <suboptstring> is part of the
## comment written to the `pq' binary for the sub-option and <suppstrings>
## is a list of such comments for the supplementary questions asked by the
## `pq' binary for the sub-option <subopt>.
##
InstallGlobalFunction( PQ_APG_CUSTOM_OUTPUT,
function(datarec, subopt, suboptstring, suppstrings)
local optrec, optlist, isOptionSet, i;
optrec := datarec.des.CustomiseOutput;
if not( IsRecord(optrec) and IsBound( optrec.(subopt) ) and
IsList( optrec.(subopt) ) ) then
optlist := [];
datarec.des.CustomiseOutput.(subopt) := optlist;
else
optlist := optrec.(subopt);
fi;
for i in [1 .. Length(suppstrings)] do
isOptionSet := IsBound( optlist[i] ) and optlist[i] in [1, true];
ToPQ_BOOL(datarec, isOptionSet, suppstrings[i]);
od;
end);
#############################################################################
##
#F SET_ANUPQ_OPTIONS( <funcname>, <fnname> ) . set options from OptionStack
##
## When called by a function with name <funcname> sets the options from
## `OptionsStack' checking that they are a subset of
## `ANUPQoptions.<fnname>'. Both <funcname> and <fnname> should be strings.
##
InstallGlobalFunction( SET_ANUPQ_OPTIONS, function( funcname, fnname )
local optrec, optnames, opt;
# there should be options
if IsEmpty( OptionsStack ) then
# no options??
optrec := rec();
Info( InfoANUPQ, 1, funcname, " called with no options!" );
else
optrec := ShallowCopy( OptionsStack[ Length( OptionsStack ) ] );
optnames := Set( REC_NAMES(optrec) );
SubtractSet( optnames, Set( ANUPQoptions.(fnname) ) );
Info( InfoANUPQ, 2, funcname, " called with options: ",
OptionsStack[ Length( OptionsStack ) ] );
if 0 < Length(optnames) then
# it's not an error to have unknown options,
# function may have been called recursively and the
# options may be intended for some other function
Info( InfoWarning + InfoANUPQ, 2,
funcname, " called with unknown options: ", optnames);
fi;
for opt in optnames do
Unbind( optrec.(opt) );
od;
fi;
return optrec;
end );
#############################################################################
##
#F ANUPQoptError( <funcname>, <illegal> ) . . . . . create an error message
##
## creates an error message for the function with name <funcname>. If
## <illegal> is a string it is taken to be the first line of the error
## message. Otherwise <illegal> should be alist of illegal options (strings)
## found. The error message (string) returned also gives the list of valid
## options together with the value types expected for function <funcname>.
##
InstallGlobalFunction( ANUPQoptError, function( funcname, illegal )
local Optstring, Valstring, errmsg, optname;
Optstring := optname -> Concatenation("\"", optname, "\"");
Valstring := optval -> Concatenation("<", optval, ">");
if IsString(illegal) then
errmsg := illegal;
else # IsList(illegal)
errmsg := Concatenation("Illegal ", funcname, " option");
if Length(illegal) > 1 then
Append(errmsg, "s");
fi;
Append(errmsg, ": ");
Append(errmsg, JoinStringsWithSeparator( List(illegal, Optstring) ));
fi;
Append(errmsg, Concatenation(".\nValid ", funcname, " options:\n"));
for optname in ANUPQoptions.(funcname) do
Append(errmsg, " ");
Append(errmsg, Optstring(optname));
if ANUPQoptionChecks.(optname) <> IsBool then
Append(errmsg, ", ");
Append(errmsg, Valstring( ANUPQoptionTypes.(optname) ));
fi;
Append(errmsg, "\n");
od;
return errmsg;
end );
#############################################################################
##
#F ANUPQextractOptions( <funcname>, <args> ) . . . . . . . . extract options
##
## extracts options from <args> for function with name <funcname> and
## returns a record suitable for use with `PushOptions'. Abbreviations are
## allowed for option names so long as each abbreviates a unique option
## name.
##
InstallGlobalFunction( ANUPQextractOptions, function(funcname, args)
local Match, error, optrec, i, optname;
# allow to give only a prefix
Match := function( argi )
local matches;
if IsString(argi) then
matches := Filtered(ANUPQoptions.(funcname),
optname -> 0 < Length(argi) and
Length(argi) <= Length(optname) and
optname{[1..Length(argi)]} = argi);
if 1 = Length(matches) then
return matches[1];
fi;
error := Concatenation( "argument: \"", argi,
"\" doesn't abbreviate a unique option");
else
error := Concatenation( "argument: ", String(argi),
" is not a (non-null) string (option name)"
);
fi;
return fail;
end;
# extract options from args
optrec := rec();
i := 1;
while i <= Length(args) do
optname := Match( args[i] );
if optname = fail then
Error( ANUPQoptError( funcname, error ) );
elif ANUPQoptionChecks.(optname) = IsBool then
optrec.(optname) := true;
i := i + 1;
elif i = Length(args) then
# all remaining options are non-boolean and expect a value to
# follow
Error( ANUPQoptError(
funcname,
Concatenation( "Expected value for option: ", args[i] )
) );
else
# checking values are ok is done later
optrec.(optname) := args[i + 1];
i := i + 2;
fi;
od;
return optrec;
end );
#E anupqopt.gi . . . . . . . . . . . . . . . . . . . . . . . . . . ends here