diff --git a/gap/perm.gi b/gap/perm.gi index a12b46448..be7dad865 100644 --- a/gap/perm.gi +++ b/gap/perm.gi @@ -355,24 +355,44 @@ end; #! @BeginChunk ThrowAwayFixedPoints #! This method defines a homomorphism of a permutation group #! G to the action on the moved points of G if -#! G does not have too many moved points. In the current setup, the -#! homomorphism is defined if the number k of moved +#! either G has a lot of fixed points, or if G knows that it is +#! primitive and has fixed points. If G has fixed points but does not +#! know whether it is primitive, then it returns NotEnoughInformation +#! so that it may be called again at a later time. +#! In all other cases, it returns NeverApplicable. +#!

+#! +#! In the current setup, the +#! homomorphism is defined if the number n of moved #! points is at most 1/3 of the largest moved point of G, -#! or k is at most half of the number of points on which -#! G is stored internally by ⪆. The method returns -#! NeverApplicable if it does not define a homomorphism indicating that it will -#! never succeed. +#! or n is at most half of the number of points on which +#! G is stored internally by ⪆. +#!

+#! +#! The fact that this method returns NotEnoughInformation if G +#! has fixed points but does not know whether it is primitive, is important for +#! the efficient handling of large-base primitive groups by +#! . #! @EndChunk -FindHomMethodsPerm.ThrowAwayFixedPoints := - function( ri, G ) +FindHomMethodsPerm.ThrowAwayFixedPoints := function( ri, G ) # Check, whether we can throw away fixed points - local gens,hom,l,n,o; + local gens,nrStoredPoints,n,largest,isApplicable,o,hom; gens := GeneratorsOfGroup(G); - l := List(gens,StoredPointsPerm); + nrStoredPoints := Maximum(List(gens,StoredPointsPerm)); n := NrMovedPoints(G); - if 2*n > Maximum(l) or 3*n > LargestMovedPoint(G) then # we do nothing - return NeverApplicable; + largest := LargestMovedPoint(G); + # If isApplicable is true, we definitely are applicable. + isApplicable := 3*n <= largest or 2*n <= nrStoredPoints + or (HasIsPrimitive(G) and IsPrimitive(G) and n < largest); + # If isApplicable is false, we might become applicable if G figures out + # that it is primitive. + if not isApplicable then + if not HasIsPrimitive(G) and n < largest then + return NotEnoughInformation; + else + return NeverApplicable; + fi; fi; o := MovedPoints(G); hom := ActionHomomorphism(G,o); diff --git a/gap/perm/largebase.gi b/gap/perm/largebase.gi index cf854f525..762bdd16e 100644 --- a/gap/perm/largebase.gi +++ b/gap/perm/largebase.gi @@ -493,7 +493,7 @@ end; #! @BeginChunk LargeBasePrimitive #! This method tries to determine whether the input group G is a -#! large-base primitive group that neither is a symmetric nor an alternating +#! fixed-point-free large-base primitive group that neither is a symmetric nor an alternating #! group in its natural action. #! This method is an implementation of . #! @@ -507,6 +507,19 @@ end; #! r \cdot k > 1 #! and 2 \cdot r \cdot k^2 \le n. #! +#! A large primitive group H of the above type which does have fixed +#! points is handled as follows: if the group H does not know yet that +#! it is primitive, then returns +#! NotEnoughInformation. After the first call to +#! LargeBasePrimitive, the group H knows that it is primitive, +#! but since it has fixed points LargeBasePrimitive returns +#! NeverApplicable. Since previously +#! returned NotEnoughInformation, it will be called again. Then it will +#! use the new information about H being primitive, and is guaranteed to +#! prune away the fixed points and set up a reduction homomorphism. +#! LargeBasePrimitive is then applicable to the image of that +#! homomorphism. +#! #! If G is imprimitive then the output is #! NeverApplicable. If G is primitive then #! the output is either a homomorphism into the @@ -515,8 +528,7 @@ end; #! NeverApplicable if no parameters n, k, and r as #! above exist. #! @EndChunk -FindHomMethodsPerm.LargeBasePrimitive := - function(ri,grp) +FindHomMethodsPerm.LargeBasePrimitive := function(ri,grp) local res,T,seen,imgens,hom; if not IsPermGroup(grp) then return NeverApplicable; @@ -526,6 +538,7 @@ FindHomMethodsPerm.LargeBasePrimitive := fi; RECOG.SetPseudoRandomStamp(grp,"Jellyfish"); res := RECOG.AllJellyfish(grp); + RECOG.SetPseudoRandomStamp(grp,"PseudoRandom"); if res = NeverApplicable or res = TemporaryFailure then return res; fi; diff --git a/tst/working/quick/PermLargeBasePrimitive.tst b/tst/working/quick/PermLargeBasePrimitive.tst index fed7adf6c..3a9d26bc3 100644 --- a/tst/working/quick/PermLargeBasePrimitive.tst +++ b/tst/working/quick/PermLargeBasePrimitive.tst @@ -1,13 +1,31 @@ -#@local S19OnSets, jellyGroup, n, random, jellyGroupConj, ri +#@local S17OnSets, jellyGroup, n, random, jellyGroupConj, ri +#@local addFixedPointsPerm, jellyGroupWithFixedPoints, riWithFixed # Test for LargeBasePrimitive -gap> S19OnSets := Action(SymmetricGroup(19), Combinations([1 .. 19], 2), OnSets);; -gap> jellyGroup := WreathProductProductAction(S19OnSets, Group((1,2)));; +gap> S17OnSets := Action(SymmetricGroup(17), Combinations([1 .. 17], 2), OnSets);; +gap> jellyGroup := WreathProductProductAction(S17OnSets, Group((1,2)));; gap> n := NrMovedPoints(jellyGroup);; gap> # Take a random conjugate gap> random := Random(SymmetricGroup(n));; gap> jellyGroupConj := jellyGroup ^ random;; -gap> RECOG.TestGroup(jellyGroupConj, +gap> ri := RECOG.TestGroup(jellyGroupConj, > false, > Size(jellyGroup), > rec(tryNonGroupElements := true));; +gap> ri!.fhmethsel.successMethod; +"LargeBasePrimitive" + +# Test that groups with fixed points are handled together by +# ThrowAwayFixedPoints and LargeBasePrimitive, confer: +# https://github.com/gap-packages/recog/issues/190 +# https://github.com/gap-packages/recog/pull/191 +gap> addFixedPointsPerm := Random(SymmetricGroup(5 * QuoInt(n,2)));; +gap> jellyGroupWithFixedPoints := jellyGroup ^ addFixedPointsPerm;; +gap> riWithFixed := RECOG.TestGroup(jellyGroupWithFixedPoints, +> false, +> Size(jellyGroup), +> rec(tryNonGroupElements := true));; +gap> riWithFixed!.fhmethsel.successMethod; +"ThrowAwayFixedPoints" +gap> RIFac(riWithFixed)!.fhmethsel.successMethod; +"LargeBasePrimitive"