From d6b6c3b77a97345fb9e74fba9410ed82f284cde6 Mon Sep 17 00:00:00 2001 From: stertooy <5571903+stertooy@users.noreply.github.com> Date: Sun, 25 Oct 2026 20:59:16 +0100 Subject: [PATCH] Fix matrix representation functions --- CHANGES.md | 2 ++ doc/matreps.xml | 9 +++++--- gap/matrep/affine.gi | 8 ++++--- gap/matrep/matrep.gi | 49 ++++++++++++++++++++++++++++------------- tst/bugfix/gh-00249.tst | 24 +++++++++++++++++++- tst/bugfix/gh-00256.tst | 32 +++++++++++++++++++++++++++ 6 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 tst/bugfix/gh-00256.tst diff --git a/CHANGES.md b/CHANGES.md index be458a3c..fa35d023 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 d369f822..2549e30e 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 03fc6158..7f59b6b1 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 03a6b488..2789b1b4 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 9e3e0423..0c291a13 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 00000000..fa62f241 --- /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" );