Path: blob/master/sage/groups/matrix_gps/matrix_group_element.py
4056 views
"""1Matrix Group Elements23AUTHORS:45- David Joyner (2006-05): initial version David Joyner67- David Joyner (2006-05): various modifications to address William8Stein's TODO's.910- William Stein (2006-12-09): many revisions.1112EXAMPLES::1314sage: F = GF(3); MS = MatrixSpace(F,2,2)15sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]16sage: G = MatrixGroup(gens); G17Matrix group over Finite Field of size 3 with 2 generators:18[[[1, 0], [0, 1]], [[1, 1], [0, 1]]]19sage: g = G([[1,1],[0,1]])20sage: h = G([[1,2],[0,1]])21sage: g*h22[1 0]23[0 1]2425You cannot add two matrices, since this is not a group operation.26You can coerce matrices back to the matrix space and add them27there::2829sage: g + h30Traceback (most recent call last):31...32TypeError: unsupported operand type(s) for +: 'MatrixGroup_gens_finite_field_with_category.element_class' and 'MatrixGroup_gens_finite_field_with_category.element_class'3334::3536sage: g.matrix() + h.matrix()37[2 0]38[0 2]3940::4142sage: 2*g43Traceback (most recent call last):44...45TypeError: unsupported operand parent(s) for '*': 'Integer Ring' and 'Matrix group over Finite Field of size 3 with 2 generators:46[[[1, 0], [0, 1]], [[1, 1], [0, 1]]]'47sage: 2*g.matrix()48[2 2]49[0 2]50"""5152#*****************************************************************************53# Copyright (C) 2006 David Joyner and William Stein <[email protected]>54#55# Distributed under the terms of the GNU General Public License (GPL)56#57# http://www.gnu.org/licenses/58#*****************************************************************************5960from sage.rings.all import Integer, Infinity61from sage.interfaces.gap import gap62import sage.structure.element as element63from sage.matrix.matrix import Matrix64from sage.structure.factorization import Factorization65from sage.structure.sage_object import have_same_parent6667def is_MatrixGroupElement(x):68return isinstance(x, MatrixGroupElement)6970class MatrixGroupElement(element.MultiplicativeGroupElement):71"""72An element of a matrix group.7374EXAMPLES::7576sage: F = GF(3); MS = MatrixSpace(F,2,2)77sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]78sage: G = MatrixGroup(gens)79sage: g = G.random_element()80sage: type(g)81<class 'sage.groups.matrix_gps.matrix_group_element.MatrixGroup_gens_finite_field_with_category.element_class'>82"""83def __init__(self, g, parent, check = True):84r"""85Create element of a matrix group.8687INPUT:888990- ``g`` - a Matrix9192- ``parent`` - defines parent group (g must be in93parent or a TypeError is raised).9495- ``check`` - bool (default: True), if true does some96type checking.979899TESTS::100101sage: F = GF(3); MS = MatrixSpace(F,2,2)102sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]103sage: G = MatrixGroup(gens)104sage: g = G.random_element()105sage: TestSuite(g).run()106"""107if check:108if not isinstance(g, Matrix):109raise TypeError, "g must be a matrix"110if not (g.parent() is parent):111g = parent.matrix_space()(g)112element.Element.__init__(self, parent)113self.__mat = g114115def matrix(self):116"""117Obtain the usual matrix (as an element of a matrix space)118associated to this matrix group element.119120One reason to compute the associated matrix is that matrices121support a huge range of functionality.122123EXAMPLES::124125sage: k = GF(7); G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])])126sage: g = G.0127sage: g.matrix()128[1 1]129[0 1]130sage: parent(g.matrix())131Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7132133Matrices have extra functionality that matrix group elements do not134have.135136::137138sage: g.matrix().charpoly('t')139t^2 + 5*t + 1140"""141return self.__mat.__copy__()142143def _gap_init_(self):144"""145Return a string representation of a Gap object corresponding to146this matrix group element.147148EXAMPLES::149150sage: k = GF(7); G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])]); g = G.1151sage: g._gap_init_() # The variable $sage27 belongs to gap(k) and is somehow random152'[[Z(7)^0,0*Z(7)],[0*Z(7),Z(7)^2]]*One($sage27)'153sage: gap(g._gap_init_())154[ [ Z(7)^0, 0*Z(7) ], [ 0*Z(7), Z(7)^2 ] ]155156It may be better to use gap(the matrix), since the result is157cached.158159::160161sage: gap(G.1)162[ [ Z(7)^0, 0*Z(7) ], [ 0*Z(7), Z(7)^2 ] ]163sage: gap(G.1).IsMatrix()164true165"""166return self.__mat._gap_init_()167168def _gap_latex_(self):169r"""170Return the GAP latex version of this matrix.171172AUTHORS:173174- S. Kohl: Wrote the GAP function.175176EXAMPLES::177178sage: F = GF(3); MS = MatrixSpace(F,2,2)179sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]180sage: G = MatrixGroup(gens)181sage: g = G([[1, 1], [0, 1]])182sage: print g._gap_latex_()183\left(\begin{array}{rr}%184Z(3)^{0}&Z(3)^{0}\\%1850*Z(3)&Z(3)^{0}\\%186\end{array}\right)%187188Type view(g._latex_()) to see the object in an xdvi window189(assuming you have latex and xdvi installed).190"""191s1 = self.__mat._gap_init_()192s2 = gap.eval("LaTeX("+s1+")")193return eval(s2)194195def _repr_(self):196"""197Return string representation of this matrix.198199EXAMPLES::200201sage: F = GF(3); MS = MatrixSpace(F,2,2)202sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]203sage: G = MatrixGroup(gens)204sage: g = G([[1, 1], [0, 1]])205sage: g # indirect doctest206[1 1]207[0 1]208"""209return str(self.__mat)210211def _latex_(self):212r"""213EXAMPLES::214215sage: F = GF(3); MS = MatrixSpace(F,2,2)216sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]217sage: G = MatrixGroup(gens)218sage: g = G([[1, 1], [0, 1]])219sage: print g._latex_()220\left(\begin{array}{rr}2211 & 1 \\2220 & 1223\end{array}\right)224225Type ``view(g._latex_())`` to see the object in an226xdvi window (assuming you have latex and xdvi installed).227"""228return self.__mat._latex_()229230def _mul_(self,other):231"""232Return the product of self and other, which must have identical233parents.234235EXAMPLES::236237sage: F = GF(3); MS = MatrixSpace(F,2)238sage: gens = [MS([1,0, 0,1]), MS([1,1, 0,1])]239sage: G = MatrixGroup(gens)240sage: g = G([1,1, 0,1])241sage: h = G([1,1, 0,1])242sage: g*h # indirect doctest243[1 2]244[0 1]245"""246parent = self.parent()247return parent.element_class(self.__mat * other.__mat, parent, check=False)248249def _act_on_(self, x, self_on_left):250"""251EXAMPLES::252253sage: G = GL(4,7)254sage: G.0 * vector([1,2,3,4])255(3, 2, 3, 4)256sage: v = vector(GF(7), [3,2,1,-1])257sage: g = G.1258sage: v * g == v * g.matrix() # indirect doctest259True260"""261if not is_MatrixGroupElement(x) and x not in self.parent().base_ring():262try:263if self_on_left:264return self.matrix() * x265else:266return x * self.matrix()267except TypeError:268return None269270def __invert__(self):271parent = self.parent()272return parent.element_class(~self.__mat, parent, check=False)273274def __cmp__(self, other):275"""276EXAMPLES::277278sage: F = GF(3); MS = MatrixSpace(F,2)279sage: gens = [MS([1,0, 0,1]), MS([1,1, 0,1])]280sage: G = MatrixGroup(gens)281sage: g = G([1,1, 0,1])282sage: h = G([1,1, 0,1])283sage: g == h284True285"""286return cmp(self.__mat, other.__mat)287288def __eq__(self, other):289"""290EXAMPLES::291292sage: F = GF(3); MS = MatrixSpace(F,2)293sage: gens = [MS([1,0, 0,1]), MS([1,1, 0,1])]294sage: G = MatrixGroup(gens)295sage: H = MatrixGroup(gens)296sage: g = G([1,1, 0,1])297sage: h = H([1,1, 0,1])298sage: g == h299True300"""301return have_same_parent(self, other) and self.__mat == other.__mat302303def __ne__(self, other):304"""305EXAMPLES::306307sage: F = GF(3); MS = MatrixSpace(F,2)308sage: gens = [MS([1,0, 0,1]), MS([1,1, 0,1])]309sage: G = MatrixGroup(gens)310sage: H = MatrixGroup(gens)311sage: g = G([1,1, 0,1])312sage: h = H([1,1, 0,1])313sage: g != h314False315"""316return not self.__eq__(other)317318def order(self):319"""320Return the order of this group element, which is the smallest321positive integer `n` such that `g^n = 1`, or322+Infinity if no such integer exists.323324EXAMPLES::325326sage: k = GF(7); G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])])327sage: G328Matrix group over Finite Field of size 7 with 2 generators:329[[[1, 1], [0, 1]], [[1, 0], [0, 2]]]330sage: G.order()33121332333See trac #1170334335::336337sage: gl=GL(2,ZZ); gl338General Linear Group of degree 2 over Integer Ring339sage: g=gl.gens()[2]; g340[1 1]341[0 1]342sage: g.order()343+Infinity344"""345try:346return self.__order347except AttributeError:348try:349self.__order = Integer(self._gap_().Order())350except TypeError:351self.__order = Infinity352return self.__order353354def word_problem(self, gens=None):355r"""356Write this group element in terms of the elements of the list357``gens``, or the standard generators of the parent of self if358``gens`` is None.359360INPUT:361362- ``gens`` - a list of elements that can be coerced into the parent of363self, or None.364365ALGORITHM: Use GAP, which has optimized algorithms for solving the366word problem (the GAP functions EpimorphismFromFreeGroup and367PreImagesRepresentative).368369EXAMPLE::370371sage: G = GL(2,5); G372General Linear Group of degree 2 over Finite Field of size 5373sage: G.gens()374[375[2 0]376[0 1],377[4 1]378[4 0]379]380sage: G(1).word_problem([G.1, G.0])3811382383Next we construct a more complicated element of the group from the384generators::385386sage: s,t = G.0, G.1387sage: a = (s * t * s); b = a.word_problem(); b388([2 0]389[0 1]) *390([4 1]391[4 0]) *392([2 0]393[0 1])394sage: b.prod() == a395True396397We solve the word problem using some different generators::398399sage: s = G([2,0,0,1]); t = G([1,1,0,1]); u = G([0,-1,1,0])400sage: a.word_problem([s,t,u])401([2 0]402[0 1])^-1 *403([1 1]404[0 1])^-1 *405([0 4]406[1 0]) *407([2 0]408[0 1])^-1409410We try some elements that don't actually generate the group::411412sage: a.word_problem([t,u])413Traceback (most recent call last):414...415ValueError: Could not solve word problem416417AUTHORS:418419- David Joyner and William Stein420- David Loeffler (2010): fixed some bugs421"""422G = self.parent()423gg = gap(G)424if not gens:425gens = gg.GeneratorsOfGroup()426else:427gens = gap([G(x) for x in gens])428H = gens.Group()429hom = H.EpimorphismFromFreeGroup()430in_terms_of_gens = str(hom.PreImagesRepresentative(self))431if 'identity' in in_terms_of_gens:432return Factorization([])433elif in_terms_of_gens == 'fail':434raise ValueError, "Could not solve word problem"435v = list(H.GeneratorsOfGroup())436F = G.field_of_definition()437w = [G(x._matrix_(F)) for x in v]438factors = [Factorization([(x,1)]) for x in w]439d = dict([('x%s'%(i+1),factors[i]) for i in range(len(factors))])440441from sage.misc.sage_eval import sage_eval442F = sage_eval(str(in_terms_of_gens), d)443F._set_cr(True)444return F445446def list(self):447"""448Return list representation of this matrix.449450EXAMPLES::451452sage: F = GF(3); MS = MatrixSpace(F,2,2)453sage: gens = [MS([[1,0],[0,1]]),MS([[1,1],[0,1]])]454sage: G = MatrixGroup(gens)455sage: g = G.0456sage: g.list()457[[1, 0], [0, 1]]458"""459rws = (self.__mat).rows()460lrws = [list(x) for x in rws]461return lrws462463464465466