Skip to content

Commit

Permalink
IsMatrixObj interface for GAP's matrix groups
Browse files Browse the repository at this point in the history
GAP's default mechanism for dealing with small matrix groups
is to compute an isomorphic permutation group
via the action on orbits of vectors.

With these changes,
this mechanism works for groups of objects in `IsMatrixObj`
that are not plain lists of lists.
Of course this is just one step, more changes in this area will follow.
(A preliminary test case is contained in the `GAPJulia` package.)

Some changes are hopefully not controversial,
such as replacing `Length` calls by calls of `NumberRows`,
and replacing matrix entry access `m[i][j]` by `m[i,j]`.

For other changes, there would be alternatives.

- Instead of introducing a new attribute `RowsOfMatrix`,
  one could declare `ListOp( <matobj> )` for `<matobj>` in `IsMatrixObj`
  (and not only for `<matobj>` in `IsRowListMatrix`).
  From the viewpoint that the use of `ListOp` for `IsMatrixObj` matrices
  is not recommended, according to `lib/matobj2.gd`,
  I prefer `RowsOfMatrix`.

- In `DefaultScalarDomainOfMatrixList`, one could argue that also
  lists of `IsMatrixObj` objects with different `BaseDomain`
  can make sense, but I think that showing an error message is more
  in the spirit of `IsMatrixObj`.
  • Loading branch information
ThomasBreuer authored and fingolfin committed Dec 6, 2018
1 parent 8a9aa64 commit 554cde7
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 49 deletions.
47 changes: 27 additions & 20 deletions lib/grpmat.gi
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function( grp )
local gens,R;
gens:= GeneratorsOfGroup( grp );
if IsEmpty( gens ) then
return Field( One( grp )[1][1] );
return Field( One( grp )[1,1] );
else
R:=DefaultScalarDomainOfMatrixList(gens);
if not IsField(R) then
Expand Down Expand Up @@ -70,7 +70,7 @@ InstallMethod( FieldOfMatrixGroup,

gens:= GeneratorsOfGroup( grp );
if IsEmpty( gens ) then
return Field( One( grp )[1][1] );
return Field( One( grp )[1,1] );
else
return FieldOfMatrixList(gens);
fi;
Expand All @@ -85,15 +85,15 @@ InstallMethod( DimensionOfMatrixGroup, "from generators",
[ IsMatrixGroup and HasGeneratorsOfGroup ],
function( grp )
if not IsEmpty( GeneratorsOfGroup( grp ) ) then
return Length( GeneratorsOfGroup( grp )[ 1 ] );
return NumberRows( GeneratorsOfGroup( grp )[1] );
else
TryNextMethod();
fi;
end );

InstallMethod( DimensionOfMatrixGroup, "from one",
[ IsMatrixGroup and HasOne ], 1,
grp -> Length( One( grp ) ) );
grp -> NumberRows( One( grp ) ) );

# InstallOtherMethod( DimensionOfMatrixGroup,
# "from source of nice monomorphism",
Expand Down Expand Up @@ -225,13 +225,13 @@ local field, dict, acts, start, j, zerov, zero, dim, base, partbas, heads,
i, lo, imgs, xset, hom, R;

field:=DefaultFieldOfMatrixGroup(G);
#dict := NewDictionary( One(G)[1], true , field ^ Length( One( G ) ) );
acts:=GeneratorsOfGroup(G);

if Length(acts)=0 then
start:=One(G);
start:= RowsOfMatrix( One( G) );
elif act=OnRight then
start:=Concatenation(BasisVectorsForMatrixAction(G),One(G));
start:= Concatenation( BasisVectorsForMatrixAction( G ),
RowsOfMatrix( One( G ) ) );
elif act=OnLines then
j:=One(G);
start:=Concatenation(List(BasisVectorsForMatrixAction(G),
Expand Down Expand Up @@ -286,7 +286,7 @@ local field, dict, acts, start, j, zerov, zero, dim, base, partbas, heads,
fi;

if not IsZero(v) then
dict := NewDictionary( v, true , field ^ Length( One( G ) ) );
dict := NewDictionary( v, true , field ^ NumberRows( One( G ) ) );
# force `img' over field
if (Size(field)=2 and not IsGF2VectorRep(img)) or
(Size(field)>2 and Size(field)<=256 and not (Is8BitVectorRep(img)
Expand Down Expand Up @@ -464,10 +464,12 @@ local nice,img,module,b;
Info(InfoGroup,1,"over nonfield");
#nice:=ActionHomomorphism( grp,AsSSortedList(grp),OnRight,"surjective");
if canon then
nice:=SortedSparseActionHomomorphism( grp, One( grp ) );
nice:= SortedSparseActionHomomorphism( grp,
RowsOfMatrix( One( grp ) ) );
SetIsCanonicalNiceMonomorphism(nice,true);
else
nice:=SparseActionHomomorphism( grp, One( grp ) );
nice:= SparseActionHomomorphism( grp,
RowsOfMatrix( One( grp ) ) );
nice:=nice*SmallerDegreePermutationRepresentation(Image(nice));
fi;
elif IsFinite(grp) and ( (HasIsNaturalGL(grp) and IsNaturalGL(grp)) or
Expand All @@ -477,7 +479,8 @@ local nice,img,module,b;
return NicomorphismFFMatGroupOnFullSpace(grp);
elif canon then
Info(InfoGroup,1,"canonical niceo");
nice:=SortedSparseActionHomomorphism( grp, One( grp ) );
nice:= SortedSparseActionHomomorphism( grp,
RowsOfMatrix( One( grp ) ) );
SetIsCanonicalNiceMonomorphism(nice,true);
else
Info(InfoGroup,1,"act to find base");
Expand All @@ -495,7 +498,7 @@ local nice,img,module,b;
# try hard, unless absirr and orbit lengths at least 1/q^2 of domain --
#then we expect improvements to be of little help
if module<>fail and not (NrMovedPoints(img)>=
Size(DefaultFieldOfMatrixGroup(grp))^(Length(One(grp))-2)
Size( DefaultFieldOfMatrixGroup( grp ) )^( NumberRows( One( grp ) )-2 )
and MTX.IsAbsolutelyIrreducible(module)) then
nice:=nice*SmallerDegreePermutationRepresentation(img);
else
Expand Down Expand Up @@ -665,8 +668,8 @@ InstallMethod( ViewObj,
function(G)
local gens;
gens:=GeneratorsOfGroup(G);
if Length(gens)>0 and Length(gens)*
Length(gens[1])^2 / GAPInfo.ViewLength > 8 then
if Length(gens)>0 and
Length(gens) * DimensionOfMatrixGroup(G)^2 / GAPInfo.ViewLength > 8 then
Print("<matrix group");
if HasSize(G) then
Print(" of size ",Size(G));
Expand Down Expand Up @@ -784,11 +787,15 @@ InstallMethod( IsGeneratorsOfMagmaWithInverses,
"for a list of matrices",
[ IsRingElementCollCollColl ],
function( matlist )
local dims;
if ForAll( matlist, IsMatrix ) then
dims:= DimensionsMat( matlist[1] );
return dims[1] = dims[2] and
ForAll( matlist, mat -> DimensionsMat( mat ) = dims ) and
local nrows, ncols;

if IsList( matlist ) and ForAll( matlist, IsMatrixObj ) then
nrows:= NumberRows( matlist[1] );
ncols:= NumberColumns( matlist[1] );
return nrows = ncols and
ForAll( matlist,
mat -> NumberRows( mat ) = nrows and
NumberColumns( mat ) = ncols ) and
ForAll( matlist, mat -> Inverse( mat ) <> fail );
fi;
return false;
Expand Down Expand Up @@ -1020,7 +1027,7 @@ InstallMethod( PreImagesRepresentative,

B:= Basis( iso );
d:= Length( B );
n:= Length( mat ) / d;
n:= NumberRows( mat ) / d;

if not IsInt( n ) then
return fail;
Expand Down
21 changes: 21 additions & 0 deletions lib/matobj.gi
Original file line number Diff line number Diff line change
Expand Up @@ -631,9 +631,30 @@ and an int",
od;
end );


############################################################################
##
#M \^( <vecobj>, <matobj> )
##
InstallMethod( \^,
[ IsVectorObj, IsMatrixObj ],
\* );


#
# Compatibility code: Install MatrixObj methods for IsMatrix.
#


############################################################################
##
#M RowsOfMatrix( <matobj> )
##
InstallMethod( RowsOfMatrix,
[ IsMatrix ],
Immutable );


InstallOtherMethod( NumberRows, "for a plist matrix",
[ IsMatrix ], Length);
InstallOtherMethod( NumberColumns, "for a plist matrix",
Expand Down
44 changes: 40 additions & 4 deletions lib/matobj2.gd
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,26 @@ DeclareOperation( "Unpack", [IsRowListMatrix] );
# TODO: this is already used by the fining package


############################################################################
##
#A RowsOfMatrix( <matrixobj> )
##
## Called with an object in <Ref Cat="IsMatrixObj"/>, this function
## returns a plain list of objects in <Ref Cat="IsVectorObj"/>,
## where the <M>i</M>-th entry describes the <M>i</M>-th row of the input.
##
## This function is used for creating an isomorphic permutation group
## of a matrix group that consists of matrix objects.
## <!-- If 'NicomorphismOfGeneralMatrixGroup' would be documented then
## one could insert a reference to it. -->
##
## We assume that the matrix knows how to create suitable vector objects;
## entering a template vector as the second argument is not an option
## in this situation.
##
DeclareAttribute( "RowsOfMatrix", IsMatrixObj );


############################################################################
############################################################################
# Operations for RowList-matrices:
Expand Down Expand Up @@ -1226,11 +1246,27 @@ DeclareOperation( "ListOp", [IsRowListMatrix, IsFunction] );
# DeclareOperation( "*", [IsVectorObj, IsMatrixObj] );
# DeclareOperation( "*", [IsMatrixObj, IsVectorObj] );

# TODO: the following does the same as "*", but is useful
# as convenience for Orbit-ish operations.
# We otherwise discourage its use in "naked" code -- use * instead
# DeclareOperation( "^", [IsVectorObj, IsMatrixObj] );

############################################################################
##
#O \^( <vecobj>, <matobj> )
##
## One of &GAP;'s strategies to study (small) matrix groups is
## to compute a faithful permutation representations of the action on
## orbits of row vectors, via right multiplication,
## see <Ref Sect="Nice Monomorphisms"/>.
## The code in question uses <Ref Func="OnPoints"/> as the default action,
## which means that the operation <C>\\\^</C> gets called.
## Therefore, we declare this operation for the case that the two arguments
## are in <Ref Cat="IsVectorObj"/> and <Ref Cat="IsMatrixObj"/>,
## and install the multiplication as a method for this situation;
## thus one need not install individual <C>\\\^</C> methods
## in special cases.
## <P/>
## For other code dealing with the multiplication of vectors and matrices,
## it is recommended to use the multiplication <C>\\\*</C> directly.
##
DeclareOperation( "^", [ IsVectorObj, IsMatrixObj ] );


############################################################################
Expand Down
57 changes: 33 additions & 24 deletions lib/matrix.gi
Original file line number Diff line number Diff line change
Expand Up @@ -4031,31 +4031,40 @@ end);
##
#M DefaultScalarDomainOfMatrixList
##
InstallMethod(DefaultScalarDomainOfMatrixList, "generic: form ring",
[IsListOrCollection],
function(l)
local i,j,k,fg,f;
# try to find out the field
if Length(l)=0 or ForAny(l,i->not IsMatrix(i)) then
Error("<l> must be a list of matrices");
fi;
fg:=[l[1][1,1]];
if Characteristic(fg)=0 then
f:=DefaultField(fg);
else
f:=DefaultRing(fg);
fi;
for i in l do
for j in i do
for k in j do
if not k in f then
Add(fg,k);
f:=DefaultRing(fg);
fi;
InstallMethod( DefaultScalarDomainOfMatrixList,
"generic: form ring",
[ IsList ],
function(l)
local B, i,j,k,fg,f;
# try to find out the field
if Length( l ) = 0 or ForAny( l, i -> not IsMatrixObj( i ) ) then
Error( "<l> must be a nonempty list of matrices" );
elif ForAll( l, HasBaseDomain ) then
B:= BaseDomain( l[1] );
if ForAll( l, x -> B = BaseDomain( x ) ) then
return B;
fi;
elif ForAll( l, IsMatrix ) then
fg:=[l[1][1,1]];
if Characteristic(fg)=0 then
f:=DefaultField(fg);
else
f:=DefaultRing(fg);
fi;
for i in l do
for j in i do
for k in j do
if not k in f then
Add(fg,k);
f:=DefaultRing(fg);
fi;
od;
od;
od;
od;
od;
return f;
return f;
fi;
Error( "all entries in <l> must either be lists of lists ",
"or have the same BaseDomain" );
end);


Expand Down
2 changes: 1 addition & 1 deletion lib/zmodnz.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ InstallMethod( DefaultRingByGenerators,
InstallMethod( DefaultFieldOfMatrixGroup,
"for a matrix group over a ring Z/nZ",
[ IsMatrixGroup and IsZmodnZObjNonprimeCollCollColl ],
G -> ZmodnZ( Characteristic( Representative( G )[1][1] ) ) );
G -> ZmodnZ( Characteristic( Representative( G )[1,1] ) ) );


#############################################################################
Expand Down

0 comments on commit 554cde7

Please sign in to comment.