Skip to content

Commit

Permalink
Fix an error in evaluating the MaximalAbelianQuotient of a subgroup o…
Browse files Browse the repository at this point in the history
…f an FPGroup which could result in wrong results (#5620)

* Conjugacy test for cyclic subgroups

Do not try the orbit mapping test for cyclic subgroups (or subgroups with
many orbits). Thiscould be memory intensive, and is done reasonably by
backtrack.

This resolves #5564

* FIX: Abelianized subgroup rewriting

Replace method for `MaximalAbelianQuotient` for a subgroup with an easier
version that rewrites the presentation and then abelianizes.

This fixes #5609

* ENHANCE: AGSRCharacteristicSeries refine

Only attempt refinements with PCore, Agemo, Omega, if steps are not already
elementary abelian. This can avoid expensive subcomputations.
  • Loading branch information
hulpke authored Feb 2, 2024
1 parent 27c6268 commit c4fff6e
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 111 deletions.
46 changes: 24 additions & 22 deletions lib/autsr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -712,34 +712,36 @@ local somechar,d,i,j,u,v;
od;
fi;

for i in PrimeDivisors(Size(r)) do
u:=PCore(r,i);
if Size(u)>1 then
d:=RefinedSubnormalSeries(d,u);
j:=1;
repeat
v:=Agemo(u,i,j);
if Size(v)>1 then
d:=RefinedSubnormalSeries(d,v);
fi;
j:=j+1;
until Size(v)=1;
j:=1;
repeat
if Size(u)>=2^24 then
v:=u; # bail out as method for `Omega` will do so.
else
v:=Omega(u,i,j);
if Size(v)<Size(u) then
if not ForAll([1..Length(d)-1],
x->HasElementaryAbelianFactorGroup(d[x],d[x+1])) then
for i in PrimeDivisors(Size(r)) do
u:=PCore(r,i);
if Size(u)>1 then
d:=RefinedSubnormalSeries(d,u);
j:=1;
repeat
v:=Agemo(u,i,j);
if Size(v)>1 then
d:=RefinedSubnormalSeries(d,v);
fi;
j:=j+1;
fi;
until Size(v)=1;
j:=1;
repeat
if Size(u)>=2^24 then
v:=u; # bail out as method for `Omega` will do so.
else
v:=Omega(u,i,j);
if Size(v)<Size(u) then
d:=RefinedSubnormalSeries(d,v);
fi;
j:=j+1;
fi;

until Size(v)=Size(u);
fi;

od;
od;
fi;
Assert(1,ForAll([1..Length(d)-1],x->Size(d[x])<>Size(d[x+1])));
return d;
end);
Expand Down
184 changes: 96 additions & 88 deletions lib/ghomfp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1127,106 +1127,114 @@ local phi, m;
end);

InstallMethod(MaximalAbelianQuotient,
"subgroups of fp. abelian rewriting", true, [IsSubgroupFpGroup], 0,
"subgroups of fp., rewrite", true, [IsSubgroupFpGroup], 0,
function(u)
local aug,r,sec,expwrd,rels,ab,s,m,img,gen,i,j,t1,t2,tn,d,pos;
local iso;
if (HasIsWholeFamily(u) and IsWholeFamily(u))
# catch trivial case of rank 0 group
or Length(GeneratorsOfGroup(FamilyObj(u)!.wholeGroup))=0 then
TryNextMethod();
fi;

# get an augmented coset table from the group. Since we don't care about
# any particular generating set, we let the function chose.
aug:=AugmentedCosetTableInWholeGroup(u);

aug:=CopiedAugmentedCosetTable(aug);

r:=Length(aug.primaryGeneratorWords);
Info( InfoFpGroup, 1, "Abelian presentation with ",
Length(aug.subgroupGenerators), " generators");
iso:=IsomorphismFpGroup(u);
return iso*MaximalAbelianQuotient(Range(iso));
end);

# make vectors
expwrd:=function(l)
local v,i;
v:=ListWithIdenticalEntries(r,0);
for i in l do
if i>0 then v:=v+sec[i];
else v:=v-sec[-i];fi;
od;
return v;
end;

#InstallMethod(MaximalAbelianQuotient,
# "subgroups of fp. abelian rewriting", true, [IsSubgroupFpGroup], 0,
#function(u)
#local aug,r,sec,expwrd,rels,ab,s,m,img,gen,i,j,t1,t2,tn,d,pos;
# if (HasIsWholeFamily(u) and IsWholeFamily(u))
# # catch trivial case of rank 0 group
# or Length(GeneratorsOfGroup(FamilyObj(u)!.wholeGroup))=0 then
# TryNextMethod();
# fi;
#
# # get an augmented coset table from the group. Since we don't care about
# # any particular generating set, we let the function chose.
# aug:=AugmentedCosetTableInWholeGroup(u);
#
# aug:=CopiedAugmentedCosetTable(aug);
#
# r:=Length(aug.primaryGeneratorWords);
# Info( InfoFpGroup, 1, "Abelian presentation with ",
# Length(aug.subgroupGenerators), " generators");
#
# # make vectors
# expwrd:=function(l)
# local v,i;
# v:=ListWithIdenticalEntries(r,0);
# for i in l do
# if i>0 then v:=v+sec[i];
# else v:=v-sec[-i];fi;
# od;
# return v;
# end;
#
# # do GeneratorTranslation abelianized
# sec:=ShallowCopy(IdentityMat(r,1)); # initialize so next command works
#
# sec:=List(GeneratorTranslationAugmentedCosetTable(aug),
# x->expwrd(LetterRepAssocWord(x)));
# t1:=aug.tree[1];
# t2:=aug.tree[2];
# tn:=aug.treeNumbers;
# if Length(tn)>0 then
# for i in [Length(sec)+1..Maximum(tn)] do
# sec[i]:=sec[AbsInt(t1[i])]*SignInt(t1[i])
# +sec[AbsInt(t2[i])]*SignInt(t2[i]);
# od;
# fi;
#
# m:=sec;
# do GeneratorTranslation abelianized
sec:=ShallowCopy(IdentityMat(r,1)); # initialize so next command works

t1:=aug.tree[1];
t2:=aug.tree[2];
tn:=aug.treeNumbers;
if Length(tn)>0 then
for i in [Length(sec)+1..Maximum(tn)] do
sec[i]:=sec[AbsInt(t1[i])]*SignInt(t1[i])
+sec[AbsInt(t2[i])]*SignInt(t2[i]);
od;
fi;
# if sec<>m then Error("ZZZ");fi;

sec:=sec{aug.treeNumbers};

# now make relators abelian
rels:=[];
rels:=RewriteSubgroupRelators( aug, aug.groupRelators);
rels:=List(rels,expwrd);

rels:=ReducedRelationMat(rels);
if Length(rels)=0 then
Add(rels,ListWithIdenticalEntries(r,0));
fi;
s:=NormalFormIntMat(rels,25); # 9+16: SNF with transforms, destructive
d:=DiagonalOfMat(s.normal);
pos:=Filtered([1..Length(d)],x->d[x]<>1);
d:=d{pos};
ab:=AbelianGroup(d);
SetAbelianInvariants(u,d);
SetAbelianInvariants(ab,d);
if not IsFinite(ab) then SetReducedMultiplication(ab);fi;

gen:=ListWithIdenticalEntries(Length(rels[1]),One(ab));
gen{pos}:=GeneratorsOfGroup(ab);

s:=s.coltrans;
img:=[];
for i in [1..Length(s)] do
m:=One(ab);
for j in [1..Length(gen)] do
m:=m*gen[j]^s[i][j];
od;
Add(img,m);
od;
aug.primaryImages:=img;
if ForAll(img,IsOne) then
sec:=List(sec,x->img[1]);
else
sec:=List(sec,x->LinearCombinationPcgs(img,x));
fi;
aug.secondaryImages:=sec;

m:=List(aug.primaryGeneratorWords,x->ElementOfFpGroup(FamilyObj(One(u)),x));
m:=GroupHomomorphismByImagesNC(u,ab,m,img:noassert);

# but give it `aug' as coset table, so we will use rewriting for images
SetCosetTableFpHom(m,aug);

SetIsSurjective(m,true);

return m;
end);
# sec:=sec{aug.treeNumbers};
#
# # now make relators abelian
# rels:=[];
# rels:=RewriteSubgroupRelators( aug, aug.groupRelators);
# rels:=List(rels,expwrd);
#
# rels:=ReducedRelationMat(rels);
# if Length(rels)=0 then
# Add(rels,ListWithIdenticalEntries(r,0));
# fi;
# s:=NormalFormIntMat(rels,25); # 9+16: SNF with transforms, destructive
# d:=DiagonalOfMat(s.normal);
# pos:=Filtered([1..Length(d)],x->d[x]<>1);
# d:=d{pos};
# ab:=AbelianGroup(d);
# SetAbelianInvariants(u,d);
# SetAbelianInvariants(ab,d);
# if not IsFinite(ab) then SetReducedMultiplication(ab);fi;
#
# gen:=ListWithIdenticalEntries(Length(rels[1]),One(ab));
# gen{pos}:=GeneratorsOfGroup(ab);
#
# s:=s.coltrans;
# img:=[];
# for i in [1..Length(s)] do
# m:=One(ab);
# for j in [1..Length(gen)] do
# m:=m*gen[j]^s[i][j];
# od;
# Add(img,m);
# od;
# aug.primaryImages:=img;
# if ForAll(img,IsOne) then
# sec:=List(sec,x->img[1]);
# else
# sec:=List(sec,x->LinearCombinationPcgs(img,x));
# fi;
# aug.secondaryImages:=sec;
#
# m:=List(aug.primaryGeneratorWords,x->ElementOfFpGroup(FamilyObj(One(u)),x));
# m:=GroupHomomorphismByImagesNC(u,ab,m,img:noassert);
#
# # but give it `aug' as coset table, so we will use rewriting for images
# SetCosetTableFpHom(m,aug);
#
# SetIsSurjective(m,true);
#
# return m;
#end);

# u must be a subgroup of the image of home
InstallGlobalFunction(
Expand Down
11 changes: 10 additions & 1 deletion lib/oprtperm.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,16 @@ InstallOtherMethod( RepresentativeActionOp, "permgrp",true, [ IsPermGroup,
# action on permgroups, use backtrack
elif act = OnPoints and IsPermGroup( d ) and IsPermGroup( e ) then

if Size(G)<10^5 or NrMovedPoints(G)<500 then
if Size(G)<10^5 or NrMovedPoints(G)<500
# cyclic is handled special by backtrack
or IsCyclic(d) or IsCyclic(e) or
# does the group have many short orbits? If so the cluster test
# would do a lot of checking
Length(Orbits(d,MovedPoints(G)))^2>NrMovedPoints(G)
# Do not test for same orbit lengths -- this will be done by next
# level routine
then

rep:=ConjugatorPermGroup(G,d,e);
else
S:=ClusterConjugacyPermgroups(G,[e,d]);
Expand Down
32 changes: 32 additions & 0 deletions tst/testbugfix/2024-01-25-MaxAbQuot.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Reported by don't know, # 5609
gap> f := FreeGroup("a", "b", "c", "d", "e");;
gap> a := f.1;;b := f.2;;c := f.3;;d := f.4;;e := f.5;;
gap> g := f / [a^2, b^2, c^2, d^2, e^2, (a*b)^5, (a*c)^2, (a*d)^2, (a*e)^2,
> (b*c)^3, (b*d)^2, (b*e)^2, (c*d)^3, (c*e)^2, (d*e)^3];;
gap> w1 := ElementOfFpGroup(FamilyObj(g.1), a*b*c*d*e);;
gap> w2 := ElementOfFpGroup(FamilyObj(g.1),
> b*a*b*c*b*a*b*a*c*b*a*d*c*e*d*c*b*a*b*a*c*d*e*b*c*a*b*a*b*c*d*c*b*a
> *b*c*a*b*a*b*c);;
gap> w3 := ElementOfFpGroup(FamilyObj(g.1),
> b*a*b*c*b*a*d*c*b*a*b*a*c*b*a*d*e*d*c*b*a*b*c*d*e*a*b*a*b*c*d*b*a*b
> *c*a*b*a*b*c*d*c*b);;
gap> w4 := ElementOfFpGroup(FamilyObj(g.1),
> b*c*b*a*b*a*d*c*b*a*b*a*c*b*a*b*c*d*c*b*a*b*a*c*d*b*c*a*b*a*b*c*d*e
> *b*c*a*b*a*b*c*d*b*a*b*c*a*b);;
gap> w5 := ElementOfFpGroup(FamilyObj(g.1),
> b*a*b*a*c*d*c*b*a*b*a*c*b*a*d*c*b*a*b*c*d*e*d*c*b*a*b*c*d*a*b*c*a*b
> *a*b*c*d*e*b*a*b*c*d*b*c*a*b*a*b*c);;
gap> s := Subgroup(g, [w1, w2, w3, w4, w5]);;
gap> s1 := Subgroup(g, [w1, w2^-2, w3*w2^-1, w3^-1*w2^-1, w4*w2^-1,
> w4^-1*w2^-1, w5*w2^-1, w5^-1*w2^-1]);;
gap> s2:=Subgroup(g,[w1^-2, w2, w3, w4*w1^-1, w1*w2*w1^-1, w1*w3*w1^-1, w5]);;
gap> ab := MaximalAbelianQuotient(s);;
gap> q1 := GQuotients(s1, SymmetricGroup(2));;
gap> q2 := GQuotients(s2, SymmetricGroup(2));;
gap> k1 := Kernel(q1[7]);;
gap> nr:=First(Concatenation([7],[1..Length(q2)]),x->Kernel(q2[x])=k1);;
gap> k2 := Kernel(q2[nr]);;
gap> k1=k2;
true
gap> Image(ab,k1)=Image(ab,k2);
true

0 comments on commit c4fff6e

Please sign in to comment.