Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/ref/matrix.xml
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,9 @@ see&nbsp;<Ref Sect="Mutability and Copyability"/>.
<Heading>Random Matrices</Heading>

<#Include Label="RandomMat">
<#Include Label="RandomMatrix">
<#Include Label="RandomInvertibleMat">
<#Include Label="RandomInvertibleMatrix">
<#Include Label="RandomUnimodularMat">

</Section>
Expand Down
2 changes: 1 addition & 1 deletion grp/classic.gd
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ BindGlobal( "SymplecticGroup", function ( arg )
rep:= filt;
filt:= IsMatrixGroup;
else
rep:= fail;
rep:= ValueOption( "ConstructingFilter" );
fi;
if DescribesInvariantBilinearForm( Last( arg ) ) then
form:= Remove( arg );
Expand Down
154 changes: 125 additions & 29 deletions lib/grpffmat.gi
Original file line number Diff line number Diff line change
Expand Up @@ -124,46 +124,95 @@ end );

#############################################################################
##
#M NiceMonomorphism( <ffe-mat-grp> )
## the natural G-set of a matrix group consists of the vectors of the
## natural module
##
InstallOtherMethod( ExternalSet,
[ IsFFEMatrixGroup and IsFinite ],
function( G )
local basis, zero;

basis:= RowsOfMatrix( One( G ) );
zero:= Zero( basis[1] );
return ExternalSet( G, AsListOfFreeLeftModule_internal(
FieldOfMatrixGroup( G ), basis, zero ) );
end );

#############################################################################
##
#V FULLGLNICOCACHE
##
## 'NicomorphismFFMatGroupOnFullSpace' uses a cache of length up to 5,
## as follows.
##
## - If the argument is a matrix group that fits to an entry of this
## cache, in the sense that dimension, field of definition,
## and 'ConstructingFilter' of the matrices in the group are the same as
## for the cached value, the stored mapping is returned.
## - If a new mapping has to be constructed, the first cached entry is
## dropped and the new mapping gets added to the cache.
##
MakeThreadLocal("FULLGLNICOCACHE"); # avoid recreating same homom. repeatedly
FULLGLNICOCACHE:=[];
InstallGlobalFunction( NicomorphismFFMatGroupOnFullSpace, function( grp )
local field, dim, V, xset, nice;
BindGlobal( "FULLGLNICOCACHE", [] );

field := FieldOfMatrixGroup( grp );
dim := DimensionOfMatrixGroup( grp );

#############################################################################
##
#M NiceMonomorphism( <ffe-mat-grp> )
##
InstallGlobalFunction( NicomorphismFFMatGroupOnFullSpace, function( grp )
local rep, filt, q, dim, field, xset, nice;

rep:= Representative( grp );
field:= FieldOfMatrixGroup( grp );
q:= Size( field );
if IsBlockMatrixRep( rep ) then
# There is no support for these matrices acting on vectors.
filt:= IsPlistRep;
elif q = 2 and Is8BitMatrixRep( rep ) then
# We cannot keep both 'field' and 'Is8BitMatrixRep',
# the latter does not admit matrices over GF(2).
filt:= IsGF2MatrixRep;
#TODO: How can we get rid of these hacks?
else
filt:= ConstructingFilter( rep );
fi;
dim:= DimensionOfMatrixGroup( grp );

#check cache
V:=Size(field);
nice:=First(FULLGLNICOCACHE,x->x[1]=V and x[2]=dim);
if nice<>fail then return nice[3];fi;
nice:= First( FULLGLNICOCACHE,
x -> x[1] = field and x[2] = dim and x[3] = filt );

if nice<>fail then return nice[4];fi;

if not (HasIsNaturalGL(grp) and IsNaturalGL(grp)) then
grp:=GL(dim,field); # enforce map on full GL
# enforce map on full GL
grp:= GL( dim, field : ConstructingFilter:= filt );
fi;
V := field ^ dim;
xset := ExternalSet( grp, V );

xset := ExternalSet( grp );

# STILL: reverse the base to get point sorting compatible with lexicographic
# vector arrangement
SetBaseOfGroup( xset, One( grp ));
if IsList( One( grp ) ) then
SetBaseOfGroup( xset, One( grp ));
else
SetBaseOfGroup( xset, RowsOfMatrix( One( grp ) ) );
fi;
nice := ActionHomomorphism( xset,"surjective" );
SetIsInjective( nice, true );
if not HasNiceMonomorphism(grp) then
SetNiceMonomorphism(grp,nice);
fi;
# because we act on the full space we are canonical.
SetIsCanonicalNiceMonomorphism(nice,true);
if Size(V)>10^5 then
if q^dim > 10^5 then
# store only one big one and have it get thrown out quickly
FULLGLNICOCACHE[1]:=[Size(field),dim,nice];
FULLGLNICOCACHE[1]:= [ field, dim, filt, nice ];
else
if Length(FULLGLNICOCACHE)>4 then
FULLGLNICOCACHE:=FULLGLNICOCACHE{[2..5]};
Remove( FULLGLNICOCACHE, 1 );
fi;
Add(FULLGLNICOCACHE,[Size(field),dim,nice]);
Add( FULLGLNICOCACHE, [ field, dim, filt, nice ] );
fi;

return nice;
Expand All @@ -190,8 +239,7 @@ local tt;
# if the permutation image would be too large, compute the orbit.
TryNextMethod();
fi;
return NicomorphismFFMatGroupOnFullSpace( GL( DimensionOfMatrixGroup( grp ),
Size( FieldOfMatrixGroup( Parent(grp) ) ) ) );
return NicomorphismFFMatGroupOnFullSpace( grp );
end );

#############################################################################
Expand Down Expand Up @@ -256,6 +304,19 @@ InstallMethod( \in, "general linear group", IsElmsColls,
and Length( mat ) = RankMat( mat );
end );

InstallMethod( \in, "general linear group", IsElmsColls,
[ IsMatrixObj, IsFFEMatrixGroup and IsFinite and IsNaturalGL ], 0,
function( mat, G )
local n, F;
n:= NumberRows( mat );
F:= FieldOfMatrixGroup( G );
return n = NumberColumns( mat )
and n = DimensionOfMatrixGroup( G )
and n = RankMat( mat )
and ( IsSubset( F, BaseDomain( mat ) ) or
ForAll( Unpack( mat ), row -> IsSubset( F, row ) ) );
Comment on lines +316 to +317
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment that explains why the "or" case is needed? I.e., because the basedomain may be larger than necessary to represent elements, and we consider explicit conversion an option...

Though... thinking about it... how would one then "coerce" mat into an actual element of G (which can e.g. be multiplied with One(G) ) ? We don't have any tooling for that in GAP so far, do we? Because we don't need to, because all matrices (over a given common base field) are expected to be always "compatible" by some magic...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The real question is what \in for a matrix (object) and a matrix group shall mean:

Can the elements of the group be represented over different base domains?
If yes then arithmetic operations in the group are more expensive, if not then we are free to define a base domain for the group, and we can define \in such that the base domain of the matrix and the group must fit.

Concerning the coercion, I thought that Matrix( filt, R, M ) is intended for that purpose:
M is the given matrix which shall be turned into "a valid group element", R is the base domain of G or of One( G ), and filt is ConstructingFilter( One( G ) ).

end );

InstallMethod( \in, "special linear group", IsElmsColls,
[ IsMatrix, IsFFEMatrixGroup and IsFinite and IsNaturalSL ], 0,
function( mat, G )
Expand All @@ -266,6 +327,19 @@ InstallMethod( \in, "special linear group", IsElmsColls,
and DeterminantMat(mat)=One(FieldOfMatrixGroup( G ));
end );

InstallMethod( \in, "special linear group", IsElmsColls,
[ IsMatrixObj, IsFFEMatrixGroup and IsFinite and IsNaturalSL ], 0,
function( mat, G )
local n, F;
n:= NumberRows( mat );
F:= FieldOfMatrixGroup( G );
return n = NumberColumns( mat )
and n = DimensionOfMatrixGroup( G )
and ( IsSubset( F, BaseDomain( mat ) ) or
ForAll( Unpack( mat ), row -> IsSubset( F, row ) ) )
and DeterminantMat( mat ) = One( F );
end );


#############################################################################
##
Expand Down Expand Up @@ -508,10 +582,23 @@ InstallMethodWithRandomSource( Random,
"for a random source and natural GL",
[ IsRandomSource, IsFFEMatrixGroup and IsFinite and IsNaturalGL ],
function(rs, G)
local m;
m := RandomInvertibleMat( rs, DimensionOfMatrixGroup( G ),
FieldOfMatrixGroup( G ) );
return ImmutableMatrix(FieldOfMatrixGroup(G), m, true);
local d, F, m;

d:= DimensionOfMatrixGroup( G );
F:= FieldOfMatrixGroup( G );
m:= Representative( G );
if IsMatrix( m ) then
m:= RandomInvertibleMat( rs, d, F );
m:= ImmutableMatrix(F, m, true);
else
m:= ZeroMatrix( d, d, m );
repeat
Randomize( rs, m );
until RankMat( m ) = d;
MakeImmutable( m );
fi;

return m;
end);


Expand All @@ -527,11 +614,20 @@ InstallMethodWithRandomSource( Random,
"for a random source and natural SL",
[ IsRandomSource, IsFFEMatrixGroup and IsFinite and IsNaturalSL ],
function(rs, G)
local m;
m:= RandomInvertibleMat( rs, DimensionOfMatrixGroup( G ),
FieldOfMatrixGroup( G ) );
MultVector(m[1], DeterminantMat(m)^-1);
return ImmutableMatrix(FieldOfMatrixGroup(G), m, true);
local d, m;

#TODO: This code assumes that all elements in the group have the same
# 'BaseDomain' value (hence we may take any 'Representative').
# If this assumption is not valid then we have to call the
# four argument variant of 'RandomInvertibleMatrix'.
# Moreover, the code assumes that 'ImmutableMatrix' is not needed
# in the situation that the result is in 'IsMatrix'.
d:= DimensionOfMatrixGroup( G );
m:= RandomInvertibleMatrix( rs, d, Representative( G ) );
MultMatrixRow( m, 1, DeterminantMatrix( m )^-1 );
MakeImmutable( m );

return m;
end);

#############################################################################
Expand Down
8 changes: 7 additions & 1 deletion lib/matobjplist.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,13 @@ InstallMethod( InverseSameMutability,

InstallMethod( RankMat,
[ "IsPlistMatrixRep" ],
M -> RankMat( List( M![ROWSPOS], x -> x![ELSPOS] ) ) );
function( M )
M:= M![ROWSPOS];
if Length( M ) = 0 then
return 0;
fi;
return RankMat( List( M, x -> x![ELSPOS] ) );
end );

InstallMethodWithRandomSource( Randomize,
"for a random source and a mutable plist matrix",
Expand Down
Loading
Loading