Path: blob/master/src/sage/modules/fg_pid/fgp_element.py
8815 views
r"""1Elements of finitely generated modules over a PID23AUTHOR:4- William Stein, 20095"""67####################################################################################8# Copyright (C) 2009 William Stein <[email protected]>9#10# Distributed under the terms of the GNU General Public License (GPL)11#12# This code is distributed in the hope that it will be useful,13# but WITHOUT ANY WARRANTY; without even the implied warranty of14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU15# General Public License for more details.16#17# The full text of the GPL is available at:18#19# http://www.gnu.org/licenses/20####################################################################################2122from sage.structure.element import ModuleElement2324# This adds extra maybe-not-necessary checks in the code, but could25# slow things down. It can impact what happens in more than just this26# file.27DEBUG=True282930class FGP_Element(ModuleElement):31"""32An element of a finitely generated module over a PID.3334INPUT:3536- ``parent`` -- parent module M3738- ``x`` -- element of M.V()3940EXAMPLES::4142sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])43sage: Q = V/W44sage: x = Q(V.0-V.1); x #indirect doctest45(0, 3)46sage: isinstance(x, sage.modules.fg_pid.fgp_element.FGP_Element)47True48sage: type(x)49<class 'sage.modules.fg_pid.fgp_element.FGP_Module_class_with_category.element_class'>50sage: x is Q(x)51True52sage: x.parent() is Q53True5455TESTS::5657sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W58sage: loads(dumps(Q.0)) == Q.059True60"""61def __init__(self, parent, x, check=DEBUG):62"""63INPUT:6465- ``parent`` -- parent module M6667- ``x`` -- element of M.V()6869- ``check`` -- (default: True) if True, verify that x in M.V()7071EXAMPLES::7273sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])74sage: Q = V/W75sage: x = Q(V.0-V.1); type(x)76<class 'sage.modules.fg_pid.fgp_element.FGP_Module_class_with_category.element_class'>77sage: isinstance(x,sage.modules.fg_pid.fgp_element.FGP_Element)78True7980For full documentation, see :class:`FGP_Element`.81"""82if check: assert x in parent.V(), 'The argument x='+str(x)+' is not in the covering module!'83ModuleElement.__init__(self, parent)84self._x = x8586def lift(self):87"""88Lift self to an element of V, where the parent of self is the quotient module V/W.8990EXAMPLES::9192sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])93sage: Q = V/W; Q94Finitely generated module V/W over Integer Ring with invariants (4, 12)95sage: Q.096(1, 0)97sage: Q.198(0, 1)99sage: Q.0.lift()100(0, 0, 1)101sage: Q.1.lift()102(0, 2, 0)103sage: x = Q(V.0); x104(0, 4)105sage: x.lift()106(1/2, 0, 0)107sage: x == 4*Q.1108True109sage: x.lift().parent() == V110True111112A silly version of the integers modulo 100::113114sage: A = (ZZ^1)/span([[100]], ZZ); A115Finitely generated module V/W over Integer Ring with invariants (100)116sage: x = A([5]); x117(5)118sage: v = x.lift(); v119(5)120sage: v.parent()121Ambient free module of rank 1 over the principal ideal domain Integer Ring122"""123return self._x124125126def __neg__(self):127"""128EXAMPLES::129130sage: V1 = ZZ^2; W1 = V1.span([[1,2],[3,4]]); A1 = V1/W1; A1131Finitely generated module V/W over Integer Ring with invariants (2)132sage: -A1.0133(1)134sage: -A1.0 == A1.0 # order 2135True136"""137P = self.parent()138return P.element_class(P, self._x.__neg__())139140141def _add_(self, other):142"""143EXAMPLES::144145sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])146sage: Q = V/W; Q147Finitely generated module V/W over Integer Ring with invariants (4, 12)148sage: x = Q.0; x149(1, 0)150sage: y = Q.1; y151(0, 1)152sage: x + y # indirect doctest153(1, 1)154sage: x + x + x + x155(0, 0)156sage: x + 0157(1, 0)158sage: 0 + x159(1, 0)160161We test canonical coercion from V and W.162163sage: Q.0 + V.0164(1, 4)165sage: V.0 + Q.0166(1, 4)167sage: W.0 + Q.0168(1, 0)169sage: W.0 + Q.0 == Q.0170True171"""172P = self.parent()173return P.element_class(P, self._x + other._x)174175176def _sub_(self, other):177"""178EXAMPLES::179180sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])181sage: Q = V/W; Q182Finitely generated module V/W over Integer Ring with invariants (4, 12)183sage: x = Q.0; x184(1, 0)185sage: y = Q.1; y186(0, 1)187sage: x - y # indirect doctest188(1, 11)189sage: x - x190(0, 0)191"""192P = self.parent()193return P.element_class(P, self._x - other._x)194195196def _rmul_(self, c):197"""198Multiplication by a scalar from the left (``self`` is on the right).199200INPUT:201202- ``c`` -- an element of ``self.parent().base_ring()``.203204OUTPUT:205206The product ``c * self`` as a new instance of a module207element.208209EXAMPLES::210211sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])212sage: Q = V/W; Q213Finitely generated module V/W over Integer Ring with invariants (4, 12)214sage: x = Q.0; x215(1, 0)216sage: 2 * x # indirect doctest217(2, 0)218sage: x._rmul_(4)219(0, 0)220sage: V = V.base_extend(QQ); W = V.span([2*V.0+4*V.1])221sage: Q = V/W; Q222Vector space quotient V/W of dimension 2 over Rational Field where223V: Vector space of degree 3 and dimension 3 over Rational Field224Basis matrix:225[1 0 0]226[0 1 0]227[0 0 1]228W: Vector space of degree 3 and dimension 1 over Rational Field229Basis matrix:230[1 2 0]231sage: x = Q.0; x232(1, 0)233sage: (1/2) * x # indirect doctest234(1/2, 0)235sage: x._rmul_(1/4)236(1/4, 0)237"""238# print "_rmul_"239P = self.parent()240return P.element_class(P, self._x._rmul_(c))241242def _lmul_(self, s):243"""244Multiplication by a scalar from the right (``self`` is on the left).245246INPUT:247248- ``c`` -- an element of ``self.parent().base_ring()``.249250OUTPUT:251252The product ``self * c`` as a new instance of a module253element.254255EXAMPLES::256257sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])258sage: Q = V/W; Q259Finitely generated module V/W over Integer Ring with invariants (4, 12)260sage: x = Q.0; x261(1, 0)262sage: x * 2 # indirect doctest263(2, 0)264sage: x._lmul_(4)265(0, 0)266sage: V = V.base_extend(QQ); W = V.span([2*V.0+4*V.1])267sage: Q = V/W; Q268Vector space quotient V/W of dimension 2 over Rational Field where269V: Vector space of degree 3 and dimension 3 over Rational Field270Basis matrix:271[1 0 0]272[0 1 0]273[0 0 1]274W: Vector space of degree 3 and dimension 1 over Rational Field275Basis matrix:276[1 2 0]277sage: x = Q.0; x278(1, 0)279sage: x * (1/2) # indirect doctest280(1/2, 0)281sage: x._lmul_(1/4)282(1/4, 0)283"""284# print '_lmul_'285P = self.parent()286return P.element_class(P, self._x._lmul_(s))287288289def _repr_(self):290"""291292EXAMPLES::293294sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])295sage: Q = V/W296sage: Q(V.1)._repr_()297'(0, 1)'298"""299return self.vector().__repr__()300301302def __getitem__(self, *args):303"""304EXAMPLES::305306sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])307sage: Q = V/W; Q308Finitely generated module V/W over Integer Ring with invariants (4, 12)309sage: x = Q.0 + 3*Q.1; x310(1, 3)311sage: x[0]3121313sage: x[1]3143315sage: x[-1]3163317"""318return self.vector().__getitem__(*args)319320def vector(self):321"""322EXAMPLES::323324sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])325sage: Q = V/W; Q326Finitely generated module V/W over Integer Ring with invariants (4, 12)327sage: x = Q.0 + 3*Q.1; x328(1, 3)329sage: x.vector()330(1, 3)331sage: tuple(x)332(1, 3)333sage: list(x)334[1, 3]335sage: x.vector().parent()336Ambient free module of rank 2 over the principal ideal domain Integer Ring337"""338try: return self.__vector339except AttributeError:340self.__vector = self.parent().coordinate_vector(self, reduce=True)341return self.__vector342343344def __cmp__(self, right):345"""346Compare self and right.347348EXAMPLES::349350sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])351sage: Q = V/W; Q352Finitely generated module V/W over Integer Ring with invariants (4, 12)353sage: x = Q.0; x354(1, 0)355sage: y = Q.1; y356(0, 1)357sage: x == y358False359sage: x == x360True361sage: x + x == 2*x362True363"""364return cmp(self.vector(), right.vector())365366def additive_order(self):367"""368Return the additive order of this element.369370EXAMPLES::371372sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])373sage: Q = V/W; Q374Finitely generated module V/W over Integer Ring with invariants (4, 12)375sage: Q.0.additive_order()3764377sage: Q.1.additive_order()37812379sage: (Q.0+Q.1).additive_order()38012381sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1])382sage: Q = V/W; Q383Finitely generated module V/W over Integer Ring with invariants (12, 0)384sage: Q.0.additive_order()38512386sage: type(Q.0.additive_order())387<type 'sage.rings.integer.Integer'>388sage: Q.1.additive_order()389+Infinity390"""391Q = self.parent()392I = Q.invariants()393v = self.vector()394395from sage.rings.all import infinity, lcm, Mod, Integer396n = Integer(1)397for i, a in enumerate(I):398if a == 0:399if v[i] != 0:400return infinity401else:402n = lcm(n, Mod(v[i],a).additive_order())403return n404405406