@@ -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