modules.py 46 KB

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