Skip to content

Commit 5a4a01e

Browse files
committed
Fix Mandarins
1 parent 40b5cb3 commit 5a4a01e

File tree

1 file changed

+99
-60
lines changed

1 file changed

+99
-60
lines changed

gap/base/recognition.gi

Lines changed: 99 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,28 @@ InstallOtherMethod( RecogNode,
228228
return RecogNode(H, projective, rec());
229229
end );
230230

231+
RECOG.SetXNodeForNodeAndString := function(r, s)
232+
if not s = MANDARIN_CRISIS then
233+
ErrorNoReturn("<s> must be MANDARIN_CRISIS");
234+
fi;
235+
return;
236+
end;
237+
238+
InstallMethod( SetParentRecogNode,
239+
"for a recognition node and a string",
240+
[ IsRecogNode, IsString ],
241+
RECOG.SetXNodeForNodeAndString);
242+
243+
InstallMethod( SetImageRecogNode,
244+
"for a recognition node and a string",
245+
[ IsRecogNode, IsString ],
246+
RECOG.SetXNodeForNodeAndString);
247+
248+
InstallMethod( SetKernelRecogNode,
249+
"for a recognition node and a string",
250+
[ IsRecogNode, IsString ],
251+
RECOG.SetXNodeForNodeAndString);
252+
231253
# Sets the stamp used by RandomElm, RandomElmOrd, and related functions.
232254
RECOG.SetPseudoRandomStamp := function(g,st)
233255
if IsBound(g!.pseudorandomfunc) then
@@ -457,9 +479,10 @@ function(ri)
457479
gensNWasEmpty := IsEmpty(gensN(ri));
458480
if gensNWasEmpty then
459481
# This gets reduced during each iteration to a minimal value of 1, to
460-
# account for the case where the kernel only has two elements. If the
461-
# findgensNmeth discards trivial or already found generators, than in
462-
# that case we could never find more than one generator.
482+
# account for the case where the kernel only has two elements. The
483+
# findgensNmeth might discard trivial or duplicate generators. In that
484+
# case we can never find more than one generator, if the kernel has
485+
# size two.
463486
targetNrGensN := 5;
464487
else
465488
targetNrGensN := 2 * Length(gensN(ri));
@@ -490,7 +513,7 @@ InstallGlobalFunction( RecogniseGeneric,
490513
local depth, ri, allmethods, s, factorMandarins, y, counter_image, rifac,
491514
kernelGenerationSuccess, l, ll, kernelMandarins, x, z,
492515
mandarinSuccess, immediateVerificationSuccess, N, riker,
493-
enlargeKernelSuccess, andarin, i;
516+
enlargeKernelSuccess, i;
494517

495518
depth := Length(depthString);
496519

@@ -506,18 +529,18 @@ InstallGlobalFunction( RecogniseGeneric,
506529
Assert(0, depth = 0);
507530
# HACK: We don't want the mandarins to be reused by any computation.
508531
# Since PseudoRandom is hacked, it is important that we generate the
509-
# mandarins before calling EmptyRecognitionInfoRecord. Otherwise the
510-
# mandarins would be reused by RandomElm and RandomElmOrd.
532+
# mandarins before calling RecogNode. Otherwise the mandarins would be
533+
# reused by RandomElm and RandomElmOrd.
511534
# TODO: enable passing NUM_MANDARINS as optional arg
512535
mandarins := List([1..NUM_MANDARINS_DEFAULT_VALUE], i -> PseudoRandom(H));
513536
fi;
514537

515538

516539
# Set up the record and the group object:
517540
ri := RecogNode(
518-
knowledge,
519541
H,
520-
IsIdenticalObj( methoddb, FindHomDbProjective )
542+
IsIdenticalObj( methoddb, FindHomDbProjective ),
543+
knowledge
521544
);
522545
if isSafeForMandarins then
523546
SetFilterObj(ri, IsSafeForMandarins);
@@ -573,11 +596,16 @@ InstallGlobalFunction( RecogniseGeneric,
573596
fi;
574597
fi;
575598

576-
# TODO: store the mandarins and their SLPs?
599+
# TODO: store the mandarin SLPs here. Make sure, to only write when succesful.
577600
# check mandarins now
578601
for x in mandarins do
579602
s := SLPforElement(ri, x);
580603
if s = fail then
604+
# TODO: with the master branch rewriting the gens as slps never
605+
# fails. at least we never enter a second iteration of the
606+
# "recognise image" loop.
607+
Info(InfoRecog, 2,
608+
"Enter Mandarin crisis (leaf, depth=", depth, ").");
581609
return MANDARIN_CRISIS;
582610
fi;
583611
od;
@@ -601,6 +629,9 @@ InstallGlobalFunction( RecogniseGeneric,
601629
# fails, then somewhere higher up in the recognition tree, a kernel must
602630
# have been too small.
603631
if ForAny(mandarins, x->not ValidateHomomInput(ri, x)) then
632+
Info(InfoRecog, 2,
633+
"Enter Mandarin crisis (depth=", depth, "), ",
634+
"ValidateHomomInput failed.");
604635
return MANDARIN_CRISIS;
605636
fi;
606637
# Compute the mandarins of the factor
@@ -648,19 +679,22 @@ InstallGlobalFunction( RecogniseGeneric,
648679
factorMandarins,
649680
IsSafeForMandarins(ri));
650681
Remove(depthString);
651-
if not IsReady(rifac) then
652-
# IsReady was not set, thus abort the whole computation.
653-
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
654-
return ri;
655-
fi;
682+
PrintTreePos("F",depthString,H);
683+
SetImageRecogNode(ri,rifac);
684+
SetParentRecogNode(rifac,ri);
656685
if rifac = MANDARIN_CRISIS then
657686
# According to the mandarins, somewhere higher up in the recognition
658687
# tree, a kernel must have been too small.
688+
Info(InfoRecog, 2, "Backtrack to the last safe node.");
659689
return MANDARIN_CRISIS;
660690
fi;
661-
PrintTreePos("F",depthString,H);
662-
SetImageRecogNode(ri,rifac);
663-
SetParentRecogNode(rifac,ri);
691+
# Check for IsReady after checking for MANDARIN_CRISIS, since
692+
# IsReady(MANDARIN_CRISIS) always is false.
693+
if not IsReady(rifac) then
694+
# IsReady was not set, thus abort the whole computation.
695+
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
696+
return ri;
697+
fi;
664698

665699
if IsMatrixGroup(H) then
666700
Info(InfoRecog,2,"Back from image (depth=",depth,
@@ -704,23 +738,14 @@ InstallGlobalFunction( RecogniseGeneric,
704738
SetgensN(ri,ll);
705739
fi;
706740

707-
# evaluate mandarins to get kernel mandarins
708-
# TODO: something is suuper iffy about the method BlocksModScalars, which
709-
# is called by BlockDiagonal.
710-
# Apparently its input is neither to be understood as a projective nor as a
711-
# matrix group, but rather as a "all block-scalars being trivial" group.
712-
# That ofc completely wrecks the mandarins, since they assume the group to
713-
# be projective.
741+
# Evaluate mandarins to get kernel mandarins
714742
kernelMandarins := [];
715743
for i in [1..Length(mandarins)] do
716744
x := mandarins[i];
717745
y := factorMandarins[i];
718746
s := SLPforElement(rifac, y);
719-
# TODO: these SLPs should be stored when they are computed for the
720-
# first time.
721-
if s = fail then
722-
Error("TODO: no SLP for factor");
723-
fi;
747+
# TODO: These SLPs should be stored when they are computed for the
748+
# first time. In particular, they can't be fail.
724749
z := ResultOfStraightLineProgram(s, pregensfac(ri));
725750
if not ri!.isequal(x, z) then
726751
Add( kernelMandarins, x / z );
@@ -732,13 +757,21 @@ InstallGlobalFunction( RecogniseGeneric,
732757
# Special case, for an explanation see the source of the called function.
733758
RECOG_HandleSpecialCaseKernelTrivialAndMarkedForImmediateVerification(ri);
734759
fi;
735-
if IsEmpty(gensN(ri)) and not IsEmpty(kernelMandarins) then
736-
# We found out that N is the trivial group, but the mandarins disagree!
760+
if IsEmpty(gensN(ri)) and not IsEmpty(kernelMandarins)
761+
# HACK: something is suuper iffy about the method BlocksModScalars,
762+
# see the comment at handling the "Enter mandarin crisis" non-leaf
763+
# case.
764+
and fhmethsel(ri).successMethod <> "BlocksModScalars" then
765+
Info(InfoRecog, 2,
766+
"Enter Mandarin crisis (depth=", depth, "), ",
767+
"kernel can't be trivial.");
737768
# We handle this in the same way as if recognition of the
738769
# kernel returned a MANDARIN_CRISIS.
739770
if not IsSafeForMandarins(ri) then
740771
return MANDARIN_CRISIS;
741772
else
773+
Info(InfoRecog, 2,
774+
"Handle the mandarin crisis (depth=", depth, ").");
742775
if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then
743776
# TODO: discard and re-recognise the image.
744777
ErrorNoReturn("TODO");
@@ -777,36 +810,38 @@ InstallGlobalFunction( RecogniseGeneric,
777810
kernelMandarins,
778811
# TODO: extend this such that riker can also
779812
# be IsSafeForMandarins, if the responsible
780-
# findgensNmeth is guaranteed to feed the
813+
# findgensNmeth is guaranteed to find the
781814
# generators for the whole kernel.
782815
false);
783816
Remove(depthString);
817+
PrintTreePos("K",depthString,H);
818+
SetKernelRecogNode(ri,riker);
819+
SetParentRecogNode(riker,ri);
784820
if riker = MANDARIN_CRISIS then
785821
# According to the mandarins, there was an error in the kernel
786822
# generation of the current node or higher up in the recognition
787823
# tree.
788824
if not IsSafeForMandarins(ri) then
789-
# Backtrack to the first safe node on the way to the root.
825+
Info(InfoRecog, 2,
826+
"Backtrack to the last safe node (depth=", depth, ").");
790827
return MANDARIN_CRISIS;
791828
fi;
829+
Info(InfoRecog, 2,
830+
"Handle the mandarin crisis (depth=", depth, ").");
792831
# We are the first safe node on the way to the root and thus need to
793832
# handle the crisis ourselves.
794-
enlargeKernelSuccess :=
795-
TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri);
796-
if not enlargeKernelSuccess then
833+
if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then
797834
# TODO: discard and re-recognise the image.
798835
ErrorNoReturn("TODO");
799836
fi;
800837
# This restarts the loop, since mandarinSuccess is false.
801838
continue;
802-
else
803-
mandarinSuccess := true;
804839
fi;
805-
PrintTreePos("K",depthString,H);
806-
SetKernelRecogNode(ri,riker);
807-
SetParentRecogNode(riker,ri);
840+
mandarinSuccess := true;
808841
Info(InfoRecog,2,"Back from kernel (depth=",depth,").");
809842

843+
# Check for IsReady after checking for MANDARIN_CRISIS, since
844+
# IsReady(MANDARIN_CRISIS) always is false.
810845
if not IsReady(riker) then
811846
# IsReady is not set, thus the whole computation aborts.
812847
return ri;
@@ -817,29 +852,33 @@ InstallGlobalFunction( RecogniseGeneric,
817852
Info(InfoRecog,2,"Doing immediate verification (depth=",
818853
depth,").");
819854
immediateVerificationSuccess := ImmediateVerification(ri);
820-
if not immediateVerificationSuccess then
821-
# Restart the loop since immediateVerificationSuccess is false.
822-
continue;
823-
fi;
824855
fi;
825-
for x in kernelMandarins do
826-
if SLPforElement(ri, x) = fail then
827-
# We handle this in the same way as if recognition of the
828-
# kernel returned a MANDARIN_CRISIS.
829-
if not IsSafeForMandarins(ri) then
830-
return MANDARIN_CRISIS;
831-
fi;
832-
if not TryToEnlargeKernelGeneratingSetAndUpdateSLPsDuringMandarinCrisis(ri) then
833-
# TODO: discard and re-recognise the image.
834-
ErrorNoReturn("TODO");
835-
fi;
836-
# This restarts the loop, since mandarinSuccess is false.
837-
continue;
838-
fi;
839-
od;
840856
until mandarinSuccess and immediateVerificationSuccess;
841857

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

0 commit comments

Comments
 (0)