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"