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);