Path: blob/master/sage/groups/matrix_gps/matrix_group.py
4058 views
"""1Matrix Groups23AUTHORS:45- William Stein: initial version67- David Joyner (2006-03-15): degree, base_ring, _contains_, list,8random, order methods; examples910- William Stein (2006-12): rewrite1112- David Joyner (2007-12): Added invariant_generators (with Martin13Albrecht and Simon King)1415- David Joyner (2008-08): Added module_composition_factors (interface16to GAP's MeatAxe implementation) and as_permutation_group (returns17isomorphic PermutationGroup).1819- Simon King (2010-05): Improve invariant_generators by using GAP20for the construction of the Reynolds operator in Singular.2122This class is designed for computing with matrix groups defined by23a (relatively small) finite set of generating matrices.2425EXAMPLES::2627sage: F = GF(3)28sage: gens = [matrix(F,2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])]29sage: G = MatrixGroup(gens)30sage: G.conjugacy_class_representatives()31[32[1 0]33[0 1],34[0 1]35[2 1],36[0 1]37[2 2],38[0 2]39[1 1],40[0 2]41[1 2],42[0 1]43[2 0],44[2 0]45[0 2]46]4748Loading, saving, ... works::4950sage: G = GL(2,5); G51General Linear Group of degree 2 over Finite Field of size 552sage: TestSuite(G).run()5354sage: g = G.1; g55[4 1]56[4 0]57sage: TestSuite(g).run()5859We test that #9437 is fixed::6061sage: len(list(SL(2, Zmod(4))))624863"""6465##############################################################################66# Copyright (C) 2006 David Joyner and William Stein <[email protected]>67#68# Distributed under the terms of the GNU General Public License (GPL)69#70# The full text of the GPL is available at:71#72# http://www.gnu.org/licenses/73##############################################################################747576from sage.misc.randstate import current_randstate77from sage.categories.groups import Groups78from sage.categories.finite_groups import FiniteGroups79from sage.structure.parent import Parent80from matrix_group_element import MatrixGroupElement81from sage.groups.group import Group82from sage.rings.all import is_Ring, infinity83from sage.rings.finite_rings.constructor import is_FiniteField84from sage.interfaces.gap import gap85from sage.matrix.all import MatrixSpace, is_MatrixSpace, is_Matrix86import sage.rings.integer as integer87from sage.misc.latex import latex88from sage.structure.sequence import Sequence89from sage.structure.sage_object import SageObject90from sage.groups.class_function import ClassFunction91from sage.misc.decorators import rename_keyword9293#################################################################9495class MatrixGroup_generic(Group):96pass9798def is_MatrixGroup(x):99"""100EXAMPLES::101102sage: from sage.groups.matrix_gps.matrix_group import is_MatrixGroup103sage: is_MatrixGroup(MatrixSpace(QQ,3))104False105sage: is_MatrixGroup(Mat(QQ,3))106False107sage: is_MatrixGroup(GL(2,ZZ))108True109sage: is_MatrixGroup(MatrixGroup([matrix(2,[1,1,0,1])]))110True111"""112return isinstance(x, MatrixGroup_generic)113114def MatrixGroup(gens):115r"""116Return the matrix group with given generators.117118INPUT:119120121- ``gens`` - list of matrices in a matrix space or122matrix group123124125EXAMPLES::126127sage: F = GF(5)128sage: gens = [matrix(F,2,[1,2, -1, 1]), matrix(F,2, [1,1, 0,1])]129sage: G = MatrixGroup(gens); G130Matrix group over Finite Field of size 5 with 2 generators:131[[[1, 2], [4, 1]], [[1, 1], [0, 1]]]132133In the second example, the generators are a matrix over134`\ZZ`, a matrix over a finite field, and the integer135`2`. Sage determines that they both canonically map to136matrices over the finite field, so creates that matrix group137there.138139::140141sage: gens = [matrix(2,[1,2, -1, 1]), matrix(GF(7), 2, [1,1, 0,1]), 2]142sage: G = MatrixGroup(gens); G143Matrix group over Finite Field of size 7 with 3 generators:144[[[1, 2], [6, 1]], [[1, 1], [0, 1]], [[2, 0], [0, 2]]]145146Each generator must be invertible::147148sage: G = MatrixGroup([matrix(ZZ,2,[1,2,3,4])])149Traceback (most recent call last):150...151ValueError: each generator must be an invertible matrix but one is not:152[1 2]153[3 4]154155Some groups aren't supported::156157sage: SL(2, CC).gens()158Traceback (most recent call last):159...160NotImplementedError: Matrix group over Complex Field with 53 bits of precision not implemented.161sage: G = SL(0, QQ)162Traceback (most recent call last):163...164ValueError: The degree must be at least 1165"""166if len(gens) == 0:167raise ValueError, "gens must have positive length"168try:169R = gens[0].base_ring()170except AttributeError:171raise TypeError, "gens must be a list of matrices"172for i in range(len(gens)):173if not is_Matrix(gens[i]):174try:175gens[i] = gens[i].matrix()176except AttributeError:177pass178if is_FiniteField(R):179return MatrixGroup_gens_finite_field(gens)180else:181return MatrixGroup_gens(gens)182183class MatrixGroup_gap(MatrixGroup_generic):184Element = MatrixGroupElement185186def __init__(self, n, R, var='a', category = None):187"""188INPUT:189190191- ``n`` - the degree192193- ``R`` - the base ring194195- ``var`` - variable used to define field of196definition of actual matrices in this group.197"""198if not is_Ring(R):199raise TypeError, "R (=%s) must be a ring"%R200201202self._var = var203self.__n = integer.Integer(n)204if self.__n <= 0:205raise ValueError, "The degree must be at least 1"206self.__R = R207208if self.base_ring().is_finite():209default_category = FiniteGroups()210else:211# Should we ask GAP whether the group is finite?212default_category = Groups()213if category is None:214category = default_category215else:216assert category.is_subcategory(default_category), \217"%s is not a subcategory of %s"%(category, default_category)218Parent.__init__(self, category = category)219# TODO: inherit from ParentWithBase, once the Group class will220# be fully replaced by the Groups() category221# ParentWithBase.__init__(self, base, category = category)222223def _gap_(self, G=None):224try:225return SageObject._gap_(self, G)226except TypeError:227raise NotImplementedError, "Matrix group over %s not implemented."%self.__R228229def __cmp__(self, H):230if not isinstance(H, MatrixGroup_gap):231return cmp(type(self), type(H))232return cmp(gap(self), gap(H))233234def __call__(self, x):235"""236EXAMPLES::237238sage: F = GF(5); MS = MatrixSpace(F,2,2)239sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])240sage: G.matrix_space()241Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5242sage: G(1)243[1 0]244[0 1]245"""246if isinstance(x, self.element_class) and x.parent() is self:247return x248M = self.matrix_space()(x)249g = self.element_class(M, self)250if not gap(g) in gap(self):251raise TypeError, "no way to coerce element to self."252return g253254def _Hom_(self, G, cat=None):255if not (cat is None or (cat is G.category() and cat is self.category())):256raise TypeError257if not is_MatrixGroup(G):258raise TypeError, "G (=%s) must be a matrix group."%G259import homset260return homset.MatrixGroupHomset(self, G)261262def hom(self, x):263v = Sequence(x)264U = v.universe()265if not is_MatrixGroup(U):266raise TypeError, "u (=%s) must have universe a matrix group."%U267return self.Hom(U)(x)268269def matrix_space(self):270"""271Return the matrix space corresponding to this matrix group.272273This is a matrix space over the field of definition of this matrix274group.275276EXAMPLES::277278sage: F = GF(5); MS = MatrixSpace(F,2,2)279sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])280sage: G.matrix_space()281Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5282"""283try:284return self.__matrix_space285except AttributeError:286pass287self.__matrix_space = MatrixSpace(self.field_of_definition(), self.__n)288return self.__matrix_space289290def degree(self):291"""292Return the degree of this matrix group.293294EXAMPLES::295296sage: SU(5,5).degree()2975298"""299return self.__n300301def field_of_definition(self, var='a'):302"""303Return a field that contains all the matrices in this matrix304group.305306EXAMPLES::307308sage: G = SU(3,GF(5))309sage: G.base_ring()310Finite Field of size 5311sage: G.field_of_definition()312Finite Field in a of size 5^2313sage: G = GO(4,GF(7),1)314sage: G.field_of_definition()315Finite Field of size 7316sage: G.base_ring()317Finite Field of size 7318"""319return self.__R320321def base_ring(self):322"""323Return the base ring of this matrix group.324325EXAMPLES::326327sage: GL(2,GF(3)).base_ring()328Finite Field of size 3329sage: G = SU(3,GF(5))330sage: G.base_ring()331Finite Field of size 5332sage: G.field_of_definition()333Finite Field in a of size 5^2334"""335return self.__R336337base_field = base_ring338339def is_abelian(self):340r"""341Return True if this group is an abelian group.342343Note: The result is cached, since it tends to get called344rather often (e.g. by word_problem) and it's very slow to345use the Gap interface every time.346347EXAMPLES::348349sage: SL(1, 17).is_abelian()350True351sage: SL(2, 17).is_abelian()352False353"""354try:355return self.__is_abelian356except AttributeError:357self.__is_abelian = self._gap_().IsAbelian().bool()358return self.__is_abelian359360def is_finite(self):361"""362Return True if this matrix group is finite.363364EXAMPLES::365366sage: G = GL(2,GF(3))367sage: G.is_finite()368True369sage: SL(2,ZZ).is_finite()370False371"""372if self.base_ring().is_finite():373return True374return self._gap_().IsFinite().bool()375376def cardinality(self):377"""378Implements :meth:`EnumeratedSets.ParentMethods.cardinality`.379380EXAMPLES::381382sage: G = Sp(4,GF(3))383sage: G.cardinality()38451840385sage: G = SL(4,GF(3))386sage: G.cardinality()38712130560388sage: F = GF(5); MS = MatrixSpace(F,2,2)389sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]390sage: G = MatrixGroup(gens)391sage: G.cardinality()392480393sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])394sage: G.cardinality()395+Infinity396"""397g = self._gap_()398if g.IsFinite().bool():399return integer.Integer(gap(self).Size())400return infinity401402def order(self):403"""404Backward compatibility alias for :meth:`.cardinality`.405406Might be deprecated in the future.407408EXAMPLES::409410sage: G = Sp(4,GF(3))411sage: G.order()41251840413"""414return self.cardinality()415416def __len__(self):417"""418__len__ has been removed ! to get the number of element in a419matrix group, use :meth:`.cardinality`.420421EXAMPLES::422423sage: G = GO(3,GF(5))424sage: len(G)425Traceback (most recent call last):426...427AttributeError: __len__ has been removed; use .cardinality() instead428429"""430raise AttributeError, "__len__ has been removed; use .cardinality() instead"431432def gens(self):433"""434Return generators for this matrix group.435436EXAMPLES::437438sage: G = GO(3,GF(5))439sage: G.gens()440[441[2 0 0]442[0 3 0]443[0 0 1],444[0 1 0]445[1 4 4]446[0 2 1]447]448"""449try:450return self.__gens451except AttributeError:452pass453F = self.field_of_definition()454gap_gens = list(gap(self).GeneratorsOfGroup())455gens = Sequence([self.element_class(g._matrix_(F), self, check=False) for g in gap_gens],456cr=True, universe=self, check=False)457self.__gens = gens458return gens459460def ngens(self):461"""462Return the number of generators of this linear group.463464EXAMPLES::465466sage: G = GO(3,GF(5))467sage: G.ngens()4682469"""470return len(self.gens())471472473def gen(self, n):474"""475Return the n-th generator.476477EXAMPLES::478479sage: G = GU(4,GF(5), var='beta')480sage: G.gen(0)481[ beta 0 0 0]482[ 0 1 0 0]483[ 0 0 1 0]484[ 0 0 0 3*beta]485"""486return self.gens()[n]487488def as_matrix_group(self):489"""490Return this group, but as a general matrix group, i.e., throw away491the extra structure of general unitary group.492493EXAMPLES::494495sage: G = SU(4,GF(5))496sage: G.as_matrix_group()497Matrix group over Finite Field in a of size 5^2 with 2 generators:498[[[a, 0, 0, 0],499[0, 2*a + 3, 0, 0],500[0, 0, 4*a + 1, 0],501[0, 0, 0, 3*a]],502[[1, 0, 4*a + 3, 0],503[1, 0, 0, 0],504[0, 2*a + 4, 0, 1],505[0, 3*a + 1, 0, 0]]]506507::508509sage: G = GO(3,GF(5))510sage: G.as_matrix_group()511Matrix group over Finite Field of size 5 with 2 generators:512[[[2, 0, 0], [0, 3, 0], [0, 0, 1]], [[0, 1, 0], [1, 4, 4], [0, 2, 1]]]513"""514from sage.groups.matrix_gps.matrix_group import MatrixGroup515return MatrixGroup([g.matrix() for g in self.gens()])516517def list(self):518"""519Return list of all elements of this group.520521Always returns a new list, so it is safe to change the returned522list.523524EXAMPLES::525526sage: F = GF(3)527sage: gens = [matrix(F,2, [1,0, -1,1]), matrix(F, 2, [1,1,0,1])]528sage: G = MatrixGroup(gens)529sage: G.cardinality()53024531sage: v = G.list()532sage: len(v)53324534sage: v[:2]535[[0 1]536[2 0], [0 1]537[2 1]]538sage: G.list()[0] in G539True540541An example over a ring (see trac 5241)::542543sage: M1 = matrix(ZZ,2,[[-1,0],[0,1]])544sage: M2 = matrix(ZZ,2,[[1,0],[0,-1]])545sage: M3 = matrix(ZZ,2,[[-1,0],[0,-1]])546sage: MG = MatrixGroup([M1, M2, M3])547sage: MG.list()548[[-1 0]549[ 0 -1], [-1 0]550[ 0 1], [ 1 0]551[ 0 -1], [1 0]552[0 1]]553sage: MG.list()[1]554[-1 0]555[ 0 1]556sage: MG.list()[1].parent()557Matrix group over Integer Ring with 3 generators:558[[[-1, 0], [0, 1]], [[1, 0], [0, -1]], [[-1, 0], [0, -1]]]559560An example over a field (see trac 10515)::561562sage: gens = [matrix(QQ,2,[1,0,0,1])]563sage: MatrixGroup(gens).list()564[[1 0]565[0 1]]566567Another example over a ring (see trac 9437)::568569sage: len(SL(2, Zmod(4)).list())57048571572An error is raised if the group is not finite::573574sage: GL(2,ZZ).list()575Traceback (most recent call last):576...577ValueError: group must be finite578"""579# We check the cache for the result580try:581return list(self.__list)582except AttributeError:583pass584if not self.is_finite():585raise ValueError, "group must be finite"586587MS = self.matrix_space()588R = self.base_ring()589if not R.is_field() or not R.is_finite():590s = list(self._gap_().Elements())591v = [self.element_class(x._matrix_(R), self, check=False) for x in s]592self.__list = v593return list(v)594595# Get basic properties of the field over which we are working596F = self.field_of_definition()597n = F.degree()598p = F.characteristic()599a = F.prime_subfield().multiplicative_generator()600b = F.multiplicative_generator()601602# Get string representation of the list of elements of self.603# Since the output is usually big, we use a file, which can604# easily give us a hundred-times speedup for at all large output.605s = self._gap_().Elements().str(use_file=True)606s = ''.join(s.split())607608# Replace the two types of gap-style 'power of generator' notation609s = s.replace('Z(%s^%s)'%(p,n),'b')610s = s.replace('Z(%s)'%p,'a')611s = s.replace('^','**')612# Then eval the string with a and b set to the corresponding613# multiplicative generators.614v = eval(s, {'a':a, 'b':b})615616# Finally, create the matrix space in which all these matrices live,617# and make each element as a MatrixGroupElement.618v = [self.element_class(MS(x), self, check=False) for x in v]619self.__list = v620return list(v)621622def irreducible_characters(self):623"""624Returns the list of irreducible characters of the group.625626EXAMPLES::627628sage: G = GL(2,2)629sage: G.irreducible_characters()630[Character of General Linear Group of degree 2 over Finite Field of size 2,631Character of General Linear Group of degree 2 over Finite Field of size 2,632Character of General Linear Group of degree 2 over Finite Field of size 2]633634"""635current_randstate().set_seed_gap()636Irr = self._gap_().Irr()637L = []638for irr in Irr:639L.append(ClassFunction(self,irr))640return L641642class MatrixGroup_gap_finite_field(MatrixGroup_gap):643"""644Python class for matrix groups over a finite field.645"""646def cardinality(self):647"""648EXAMPLES::649650sage: G = Sp(4,GF(3))651sage: G.cardinality()65251840653sage: G = SL(4,GF(3))654sage: G.cardinality()65512130560656sage: F = GF(5); MS = MatrixSpace(F,2,2)657sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]658sage: G = MatrixGroup(gens)659sage: G.cardinality()660480661sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])662sage: G.cardinality()663+Infinity664"""665return integer.Integer(gap(self).Size())666667def random_element(self):668"""669Return a random element of this group.670671EXAMPLES::672673sage: G = Sp(4,GF(3))674sage: G.random_element() # random675[2 1 1 1]676[1 0 2 1]677[0 1 1 0]678[1 0 0 1]679sage: G.random_element() in G680True681682::683684sage: F = GF(5); MS = MatrixSpace(F,2,2)685sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]686sage: G = MatrixGroup(gens)687sage: G.random_element() # random688[1 3]689[0 3]690sage: G.random_element() in G691True692"""693# Note: even with fixed random seed, the Random() element694# returned by gap does depend on execution order and695# architecture. Presumably due to different memory loctions.696current_randstate().set_seed_gap()697F = self.field_of_definition()698return self.element_class(gap(self).Random()._matrix_(F), self, check=False)699700def random(self):701"""702Deprecated. Use self.random_element() instead.703"""704raise NotImplementedError, "Deprecated: use random_element() instead"705706707def __contains__(self, x):708"""709Return True if `x` is an element of this abelian group.710711EXAMPLES::712713sage: F = GF(5); MS = MatrixSpace(F,2,2)714sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])715sage: G716Matrix group over Finite Field of size 5 with 2 generators:717[[[1, 0], [0, 1]], [[1, 2], [3, 4]]]718sage: G.cardinality()7198720sage: G(1)721[1 0]722[0 1]723sage: G.1 in G724True725sage: 1 in G726True727sage: [1,2,3,4] in G728True729sage: matrix(GF(5),2,[1,2,3,5]) in G730False731sage: G(matrix(GF(5),2,[1,2,3,5]))732Traceback (most recent call last):733...734TypeError: no way to coerce element to self.735"""736if isinstance(x, self.element_class):737if x.parent() == self:738return True739return gap(x) in gap(self)740try:741self(x)742return True743except TypeError:744return False745746def conjugacy_class_representatives(self):747"""748Return a set of representatives for each of the conjugacy classes749of the group.750751EXAMPLES::752753sage: G = SU(3,GF(2))754sage: len(G.conjugacy_class_representatives())75516756sage: len(GL(2,GF(3)).conjugacy_class_representatives())7578758sage: len(GU(2,GF(5)).conjugacy_class_representatives())75936760"""761current_randstate().set_seed_gap()762try:763return self.__reps764except AttributeError:765pass766G = self._gap_().ConjugacyClasses()767reps = list(gap.List(G, 'x -> Representative(x)'))768F = self.field_of_definition()769self.__reps = Sequence([self(g._matrix_(F)) for g in reps], cr=True, universe=self, check=False)770return self.__reps771772def center(self):773"""774Return the center of this linear group as a matrix group.775776EXAMPLES::777778sage: G = SU(3,GF(2))779sage: G.center()780Matrix group over Finite Field in a of size 2^2 with 1 generators:781[[[a, 0, 0], [0, a, 0], [0, 0, a]]]782sage: GL(2,GF(3)).center()783Matrix group over Finite Field of size 3 with 1 generators:784[[[2, 0], [0, 2]]]785sage: GL(3,GF(3)).center()786Matrix group over Finite Field of size 3 with 1 generators:787[[[2, 0, 0], [0, 2, 0], [0, 0, 2]]]788sage: GU(3,GF(2)).center()789Matrix group over Finite Field in a of size 2^2 with 1 generators:790[[[a + 1, 0, 0], [0, a + 1, 0], [0, 0, a + 1]]]791sage: A=Matrix(FiniteField(5), [[2,0,0], [0,3,0], [0,0,1]])792sage: B=Matrix(FiniteField(5), [[1,0,0], [0,1,0], [0,1,1]])793sage: MatrixGroup([A,B]).center()794Matrix group over Finite Field of size 5 with 1 generators:795[[[1, 0, 0], [0, 1, 0], [0, 0, 1]]]796"""797try:798return self.__center799except AttributeError:800pass801G = list(self._gap_().Center().GeneratorsOfGroup())802from sage.groups.matrix_gps.matrix_group import MatrixGroup803if len(G) == 0:804self.__center = MatrixGroup([self.one()])805else:806F = self.field_of_definition()807self.__center = MatrixGroup([g._matrix_(F) for g in G])808return self.__center809810811class MatrixGroup_gens(MatrixGroup_gap):812"""813EXAMPLES:814815A ValueError is raised if one of the generators is not invertible.816817::818819sage: F = GF(5); MS = MatrixSpace(F,2,2)820sage: G = MatrixGroup([MS.0])821Traceback (most recent call last):822...823ValueError: each generator must be an invertible matrix but one is not:824[1 0]825[0 0]826"""827def __init__(self, gensG, category = None):828v = Sequence(gensG, immutable=True)829M = v.universe()830if not is_MatrixSpace(M):831raise TypeError, "universe of sequence (=%s) of generators must be a matrix space"%M832if M.nrows() != M.ncols():833raise ValueError, "matrices must be square."834for x in v:835if not x.is_invertible():836raise ValueError, "each generator must be an invertible matrix but one is not:\n%s"%x837self._gensG = v838MatrixGroup_gap.__init__(self, M.nrows(), M.base_ring(), category = category)839840@rename_keyword(deprecated='Sage version 4.6', method="algorithm")841def as_permutation_group(self, algorithm=None):842r"""843Return a permutation group representation for the group.844845In most cases occurring in practice, this is a permutation846group of minimal degree (the degree begin determined from847orbits under the group action). When these orbits are hard to848compute, the procedure can be time-consuming and the degree849may not be minimal.850851INPUT:852853- ``algorithm`` -- ``None`` or ``'smaller'``. In the latter854case, try harder to find a permutation representation of855small degree.856857OUTPUT:858859A permutation group isomorphic to ``self``. The860``algorithm='smaller'`` option tries to return an isomorphic861group of low degree, but is not guaranteed to find the862smallest one.863864EXAMPLES::865866sage: MS = MatrixSpace(GF(2), 5, 5)867sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]])868sage: G = MatrixGroup([A])869sage: G.as_permutation_group()870Permutation Group with generators [(1,2)]871sage: MS = MatrixSpace( GF(7), 12, 12)872sage: GG = gap("ImfMatrixGroup( 12, 3 )")873sage: GG.GeneratorsOfGroup().Length()8743875sage: g1 = MS(eval(str(GG.GeneratorsOfGroup()[1]).replace("\n","")))876sage: g2 = MS(eval(str(GG.GeneratorsOfGroup()[2]).replace("\n","")))877sage: g3 = MS(eval(str(GG.GeneratorsOfGroup()[3]).replace("\n","")))878sage: G = MatrixGroup([g1, g2, g3])879sage: G.cardinality()88021499084800881sage: set_random_seed(0); current_randstate().set_seed_gap()882sage: P = G.as_permutation_group()883sage: P.cardinality()88421499084800885sage: P.degree() # random output886144887sage: set_random_seed(3); current_randstate().set_seed_gap()888sage: Psmaller = G.as_permutation_group(algorithm="smaller")889sage: Psmaller.cardinality()89021499084800891sage: Psmaller.degree() # random output892108893894In this case, the "smaller" option returned an isomorphic group of895lower degree. The above example used GAP's library of irreducible896maximal finite ("imf") integer matrix groups to construct the897MatrixGroup G over GF(7). The section "Irreducible Maximal Finite898Integral Matrix Groups" in the GAP reference manual has more899details.900"""901# Note that the output of IsomorphismPermGroup() depends on902# memory locations and will change if you change the order of903# doctests and/or architecture904from sage.groups.perm_gps.permgroup import PermutationGroup905if not self.is_finite():906raise NotImplementedError, "Group must be finite."907n = self.degree()908MS = MatrixSpace(self.base_ring(), n, n)909mats = [] # initializing list of mats by which the gens act on self910for g in self.gens():911p = MS(g.matrix())912m = p.rows()913mats.append(m)914mats_str = str(gap([[list(r) for r in m] for m in mats]))915gap.eval("iso:=IsomorphismPermGroup(Group("+mats_str+"))")916if algorithm == "smaller":917gap.eval("small:= SmallerDegreePermutationRepresentation( Image( iso ) );")918C = gap("Image( small )")919else:920C = gap("Image( iso )")921return PermutationGroup(gap_group=C)922923@rename_keyword(deprecated='Sage version 4.6', method="algorithm")924def module_composition_factors(self, algorithm=None):925r"""926Returns a list of triples consisting of [base field, dimension,927irreducibility], for each of the Meataxe composition factors928modules. The algorithm="verbose" option returns more information, but929in Meataxe notation.930931EXAMPLES::932933sage: F=GF(3);MS=MatrixSpace(F,4,4)934sage: M=MS(0)935sage: M[0,1]=1;M[1,2]=1;M[2,3]=1;M[3,0]=1936sage: G = MatrixGroup([M])937sage: G.module_composition_factors()938[(Finite Field of size 3, 1, True),939(Finite Field of size 3, 1, True),940(Finite Field of size 3, 2, True)]941sage: F = GF(7); MS = MatrixSpace(F,2,2)942sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])]943sage: G = MatrixGroup(gens)944sage: G.module_composition_factors()945[(Finite Field of size 7, 2, True)]946947Type "G.module_composition_factors(algorithm='verbose')" to get a948more verbose version.949950For more on MeatAxe notation, see951http://www.gap-system.org/Manuals/doc/htm/ref/CHAP067.htm952"""953from sage.misc.sage_eval import sage_eval954F = self.base_ring()955if not(F.is_finite()):956raise NotImplementedError, "Base ring must be finite."957q = F.cardinality()958gens = self.gens()959n = self.degree()960MS = MatrixSpace(F,n,n)961mats = [] # initializing list of mats by which the gens act on self962W = self.matrix_space().row_space()963for g in gens:964p = MS(g.matrix())965m = p.rows()966mats.append(m)967mats_str = str(gap([[list(r) for r in m] for m in mats]))968gap.eval("M:=GModuleByMats("+mats_str+", GF("+str(q)+"))")969gap.eval("MCFs := MTX.CompositionFactors( M )")970N = eval(gap.eval("Length(MCFs)"))971if algorithm == "verbose":972print gap.eval('MCFs')+"\n"973L = []974for i in range(1,N+1):975gap.eval("MCF := MCFs[%s]"%i)976L.append(tuple([sage_eval(gap.eval("MCF.field")),977eval(gap.eval("MCF.dimension")),978sage_eval(gap.eval("MCF.IsIrreducible")) ]))979return sorted(L)980981def gens(self):982"""983EXAMPLES::984985sage: F = GF(3); MS = MatrixSpace(F,2,2)986sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]987sage: G = MatrixGroup(gens)988sage: gens[0] in G989True990sage: gens = G.gens()991sage: gens[0] in G992True993sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]994995::996997sage: F = GF(5); MS = MatrixSpace(F,2,2)998sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])999sage: G1000Matrix group over Finite Field of size 5 with 2 generators:1001[[[1, 0], [0, 1]], [[1, 2], [3, 4]]]1002sage: G.gens()1003[[1 0]1004[0 1], [1 2]1005[3 4]]1006"""1007try:1008return self.__gens1009except AttributeError:1010t = Sequence([self.element_class(x, self) for x in self._gensG],1011immutable=True, universe=self)1012self.__gens = t1013return t10141015def _gap_init_(self):1016"""1017Returns a string representation of the corresponding GAP object.10181019EXAMPLES::10201021sage: F = GF(5); MS = MatrixSpace(F,2,2)1022sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]1023sage: G = MatrixGroup(gens)1024sage: G._gap_init_() # The variable $sage11 belongs to gap(F) and is somehow random1025'Group([[Z(5)^0,Z(5)^1],[Z(5)^2,Z(5)^0]]*One($sage11),[[Z(5)^0,Z(5)^0],[0*Z(5),Z(5)^0]]*One($sage11))'1026sage: gap(G._gap_init_())1027Group([ [ [ Z(5)^0, Z(5) ], [ Z(5)^2, Z(5)^0 ] ],1028[ [ Z(5)^0, Z(5)^0 ], [ 0*Z(5), Z(5)^0 ] ] ])1029"""1030gens_gap = ','.join([x._gap_init_() for x in self._gensG])1031return 'Group(%s)'%gens_gap10321033def _repr_(self):1034"""1035EXAMPLES::10361037sage: F = GF(5); MS = MatrixSpace(F,2,2)1038sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]1039sage: G = MatrixGroup(gens)1040sage: G1041Matrix group over Finite Field of size 5 with 2 generators:1042[[[1, 2], [4, 1]], [[1, 1], [0, 1]]]1043"""1044gns = [x.list() for x in self.gens()]1045return "Matrix group over %s with %s generators: \n %s"%(self.base_ring(), self.ngens(), gns)10461047def _latex_(self):1048r"""1049EXAMPLES::10501051sage: F = GF(5); MS = MatrixSpace(F,2,2)1052sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]1053sage: G = MatrixGroup(gens)1054sage: latex(G)1055\left\langle \left(\begin{array}{rr}10561 & 2 \\10574 & 11058\end{array}\right), \left(\begin{array}{rr}10591 & 1 \\10600 & 11061\end{array}\right) \right\rangle1062"""1063gens = ', '.join([latex(x) for x in self.gens()])1064return '\\left\\langle %s \\right\\rangle'%gens10651066def invariant_generators(self):1067"""1068Wraps Singular's invariant_algebra_reynolds and invariant_ring1069in finvar.lib, with help from Simon King and Martin Albrecht.1070Computes generators for the polynomial ring1071`F[x_1,\ldots,x_n]^G`, where G in GL(n,F) is a finite1072matrix group.10731074In the "good characteristic" case the polynomials returned form a1075minimal generating set for the algebra of G-invariant polynomials.1076In the "bad" case, the polynomials returned are primary and1077secondary invariants, forming a not necessarily minimal generating1078set for the algebra of G-invariant polynomials.10791080EXAMPLES::10811082sage: F = GF(7); MS = MatrixSpace(F,2,2)1083sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])]1084sage: G = MatrixGroup(gens)1085sage: G.invariant_generators()1086[x1^7*x2 - x1*x2^7, x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12, x1^18 + 2*x1^15*x2^3 + 3*x1^12*x2^6 + 3*x1^6*x2^12 - 2*x1^3*x2^15 + x2^18]1087sage: q = 4; a = 21088sage: MS = MatrixSpace(QQ, 2, 2)1089sage: gen1 = [[1/a,(q-1)/a],[1/a, -1/a]]; gen2 = [[1,0],[0,-1]]; gen3 = [[-1,0],[0,1]]1090sage: G = MatrixGroup([MS(gen1),MS(gen2),MS(gen3)])1091sage: G.cardinality()1092121093sage: G.invariant_generators()1094[x1^2 + 3*x2^2, x1^6 + 15*x1^4*x2^2 + 15*x1^2*x2^4 + 33*x2^6]1095sage: F = GF(5); MS = MatrixSpace(F,2,2)1096sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[-1,1]])]1097sage: G = MatrixGroup(gens)1098sage: G.invariant_generators() # long time (67s on sage.math, 2012)1099[x1^20 + x1^16*x2^4 + x1^12*x2^8 + x1^8*x2^12 + x1^4*x2^16 + x2^20, x1^20*x2^4 + x1^16*x2^8 + x1^12*x2^12 + x1^8*x2^16 + x1^4*x2^20]1100sage: F=CyclotomicField(8)1101sage: z=F.gen()1102sage: a=z+1/z1103sage: b=z^21104sage: MS=MatrixSpace(F,2,2)1105sage: g1=MS([[1/a,1/a],[1/a,-1/a]])1106sage: g2=MS([[1,0],[0,b]])1107sage: g3=MS([[b,0],[0,1]])1108sage: G=MatrixGroup([g1,g2,g3])1109sage: G.invariant_generators() # long time (12s on sage.math, 2011)1110[x1^8 + 14*x1^4*x2^4 + x2^8,1111x1^24 + 10626/1025*x1^20*x2^4 + 735471/1025*x1^16*x2^8 + 2704156/1025*x1^12*x2^12 + 735471/1025*x1^8*x2^16 + 10626/1025*x1^4*x2^20 + x2^24]11121113AUTHORS:11141115- David Joyner, Simon King and Martin Albrecht.11161117REFERENCES:11181119- Singular reference manual11201121- B. Sturmfels, "Algorithms in invariant theory", Springer-Verlag, 1993.11221123- S. King, "Minimal Generating Sets of non-modular invariant rings of1124finite groups", arXiv:math.AC/07030351125"""1126from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing1127from sage.interfaces.singular import singular1128gens = self.gens()1129singular.LIB("finvar.lib")1130n = self.degree() #len((gens[0].matrix()).rows())1131F = self.base_ring()1132q = F.characteristic()1133## test if the field is admissible1134if F.gen()==1: # we got the rationals or GF(prime)1135FieldStr = str(F.characteristic())1136elif hasattr(F,'polynomial'): # we got an algebraic extension1137if len(F.gens())>1:1138raise NotImplementedError, "can only deal with finite fields and (simple algebraic extensions of) the rationals"1139FieldStr = '(%d,%s)'%(F.characteristic(),str(F.gen()))1140else: # we have a transcendental extension1141FieldStr = '(%d,%s)'%(F.characteristic(),','.join([str(p) for p in F.gens()]))11421143## Setting Singular's variable names1144## We need to make sure that field generator and variables get different names.1145if str(F.gen())[0]=='x':1146VarStr = 'y'1147else:1148VarStr = 'x'1149VarNames='('+','.join((VarStr+str(i+1) for i in range(n)))+')'1150R=singular.ring(FieldStr,VarNames,'dp')1151if hasattr(F,'polynomial') and F.gen()!=1: # we have to define minpoly1152singular.eval('minpoly = '+str(F.polynomial()).replace('x',str(F.gen())))1153A = [singular.matrix(n,n,str((x.matrix()).list())) for x in gens]1154Lgens = ','.join((x.name() for x in A))1155PR = PolynomialRing(F,n,[VarStr+str(i) for i in range(1,n+1)])1156if q == 0 or (q > 0 and self.cardinality()%q != 0):1157from sage.all import Integer, Matrix1158try:1159gapself = gap(self)1160# test whether the backwards transformation works as well:1161for i in range(self.ngens()):1162if Matrix(gapself.gen(i+1),F) != self.gen(i).matrix():1163raise ValueError1164except (TypeError,ValueError):1165gapself is None1166if gapself is not None:1167ReyName = 't'+singular._next_var_name()1168singular.eval('matrix %s[%d][%d]'%(ReyName,self.cardinality(),n))1169En = gapself.Enumerator()1170for i in range(1,self.cardinality()+1):1171M = Matrix(En[i],F)1172D = [{} for foobar in range(self.degree())]1173for x,y in M.dict().items():1174D[x[0]][x[1]] = y1175for row in range(self.degree()):1176for t in D[row].items():1177singular.eval('%s[%d,%d]=%s[%d,%d]+(%s)*var(%d)'%(ReyName,i,row+1,ReyName,i,row+1, repr(t[1]),t[0]+1))1178foobar = singular(ReyName)1179IRName = 't'+singular._next_var_name()1180singular.eval('matrix %s = invariant_algebra_reynolds(%s)'%(IRName,ReyName))1181else:1182ReyName = 't'+singular._next_var_name()1183singular.eval('list %s=group_reynolds((%s))'%(ReyName,Lgens))1184IRName = 't'+singular._next_var_name()1185singular.eval('matrix %s = invariant_algebra_reynolds(%s[1])'%(IRName,ReyName))11861187OUT = [singular.eval(IRName+'[1,%d]'%(j)) for j in range(1,1+singular('ncols('+IRName+')'))]1188return [PR(gen) for gen in OUT]1189if self.cardinality()%q == 0:1190PName = 't'+singular._next_var_name()1191SName = 't'+singular._next_var_name()1192singular.eval('matrix %s,%s=invariant_ring(%s)'%(PName,SName,Lgens))1193OUT = [singular.eval(PName+'[1,%d]'%(j)) for j in range(1,1+singular('ncols('+PName+')'))] + [singular.eval(SName+'[1,%d]'%(j)) for j in range(2,1+singular('ncols('+SName+')'))]1194return [PR(gen) for gen in OUT]119511961197class MatrixGroup_gens_finite_field(MatrixGroup_gens, MatrixGroup_gap_finite_field):1198pass11991200## def conjugacy_class_representatives_gap(self):1201## """1202## Wraps GAP Representative+ConjugactClasses but returns a list of1203## strings representing the GAP matrices which form a complete1204## set of representatives of the conjugacy classes of the group.12051206## EXAMPLES:1207## sage: F = GF(3); MS = MatrixSpace(F,2,2)1208## sage: gens = [MS([[1,0],[-1,1]]),MS([[1,1],[0,1]])]1209## sage: G = MatrixGroup(gens)1210## sage: G.conjugacy_class_representatives_gap()1211## ['[ [ Z(3)^0, 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]',1212## '[ [ 0*Z(3), Z(3)^0 ], [ Z(3), Z(3)^0 ] ]',1213## '[ [ 0*Z(3), Z(3)^0 ], [ Z(3), Z(3) ] ]',1214## '[ [ 0*Z(3), Z(3) ], [ Z(3)^0, Z(3)^0 ] ]',1215## '[ [ 0*Z(3), Z(3) ], [ Z(3)^0, Z(3) ] ]',1216## '[ [ 0*Z(3), Z(3)^0 ], [ Z(3), 0*Z(3) ] ]',1217## '[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3) ] ]']12181219## AUTHOR: David Joyner (1-2006)1220## """1221## F = self.__R1222## deg = self.__n1223## gp_gens = self.gens()1224## L = [gap(A) for A in gp_gens]1225## sL = ','.join(str(x) for x in L)1226## if is_FiniteField(F):1227## q = F.cardinality()1228## gap.eval("cl:=ConjugacyClasses(Group(["+sL+"]))")1229## m = eval(gap.eval("Length(cl)"))1230## gap.eval("reps:=List(cl,x->Representative(x))")1231## sreps = [gap.eval("reps["+str(i+1)+"]") for i in range(m)]1232## return sreps1233## raise TypeError, "R (=%s) must be a finite field"%R123412351236123712381239