From 497b0711ec3a100d65d96e61ece58a869bfa409c Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Wed, 31 Mar 2021 20:36:27 +0200 Subject: [PATCH] added an `\in` method for `GO` and `SO` ... that is based on the stored invariant quadratic form, and extended the related tests --- lib/grpmat.gi | 45 +++++++++++++++++++++++++++ tst/testinstall/grp/classic-G.tst | 34 ++++++++++++++++++++ tst/testinstall/grp/classic-forms.tst | 10 +++--- 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/lib/grpmat.gi b/lib/grpmat.gi index 6ae2e29f4b..8d26b6ca8a 100644 --- a/lib/grpmat.gi +++ b/lib/grpmat.gi @@ -789,10 +789,55 @@ InstallMethod(IsSubgroupSL,"determinant test for generators", [IsMatrixGroup and HasGeneratorsOfGroup], G -> ForAll(GeneratorsOfGroup(G),i->IsOne(DeterminantMat(i))) ); + +############################################################################# +## +#M RespectsQuadraticForm( , ) . . . . . . . . . . is form invariant? +## +## Let be the matrix of a quadratic form, and let be a matrix of the +## same dimensions. +## The value of the form at the vector $v$ is $v v^{tr}$. +## If we define the matrix $i'$ by +## $'[i,i] = [i,i]$, +## $'[i,j] = 0$ for $i > j$, +## $'[i,j] = [i,j] + [j,i]$ for $i < j$, +## then $v v^{tr} = v ' v^{tr}$ holds for all $v$. +## By definition, leaves the form invariant +## if $v ^{tr} v^{tr} = v v^{tr}$ holds for all $v$. +## This happens if and only if $( ^{tr})' = '$ holds. +## (For the "only if" part, +## take the $i$-th standard basis vector $e_i$ to check the equality +## of the $i$-th diagonal element, +## and take $e_i + e_j$ to check the equality of the entry in position +## $(i,j)$.) +## +BindGlobal( "RespectsQuadraticForm", function( Q, M ) + local Qimg; + + Qimg:= M * Q * TransposedMat( M ); + return ForAll( [ 1 .. NumberRows( M ) ], + i -> Q[i,i] = Qimg[i,i] and + ForAll( [ 1 .. i-1 ], + j -> Q[i,j] + Q[j,i] = Qimg[i,j] + Qimg[j,i] ) ); + end ); + + ############################################################################# ## #M in . . . . . . . . . . . . . . . . . . . . is form invariant? ## +InstallMethod( \in, "respecting quadratic form", IsElmsColls, + [ IsMatrix, IsFullSubgroupGLorSLRespectingQuadraticForm ], + NICE_FLAGS, # this method is better than the one using a nice monom.; + # it has the same rank as the method based on the inv. + # bilinear form, which is cheaper to check, + # thus we install the current method first + function( mat, G ) + return IsSubset( FieldOfMatrixGroup( G ), FieldOfMatrixList( [ mat ] ) ) + and ( not IsSubgroupSL( G ) or IsOne( DeterminantMat( mat ) ) ) + and RespectsQuadraticForm( InvariantQuadraticForm( G ).matrix, mat ); + end ); + InstallMethod( \in, "respecting bilinear form", IsElmsColls, [ IsMatrix, IsFullSubgroupGLorSLRespectingBilinearForm ], NICE_FLAGS, # this method is better than the one using a nice monom. diff --git a/tst/testinstall/grp/classic-G.tst b/tst/testinstall/grp/classic-G.tst index dfc60c10e1..83c234044f 100644 --- a/tst/testinstall/grp/classic-G.tst +++ b/tst/testinstall/grp/classic-G.tst @@ -1,6 +1,8 @@ # # Tests for the "general" group constructors: GL, GO, GU, GammaL # +#@local G, H, d, q, S, grps + gap> START_TEST("classic-G.tst"); # @@ -187,5 +189,37 @@ Error, no 1st choice method found for `OmegaCons' on 4 arguments gap> Omega(2,2); Error, sign = 0 but dimension is even +# Membership tests in GL, SL, GO, SO, GU, SU, Sp can be delegated +# to the tests of the stored respected forms and therefore are cheap. +gap> for d in [ 1 .. 10 ] do +> for q in Filtered( [ 2 .. 30 ], IsPrimePowerInt ) do +> G:= GL(d,q); +> S:= SL(d,q); +> if Size( G ) <> Size( S ) and +> ForAll( GeneratorsOfGroup( G ), g -> g in S ) then +> Error( "wrong membership test" ); +> fi; +> grps:= []; +> if Length( Factors( q ) ) mod 2 = 0 then +> Append( grps, [ GU(d, RootInt( q )), SU(d, RootInt( q )) ] ); +> fi; +> if d mod 2 = 0 then +> Append( grps, [ GO(-1,d,q), GO(1,d,q) ] ); +> Add( grps, Sp(d,q) ); +> else +> Add( grps, GO(d,q) ); +> fi; +> if ForAny( grps, +> U -> ( Size( U ) < Size( G ) and +> ForAll( GeneratorsOfGroup( G ), g -> g in U ) ) or +> ( Size( U ) < Size( S ) and +> ForAll( GeneratorsOfGroup( S ), g -> g in U ) ) or +> ForAny( [ 1 .. 20 ], +> i -> not PseudoRandom( U ) in U ) ) then +> Error( "wrong membership test" ); +> fi; +> od; +> od; + # gap> STOP_TEST("classic-G.tst", 1); diff --git a/tst/testinstall/grp/classic-forms.tst b/tst/testinstall/grp/classic-forms.tst index 639b41cc86..862cc162a3 100644 --- a/tst/testinstall/grp/classic-forms.tst +++ b/tst/testinstall/grp/classic-forms.tst @@ -21,14 +21,12 @@ gap> CheckBilinearForm := function(G) > g -> g*M*TransposedMat(g) = M); > end;; gap> CheckQuadraticForm := function(G) -> local M, Q, V, vecs; +> local M, Q; > M := InvariantBilinearForm(G).matrix; > Q := InvariantQuadraticForm(G).matrix; -> V := FieldOfMatrixGroup(G)^DegreeOfMatrixGroup(G); -> vecs:=List([1..100], i->Random(V)); -> return (Q+TransposedMat(Q) = M) and ForAll(vecs, -> v->ForAll(GeneratorsOfGroup(G), -> g -> v*Q*v = (v*g)*Q*(v*g))); +> return (Q+TransposedMat(Q) = M) and +> ForAll(GeneratorsOfGroup(G), +> g -> RespectsQuadraticForm(Q, g)); > end;; gap> frob := function(g,aut) > return List(g,row->List(row,x->x^aut));