diff --git a/PLAN.md b/PLAN.md
new file mode 100644
index 000000000..beabcbd20
--- /dev/null
+++ b/PLAN.md
@@ -0,0 +1,6 @@
+CachedSLPToNiceGenerators
+Completely independent implementation. Computes an SLP and maybe also the
+nicegens, then stores it. Then, whenever someone needs another
+SLPToNiceGenerators, this can be taken and evaluated.
+Wherever this is called, assert that this and `CalcNiceGens` return the same
+group elements, maybe even SLPs with equal `LinesOfSLP`.
diff --git a/doc/recognition.xml b/doc/recognition.xml
index 92060023e..c7832939e 100644
--- a/doc/recognition.xml
+++ b/doc/recognition.xml
@@ -264,7 +264,7 @@ returns true.
-The following two attributes are concerned with the relation between
+The following four attributes are concerned with the relation between
the original generators and the nice generators for a node.
They are used to transport this information from a successful find
homomorphism method up to the recursive recognition function:
@@ -272,7 +272,6 @@ homomorphism method up to the recursive recognition function:
<#Include Label="calcnicegens">
<#Include Label="CalcNiceGensGeneric">
<#Include Label="CalcNiceGensHomNode">
-<#Include Label="CalcNiceGens">
<#Include Label="slptonice">
The following three attributes are concerned with the administration of the
diff --git a/gap/base/recognition.gd b/gap/base/recognition.gd
index cf463517b..1c1fb30c9 100644
--- a/gap/base/recognition.gd
+++ b/gap/base/recognition.gd
@@ -99,23 +99,24 @@ DeclareAttribute( "Homom", IsRecogNode, "mutable" );
## <#GAPDoc Label="NiceGens">
##
##
+##
##
-## The value of this attribute must be set for all nodes and contains
-## the nice generators. The function of the
+## The value of this attribute contains the nice generators and must be set
+## for all nodes. The function of the
## node will write its straight line program in terms of these nice
-## generators. For leaf nodes, the find homomorphism method is responsible
-## to set the value of . By default, the original
-## generators of the group at this node are taken. For a homomorphism
-## (or isomorphism), the will be the concatenation
-## of preimages of the of the image group
+## generators.
+##
+## For a leaf node, can be any list of generators.
+##
+## For a splitting node, is the concatenation
+## of preimages of the of the factor group
## (see ) and
-## the of the kernel. A find homomorphism method
-## does not have to set if it finds a homomorphism.
-## Note however, that such a find homomorphism method has to ensure somehow,
-## that preimages of the of the image group
-## can be acquired. See ,
-## and
-## for instructions.
+## the of the kernel.
+##
+## To compute the nice generators, a method with two-arguments is installed
+## for which takes the value of the attribute
+## and calls it with the arguments ri and
+## origgens. For more information see .
##
##
## <#/GAPDoc>
@@ -202,21 +203,30 @@ DeclareAttribute( "validatehomominput", IsRecogNode);
##
##
##
-## To make the recursion work, we have to acquire preimages of the
-## nice generators in image groups under the homomorphism found.
-## But we want to keep the information, how the nice generators
-## were found, locally at the node where they were found. This
-## attribute solves this problem of acquiring preimages in the following
-## way: Its value must be a function, taking the recognition
-## node ri as first argument, and a list origgens of
-## preimages of the
-## original generators of the current node, and has to
-## return corresponding preimages of the nice generators. Usually this
-## task can be done by storing a straight line program writing the
-## nice generators in terms of the original generators and executing
-## this with inputs origgens. Therefore the default value of
-## this attribute is the function
-## described below.
+## Stores a function func(ri2, gens2) which computes group elements
+## of ri2 by evaluating words in gens2.
+## These words must be chosen such that, if ri2 is equal to
+## ri and gens2 is equal to
+## GeneratorsOfGroup(Grp(ri)), then func returns the nice
+## generators of ri.
+## Correspondingly, if gens2 is another list of group elements, then
+## the words which yield the nice generators of ri are evaluated in
+## gens2.
+##
+## This us used by the recursive group recognition to compute preimages of
+## nice generators as follows:
+## if imagenode is the image node of a node node and
+## nodegens are the generators of Grp(node),
+## then func(imagenode, nodegens) computes the preimages of the
+## nice generators of imagenode.
+##
+## Usually func stores a straight line program writing the nice
+## generators in terms of the generators of the group represented
+## by ri and executes this with inputs gens2.
+##
+## The default values of this attribute are the functions
+## and
+## .
##
##
## <#/GAPDoc>
@@ -547,18 +557,6 @@ DeclareGlobalFunction( "TryFindHomMethod" );
# Helper functions for the generic part:
-## <#GAPDoc Label="CalcNiceGens">
-##
-##
-## a list of preimages of the nice generators
-##
-## This is a wrapper function which extracts the value of the attribute
-## and calls that function with the arguments
-## ri and origgens.
-##
-##
-## <#/GAPDoc>
-DeclareGlobalFunction( "CalcNiceGens" );
DeclareGlobalFunction( "ValidateHomomInput" );
## <#GAPDoc Label="CalcNiceGensGeneric">
diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi
index 5c4f6057e..1045a9bf8 100644
--- a/gap/base/recognition.gi
+++ b/gap/base/recognition.gi
@@ -23,7 +23,7 @@ RECOG_ViewObj := function( level, ri )
if IsReady(ri) then
Print("ImageElm(Homom(ri),x))),
- methodsforfactor(ri), depthString, forfactor(ri) ); # TODO: change forfactor to hintsForFactor??)
+ methodsforfactor(ri), depthString, forfactor(ri) );
Remove(depthString);
- PrintTreePos("F",depthString,H);
+ PrintTreePos("I",depthString,H);
SetImageRecogNode(ri,rifac);
SetRIParent(rifac,ri);
@@ -555,7 +566,7 @@ InstallGlobalFunction( RecogniseGeneric,
# Now we want to have preimages of the new generators in the image:
Info(InfoRecog,2,"Calculating preimages of nice generators.");
- ri!.pregensfacwithmem := CalcNiceGens(rifac, ri!.gensHmem);
+ ri!.pregensfacwithmem := NiceGens(rifac, ri!.gensHmem);
Setpregensfac(ri, StripMemory(ri!.pregensfacwithmem));
# Now create the kernel generators with the stored method:
@@ -654,14 +665,8 @@ InstallGlobalFunction( RecogniseGeneric,
fi;
until done;
- if IsReady(riker) then # we are only ready when the kernel is
- # Now make the two projection slps:
- SetNiceGens(ri,Concatenation(pregensfac(ri), NiceGens(riker)));
- #ll := List([1..Length(NiceGens(rifac))],i->[i,1]);
- #ri!.proj1 := StraightLineProgramNC([ll],Length(NiceGens(ri)));
- #ll := List([1..Length(NiceGens(riker))],
- # i->[i+Length(NiceGens(rifac)),1]);
- #ri!.proj2 := StraightLineProgramNC([ll],Length(NiceGens(ri)));
+ # we are only ready when the kernel is
+ if IsReady(riker) then
SetFilterObj(ri,IsReady);
fi;
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
@@ -678,11 +683,6 @@ InstallGlobalFunction( ValidateHomomInput,
fi;
end );
-InstallGlobalFunction( CalcNiceGens,
- function(ri,origgens)
- return calcnicegens(ri)(ri,origgens);
- end );
-
InstallGlobalFunction( CalcNiceGensGeneric,
# generic function using an slp:
function(ri,origgens)
@@ -696,16 +696,32 @@ InstallGlobalFunction( CalcNiceGensGeneric,
InstallGlobalFunction( CalcNiceGensHomNode,
# function for the situation on a homomorphism node (non-Leaf):
function(ri, origgens)
- local nicegens, kernelgens;
+ local nicegens, nicekernelgens, x, kernelgens;
# compute preimages of the nicegens of the image group
- nicegens := CalcNiceGens(ImageRecogNode(ri), origgens);
+ nicegens := NiceGens(ImageRecogNode(ri), origgens);
# Is there a non-trivial kernel? then add its nicegens
if HasKernelRecogNode(ri) and KernelRecogNode(ri) <> fail then
# we cannot just use gensN(KernelRecogNode(ri)) here, as those values are defined
# relative to the original generators we used during recognition; but
# the origgens passed to this function might differ
- kernelgens := ResultOfStraightLineProgram(gensNslp(ri), origgens);
- Append(nicegens, CalcNiceGens(KernelRecogNode(ri), kernelgens));
+ if origgens = GeneratorsOfGroup(Grp(ri)) then
+ # Print("HIT\n");
+ #Error("break");
+ nicekernelgens := NiceGens(KernelRecogNode(ri));
+ if IsObjWithMemory(origgens[1]) then
+ nicekernelgens := GeneratorsWithMemory(nicekernelgens);
+ # HACK!
+ for x in nicekernelgens do
+ x!.slp := origgens[1]!.slp;
+ od;
+ fi;
+ else
+ # when recognizing, origgens have memory. When recognition is finished,
+ # these are usually without memory?
+ kernelgens := ResultOfStraightLineProgram(gensNslp(ri), origgens);
+ nicekernelgens := NiceGens(KernelRecogNode(ri), kernelgens);
+ fi;
+ Append(nicegens, nicekernelgens);
fi;
return nicegens;
end );
@@ -858,7 +874,7 @@ InstallGlobalFunction( "SLPforNiceGens", function(ri)
local l,ll,s;
l := List( [1..Length(GeneratorsOfGroup(Grp(ri)))], x->() );
l := GeneratorsWithMemory(l);
- ll := CalcNiceGens(ri,l);
+ ll := NiceGens(ri,l);
s := SLPOfElms(ll);
if s <> fail then
SlotUsagePattern(s);
@@ -955,7 +971,9 @@ RECOG.TestGroup := function(g,proj,size, optionlist...)
if IsEmpty(gens) then
gens := [One(g)];
fi;
- l := CalcNiceGens(ri,gens);
+ l := NiceGens(ri,gens);
+ l := NiceGens(ri,gens);
+ # Test whether SLPForNiceGens gives the same slps
repeat
count := count + 1;
#Print(".\c");
diff --git a/gap/generic/KnownNilpotent.gi b/gap/generic/KnownNilpotent.gi
index a4525459f..88923560e 100644
--- a/gap/generic/KnownNilpotent.gi
+++ b/gap/generic/KnownNilpotent.gi
@@ -66,8 +66,8 @@ RECOG.CalcNiceGensKnownNilpotent := function(ri,origgens)
local kernelgens;
kernelgens := List([1..Length(ri!.decompositionExponents)],
i -> origgens[i]^ri!.decompositionExponents[i]);
- return Concatenation(CalcNiceGens(ImageRecogNode(ri), origgens),
- CalcNiceGens(KernelRecogNode(ri), kernelgens));
+ return Concatenation(NiceGens(ImageRecogNode(ri), origgens),
+ NiceGens(KernelRecogNode(ri), kernelgens));
end;
#! @BeginChunk KnownNilpotent
diff --git a/misc/colva/DPleaf.g b/misc/colva/DPleaf.g
index 8d00a8fe5..7ebe6f06e 100644
--- a/misc/colva/DPleaf.g
+++ b/misc/colva/DPleaf.g
@@ -320,7 +320,7 @@ SolveLeafDP := function(ri,rifac,name)
blkdata := RecogniseLeaf(riH1,blk,name);;
# Get the inverse images of the nice generators of blk in H1
- invims := CalcNiceGens(blkdata,GeneratorsOfGroup(H1));
+ invims := NiceGens(blkdata,GeneratorsOfGroup(H1));
Yhat := ShallowCopy(invims);
blktoH1 := GroupHomomorphismByFunction(blk,Grp(ri),g->
ResultOfStraightLineProgram( SLPforElement(blkdata,g),invims));
diff --git a/misc/colva/Evaluate.g b/misc/colva/Evaluate.g
index 967275608..5eebdaf22 100644
--- a/misc/colva/Evaluate.g
+++ b/misc/colva/Evaluate.g
@@ -242,7 +242,7 @@ InstallGlobalFunction( NormalTree,
# Now we want to have preimages of the new generators in the image:
if not IsBound(ri!.pregensfac) then
Info(InfoRecognition,1,"Calculating preimages of nice generators.");
- Setpregensfac( ri, CalcNiceGens(rifac,GeneratorsOfGroup(H)));
+ Setpregensfac( ri, NiceGens(rifac,GeneratorsOfGroup(H)));
fi;
Setcalcnicegens(ri,CalcNiceGensHomNode);
diff --git a/misc/colva/README.md b/misc/colva/README.md
new file mode 100644
index 000000000..a694782a2
--- /dev/null
+++ b/misc/colva/README.md
@@ -0,0 +1,4 @@
+This is probably an attempt by Colva Roney-Dougal to port an implementation of
+Mark Stather (a PhD Student of Derek Holt) for computing sylow subgroups of
+matrix groups. That may have needed "normal trees" and chief series. The main
+file might be `NSM.g`?
diff --git a/tst/working/quick/bugfix.tst b/tst/working/quick/bugfix.tst
index bb03aa115..fcdc3f0b0 100644
--- a/tst/working/quick/bugfix.tst
+++ b/tst/working/quick/bugfix.tst
@@ -34,27 +34,27 @@ gap> old:=InfoLevel(InfoRecog);;
gap> SetInfoLevel(InfoRecog, 0);
gap> RecogniseGroup(SL(2,2));
K:
gap> RecogniseGroup(SL(2,3));
K:
+ I:
K:>
gap> RecogniseGroup(SL(2,4));
K:
gap> RecogniseGroup(SL(2,5));
K:
+ I:
K:>
gap> SetInfoLevel(InfoRecog, old);