From 0b2296b0cc415be416ab49ae6eab03daed6c03a1 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Mon, 10 Jan 2022 14:07:53 +0100 Subject: [PATCH 01/14] WIP: mandarins Old commit msg of a commit which was squashed into this one and which was nonsense: RecogniseGeneric: recognise image only once This is preparation for the implementation of Mandarins. The following case is going to be handled by the Mandarins. Previously, if in an image node writing of random elements as SLPs in the image node's nice generators failed, that image node would be discarded and recomputed. --- gap/base/recognition.gd | 7 + gap/base/recognition.gi | 342 ++++++++++++++++++++++++++++++---------- 2 files changed, 269 insertions(+), 80 deletions(-) diff --git a/gap/base/recognition.gd b/gap/base/recognition.gd index ca6cbfea1..3e507a91d 100644 --- a/gap/base/recognition.gd +++ b/gap/base/recognition.gd @@ -470,6 +470,13 @@ BindGlobal( "FindHomMethodsGeneric", rec() ); ## <#/GAPDoc> BindGlobal( "SLPforElementFuncsGeneric", rec() ); +# TODO Document mandarins +# Refer to overview paper by Baarnhielm, Holt, Charles, Eamonn, sections "5.2 +# The main algorithm" and "5.4 Crisis management". +# Explain safe and unsafe nodes. +BindGlobal("MANDARIN_CRISIS", MakeImmutable("MANDARIN_CRISIS")); +BindGlobal("NUM_MANDARINS_DEFAULT_VALUE", 100); +DeclareFilter( "IsSafeForMandarins" ); # Our global functions for the main recursion: diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index 6db8eed00..6bc39fdcf 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -91,25 +91,25 @@ InstallMethod( ViewObj, "for recognition nodes", [IsRecogNode], InstallGlobalFunction( RecognisePermGroup, function(G) - return RecogniseGeneric(G, FindHomDbPerm, "", rec()); + return RecogniseGeneric(G, FindHomDbPerm, "", rec(), fail, true); end); InstallGlobalFunction( RecogniseMatrixGroup, function(G) - return RecogniseGeneric(G, FindHomDbMatrix, "", rec()); + return RecogniseGeneric(G, FindHomDbMatrix, "", rec(), fail, true); end); InstallGlobalFunction( RecogniseProjectiveGroup, function(G) - return RecogniseGeneric(G, FindHomDbProjective, "", rec()); + return RecogniseGeneric(G, FindHomDbProjective, "", rec(), fail, true); end); InstallGlobalFunction( RecogniseGroup, function(G) if IsPermGroup(G) then - return RecogniseGeneric(G, FindHomDbPerm, "", rec()); + return RecogniseGeneric(G, FindHomDbPerm, "", rec(), fail, true); elif IsMatrixGroup(G) then - return RecogniseGeneric(G, FindHomDbMatrix, "", rec()); + return RecogniseGeneric(G, FindHomDbMatrix, "", rec(), fail, true); else ErrorNoReturn("Only matrix and permutation groups are supported"); fi; @@ -228,6 +228,28 @@ InstallOtherMethod( RecogNode, return RecogNode(H, projective, rec()); end ); +RECOG.SetXNodeForNodeAndString := function(r, s) + if not s = MANDARIN_CRISIS then + ErrorNoReturn(" must be MANDARIN_CRISIS"); + fi; + return; + end; + +InstallMethod( SetParentRecogNode, + "for a recognition node and a string", + [ IsRecogNode, IsString ], + RECOG.SetXNodeForNodeAndString); + +InstallMethod( SetImageRecogNode, + "for a recognition node and a string", + [ IsRecogNode, IsString ], + RECOG.SetXNodeForNodeAndString); + +InstallMethod( SetKernelRecogNode, + "for a recognition node and a string", + [ IsRecogNode, IsString ], + RECOG.SetXNodeForNodeAndString); + # Sets the stamp used by RandomElm, RandomElmOrd, and related functions. RECOG.SetPseudoRandomStamp := function(g,st) if IsBound(g!.pseudorandomfunc) then @@ -451,12 +473,47 @@ InstallGlobalFunction( PrintTreePos, fi; end ); +BindGlobal("TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis", +function(ri) + local gensNWasEmpty, targetNrGensN, kernelGenerationSuccess; + gensNWasEmpty := IsEmpty(gensN(ri)); + if gensNWasEmpty then + # This gets reduced during each iteration to a minimal value of 1, to + # account for the case where the kernel only has two elements. The + # findgensNmeth might discard trivial or duplicate generators. In that + # case we can never find more than one generator, if the kernel has + # size two. + targetNrGensN := 5; + else + targetNrGensN := 2 * Length(gensN(ri)); + fi; + Info(InfoRecog, 2, + "Enlarging the kernel's generating set due to a mandarin crisis."); + repeat + if gensNWasEmpty and targetNrGensN > 1 then + targetNrGensN := targetNrGensN - 1; + fi; + # Create additional kernel generators with the stored method: + # kernelGenerationSuccess is either true or fail. + kernelGenerationSuccess := + CallFuncList(findgensNmeth(ri).method, + Concatenation([ri],findgensNmeth(ri).args)); + if kernelGenerationSuccess = fail then + return false; + fi; + until Length(gensN(ri)) >= targetNrGensN; + SetgensNslp(ri,SLPOfElms(gensN(ri))); + SlotUsagePattern(gensNslp(ri)); + return true; +end); + InstallGlobalFunction( RecogniseGeneric, - function(H, methoddb, depthString, knowledge) + function(H, methoddb, depthString, knowledge, mandarins, isSafeForMandarins) # Assume all the generators have no memory! - local N,depth,done,i,l,ll,allmethods, - hint, - proj1,proj2,ri,rifac,riker,s,x,y,z,succ,counter; + local depth, ri, allmethods, s, imageMandarins, y, counter_image, rifac, + kernelGenerationSuccess, l, ll, kernelMandarins, x, z, + mandarinSuccess, immediateVerificationSuccess, N, riker, + enlargeKernelSuccess, i; depth := Length(depthString); @@ -464,15 +521,30 @@ InstallGlobalFunction( RecogniseGeneric, Info(InfoRecog,4,"Recognising: ",H); if Length(GeneratorsOfGroup(H)) = 0 then + # FIXME: shouldn't we just, like, finish here immediately? H := Group([One(H)]); fi; + if mandarins = fail then + Assert(0, depth = 0); + # HACK: We don't want the mandarins to be reused by any computation. + # Since PseudoRandom is hacked, it is important that we generate the + # mandarins before calling RecogNode. Otherwise the mandarins would be + # reused by RandomElm and RandomElmOrd. + # TODO: enable passing NUM_MANDARINS as optional arg + mandarins := List([1..NUM_MANDARINS_DEFAULT_VALUE], i -> PseudoRandom(H)); + fi; + + # Set up the record and the group object: ri := RecogNode( H, IsIdenticalObj( methoddb, FindHomDbProjective ), knowledge ); + if isSafeForMandarins then + SetFilterObj(ri, IsSafeForMandarins); + fi; # was here earlier: Setcalcnicegens(ri,CalcNiceGensGeneric); Setmethodsforimage(ri,methoddb); @@ -523,6 +595,21 @@ InstallGlobalFunction( RecogniseGeneric, SetNiceGens(ri,GeneratorsOfGroup(H)); fi; fi; + + # TODO: store the mandarin SLPs here. Make sure, to only write when succesful. + # check mandarins now + for x in mandarins do + s := SLPforElement(ri, x); + if s = fail then + # TODO: with the master branch rewriting the gens as slps never + # fails. at least we never enter a second iteration of the + # "recognise image" loop. + Info(InfoRecog, 2, + "Enter Mandarin crisis (leaf, depth=", depth, ")."); + return MANDARIN_CRISIS; + fi; + od; + if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; # StopStoringRandEls(ri); SetFilterObj(ri,IsReady); @@ -532,39 +619,82 @@ InstallGlobalFunction( RecogniseGeneric, # The non-leaf case: # In that case we know that ri now knows: homom plus additional data. - # Try to recognise the image a few times, then give up: - counter := 0; + if ForAny(GeneratorsOfGroup(H), x->not ValidateHomomInput(ri, x)) then + # We just computed the homomorphism using exactly those generators. + ErrorNoReturn("Can't map generators of under the homomorphism", + " Homom(): ValidateHomomInput failed"); + fi; + + # Check that the mandarins can be mapped under the homomorphism. If this + # fails, then somewhere higher up in the recognition tree, a kernel must + # have been too small. + if ForAny(mandarins, x->not ValidateHomomInput(ri, x)) then + Info(InfoRecog, 2, + "Enter Mandarin crisis (depth=", depth, "), ", + "ValidateHomomInput failed."); + return MANDARIN_CRISIS; + fi; + # Compute the mandarins of the factor + imageMandarins := []; + for x in mandarins do + y := ImageElm(Homom(ri), x); + Assert(2, y <> fail); + Add(imageMandarins, y); + od; + # TODO: sort the imageMandarins and remove duplicates and trivials + + counter_image := 1; repeat - counter := counter + 1; - if counter > 10 then + if counter_image > 2 then + # We enter here, if kernelGenerationSuccess was fail twice in + # a row. The value of kernelGenerationSuccess is fail, if + # writing of a random element of the image as an SLP in its nice + # generators failed and thus somewhere below the image node rifac + # there is a too small kernel, which the Mandarins didn't catch. + # This should be super seldom. + # Maybe this can happen more often when, deep in the tree, the + # Mandarins are very few? if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; Info(InfoRecog, 1, - "ImageRecogNode of RecogNode could not be recognised,", + "Kernel generation for RecogNode failed ", + counter_image, " times, ", " IsReady() is not set, recognition aborts"); return ri; fi; if IsMatrixGroup(Image(Homom(ri))) then Info(InfoRecog,2,"Going to the image (depth=",depth,", try=", - counter,", dim=",DimensionOfMatrixGroup(Image(Homom(ri))), + counter_image,", dim=",DimensionOfMatrixGroup(Image(Homom(ri))), ", field=",Size(FieldOfMatrixGroup(Image(Homom(ri)))),")."); else Info(InfoRecog,2,"Going to the image (depth=",depth,", try=", - counter,")."); - fi; - if ForAny(GeneratorsOfGroup(H), x->not ValidateHomomInput(ri, x)) then - # Our group fails to contain some of the generators of H! - return fail; + counter_image,")."); fi; Add(depthString,'F'); rifac := RecogniseGeneric( Group(List(GeneratorsOfGroup(H), x->ImageElm(Homom(ri),x))), - methodsforimage(ri), depthString, InitialDataForImageRecogNode(ri) ); + methodsforimage(ri), depthString, + InitialDataForImageRecogNode(ri), + imageMandarins, + IsSafeForMandarins(ri)); Remove(depthString); PrintTreePos("F",depthString,H); SetImageRecogNode(ri,rifac); SetParentRecogNode(rifac,ri); + if rifac = MANDARIN_CRISIS then + # According to the mandarins, somewhere higher up in the recognition + # tree, a kernel must have been too small. + Info(InfoRecog, 2, "Backtrack to the last safe node."); + return MANDARIN_CRISIS; + fi; + # Check for IsReady after checking for MANDARIN_CRISIS, since + # IsReady(MANDARIN_CRISIS) always is false. + if not IsReady(rifac) then + # IsReady was not set, thus abort the whole computation. + if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; + return ri; + fi; if IsMatrixGroup(H) then Info(InfoRecog,2,"Back from image (depth=",depth, @@ -574,21 +704,17 @@ InstallGlobalFunction( RecogniseGeneric, Info(InfoRecog,2,"Back from image (depth=",depth,")."); fi; - if not IsReady(rifac) then - # IsReady was not set, thus abort the whole computation. - if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; - return ri; - fi; - # 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); Setpregensfac(ri, StripMemory(ri!.pregensfacwithmem)); # Now create the kernel generators with the stored method: - succ := CallFuncList(findgensNmeth(ri).method, - Concatenation([ri],findgensNmeth(ri).args)); - until succ = true; + # The value of kernelGenerationSuccess is either true or fail. + kernelGenerationSuccess := + CallFuncList(findgensNmeth(ri).method, + Concatenation([ri],findgensNmeth(ri).args)); + until kernelGenerationSuccess = true; # If nobody has set how we produce preimages of the nicegens: if not Hascalcnicegens(ri) then @@ -601,7 +727,7 @@ InstallGlobalFunction( RecogniseGeneric, Sort(l,SortFunctionWithMemory); # this favours "shorter" memories! # FIXME: For projective groups different matrices might stand # for the same element, we might overlook this here! - # remove duplicates: + # remove duplicates and trivial entries: ll := []; for i in [1..Length(l)] do if not isone(ri)(l[i]) and @@ -611,13 +737,50 @@ InstallGlobalFunction( RecogniseGeneric, od; SetgensN(ri,ll); fi; + + # Evaluate mandarins to get kernel mandarins + kernelMandarins := []; + for i in [1..Length(mandarins)] do + x := mandarins[i]; + y := imageMandarins[i]; + s := SLPforElement(rifac, y); + # TODO: These SLPs should be stored when they are computed for the + # first time. In particular, they can't be fail. + z := ResultOfStraightLineProgram(s, pregensfac(ri)); + if not ri!.isequal(x, z) then + Add( kernelMandarins, x / z ); + fi; + od; + # TODO: sort the kernelMandarins and remove duplicates and trivials + if IsEmpty(gensN(ri)) and immediateverification(ri) then # Special case, for an explanation see the source of the called function. RECOG_HandleSpecialCaseKernelTrivialAndMarkedForImmediateVerification(ri); fi; + if IsEmpty(gensN(ri)) and not IsEmpty(kernelMandarins) + # HACK: something is suuper iffy about the method BlocksModScalars, + # see the comment at handling the "Enter mandarin crisis" non-leaf + # case. + and fhmethsel(ri).successMethod <> "BlocksModScalars" then + Info(InfoRecog, 2, + "Enter Mandarin crisis (depth=", depth, "), ", + "kernel can't be trivial."); + # We handle this in the same way as if recognition of the + # kernel returned a MANDARIN_CRISIS. + if not IsSafeForMandarins(ri) then + return MANDARIN_CRISIS; + else + Info(InfoRecog, 2, + "Handle the mandarin crisis (depth=", depth, ")."); + if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then + # TODO: discard and re-recognise the image. + ErrorNoReturn("TODO"); + fi; + fi; + fi; if IsEmpty(gensN(ri)) then - # We found out that N is the trivial group! - # In this case we do nothing, kernel is fail indicating this. + # We only enter this case, if the mandarins agreed that the kernel is + # trivial. Set the kernel to fail to indicate that it is trivial. Info(InfoRecog,2,"Found trivial kernel (depth=",depth,")."); SetKernelRecogNode(ri,fail); # We have to learn from the image, what our nice generators are: @@ -629,8 +792,12 @@ InstallGlobalFunction( RecogniseGeneric, fi; Info(InfoRecog,2,"Going to the kernel (depth=",depth,")."); + # Due to mandarins or immediate verification we may have to enlarge gensN + # and then recognise the kernel again. repeat - # Now we go on as usual: + mandarinSuccess := false; + immediateVerificationSuccess := false; + SetgensNslp(ri,SLPOfElms(gensN(ri))); SlotUsagePattern(gensNslp(ri)); @@ -638,26 +805,80 @@ InstallGlobalFunction( RecogniseGeneric, N := Group(StripMemory(gensN(ri))); Add(depthString,'K'); - riker := RecogniseGeneric( N, methoddb, depthString, InitialDataForKernelRecogNode(ri) ); + riker := RecogniseGeneric( N, methoddb, depthString, + InitialDataForKernelRecogNode(ri), + kernelMandarins, + # TODO: extend this such that riker can also + # be IsSafeForMandarins, if the responsible + # findgensNmeth is guaranteed to find the + # generators for the whole kernel. + false); Remove(depthString); PrintTreePos("K",depthString,H); SetKernelRecogNode(ri,riker); SetParentRecogNode(riker,ri); + if riker = MANDARIN_CRISIS then + # According to the mandarins, there was an error in the kernel + # generation of the current node or higher up in the recognition + # tree. + if not IsSafeForMandarins(ri) then + Info(InfoRecog, 2, + "Backtrack to the last safe node (depth=", depth, ")."); + return MANDARIN_CRISIS; + fi; + Info(InfoRecog, 2, + "Handle the mandarin crisis (depth=", depth, ")."); + # We are the first safe node on the way to the root and thus need to + # handle the crisis ourselves. + if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then + # TODO: discard and re-recognise the image. + ErrorNoReturn("TODO"); + fi; + # This restarts the loop, since mandarinSuccess is false. + continue; + fi; + mandarinSuccess := true; Info(InfoRecog,2,"Back from kernel (depth=",depth,")."); + # Check for IsReady after checking for MANDARIN_CRISIS, since + # IsReady(MANDARIN_CRISIS) always is false. if not IsReady(riker) then # IsReady is not set, thus the whole computation aborts. return ri; fi; - done := true; - if immediateverification(ri) then + if not immediateverification(ri) then + immediateVerificationSuccess := true; + else Info(InfoRecog,2,"Doing immediate verification (depth=", depth,")."); - done := ImmediateVerification(ri); + immediateVerificationSuccess := ImmediateVerification(ri); fi; - until done; + until mandarinSuccess and immediateVerificationSuccess; SetNiceGens(ri,Concatenation(pregensfac(ri), NiceGens(riker))); + + # Check mandarins now + for x in mandarins do + # TODO: something is suuper iffy about the method BlocksModScalars, which + # is called by BlockDiagonal. + # Apparently its input is neither to be understood as a projective nor as a + # matrix group, but rather as a "all block-scalars being trivial" group. + # That ofc completely wrecks the mandarins, since they assume the group to + # be projective. Currently we don't check here whether the SLP for a + # mandarin evaluates to the mandarin. + # This also has to be considered when doing immediate verification. + # To solve that situation we hacked SLPforElementGeneric. + s := SLPforElement(ri, x); + if s = fail then + # TODO: with the master branch rewriting the gens as slps never + # fails. at least we never enter a second iteration of the + # "recognise image" loop. + Info(InfoRecog, 2, + "Enter Mandarin crisis (non-leaf, depth=", depth, ")."); + return MANDARIN_CRISIS; + fi; + od; + if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; # StopStoringRandEls(ri); SetFilterObj(ri,IsReady); @@ -785,7 +1006,7 @@ InstallOtherMethod( Size, "for a recognition node", InstallOtherMethod( Size, "for a failed recognition node", [IsRecogNode], function(ri) - ErrorNoReturn("the recognition described by this recognition node has failed!"); + ErrorNoReturn("Can't compute size since is not ready (see IsReady)"); end); InstallOtherMethod( \in, "for a group element and a recognition node", @@ -807,7 +1028,7 @@ InstallOtherMethod( \in, "for a group element and a recognition node", InstallOtherMethod( \in, "for a group element and a recognition node", [IsObject, IsRecogNode], function( el, ri ) - ErrorNoReturn("the recognition described by this recognition node has failed!"); + ErrorNoReturn("Can't decide membership since is not ready (see IsReady)"); end); InstallGlobalFunction( "DisplayCompositionFactors", function(arg) @@ -1066,42 +1287,3 @@ RECOG.testAllSubgroups := function(g, options...) CallFuncList(RECOG.TestGroup, Concatenation([sub, false, Size(sub)],options)); od; end; - - -RECOG.TestRecognitionNode := function(ri,stop,recurse) - local err, grp, x, slp, y, ef, ek, i; - err := 0; - grp := Grp(ri); - for i in [1..100] do - x := PseudoRandom(grp); - slp := SLPforElement(ri,x); - if slp <> fail then - y := ResultOfStraightLineProgram(slp,NiceGens(ri)); - fi; - if slp = fail or not ri!.isone(x/y) then - if stop then ErrorNoReturn("ErrorNoReturn found, look at x, slp and y"); fi; - err := err + 1; - Print("X\c"); - else - Print(".\c"); - fi; - od; - Print("\n"); - if err > 0 and recurse then - if IsLeaf(ri) then - return rec(err := err, badnode := ri); - fi; - ef := RECOG.TestRecognitionNode(ImageRecogNode(ri),stop,recurse); - if IsRecord(ef) then - return ef; - fi; - if KernelRecogNode(ri) <> fail then - ek := RECOG.TestRecognitionNode(KernelRecogNode(ri),stop,recurse); - if IsRecord(ek) then - return ek; - fi; - fi; - return rec( err := err, badnode := ri, factorkernelok := true ); - fi; - return err; -end; From 7bf239ddaf51c16363130bb53c6e5e09a5d67fb4 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Wed, 26 Jan 2022 08:15:48 +0100 Subject: [PATCH 02/14] Store mandarins and their SLPs --- gap/base/recognition.gi | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index 6bc39fdcf..ed59d3d14 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -542,6 +542,7 @@ InstallGlobalFunction( RecogniseGeneric, IsIdenticalObj( methoddb, FindHomDbProjective ), knowledge ); + ri!.mandarins := mandarins; if isSafeForMandarins then SetFilterObj(ri, IsSafeForMandarins); fi; @@ -596,19 +597,18 @@ InstallGlobalFunction( RecogniseGeneric, fi; fi; - # TODO: store the mandarin SLPs here. Make sure, to only write when succesful. - # check mandarins now + # Check mandarins now + mandarinSLPs := []; for x in mandarins do s := SLPforElement(ri, x); if s = fail then - # TODO: with the master branch rewriting the gens as slps never - # fails. at least we never enter a second iteration of the - # "recognise image" loop. Info(InfoRecog, 2, "Enter Mandarin crisis (leaf, depth=", depth, ")."); return MANDARIN_CRISIS; fi; + Add(mandarinSLPs, s); od; + ri!.mandarinSLPs := mandarinSLPs; if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; # StopStoringRandEls(ri); @@ -641,7 +641,7 @@ InstallGlobalFunction( RecogniseGeneric, Assert(2, y <> fail); Add(imageMandarins, y); od; - # TODO: sort the imageMandarins and remove duplicates and trivials + # TODO: sort the imageMandarins and handle duplicates and trivials counter_image := 1; repeat @@ -740,15 +740,32 @@ InstallGlobalFunction( RecogniseGeneric, # Evaluate mandarins to get kernel mandarins kernelMandarins := []; + # The image node SLPs are in terms of the generators of the image. Rewrite + # these in terms of the generators of H. + # TODO, compose: slp to pregensfac -> imageMandarinSLPs[i] + # How can I access / store an slpToPregensfac? I don't want to have a + # single slp for every element of pregensfac but one slp which returns all. + # Btw. for kernels this is stored in gensNslp. + imageMandarinSLPs := List(rifac!.mandarinSLPs, + x -> PrependRestrictionToImageNodeSLP(ri, x)); for i in [1..Length(mandarins)] do x := mandarins[i]; + sx := mandarinSLPs[i]; y := imageMandarins[i]; - s := SLPforElement(rifac, y); - # TODO: These SLPs should be stored when they are computed for the - # first time. In particular, they can't be fail. - z := ResultOfStraightLineProgram(s, pregensfac(ri)); + sy := imageMandarinSLPs[i]; + z := ResultOfStraightLineProgram(sy, pregensfac(ri)); if not ri!.isequal(x, z) then - Add( kernelMandarins, x / z ); + Add(kernelMandarins, x / z); + # TODO: Can we compute the SLPs here already? Yes, because we know + # how we got the kernels gens? + Add(kernelMandarinSLPs, + # TODO: Is this valid syntax? + mandarinSLPs[i] / imageMandarinSLPs[i]); + else + Add(kernelMandarins, One(Grp(ri))); + Add(kernelMandarinSLPs, + # TODO + trivialCase); fi; od; # TODO: sort the kernelMandarins and remove duplicates and trivials From ef0ff900e740c3fc749fb541eaa868f66bb17ffd Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Mon, 21 Feb 2022 17:38:24 +0100 Subject: [PATCH 03/14] WIP mandarin SLPs --- gap/base/recognition.gi | 134 +++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 57 deletions(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index ed59d3d14..962baf81b 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -478,11 +478,11 @@ function(ri) local gensNWasEmpty, targetNrGensN, kernelGenerationSuccess; gensNWasEmpty := IsEmpty(gensN(ri)); if gensNWasEmpty then - # This gets reduced during each iteration to a minimal value of 1, to - # account for the case where the kernel only has two elements. The - # findgensNmeth might discard trivial or duplicate generators. In that - # case we can never find more than one generator, if the kernel has - # size two. + # The following value was chosen arbitrarily. It gets reduced during + # each iteration to a minimal value of 1, to account for the case where + # the kernel only has two elements. The findgensNmeth might discard + # trivial or duplicate generators. In that case we can never find more + # than one generator, if the kernel has size two. targetNrGensN := 5; else targetNrGensN := 2 * Length(gensN(ri)); @@ -513,7 +513,7 @@ InstallGlobalFunction( RecogniseGeneric, local depth, ri, allmethods, s, imageMandarins, y, counter_image, rifac, kernelGenerationSuccess, l, ll, kernelMandarins, x, z, mandarinSuccess, immediateVerificationSuccess, N, riker, - enlargeKernelSuccess, i; + enlargeKernelSuccess, i, mandarinSLPs, nrNiceGensOfImageNode; depth := Length(depthString); @@ -535,7 +535,6 @@ InstallGlobalFunction( RecogniseGeneric, mandarins := List([1..NUM_MANDARINS_DEFAULT_VALUE], i -> PseudoRandom(H)); fi; - # Set up the record and the group object: ri := RecogNode( H, @@ -597,7 +596,7 @@ InstallGlobalFunction( RecogniseGeneric, fi; fi; - # Check mandarins now + # Check mandarins and compute their SLPs in the nice generators of ri. mandarinSLPs := []; for x in mandarins do s := SLPforElement(ri, x); @@ -641,8 +640,9 @@ InstallGlobalFunction( RecogniseGeneric, Assert(2, y <> fail); Add(imageMandarins, y); od; - # TODO: sort the imageMandarins and handle duplicates and trivials + # TODO: sort (?) the imageMandarins and handle duplicates and trivials + # Recognise the image and build the kernel. counter_image := 1; repeat if counter_image > 2 then @@ -738,47 +738,24 @@ InstallGlobalFunction( RecogniseGeneric, SetgensN(ri,ll); fi; - # Evaluate mandarins to get kernel mandarins - kernelMandarins := []; - # The image node SLPs are in terms of the generators of the image. Rewrite - # these in terms of the generators of H. - # TODO, compose: slp to pregensfac -> imageMandarinSLPs[i] - # How can I access / store an slpToPregensfac? I don't want to have a - # single slp for every element of pregensfac but one slp which returns all. - # Btw. for kernels this is stored in gensNslp. - imageMandarinSLPs := List(rifac!.mandarinSLPs, - x -> PrependRestrictionToImageNodeSLP(ri, x)); - for i in [1..Length(mandarins)] do - x := mandarins[i]; - sx := mandarinSLPs[i]; - y := imageMandarins[i]; - sy := imageMandarinSLPs[i]; - z := ResultOfStraightLineProgram(sy, pregensfac(ri)); - if not ri!.isequal(x, z) then - Add(kernelMandarins, x / z); - # TODO: Can we compute the SLPs here already? Yes, because we know - # how we got the kernels gens? - Add(kernelMandarinSLPs, - # TODO: Is this valid syntax? - mandarinSLPs[i] / imageMandarinSLPs[i]); - else - Add(kernelMandarins, One(Grp(ri))); - Add(kernelMandarinSLPs, - # TODO - trivialCase); - fi; - od; - # TODO: sort the kernelMandarins and remove duplicates and trivials + # Build kernel mandarins + kernelMandarins := List( + [1..Length(mandarins)], + i -> mandarins[i] + # Divide by a preimage of its image under Homom(ri). + / ResultOfStraightLineProgram(rifac!.mandarinSLPs[i], pregensfac(ri)) + ); + # TODO: sort(?) the kernelMandarins and handle duplicates and trivials if IsEmpty(gensN(ri)) and immediateverification(ri) then # Special case, for an explanation see the source of the called function. RECOG_HandleSpecialCaseKernelTrivialAndMarkedForImmediateVerification(ri); fi; - if IsEmpty(gensN(ri)) and not IsEmpty(kernelMandarins) + if IsEmpty(gensN(ri)) # HACK: something is suuper iffy about the method BlocksModScalars, - # see the comment at handling the "Enter mandarin crisis" non-leaf - # case. - and fhmethsel(ri).successMethod <> "BlocksModScalars" then + # see the comment at the "check mandarins" part of the non-leaf case. + and not fhmethsel(ri).successMethod in ["BlocksModScalars", "BlockScalar"] + and ForAny(kernelMandarins, x -> not ri!.isone(x)) then Info(InfoRecog, 2, "Enter Mandarin crisis (depth=", depth, "), ", "kernel can't be trivial."); @@ -802,6 +779,21 @@ InstallGlobalFunction( RecogniseGeneric, SetKernelRecogNode(ri,fail); # We have to learn from the image, what our nice generators are: SetNiceGens(ri,pregensfac(ri)); + # Since the kernel is trivial, evaluating the image's mandarinSLPs in + # pregensfac(ri) must yield the mandarins of the current node. + # Since the mandarins agree that the kernel is trivial, the current + # node can't be IsSafeForMandarins and we can ignore that case. + ri!.mandarinSLPs := ShallowCopy(rifac!.mandarinSLPs); + for i in [1..Length(mandarins)] do + x := mandarins[i]; + s := ri!.mandarinSLPs[i]; + if not isequal(ri)(x, ResultOfStraightLineProgram(s, NiceGens(ri))) + # HACK: something is suuper iffy about the method BlocksModScalars, + # see the comment at the "check mandarins" part of the non-leaf case. + and fhmethsel(ri).successMethod <> "BlocksModScalars" then + return MANDARIN_CRISIS; + fi; + od; if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; # StopStoringRandEls(ri); SetFilterObj(ri,IsReady); @@ -874,19 +866,30 @@ InstallGlobalFunction( RecogniseGeneric, SetNiceGens(ri,Concatenation(pregensfac(ri), NiceGens(riker))); - # Check mandarins now - for x in mandarins do - # TODO: something is suuper iffy about the method BlocksModScalars, which - # is called by BlockDiagonal. - # Apparently its input is neither to be understood as a projective nor as a - # matrix group, but rather as a "all block-scalars being trivial" group. - # That ofc completely wrecks the mandarins, since they assume the group to - # be projective. Currently we don't check here whether the SLP for a - # mandarin evaluates to the mandarin. - # This also has to be considered when doing immediate verification. - # To solve that situation we hacked SLPforElementGeneric. - s := SLPforElement(ri, x); - if s = fail then + # Check mandarins + mandarinSLPs := []; + for i in [1..Length(mandarins)] do + x := mandarins[i]; + # Build an SLP for the mandarin x and check that it evaluates to x. + # We get that SLP by multiplying the results of the corresponding + # kernel and image node SLPs. We also need to adjust for the fact that + # the nice generators of our node are the concatenation of the image + # and kernel node nice generators. + # Note that the case with trivial kernel was handled above. + nrNiceGensOfImageNode := Length(NiceGens(rifac)); + s := NewProductOfStraightLinePrograms(riker!.mandarinSLPs[i], [nrNiceGensOfImageNode + 1 .. Length(NiceGens(ri))], + rifac!.mandarinSLPs[i], [1..nrNiceGensOfImageNode], + Length(NiceGens(ri))); + if not isequal(ri)(x, ResultOfStraightLineProgram(s, NiceGens(ri))) + # HACK: something is suuper iffy about the method BlocksModScalars, which + # is called by BlockDiagonal. Groups recognized by BlocksModScalars + # are to be understood as a projective nor as a matrix group, but + # rather as a "all block-scalars being trivial" group. To be able + # to check the mandarins we would thus need special functions + # handling isone and isequal, but these do not exist. + # Note that this also has to be considered when doing immediate verification. + # To solve that situation we hacked SLPforElementGeneric. + and fhmethsel(ri).successMethod <> "BlocksModScalars" then # TODO: with the master branch rewriting the gens as slps never # fails. at least we never enter a second iteration of the # "recognise image" loop. @@ -894,7 +897,24 @@ InstallGlobalFunction( RecogniseGeneric, "Enter Mandarin crisis (non-leaf, depth=", depth, ")."); return MANDARIN_CRISIS; fi; + Add(mandarinSLPs, s); + # WHERE TO PUT THIS? + # How can I access / store an slpToPregensfac? I don't want to have a + # single slp for every element of pregensfac but one slp which returns all. + # Btw. for kernels this is stored in gensNslp. + # TODO: I bet I can just call these with NiceGens{[1..Length(NiceGens(rifac))]}; + # projection SLP, do I need this? + #imageMandarinSLPs := List( + # rifac!.mandarinSLPs, + # x -> CompositionOfStraightLinePrograms( + # x, + # projection SLP + # ) + #); + # StraightLineProgramNC([List([1..Length(NiceGens(rifac))], i -> [i, 1])], + # Length(NiceGens(ri))) od; + ri!.mandarinSLPs := mandarinSLPs; if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; # StopStoringRandEls(ri); From 33f785f39551e013613e4c2c6ec4f19ffce9bbc1 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Wed, 23 Feb 2022 08:44:51 +0100 Subject: [PATCH 04/14] Var names and info levels --- gap/base/recognition.gi | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index 962baf81b..91f08207e 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -512,7 +512,7 @@ InstallGlobalFunction( RecogniseGeneric, # Assume all the generators have no memory! local depth, ri, allmethods, s, imageMandarins, y, counter_image, rifac, kernelGenerationSuccess, l, ll, kernelMandarins, x, z, - mandarinSuccess, immediateVerificationSuccess, N, riker, + kernelMandarinSuccess, immediateVerificationSuccess, N, riker, enlargeKernelSuccess, i, mandarinSLPs, nrNiceGensOfImageNode; depth := Length(depthString); @@ -597,6 +597,7 @@ InstallGlobalFunction( RecogniseGeneric, fi; # Check mandarins and compute their SLPs in the nice generators of ri. + Info(InfoRecog, 3, "Check mandarins (leaf, depth=", depth,")."); mandarinSLPs := []; for x in mandarins do s := SLPforElement(ri, x); @@ -685,7 +686,8 @@ InstallGlobalFunction( RecogniseGeneric, if rifac = MANDARIN_CRISIS then # According to the mandarins, somewhere higher up in the recognition # tree, a kernel must have been too small. - Info(InfoRecog, 2, "Backtrack to the last safe node."); + Info(InfoRecog, 2, + "Backtrack to the last safe node (depth=", depth, ")."); return MANDARIN_CRISIS; fi; # Check for IsReady after checking for MANDARIN_CRISIS, since @@ -804,7 +806,7 @@ InstallGlobalFunction( RecogniseGeneric, # Due to mandarins or immediate verification we may have to enlarge gensN # and then recognise the kernel again. repeat - mandarinSuccess := false; + kernelMandarinSuccess := false; immediateVerificationSuccess := false; SetgensNslp(ri,SLPOfElms(gensN(ri))); @@ -843,10 +845,10 @@ InstallGlobalFunction( RecogniseGeneric, # TODO: discard and re-recognise the image. ErrorNoReturn("TODO"); fi; - # This restarts the loop, since mandarinSuccess is false. + # This restarts the loop, since kernelMandarinSuccess is false. continue; fi; - mandarinSuccess := true; + kernelMandarinSuccess := true; Info(InfoRecog,2,"Back from kernel (depth=",depth,")."); # Check for IsReady after checking for MANDARIN_CRISIS, since @@ -858,15 +860,15 @@ InstallGlobalFunction( RecogniseGeneric, if not immediateverification(ri) then immediateVerificationSuccess := true; else - Info(InfoRecog,2,"Doing immediate verification (depth=", + Info(InfoRecog,3,"Doing immediate verification (depth=", depth,")."); immediateVerificationSuccess := ImmediateVerification(ri); fi; - until mandarinSuccess and immediateVerificationSuccess; + until kernelMandarinSuccess and immediateVerificationSuccess; SetNiceGens(ri,Concatenation(pregensfac(ri), NiceGens(riker))); - # Check mandarins + Info(InfoRecog, 3, "Check mandarins (depth=", depth,")."); mandarinSLPs := []; for i in [1..Length(mandarins)] do x := mandarins[i]; From b91d09475543ce04e9f83204b079eccaa2334cd1 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Wed, 23 Feb 2022 11:55:53 +0100 Subject: [PATCH 05/14] Fine tune Imprimitive for permutation groups --- gap/perm.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/perm.gi b/gap/perm.gi index ec1dcbd5b..85d274df3 100644 --- a/gap/perm.gi +++ b/gap/perm.gi @@ -128,7 +128,7 @@ function(ri, G) InitialDataForKernelRecogNode(ri).blocks := blocks; AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsPerm.PcgsForBlocks, 400); AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsPerm.BalTreeForBlocks, 200); - findgensNmeth(ri).args[1] := Length(blocks)+3; + findgensNmeth(ri).args[1] := 2 * Length(blocks)+3; findgensNmeth(ri).args[2] := 5; return Success; end); From e07a4ee0f3d83c11c33266641888c5dcc1f64e29 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Wed, 23 Feb 2022 15:05:24 +0100 Subject: [PATCH 06/14] Fix typo --- gap/base/recognition.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index 91f08207e..c905525c3 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -885,7 +885,7 @@ InstallGlobalFunction( RecogniseGeneric, if not isequal(ri)(x, ResultOfStraightLineProgram(s, NiceGens(ri))) # HACK: something is suuper iffy about the method BlocksModScalars, which # is called by BlockDiagonal. Groups recognized by BlocksModScalars - # are to be understood as a projective nor as a matrix group, but + # are to be understood neither as a projective nor as a matrix group, but # rather as a "all block-scalars being trivial" group. To be able # to check the mandarins we would thus need special functions # handling isone and isequal, but these do not exist. From e17882a3fbbd566c40f40278d5e716e3544bbc85 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Thu, 24 Feb 2022 10:28:19 +0100 Subject: [PATCH 07/14] Fine tune mandarins --- gap/base/recognition.gi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index c905525c3..d6e948aab 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -485,7 +485,12 @@ function(ri) # than one generator, if the kernel has size two. targetNrGensN := 5; else - targetNrGensN := 2 * Length(gensN(ri)); + # The goal is to obtain twice as many generators as were in gensN. The + # kernel generation methods write directly into gensN and don't provide + # a means to specify how many generators should be created. Thus, if we + # set the factor below to 2, the kernel generation method gets called + # twice + targetNrGensN := Int(1.7 * Length(gensN(ri))); fi; Info(InfoRecog, 2, "Enlarging the kernel's generating set due to a mandarin crisis."); From 4bc778c862004ab91dd10ff13cab392bdcfc485f Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Thu, 24 Feb 2022 16:21:03 +0100 Subject: [PATCH 08/14] Mandarin docs --- gap/base/recognition.gd | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gap/base/recognition.gd b/gap/base/recognition.gd index 3e507a91d..990c3a959 100644 --- a/gap/base/recognition.gd +++ b/gap/base/recognition.gd @@ -474,6 +474,16 @@ BindGlobal( "SLPforElementFuncsGeneric", rec() ); # Refer to overview paper by Baarnhielm, Holt, Charles, Eamonn, sections "5.2 # The main algorithm" and "5.4 Crisis management". # Explain safe and unsafe nodes. +# Explain in which situations a crisis can be evoked: +# - only in a leaf: mandarin can't be written as SLPs in nice gens, this does +# not happen in non-leaf nodes +# - mandarins can't be mapped under reduction homomorphism +# - +# Note that when implementing verification via presentations, that can also +# evoke crises. Then I'd make sense to remove the "MANDARIN_" prefix from the +# name. +# TODO Wait a second, if the generators of the root can be expressed as SLPs in +# the nice gens, then the kernels must be correct, right?! BindGlobal("MANDARIN_CRISIS", MakeImmutable("MANDARIN_CRISIS")); BindGlobal("NUM_MANDARINS_DEFAULT_VALUE", 100); DeclareFilter( "IsSafeForMandarins" ); From 89de579e732ddfe01b61be3165fac2e64c2ec7c4 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Thu, 24 Feb 2022 16:39:22 +0100 Subject: [PATCH 09/14] Mandarins remove unused code --- gap/base/recognition.gi | 44 ----------------------------------------- 1 file changed, 44 deletions(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index d6e948aab..278f862ad 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -788,19 +788,7 @@ InstallGlobalFunction( RecogniseGeneric, SetNiceGens(ri,pregensfac(ri)); # Since the kernel is trivial, evaluating the image's mandarinSLPs in # pregensfac(ri) must yield the mandarins of the current node. - # Since the mandarins agree that the kernel is trivial, the current - # node can't be IsSafeForMandarins and we can ignore that case. ri!.mandarinSLPs := ShallowCopy(rifac!.mandarinSLPs); - for i in [1..Length(mandarins)] do - x := mandarins[i]; - s := ri!.mandarinSLPs[i]; - if not isequal(ri)(x, ResultOfStraightLineProgram(s, NiceGens(ri))) - # HACK: something is suuper iffy about the method BlocksModScalars, - # see the comment at the "check mandarins" part of the non-leaf case. - and fhmethsel(ri).successMethod <> "BlocksModScalars" then - return MANDARIN_CRISIS; - fi; - od; if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi; # StopStoringRandEls(ri); SetFilterObj(ri,IsReady); @@ -887,39 +875,7 @@ InstallGlobalFunction( RecogniseGeneric, s := NewProductOfStraightLinePrograms(riker!.mandarinSLPs[i], [nrNiceGensOfImageNode + 1 .. Length(NiceGens(ri))], rifac!.mandarinSLPs[i], [1..nrNiceGensOfImageNode], Length(NiceGens(ri))); - if not isequal(ri)(x, ResultOfStraightLineProgram(s, NiceGens(ri))) - # HACK: something is suuper iffy about the method BlocksModScalars, which - # is called by BlockDiagonal. Groups recognized by BlocksModScalars - # are to be understood neither as a projective nor as a matrix group, but - # rather as a "all block-scalars being trivial" group. To be able - # to check the mandarins we would thus need special functions - # handling isone and isequal, but these do not exist. - # Note that this also has to be considered when doing immediate verification. - # To solve that situation we hacked SLPforElementGeneric. - and fhmethsel(ri).successMethod <> "BlocksModScalars" then - # TODO: with the master branch rewriting the gens as slps never - # fails. at least we never enter a second iteration of the - # "recognise image" loop. - Info(InfoRecog, 2, - "Enter Mandarin crisis (non-leaf, depth=", depth, ")."); - return MANDARIN_CRISIS; - fi; Add(mandarinSLPs, s); - # WHERE TO PUT THIS? - # How can I access / store an slpToPregensfac? I don't want to have a - # single slp for every element of pregensfac but one slp which returns all. - # Btw. for kernels this is stored in gensNslp. - # TODO: I bet I can just call these with NiceGens{[1..Length(NiceGens(rifac))]}; - # projection SLP, do I need this? - #imageMandarinSLPs := List( - # rifac!.mandarinSLPs, - # x -> CompositionOfStraightLinePrograms( - # x, - # projection SLP - # ) - #); - # StraightLineProgramNC([List([1..Length(NiceGens(rifac))], i -> [i, 1])], - # Length(NiceGens(ri))) od; ri!.mandarinSLPs := mandarinSLPs; From 582f33077224e2e17ce1ef5dc0df19c6084b952e Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Tue, 22 Feb 2022 18:14:25 +0100 Subject: [PATCH 10/14] DEBUG COMMIT --- gap/base/recognition.gi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index 278f862ad..b570ae976 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -18,7 +18,8 @@ BindGlobal("RECOG_FindKernelFastNormalClosureStandardArgumentValues", Immutable([6, 3])); -BindConstant("RECOG_NrElementsInImmediateVerification", 10); +#BindConstant("RECOG_NrElementsInImmediateVerification", 10); +RECOG_NrElementsInImmediateVerification := 10; # a nice view method: RECOG_ViewObj := function( level, ri ) @@ -476,6 +477,7 @@ InstallGlobalFunction( PrintTreePos, BindGlobal("TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis", function(ri) local gensNWasEmpty, targetNrGensN, kernelGenerationSuccess; + Print("Handling Mandarin Crisis!\n"); gensNWasEmpty := IsEmpty(gensN(ri)); if gensNWasEmpty then # The following value was chosen arbitrarily. It gets reduced during From ad713a29e1b90f994490ca823341a8121b616df8 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Wed, 23 Feb 2022 11:55:06 +0100 Subject: [PATCH 11/14] DEBUG Mandarins --- gap/base/recognition.gi | 1 + 1 file changed, 1 insertion(+) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index b570ae976..14262b74c 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -478,6 +478,7 @@ BindGlobal("TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis", function(ri) local gensNWasEmpty, targetNrGensN, kernelGenerationSuccess; Print("Handling Mandarin Crisis!\n"); + MC_CNT := MC_CNT + 1; gensNWasEmpty := IsEmpty(gensN(ri)); if gensNWasEmpty then # The following value was chosen arbitrarily. It gets reduced during From 75fddb1003ef487977ad79d4e4d99c142f707de9 Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Wed, 23 Feb 2022 11:55:38 +0100 Subject: [PATCH 12/14] DEBUG ImmVer and BalBLocks --- gap/base/kernel.gi | 2 ++ gap/perm.gi | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gap/base/kernel.gi b/gap/base/kernel.gi index b5ad92588..e7f55a0d8 100644 --- a/gap/base/kernel.gi +++ b/gap/base/kernel.gi @@ -74,6 +74,8 @@ InstallGlobalFunction( ImmediateVerification, fi; if verified = true then return true; fi; # Now, verified = false. + Print("Immediate verification: found extra kernel element(s)!\n"); + IV_CNT := IV_CNT + 1; Info(InfoRecog,2, "Immediate verification: found extra kernel element(s)!"); if FindKernelFastNormalClosure(ri,5,5) = fail then diff --git a/gap/perm.gi b/gap/perm.gi index 85d274df3..87829fcad 100644 --- a/gap/perm.gi +++ b/gap/perm.gi @@ -192,7 +192,7 @@ function(ri, G) Setvalidatehomominput(ri, {ri,p} -> ForAll(o, x -> x^p in seto)); SetHomom(ri,hom); Setimmediateverification(ri,true); - findgensNmeth(ri).args[1] := 3+cut; + findgensNmeth(ri).args[1] := 3 + BAL_CONST * cut; findgensNmeth(ri).args[2] := 5; if nrblocks - cut > 1 then l := Length(upperhalf[1]); From 59e09ba16c517d663c426d9aaa429377989185ad Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Wed, 23 Feb 2022 15:05:55 +0100 Subject: [PATCH 13/14] DEBUG reduce info levels --- gap/base/recognition.gi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index 14262b74c..e1e7a9787 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -610,8 +610,8 @@ InstallGlobalFunction( RecogniseGeneric, for x in mandarins do s := SLPforElement(ri, x); if s = fail then - Info(InfoRecog, 2, - "Enter Mandarin crisis (leaf, depth=", depth, ")."); + Info(InfoRecog, 1, + "Enter mandarin crisis (leaf, depth=", depth, ")."); return MANDARIN_CRISIS; fi; Add(mandarinSLPs, s); @@ -637,8 +637,8 @@ InstallGlobalFunction( RecogniseGeneric, # fails, then somewhere higher up in the recognition tree, a kernel must # have been too small. if ForAny(mandarins, x->not ValidateHomomInput(ri, x)) then - Info(InfoRecog, 2, - "Enter Mandarin crisis (depth=", depth, "), ", + Info(InfoRecog, 1, + "Enter mandarin crisis (depth=", depth, "), ", "ValidateHomomInput failed."); return MANDARIN_CRISIS; fi; @@ -766,8 +766,8 @@ InstallGlobalFunction( RecogniseGeneric, # see the comment at the "check mandarins" part of the non-leaf case. and not fhmethsel(ri).successMethod in ["BlocksModScalars", "BlockScalar"] and ForAny(kernelMandarins, x -> not ri!.isone(x)) then - Info(InfoRecog, 2, - "Enter Mandarin crisis (depth=", depth, "), ", + Info(InfoRecog, 1, + "Enter mandarin crisis (depth=", depth, "), ", "kernel can't be trivial."); # We handle this in the same way as if recognition of the # kernel returned a MANDARIN_CRISIS. From 11b833e4484f748177100f0f46cfaedfb03dc9ba Mon Sep 17 00:00:00 2001 From: Sergio Siccha Date: Thu, 24 Feb 2022 10:29:23 +0100 Subject: [PATCH 14/14] DEBUG constants --- gap/perm.gi | 2 +- init.g | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gap/perm.gi b/gap/perm.gi index 87829fcad..eaa8060c8 100644 --- a/gap/perm.gi +++ b/gap/perm.gi @@ -128,7 +128,7 @@ function(ri, G) InitialDataForKernelRecogNode(ri).blocks := blocks; AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsPerm.PcgsForBlocks, 400); AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsPerm.BalTreeForBlocks, 200); - findgensNmeth(ri).args[1] := 2 * Length(blocks)+3; + findgensNmeth(ri).args[1] := 3 + BAL_CONST * Length(blocks); findgensNmeth(ri).args[2] := 5; return Success; end); diff --git a/init.g b/init.g index 45bf891eb..8115aec26 100644 --- a/init.g +++ b/init.g @@ -14,6 +14,7 @@ ## ############################################################################# +MC_CNT := 0; IV_CNT := 0; BAL_CONST := 1; ReadPackage("recog","gap/base/hack.g"); ReadPackage("recog","gap/base/methods.gd"); ReadPackage("recog","gap/base/methsel.gd");