home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-05-05 | 53.5 KB | 1,786 lines |
- #############################################################################
- ##
- #A matgrp.g GAP library Martin Schoenert
- ##
- #A @(#)$Id: matgrp.g,v 3.13 1993/02/09 14:27:19 martin Rel $
- ##
- #Y Copyright 1990-1992, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
- ##
- ## This file contains those functions that mainly deal with matrix groups.
- ##
- #H $Log: matgrp.g,v $
- #H Revision 3.13 1993/02/09 14:27:19 martin
- #H made undefined globals local
- #H
- #H Revision 3.12 1992/12/16 19:47:27 martin
- #H replaced quoted record names with escaped ones
- #H
- #H Revision 3.11 1992/12/03 10:03:28 fceller
- #H changed 'MatGroupOps.PermGroup' to return a bijection
- #H
- #H Revision 3.10 1992/05/08 16:21:25 martin
- #H added 'MatGroupOps.RightCoset'
- #H
- #H Revision 3.9 1992/05/04 19:04:28 martin
- #H fixed 'MatGroupOps.Intersection' to assign '<X>.permDomain'
- #H
- #H Revision 3.8 1992/04/04 15:27:07 martin
- #H added many more special functions for matrix groups
- #H
- #H Revision 3.7 1992/04/03 16:45:12 martin
- #H fixed 'MatricesOps.Group' to check the arguments
- #H
- #H Revision 3.6 1992/02/29 13:25:11 jmnich
- #H general library review, some bug fixes
- #H
- #H Revision 3.5 1992/02/14 09:46:19 jmnich
- #H changed call of 'Order'
- #H
- #H Revision 3.4 1992/01/29 09:09:38 martin
- #H changed 'Order' to take two arguments, group and element
- #H
- #H Revision 3.3 1992/01/09 13:25:48 jmnich
- #H added the meataxe functions
- #H
- #H Revision 3.2 1992/01/03 15:44:57 martin
- #H changed 'Matrix' to 'Mat'
- #H
- #H Revision 3.1 1991/12/06 16:45:52 martin
- #H changed 'MatricesOps.Group' to default to 'GroupElementsOps.Group'
- #H
- #H Revision 3.0 1991/11/08 15:09:30 martin
- #H initial revision under RCS
- #H
- ##
-
-
- #############################################################################
- ##
- #F IsMatGroup(<obj>) . . . . . . . . . . test if an object is a matrix group
- ##
- IsMatGroup := function ( obj )
- return IsRec( obj )
- and IsBound( obj.isMatGroup ) and obj.isMatGroup;
- end;
-
-
- #############################################################################
- ##
- #F MatricesOps.Group(<gens>,<id>) . . . . . . . . . . create a matrix group
- ##
- MatricesOps.Group := function ( Matrices, gens, id )
- local G,
- d,
- g;
-
- # check that the generators are all of the same size and invertable
- d := Length(id);
- for g in gens do
- if Length(g) <> d or Length(g[1]) <> d or RankMat(g) <> d then
- Error("<gens> must be a list of invertable square matrices");
- fi;
- od;
-
- # make the group record
- G := GroupElementsOps.Group( Matrices, gens, id );
-
- # add the matrix group tag
- G.isMatGroup := true;
-
- # add the known information
- G.dimension := Length(id);
- G.field := Field( Flat( Concatenation( gens, [ id ] ) ) );
-
- # add the operations record
- G.operations := MatGroupOps;
-
- # return the group record
- return G;
- end;
-
-
- #############################################################################
- ##
- #V MatGroupOps . . . . . . . . . operation record for matrix group category
- ##
- ## 'MatGroupOps' is the operation record for matrix groups. It contains
- ## the domain functions, e.g., 'Size' and 'Intersection', and the group
- ## functions, e.g., 'Centralizer' and 'SylowSubgroup'.
- ##
- ## 'MatGroupOps' is initially a copy of 'GroupOps', and thus inherits the
- ## default group functions. Currently we overlay very few of those
- ## functions. We should, however, handle matrix groups over small and
- ## medium sized finite vector spaces by treating them as permutation groups
- ## over those vector spaces and using the permutation group functions.
- ##
- MatGroupOps := Copy( GroupOps );
-
-
- #############################################################################
- ##
- #F MatGroupOps.Subgroup(<G>,<gens>) . . . make a subgroup of a matrix group
- ##
- MatGroupOps.Subgroup := function ( G, gens )
- local S;
- S := GroupOps.Subgroup( G, gens );
- S.isMatGroup := true;
- S.field := G.field;
- S.operations := MatGroupOps;
- return S;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.IsFinite(<G>) . . . . . . . test if a matrix group is finite
- ##
- MatGroupOps.IsFinite := function ( G )
- if IsFinite( G.field ) then
- return true;
- else
- return GroupOps.IsFinite( G );
- fi;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.MakePermGroupP(<G>) . . . make a isomorphic permutation group
- ##
- ## The difference between this function and the usual 'PermGroup' is that
- ## the permutation group constructed for <G> will be a subgroup of the
- ## corresponding permutation group of <G>\'s parent.
- ##
- MatGroupOps.MakePermGroupP := function ( G )
- local P;
-
- # compute the isomorphic permutation group for the pareng group of <G>
- P := Parent( G );
- if not IsBound( P.permDomain ) then
- P.permDomain := Union( Orbits( P, P.identity ) );
- P.permGroupP := Operation( P, P.permDomain );
- fi;
-
- # compute the isomorphic permutation group for <G>
- if not IsBound( G.permGroupP ) then
- G.permDomain := P.permDomain;
- G.permGroupP := Subgroup( P.permGroupP,
- Operation( G, P.permDomain ).generators );
- fi;
-
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Size(<G>) . . . . . . . . . . . . . . size of a matrix group
- ##
- MatGroupOps.Size := function ( G )
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # return the size of the permutation group
- return Size( G.permGroupP );
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.\in( <obj>, <G> ) . . . . membership test for matrix groups
- ##
- MatGroupOps.\in := function ( obj, G )
- local l, # <obj> as a permutation represented by a list
- v, # vector from the operation domain of <P>
- p; # position of '<v> \^\ <obj>' in the operation domain
-
- # first a quick test
- if not IsMat( obj )
- or Length(obj) <> Length(G.identity)
- or Length(obj[1]) <> Length(G.identity[1])
- or RankMat(obj) <> Length(G.identity)
- or not IsSubset( G.field, Field( Flat(obj) ) )
- then
- return false;
- fi;
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # try to transform <obj> to a permutation
- l := [];
- for v in G.permDomain do
- p := Position( G.permDomain, v ^ obj );
- if p = false then
- return false;
- fi;
- Add( l, p );
- od;
-
- # test if the permutation is in the permutation group
- return PermList(l) in G.permGroupP;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Intersection(<G>,<H>) . . . . . intersection of matrix groups
- ##
- MatGroupOps.Intersection := function ( G, H )
- local I, # intersection of <G> and <H>, result
- P; # permutation representation of <I>
-
- # handle the intersection of two matrix groups with the same parent
- if IsMatGroup(G) and IsMatGroup(H) and Parent(G) = Parent(H) then
-
- # compute the isomorphic permutation groups for <G> and <H>
- G.operations.MakePermGroupP( G );
- H.operations.MakePermGroupP( H );
-
- # intersect the permutation groups and translate back
- P := Intersection( G.permGroupP, H.permGroupP );
- I := Subgroup( Parent( G ), List( P.generators, gen ->
- List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^gen] ) ));
- if not IsBound( I.permGroupP ) then
- I.permDomain := G.permDomain;
- I.permGroupP := P;
- fi;
-
- # delegate other cases
- else
- I := GroupOps.Intersection( G, H );
- fi;
-
- # return the intersection
- return I;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Random(<G>) . . . . . . . . random element in a matrix group
- ##
- MatGroupOps.Random := function ( G )
- local rnd; # random element of '<G>.permGroupP'
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # take a random permutation and translate it back
- rnd := Random( G.permGroupP );
- return List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^rnd] );
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Centralizer(<G>,<U>) . . . . . centralizer in a matrix group
- ##
- MatGroupOps.Centralizer := function ( G, U )
- local C, # centralizer of <U> in <G>, result
- P; # permutation group isomorphic to <C> or <U>
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # compute the isomorphic permutation or permutation group for <U>
- if IsMat(U) then
- P := Permutation( U, G.permDomain );
- else
- U.operations.MakePermGroupP( U );
- P := U.permGroupP;
- fi;
-
- # compute the centralizer in the permutation group and translate back
- P := Centralizer( G.permGroupP, P );
- C := Subgroup( Parent( G ),
- List( P.generators, gen ->
- List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^gen] ) ) );
- if not IsBound( C.permGroupP ) then
- C.permDomain := G.permDomain;
- C.permGroupP := P;
- fi;
-
- # return the centralizer
- return C;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Normalizer(<G>,<U>) . . . . . . normalizer in a matrix group
- ##
- MatGroupOps.Normalizer := function ( G, U )
- local N, # normalizer of <U> in <G>, result
- P; # permutation group isomorphic to <N> or <U>
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # compute the isomorphic permutation or permutation group for <U>
- if IsMat(U) then
- P := Permutation( U, G.permDomain );
- else
- U.operations.MakePermGroupP( U );
- P := U.permGroupP;
- fi;
-
- # compute the normalizer in the permutation group and translate back
- P := Normalizer( G.permGroupP, P );
- N := Subgroup( Parent( G ),
- List( P.generators, gen ->
- List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^gen] ) ) );
- if not IsBound( N.permGroupP ) then
- N.permDomain := G.permDomain;
- N.permGroupP := P;
- fi;
-
- # return the normalizer
- return N;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.SylowSubgroup(<G>,<p>) . . . Sylowsubgroup of a matrix group
- ##
- MatGroupOps.SylowSubgroup := function ( G, p )
- local S, # <p>-Sylow subgroup of <G>, result
- P; # permutation group isomorphic to <S>
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # compute the Sylow subgroup in the permutation group and translate back
- P := SylowSubgroup( G.permGroupP, p );
- S := Subgroup( Parent( G ),
- List( P.generators, gen ->
- List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^gen] ) ) );
- if not IsBound( S.permGroupP ) then
- S.permDomain := G.permDomain;
- S.permGroupP := P;
- fi;
-
- # return the Sylow subgroup
- return S;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.ConjugacyClasses(<G>) . . conjugacy classes of a matrix group
- ##
- MatGroupOps.ConjugacyClasses := function ( G )
- local classes, # conjugacy classes of <G>, result
- pclasses, # conjugacy classes of '<G>.permGroupP'
- class, # one conjugacy class in <pclasses>
- rep;
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # compute the conjugacy classes in the permutation group
- pclasses := ConjugacyClasses( G.permGroupP );
-
- # translate every conjugacy class back
- classes := [];
- for class in pclasses do
- rep := Representative( class );
- rep := List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^rep] );
- Add( classes, ConjugacyClass( G, rep ) );
- od;
-
- # return the classes
- return classes;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.PermGroup(<G>) . . . . convert a matrix group to a permgroup
- ##
- MatGroupOps.PermGroup := function ( G )
- local P;
-
- # construct the permutation group
- P := Operation( G, Union( Orbits( G, G.identity ) ) );
-
- # construct the bijection
- P.bijection := GroupHomomorphismByImages( P, G,
- P.operationImages,
- G.generators );
- P.bijection.isMapping := true;
- P.bijection.isGroupHomomorphism := true;
- P.bijection.isInjective := true;
- P.bijection.isMonomorphism := true;
- P.bijection.isSurjective := true;
- P.bijection.isEpimorphism := true;
- P.bijection.isBijection := true;
- P.bijection.isIsomorphism := true;
-
- # return the permutation group
- return P;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Stabilizer(<G>,<d>,<opr>) . . . stabilizer in a matrix group
- ##
- MatGroupOps.Stabilizer := function ( G, d, opr )
- local S, # stabilizer of <d> in <G>, result
- P; # permutation group isomorphic to <S>
-
- # special case to find the stabilizer of a vector
- if IsVector(d) and opr = OnPoints then
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # test whether we can handle this case
- if not d in G.permDomain then
- return GroupOps.Stabilizer( G, d, opr );
- fi;
-
- # translate the vector to a point
- d := Position( G.permDomain, d );
-
- # find the stabilizer in the permutation group and translate back
- P := Stabilizer( G.permGroupP, d );
- S := Subgroup( Parent( G ),
- List( P.generators, gen ->
- List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^gen] ) ) );
- if not IsBound( S.permGroupP ) then
- S.permDomain := G.permDomain;
- S.permGroupP := P;
- fi;
-
- # delegate other cases
- else
- S := GroupOps.Stabilizer( G, d, opr );
- fi;
-
- # return the stabilizer
- return S;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.RepresentativeOperation(<G>,<d>,<e>,<opr>) . representative
- #F of a point in a matrix group
- ##
- MatGroupOps.RepresentativeOperation := function ( G, d, e, opr )
- local rep; # representative taking <d> to <e>, result
-
- # special case to find a conjugating element
- if d in G and e in G and opr = OnPoints then
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # translage the two matrices
- d := Permutation( d, G.permDomain );
- e := Permutation( e, G.permDomain );
-
- # find a conjugating permutation and translate back
- rep := RepresentativeOperation( G.permGroupP, d, e );
- if rep <> false then
- rep := List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^rep] );
- fi;
-
- # special case to find a matrix taking one vector to another
- elif IsVector(d) and IsVector(e) and opr = OnPoints then
-
- # compute the isomorphic permutation group for <G> and its parent
- G.operations.MakePermGroupP( G );
-
- # make sure we can handle this case
- if not d in G.permDomain or not e in G.permDomain then
- return GroupOps.RepresentativeOperation( G, d, e, opr );
- fi;
-
- # translate the two vector to points
- d := Position( G.permDomain, d );
- e := Position( G.permDomain, e );
-
- # find a representative and translate back
- rep := RepresentativeOperation( G.permGroupP, d, e );
- if rep <> false then
- rep := List( G.identity,
- v -> G.permDomain[Position(G.permDomain,v)^rep] );
- fi;
-
- # delegate other cases
- else
- rep := GroupOps.RepresentativeOperation( G, d, e, opr );
- fi;
-
- # return the representative
- return rep;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Order(<G>,<g>) . . . . . . . . . . . . . . order of a matrix
- ##
- MatGroupOps.Order := MatricesOps.Order;
-
-
- #############################################################################
- ##
- #F MatGroupOps.RightCoset(<U>,<g>) . . . . . . right coset in a matrix group
- #V RightCosetMatGroupOps operations record of right cosets in a matrix group
- ##
- ## 'MatGroupOps.RightCoset' is the function to create a right coset in a
- ## matrix group. It computes a special element (namely the matrix
- ## corresponding to the smallest element of the corresponding coset in the
- ## permutation group) of the coset and stores <U> together with this special
- ## element as representative in a record, and enters the operations record
- ## 'RightCosetMatGroupOps'.
- ##
- ## 'RightCosetMatGroupOps' is the operations record of right cosets in a
- ## matrix group. It inherits the default functions from
- ## 'RightCosetGroupOps', and overlays the comparison function, using the
- ## fact that matrix group cosets have a special unique element as
- ## representative.
- ##
- MatGroupOps.RightCoset := function ( U, g )
- local C, # right coset of <U> and <g>, result
- p; # permutation corresponding to <g>
-
- # compute the isomorphic permutation group for <G> and its parent
- U.operations.MakePermGroupP( U );
-
- # compute the isomorphic permutation for <g>
- p := Permutation( g, U.permDomain );
-
- # compute the right coset in the permutation group
- C := U.permGroupP.operations.RightCoset( U.permGroupP, p );
-
- # take its representative and translate it back
- p := C.representative;
- g := List( U.identity, v -> U.permDomain[Position(U.permDomain,v)^p] );
-
- # make the domain
- C := rec( );
- C.isDomain := true;
- C.isRightCoset := true;
-
- # enter the identifying information
- C.group := U;
- C.representative := g;
- C.special := g;
-
- # enter knowledge
- if IsBound( U.isFinite ) then
- C.isFinite := U.isFinite;
- fi;
- if IsBound( U.size ) then
- C.size := U.size;
- fi;
-
- # enter the operations record
- C.operations := RightCosetMatGroupOps;
-
- # return the coset
- return C;
- end;
-
- RightCosetMatGroupOps := Copy( RightCosetGroupOps );
-
- RightCosetMatGroupOps.\= := function ( C, D )
- local isEql;
-
- # compare a right coset with minimal representative
- if IsRightCoset( C ) and IsBound( C.special ) then
-
- # with another right coset with minimal representative
- if IsRightCoset( D ) and IsBound( D.special ) then
- if C.group = D.group then
- isEql := C.special = D.special;
- else
- isEql := RightCosetGroupOps.\=( C, D );
- fi;
-
- # with a subgroup, which is a special right coset
- elif IsGroup( D ) then
- if C.group = D then
- isEql := C.special = D.identity;
- else
- isEql := RightCosetGroupOps.\=( C, D );
- fi;
-
- # with something else
- else
- isEql := RightCosetGroupOps.\=( C, D );
- fi;
-
- # compare a subgroup, which is a special right coset
- elif IsGroup( C ) then
-
- # with a right coset with minimal representative
- if IsRightCoset( D ) and IsBound( D.special ) then
- if C = D.group then
- isEql := C.identity = D.special;
- else
- isEql := RightCosetGroupOps.\=( C, D );
- fi;
-
- # with something else
- else
- isEql := RightCosetGroupOps.\=( C, D );
- fi;
-
- # compare something else
- else
- isEql := RightCosetGroupOps.\=( C, D );
- fi;
-
- # return the result
- return isEql;
- end;
-
-
- #############################################################################
- ##
- #F MatGroup( <gens>, <field>[, <identity>] ) . . . . . create a matrix group
- ##
- MatGroup := function( arg )
- local gens, m, idmat;
-
- if Length( arg ) = 2 then
- if arg[1] = [] then
- Error( "sorry, need at least one element" );
- fi;
- idmat := arg[1][1] ^ 0;
- elif Length( arg ) = 3 then
- idmat := arg[3];
- else
- Error( "usage: MatGroup( <generators>, <field>[, <identity>] )" );
- fi;
-
- gens := [];
- for m in arg[1] do
- if m <> idmat then Add( gens, m ); fi;
- od;
-
- return rec(
- generators := gens,
- field := arg[2],
- identity := idmat,
- dimension := Length( idmat ),
- isMatGroup := true,
- isGroup := true,
- isDomain := true,
- operations := MatGroupOps
- );
- end;
-
-
- #############################################################################
- ##
- #F RandomMatGroup( <dim>, <field>, <numgens> ) . create random matrix group
- ##
- RandomMatGroup := function( dim, field, k )
- local group, mats, id, i;
-
- id := IdentityMat( dim, field );
- mats := [1..k];
- for i in [1..k] do
- mats[i] := RandomInvertableMat( dim, field );
- od;
- return MatGroup( mats, field, id );
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.Transposed( <matgroup> ) . . . . . . . . . . . . . . . . . .
- ##
- MatGroupOps.Transposed := function( group )
- local mats, m;
-
- mats := [];
- for m in group.generators do
- Add( mats, TransposedMat( m ) );
- od;
- return MatGroup( mats, group.field, group.identity );
- end;
-
-
- #############################################################################
- ##
- #F Transposed( <domain> ) . . . . . . . . . . . . . . . . . . . . . . . . .
- ##
- Transposed := function( D )
- local trans;
-
- if IsMat( D ) then
- trans := TransposedMat( D );
- elif IsDomain( D ) and IsBound( D.operations.Transposed ) then
- trans := D.operations.Transposed( D );
- else
- Error( "sorry, can't compute transposed <domain>" );
- fi;
- return trans;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.InvariantSubspace( <matgroup>[, <matrix>] ) . . . . . . . . .
- #F . . . . . . . . . . . . . . . . . . . . . . . find an invariant subspace
- ##
- ## This function tries to find an invariant Subspace for the matrix group as
- ## suggested by Norton's criterion for irreducibility. However some basic
- ## calculations have to be made if reducibility is concluded in the
- ## transposed case.
- ##
- MatGroupOps.InvariantSubspace := function( arg )
- local group, m, module, subm, sdim, ns, tmodule, tsubm, tsdim, tns,
- base, tbase, enum, line, wgts, perm, i, j;
-
- if Length( arg ) = 1 then
- group := arg[1];
- m := SmallCorankMatrixRecord( group );
- elif Length( arg ) = 2 then
- group := arg[1];
- m := arg[2];
- ns := NullspaceMat( m );
- if ns = [] then
- Error( "sorry, <matrix> has to be singular" );
- fi;
- m := rec(
- matrix := m,
- corank := Length( ns ),
- nullspace := RowSpace( ns, group.field ),
- corankGcd := Length( ns )
- );
- else
- Error( "usage: InvariantSubspace( <matgroup>[, <matrix>] )" );
- fi;
-
- module := RowModule( group );
- enum := LineEnumeration( m.nullspace );
- line := 1;
- while line <= enum.numberLines do
- subm := Submodule( module,
- RowSpace( [ enum.line( line ) ], group.field ) );
- sdim := Dimension( subm );
- line := line + 1;
- if 0 < sdim and sdim < group.dimension then
- return subm.abelianGroup;
- fi;
- od;
-
-
- # try to find a proper submodule in the transposed matrix group
-
- tmodule := RowModule( Transposed( module.ring ), module.abelianGroup );
- tns := NullspaceMat( Transposed( m.matrix ) );
- tsubm := Submodule( tmodule,
- RowSpace( [ tns[1] ], group.field ) );
- tsdim := Dimension( tsubm );
-
- if 0 < tsdim and tsdim < group.dimension then
-
- # determine the permutation that sorts the base by weights
-
- wgts := Information( tsubm.abelianGroup ).weights;
- perm := PermList( Concatenation( wgts, Difference( [1..group.dimension], wgts ) ) );
-
-
- # determine the submodule base for the normal case
-
- sdim := group.dimension - tsdim;
- tbase := Base( tsubm );
- base := [];
-
- for i in [1..sdim] do
- base[i] := ShallowCopy( module.abelianGroup.zero );
- base[i][tsdim+i] := module.abelianGroup.field.one;
- for j in [1..tsdim] do
- base[i][j] := -tbase[j][(tsdim+i)^perm];
- od;
- od;
-
- return RowSpace( base,
- module.abelianGroup.field,
- module.abelianGroup.zero );
- else
- return m.corankGcd;
- fi;
- end;
-
-
- #############################################################################
- ##
- #F InvariantSubspace( <domain> ) . . . . . . . . . . . . . . . . . . . . . .
- ##
- InvariantSubspace := function( D )
- local subs;
-
- if IsDomain( D ) and IsBound( D.operations.InvariantSubspace ) then
- subs := D.operations.InvariantSubspace( D );
- else
- Error( "sorry, can't compute an invariant subspace for <domain>" );
- fi;
- return subs;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.IsInvariantSubspace( <matgroup>, <rowspace> ) . . . . . . . .
- #F . . . . . . . . . . . . . . . . . . . . . . test if is invariant subspace
- ##
- MatGroupOps.IsInvariantSubspace := function( group, vs )
- return Submodule( RowModule( group ), vs ).abelianGroup = vs;
- end;
-
-
- #############################################################################
- ##
- #F IsInvariantSubspace( <domain>, <object> ) . . . . . . . . . . . . . . . .
- ##
- IsInvariantSubspace := function( D, obj )
- local isinv;
-
- if IsDomain( D ) and IsBound( D.operations.IsInvariantSubspace ) then
- isinv := D.operations.IsInvariantSubspace( D, obj );
- else
- Error( "sorry, can't test on invariant subspace for <domain>" );
- fi;
- return isinv;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.IrreducibilityTest( <matgroup>[, <matrix>] ) . . . . . . . .
- #F . . . . . . . . . . . . . . test whether a matrix group acts irreducible
- ##
- MatGroupOps.IrreducibilityTest := function( arg )
- local subs;
-
- if Length( arg ) = 1 then
- subs := InvariantSubspace( arg[1] );
- elif Length( arg ) = 1 then
- subs := InvariantSubspace( arg[1], arg[2] );
- else
- Error( "usage: IrreducibilityTest( <matgroup>[, <matrix>] )" );
- fi;
-
- if IsInt( subs ) then
- return rec(
- isIrreducible := true,
- isReducible := false,
- degree := subs
- );
- else
- return rec(
- isIrreducible := false,
- isReducible := true,
- invariantSubspace := subs
- );
- fi;
- end;
-
-
- #############################################################################
- ##
- #F IrreducibilityTest( <domain> ) . . . . . . . . . . . . . . . . . . . . .
- ##
- IrreducibilityTest := function( D )
- local test;
-
- if IsDomain( D ) and IsBound( D.irreducibilityTest ) then
- test := D.irreducibilityTest;
- elif IsDomain( D ) and IsBound( D.operations.IrreducibilityTest ) then
- D.irreducibilityTest := D.operations.IrreducibilityTest( D );
- test := D.irreducibilityTest;
- else
- Error( "sorry, can't test <domain> for irreducibility" );
- fi;
- return test;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.AbsoluteIrreducibilityTest( <matgroup>[, <matrix>] ) . . . .
- #F . . . . . . . . . . test whether a matrix group acts absolute irreducible
- ##
- MatGroupOps.AbsoluteIrreducibilityTest := function( arg )
- local subs, deg, group, mats, field, m;
-
- if Length( arg ) = 1 then
- group := arg[1];
- subs := InvariantSubspace( arg[1] );
- elif Length( arg ) = 1 then
- group := arg[1];
- subs := InvariantSubspace( arg[1], arg[2] );
- else
- Error( "usage: AbsoluteIrreducibilityTest( <matgroup>[, <matrix>] )" );
- fi;
-
- if IsInt( subs ) then
- deg := subs;
- if deg = 1 then
- return rec(
- isIrreducible := true,
- isReducible := false,
- isAbsoluteIrreducible := true,
- degree := deg
- );
- fi;
-
- if IsFinite( arg[1] ) then
-
- # construct the new matrix group over the bigger field
-
- field := GF( Size( group.field ) ^ deg );
- mats := [];
- for m in group.generators do
- Add( mats, field.one * m );
- od;
- if mats = [] then
- group := MatGroup( mats, field, field.one * group.identity );
- else
- group := MatGroup( mats, field );
- fi;
-
- if Length( arg ) = 1 then
- subs := InvariantSubspace( group );
- else
- subs := InvariantSubspace( group, arg[2] );
- fi;
-
- if IsInt( subs ) then
- return rec(
- isIrreducible := true,
- isReducible := false,
- isAbsoluteIrreducible := true,
- degree := deg * subs
- );
- else
- return rec(
- isIrreducible := true,
- isReducible := false,
- isAbsoluteIrreducible := false,
- degree := deg,
- invariantSubspace := subs
-
- );
- fi;
-
- else
- Error( "sorry, don't know how to extend infinte fields" );
- fi;
- else
- return rec(
- isIrreducible := false,
- isReducible := true,
- isAbsoluteIrreducible := false,
- invariantSubspace := subs
- );
- fi;
- end;
-
-
- #############################################################################
- ##
- #F AbsoluteIrreducibilityTest( <domain> ) . . . . . . . . . . . . . . . . .
- ##
- AbsoluteIrreducibilityTest := function( D )
- local test;
-
- if IsDomain( D ) and IsBound( D.absoluteIrreducibilityTest ) then
- test := D.absoluteIrreducibilityTest;
- elif IsDomain( D ) and IsBound( D.operations.AbsoluteIrreducibilityTest ) then
- D.absoluteIrreducibilityTest := D.operations.AbsoluteIrreducibilityTest( D );
- test := D.absoluteIrreducibilityTest;
- else
- Error( "sorry, can't test <domain> for absolute irreducibility" );
- fi;
- return test;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.CompositionFactors( <matgroup> ) . . . . . . . . . . . . . .
- #F . . . . . . . . . . . . . . . . . . composition factors of a matrix group
- ##
- MatGroupOps.CompositionFactors := function( group )
- local decompose, groups, bases;
-
- decompose := function ( m, b )
- local subs, rep;
-
- subs := InvariantSubspace( m );
- if IsInt( subs ) then
- Add( groups, m );
- Add( bases, b );
- else
- rep := Representation( RowModule( m ), RowModule( m, subs ) );
- decompose( rep.range, rep.base * b );
- rep := Representation( RowModule( m, subs ) );
- decompose( rep.range, rep.base * b );
- fi;
- end;
-
- groups := [];
- bases := [];
- decompose( group, IdentityMat( group.dimension, group.field ) );
-
- return rec(
- groups := groups,
- bases := bases
- );
- end;
-
-
- #############################################################################
- ##
- #F CompositionFactors( <domain> ) . . . . . . composition factors of domain
- ##
- CompositionFactors := function( D )
- local comp;
-
- if IsDomain( D ) and IsBound( D.compositionFactors ) then
- comp := D.compositionFactors;
- elif IsDomain( D ) and IsBound( D.operations.CompositionFactors ) then
- D.compositionFactors := D.operations.CompositionFactors( D );
- comp := D.compositionFactors;
- else
- Error( "sorry, can't compute composition factors for <domain>" );
- fi;
- return comp;
- end;
-
-
- #############################################################################
- ##
- #F MatGroupOps.EquivalenceTest( <matgroup>, <matgroup> ) . . . . . . . . . .
- #F . . . . . . . . . . . . . perform a test for equivalence of matrix groups
- ##
- MatGroupOps.EquivalenceTest := function( group1, group2 )
- local fp1, fp2, module, minpos, ns1, ns2, crk, result, base, line,
- enum, y1, x, x_inv, i;
-
- if group1.identity <> group2.identity
- or group1.field <> group2.field
- or Length( group1.generators ) <> Length( group2.generators ) then
- return rec( areequivalent := false );
- fi;
-
- # first check the trivial cases
-
- if group1.generators = group2.generators then
- return rec(
- areequivalent := true,
- transformationMatrix := group1.identity
- );
- elif group1.dimension = 1 then
- return rec( areequivalent := false );
- fi;
-
- fp1 := Fingerprint( group1 );
- AddNextMatrixFunction( group2, group1.operations.NextMatrix );
- fp2 := Fingerprint( group2 );
-
- if fp1.coranks <> fp2.coranks then
- return rec( areequivalent := false );
- fi;
- if fp1.failed then
- Error( "sorry, fingerprint failed" );
- fi;
-
- minpos := Position( fp1.coranks,
- Minimum( Filtered( fp1.coranks, x -> x <> 0 ) ) );
-
- ns1 := fp1.nullspaces[minpos];
- ns2 := fp2.nullspaces[minpos];
- crk := fp1.coranks[minpos];
-
- result := rec( areequivalent := false );
-
- enum := LineEnumeration( ns1 );
- line := 1;
- repeat
- module := RowModule( group1,
- RowSpace( [ enum.line( line ) ], group1.field ) );
- module.isNormalizedBase := false;
- base := Base( module );
- line := line + 1;
- until Length( base ) = group1.dimension or line > enum.numberLines;
-
- if Length( base ) = group1.dimension then
- y1 := base;
- enum := LineEnumeration( ns2 );
- line := 1;
-
- repeat
-
- module := RowModule( group2,
- RowSpace( [ enum.line( line ) ], group2.field ) );
- module.isNormalizedBase := false;
- base := Base( module );
- line := line + 1;
-
- if Length( base ) = group2.dimension then
- x := base^-1 * y1;
- x_inv := x ^ -1;
- i := 1;
- result.areequivalent := true;
- while i <= Length( group1.generators ) and result.areequivalent do
- if x * group1.generators[i] * x_inv <> group2.generators[i] then
- result.areequivalent := false;
- fi;
- i := i + 1;
- od;
- if result.areequivalent then
- result.transformationMatrix := x;
- fi;
- fi;
-
- until result.areequivalent or line > enum.numberLines;
-
- else
- Error( "sorry, failed finding a cyclic generator" );
- fi;
- return result;
- end;
-
-
- #############################################################################
- ##
- #F EquivalenceTest( <domain>, <domain> ) . . . . . . equivalence of domains
- ##
- EquivalenceTest := function( D1, D2 )
- local equiv;
-
- if IsDomain( D1 ) and IsBound( D1.operations.EquivalenceTest ) then
- equiv := D1.operations.EquivalenceTest( D1, D2 );
- else
- Error( "sorry, can't test equivalence of the given domains" );
- fi;
- return equiv;
- end;
-
-
- #############################################################################
- ##
- #F AddNextMatrixFunction( <matgroup>, <function> ) . . . . . . . . . . . . .
- #F . . . . . . . . . . . . . set the NextMatrix function for a matrix group
- ##
- AddNextMatrixFunction := function( group, func )
- group.operations.NextMatrix := func;
- end;
-
-
- #############################################################################
- ##
- #F NextMatrix( <matgroup>, <info> ) . . . . . . . . . generate next matrix
- ##
- NextMatrix := function( group, info )
- local m;
-
- if IsMatGroup( group ) then
- if not IsBound( group.operations.NextMatrix ) then
- AddNextMatrixFunction( group, NextMatrix2 );
- fi;
- m := group.operations.NextMatrix( group, info );
- else
- Error( "sorry, I only can compute a next matrix for matrix groups" );
- fi;
- return m;
- end;
-
-
- #############################################################################
- ##
- #F SmallCorankMatrixRecord( <matgroup> ) . choose random matrix of low rank
- ##
- SmallCorankMatrixRecord := G -> RandomMatrixRecord( G, 1 );
-
-
- #############################################################################
- ##
- #F RandomMatrixRecord( <matgroup>[, <integer>] ) . . . choose random matrix
- ##
- ##
- ##
- ## returns
- ##
- ## rec(
- ## matrix := <matrix>,
- ## corank := <integer>,
- ## nullspace := <rowspace>,
- ## corankGcd := <integer>
- ## )
- ##
- RandomMatrixRecord := function( arg )
- local group, maxcrk, m, crk, gcd, ns, minmat, mincrk, minns, zero, info;
-
- if Length( arg ) = 1 then group := arg[1]; maxcrk := group.dimension;
- elif Length( arg ) = 2 then group := arg[1]; maxcrk := arg[2];
- else Error( "usage: RandomMatrixRecord( <matgroup>[, <maxcorank>] )" );
- fi;
-
- if group.generators = [] or group.dimension = 1 then
- return rec(
- matrix := 0 * group.identity,
- corank := group.dimension,
- nullspace := RowSpace( group.dimension, group.field ),
- corankGcd := group.dimension
- );
- fi;
-
- zero := 0 * group.identity[1];
- info := rec();
- m := NextMatrix( group, info );
-
- ns := NullspaceMat( m );
- crk := Length( ns );
- gcd := crk;
- if 0 < crk and crk <= maxcrk then
- return rec(
- matrix := m,
- corank := crk,
- nullspace := RowSpace( ns, group.field, zero ),
- corankGcd := gcd
- );
- elif 0 < crk then
- minmat := m;
- mincrk := crk;
- minns := ns;
- else
- minmat := 0 * m;
- mincrk := group.dimension;
- minns := RowSpace( group.dimension, group.field ).generators;
- gcd := group.dimension;
- fi;
-
- m := NextMatrix( group, info );
- while m <> false do
- ns := NullspaceMat( m );
- crk := Length( ns );
- gcd := Gcd( gcd, crk );
- if 0 < crk and crk <= maxcrk then
- return rec(
- matrix := m,
- corank := crk,
- nullspace := VectorSpace( ns, group.field, zero ),
- corankGcd := gcd
- );
- elif 0 < crk and crk < mincrk then
- minmat := m;
- mincrk := crk;
- minns := ns;
- fi;
-
- m := NextMatrix( group, info );
- od;
-
- return rec(
- matrix := minmat,
- corank := mincrk,
- nullspace := VectorSpace( minns, group.field, zero ),
- corankGcd := gcd
- );
- end;
-
-
- #############################################################################
- ##
- #F Fingerprint( <matgroup>[, <integer>] ) . . . . . . . . . . . . . . . . .
- ##
- ##
- ##
- ## returns
- ##
- ## rec(
- ## matrices := [ <matrix> ],
- ## coranks := [ <integer> ],
- ## nullspaces := [ <rowspace> ],
- ## corankGcd := <integer>,
- ## failed := <boolean>
- ## )
- ##
- Fingerprint := function( arg )
- local group, maxcrk, corank, nullspace, matrix, m, zero, info, gcd, i;
-
- if Length( arg ) = 1 then group := arg[1]; maxcrk := 0;
- elif Length( arg ) = 2 then group := arg[1]; maxcrk := arg[2];
- else Error( "usage: Fingerprint( <matgroup>[, <maxcorank>] )" );
- fi;
-
- # if the group is easy to handle do it now. Remember that a corank of
- # one (although possibly trivial) means the fingerprint did not fail.
-
- if group.generators = [] or group.dimension = 1 then
- return rec(
- coranks := [ 1 ],
- nullspaces := [ RowSpace( 1, group.field ) ],
- matrices := [ 0 * group.identity ],
- failed := false
- );
- fi;
-
- corank := [];
- nullspace := [];
- matrix := [];
-
- zero := 0 * group.identity[1];
- gcd := group.dimension;
- info := rec();
- m := NextMatrix( group, info );
- i := 0;
-
- while m <> false do
-
- i := i + 1;
- nullspace[i] := RowSpace( NullspaceMat( m ), group.field, zero );
- corank[i] := Dimension( nullspace[i] );
- matrix[i] := m;
- gcd := Gcd( gcd, corank[i] );
-
- if 0 < corank[i] and corank[i] <= maxcrk then
- return rec(
- coranks := corank,
- nullspaces := nullspace,
- matrices := matrix,
- corankGcd := gcd,
- failed := false
- );
- fi;
-
- m := NextMatrix( group, info );
- od;
-
- return rec(
- coranks := corank,
- nullspaces := nullspace,
- matrices := matrix,
- corankGcd := gcd,
- failed := maxcrk <> 0 or Maximum( corank ) = 0
- );
- end;
-
-
- #############################################################################
- ##
- #F ClassicNextMatrix( <matgroup>, <info> ) . . . . . . . . . . . . . . . . .
- ##
- ## This function implements the classical fingerprint methods for two
- ## matrices as proposed by R.A. Parker in his first paper about the
- ## meat-axe system.
- ##
- ClassicNextMatrix := function( group, info )
- local m;
-
- if info = rec() then
- info.R := [];
- info.number := 0;
-
- if Length( group.generators ) >= 2 then
- info.R[1] := group.generators[1];
- info.R[2] := group.generators[2];
- elif Length( group.generators ) = 1 then
- info.R[1] := group.generators[1];
- info.R[2] := group.identity;
- else
- info.R[1] := group.identity;
- info.R[2] := group.identity;
- fi;
-
- info.R[3] := info.R[1] * info.R[2];
- info.R[4] := info.R[1] + info.R[2];
- info.R[5] := info.R[3] + info.R[4];
- fi;
-
- info.number := info.number + 1;
-
- if info.number = 1 then
- m := info.R[5];
- elif info.number = 2 then
- info.R[6] := info.R[3] * info.R[2];
- info.R[7] := info.R[5] + info.R[6];
- m := info.R[7];
- elif info.number = 3 then
- info.R[8] := info.R[2] * info.R[7];
- info.R[9] := info.R[1] + info.R[8];
- m := info.R[9];
- elif info.number = 4 then
- info.R[10] := info.R[2] + info.R[9];
- m := info.R[10];
- elif info.number = 5 then
- info.R[11] := info.R[3] + info.R[10];
- m := info.R[11];
- elif info.number = 6 then
- info.R[12] := info.R[1] + info.R[11];
- m := info.R[12];
- else
- m := false;
- fi;
-
- return m;
- end;
-
-
- #############################################################################
- ##
- #F ExtendedClassicNextMatrix( <matgroup>, <info> ) . . . . . . . . . . . . .
- ##
- ## This function implements the classical fingerprint methods for two
- ## matrices as proposed by R.A. Parker in his first paper about the
- ## meat-axe system, extended for the case when more generating matrices are
- ## given.
- ##
- ExtendedClassicNextMatrix := function( group, info )
- local m;
-
- if info = rec() then
-
- info.R := [];
- info.number := 0;
- info.next := false;
- if Length( group.generators ) >= 2 then
- info.R[1] := group.generators[1]; info.1 := 1;
- info.R[2] := group.generators[2]; info.2 := 2;
- elif Length( group.generators ) = 1 then
- info.R[1] := group.identity; info.2 := 0;
- info.R[2] := group.generators[1]; info.1 := 1;
- else
- info.R[1] := group.identity; info.1 := 0;
- info.R[2] := group.identity; info.2 := 0;
- fi;
- info.R[3] := info.R[1] * info.R[2];
- info.R[4] := info.R[1] + info.R[2];
- info.R[5] := info.R[3] + info.R[4];
-
- elif info.next then
-
- info.2 := info.2 + 1;
- if info.2 > Length( group.generators ) then
- info.1 := info.1 + 1;
- info.2 := info.1 + 1;
- fi;
- if info.2 > Length( group.generators ) then
- return false;
- fi;
-
- info.R := [];
- info.number := 0;
- info.next := false;
- info.R[1] := group.generators[info.1];
- info.R[2] := group.generators[info.2];
- info.R[3] := info.R[1] * info.R[2];
- info.R[4] := info.R[1] + info.R[2];
- info.R[5] := info.R[3] + info.R[4];
-
- fi;
-
- info.number := info.number + 1;
-
- if info.number = 1 then
- m := info.R[5];
- elif info.number = 2 then
- info.R[6] := info.R[3] * info.R[2];
- info.R[7] := info.R[5] + info.R[6];
- m := info.R[7];
- elif info.number = 3 then
- info.R[8] := info.R[2] * info.R[7];
- info.R[9] := info.R[1] + info.R[8];
- m := info.R[9];
- elif info.number = 4 then
- info.R[10] := info.R[2] + info.R[9];
- m := info.R[10];
- elif info.number = 5 then
- info.R[11] := info.R[3] + info.R[10];
- m := info.R[11];
- elif info.number = 6 then
- info.R[12] := info.R[1] + info.R[11];
- m := info.R[12];
- else
- info.next := true;
- m := NextMatrix( group, info );
- fi;
-
- return m;
- end;
-
-
- #############################################################################
- ##
- #F NextMatrix1( <matgroup>, <info> ) . . . . . . . . . . . . . . . . . . . .
- ##
- ##
- NextMatrix1 := function( group, info )
- local m, g, i;
-
- if info = rec() then
- if group.generators = [] then
- m := group.identity;
- else
- m := group.generators[1];
- for i in [2..Length( group.generators )] do
- m := m * group.generators[i];
- od;
- info.product := m;
- for i in [1..Length( group.generators )] do
- m := m + group.generators[i];
- od;
- fi;
-
- info.matrix := m;
- info.generator := 0;
- info.nextgen := true;
-
- return m;
- fi;
-
- if info.nextgen then
- info.generator := info.generator + 1;
- if info.generator > Length( group.generators ) then
- return false;
- fi;
-
- m := info.matrix;
- g := group.generators[info.generator];
-
- m := m * g;
- for i in [1..info.generator] do
- m := m + group.generators[i];
- od;
- info.matrix := m;
- info.nextgen := false;
- else
- m := info.matrix;
- m := m + info.product;
- info.matrix := m;
- info.nextgen := true;
- fi;
-
- return m;
- end;
-
-
- #############################################################################
- ##
- #F NextMatrix2( <matgroup>, <info> ) . . . . . . . . . . . . . . . . . . . .
- ##
- ##
- NextMatrix2 := function( group, info )
- local m, g, ew, ew2, i;
-
- if info = rec() then
- if group.generators = [] then
- m := group.identity;
- else
- m := group.generators[1];
- for i in [2..Length( group.generators )] do
- m := m * group.generators[i];
- od;
- info.product := m;
- for i in [1..Length( group.generators )] do
- m := m + group.generators[i];
- od;
- fi;
-
- if IsFinite( group.field ) then
- ew := group.field.one;
- ew2 := group.field.zero;
- info.eigenvalues := [ ew2 ];
- for i in [2..Order( group.field, group.field.root )+1] do
- ew := ew * group.field.root;
- info.eigenvalues[i] := ew - ew2;
- ew2 := ew;
- od;
- else
- info.eigenvalues := [ 0, -3, 1, 1, 2, 1, 1 ];
- fi;
-
- info.matrix := m;
- info.generator := 0;
- info.nextgen := true;
- info.nextev := 1;
-
- return m;
- fi;
-
- if info.nextgen then
- if info.nextev = 1 then
-
- info.generator := info.generator + 1;
- if info.generator > Length( group.generators ) then
- return false;
- fi;
-
- m := info.matrix;
- g := group.generators[info.generator];
-
- m := m * g;
- for i in [1..info.generator] do
- m := m + group.generators[i];
- od;
- info.matrix := m;
- info.nextev := info.nextev + 1;
- if info.nextev > Length( info.eigenvalues ) then
- info.nextgen := false;
- info.nextev := 1;
- fi;
- else
- if info.nextev = 2 then
- info.matrix2 := info.matrix;
- fi;
-
- m := Copy( info.matrix2 );
- for i in [1..group.dimension] do
- m[i][i] := m[i][i] + info.eigenvalues[info.nextev];
- od;
- info.matrix2 := m;
-
- info.nextev := info.nextev + 1;
- if info.nextev > Length( info.eigenvalues ) then
- info.nextgen := false;
- info.nextev := 1;
- fi;
- fi;
- else
- if info.nextev = 1 then
- m := info.matrix;
- m := m + info.product;
- info.matrix := m;
- info.nextev := info.nextev + 1;
- if info.nextev > Length( info.eigenvalues ) then
- info.nextgen := true;
- info.nextev := 1;
- fi;
- else
- if info.nextev = 2 then
- info.matrix2 := info.matrix;
- fi;
-
- m := Copy( info.matrix2 );
- for i in [1..group.dimension] do
- m[i][i] := m[i][i] + info.eigenvalues[info.nextev];
- od;
- info.matrix2 := m;
-
- info.nextev := info.nextev + 1;
- if info.nextev > Length( info.eigenvalues ) then
- info.nextgen := true;
- info.nextev := 1;
- fi;
- fi;
- fi;
-
- return m;
- end;
-
-
- #############################################################################
- ##
- #F NextMatrix3( <matgroup>, <info> ) . . . . . . . . . . . . . . . . . . . .
- ##
- ##
- NextMatrix3 := function( group, info )
- local m;
-
- if info = rec() then
- info.R := [];
- info.number := 0;
- info.next := false;
- if Length( group.generators ) >= 2 then
- info.R[1] := group.generators[1]; info.1 := 1;
- info.R[2] := group.generators[2]; info.2 := 2;
- elif Length( group.generators ) = 1 then
- info.R[1] := group.identity; info.2 := 0;
- info.R[2] := group.generators[1]; info.1 := 1;
- else
- info.R[1] := group.identity; info.1 := 0;
- info.R[2] := group.identity; info.2 := 0;
- fi;
-
- elif info.next then
-
- info.2 := info.2 + 1;
- if info.2 > Length( group.generators ) then
- info.1 := info.1 + 1;
- info.2 := info.1 + 1;
- fi;
- if info.2 > Length( group.generators ) then
- return false;
- fi;
-
- info.R := [];
- info.number := 0;
- info.next := false;
- fi;
-
- info.number := info.number + 1;
-
- if info.number = 1 then
- info.R[3] := info.R[1] * info.R[2];
- info.R[4] := info.R[1] + info.R[2];
- info.R[5] := info.R[3] + info.R[4];
- m := info.R[5];
- elif info.number = 2 then
- info.R[6] := info.R[3] * info.R[2];
- info.R[7] := info.R[5] + info.R[6];
- m := info.R[7];
- elif info.number = 3 then
- info.R[8] := info.R[2] * info.R[7];
- info.R[9] := info.R[1] + info.R[8];
- m := info.R[9];
- elif info.number = 4 then
- info.R[10] := info.R[2] + info.R[9];
- m := info.R[10];
- elif info.number = 5 then
- info.R[11] := info.R[3] + info.R[10];
- m := info.R[11];
- elif info.number = 6 then
- info.R[12] := info.R[1] + info.R[11];
- m := info.R[12];
- elif 7 <= info.number and info.number <= 18 then
- m := info.R[info.number-6] - group.identity;
- elif 19 <= info.number and info.number <= 30 then
- m := info.R[info.number-18] + group.identity;
- else
- info.next := true;
- m := NextMatrix( group, info );
- fi;
-
- return m;
- end;
-
-
- #############################################################################
- ##
- #E Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables
- ##
- ## Local Variables:
- ## mode: outline
- ## outline-regexp: "#F\\|#V\\|#E"
- ## fill-column: 73
- ## fill-prefix: "## "
- ## eval: (hide-body)
- ## End:
- ##
-
-
-
-