|
#############################################################################
##
#W unipo.gi POLENTA package Bjoern Assmann
##
## Methods for the calculation of
## constructive pc-sequences for unipotent matrix groups
##
#Y 2003
##
# We have to calculate a basis of Q^d
# which exhibits a flag for all u in gens.
# we know that the matrices
# in gens are unipotent. next we have to determine the nullspace of
# (u-1)^1, (u-1)^2,... we have to do that simultaneously for all
# matrices in gens so we have to write them in one big matrix.
#############################################################################
##
#F POL_BuildBigMatrix( modifiedGens )
##
## writes the matrices of modifiedGens in matrix s.t. we can
## apply NullspaceRatMat
## if modifiedGens=[g_1,...,g_n] then
## BigMatrix:=(g_1,...,g_n)
##
POL_BuildBigMatrix := function( modifiedGens )
local bigMatrix,i,j ;
bigMatrix := [];
for i in [1..Length( modifiedGens[1] )] do
bigMatrix[i] := [];
for j in [1..Length(modifiedGens )] do
Append( bigMatrix[i],modifiedGens[j][i] );
od;
od;
return bigMatrix;
end;
#For determining a flag you have to compute the nullspace W of a matrix u
#then you proceed by passing to the factor V/W an compute a new
#nullspace.
#this process will terminate, because u is unipotent which means that
#u is conjugate to a upper triangular matrix with one's on the diagonal
#############################################################################
##
#F POL_DetermineFlag( gens )
##
POL_DetermineFlag := function( gens )
local d,flag,u,bigMatrix,nullSpace,full,indGens,factorFlag,
preImage,modifiedGens,nath;
d := Length( gens[1][1] );
flag := [];
# calculate (u-1 ) for all u in gens
modifiedGens := [];
for u in gens do
Add( modifiedGens,u-IdentityMat(d ) );
od;
# calculate the nullspace W
bigMatrix := POL_BuildBigMatrix( modifiedGens );
nullSpace := NullspaceRatMat( bigMatrix );
if nullSpace=[] then
#Error("Failure in POL_DetermineFlag\n Group is not unipotent\n" );
return fail;
fi;
# induce action to the factor V/W
full := IdentityMat( d );
if Length( nullSpace )=d then
return nullSpace;
fi;
nullSpace :=POL_CopyVectorList( nullSpace );
TriangulizeMat( nullSpace );
Append( flag, nullSpace );
nath := NaturalHomomorphismBySemiEchelonBases( full, nullSpace );
indGens := List( gens, x-> InducedActionFactorByNHSEB(x,nath) );
# recursive call
factorFlag := POL_DetermineFlag( indGens );
if factorFlag = fail then return fail; fi;
preImage := PreimagesRepresentativeByNHSEB( factorFlag,nath );
Append( flag,preImage );
return flag;
end;
#############################################################################
##
#F POL_DetermineConjugatorTriangular( gens )
##
## brings gens in upper triangular form
##
POL_DetermineConjugatorTriangular := function( gens )
local a,flag,d,g,i,j,alpha,beta;
flag := POL_DetermineFlag( gens );
if flag = fail then return fail; fi;
# POL_TestFlag( flag,gens );
d := Length( gens[1] );
g := [];
# for an upper triangular matrix we need a inversed flag
for i in [1..d] do
g[i] := flag[d-i+1];
od;
return g^-1;
end;
#############################################################################
##
#F POL_DetermineConjugatorIntegral( gens )
##
## brings gens in integer form
##
POL_DetermineConjugatorIntegral := function( gens )
local d,a,i,j,g,x,alpha;
d := Length( gens[1] );
alpha := IdentityMat(d );
for i in [2..d] do
a := 1;
for g in gens do
for j in [1..i-1] do
x := DenominatorRat( alpha[j][j]^-1*g[j][i] );
a := Lcm( a, x );
od;
od;
alpha[i][i] := a;
od;
return alpha;
end;
#############################################################################
##
#F POL_UpperTriangIntTest( gens )
##
##
POL_UpperTriangIntTest := function( gens )
local d,goodForm,g,i,j;
d := Length( gens[1] );
goodForm := true;
for g in gens do
for i in [1..d] do
for j in [1..d] do
if i=j then
if not g[i][j]=1 then
Info( InfoPolenta,4, i,"problemplace ",j,"\n" );
goodForm := false;
return goodForm;
fi;
elif i < j then
if DenominatorRat( g[i][j] )>1 then
Info( InfoPolenta, 4,i,"problemplace ",j,"\n" );
goodForm := false;
return goodForm;
fi;
elif not g[i][j]=0 then
Info( InfoPolenta, 4,i,"problemplace ",j,"\n" );
goodForm := false;
return goodForm;
fi;
od;
od;
od;
return goodForm;
end;
#############################################################################
##
#F POL_DetermineRealConjugator( gens )
##
## brings <gens> in upper triangular integral form
##
POL_DetermineRealConjugator := function( gens )
local v,gens_mod,w,conjugator;
# upper triangular form
v := POL_DetermineConjugatorTriangular( gens );
if v = fail then return fail; fi;
gens_mod := List( gens, x-> x^v );
# upper triangular integer form
w := POL_DetermineConjugatorIntegral( gens_mod );
conjugator := v*w;
# test if it is in upper triangular and integer form
return conjugator;
end;
#############################################################################
##
#F POL_UnipotentMats2Pcp( gens )
##
## maps the unipotent group <gens> to a Pcp-Group, and saves the
## used conjugator
##
POL_UnipotentMats2Pcp := function( gens )
local v,gens_mod,w,conjugator,pcp;
# determine conjugator
# upper triangular form
v := POL_DetermineConjugatorTriangular( gens );
if v = fail then return fail; fi;
gens_mod := GeneratorsOfGroup( Group( gens )^v );
# upper triangular integer form
w := POL_DetermineConjugatorIntegral( gens_mod );
conjugator := v*w;
# conjugate group
gens_mod := GeneratorsOfGroup( Group( gens )^conjugator );
# test if it is in upper triangular and integer form
Assert( 2, POL_UpperTriangIntTest( gens_mod ) );
# convert the conjugated group to a pcp-group
pcp := SubgroupUnitriangularPcpGroup( gens_mod );
return rec( pcp := pcp,conjugator := conjugator,gens_mod := gens_mod );
end;
#############################################################################
##
#F POL_FirstCloseUnderConjugation( gens,gens_U_p )
##
## extends the matrices in gens_U_p to gens_U_p2 in such a way that
## the conjugator belonging to gens_U_p2 can be used also for the
## matrices of the form gens_U_p2[i]^gens[j]
##
POL_FirstCloseUnderConjugation := function( gens,gens_U_p )
local conjugator,found,g,h,matrix,newGens,rec1;
conjugator := POL_DetermineRealConjugator( gens_U_p );
if conjugator = fail then return fail; fi;
newGens := [];
for g in gens_U_p do
for h in gens do
matrix := g^h;
if not POL_UpperTriangIntTest( [matrix^conjugator] ) then
# we have to extend our gens_U_p
newGens := Concatenation( gens_U_p,[matrix] );
Info( InfoPolenta, 3,
"Extending in FirstCloseUnderConjugation\n",
"newGens are",newGens,"\n" );
rec1 := POL_FirstCloseUnderConjugation( gens,newGens );
return rec1;
fi;
od;
od;
# if the conjugator is good for all conjugates we can proceed
return rec( gens := gens,gens_U_p := gens_U_p,conjugator := conjugator );
end;
#############################################################################
##
#M POL_UnitriangularPcpGroup( n, p ) . . .. . . . for p = 0 we take UT( n, Z )
##
POL_UnitriangularPcpGroup := function( n, p )
local l, c, g, r, i, j, h, f, k, v, o, G;
if not IsInt(n) or n <= 1 then return fail; fi;
if not (IsPrimeInt(p) or p=0) then return fail; fi;
l := n*(n-1)/2;
c := FromTheLeftCollector( l );
# compute matrix generators
g := [];
for i in [1..n-1] do
for j in [1..n-i] do
r := IdentityMat( n );
r[j][i+j] := 1;
Add( g, r );
od;
od;
# mod out p if necessary
if p > 0 then g := List( g, x -> x * One( GF(p) ) ); fi;
# get inverses
h := List( g, x -> x^-1 );
# read of pc presentation
for i in [1..l] do
# commutators
for j in [1..i-1] do
#v := Comm( g[j], g[i] );
v := Comm( g[i], g[j] );
if v <> v^0 then
if v in g then
k := Position( g, v );
o := [k, 1];
elif v in h then
k := Position( h, v );
o := [k, -1];
else
Error("commutator out of range");
fi;
SetCommutator( c, i, j, o );
fi;
od;
# powers
if p > 0 then
SetRelativeOrder( c, i, p );
v := g[i]^p;
if v <> v^0 then Error("power out of range"); fi;
fi;
od;
UpdatePolycyclicCollector( c );
# translate from collector to group
G := PcpGroupByCollectorNC( c );
G!.mats := g;
G!.isomorphism := GroupHomomorphismByImagesNC( G, Group(g), Igs(G), g);
return G;
end;
#############################################################################
##
#F POL_SubgroupUnitriangularPcpGroup_Mod( mats )
##
## just the returned value is changed in comparaison with original
## function
##
POL_SubgroupUnitriangularPcpGroup_Mod := function( mats )
local rec1,n, p, G, g, i, j, r, h, m, e, v, c;
# get the dimension, the char and the full unitriangular group
n := Length( mats[1] );
p := Characteristic( mats[1][1][1] );
G := POL_UnitriangularPcpGroup( n, p );
# compute corresponding generators
g := [];
for i in [1..n-1] do
for j in [1..n-i] do
r := IdentityMat( n );
r[j][i+j] := 1;
Add( g, r );
od;
od;
# get exponents for each matrix
h := [];
for m in mats do
e := [];
c := 0;
for i in [1..n-1] do
v := List( [1..n-i], x -> m[x][x+i] );
r := MappedVector( v, g{[c+1..c+n-i]} );
m := r^-1 * m;
c := c + n-i;
Append( e, v );
od;
Add( h, MappedVector( e, Pcp( G ) ) );
od;
# Print( " h = ",h,"\n" );
return rec( pcp := Subgroup( G, h ),UT := G );
end;
#############################################################################
##
#F POL_MapToUnipotentPcp( matrix,pcp_record )
##
##
POL_MapToUnipotentPcp := function( matrix,pcp_record )
local n,p,m,i,j,r,g,e,c,v;
# get the dimension, and the full unitriangular group
n := Length( matrix );
p := 0;
m := matrix;
# compute corresponding generators
g := [];
for i in [1..n-1] do
for j in [1..n-i] do
r := IdentityMat( n );
r[j][i+j] := 1;
Add( g, r );
od;
od;
# get exponent
e := [];
c := 0;
for i in [1..n-1] do
v := List( [1..n-i], x -> m[x][x+i] );
r := MappedVector( v, g{[c+1..c+n-i]} );
m := r^-1 * m;
c := c + n-i;
Append( e, v );
od;
return MappedVector( e,Pcp( pcp_record.UT ) ) ;
end;
#############################################################################
##
#F CPCS_Unipotent( gens_U_p )
##
## calculates a constructive pc-sequence for
## the unipotent group <gens_U_p>
##
CPCS_Unipotent := function( gens_U_p )
local g,rec1,mats,A,dim,gens_U_p_mod,mat,mat3,h,
mat2,pcpElement,conjugator,G,gensOfG,
pcp_rec,rels,pcs,newGens,i;
dim := Length( gens_U_p[1] );
#check for trivial elements
gens_U_p_mod := [];
for i in [1..Length( gens_U_p )] do
if not gens_U_p[i]=gens_U_p[i]^0 then
Add( gens_U_p_mod,gens_U_p[i] );
fi;
od;
# exclude the trivial case
if gens_U_p_mod=[] then
return rec( rels := [],pcs := [] );
fi;
# find a conjugator
conjugator := POL_DetermineRealConjugator( gens_U_p_mod );
if conjugator = fail then return fail; fi;
#calculate a pcp for <gens_U_p_mod>^conjugator
G := Group( gens_U_p_mod );
G := G^conjugator;
gensOfG := GeneratorsOfGroup( G );
# assert that <gensOfG> is in upper triangular and integer form
Assert( 2, POL_UpperTriangIntTest( gensOfG ) );
# convert the conjugated group to a Pcp-group
Info( InfoPolenta, 3, "calculate the pcp-Group of the group\n",
gensOfG,"\n" );
pcp_rec := POL_SubgroupUnitriangularPcpGroup_Mod( gensOfG );
# calculate a pc-sequence for <gens_U_p>
pcs := [];
A := POL_UnitriangularPcpGroup( dim,0 );
mats := A!.mats;
for g in GeneratorsOfPcp( Pcp( pcp_rec.pcp ) ) do
#calculate preimage, i.e. convert it to a mat and conjugate it
mat := MappedVector( Exponents( g ), mats );
mat := mat^( conjugator^-1 );
Add( pcs,mat );
od;
# save the relative orders
rels := Pcp( pcp_rec.pcp )!.rels;
return rec( pcp_record := pcp_rec,
conjugator := conjugator,
pcs := pcs,rels := rels );
end;
#############################################################################
##
#F CPCS_Unipotent_Conjugation_Version2( gens, gens_U_p )
##
## calculate a constructive pc-sequence for
## the unipotent group <gens_U_p>^<gens>
##
CPCS_Unipotent_Conjugation_Version2 := function( gens, gens_U_p )
local g,rec1,mats,A,dim,gens_U_p_mod,mat,mat3,h,
mat2,pcpElement,conjugator,G,gensOfG,
pcp_rec,rels,pcs,newGens,i, gens2;
dim := Length( gens[1] );
#check for trivial elements
gens_U_p_mod := [];
for i in [1..Length( gens_U_p )] do
if not gens_U_p[i]=gens_U_p[i]^0 then
Add( gens_U_p_mod,gens_U_p[i] );
fi;
od;
# exclude the trivial case
if gens_U_p_mod=[] then
return rec( rels := [], pcs := [] );
fi;
# find a good conjugator even for conjugated elements of gens_U_p
rec1 := POL_FirstCloseUnderConjugation( gens, gens_U_p_mod );
if rec1 = fail then return fail; fi;
gens_U_p_mod := rec1.gens_U_p;
conjugator := rec1.conjugator;
#calculate a pcp for <gens_U_p_mod>^conjugator;
G := Group( gens_U_p_mod );
G := G^conjugator;
gensOfG := GeneratorsOfGroup( G );
# assert that <gensOfG> is in upper triangular and integer form
Assert( 2, POL_UpperTriangIntTest( gensOfG ) );
# convert the conjugated group to a Pcp-group
Info( InfoPolenta, 3, "Unipotent: calculate the pcp-Group of the group\n",
gensOfG,"\n" );
pcp_rec := POL_SubgroupUnitriangularPcpGroup_Mod( gensOfG );
# check if the preimages of the gens of the pcp are
# stable under conjugation
A := POL_UnitriangularPcpGroup( dim,0 );
mats := A!.mats;
for g in GeneratorsOfGroup( pcp_rec.pcp ) do
# calculate the preimage, i.e. convert it to a matrix and conjugate
mat := MappedVector( Exponents( g ),mats );
mat := mat^( conjugator^-1 );
gens2 := Concatenation( gens, List( gens, x-> x^-1 ));
for h in gens2 do
mat2 := mat^h;
mat3 := mat2^conjugator;
if not POL_MapToUnipotentPcp( mat3,pcp_rec ) in pcp_rec.pcp then
#extend gens_U_p
Info( InfoPolenta,3, "Extending gens_U_p \n" );
# newGens := Concatenation( gens_U_p,[mat2] );
newGens := Concatenation( gens_U_p_mod,[mat2] );
return CPCS_Unipotent_Conjugation_Version2( gens,newGens );
fi;
od;
od;
# calculate a pc-sequence for <gens_U_p>
pcs := [];
for g in GeneratorsOfPcp( Pcp( pcp_rec.pcp ) ) do
#calculate preimage, i.e. convert it to a mat and conjugate it
mat := MappedVector( Exponents( g ),mats );
mat := mat^( conjugator^-1 );
Add( pcs,mat );
od;
# save the relative orders
rels := Pcp( pcp_rec.pcp )!.rels;
return rec( pcp_record := pcp_rec,
conjugator := conjugator,
pcs := pcs,rels := rels );
end;
#############################################################################
##
#F CPCS_Unipotent_Conjugation( gens, gens_U_p )
##
## calculates a constructive pc-sequence for
## the unipotent group <gens_U_p>^<gens>
##
CPCS_Unipotent_Conjugation := function( gens, gens_U_p )
local dim, gens_U_p_mod,rec1,conjugator,U,gensOfU, gensWithInverses,
level, mat, h, mat2, mat3,P, rels, newGens,i,testMembership,
pcs, gensWithInversesConj, pcs_U_p;
dim := Length( gens[1] );
# clear generators list from trivial elements
gens_U_p_mod := [];
for i in [1..Length( gens_U_p )] do
if not gens_U_p[i]=gens_U_p[i]^0 then
Add( gens_U_p_mod,gens_U_p[i] );
fi;
od;
# exclude the trivial case
if gens_U_p_mod=[] then
return rec( rels := [], pcs := [] );
fi;
# find a good conjugator even for conjugated elements of gens_U_p
rec1 := POL_FirstCloseUnderConjugation( gens, gens_U_p_mod );
if rec1 = fail then return fail; fi;
gens_U_p_mod := rec1.gens_U_p;
conjugator := rec1.conjugator;
#calculate a pcp for <gens_U_p_mod>^conjugator;
U := Group( gens_U_p_mod );
U := U^conjugator;
gensOfU := GeneratorsOfGroup( U );
# assert that <gensOfU> is in upper triangular and integer form
Assert( 2, POL_UpperTriangIntTest( gensOfU ) );
# compute a polycyclic sequence for U
Info( InfoPolenta, 3, "calculate levels ",
" of the group...\n",
gensOfU,"\n" );
level := SiftUpperUnitriMatGroup( U );
Info( InfoPolenta, 3, "... finished\n" );
# check if <gens_U_p> is stable under conjugation
Info( InfoPolenta, 3,
"check if <gens_U_p> is stable under conjugation...");
gensWithInverses := Concatenation( gens, List( gens, x-> x^-1 ));
gensWithInversesConj := List( gensWithInverses, x-> x^conjugator );
P := PolycyclicGenerators( level );
# maybe incomplete pcs of U^conjugator
pcs_U_p := P.matrices;
for mat in pcs_U_p do
#for mat in gens_U_p do
for h in gensWithInversesConj do
mat2 := mat^h;
Info( InfoPolenta, 3, "test membership ..." );
testMembership := DecomposeUpperUnitriMat( level, mat2 );
Info( InfoPolenta, 3, "... finished" );
if IsBool( testMembership ) then
#extend gens_U_p
Info(InfoPolenta,3,"Extending generator list of unipotent subgroup\n" );
#newGens := Concatenation( gens_U_p,[mat2] );
newGens := Concatenation( pcs_U_p,[mat2] );
newGens := List( newGens, x-> x^( conjugator^-1 ) );
Info( InfoPolenta, 2,
"An extended list of the normal subgroup generators for the\n",
" unipotent subgroup is" );
Info( InfoPolenta, 2, newGens );
return CPCS_Unipotent_Conjugation( gens,newGens );
fi;
od;
od;
Info( InfoPolenta, 3, "...finished" );
# assemble necessary data for a constructive pcs of <gens_U_p>
#P := PolycyclicGenerators( level );
rels := List( [1..Length(P.gens)], x->0 );
pcs := List( pcs_U_p, x-> x^( conjugator^-1 ) );
#U := Group( P.matrices );
#U := U^( conjugator^-1 );
return rec( level := level,
pcs := pcs,
gens := P.gens,
conjugator := conjugator,
rels := rels );
end;
#############################################################################
##
#F ExponentOfCPCS_Unipotent( matrix, conPcs )
##
##
ExponentOfCPCS_Unipotent := function( matrix, conPcs )
local matrix2,exp,n,counter,i,e,decomp;
# exclude trivial case
if conPcs.rels=[] then
return [];
fi;
matrix2 := matrix^conPcs.conjugator;
if not POL_UpperTriangIntTest( [matrix2] ) then
return fail;
fi;
decomp := DecomposeUpperUnitriMat( conPcs.level, matrix2 );
if IsBool( decomp ) then return fail; fi;
n := Length( conPcs.gens );
exp := [];
counter := 1;
for i in [1..n] do
if IsBound( decomp[counter] ) then
e := decomp[counter];
if conPcs.gens[i] = e[1] then
Add( exp, e[2] );
counter := counter + 1;
else
Add( exp, 0 );
fi;
else
Add( exp, 0 );
fi;
od;
Assert( 1, matrix = Exp2Groupelement( conPcs.pcs, exp ),
"Failure in ExponentOfCPCS_Unipotent \n" );
return exp;
end;
#############################################################################
##
## Test functions
#############################################################################
##
#F POL_TestCPCS_Unipotent( gens )
##
##
POL_TestCPCS_Unipotent :=
function( gens )
local con, i, g, exp;
con := CPCS_Unipotent( gens );
Print( "START TESTING !!!\n" );
SetAssertionLevel( 1 );
for i in [1..10] do
g := POL_RandomGroupElement( gens );
Print( g );
exp := ExponentOfCPCS_Unipotent( g, con );
Print( i );
od;
# SetAssertionLevel( 0 );
end;
#############################################################################
##
#F POL_TestCPCS_Unipotent2( dim, numberGens_U_p )
##
##
POL_TestCPCS_Unipotent2 :=
function( dim, numberGens_U_p )
local g2,exp,G,k,i,j,d,mats,h2,g,matrix,U,U2,h,v,gens2,gens_U_p,
gens,con, numberOfTests;
g := [];
matrix := [];
d := dim;
k := numberGens_U_p;
numberOfTests := 10;
# construct some unipotent rational matrix groups
G := POL_UnitriangularPcpGroup( dim,0 );
mats := G!.mats;
for i in [1..k] do
g[i] := Random( G );
od;
for i in [1..k] do
matrix[i] := MappedVector( Exponents( g[i] ),mats );
od;
Print( "matrix ist gleich ",matrix,"\n" );
U := Group( matrix );
# we need a random element of GL( n,Q )
h := RandomInvertibleMat( dim,Rationals );
Print( "h ist gleich ",h,"\n" );
U2 := U^h;
gens_U_p := GeneratorsOfGroup( U2 );
# gens_U_p := GeneratorsOfGroup( U );
Print( "gens_U_p ist gleich ", gens_U_p,"\n" );
con := CPCS_Unipotent( gens_U_p );
Print( "START TESTING !!!\n" );
SetAssertionLevel( 1 );
for i in [1..numberOfTests] do
g := POL_RandomGroupElement( gens_U_p );
Print( g );
exp := ExponentOfCPCS_Unipotent( g,con );
Print( i );
od;
# SetAssertionLevel( 0 );
end;
#############################################################################
##
#F POL_TestFlag( flag,gens )
##
POL_TestFlag := function( flag,gens )
local i,V,v,g, test;
test := true;
for i in [1..( Length( flag ) )] do
V := VectorSpace( Rationals,flag{[1..i]} );
for g in gens do
v := flag[i]*g;
#Print( "flag[i] ist gleich ",flag[i],"\n" );
#Print( "v ist gleich ",v,"\n" );
if not v in V then
Print( "Flag Fehler enthalten gleich ",v in V,"\n" );
Print( "flag[",i,"] ist gleich ",flag[i],"\n" );
Print( "v ist gleich ",v,"\n\n" );
test := false;
fi;
od;
od;
return test;
end;
#############################################################################
##
##
#F POL_Test_UnipotentMats2Pcp( dim, k )
##
POL_Test_UnipotentMats2Pcp := function( dim, k )
local G,i,j,d,mats,g,matrices,U,U2,h,v,gens2,gens3;
SetAssertionLevel( 2 );
g := [];
matrices := [];
d := dim;
# construct some unipotent rational matrix groups
G := POL_UnitriangularPcpGroup( dim,0 );
mats := G!.mats;
for i in [1..k] do
g[i] := Random( G );
od;
for i in [1..k] do
matrices[i] := MappedVector( Exponents( g[i] ),mats );;
od;
Print( "used matrices are ",matrices,"\n" );
U := Group( matrices );
# random element of GL( n,Q )
h := RandomInvertibleMat( dim,Rationals );
Print( "h is ",h,"\n" );
U2 := U^h;
gens2 := GeneratorsOfGroup( U2 );
gens3 := POL_UnipotentMats2Pcp( gens2 );
if gens3 = fail then return fail; fi;
SetAssertionLevel( 0 );
return gens3;
end;
#############################################################################
##
#E
[ Dauer der Verarbeitung: 0.30 Sekunden
(vorverarbeitet)
]
|