Skip to content

Commit

Permalink
ENHANCE: normalform option for FpGroupCocycle
Browse files Browse the repository at this point in the history
Using the RWS and normal form. This often costs little extra, and is just nicer overall.

Also adds required forward declaration of utility function.
  • Loading branch information
hulpke authored and fingolfin committed May 3, 2021
1 parent b1c4988 commit 69f0389
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 8 deletions.
2 changes: 1 addition & 1 deletion lib/gpfpiso.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,7 @@ local hom;
return hom;
end);

BindGlobal("MakeFpGroupToMonoidHomType1",function(fp,m)
InstallGlobalFunction(MakeFpGroupToMonoidHomType1,function(fp,m)
local fam,mfam,fpfam,mfpfam,hom;
fam:=FamilyObj(UnderlyingElement(One(fp)));
mfam:=FamilyObj(UnderlyingElement(One(m)));
Expand Down
3 changes: 3 additions & 0 deletions lib/grpfp.gd
Original file line number Diff line number Diff line change
Expand Up @@ -1352,5 +1352,8 @@ DeclareGlobalFunction("StringFactorizationWord");
# used to test whether abeliniazation can be mapped in GQuotients
DeclareGlobalFunction("CanMapFiniteAbelianInvariants");

# map fpgrp->fpmon creator
DeclareGlobalFunction("MakeFpGroupToMonoidHomType1");

# used in homomorphisms
DeclareGlobalName("TRIVIAL_FP_GROUP");
8 changes: 7 additions & 1 deletion lib/twocohom.gd
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,9 @@ DeclareOperation( "TwoCohomology", [ IsPcGroup, IsObject ] );
## routine, this generating system corresponds to the components
## <C>group</C> and <C>module</C> of the record returned.
## The extension corresponding to a cocyle <C>c</C> can be constructed as
## <C>Extension(r,c)</C> where <C>r</C> is the cohomology record. This is
## <C>FpGroupCocycle(r,c)</C> where <C>r</C> is the cohomology record. This is
## currently done as a finitely presented group.
##
## <Example><![CDATA[
## gap> g:=Group((1,2,3,4,5),(1,2,3));;
## gap> mats:=[[[2,0,0,1],[1,2,1,0],[2,1,1,1],[2,1,1,0]],
Expand Down Expand Up @@ -274,6 +275,8 @@ DeclareOperation( "TwoCohomologyGeneric", [ IsGroup, IsObject ] );
## If the optional parameter <A>doperm</A> is given as <A>true</A>, a
## faithful permutation representation is computed and stored in the
## attribute <Ref Attr="IsomorphismPermGroup"/> of the computed group.
## If the option <C>normalform</C> is given as <C>true</C>, arithmetic in
## the resulting finitely presented group will bring words into normal form.
## <Example><![CDATA[
## gap> g:=Group((2,15,8,16)(3,17,14,21)(4,23,20,6)(5,9,22,11)(7,13,19,25),
## > (2,12,7,17)(3,18,13,23)(4,24,19,9)(5,10,25,15)(6,11,16,21));;
Expand All @@ -299,6 +302,9 @@ DeclareOperation( "TwoCohomologyGeneric", [ IsGroup, IsObject ] );
## [ [ 480, 3 ], [ 3888, 1 ], [ 6480, 1 ], [ 7776, 1 ], [ 19440, 1 ] ]
## gap> Collected(List(MaximalSubgroupClassReps(g2),Size));
## [ [ 3888, 1 ], [ 6480, 1 ], [ 7776, 1 ], [ 19440, 1 ] ]
## gap> p:=FpGroupCocycle(coh,coh.cohomology[1],true:normalform);;
## gap> p.7*p.1; # i.e. m1*F1, but in normal form
## F1*m2^-1
## ]]></Example>
## </Description>
## </ManSection>
Expand Down
124 changes: 118 additions & 6 deletions lib/twocohom.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,8 @@ end);
InstallGlobalFunction(FpGroupCocycle,function(arg)
local r,z,ogens,n,gens,str,dim,i,j,f,rels,new,quot,g,p,collect,m,e,fp,old,sim,
it,hom,trysy,prime,mindeg,fps,ei,mgens,mwrd,nn,newfree,mfpi,mmats,sub,
tab,tab0,evalprod,gensmrep,invsmrep,zerob,step,simi,simiq,wasbold;
tab,tab0,evalprod,gensmrep,invsmrep,zerob,step,simi,simiq,wasbold,
mon,ord,mn,melmvec;

# function to evaluate product (as integer list) in gens (and their
# inverses invs) with corresponding action mats
Expand All @@ -1518,17 +1519,124 @@ local r,z,ogens,n,gens,str,dim,i,j,f,rels,new,quot,g,p,collect,m,e,fp,old,sim,
fi;
od;
return new;

end;


melmvec:=function(v)
local i,a,w;
w:=One(f);
for i in [1..Length(v)] do
a:=Int(v[i]);
if prime=2 or a*2<prime then
w:=w*gens[2*i-1+mn]^a;
else
a:=prime-a;
w:=w*gens[2*i+mn]^a;
fi;
od;
return w;
end;

r:=arg[1];
z:=arg[2];
ogens:=GeneratorsOfGroup(r.presentation.group);
dim:=r.module.dimension;
prime:=Size(r.module.field);

if ValueOption("normalform")<>true then
mon:=fail;
else
# Construct the monoid and rewriting system, as this is cheap to do but
# will allow for reduced multiplication. Do so before the group, so there is no
# issue about overwriting variables that might be needed later
mon:=Image(r.monhom);
str:=List(GeneratorsOfMonoid(mon),String);
mn:=Length(str);
for i in [1..dim] do
Add(str,Concatenation("m",String(i)));
Add(str,Concatenation("m",String(i),"^-1"));
od;
f:=FreeMonoid(str);
gens:=GeneratorsOfMonoid(f);

rels:=[];
# inverse rules
for i in [1,3..Length(gens)-1] do
Add(rels,[gens[i]*gens[i+1],One(f)]);
Add(rels,[gens[i+1]*gens[i],One(f)]);
od;
# rules with tails
for i in [1..Length(r.presentation.monrulpos)] do
new:=RelationsOfFpMonoid(mon)[r.presentation.monrulpos[i]];
new:=List(new,x->MappedWord(x,FreeGeneratorsOfFpMonoid(mon),gens{[1..mn]}));
new[2]:=new[2]*melmvec(z{[(i-1)*dim+1..i*dim]});
Add(rels,new);
od;

if r.presentation.killrelators<>[] then Error("TODO killrelators");fi;

# elementary abelian
for i in [mn+1,mn+3..Length(str)-1] do
if prime=2 then
Add(rels,[gens[i]^2,One(f)]);
Add(rels,[gens[i+1],gens[i]]);
else
j:=QuoInt(prime+1,2); # power that changes the exponent sign
Add(rels,[gens[i]^j,gens[i+1]^(j-1)]);
Add(rels,[gens[i+1]^j,gens[i]^(j-1)]);
fi;
for j in [i+2..Length(str)] do
Add(rels,[gens[j]*gens[i],gens[i]*gens[j]]);
Add(rels,[gens[j]*gens[i+1],gens[i+1]*gens[j]]);
od;
od;
# module rules
for i in [1..mn] do
for j in [mn+1..Length(str)] do
new:=r.module.generators[QuoInt(i+1,2)];
if IsEvenInt(i) then new:=new^-1; fi;
new:=new[QuoInt(j-mn+1,2)];
if IsEvenInt(j) then new:=-new;fi;
Add(rels,[gens[j]*gens[i],gens[i]*melmvec(new)]);
od;
od;
if HasReducedConfluentRewritingSystem(mon) then
ord:=OrderingOfRewritingSystem(ReducedConfluentRewritingSystem(mon));
if HasLevelsOfGenerators(ord) then
ord:=WreathProductOrdering(f,
Concatenation(LevelsOfGenerators(ord)+1,
ListWithIdenticalEntries(2*dim,1)));
else
ord:=WreathProductOrdering(f,
Concatenation(ListWithIdenticalEntries(mn,2),
ListWithIdenticalEntries(2*dim,1)));
fi;
else
ord:=WreathProductOrdering(f,
Concatenation(ListWithIdenticalEntries(mn,2),
ListWithIdenticalEntries(2*dim,1)));
fi;

# if there is any [x^2,1] relation, this means the inverse needs to be
# mapped to the generator. (This will have been skipped in the
# monrulpos.)
for i in rels do
if Length(i[2])=0 and Length(i[1])=2
and Length(Set(LetterRepAssocWord(i[1])))=1 then
new:=LetterRepAssocWord(i[1])[1];
if IsOddInt(new) then
Add(rels,[gens[new+1],gens[new]]);
fi;
fi;
od;

mon:=FactorFreeMonoidByRelations(f,rels);
new:=KnuthBendixRewritingSystem(FamilyObj(One(mon)),ord);
MakeConfluent(new); # will add rules to kill inverses, if needed
SetReducedConfluentRewritingSystem(mon,new);
fi;

# now construct the group
str:=List(ogens,String);
dim:=r.module.dimension;
zerob:=ImmutableVector(r.module.field,
ListWithIdenticalEntries(dim,Zero(r.module.field)));
n:=Length(ogens);
Expand Down Expand Up @@ -1560,7 +1668,7 @@ local r,z,ogens,n,gens,str,dim,i,j,f,rels,new,quot,g,p,collect,m,e,fp,old,sim,
od;

for i in [n+1..Length(gens)] do
Add(rels,gens[i]^r.prime);
Add(rels,gens[i]^prime);
for j in [i+1..Length(gens)] do
Add(rels,Comm(gens[i],gens[j]));
od;
Expand All @@ -1572,11 +1680,15 @@ local r,z,ogens,n,gens,str,dim,i,j,f,rels,new,quot,g,p,collect,m,e,fp,old,sim,
od;
od;
fp:=f/rels;
prime:=Size(r.module.field);
SetSize(fp,Size(r.group)*prime^r.module.dimension);
simi:=fail;
wasbold:=false;

if mon<>fail then
rels:=MakeFpGroupToMonoidHomType1(fp,mon);
SetReducedMultiplication(fp);
fi;

if Length(arg)>2 and arg[3]=true then
if IsZero(z) and MTX.IsIrreducible(r.module) then
# make SDP directly
Expand Down

0 comments on commit 69f0389

Please sign in to comment.