diff --git a/CHANGES.md b/CHANGES.md
index be458a3..fa35d02 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -6,6 +6,7 @@ This file describes changes in the GAP package 'polycyclic'.
in the following functions:
- `AbelianPcpGroup`
- `AddToIgs` (and variants)
+ - `AffineRepresentation`
- `CentralizerBySeries`
- `CgsParallel`
- `CoefficientsByFactorLattice`
@@ -45,6 +46,7 @@ This file describes changes in the GAP package 'polycyclic'.
- Implement a method for `RepresentativeAction`
- Add `IsomorphismPcpGroupByIgs` and its `NC` variant to construct an isomorphic
pcp-group whose pcp corresponds to the given igs
+- Support explicit generators in `IsMatrixRepresentation`
- Allow a finite group fallback for `RepresentativeAction` and `IsConjugate` for
subgroups
- Optimise `NormalIntersection` and `EfaSeries`
diff --git a/doc/matreps.xml b/doc/matreps.xml
index d369f82..2549e30 100644
--- a/doc/matreps.xml
+++ b/doc/matreps.xml
@@ -19,10 +19,13 @@ nilpotent groups.
-
+
- checks if the map defined by mapping the i-th generator of the
- pcp-group G to the i-th matrix of matrices defines a homomorphism.
+ checks if the map defined by mapping the i-th generator of
+ gens to the i-th matrix of matrices defines a
+ homomorphism from the pcp-group G.
+ If omitted, gens defaults to GeneratorsOfGroup(G). If
+ provided, it must generate G.
diff --git a/gap/matrep/affine.gi b/gap/matrep/affine.gi
index 03fc615..7f59b6b 100644
--- a/gap/matrep/affine.gi
+++ b/gap/matrep/affine.gi
@@ -20,8 +20,9 @@ end );
NextStepRepresentation := function( G, i, mats )
local pcp, N, hom, F, C, cc, rc, co, j, coc, news, d, z;
- Print("starting level ",i,"\n");
pcp := Pcp(G);
+ if i > Length(pcp) then return mats; fi;
+ Print("starting level ",i,"\n");
N := SubgroupByIgs( G, pcp{[i+1..Length(pcp)]} );
hom := NaturalHomomorphismByNormalSubgroupNC( G, N );
F := ImagesSource( hom );
@@ -46,7 +47,7 @@ NextStepRepresentation := function( G, i, mats )
coc := co + cc.factor.prei[j];
fi;
news := ExtendAffine( mats, coc );
- if not IsMatrixRepresentation( F, news ) then
+ if not IsMatrixRepresentation( F, GeneratorsOfPcp(Pcp(F)), news ) then
Error("no mat rep");
fi;
news := NextStepRepresentation( G, i+1, news );
@@ -58,10 +59,11 @@ MakeReadOnlyGlobal( "NextStepRepresentation" );
BindGlobal( "AffineRepresentation", function( G )
local mats, news;
+ if IsTrivial(G) then return []; fi;
mats := [[[1,0],[1,1]]];
news := NextStepRepresentation( G, 2, mats );
if IsBool( news ) then return fail; fi;
- if not IsMatrixRepresentation( G, news ) then
+ if not IsMatrixRepresentation( G, GeneratorsOfPcp(Pcp(G)), news ) then
Error("no representation ");
fi;
return news;
diff --git a/gap/matrep/matrep.gi b/gap/matrep/matrep.gi
index 03a6b48..2789b1b 100644
--- a/gap/matrep/matrep.gi
+++ b/gap/matrep/matrep.gi
@@ -4,10 +4,24 @@
##
InstallGlobalFunction( "IsMatrixRepresentation",
-function( G, matrices )
- local coll, conjugates, powers, d, I, i, j, conj, rhs, k;
+function( arg )
+ local G, gens, matrices, coll, conjugates, powers, d, I, i, j, conj, rhs,
+ k;
+
+ G := arg[1];
+ matrices := arg[Length(arg)];
+ if Length(arg) = 2 then
+ gens := GeneratorsOfGroup(G);
+ else
+ gens := arg[2];
+ fi;
+ if IsEmpty(gens) then return IsTrivial(G); fi;
coll := Collector( G );
+ if gens <> GeneratorsOfGroup(PcpGroupByCollectorNC(coll)) then
+ return IsSingleValued(GroupGeneralMappingByImagesNC(
+ G, Group(matrices), gens, matrices));
+ fi;
conjugates := coll![PC_CONJUGATES];
powers := coll![PC_POWERS];
@@ -58,7 +72,7 @@ function( hom )
View( mapi[1] );
Print( " -> " );
- d := Length(mapi[2][1]);
+ d := DimensionOfMatrixGroup( Range(hom) );
Print( "<", Length(mapi[2]), " ", d, "x", d, "-matrices>" );
return;
end );
@@ -662,20 +676,25 @@ function( tgroup )
fi;
pcp := Pcp( tgroup );
- if ForAny( RelativeOrdersOfPcp( pcp ), r -> r <> 0 ) then
- pgroup := PcpGroupBySeries(UpperCentralSeriesOfGroup(tgroup), "snf");
- coll := Collector( pgroup );
- gens := List(
- GeneratorsOfPcp( Pcp( pgroup ) ),
- g -> ImagesRepresentative( pgroup!.bijection, g )
- );
+ if Length(pcp) = 0 then
+ gens := [];
+ mats := [];
+ mgroup := Group( [], IdentityMat(1) );
else
- coll := Collector( PcpGroupByPcp(pcp) );
- gens := GeneratorsOfPcp( pcp );
+ if ForAny( RelativeOrdersOfPcp( pcp ), r -> r <> 0 ) then
+ pgroup := PcpGroupBySeries(UpperCentralSeriesOfGroup(tgroup), "snf");
+ coll := Collector( pgroup );
+ gens := List(
+ GeneratorsOfPcp( Pcp( pgroup ) ),
+ g -> ImagesRepresentative( pgroup!.bijection, g )
+ );
+ else
+ coll := Collector( PcpGroupByPcp(pcp) );
+ gens := GeneratorsOfPcp( pcp );
+ fi;
+ mats := LowerUnitriangularForm( RepresentationForPcpCollector( coll ) );
+ mgroup := Group( mats, mats[1]^0 );
fi;
- mats := LowerUnitriangularForm( RepresentationForPcpCollector( coll ) );
-
- mgroup := Group( mats, mats[1]^0 );
UseIsomorphismRelation( tgroup, mgroup );
phi := GroupHomomorphismByImagesNC( tgroup, mgroup, gens, mats );
diff --git a/tst/bugfix/gh-00249.tst b/tst/bugfix/gh-00249.tst
index 9e3e042..0c291a1 100644
--- a/tst/bugfix/gh-00249.tst
+++ b/tst/bugfix/gh-00249.tst
@@ -1,15 +1,22 @@
gap> START_TEST( "gh-00249.tst" );
#
-# Fix UnitriangularMatrixRepresentation for pcp subgroups
+# Fix matrix representation functions
#
#
gap> G := UnitriangularPcpGroup( 3, 0 );;
gap> H := Subgroup( G, [ G.1^2, G.2, G.3 ] );;
gap> IsNilpotentGroup( H );;
gap> phi := UnitriangularMatrixRepresentation( H );;
+gap> IsBijective( phi ) and IsGroupHomomorphism( phi );
+true
gap> Comm( H.1, H.2 )^phi = Comm( H.1^phi, H.2^phi );
true
+gap> gensimgs := MappingGeneratorsImages( phi );;
+gap> IsMatrixRepresentation( H, gensimgs[ 2 ] );
+true
+gap> IsMatrixRepresentation( H, [ G.1, G.2, G.3 ], gensimgs[ 2 ] );
+false
#
gap> G := AbelianPcpGroup( [ 2, 0 ] );;
@@ -31,5 +38,20 @@ gap> phi := UnitriangularMatrixRepresentation( H );;
gap> Image( phi, H.1 ) ^ 2 = Image( phi, H.1 ^ 2 );
true
+#
+gap> A := UnitriangularPcpGroup( 3, 0 );;
+gap> G := Group( [ A.3, A.1, A.2 ] );;
+gap> IsNilpotentGroup( G ) and IsTorsionFree( G ) and G = PcpGroupByCollector( Collector(G) );
+true
+gap> x := [ [ 1, 0, 0 ],[ 1, 1, 0 ],[ 0, 0, 1 ] ];;
+gap> y := [ [ 1, 0, 0 ],[ 0, 1, 0 ],[ 0, 1, 1 ] ];;
+gap> z := Comm( x, y );;
+gap> IsMatrixRepresentation( G, [ x, y, z ] );
+false
+gap> IsMatrixRepresentation( G, [ z, x, y ] );
+true
+gap> IsMatrixRepresentation( G, [ G.2, G.3, G.1 ], [ x, y, z ] );
+true
+
#
gap> STOP_TEST( "gh-00249.tst" );
diff --git a/tst/bugfix/gh-00256.tst b/tst/bugfix/gh-00256.tst
new file mode 100644
index 0000000..fa62f24
--- /dev/null
+++ b/tst/bugfix/gh-00256.tst
@@ -0,0 +1,32 @@
+gap> START_TEST( "gh-00256.tst" );
+
+#
+# Fix matrix representation functions for trivial input
+#
+#
+gap> G := AbelianPcpGroup( [] );;
+gap> IsMatrixRepresentation( G, [] );
+true
+gap> IsMatrixRepresentation( G, [], [] );
+true
+gap> UnitriangularMatrixRepresentation( G );
+[ ] -> <0 1x1-matrices>
+gap> H := Subgroup( G, [ One( G ) ] );;
+gap> IsMatrixRepresentation( H, [ IdentityMat( 1 ) ] );
+true
+gap> IsMatrixRepresentation( H, [ One( H ) ], [ IdentityMat( 1 ) ] );
+true
+gap> rep := UnitriangularMatrixRepresentation( H );
+[ ] -> <0 1x1-matrices>
+gap> MappingGeneratorsImages( rep );
+[ [ ], [ ] ]
+gap> Image( rep, H.1 );
+[ [ 1 ] ]
+gap> K := Image( rep );;
+gap> IsFinite( K );
+true
+gap> List( GeneratorsOfGroup( K ), Order );
+[ ]
+
+#
+gap> STOP_TEST( "gh-00256.tst" );