Skip to content

Commit 65539bf

Browse files
committed
Fix Mandarins
1 parent 22122b3 commit 65539bf

File tree

1 file changed

+97
-58
lines changed

1 file changed

+97
-58
lines changed

gap/base/recognition.gi

Lines changed: 97 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,28 @@ InstallOtherMethod( RecogNode,
235235
return RecogNode(H, projective, r);
236236
end);
237237

238+
RECOG.SetXNodeForNodeAndString := function(r, s)
239+
if not s = MANDARIN_CRISIS then
240+
ErrorNoReturn("<s> must be MANDARIN_CRISIS");
241+
fi;
242+
return;
243+
end;
244+
245+
InstallMethod( SetParentRecogNode,
246+
"for a recognition node and a string",
247+
[ IsRecogNode, IsString ],
248+
RECOG.SetXNodeForNodeAndString);
249+
250+
InstallMethod( SetImageRecogNode,
251+
"for a recognition node and a string",
252+
[ IsRecogNode, IsString ],
253+
RECOG.SetXNodeForNodeAndString);
254+
255+
InstallMethod( SetKernelRecogNode,
256+
"for a recognition node and a string",
257+
[ IsRecogNode, IsString ],
258+
RECOG.SetXNodeForNodeAndString);
259+
238260
# Sets the stamp used by RandomElm, RandomElmOrd, and related functions.
239261
RECOG.SetPseudoRandomStamp := function(g,st)
240262
if IsBound(g!.pseudorandomfunc) then
@@ -464,9 +486,10 @@ function(ri)
464486
gensNWasEmpty := IsEmpty(gensN(ri));
465487
if gensNWasEmpty then
466488
# This gets reduced during each iteration to a minimal value of 1, to
467-
# account for the case where the kernel only has two elements. If the
468-
# findgensNmeth discards trivial or already found generators, than in
469-
# that case we could never find more than one generator.
489+
# account for the case where the kernel only has two elements. The
490+
# findgensNmeth might discard trivial or duplicate generators. In that
491+
# case we can never find more than one generator, if the kernel has
492+
# size two.
470493
targetNrGensN := 5;
471494
else
472495
targetNrGensN := 2 * Length(gensN(ri));
@@ -497,7 +520,7 @@ InstallGlobalFunction( RecogniseGeneric,
497520
local depth, ri, allmethods, s, factorMandarins, y, counter_image, rifac,
498521
kernelGenerationSuccess, l, ll, kernelMandarins, x, z,
499522
mandarinSuccess, immediateVerificationSuccess, N, riker,
500-
enlargeKernelSuccess, andarin, i;
523+
enlargeKernelSuccess, i;
501524

502525
depth := Length(depthString);
503526

@@ -513,8 +536,8 @@ InstallGlobalFunction( RecogniseGeneric,
513536
Assert(0, depth = 0);
514537
# HACK: We don't want the mandarins to be reused by any computation.
515538
# Since PseudoRandom is hacked, it is important that we generate the
516-
# mandarins before calling EmptyRecognitionInfoRecord. Otherwise the
517-
# mandarins would be reused by RandomElm and RandomElmOrd.
539+
# mandarins before calling RecogNode. Otherwise the mandarins would be
540+
# reused by RandomElm and RandomElmOrd.
518541
# TODO: enable passing NUM_MANDARINS as optional arg
519542
mandarins := List([1..NUM_MANDARINS_DEFAULT_VALUE], i -> PseudoRandom(H));
520543
fi;
@@ -580,11 +603,16 @@ InstallGlobalFunction( RecogniseGeneric,
580603
fi;
581604
fi;
582605

583-
# TODO: store the mandarins and their SLPs?
606+
# TODO: store the mandarin SLPs here. Make sure, to only write when succesful.
584607
# check mandarins now
585608
for x in mandarins do
586609
s := SLPforElement(ri, x);
587610
if s = fail then
611+
# TODO: with the master branch rewriting the gens as slps never
612+
# fails. at least we never enter a second iteration of the
613+
# "recognise image" loop.
614+
Info(InfoRecog, 2,
615+
"Enter Mandarin crisis (leaf, depth=", depth, ").");
588616
return MANDARIN_CRISIS;
589617
fi;
590618
od;
@@ -608,6 +636,9 @@ InstallGlobalFunction( RecogniseGeneric,
608636
# fails, then somewhere higher up in the recognition tree, a kernel must
609637
# have been too small.
610638
if ForAny(mandarins, x->not ValidateHomomInput(ri, x)) then
639+
Info(InfoRecog, 2,
640+
"Enter Mandarin crisis (depth=", depth, "), ",
641+
"ValidateHomomInput failed.");
611642
return MANDARIN_CRISIS;
612643
fi;
613644
# Compute the mandarins of the factor
@@ -655,19 +686,22 @@ InstallGlobalFunction( RecogniseGeneric,
655686
factorMandarins,
656687
IsSafeForMandarins(ri));
657688
Remove(depthString);
658-
if not IsReady(rifac) then
659-
# IsReady was not set, thus abort the whole computation.
660-
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
661-
return ri;
662-
fi;
689+
PrintTreePos("F",depthString,H);
690+
SetImageRecogNode(ri,rifac);
691+
SetParentRecogNode(rifac,ri);
663692
if rifac = MANDARIN_CRISIS then
664693
# According to the mandarins, somewhere higher up in the recognition
665694
# tree, a kernel must have been too small.
695+
Info(InfoRecog, 2, "Backtrack to the last safe node.");
666696
return MANDARIN_CRISIS;
667697
fi;
668-
PrintTreePos("F",depthString,H);
669-
SetImageRecogNode(ri,rifac);
670-
SetParentRecogNode(rifac,ri);
698+
# Check for IsReady after checking for MANDARIN_CRISIS, since
699+
# IsReady(MANDARIN_CRISIS) always is false.
700+
if not IsReady(rifac) then
701+
# IsReady was not set, thus abort the whole computation.
702+
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
703+
return ri;
704+
fi;
671705

672706
if IsMatrixGroup(H) then
673707
Info(InfoRecog,2,"Back from image (depth=",depth,
@@ -711,23 +745,14 @@ InstallGlobalFunction( RecogniseGeneric,
711745
SetgensN(ri,ll);
712746
fi;
713747

714-
# evaluate mandarins to get kernel mandarins
715-
# TODO: something is suuper iffy about the method BlocksModScalars, which
716-
# is called by BlockDiagonal.
717-
# Apparently its input is neither to be understood as a projective nor as a
718-
# matrix group, but rather as a "all block-scalars being trivial" group.
719-
# That ofc completely wrecks the mandarins, since they assume the group to
720-
# be projective.
748+
# Evaluate mandarins to get kernel mandarins
721749
kernelMandarins := [];
722750
for i in [1..Length(mandarins)] do
723751
x := mandarins[i];
724752
y := factorMandarins[i];
725753
s := SLPforElement(rifac, y);
726-
# TODO: these SLPs should be stored when they are computed for the
727-
# first time.
728-
if s = fail then
729-
Error("TODO: no SLP for factor");
730-
fi;
754+
# TODO: These SLPs should be stored when they are computed for the
755+
# first time. In particular, they can't be fail.
731756
z := ResultOfStraightLineProgram(s, pregensfac(ri));
732757
if not ri!.isequal(x, z) then
733758
Add( kernelMandarins, x / z );
@@ -739,13 +764,21 @@ InstallGlobalFunction( RecogniseGeneric,
739764
# Special case, for an explanation see the source of the called function.
740765
RECOG_HandleSpecialCaseKernelTrivialAndMarkedForImmediateVerification(ri);
741766
fi;
742-
if IsEmpty(gensN(ri)) and not IsEmpty(kernelMandarins) then
743-
# We found out that N is the trivial group, but the mandarins disagree!
767+
if IsEmpty(gensN(ri)) and not IsEmpty(kernelMandarins)
768+
# HACK: something is suuper iffy about the method BlocksModScalars,
769+
# see the comment at handling the "Enter mandarin crisis" non-leaf
770+
# case.
771+
and fhmethsel(ri).successMethod <> "BlocksModScalars" then
772+
Info(InfoRecog, 2,
773+
"Enter Mandarin crisis (depth=", depth, "), ",
774+
"kernel can't be trivial.");
744775
# We handle this in the same way as if recognition of the
745776
# kernel returned a MANDARIN_CRISIS.
746777
if not IsSafeForMandarins(ri) then
747778
return MANDARIN_CRISIS;
748779
else
780+
Info(InfoRecog, 2,
781+
"Handle the mandarin crisis (depth=", depth, ").");
749782
if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then
750783
# TODO: discard and re-recognise the image.
751784
ErrorNoReturn("TODO");
@@ -784,36 +817,38 @@ InstallGlobalFunction( RecogniseGeneric,
784817
kernelMandarins,
785818
# TODO: extend this such that riker can also
786819
# be IsSafeForMandarins, if the responsible
787-
# findgensNmeth is guaranteed to feed the
820+
# findgensNmeth is guaranteed to find the
788821
# generators for the whole kernel.
789822
false);
790823
Remove(depthString);
824+
PrintTreePos("K",depthString,H);
825+
SetKernelRecogNode(ri,riker);
826+
SetParentRecogNode(riker,ri);
791827
if riker = MANDARIN_CRISIS then
792828
# According to the mandarins, there was an error in the kernel
793829
# generation of the current node or higher up in the recognition
794830
# tree.
795831
if not IsSafeForMandarins(ri) then
796-
# Backtrack to the first safe node on the way to the root.
832+
Info(InfoRecog, 2,
833+
"Backtrack to the last safe node (depth=", depth, ").");
797834
return MANDARIN_CRISIS;
798835
fi;
836+
Info(InfoRecog, 2,
837+
"Handle the mandarin crisis (depth=", depth, ").");
799838
# We are the first safe node on the way to the root and thus need to
800839
# handle the crisis ourselves.
801-
enlargeKernelSuccess :=
802-
TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri);
803-
if not enlargeKernelSuccess then
840+
if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then
804841
# TODO: discard and re-recognise the image.
805842
ErrorNoReturn("TODO");
806843
fi;
807844
# This restarts the loop, since mandarinSuccess is false.
808845
continue;
809-
else
810-
mandarinSuccess := true;
811846
fi;
812-
PrintTreePos("K",depthString,H);
813-
SetKernelRecogNode(ri,riker);
814-
SetParentRecogNode(riker,ri);
847+
mandarinSuccess := true;
815848
Info(InfoRecog,2,"Back from kernel (depth=",depth,").");
816849

850+
# Check for IsReady after checking for MANDARIN_CRISIS, since
851+
# IsReady(MANDARIN_CRISIS) always is false.
817852
if not IsReady(riker) then
818853
# IsReady is not set, thus the whole computation aborts.
819854
return ri;
@@ -824,29 +859,33 @@ InstallGlobalFunction( RecogniseGeneric,
824859
Info(InfoRecog,2,"Doing immediate verification (depth=",
825860
depth,").");
826861
immediateVerificationSuccess := ImmediateVerification(ri);
827-
if not immediateVerificationSuccess then
828-
# Restart the loop since immediateVerificationSuccess is false.
829-
continue;
830-
fi;
831862
fi;
832-
for x in kernelMandarins do
833-
if SLPforElement(ri, x) = fail then
834-
# We handle this in the same way as if recognition of the
835-
# kernel returned a MANDARIN_CRISIS.
836-
if not IsSafeForMandarins(ri) then
837-
return MANDARIN_CRISIS;
838-
fi;
839-
if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then
840-
# TODO: discard and re-recognise the image.
841-
ErrorNoReturn("TODO");
842-
fi;
843-
# This restarts the loop, since mandarinSuccess is false.
844-
continue;
845-
fi;
846-
od;
847863
until mandarinSuccess and immediateVerificationSuccess;
848864

849865
SetNiceGens(ri,Concatenation(pregensfac(ri), NiceGens(riker)));
866+
867+
# Check mandarins now
868+
for x in mandarins do
869+
# TODO: something is suuper iffy about the method BlocksModScalars, which
870+
# is called by BlockDiagonal.
871+
# Apparently its input is neither to be understood as a projective nor as a
872+
# matrix group, but rather as a "all block-scalars being trivial" group.
873+
# That ofc completely wrecks the mandarins, since they assume the group to
874+
# be projective. Currently we don't check here whether the SLP for a
875+
# mandarin evaluates to the mandarin.
876+
# This also has to be considered when doing immediate verification.
877+
# To solve that situation we hacked SLPforElementGeneric.
878+
s := SLPforElement(ri, x);
879+
if s = fail then
880+
# TODO: with the master branch rewriting the gens as slps never
881+
# fails. at least we never enter a second iteration of the
882+
# "recognise image" loop.
883+
Info(InfoRecog, 2,
884+
"Enter Mandarin crisis (non-leaf, depth=", depth, ").");
885+
return MANDARIN_CRISIS;
886+
fi;
887+
od;
888+
850889
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
851890
# StopStoringRandEls(ri);
852891
SetFilterObj(ri,IsReady);

0 commit comments

Comments
 (0)