Source code for sympy.polys.domains.domain

"""Implementation of :class:`Domain` class. """

from __future__ import print_function, division

from sympy.polys.domains.domainelement import DomainElement

from sympy.core import Basic, sympify
from sympy.core.compatibility import HAS_GMPY, integer_types, is_sequence

from sympy.polys.polyerrors import UnificationFailed, CoercionFailed, DomainError
from sympy.polys.orderings import lex
from sympy.polys.polyutils import _unify_gens

from sympy.utilities import default_sort_key, public
from sympy.core.decorators import deprecated

@public
[docs]class Domain(object): """Represents an abstract domain. """ dtype = None zero = None one = None is_Ring = False is_Field = False has_assoc_Ring = False has_assoc_Field = False is_FiniteField = is_FF = False is_IntegerRing = is_ZZ = False is_RationalField = is_QQ = False is_RealField = is_RR = False is_ComplexField = is_CC = False is_AlgebraicField = is_Algebraic = False is_PolynomialRing = is_Poly = False is_FractionField = is_Frac = False is_SymbolicDomain = is_EX = False is_Exact = True is_Numerical = False is_Simple = False is_Composite = False is_PID = False has_CharacteristicZero = False rep = None alias = None @property @deprecated(useinstead="is_Field", issue=12723, deprecated_since_version="1.1") def has_Field(self): return self.is_Field @property @deprecated(useinstead="is_Ring", issue=12723, deprecated_since_version="1.1") def has_Ring(self): return self.is_Ring def __init__(self): raise NotImplementedError def __str__(self): return self.rep def __repr__(self): return str(self) def __hash__(self): return hash((self.__class__.__name__, self.dtype)) def new(self, *args): return self.dtype(*args) @property def tp(self): return self.dtype def __call__(self, *args): """Construct an element of ``self`` domain from ``args``. """ return self.new(*args) def normal(self, *args): return self.dtype(*args)
[docs] def convert_from(self, element, base): """Convert ``element`` to ``self.dtype`` given the base domain. """ if base.alias is not None: method = "from_" + base.alias else: method = "from_" + base.__class__.__name__ _convert = getattr(self, method) if _convert is not None: result = _convert(element, base) if result is not None: return result raise CoercionFailed("can't convert %s of type %s from %s to %s" % (element, type(element), base, self))
[docs] def convert(self, element, base=None): """Convert ``element`` to ``self.dtype``. """ if base is not None: return self.convert_from(element, base) if self.of_type(element): return element from sympy.polys.domains import PythonIntegerRing, GMPYIntegerRing, GMPYRationalField, RealField, ComplexField if isinstance(element, integer_types): return self.convert_from(element, PythonIntegerRing()) if HAS_GMPY: integers = GMPYIntegerRing() if isinstance(element, integers.tp): return self.convert_from(element, integers) rationals = GMPYRationalField() if isinstance(element, rationals.tp): return self.convert_from(element, rationals) if isinstance(element, float): parent = RealField(tol=False) return self.convert_from(parent(element), parent) if isinstance(element, complex): parent = ComplexField(tol=False) return self.convert_from(parent(element), parent) if isinstance(element, DomainElement): return self.convert_from(element, element.parent()) # TODO: implement this in from_ methods if self.is_Numerical and getattr(element, 'is_ground', False): return self.convert(element.LC()) if isinstance(element, Basic): try: return self.from_sympy(element) except (TypeError, ValueError): pass else: # TODO: remove this branch if not is_sequence(element): try: element = sympify(element) if isinstance(element, Basic): return self.from_sympy(element) except (TypeError, ValueError): pass raise CoercionFailed("can't convert %s of type %s to %s" % (element, type(element), self))
[docs] def of_type(self, element): """Check if ``a`` is of type ``dtype``. """ return isinstance(element, self.tp) # XXX: this isn't correct, e.g. PolyElement
def __contains__(self, a): """Check if ``a`` belongs to this domain. """ try: self.convert(a) except CoercionFailed: return False return True
[docs] def to_sympy(self, a): """Convert ``a`` to a SymPy object. """ raise NotImplementedError
[docs] def from_sympy(self, a): """Convert a SymPy object to ``dtype``. """ raise NotImplementedError
[docs] def from_FF_python(K1, a, K0): """Convert ``ModularInteger(int)`` to ``dtype``. """ return None
[docs] def from_ZZ_python(K1, a, K0): """Convert a Python ``int`` object to ``dtype``. """ return None
[docs] def from_QQ_python(K1, a, K0): """Convert a Python ``Fraction`` object to ``dtype``. """ return None
[docs] def from_FF_gmpy(K1, a, K0): """Convert ``ModularInteger(mpz)`` to ``dtype``. """ return None
[docs] def from_ZZ_gmpy(K1, a, K0): """Convert a GMPY ``mpz`` object to ``dtype``. """ return None
[docs] def from_QQ_gmpy(K1, a, K0): """Convert a GMPY ``mpq`` object to ``dtype``. """ return None
[docs] def from_RealField(K1, a, K0): """Convert a real element object to ``dtype``. """ return None
[docs] def from_ComplexField(K1, a, K0): """Convert a complex element to ``dtype``. """ return None
[docs] def from_AlgebraicField(K1, a, K0): """Convert an algebraic number to ``dtype``. """ return None
[docs] def from_PolynomialRing(K1, a, K0): """Convert a polynomial to ``dtype``. """ if a.is_ground: return K1.convert(a.LC, K0.dom)
[docs] def from_FractionField(K1, a, K0): """Convert a rational function to ``dtype``. """ return None
[docs] def from_ExpressionDomain(K1, a, K0): """Convert a ``EX`` object to ``dtype``. """ return K1.from_sympy(a.ex)
[docs] def from_GlobalPolynomialRing(K1, a, K0): """Convert a polynomial to ``dtype``. """ if a.degree() <= 0: return K1.convert(a.LC(), K0.dom)
def from_GeneralizedPolynomialRing(K1, a, K0): return K1.from_FractionField(a, K0) def unify_with_symbols(K0, K1, symbols): if (K0.is_Composite and (set(K0.symbols) & set(symbols))) or (K1.is_Composite and (set(K1.symbols) & set(symbols))): raise UnificationFailed("can't unify %s with %s, given %s generators" % (K0, K1, tuple(symbols))) return K0.unify(K1)
[docs] def unify(K0, K1, symbols=None): """ Construct a minimal domain that contains elements of ``K0`` and ``K1``. Known domains (from smallest to largest): - ``GF(p)`` - ``ZZ`` - ``QQ`` - ``RR(prec, tol)`` - ``CC(prec, tol)`` - ``ALG(a, b, c)`` - ``K[x, y, z]`` - ``K(x, y, z)`` - ``EX`` """ if symbols is not None: return K0.unify_with_symbols(K1, symbols) if K0 == K1: return K0 if K0.is_EX: return K0 if K1.is_EX: return K1 if K0.is_Composite or K1.is_Composite: K0_ground = K0.dom if K0.is_Composite else K0 K1_ground = K1.dom if K1.is_Composite else K1 K0_symbols = K0.symbols if K0.is_Composite else () K1_symbols = K1.symbols if K1.is_Composite else () domain = K0_ground.unify(K1_ground) symbols = _unify_gens(K0_symbols, K1_symbols) order = K0.order if K0.is_Composite else K1.order if ((K0.is_FractionField and K1.is_PolynomialRing or K1.is_FractionField and K0.is_PolynomialRing) and (not K0_ground.is_Field or not K1_ground.is_Field) and domain.is_Field): domain = domain.get_ring() if K0.is_Composite and (not K1.is_Composite or K0.is_FractionField or K1.is_PolynomialRing): cls = K0.__class__ else: cls = K1.__class__ from sympy.polys.domains.old_polynomialring import GlobalPolynomialRing if cls == GlobalPolynomialRing: return cls(domain, symbols) return cls(domain, symbols, order) def mkinexact(cls, K0, K1): prec = max(K0.precision, K1.precision) tol = max(K0.tolerance, K1.tolerance) return cls(prec=prec, tol=tol) if K0.is_ComplexField and K1.is_ComplexField: return mkinexact(K0.__class__, K0, K1) if K0.is_ComplexField and K1.is_RealField: return mkinexact(K0.__class__, K0, K1) if K0.is_RealField and K1.is_ComplexField: return mkinexact(K1.__class__, K1, K0) if K0.is_RealField and K1.is_RealField: return mkinexact(K0.__class__, K0, K1) if K0.is_ComplexField or K0.is_RealField: return K0 if K1.is_ComplexField or K1.is_RealField: return K1 if K0.is_AlgebraicField and K1.is_AlgebraicField: return K0.__class__(K0.dom.unify(K1.dom), *_unify_gens(K0.orig_ext, K1.orig_ext)) elif K0.is_AlgebraicField: return K0 elif K1.is_AlgebraicField: return K1 if K0.is_RationalField: return K0 if K1.is_RationalField: return K1 if K0.is_IntegerRing: return K0 if K1.is_IntegerRing: return K1 if K0.is_FiniteField and K1.is_FiniteField: return K0.__class__(max(K0.mod, K1.mod, key=default_sort_key)) from sympy.polys.domains import EX return EX
def __eq__(self, other): """Returns ``True`` if two domains are equivalent. """ return isinstance(other, Domain) and self.dtype == other.dtype def __ne__(self, other): """Returns ``False`` if two domains are equivalent. """ return not self.__eq__(other)
[docs] def map(self, seq): """Rersively apply ``self`` to all elements of ``seq``. """ result = [] for elt in seq: if isinstance(elt, list): result.append(self.map(elt)) else: result.append(self(elt)) return result
[docs] def get_ring(self): """Returns a ring associated with ``self``. """ raise DomainError('there is no ring associated with %s' % self)
[docs] def get_field(self): """Returns a field associated with ``self``. """ raise DomainError('there is no field associated with %s' % self)
[docs] def get_exact(self): """Returns an exact domain associated with ``self``. """ return self
def __getitem__(self, symbols): """The mathematical way to make a polynomial ring. """ if hasattr(symbols, '__iter__'): return self.poly_ring(*symbols) else: return self.poly_ring(symbols)
[docs] def poly_ring(self, *symbols, **kwargs): """Returns a polynomial ring, i.e. `K[X]`. """ from sympy.polys.domains.polynomialring import PolynomialRing return PolynomialRing(self, symbols, kwargs.get("order", lex))
[docs] def frac_field(self, *symbols, **kwargs): """Returns a fraction field, i.e. `K(X)`. """ from sympy.polys.domains.fractionfield import FractionField return FractionField(self, symbols, kwargs.get("order", lex))
[docs] def old_poly_ring(self, *symbols, **kwargs): """Returns a polynomial ring, i.e. `K[X]`. """ from sympy.polys.domains.old_polynomialring import PolynomialRing return PolynomialRing(self, *symbols, **kwargs)
[docs] def old_frac_field(self, *symbols, **kwargs): """Returns a fraction field, i.e. `K(X)`. """ from sympy.polys.domains.old_fractionfield import FractionField return FractionField(self, *symbols, **kwargs)
[docs] def algebraic_field(self, *extension): r"""Returns an algebraic field, i.e. `K(\alpha, \ldots)`. """ raise DomainError("can't create algebraic field over %s" % self)
[docs] def inject(self, *symbols): """Inject generators into this domain. """ raise NotImplementedError
[docs] def is_zero(self, a): """Returns True if ``a`` is zero. """ return not a
[docs] def is_one(self, a): """Returns True if ``a`` is one. """ return a == self.one
[docs] def is_positive(self, a): """Returns True if ``a`` is positive. """ return a > 0
[docs] def is_negative(self, a): """Returns True if ``a`` is negative. """ return a < 0
[docs] def is_nonpositive(self, a): """Returns True if ``a`` is non-positive. """ return a <= 0
[docs] def is_nonnegative(self, a): """Returns True if ``a`` is non-negative. """ return a >= 0
[docs] def abs(self, a): """Absolute value of ``a``, implies ``__abs__``. """ return abs(a)
[docs] def neg(self, a): """Returns ``a`` negated, implies ``__neg__``. """ return -a
[docs] def pos(self, a): """Returns ``a`` positive, implies ``__pos__``. """ return +a
[docs] def add(self, a, b): """Sum of ``a`` and ``b``, implies ``__add__``. """ return a + b
[docs] def sub(self, a, b): """Difference of ``a`` and ``b``, implies ``__sub__``. """ return a - b
[docs] def mul(self, a, b): """Product of ``a`` and ``b``, implies ``__mul__``. """ return a * b
[docs] def pow(self, a, b): """Raise ``a`` to power ``b``, implies ``__pow__``. """ return a ** b
[docs] def exquo(self, a, b): """Exact quotient of ``a`` and ``b``, implies something. """ raise NotImplementedError
[docs] def quo(self, a, b): """Quotient of ``a`` and ``b``, implies something. """ raise NotImplementedError
[docs] def rem(self, a, b): """Remainder of ``a`` and ``b``, implies ``__mod__``. """ raise NotImplementedError
[docs] def div(self, a, b): """Division of ``a`` and ``b``, implies something. """ raise NotImplementedError
[docs] def invert(self, a, b): """Returns inversion of ``a mod b``, implies something. """ raise NotImplementedError
[docs] def revert(self, a): """Returns ``a**(-1)`` if possible. """ raise NotImplementedError
[docs] def numer(self, a): """Returns numerator of ``a``. """ raise NotImplementedError
[docs] def denom(self, a): """Returns denominator of ``a``. """ raise NotImplementedError
[docs] def half_gcdex(self, a, b): """Half extended GCD of ``a`` and ``b``. """ s, t, h = self.gcdex(a, b) return s, h
[docs] def gcdex(self, a, b): """Extended GCD of ``a`` and ``b``. """ raise NotImplementedError
[docs] def cofactors(self, a, b): """Returns GCD and cofactors of ``a`` and ``b``. """ gcd = self.gcd(a, b) cfa = self.quo(a, gcd) cfb = self.quo(b, gcd) return gcd, cfa, cfb
[docs] def gcd(self, a, b): """Returns GCD of ``a`` and ``b``. """ raise NotImplementedError
[docs] def lcm(self, a, b): """Returns LCM of ``a`` and ``b``. """ raise NotImplementedError
[docs] def log(self, a, b): """Returns b-base logarithm of ``a``. """ raise NotImplementedError
[docs] def sqrt(self, a): """Returns square root of ``a``. """ raise NotImplementedError
[docs] def evalf(self, a, prec=None, **options): """Returns numerical approximation of ``a``. """ return self.to_sympy(a).evalf(prec, **options)
n = evalf def real(self, a): return a def imag(self, a): return self.zero
[docs] def almosteq(self, a, b, tolerance=None): """Check if ``a`` and ``b`` are almost equal. """ return a == b
[docs] def characteristic(self): """Return the characteristic of this domain. """ raise NotImplementedError('characteristic()')