Skip to content

Commit faf71d4

Browse files
committed
WIP mandarin SLPs
1 parent 09df5ce commit faf71d4

File tree

1 file changed

+77
-57
lines changed

1 file changed

+77
-57
lines changed

gap/base/recognition.gi

Lines changed: 77 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -478,11 +478,11 @@ function(ri)
478478
local gensNWasEmpty, targetNrGensN, kernelGenerationSuccess;
479479
gensNWasEmpty := IsEmpty(gensN(ri));
480480
if gensNWasEmpty then
481-
# This gets reduced during each iteration to a minimal value of 1, to
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.
481+
# The following value was chosen arbitrarily. It gets reduced during
482+
# each iteration to a minimal value of 1, to account for the case where
483+
# the kernel only has two elements. The findgensNmeth might discard
484+
# trivial or duplicate generators. In that case we can never find more
485+
# than one generator, if the kernel has size two.
486486
targetNrGensN := 5;
487487
else
488488
targetNrGensN := 2 * Length(gensN(ri));
@@ -513,7 +513,7 @@ InstallGlobalFunction( RecogniseGeneric,
513513
local depth, ri, allmethods, s, imageMandarins, y, counter_image, rifac,
514514
kernelGenerationSuccess, l, ll, kernelMandarins, x, z,
515515
mandarinSuccess, immediateVerificationSuccess, N, riker,
516-
enlargeKernelSuccess, i;
516+
enlargeKernelSuccess, i, mandarinSLPs, nrNiceGensOfImageNode;
517517

518518
depth := Length(depthString);
519519

@@ -535,7 +535,6 @@ InstallGlobalFunction( RecogniseGeneric,
535535
mandarins := List([1..NUM_MANDARINS_DEFAULT_VALUE], i -> PseudoRandom(H));
536536
fi;
537537

538-
539538
# Set up the record and the group object:
540539
ri := RecogNode(
541540
H,
@@ -597,7 +596,7 @@ InstallGlobalFunction( RecogniseGeneric,
597596
fi;
598597
fi;
599598

600-
# Check mandarins now
599+
# Check mandarins and compute their SLPs in the nice generators of ri.
601600
mandarinSLPs := [];
602601
for x in mandarins do
603602
s := SLPforElement(ri, x);
@@ -641,8 +640,9 @@ InstallGlobalFunction( RecogniseGeneric,
641640
Assert(2, y <> fail);
642641
Add(imageMandarins, y);
643642
od;
644-
# TODO: sort the imageMandarins and handle duplicates and trivials
643+
# TODO: sort (?) the imageMandarins and handle duplicates and trivials
645644

645+
# Recognise the image and build the kernel.
646646
counter_image := 1;
647647
repeat
648648
if counter_image > 2 then
@@ -738,47 +738,24 @@ InstallGlobalFunction( RecogniseGeneric,
738738
SetgensN(ri,ll);
739739
fi;
740740

741-
# Evaluate mandarins to get kernel mandarins
742-
kernelMandarins := [];
743-
# The image node SLPs are in terms of the generators of the image. Rewrite
744-
# these in terms of the generators of H.
745-
# TODO, compose: slp to pregensfac -> imageMandarinSLPs[i]
746-
# How can I access / store an slpToPregensfac? I don't want to have a
747-
# single slp for every element of pregensfac but one slp which returns all.
748-
# Btw. for kernels this is stored in gensNslp.
749-
imageMandarinSLPs := List(rifac!.mandarinSLPs,
750-
x -> PrependRestrictionToImageNodeSLP(ri, x));
751-
for i in [1..Length(mandarins)] do
752-
x := mandarins[i];
753-
sx := mandarinSLPs[i];
754-
y := imageMandarins[i];
755-
sy := imageMandarinSLPs[i];
756-
z := ResultOfStraightLineProgram(sy, pregensfac(ri));
757-
if not ri!.isequal(x, z) then
758-
Add(kernelMandarins, x / z);
759-
# TODO: Can we compute the SLPs here already? Yes, because we know
760-
# how we got the kernels gens?
761-
Add(kernelMandarinSLPs,
762-
# TODO: Is this valid syntax?
763-
mandarinSLPs[i] / imageMandarinSLPs[i]);
764-
else
765-
Add(kernelMandarins, One(Grp(ri)));
766-
Add(kernelMandarinSLPs,
767-
# TODO
768-
trivialCase);
769-
fi;
770-
od;
771-
# TODO: sort the kernelMandarins and remove duplicates and trivials
741+
# Build kernel mandarins
742+
kernelMandarins := List(
743+
[1..Length(mandarins)],
744+
i -> mandarins[i]
745+
# Divide by a preimage of its image under Homom(ri).
746+
/ ResultOfStraightLineProgram(rifac!.mandarinSLPs[i], pregensfac(ri))
747+
);
748+
# TODO: sort(?) the kernelMandarins and handle duplicates and trivials
772749

773750
if IsEmpty(gensN(ri)) and immediateverification(ri) then
774751
# Special case, for an explanation see the source of the called function.
775752
RECOG_HandleSpecialCaseKernelTrivialAndMarkedForImmediateVerification(ri);
776753
fi;
777-
if IsEmpty(gensN(ri)) and not IsEmpty(kernelMandarins)
754+
if IsEmpty(gensN(ri))
778755
# HACK: something is suuper iffy about the method BlocksModScalars,
779-
# see the comment at handling the "Enter mandarin crisis" non-leaf
780-
# case.
781-
and fhmethsel(ri).successMethod <> "BlocksModScalars" then
756+
# see the comment at the "check mandarins" part of the non-leaf case.
757+
and not fhmethsel(ri).successMethod in ["BlocksModScalars", "BlockScalar"]
758+
and ForAny(kernelMandarins, x -> not ri!.isone(x)) then
782759
Info(InfoRecog, 2,
783760
"Enter Mandarin crisis (depth=", depth, "), ",
784761
"kernel can't be trivial.");
@@ -802,6 +779,21 @@ InstallGlobalFunction( RecogniseGeneric,
802779
SetKernelRecogNode(ri,fail);
803780
# We have to learn from the image, what our nice generators are:
804781
SetNiceGens(ri,pregensfac(ri));
782+
# Since the kernel is trivial, evaluating the image's mandarinSLPs in
783+
# pregensfac(ri) must yield the mandarins of the current node.
784+
# Since the mandarins agree that the kernel is trivial, the current
785+
# node can't be IsSafeForMandarins and we can ignore that case.
786+
ri!.mandarinSLPs := ShallowCopy(rifac!.mandarinSLPs);
787+
for i in [1..Length(mandarins)] do
788+
x := mandarins[i];
789+
s := ri!.mandarinSLPs[i];
790+
if not isequal(ri)(x, ResultOfStraightLineProgram(s, NiceGens(ri)))
791+
# HACK: something is suuper iffy about the method BlocksModScalars,
792+
# see the comment at the "check mandarins" part of the non-leaf case.
793+
and fhmethsel(ri).successMethod <> "BlocksModScalars" then
794+
return MANDARIN_CRISIS;
795+
fi;
796+
od;
805797
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
806798
# StopStoringRandEls(ri);
807799
SetFilterObj(ri,IsReady);
@@ -874,27 +866,55 @@ InstallGlobalFunction( RecogniseGeneric,
874866

875867
SetNiceGens(ri,Concatenation(pregensfac(ri), NiceGens(riker)));
876868

877-
# Check mandarins now
878-
for x in mandarins do
879-
# TODO: something is suuper iffy about the method BlocksModScalars, which
880-
# is called by BlockDiagonal.
881-
# Apparently its input is neither to be understood as a projective nor as a
882-
# matrix group, but rather as a "all block-scalars being trivial" group.
883-
# That ofc completely wrecks the mandarins, since they assume the group to
884-
# be projective. Currently we don't check here whether the SLP for a
885-
# mandarin evaluates to the mandarin.
886-
# This also has to be considered when doing immediate verification.
887-
# To solve that situation we hacked SLPforElementGeneric.
888-
s := SLPforElement(ri, x);
889-
if s = fail then
869+
# Check mandarins
870+
mandarinSLPs := [];
871+
for i in [1..Length(mandarins)] do
872+
x := mandarins[i];
873+
# Build an SLP for the mandarin x and check that it evaluates to x.
874+
# We get that SLP by multiplying the results of the corresponding
875+
# kernel and image node SLPs. We also need to adjust for the fact that
876+
# the nice generators of our node are the concatenation of the image
877+
# and kernel node nice generators.
878+
# Note that the case with trivial kernel was handled above.
879+
nrNiceGensOfImageNode := Length(NiceGens(rifac));
880+
s := NewProductOfStraightLinePrograms(riker!.mandarinSLPs[i], [nrNiceGensOfImageNode + 1 .. Length(NiceGens(ri))],
881+
rifac!.mandarinSLPs[i], [1..nrNiceGensOfImageNode],
882+
Length(NiceGens(ri)));
883+
if not isequal(ri)(x, ResultOfStraightLineProgram(s, NiceGens(ri)))
884+
# HACK: something is suuper iffy about the method BlocksModScalars, which
885+
# is called by BlockDiagonal. Groups recognized by BlocksModScalars
886+
# are to be understood as a projective nor as a matrix group, but
887+
# rather as a "all block-scalars being trivial" group. To be able
888+
# to check the mandarins we would thus need special functions
889+
# handling isone and isequal, but these do not exist.
890+
# Note that this also has to be considered when doing immediate verification.
891+
# To solve that situation we hacked SLPforElementGeneric.
892+
and fhmethsel(ri).successMethod <> "BlocksModScalars" then
890893
# TODO: with the master branch rewriting the gens as slps never
891894
# fails. at least we never enter a second iteration of the
892895
# "recognise image" loop.
893896
Info(InfoRecog, 2,
894897
"Enter Mandarin crisis (non-leaf, depth=", depth, ").");
895898
return MANDARIN_CRISIS;
896899
fi;
900+
Add(mandarinSLPs, s);
901+
# WHERE TO PUT THIS?
902+
# How can I access / store an slpToPregensfac? I don't want to have a
903+
# single slp for every element of pregensfac but one slp which returns all.
904+
# Btw. for kernels this is stored in gensNslp.
905+
# TODO: I bet I can just call these with NiceGens{[1..Length(NiceGens(rifac))]};
906+
# projection SLP, do I need this?
907+
#imageMandarinSLPs := List(
908+
# rifac!.mandarinSLPs,
909+
# x -> CompositionOfStraightLinePrograms(
910+
# x,
911+
# projection SLP
912+
# )
913+
#);
914+
# StraightLineProgramNC([List([1..Length(NiceGens(rifac))], i -> [i, 1])],
915+
# Length(NiceGens(ri)))
897916
od;
917+
ri!.mandarinSLPs := mandarinSLPs;
898918

899919
if InfoLevel(InfoRecog) = 1 and depth = 0 then Print("\n"); fi;
900920
# StopStoringRandEls(ri);

0 commit comments

Comments
 (0)