GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
#W present.gi Alnuth - ALgebraic NUmber THeory Bjoern Assmann
##
#############################################################################
##
#F GeneratorLatticeTF( rels )
##
## rels is a sublattice of Z^n.
## this function compute a minimal generatorset of Z^n/rels
## which is torsion-free
##
GeneratorLatticeTF := function( rels )
local n, normal,i,gens;
n := Length( rels[1] );
normal:=NormalFormIntMat(rels,13);
for i in [1..Length( normal.normal )] do
if normal.normal[i][i] <> 1 then
break;
fi;
od;
if i = Length( normal.normal ) then
i := i+1;
fi;
#gens := IdentityMat( n );
#gens := gens{[i..n]};
#gens := gens * normal.coltrans^-1;
gens := (normal.coltrans^-1);
gens := gens{[i..n]};
return gens;
end;
#############################################################################
##
#F CPCSOfTFGroupByFieldElements( F, gens )
##
## computes a constructive polycyclic sequence for gens
##
CPCSOfTFGroupByFieldElements := function( F, gens )
local rels, exps, newGens, e, newRels;
rels := RelationLatticeTF( F, gens );
if rels = [] then
return rec( gens:=gens,
relord:=List([1..Length(gens)], x -> 0));
fi;
exps := GeneratorLatticeTF(rels);
newGens := [];
for e in exps do
Add( newGens, MappedVector( e, gens ));
od;
newRels := List( [1..Length(newGens)], x -> 0);
return rec( gens:=newGens, relord:=newRels);
end;
#############################################################################
##
#F ExpVectorOfTFGroupByFieldElements( F, CPCS, elm )
##
## torsion free group !!
##
ExpVectorOfTFGroupByFieldElements := function( F, CPCS, elm )
local elms, rels, v, m, exp, i;
m := Length( CPCS.gens );
elms := StructuralCopy( CPCS.gens );
Add( elms, elm );
rels:= RelationLatticeTF( F, elms );
v := rels[1];
exp:=[];
for i in [1..m] do
exp[i]:=-v[i]/v[m+1];
od;
Assert( 2, MappedVector( exp, CPCS.gens ) = elm );
return exp;
end;
#############################################################################
##
#F Exp2genList(exp);
##
Exp2GenList:= function(exp)
local n, genList,i;
n:=Length(exp);
genList:=[];
for i in [1..n] do
if exp[i] <> 0 then
Append(genList,[i,exp[i]]);
fi;
od;
return genList;
end;
#############################################################################
##
#F PCPOfTFGroupByFieldElementsByCPCS( F, CPCS )
##
PCPOfTFGroupByFieldElementsByCPCS := function( F, CPCS )
local ro, n;
# Setup
ro := CPCS.relord;
n := Length( CPCS.gens );
return AbelianPcpGroup( n, ro );
end;
#############################################################################
##
#F PcpPresentationOfTFGroupByFieldElements( F, elms )
##
## given a field F and elms in F.
## this function computes a polycyclic presentation for the group
## generated by elms
##
PcpPresentationOfTFGroupByFieldElements := function( F, elms )
local CPCS, pcp;
CPCS := CPCSOfTFGroupByFieldElements( F, elms );
pcp := PCPOfTFGroupByFieldElementsByCPCS( F, CPCS );
return pcp;
end;
#############################################################################
# generalization to groups with torsion
#############################################################################
##
#F GeneratorLattice( rels )
##
## rels is a sublattice of Z^n.
## this function compute a minimal generatorset of Z^n/rels
## and the orders of the generators.
##
GeneratorLattice := function( rels )
local n, normal,i,gens, torsion, relord, j;
torsion := false;
n := Length( rels[1] );
normal:=NormalFormIntMat(rels,13);
for i in [1..Length( normal.normal )] do
if normal.normal[i][i] <> 1 then
torsion := true;
break;
fi;
od;
if not torsion then
i := i+1;
fi;
#gens := IdentityMat( n );
#gens := gens{[i..n]};
#gens := gens * normal.coltrans^-1;
gens := (normal.coltrans^-1);
gens := gens{[i..n]};
# set relative orders of gens
relord := [];
for j in [i..n] do
if IsBound(normal.normal[j]) then
Add( relord, normal.normal[j][j] );
else
Add( relord, 0 );
fi;
od;
return rec(exps := gens, relord:=relord );
end;
#############################################################################
##
#F CPCSOfGroupByFieldElements( F, gens )
##
## computes a constructive polycyclic sequence for gens
##
CPCSOfGroupByFieldElements := function( F, gens )
local rels, exps, newGens, e, newRels;
rels := RelationLattice( F, gens );
if rels = [] then
return rec( gens:=gens,
relord:=List([1..Length(gens)], x -> 0));
fi;
exps := GeneratorLattice(rels);
newGens := [];
for e in exps.exps do
Add( newGens, MappedVector( e, gens ));
od;
return rec( gens:=newGens, relord:=exps.relord);
end;
#############################################################################
##
#F ExpVectorOfGroupByFieldElements( F, CPCS, elm )
##
ExpVectorOfGroupByFieldElements := function( F, CPCS, elm )
local elms, rels, l, m, exp, i;
if IsList(CPCS.gens[1]) then
if Length(elm) <> Length(CPCS.gens[1]) then
return fail;
fi;
fi;
m := Length( CPCS.gens );
if elm=elm^0 then
return List([1..m], x-> 0);
fi;
elms := StructuralCopy( CPCS.gens );
l :=Concatenation([elm],elms);
rels := RelationLattice( F, l );
if rels=[] then
return fail;
fi;
rels := NormalFormIntMat(rels,0).normal;
if not rels[1][1]=1 then return fail; fi;
exp := -rels[1]{[2..(m+1)]};
Assert( 2, MappedVector( exp, CPCS.gens ) = elm,
"failure in ExpVectorOfGroupByFieldElements" );
return exp;
end;
#############################################################################
##
#F PCPOfGroupByFieldElementsByCPCS( F, CPCS )
##
PCPOfGroupByFieldElementsByCPCS := function( F, CPCS )
local ro, n;
# Setup
ro := CPCS.relord;
n := Length( CPCS.gens );
return AbelianPcpGroup( n, ro );
end;
#############################################################################
##
#F PcpPresentationOfGroupByFieldElements( F, elms )
##
## given a field F and elms in F.
## this function computes a polycyclic presentation for the group
## generated by elms
##
PcpPresentationOfGroupByFieldElements := function( F, elms )
local CPCS, pcp;
CPCS := CPCSOfGroupByFieldElements( F, elms );
pcp := PCPOfGroupByFieldElementsByCPCS( F, CPCS );
return pcp;
end;
InstallGlobalFunction( PcpPresentationMultGroupByFieldEl, function( F, elms )
local CPCS, pcp;
CPCS := CPCSOfGroupByFieldElements( F, elms );
pcp := PCPOfGroupByFieldElementsByCPCS( F, CPCS );
return pcp;
end);
InstallGlobalFunction( PcpPresentationOfMultiplicativeSubgroup, function( F, elms )
local CPCS, pcp;
CPCS := CPCSOfGroupByFieldElements( F, elms );
pcp := PCPOfGroupByFieldElementsByCPCS( F, CPCS );
return pcp;
end);
#############################################################################
# test functions
RandomGroupElement := function(gens)
local d,k,g,i,length,x,n;
k:=Length(gens);
g:=gens[1]^0;
length:=Random(5,30);
for i in [1..length] do
x:=Random(1,k);
n:=Random(Integers);
g:=g*(gens[x]^n);
od;
return g;
end;
TestExpVectorOfGroupByFieldElements :=function( F, CPCS, gens,numberOfTests)
local i,g,exp;
SetAssertionLevel(2);
for i in [1..numberOfTests] do
Print(i);
g:=RandomGroupElement(gens);
#Print("g ist gleich ",g,"\n");
exp:=ExpVectorOfGroupByFieldElements( F, CPCS, g );
#Print("exp ist gleich ",exp,"\n");
od;
SetAssertionLevel(0);
end;
TestCPCSOfGroupByFieldElements := function( mats )
local F,j, CPCS;
F := FieldByMatricesNC( mats );
#j := Random([1..Length(mats)]);
j := Length(mats);
CPCS:=CPCSOfGroupByFieldElements( F, mats{[1..j]} );
TestExpVectorOfGroupByFieldElements( F, CPCS, mats{[1..j]},10);
end;
# faster
TestCPCSOfGroupByFieldElements2 := function( mats )
local F,j, CPCS,b;
F := FieldByMatricesNC( mats );
b := Basis( F );
F := FieldByMatrixBasisNC( b );
#j := Random([1..Length(mats)]);
j := Length(mats);
CPCS:=CPCSOfGroupByFieldElements( F, mats{[1..j]} );
TestExpVectorOfGroupByFieldElements( F, CPCS, mats{[1..j]},10);
end;
TestCPCSOfGroupByFieldElementsPol := function( pol )
local elms,F,j, CPCS;
F := FieldByPolynomialNC( pol );
elms := List( [1..10], x-> Random(F) );
CPCS:=CPCSOfGroupByFieldElements( F, elms );
TestExpVectorOfGroupByFieldElements( F, CPCS, elms,10);
end;