Path: blob/master/src/sage/groups/matrix_gps/morphism.py
8815 views
"""1Homomorphisms Between Matrix Groups23AUTHORS:45- David Joyner and William Stein (2006-03): initial version67- David Joyner (2006-05): examples89- Simon King (2011-01): cleaning and improving code1011- Volker Braun (2013-1) port to new Parent, libGAP.12"""1314#*****************************************************************************15# Copyright (C) 2006 David Joyner and William Stein <[email protected]>16#17# Distributed under the terms of the GNU General Public License (GPL)18# as published by the Free Software Foundation; either version 2 of19# the License, or (at your option) any later version.20# http://www.gnu.org/licenses/21#*****************************************************************************2223from sage.categories.morphism import Morphism24from sage.misc.latex import latex252627def to_libgap(x):28"""29Helper to convert ``x`` to a LibGAP matrix or matrix group30element.3132EXAMPLES::3334sage: from sage.groups.matrix_gps.morphism import to_libgap35sage: to_libgap(GL(2,3).gen(0))36[ [ Z(3), 0*Z(3) ], [ 0*Z(3), Z(3)^0 ] ]37sage: to_libgap(matrix(QQ, [[1,2],[3,4]]))38[ [ 1, 2 ], [ 3, 4 ] ]39"""40try:41return x.gap()42except AttributeError:43from sage.libs.gap.libgap import libgap44return libgap(x)454647class MatrixGroupMap(Morphism):4849def __init__(self, parent):50"""51Set-theoretic map between matrix groups.5253EXAMPLES::5455sage: from sage.groups.matrix_gps.morphism import MatrixGroupMap56sage: MatrixGroupMap(ZZ.Hom(ZZ)) # mathematical nonsense57MatrixGroup endomorphism of Integer Ring58"""59Morphism.__init__(self, parent)6061def _repr_type(self):62"""63Part of the implementation of :meth:`_repr_`6465EXAMPLES::6667sage: from sage.groups.matrix_gps.morphism import MatrixGroupMap68sage: MatrixGroupMap(ZZ.Hom(ZZ))._repr_type()69'MatrixGroup'70"""71return "MatrixGroup"727374class MatrixGroupMorphism(MatrixGroupMap):75pass767778class MatrixGroupMorphism_im_gens(MatrixGroupMorphism):7980def __init__(self, homset, imgsH, check=True):81"""82Group morphism specified by images of generators.8384Some Python code for wrapping GAP's GroupHomomorphismByImages85function but only for matrix groups. Can be expensive if G is86large.8788EXAMPLES::8990sage: F = GF(5); MS = MatrixSpace(F,2,2)91sage: G = MatrixGroup([MS([1,1,0,1])])92sage: H = MatrixGroup([MS([1,0,1,1])])93sage: phi = G.hom(H.gens())94sage: phi95Homomorphism : Matrix group over Finite Field of size 5 with 1 generators (96[1 1]97[0 1]98) --> Matrix group over Finite Field of size 5 with 1 generators (99[1 0]100[1 1]101)102sage: phi(MS([1,1,0,1]))103[1 0]104[1 1]105sage: F = GF(7); MS = MatrixSpace(F,2,2)106sage: F.multiplicative_generator()1073108sage: G = MatrixGroup([MS([3,0,0,1])])109sage: a = G.gens()[0]^2110sage: phi = G.hom([a])111"""112MatrixGroupMorphism.__init__(self, homset) # sets the parent113from sage.libs.gap.libgap import libgap114G = homset.domain()115H = homset.codomain()116gens = [x.gap() for x in G.gens()]117imgs = [to_libgap(x) for x in imgsH]118self._phi = phi = libgap.GroupHomomorphismByImages(G.gap(), H.gap(), gens, imgs)119if not phi.IsGroupHomomorphism():120raise ValueError('The map '+str(gensG)+'-->'+str(imgsH)+' is not a homomorphism')121122def gap(self):123"""124Return the underlying LibGAP group homomorphism125126OUTPUT:127128A LibGAP element.129130EXAMPLES::131132sage: F = GF(5); MS = MatrixSpace(F,2,2)133sage: G = MatrixGroup([MS([1,1,0,1])])134sage: H = MatrixGroup([MS([1,0,1,1])])135sage: phi = G.hom(H.gens())136sage: phi.gap()137CompositionMapping( [ (6,7,8,10,9)(11,13,14,12,15)(16,19,20,18,17)(21,25,22,24,23) ]138-> [ [ [ Z(5)^0, 0*Z(5) ], [ Z(5)^0, Z(5)^0 ] ] ], <action isomorphism> )139sage: type(_)140<type 'sage.libs.gap.element.GapElement'>141"""142return self._phi143144def _repr_(self):145"""146EXAMPLES::147148sage: F = GF(5); MS = MatrixSpace(F,2,2)149sage: G = MatrixGroup([MS([1,1,0,1])])150sage: H = MatrixGroup([MS([1,0,1,1])])151sage: phi = G.hom(H.gens())152sage: phi153Homomorphism : Matrix group over Finite Field of size 5 with 1 generators (154[1 1]155[0 1]156) --> Matrix group over Finite Field of size 5 with 1 generators (157[1 0]158[1 1]159)160sage: phi(MS([1,1,0,1]))161[1 0]162[1 1]163"""164return "Homomorphism : %s --> %s"%(self.domain(),self.codomain())165166def _latex_(self):167r"""168EXAMPLES::169170sage: F = GF(5); MS = MatrixSpace(F,2,2)171sage: G = MatrixGroup([MS([1,1,0,1])])172sage: phi = G.hom(G.gens())173sage: print latex(phi)174\left\langle \left(\begin{array}{rr}1751 & 1 \\1760 & 1177\end{array}\right) \right\rangle \rightarrow{} \left\langle \left(\begin{array}{rr}1781 & 1 \\1790 & 1180\end{array}\right) \right\rangle181"""182return "%s \\rightarrow{} %s"%(latex(self.domain()), latex(self.codomain()))183184def kernel(self):185"""186Return the kernel of ``self``, i.e., a matrix group.187188EXAMPLES::189190sage: F = GF(7); MS = MatrixSpace(F,2,2)191sage: F.multiplicative_generator()1923193sage: G = MatrixGroup([MS([3,0,0,1])])194sage: a = G.gens()[0]^2195sage: phi = G.hom([a])196sage: phi.kernel()197Matrix group over Finite Field of size 7 with 1 generators (198[6 0]199[0 1]200)201"""202gap_ker = self.gap().Kernel()203F = self.domain().base_ring()204from sage.groups.matrix_gps.all import MatrixGroup205return MatrixGroup([x.matrix(F) for x in gap_ker.GeneratorsOfGroup()])206207def pushforward(self, J, *args,**kwds):208"""209The image of an element or a subgroup.210211INPUT:212213``J`` -- a subgroup or an element of the domain of ``self``.214215OUTPUT:216217The image of ``J`` under ``self``218219NOTE:220221``pushforward`` is the method that is used when a map is called on222anything that is not an element of its domain. For historical reasons,223we keep the alias ``image()`` for this method.224225EXAMPLES::226227sage: F = GF(7); MS = MatrixSpace(F,2,2)228sage: F.multiplicative_generator()2293230sage: G = MatrixGroup([MS([3,0,0,1])])231sage: a = G.gens()[0]^2232sage: phi = G.hom([a])233sage: phi.image(G.gens()[0]) # indirect doctest234[2 0]235[0 1]236sage: H = MatrixGroup([MS(a.list())])237sage: H238Matrix group over Finite Field of size 7 with 1 generators (239[2 0]240[0 1]241)242243The following tests against trac ticket #10659::244245sage: phi(H) # indirect doctestest246Matrix group over Finite Field of size 7 with 1 generators (247[4 0]248[0 1]249)250"""251phi = self.gap()252F = self.codomain().base_ring()253gapJ = to_libgap(J)254if gapJ.IsGroup():255from sage.groups.matrix_gps.all import MatrixGroup256img_gens = [x.matrix(F) for x in phi.Image(gapJ).GeneratorsOfGroup()]257return MatrixGroup(img_gens)258return phi.Image(gapJ).matrix(F)259260image = pushforward261262def _call_( self, g ):263"""264Call syntax for morphisms.265266Some python code for wrapping GAP's Images function for a267matrix group G. Returns an error if g is not in G.268269EXAMPLES::270271sage: F = GF(5); MS = MatrixSpace(F,2,2)272sage: g = MS([1,1,0,1])273sage: G = MatrixGroup([g])274sage: phi = G.hom(G.gens())275sage: phi(G.0)276[1 1]277[0 1]278sage: phi(G(g^2))279[1 2]280[0 1]281282sage: F = GF(5); MS = MatrixSpace(F,2,2)283sage: gens = [MS([1,2, -1,1]),MS([1,1, 0,1])]284sage: G = MatrixGroup(gens)285sage: phi = G.hom(G.gens())286sage: phi(G.0)287[1 2]288[4 1]289sage: phi(G.1)290[1 1]291[0 1]292293TEST:294295The following tests that the call method was successfully296improved in trac ticket #10659::297298sage: O = WeylGroup(['D',6])299sage: r = prod(O.gens())300sage: r_ = r^-1301sage: f = O.hom([r*x*r_ for x in O.gens()]) # long time (19s on sage.math, 2011)302sage: [f(x) for x in O.gens()] # long time303[304[1 0 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0] [ 0 0 0 0 -1 0]305[0 0 1 0 0 0] [0 1 0 0 0 0] [0 1 0 0 0 0] [ 0 1 0 0 0 0]306[0 1 0 0 0 0] [0 0 0 1 0 0] [0 0 1 0 0 0] [ 0 0 1 0 0 0]307[0 0 0 1 0 0] [0 0 1 0 0 0] [0 0 0 0 1 0] [ 0 0 0 1 0 0]308[0 0 0 0 1 0] [0 0 0 0 1 0] [0 0 0 1 0 0] [-1 0 0 0 0 0]309[0 0 0 0 0 1], [0 0 0 0 0 1], [0 0 0 0 0 1], [ 0 0 0 0 0 1],310<BLANKLINE>311[0 0 0 0 0 1] [ 0 0 0 0 0 -1]312[0 1 0 0 0 0] [ 0 1 0 0 0 0]313[0 0 1 0 0 0] [ 0 0 1 0 0 0]314[0 0 0 1 0 0] [ 0 0 0 1 0 0]315[0 0 0 0 1 0] [ 0 0 0 0 1 0]316[1 0 0 0 0 0], [-1 0 0 0 0 0]317]318sage: f(O) # long time319Matrix group over Rational Field with 6 generators320sage: f(O).gens() # long time321(322[1 0 0 0 0 0] [1 0 0 0 0 0] [1 0 0 0 0 0] [ 0 0 0 0 -1 0]323[0 0 1 0 0 0] [0 1 0 0 0 0] [0 1 0 0 0 0] [ 0 1 0 0 0 0]324[0 1 0 0 0 0] [0 0 0 1 0 0] [0 0 1 0 0 0] [ 0 0 1 0 0 0]325[0 0 0 1 0 0] [0 0 1 0 0 0] [0 0 0 0 1 0] [ 0 0 0 1 0 0]326[0 0 0 0 1 0] [0 0 0 0 1 0] [0 0 0 1 0 0] [-1 0 0 0 0 0]327[0 0 0 0 0 1], [0 0 0 0 0 1], [0 0 0 0 0 1], [ 0 0 0 0 0 1],328<BLANKLINE>329[0 0 0 0 0 1] [ 0 0 0 0 0 -1]330[0 1 0 0 0 0] [ 0 1 0 0 0 0]331[0 0 1 0 0 0] [ 0 0 1 0 0 0]332[0 0 0 1 0 0] [ 0 0 0 1 0 0]333[0 0 0 0 1 0] [ 0 0 0 0 1 0]334[1 0 0 0 0 0], [-1 0 0 0 0 0]335)336"""337phi = self.gap()338G = self.domain()339F = G.base_ring()340h = g.gap()341return phi.Image(h).matrix(F)342343344