polynomialring.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. """Implementation of :class:`PolynomialRing` class. """
  2. from sympy.polys.domains.ring import Ring
  3. from sympy.polys.domains.compositedomain import CompositeDomain
  4. from sympy.polys.polyerrors import CoercionFailed, GeneratorsError
  5. from sympy.utilities import public
  6. @public
  7. class PolynomialRing(Ring, CompositeDomain):
  8. """A class for representing multivariate polynomial rings. """
  9. is_PolynomialRing = is_Poly = True
  10. has_assoc_Ring = True
  11. has_assoc_Field = True
  12. def __init__(self, domain_or_ring, symbols=None, order=None):
  13. from sympy.polys.rings import PolyRing
  14. if isinstance(domain_or_ring, PolyRing) and symbols is None and order is None:
  15. ring = domain_or_ring
  16. else:
  17. ring = PolyRing(symbols, domain_or_ring, order)
  18. self.ring = ring
  19. self.dtype = ring.dtype
  20. self.gens = ring.gens
  21. self.ngens = ring.ngens
  22. self.symbols = ring.symbols
  23. self.domain = ring.domain
  24. if symbols:
  25. if ring.domain.is_Field and ring.domain.is_Exact and len(symbols)==1:
  26. self.is_PID = True
  27. # TODO: remove this
  28. self.dom = self.domain
  29. def new(self, element):
  30. return self.ring.ring_new(element)
  31. def of_type(self, element):
  32. """Check if ``a`` is of type ``dtype``. """
  33. return self.ring.is_element(element)
  34. @property
  35. def zero(self):
  36. return self.ring.zero
  37. @property
  38. def one(self):
  39. return self.ring.one
  40. @property
  41. def order(self):
  42. return self.ring.order
  43. def __str__(self):
  44. return str(self.domain) + '[' + ','.join(map(str, self.symbols)) + ']'
  45. def __hash__(self):
  46. return hash((self.__class__.__name__, self.ring, self.domain, self.symbols))
  47. def __eq__(self, other):
  48. """Returns `True` if two domains are equivalent. """
  49. if not isinstance(other, PolynomialRing):
  50. return NotImplemented
  51. return self.ring == other.ring
  52. def is_unit(self, a):
  53. """Returns ``True`` if ``a`` is a unit of ``self``"""
  54. if not a.is_ground:
  55. return False
  56. K = self.domain
  57. return K.is_unit(K.convert_from(a, self))
  58. def canonical_unit(self, a):
  59. u = self.domain.canonical_unit(a.LC)
  60. return self.ring.ground_new(u)
  61. def to_sympy(self, a):
  62. """Convert `a` to a SymPy object. """
  63. return a.as_expr()
  64. def from_sympy(self, a):
  65. """Convert SymPy's expression to `dtype`. """
  66. return self.ring.from_expr(a)
  67. def from_ZZ(K1, a, K0):
  68. """Convert a Python `int` object to `dtype`. """
  69. return K1(K1.domain.convert(a, K0))
  70. def from_ZZ_python(K1, a, K0):
  71. """Convert a Python `int` object to `dtype`. """
  72. return K1(K1.domain.convert(a, K0))
  73. def from_QQ(K1, a, K0):
  74. """Convert a Python `Fraction` object to `dtype`. """
  75. return K1(K1.domain.convert(a, K0))
  76. def from_QQ_python(K1, a, K0):
  77. """Convert a Python `Fraction` object to `dtype`. """
  78. return K1(K1.domain.convert(a, K0))
  79. def from_ZZ_gmpy(K1, a, K0):
  80. """Convert a GMPY `mpz` object to `dtype`. """
  81. return K1(K1.domain.convert(a, K0))
  82. def from_QQ_gmpy(K1, a, K0):
  83. """Convert a GMPY `mpq` object to `dtype`. """
  84. return K1(K1.domain.convert(a, K0))
  85. def from_GaussianIntegerRing(K1, a, K0):
  86. """Convert a `GaussianInteger` object to `dtype`. """
  87. return K1(K1.domain.convert(a, K0))
  88. def from_GaussianRationalField(K1, a, K0):
  89. """Convert a `GaussianRational` object to `dtype`. """
  90. return K1(K1.domain.convert(a, K0))
  91. def from_RealField(K1, a, K0):
  92. """Convert a mpmath `mpf` object to `dtype`. """
  93. return K1(K1.domain.convert(a, K0))
  94. def from_ComplexField(K1, a, K0):
  95. """Convert a mpmath `mpf` object to `dtype`. """
  96. return K1(K1.domain.convert(a, K0))
  97. def from_AlgebraicField(K1, a, K0):
  98. """Convert an algebraic number to ``dtype``. """
  99. if K1.domain != K0:
  100. a = K1.domain.convert_from(a, K0)
  101. if a is not None:
  102. return K1.new(a)
  103. def from_PolynomialRing(K1, a, K0):
  104. """Convert a polynomial to ``dtype``. """
  105. try:
  106. return a.set_ring(K1.ring)
  107. except (CoercionFailed, GeneratorsError):
  108. return None
  109. def from_FractionField(K1, a, K0):
  110. """Convert a rational function to ``dtype``. """
  111. if K1.domain == K0:
  112. return K1.ring.from_list([a])
  113. q, r = K0.numer(a).div(K0.denom(a))
  114. if r.is_zero:
  115. return K1.from_PolynomialRing(q, K0.field.ring.to_domain())
  116. else:
  117. return None
  118. def from_GlobalPolynomialRing(K1, a, K0):
  119. """Convert from old poly ring to ``dtype``. """
  120. if K1.symbols == K0.gens:
  121. ad = a.to_dict()
  122. if K1.domain != K0.domain:
  123. ad = {m: K1.domain.convert(c) for m, c in ad.items()}
  124. return K1(ad)
  125. elif a.is_ground and K0.domain == K1:
  126. return K1.convert_from(a.to_list()[0], K0.domain)
  127. def get_field(self):
  128. """Returns a field associated with `self`. """
  129. return self.ring.to_field().to_domain()
  130. def is_positive(self, a):
  131. """Returns True if `LC(a)` is positive. """
  132. return self.domain.is_positive(a.LC)
  133. def is_negative(self, a):
  134. """Returns True if `LC(a)` is negative. """
  135. return self.domain.is_negative(a.LC)
  136. def is_nonpositive(self, a):
  137. """Returns True if `LC(a)` is non-positive. """
  138. return self.domain.is_nonpositive(a.LC)
  139. def is_nonnegative(self, a):
  140. """Returns True if `LC(a)` is non-negative. """
  141. return self.domain.is_nonnegative(a.LC)
  142. def gcdex(self, a, b):
  143. """Extended GCD of `a` and `b`. """
  144. return a.gcdex(b)
  145. def gcd(self, a, b):
  146. """Returns GCD of `a` and `b`. """
  147. return a.gcd(b)
  148. def lcm(self, a, b):
  149. """Returns LCM of `a` and `b`. """
  150. return a.lcm(b)
  151. def factorial(self, a):
  152. """Returns factorial of `a`. """
  153. return self.dtype(self.domain.factorial(a))