modules.py 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. """
  2. Computations with modules over polynomial rings.
  3. This module implements various classes that encapsulate groebner basis
  4. computations for modules. Most of them should not be instantiated by hand.
  5. Instead, use the constructing routines on objects you already have.
  6. For example, to construct a free module over ``QQ[x, y]``, call
  7. ``QQ[x, y].free_module(rank)`` instead of the ``FreeModule`` constructor.
  8. In fact ``FreeModule`` is an abstract base class that should not be
  9. instantiated, the ``free_module`` method instead returns the implementing class
  10. ``FreeModulePolyRing``.
  11. In general, the abstract base classes implement most functionality in terms of
  12. a few non-implemented methods. The concrete base classes supply only these
  13. non-implemented methods. They may also supply new implementations of the
  14. convenience methods, for example if there are faster algorithms available.
  15. """
  16. from copy import copy
  17. from functools import reduce
  18. from sympy.polys.agca.ideals import Ideal
  19. from sympy.polys.domains.field import Field
  20. from sympy.polys.orderings import ProductOrder, monomial_key
  21. from sympy.polys.polyerrors import CoercionFailed
  22. from sympy.core.basic import _aresame
  23. from sympy.utilities.iterables import iterable
  24. # TODO
  25. # - module saturation
  26. # - module quotient/intersection for quotient rings
  27. # - free resoltutions / syzygies
  28. # - finding small/minimal generating sets
  29. # - ...
  30. ##########################################################################
  31. ## Abstract base classes #################################################
  32. ##########################################################################
  33. class Module:
  34. """
  35. Abstract base class for modules.
  36. Do not instantiate - use ring explicit constructors instead:
  37. >>> from sympy import QQ
  38. >>> from sympy.abc import x
  39. >>> QQ.old_poly_ring(x).free_module(2)
  40. QQ[x]**2
  41. Attributes:
  42. - dtype - type of elements
  43. - ring - containing ring
  44. Non-implemented methods:
  45. - submodule
  46. - quotient_module
  47. - is_zero
  48. - is_submodule
  49. - multiply_ideal
  50. The method convert likely needs to be changed in subclasses.
  51. """
  52. def __init__(self, ring):
  53. self.ring = ring
  54. def convert(self, elem, M=None):
  55. """
  56. Convert ``elem`` into internal representation of this module.
  57. If ``M`` is not None, it should be a module containing it.
  58. """
  59. if not isinstance(elem, self.dtype):
  60. raise CoercionFailed
  61. return elem
  62. def submodule(self, *gens):
  63. """Generate a submodule."""
  64. raise NotImplementedError
  65. def quotient_module(self, other):
  66. """Generate a quotient module."""
  67. raise NotImplementedError
  68. def __truediv__(self, e):
  69. if not isinstance(e, Module):
  70. e = self.submodule(*e)
  71. return self.quotient_module(e)
  72. def contains(self, elem):
  73. """Return True if ``elem`` is an element of this module."""
  74. try:
  75. self.convert(elem)
  76. return True
  77. except CoercionFailed:
  78. return False
  79. def __contains__(self, elem):
  80. return self.contains(elem)
  81. def subset(self, other):
  82. """
  83. Returns True if ``other`` is is a subset of ``self``.
  84. Examples
  85. ========
  86. >>> from sympy.abc import x
  87. >>> from sympy import QQ
  88. >>> F = QQ.old_poly_ring(x).free_module(2)
  89. >>> F.subset([(1, x), (x, 2)])
  90. True
  91. >>> F.subset([(1/x, x), (x, 2)])
  92. False
  93. """
  94. return all(self.contains(x) for x in other)
  95. def __eq__(self, other):
  96. return self.is_submodule(other) and other.is_submodule(self)
  97. def __ne__(self, other):
  98. return not (self == other)
  99. def is_zero(self):
  100. """Returns True if ``self`` is a zero module."""
  101. raise NotImplementedError
  102. def is_submodule(self, other):
  103. """Returns True if ``other`` is a submodule of ``self``."""
  104. raise NotImplementedError
  105. def multiply_ideal(self, other):
  106. """
  107. Multiply ``self`` by the ideal ``other``.
  108. """
  109. raise NotImplementedError
  110. def __mul__(self, e):
  111. if not isinstance(e, Ideal):
  112. try:
  113. e = self.ring.ideal(e)
  114. except (CoercionFailed, NotImplementedError):
  115. return NotImplemented
  116. return self.multiply_ideal(e)
  117. __rmul__ = __mul__
  118. def identity_hom(self):
  119. """Return the identity homomorphism on ``self``."""
  120. raise NotImplementedError
  121. class ModuleElement:
  122. """
  123. Base class for module element wrappers.
  124. Use this class to wrap primitive data types as module elements. It stores
  125. a reference to the containing module, and implements all the arithmetic
  126. operators.
  127. Attributes:
  128. - module - containing module
  129. - data - internal data
  130. Methods that likely need change in subclasses:
  131. - add
  132. - mul
  133. - div
  134. - eq
  135. """
  136. def __init__(self, module, data):
  137. self.module = module
  138. self.data = data
  139. def add(self, d1, d2):
  140. """Add data ``d1`` and ``d2``."""
  141. return d1 + d2
  142. def mul(self, m, d):
  143. """Multiply module data ``m`` by coefficient d."""
  144. return m * d
  145. def div(self, m, d):
  146. """Divide module data ``m`` by coefficient d."""
  147. return m / d
  148. def eq(self, d1, d2):
  149. """Return true if d1 and d2 represent the same element."""
  150. return d1 == d2
  151. def __add__(self, om):
  152. if not isinstance(om, self.__class__) or om.module != self.module:
  153. try:
  154. om = self.module.convert(om)
  155. except CoercionFailed:
  156. return NotImplemented
  157. return self.__class__(self.module, self.add(self.data, om.data))
  158. __radd__ = __add__
  159. def __neg__(self):
  160. return self.__class__(self.module, self.mul(self.data,
  161. self.module.ring.convert(-1)))
  162. def __sub__(self, om):
  163. if not isinstance(om, self.__class__) or om.module != self.module:
  164. try:
  165. om = self.module.convert(om)
  166. except CoercionFailed:
  167. return NotImplemented
  168. return self.__add__(-om)
  169. def __rsub__(self, om):
  170. return (-self).__add__(om)
  171. def __mul__(self, o):
  172. if not isinstance(o, self.module.ring.dtype):
  173. try:
  174. o = self.module.ring.convert(o)
  175. except CoercionFailed:
  176. return NotImplemented
  177. return self.__class__(self.module, self.mul(self.data, o))
  178. __rmul__ = __mul__
  179. def __truediv__(self, o):
  180. if not isinstance(o, self.module.ring.dtype):
  181. try:
  182. o = self.module.ring.convert(o)
  183. except CoercionFailed:
  184. return NotImplemented
  185. return self.__class__(self.module, self.div(self.data, o))
  186. def __eq__(self, om):
  187. if not isinstance(om, self.__class__) or om.module != self.module:
  188. try:
  189. om = self.module.convert(om)
  190. except CoercionFailed:
  191. return False
  192. return self.eq(self.data, om.data)
  193. def __ne__(self, om):
  194. return not self == om
  195. ##########################################################################
  196. ## Free Modules ##########################################################
  197. ##########################################################################
  198. class FreeModuleElement(ModuleElement):
  199. """Element of a free module. Data stored as a tuple."""
  200. def add(self, d1, d2):
  201. return tuple(x + y for x, y in zip(d1, d2))
  202. def mul(self, d, p):
  203. return tuple(x * p for x in d)
  204. def div(self, d, p):
  205. return tuple(x / p for x in d)
  206. def __repr__(self):
  207. from sympy.printing.str import sstr
  208. return '[' + ', '.join(sstr(x) for x in self.data) + ']'
  209. def __iter__(self):
  210. return self.data.__iter__()
  211. def __getitem__(self, idx):
  212. return self.data[idx]
  213. class FreeModule(Module):
  214. """
  215. Abstract base class for free modules.
  216. Additional attributes:
  217. - rank - rank of the free module
  218. Non-implemented methods:
  219. - submodule
  220. """
  221. dtype = FreeModuleElement
  222. def __init__(self, ring, rank):
  223. Module.__init__(self, ring)
  224. self.rank = rank
  225. def __repr__(self):
  226. return repr(self.ring) + "**" + repr(self.rank)
  227. def is_submodule(self, other):
  228. """
  229. Returns True if ``other`` is a submodule of ``self``.
  230. Examples
  231. ========
  232. >>> from sympy.abc import x
  233. >>> from sympy import QQ
  234. >>> F = QQ.old_poly_ring(x).free_module(2)
  235. >>> M = F.submodule([2, x])
  236. >>> F.is_submodule(F)
  237. True
  238. >>> F.is_submodule(M)
  239. True
  240. >>> M.is_submodule(F)
  241. False
  242. """
  243. if isinstance(other, SubModule):
  244. return other.container == self
  245. if isinstance(other, FreeModule):
  246. return other.ring == self.ring and other.rank == self.rank
  247. return False
  248. def convert(self, elem, M=None):
  249. """
  250. Convert ``elem`` into the internal representation.
  251. This method is called implicitly whenever computations involve elements
  252. not in the internal representation.
  253. Examples
  254. ========
  255. >>> from sympy.abc import x
  256. >>> from sympy import QQ
  257. >>> F = QQ.old_poly_ring(x).free_module(2)
  258. >>> F.convert([1, 0])
  259. [1, 0]
  260. """
  261. if isinstance(elem, FreeModuleElement):
  262. if elem.module is self:
  263. return elem
  264. if elem.module.rank != self.rank:
  265. raise CoercionFailed
  266. return FreeModuleElement(self,
  267. tuple(self.ring.convert(x, elem.module.ring) for x in elem.data))
  268. elif iterable(elem):
  269. tpl = tuple(self.ring.convert(x) for x in elem)
  270. if len(tpl) != self.rank:
  271. raise CoercionFailed
  272. return FreeModuleElement(self, tpl)
  273. elif _aresame(elem, 0):
  274. return FreeModuleElement(self, (self.ring.convert(0),)*self.rank)
  275. else:
  276. raise CoercionFailed
  277. def is_zero(self):
  278. """
  279. Returns True if ``self`` is a zero module.
  280. (If, as this implementation assumes, the coefficient ring is not the
  281. zero ring, then this is equivalent to the rank being zero.)
  282. Examples
  283. ========
  284. >>> from sympy.abc import x
  285. >>> from sympy import QQ
  286. >>> QQ.old_poly_ring(x).free_module(0).is_zero()
  287. True
  288. >>> QQ.old_poly_ring(x).free_module(1).is_zero()
  289. False
  290. """
  291. return self.rank == 0
  292. def basis(self):
  293. """
  294. Return a set of basis elements.
  295. Examples
  296. ========
  297. >>> from sympy.abc import x
  298. >>> from sympy import QQ
  299. >>> QQ.old_poly_ring(x).free_module(3).basis()
  300. ([1, 0, 0], [0, 1, 0], [0, 0, 1])
  301. """
  302. from sympy.matrices import eye
  303. M = eye(self.rank)
  304. return tuple(self.convert(M.row(i)) for i in range(self.rank))
  305. def quotient_module(self, submodule):
  306. """
  307. Return a quotient module.
  308. Examples
  309. ========
  310. >>> from sympy.abc import x
  311. >>> from sympy import QQ
  312. >>> M = QQ.old_poly_ring(x).free_module(2)
  313. >>> M.quotient_module(M.submodule([1, x], [x, 2]))
  314. QQ[x]**2/<[1, x], [x, 2]>
  315. Or more conicisely, using the overloaded division operator:
  316. >>> QQ.old_poly_ring(x).free_module(2) / [[1, x], [x, 2]]
  317. QQ[x]**2/<[1, x], [x, 2]>
  318. """
  319. return QuotientModule(self.ring, self, submodule)
  320. def multiply_ideal(self, other):
  321. """
  322. Multiply ``self`` by the ideal ``other``.
  323. Examples
  324. ========
  325. >>> from sympy.abc import x
  326. >>> from sympy import QQ
  327. >>> I = QQ.old_poly_ring(x).ideal(x)
  328. >>> F = QQ.old_poly_ring(x).free_module(2)
  329. >>> F.multiply_ideal(I)
  330. <[x, 0], [0, x]>
  331. """
  332. return self.submodule(*self.basis()).multiply_ideal(other)
  333. def identity_hom(self):
  334. """
  335. Return the identity homomorphism on ``self``.
  336. Examples
  337. ========
  338. >>> from sympy.abc import x
  339. >>> from sympy import QQ
  340. >>> QQ.old_poly_ring(x).free_module(2).identity_hom()
  341. Matrix([
  342. [1, 0], : QQ[x]**2 -> QQ[x]**2
  343. [0, 1]])
  344. """
  345. from sympy.polys.agca.homomorphisms import homomorphism
  346. return homomorphism(self, self, self.basis())
  347. class FreeModulePolyRing(FreeModule):
  348. """
  349. Free module over a generalized polynomial ring.
  350. Do not instantiate this, use the constructor method of the ring instead:
  351. Examples
  352. ========
  353. >>> from sympy.abc import x
  354. >>> from sympy import QQ
  355. >>> F = QQ.old_poly_ring(x).free_module(3)
  356. >>> F
  357. QQ[x]**3
  358. >>> F.contains([x, 1, 0])
  359. True
  360. >>> F.contains([1/x, 0, 1])
  361. False
  362. """
  363. def __init__(self, ring, rank):
  364. from sympy.polys.domains.old_polynomialring import PolynomialRingBase
  365. FreeModule.__init__(self, ring, rank)
  366. if not isinstance(ring, PolynomialRingBase):
  367. raise NotImplementedError('This implementation only works over '
  368. + 'polynomial rings, got %s' % ring)
  369. if not isinstance(ring.dom, Field):
  370. raise NotImplementedError('Ground domain must be a field, '
  371. + 'got %s' % ring.dom)
  372. def submodule(self, *gens, **opts):
  373. """
  374. Generate a submodule.
  375. Examples
  376. ========
  377. >>> from sympy.abc import x, y
  378. >>> from sympy import QQ
  379. >>> M = QQ.old_poly_ring(x, y).free_module(2).submodule([x, x + y])
  380. >>> M
  381. <[x, x + y]>
  382. >>> M.contains([2*x, 2*x + 2*y])
  383. True
  384. >>> M.contains([x, y])
  385. False
  386. """
  387. return SubModulePolyRing(gens, self, **opts)
  388. class FreeModuleQuotientRing(FreeModule):
  389. """
  390. Free module over a quotient ring.
  391. Do not instantiate this, use the constructor method of the ring instead:
  392. Examples
  393. ========
  394. >>> from sympy.abc import x
  395. >>> from sympy import QQ
  396. >>> F = (QQ.old_poly_ring(x)/[x**2 + 1]).free_module(3)
  397. >>> F
  398. (QQ[x]/<x**2 + 1>)**3
  399. Attributes
  400. - quot - the quotient module `R^n / IR^n`, where `R/I` is our ring
  401. """
  402. def __init__(self, ring, rank):
  403. from sympy.polys.domains.quotientring import QuotientRing
  404. FreeModule.__init__(self, ring, rank)
  405. if not isinstance(ring, QuotientRing):
  406. raise NotImplementedError('This implementation only works over '
  407. + 'quotient rings, got %s' % ring)
  408. F = self.ring.ring.free_module(self.rank)
  409. self.quot = F / (self.ring.base_ideal*F)
  410. def __repr__(self):
  411. return "(" + repr(self.ring) + ")" + "**" + repr(self.rank)
  412. def submodule(self, *gens, **opts):
  413. """
  414. Generate a submodule.
  415. Examples
  416. ========
  417. >>> from sympy.abc import x, y
  418. >>> from sympy import QQ
  419. >>> M = (QQ.old_poly_ring(x, y)/[x**2 - y**2]).free_module(2).submodule([x, x + y])
  420. >>> M
  421. <[x + <x**2 - y**2>, x + y + <x**2 - y**2>]>
  422. >>> M.contains([y**2, x**2 + x*y])
  423. True
  424. >>> M.contains([x, y])
  425. False
  426. """
  427. return SubModuleQuotientRing(gens, self, **opts)
  428. def lift(self, elem):
  429. """
  430. Lift the element ``elem`` of self to the module self.quot.
  431. Note that self.quot is the same set as self, just as an R-module
  432. and not as an R/I-module, so this makes sense.
  433. Examples
  434. ========
  435. >>> from sympy.abc import x
  436. >>> from sympy import QQ
  437. >>> F = (QQ.old_poly_ring(x)/[x**2 + 1]).free_module(2)
  438. >>> e = F.convert([1, 0])
  439. >>> e
  440. [1 + <x**2 + 1>, 0 + <x**2 + 1>]
  441. >>> L = F.quot
  442. >>> l = F.lift(e)
  443. >>> l
  444. [1, 0] + <[x**2 + 1, 0], [0, x**2 + 1]>
  445. >>> L.contains(l)
  446. True
  447. """
  448. return self.quot.convert([x.data for x in elem])
  449. def unlift(self, elem):
  450. """
  451. Push down an element of self.quot to self.
  452. This undoes ``lift``.
  453. Examples
  454. ========
  455. >>> from sympy.abc import x
  456. >>> from sympy import QQ
  457. >>> F = (QQ.old_poly_ring(x)/[x**2 + 1]).free_module(2)
  458. >>> e = F.convert([1, 0])
  459. >>> l = F.lift(e)
  460. >>> e == l
  461. False
  462. >>> e == F.unlift(l)
  463. True
  464. """
  465. return self.convert(elem.data)
  466. ##########################################################################
  467. ## Submodules and subquotients ###########################################
  468. ##########################################################################
  469. class SubModule(Module):
  470. """
  471. Base class for submodules.
  472. Attributes:
  473. - container - containing module
  474. - gens - generators (subset of containing module)
  475. - rank - rank of containing module
  476. Non-implemented methods:
  477. - _contains
  478. - _syzygies
  479. - _in_terms_of_generators
  480. - _intersect
  481. - _module_quotient
  482. Methods that likely need change in subclasses:
  483. - reduce_element
  484. """
  485. def __init__(self, gens, container):
  486. Module.__init__(self, container.ring)
  487. self.gens = tuple(container.convert(x) for x in gens)
  488. self.container = container
  489. self.rank = container.rank
  490. self.ring = container.ring
  491. self.dtype = container.dtype
  492. def __repr__(self):
  493. return "<" + ", ".join(repr(x) for x in self.gens) + ">"
  494. def _contains(self, other):
  495. """Implementation of containment.
  496. Other is guaranteed to be FreeModuleElement."""
  497. raise NotImplementedError
  498. def _syzygies(self):
  499. """Implementation of syzygy computation wrt self generators."""
  500. raise NotImplementedError
  501. def _in_terms_of_generators(self, e):
  502. """Implementation of expression in terms of generators."""
  503. raise NotImplementedError
  504. def convert(self, elem, M=None):
  505. """
  506. Convert ``elem`` into the internal represantition.
  507. Mostly called implicitly.
  508. Examples
  509. ========
  510. >>> from sympy.abc import x
  511. >>> from sympy import QQ
  512. >>> M = QQ.old_poly_ring(x).free_module(2).submodule([1, x])
  513. >>> M.convert([2, 2*x])
  514. [2, 2*x]
  515. """
  516. if isinstance(elem, self.container.dtype) and elem.module is self:
  517. return elem
  518. r = copy(self.container.convert(elem, M))
  519. r.module = self
  520. if not self._contains(r):
  521. raise CoercionFailed
  522. return r
  523. def _intersect(self, other):
  524. """Implementation of intersection.
  525. Other is guaranteed to be a submodule of same free module."""
  526. raise NotImplementedError
  527. def _module_quotient(self, other):
  528. """Implementation of quotient.
  529. Other is guaranteed to be a submodule of same free module."""
  530. raise NotImplementedError
  531. def intersect(self, other, **options):
  532. """
  533. Returns the intersection of ``self`` with submodule ``other``.
  534. Examples
  535. ========
  536. >>> from sympy.abc import x, y
  537. >>> from sympy import QQ
  538. >>> F = QQ.old_poly_ring(x, y).free_module(2)
  539. >>> F.submodule([x, x]).intersect(F.submodule([y, y]))
  540. <[x*y, x*y]>
  541. Some implementation allow further options to be passed. Currently, to
  542. only one implemented is ``relations=True``, in which case the function
  543. will return a triple ``(res, rela, relb)``, where ``res`` is the
  544. intersection module, and ``rela`` and ``relb`` are lists of coefficient
  545. vectors, expressing the generators of ``res`` in terms of the
  546. generators of ``self`` (``rela``) and ``other`` (``relb``).
  547. >>> F.submodule([x, x]).intersect(F.submodule([y, y]), relations=True)
  548. (<[x*y, x*y]>, [(y,)], [(x,)])
  549. The above result says: the intersection module is generated by the
  550. single element `(-xy, -xy) = -y (x, x) = -x (y, y)`, where
  551. `(x, x)` and `(y, y)` respectively are the unique generators of
  552. the two modules being intersected.
  553. """
  554. if not isinstance(other, SubModule):
  555. raise TypeError('%s is not a SubModule' % other)
  556. if other.container != self.container:
  557. raise ValueError(
  558. '%s is contained in a different free module' % other)
  559. return self._intersect(other, **options)
  560. def module_quotient(self, other, **options):
  561. r"""
  562. Returns the module quotient of ``self`` by submodule ``other``.
  563. That is, if ``self`` is the module `M` and ``other`` is `N`, then
  564. return the ideal `\{f \in R | fN \subset M\}`.
  565. Examples
  566. ========
  567. >>> from sympy import QQ
  568. >>> from sympy.abc import x, y
  569. >>> F = QQ.old_poly_ring(x, y).free_module(2)
  570. >>> S = F.submodule([x*y, x*y])
  571. >>> T = F.submodule([x, x])
  572. >>> S.module_quotient(T)
  573. <y>
  574. Some implementations allow further options to be passed. Currently, the
  575. only one implemented is ``relations=True``, which may only be passed
  576. if ``other`` is principal. In this case the function
  577. will return a pair ``(res, rel)`` where ``res`` is the ideal, and
  578. ``rel`` is a list of coefficient vectors, expressing the generators of
  579. the ideal, multiplied by the generator of ``other`` in terms of
  580. generators of ``self``.
  581. >>> S.module_quotient(T, relations=True)
  582. (<y>, [[1]])
  583. This means that the quotient ideal is generated by the single element
  584. `y`, and that `y (x, x) = 1 (xy, xy)`, `(x, x)` and `(xy, xy)` being
  585. the generators of `T` and `S`, respectively.
  586. """
  587. if not isinstance(other, SubModule):
  588. raise TypeError('%s is not a SubModule' % other)
  589. if other.container != self.container:
  590. raise ValueError(
  591. '%s is contained in a different free module' % other)
  592. return self._module_quotient(other, **options)
  593. def union(self, other):
  594. """
  595. Returns the module generated by the union of ``self`` and ``other``.
  596. Examples
  597. ========
  598. >>> from sympy.abc import x
  599. >>> from sympy import QQ
  600. >>> F = QQ.old_poly_ring(x).free_module(1)
  601. >>> M = F.submodule([x**2 + x]) # <x(x+1)>
  602. >>> N = F.submodule([x**2 - 1]) # <(x-1)(x+1)>
  603. >>> M.union(N) == F.submodule([x+1])
  604. True
  605. """
  606. if not isinstance(other, SubModule):
  607. raise TypeError('%s is not a SubModule' % other)
  608. if other.container != self.container:
  609. raise ValueError(
  610. '%s is contained in a different free module' % other)
  611. return self.__class__(self.gens + other.gens, self.container)
  612. def is_zero(self):
  613. """
  614. Return True if ``self`` is a zero module.
  615. Examples
  616. ========
  617. >>> from sympy.abc import x
  618. >>> from sympy import QQ
  619. >>> F = QQ.old_poly_ring(x).free_module(2)
  620. >>> F.submodule([x, 1]).is_zero()
  621. False
  622. >>> F.submodule([0, 0]).is_zero()
  623. True
  624. """
  625. return all(x == 0 for x in self.gens)
  626. def submodule(self, *gens):
  627. """
  628. Generate a submodule.
  629. Examples
  630. ========
  631. >>> from sympy.abc import x
  632. >>> from sympy import QQ
  633. >>> M = QQ.old_poly_ring(x).free_module(2).submodule([x, 1])
  634. >>> M.submodule([x**2, x])
  635. <[x**2, x]>
  636. """
  637. if not self.subset(gens):
  638. raise ValueError('%s not a subset of %s' % (gens, self))
  639. return self.__class__(gens, self.container)
  640. def is_full_module(self):
  641. """
  642. Return True if ``self`` is the entire free module.
  643. Examples
  644. ========
  645. >>> from sympy.abc import x
  646. >>> from sympy import QQ
  647. >>> F = QQ.old_poly_ring(x).free_module(2)
  648. >>> F.submodule([x, 1]).is_full_module()
  649. False
  650. >>> F.submodule([1, 1], [1, 2]).is_full_module()
  651. True
  652. """
  653. return all(self.contains(x) for x in self.container.basis())
  654. def is_submodule(self, other):
  655. """
  656. Returns True if ``other`` is a submodule of ``self``.
  657. >>> from sympy.abc import x
  658. >>> from sympy import QQ
  659. >>> F = QQ.old_poly_ring(x).free_module(2)
  660. >>> M = F.submodule([2, x])
  661. >>> N = M.submodule([2*x, x**2])
  662. >>> M.is_submodule(M)
  663. True
  664. >>> M.is_submodule(N)
  665. True
  666. >>> N.is_submodule(M)
  667. False
  668. """
  669. if isinstance(other, SubModule):
  670. return self.container == other.container and \
  671. all(self.contains(x) for x in other.gens)
  672. if isinstance(other, (FreeModule, QuotientModule)):
  673. return self.container == other and self.is_full_module()
  674. return False
  675. def syzygy_module(self, **opts):
  676. r"""
  677. Compute the syzygy module of the generators of ``self``.
  678. Suppose `M` is generated by `f_1, \ldots, f_n` over the ring
  679. `R`. Consider the homomorphism `\phi: R^n \to M`, given by
  680. sending `(r_1, \ldots, r_n) \to r_1 f_1 + \cdots + r_n f_n`.
  681. The syzygy module is defined to be the kernel of `\phi`.
  682. Examples
  683. ========
  684. The syzygy module is zero iff the generators generate freely a free
  685. submodule:
  686. >>> from sympy.abc import x, y
  687. >>> from sympy import QQ
  688. >>> QQ.old_poly_ring(x).free_module(2).submodule([1, 0], [1, 1]).syzygy_module().is_zero()
  689. True
  690. A slightly more interesting example:
  691. >>> M = QQ.old_poly_ring(x, y).free_module(2).submodule([x, 2*x], [y, 2*y])
  692. >>> S = QQ.old_poly_ring(x, y).free_module(2).submodule([y, -x])
  693. >>> M.syzygy_module() == S
  694. True
  695. """
  696. F = self.ring.free_module(len(self.gens))
  697. # NOTE we filter out zero syzygies. This is for convenience of the
  698. # _syzygies function and not meant to replace any real "generating set
  699. # reduction" algorithm
  700. return F.submodule(*[x for x in self._syzygies() if F.convert(x) != 0],
  701. **opts)
  702. def in_terms_of_generators(self, e):
  703. """
  704. Express element ``e`` of ``self`` in terms of the generators.
  705. Examples
  706. ========
  707. >>> from sympy.abc import x
  708. >>> from sympy import QQ
  709. >>> F = QQ.old_poly_ring(x).free_module(2)
  710. >>> M = F.submodule([1, 0], [1, 1])
  711. >>> M.in_terms_of_generators([x, x**2])
  712. [-x**2 + x, x**2]
  713. """
  714. try:
  715. e = self.convert(e)
  716. except CoercionFailed:
  717. raise ValueError('%s is not an element of %s' % (e, self))
  718. return self._in_terms_of_generators(e)
  719. def reduce_element(self, x):
  720. """
  721. Reduce the element ``x`` of our ring modulo the ideal ``self``.
  722. Here "reduce" has no specific meaning, it could return a unique normal
  723. form, simplify the expression a bit, or just do nothing.
  724. """
  725. return x
  726. def quotient_module(self, other, **opts):
  727. """
  728. Return a quotient module.
  729. This is the same as taking a submodule of a quotient of the containing
  730. module.
  731. Examples
  732. ========
  733. >>> from sympy.abc import x
  734. >>> from sympy import QQ
  735. >>> F = QQ.old_poly_ring(x).free_module(2)
  736. >>> S1 = F.submodule([x, 1])
  737. >>> S2 = F.submodule([x**2, x])
  738. >>> S1.quotient_module(S2)
  739. <[x, 1] + <[x**2, x]>>
  740. Or more coincisely, using the overloaded division operator:
  741. >>> F.submodule([x, 1]) / [(x**2, x)]
  742. <[x, 1] + <[x**2, x]>>
  743. """
  744. if not self.is_submodule(other):
  745. raise ValueError('%s not a submodule of %s' % (other, self))
  746. return SubQuotientModule(self.gens,
  747. self.container.quotient_module(other), **opts)
  748. def __add__(self, oth):
  749. return self.container.quotient_module(self).convert(oth)
  750. __radd__ = __add__
  751. def multiply_ideal(self, I):
  752. """
  753. Multiply ``self`` by the ideal ``I``.
  754. Examples
  755. ========
  756. >>> from sympy.abc import x
  757. >>> from sympy import QQ
  758. >>> I = QQ.old_poly_ring(x).ideal(x**2)
  759. >>> M = QQ.old_poly_ring(x).free_module(2).submodule([1, 1])
  760. >>> I*M
  761. <[x**2, x**2]>
  762. """
  763. return self.submodule(*[x*g for [x] in I._module.gens for g in self.gens])
  764. def inclusion_hom(self):
  765. """
  766. Return a homomorphism representing the inclusion map of ``self``.
  767. That is, the natural map from ``self`` to ``self.container``.
  768. Examples
  769. ========
  770. >>> from sympy.abc import x
  771. >>> from sympy import QQ
  772. >>> QQ.old_poly_ring(x).free_module(2).submodule([x, x]).inclusion_hom()
  773. Matrix([
  774. [1, 0], : <[x, x]> -> QQ[x]**2
  775. [0, 1]])
  776. """
  777. return self.container.identity_hom().restrict_domain(self)
  778. def identity_hom(self):
  779. """
  780. Return the identity homomorphism on ``self``.
  781. Examples
  782. ========
  783. >>> from sympy.abc import x
  784. >>> from sympy import QQ
  785. >>> QQ.old_poly_ring(x).free_module(2).submodule([x, x]).identity_hom()
  786. Matrix([
  787. [1, 0], : <[x, x]> -> <[x, x]>
  788. [0, 1]])
  789. """
  790. return self.container.identity_hom().restrict_domain(
  791. self).restrict_codomain(self)
  792. class SubQuotientModule(SubModule):
  793. """
  794. Submodule of a quotient module.
  795. Equivalently, quotient module of a submodule.
  796. Do not instantiate this, instead use the submodule or quotient_module
  797. constructing methods:
  798. >>> from sympy.abc import x
  799. >>> from sympy import QQ
  800. >>> F = QQ.old_poly_ring(x).free_module(2)
  801. >>> S = F.submodule([1, 0], [1, x])
  802. >>> Q = F/[(1, 0)]
  803. >>> S/[(1, 0)] == Q.submodule([5, x])
  804. True
  805. Attributes:
  806. - base - base module we are quotient of
  807. - killed_module - submodule used to form the quotient
  808. """
  809. def __init__(self, gens, container, **opts):
  810. SubModule.__init__(self, gens, container)
  811. self.killed_module = self.container.killed_module
  812. # XXX it is important for some code below that the generators of base
  813. # are in this particular order!
  814. self.base = self.container.base.submodule(
  815. *[x.data for x in self.gens], **opts).union(self.killed_module)
  816. def _contains(self, elem):
  817. return self.base.contains(elem.data)
  818. def _syzygies(self):
  819. # let N = self.killed_module be generated by e_1, ..., e_r
  820. # let F = self.base be generated by f_1, ..., f_s and e_1, ..., e_r
  821. # Then self = F/N.
  822. # Let phi: R**s --> self be the evident surjection.
  823. # Similarly psi: R**(s + r) --> F.
  824. # We need to find generators for ker(phi). Let chi: R**s --> F be the
  825. # evident lift of phi. For X in R**s, phi(X) = 0 iff chi(X) is
  826. # contained in N, iff there exists Y in R**r such that
  827. # psi(X, Y) = 0.
  828. # Hence if alpha: R**(s + r) --> R**s is the projection map, then
  829. # ker(phi) = alpha ker(psi).
  830. return [X[:len(self.gens)] for X in self.base._syzygies()]
  831. def _in_terms_of_generators(self, e):
  832. return self.base._in_terms_of_generators(e.data)[:len(self.gens)]
  833. def is_full_module(self):
  834. """
  835. Return True if ``self`` is the entire free module.
  836. Examples
  837. ========
  838. >>> from sympy.abc import x
  839. >>> from sympy import QQ
  840. >>> F = QQ.old_poly_ring(x).free_module(2)
  841. >>> F.submodule([x, 1]).is_full_module()
  842. False
  843. >>> F.submodule([1, 1], [1, 2]).is_full_module()
  844. True
  845. """
  846. return self.base.is_full_module()
  847. def quotient_hom(self):
  848. """
  849. Return the quotient homomorphism to self.
  850. That is, return the natural map from ``self.base`` to ``self``.
  851. Examples
  852. ========
  853. >>> from sympy.abc import x
  854. >>> from sympy import QQ
  855. >>> M = (QQ.old_poly_ring(x).free_module(2) / [(1, x)]).submodule([1, 0])
  856. >>> M.quotient_hom()
  857. Matrix([
  858. [1, 0], : <[1, 0], [1, x]> -> <[1, 0] + <[1, x]>, [1, x] + <[1, x]>>
  859. [0, 1]])
  860. """
  861. return self.base.identity_hom().quotient_codomain(self.killed_module)
  862. _subs0 = lambda x: x[0]
  863. _subs1 = lambda x: x[1:]
  864. class ModuleOrder(ProductOrder):
  865. """A product monomial order with a zeroth term as module index."""
  866. def __init__(self, o1, o2, TOP):
  867. if TOP:
  868. ProductOrder.__init__(self, (o2, _subs1), (o1, _subs0))
  869. else:
  870. ProductOrder.__init__(self, (o1, _subs0), (o2, _subs1))
  871. class SubModulePolyRing(SubModule):
  872. """
  873. Submodule of a free module over a generalized polynomial ring.
  874. Do not instantiate this, use the constructor method of FreeModule instead:
  875. >>> from sympy.abc import x, y
  876. >>> from sympy import QQ
  877. >>> F = QQ.old_poly_ring(x, y).free_module(2)
  878. >>> F.submodule([x, y], [1, 0])
  879. <[x, y], [1, 0]>
  880. Attributes:
  881. - order - monomial order used
  882. """
  883. #self._gb - cached groebner basis
  884. #self._gbe - cached groebner basis relations
  885. def __init__(self, gens, container, order="lex", TOP=True):
  886. SubModule.__init__(self, gens, container)
  887. if not isinstance(container, FreeModulePolyRing):
  888. raise NotImplementedError('This implementation is for submodules of '
  889. + 'FreeModulePolyRing, got %s' % container)
  890. self.order = ModuleOrder(monomial_key(order), self.ring.order, TOP)
  891. self._gb = None
  892. self._gbe = None
  893. def __eq__(self, other):
  894. if isinstance(other, SubModulePolyRing) and self.order != other.order:
  895. return False
  896. return SubModule.__eq__(self, other)
  897. def _groebner(self, extended=False):
  898. """Returns a standard basis in sdm form."""
  899. from sympy.polys.distributedmodules import sdm_groebner, sdm_nf_mora
  900. if self._gbe is None and extended:
  901. gb, gbe = sdm_groebner(
  902. [self.ring._vector_to_sdm(x, self.order) for x in self.gens],
  903. sdm_nf_mora, self.order, self.ring.dom, extended=True)
  904. self._gb, self._gbe = tuple(gb), tuple(gbe)
  905. if self._gb is None:
  906. self._gb = tuple(sdm_groebner(
  907. [self.ring._vector_to_sdm(x, self.order) for x in self.gens],
  908. sdm_nf_mora, self.order, self.ring.dom))
  909. if extended:
  910. return self._gb, self._gbe
  911. else:
  912. return self._gb
  913. def _groebner_vec(self, extended=False):
  914. """Returns a standard basis in element form."""
  915. if not extended:
  916. return [FreeModuleElement(self,
  917. tuple(self.ring._sdm_to_vector(x, self.rank)))
  918. for x in self._groebner()]
  919. gb, gbe = self._groebner(extended=True)
  920. return ([self.convert(self.ring._sdm_to_vector(x, self.rank))
  921. for x in gb],
  922. [self.ring._sdm_to_vector(x, len(self.gens)) for x in gbe])
  923. def _contains(self, x):
  924. from sympy.polys.distributedmodules import sdm_zero, sdm_nf_mora
  925. return sdm_nf_mora(self.ring._vector_to_sdm(x, self.order),
  926. self._groebner(), self.order, self.ring.dom) == \
  927. sdm_zero()
  928. def _syzygies(self):
  929. """Compute syzygies. See [SCA, algorithm 2.5.4]."""
  930. # NOTE if self.gens is a standard basis, this can be done more
  931. # efficiently using Schreyer's theorem
  932. # First bullet point
  933. k = len(self.gens)
  934. r = self.rank
  935. zero = self.ring.convert(0)
  936. one = self.ring.convert(1)
  937. Rkr = self.ring.free_module(r + k)
  938. newgens = []
  939. for j, f in enumerate(self.gens):
  940. m = [0]*(r + k)
  941. for i, v in enumerate(f):
  942. m[i] = f[i]
  943. for i in range(k):
  944. m[r + i] = one if j == i else zero
  945. m = FreeModuleElement(Rkr, tuple(m))
  946. newgens.append(m)
  947. # Note: we need *descending* order on module index, and TOP=False to
  948. # get an elimination order
  949. F = Rkr.submodule(*newgens, order='ilex', TOP=False)
  950. # Second bullet point: standard basis of F
  951. G = F._groebner_vec()
  952. # Third bullet point: G0 = G intersect the new k components
  953. G0 = [x[r:] for x in G if all(y == zero for y in x[:r])]
  954. # Fourth and fifth bullet points: we are done
  955. return G0
  956. def _in_terms_of_generators(self, e):
  957. """Expression in terms of generators. See [SCA, 2.8.1]."""
  958. # NOTE: if gens is a standard basis, this can be done more efficiently
  959. M = self.ring.free_module(self.rank).submodule(*((e,) + self.gens))
  960. S = M.syzygy_module(
  961. order="ilex", TOP=False) # We want decreasing order!
  962. G = S._groebner_vec()
  963. # This list cannot not be empty since e is an element
  964. e = [x for x in G if self.ring.is_unit(x[0])][0]
  965. return [-x/e[0] for x in e[1:]]
  966. def reduce_element(self, x, NF=None):
  967. """
  968. Reduce the element ``x`` of our container modulo ``self``.
  969. This applies the normal form ``NF`` to ``x``. If ``NF`` is passed
  970. as none, the default Mora normal form is used (which is not unique!).
  971. """
  972. from sympy.polys.distributedmodules import sdm_nf_mora
  973. if NF is None:
  974. NF = sdm_nf_mora
  975. return self.container.convert(self.ring._sdm_to_vector(NF(
  976. self.ring._vector_to_sdm(x, self.order), self._groebner(),
  977. self.order, self.ring.dom),
  978. self.rank))
  979. def _intersect(self, other, relations=False):
  980. # See: [SCA, section 2.8.2]
  981. fi = self.gens
  982. hi = other.gens
  983. r = self.rank
  984. ci = [[0]*(2*r) for _ in range(r)]
  985. for k in range(r):
  986. ci[k][k] = 1
  987. ci[k][r + k] = 1
  988. di = [list(f) + [0]*r for f in fi]
  989. ei = [[0]*r + list(h) for h in hi]
  990. syz = self.ring.free_module(2*r).submodule(*(ci + di + ei))._syzygies()
  991. nonzero = [x for x in syz if any(y != self.ring.zero for y in x[:r])]
  992. res = self.container.submodule(*([-y for y in x[:r]] for x in nonzero))
  993. reln1 = [x[r:r + len(fi)] for x in nonzero]
  994. reln2 = [x[r + len(fi):] for x in nonzero]
  995. if relations:
  996. return res, reln1, reln2
  997. return res
  998. def _module_quotient(self, other, relations=False):
  999. # See: [SCA, section 2.8.4]
  1000. if relations and len(other.gens) != 1:
  1001. raise NotImplementedError
  1002. if len(other.gens) == 0:
  1003. return self.ring.ideal(1)
  1004. elif len(other.gens) == 1:
  1005. # We do some trickery. Let f be the (vector!) generating ``other``
  1006. # and f1, .., fn be the (vectors) generating self.
  1007. # Consider the submodule of R^{r+1} generated by (f, 1) and
  1008. # {(fi, 0) | i}. Then the intersection with the last module
  1009. # component yields the quotient.
  1010. g1 = list(other.gens[0]) + [1]
  1011. gi = [list(x) + [0] for x in self.gens]
  1012. # NOTE: We *need* to use an elimination order
  1013. M = self.ring.free_module(self.rank + 1).submodule(*([g1] + gi),
  1014. order='ilex', TOP=False)
  1015. if not relations:
  1016. return self.ring.ideal(*[x[-1] for x in M._groebner_vec() if
  1017. all(y == self.ring.zero for y in x[:-1])])
  1018. else:
  1019. G, R = M._groebner_vec(extended=True)
  1020. indices = [i for i, x in enumerate(G) if
  1021. all(y == self.ring.zero for y in x[:-1])]
  1022. return (self.ring.ideal(*[G[i][-1] for i in indices]),
  1023. [[-x for x in R[i][1:]] for i in indices])
  1024. # For more generators, we use I : <h1, .., hn> = intersection of
  1025. # {I : <hi> | i}
  1026. # TODO this can be done more efficiently
  1027. return reduce(lambda x, y: x.intersect(y),
  1028. (self._module_quotient(self.container.submodule(x)) for x in other.gens))
  1029. class SubModuleQuotientRing(SubModule):
  1030. """
  1031. Class for submodules of free modules over quotient rings.
  1032. Do not instantiate this. Instead use the submodule methods.
  1033. >>> from sympy.abc import x, y
  1034. >>> from sympy import QQ
  1035. >>> M = (QQ.old_poly_ring(x, y)/[x**2 - y**2]).free_module(2).submodule([x, x + y])
  1036. >>> M
  1037. <[x + <x**2 - y**2>, x + y + <x**2 - y**2>]>
  1038. >>> M.contains([y**2, x**2 + x*y])
  1039. True
  1040. >>> M.contains([x, y])
  1041. False
  1042. Attributes:
  1043. - quot - the subquotient of `R^n/IR^n` generated by lifts of our generators
  1044. """
  1045. def __init__(self, gens, container):
  1046. SubModule.__init__(self, gens, container)
  1047. self.quot = self.container.quot.submodule(
  1048. *[self.container.lift(x) for x in self.gens])
  1049. def _contains(self, elem):
  1050. return self.quot._contains(self.container.lift(elem))
  1051. def _syzygies(self):
  1052. return [tuple(self.ring.convert(y, self.quot.ring) for y in x)
  1053. for x in self.quot._syzygies()]
  1054. def _in_terms_of_generators(self, elem):
  1055. return [self.ring.convert(x, self.quot.ring) for x in
  1056. self.quot._in_terms_of_generators(self.container.lift(elem))]
  1057. ##########################################################################
  1058. ## Quotient Modules ######################################################
  1059. ##########################################################################
  1060. class QuotientModuleElement(ModuleElement):
  1061. """Element of a quotient module."""
  1062. def eq(self, d1, d2):
  1063. """Equality comparison."""
  1064. return self.module.killed_module.contains(d1 - d2)
  1065. def __repr__(self):
  1066. return repr(self.data) + " + " + repr(self.module.killed_module)
  1067. class QuotientModule(Module):
  1068. """
  1069. Class for quotient modules.
  1070. Do not instantiate this directly. For subquotients, see the
  1071. SubQuotientModule class.
  1072. Attributes:
  1073. - base - the base module we are a quotient of
  1074. - killed_module - the submodule used to form the quotient
  1075. - rank of the base
  1076. """
  1077. dtype = QuotientModuleElement
  1078. def __init__(self, ring, base, submodule):
  1079. Module.__init__(self, ring)
  1080. if not base.is_submodule(submodule):
  1081. raise ValueError('%s is not a submodule of %s' % (submodule, base))
  1082. self.base = base
  1083. self.killed_module = submodule
  1084. self.rank = base.rank
  1085. def __repr__(self):
  1086. return repr(self.base) + "/" + repr(self.killed_module)
  1087. def is_zero(self):
  1088. """
  1089. Return True if ``self`` is a zero module.
  1090. This happens if and only if the base module is the same as the
  1091. submodule being killed.
  1092. Examples
  1093. ========
  1094. >>> from sympy.abc import x
  1095. >>> from sympy import QQ
  1096. >>> F = QQ.old_poly_ring(x).free_module(2)
  1097. >>> (F/[(1, 0)]).is_zero()
  1098. False
  1099. >>> (F/[(1, 0), (0, 1)]).is_zero()
  1100. True
  1101. """
  1102. return self.base == self.killed_module
  1103. def is_submodule(self, other):
  1104. """
  1105. Return True if ``other`` is a submodule of ``self``.
  1106. Examples
  1107. ========
  1108. >>> from sympy.abc import x
  1109. >>> from sympy import QQ
  1110. >>> Q = QQ.old_poly_ring(x).free_module(2) / [(x, x)]
  1111. >>> S = Q.submodule([1, 0])
  1112. >>> Q.is_submodule(S)
  1113. True
  1114. >>> S.is_submodule(Q)
  1115. False
  1116. """
  1117. if isinstance(other, QuotientModule):
  1118. return self.killed_module == other.killed_module and \
  1119. self.base.is_submodule(other.base)
  1120. if isinstance(other, SubQuotientModule):
  1121. return other.container == self
  1122. return False
  1123. def submodule(self, *gens, **opts):
  1124. """
  1125. Generate a submodule.
  1126. This is the same as taking a quotient of a submodule of the base
  1127. module.
  1128. Examples
  1129. ========
  1130. >>> from sympy.abc import x
  1131. >>> from sympy import QQ
  1132. >>> Q = QQ.old_poly_ring(x).free_module(2) / [(x, x)]
  1133. >>> Q.submodule([x, 0])
  1134. <[x, 0] + <[x, x]>>
  1135. """
  1136. return SubQuotientModule(gens, self, **opts)
  1137. def convert(self, elem, M=None):
  1138. """
  1139. Convert ``elem`` into the internal representation.
  1140. This method is called implicitly whenever computations involve elements
  1141. not in the internal representation.
  1142. Examples
  1143. ========
  1144. >>> from sympy.abc import x
  1145. >>> from sympy import QQ
  1146. >>> F = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
  1147. >>> F.convert([1, 0])
  1148. [1, 0] + <[1, 2], [1, x]>
  1149. """
  1150. if isinstance(elem, QuotientModuleElement):
  1151. if elem.module is self:
  1152. return elem
  1153. if self.killed_module.is_submodule(elem.module.killed_module):
  1154. return QuotientModuleElement(self, self.base.convert(elem.data))
  1155. raise CoercionFailed
  1156. return QuotientModuleElement(self, self.base.convert(elem))
  1157. def identity_hom(self):
  1158. """
  1159. Return the identity homomorphism on ``self``.
  1160. Examples
  1161. ========
  1162. >>> from sympy.abc import x
  1163. >>> from sympy import QQ
  1164. >>> M = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
  1165. >>> M.identity_hom()
  1166. Matrix([
  1167. [1, 0], : QQ[x]**2/<[1, 2], [1, x]> -> QQ[x]**2/<[1, 2], [1, x]>
  1168. [0, 1]])
  1169. """
  1170. return self.base.identity_hom().quotient_codomain(
  1171. self.killed_module).quotient_domain(self.killed_module)
  1172. def quotient_hom(self):
  1173. """
  1174. Return the quotient homomorphism to ``self``.
  1175. That is, return a homomorphism representing the natural map from
  1176. ``self.base`` to ``self``.
  1177. Examples
  1178. ========
  1179. >>> from sympy.abc import x
  1180. >>> from sympy import QQ
  1181. >>> M = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
  1182. >>> M.quotient_hom()
  1183. Matrix([
  1184. [1, 0], : QQ[x]**2 -> QQ[x]**2/<[1, 2], [1, x]>
  1185. [0, 1]])
  1186. """
  1187. return self.base.identity_hom().quotient_codomain(
  1188. self.killed_module)