Buckets:
MisterAI/LocalAI_Demo_backends / cpu-diffusers.upgrade-tmp /venv /lib /python3.10 /site-packages /sympy /polys /puiseux.py
| """ | |
| Puiseux rings. These are used by the ring_series module to represented | |
| truncated Puiseux series. Elements of a Puiseux ring are like polynomials | |
| except that the exponents can be negative or rational rather than just | |
| non-negative integers. | |
| """ | |
| # Previously the ring_series module used PolyElement to represent Puiseux | |
| # series. This is problematic because it means that PolyElement has to support | |
| # negative and non-integer exponents which most polynomial representations do | |
| # not support. This module provides an implementation of a ring for Puiseux | |
| # series that can be used by ring_series without breaking the basic invariants | |
| # of polynomial rings. | |
| # | |
| # Ideally there would be more of a proper series type that can keep track of | |
| # not just the leading terms of a truncated series but also the precision | |
| # of the series. For now the rings here are just introduced to keep the | |
| # interface that ring_series was using before. | |
| from __future__ import annotations | |
| from sympy.polys.domains import QQ | |
| from sympy.polys.rings import PolyRing, PolyElement | |
| from sympy.core.add import Add | |
| from sympy.core.mul import Mul | |
| from sympy.external.gmpy import gcd, lcm | |
| from typing import TYPE_CHECKING | |
| if TYPE_CHECKING: | |
| from typing import Any, Unpack | |
| from sympy.core.expr import Expr | |
| from sympy.polys.domains import Domain | |
| from collections.abc import Iterable, Iterator | |
| def puiseux_ring( | |
| symbols: str | list[Expr], domain: Domain | |
| ) -> tuple[PuiseuxRing, Unpack[tuple[PuiseuxPoly, ...]]]: | |
| """Construct a Puiseux ring. | |
| This function constructs a Puiseux ring with the given symbols and domain. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x, y = puiseux_ring('x y', QQ) | |
| >>> R | |
| PuiseuxRing((x, y), QQ) | |
| >>> p = 5*x**QQ(1,2) + 7/y | |
| >>> p | |
| 7*y**(-1) + 5*x**(1/2) | |
| """ | |
| ring = PuiseuxRing(symbols, domain) | |
| return (ring,) + ring.gens # type: ignore | |
| class PuiseuxRing: | |
| """Ring of Puiseux polynomials. | |
| A Puiseux polynomial is a truncated Puiseux series. The exponents of the | |
| monomials can be negative or rational numbers. This ring is used by the | |
| ring_series module: | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> from sympy.polys.ring_series import rs_exp, rs_nth_root | |
| >>> ring, x, y = puiseux_ring('x y', QQ) | |
| >>> f = x**2 + y**3 | |
| >>> f | |
| y**3 + x**2 | |
| >>> f.diff(x) | |
| 2*x | |
| >>> rs_exp(x, x, 5) | |
| 1 + x + 1/2*x**2 + 1/6*x**3 + 1/24*x**4 | |
| Importantly the Puiseux ring can represent truncated series with negative | |
| and fractional exponents: | |
| >>> f = 1/x + 1/y**2 | |
| >>> f | |
| x**(-1) + y**(-2) | |
| >>> f.diff(x) | |
| -1*x**(-2) | |
| >>> rs_nth_root(8*x + x**2 + x**3, 3, x, 5) | |
| 2*x**(1/3) + 1/12*x**(4/3) + 23/288*x**(7/3) + -139/20736*x**(10/3) | |
| See Also | |
| ======== | |
| sympy.polys.ring_series.rs_series | |
| PuiseuxPoly | |
| """ | |
| def __init__(self, symbols: str | list[Expr], domain: Domain): | |
| poly_ring = PolyRing(symbols, domain) | |
| domain = poly_ring.domain | |
| ngens = poly_ring.ngens | |
| self.poly_ring = poly_ring | |
| self.domain = domain | |
| self.symbols = poly_ring.symbols | |
| self.gens = tuple([self.from_poly(g) for g in poly_ring.gens]) | |
| self.ngens = ngens | |
| self.zero = self.from_poly(poly_ring.zero) | |
| self.one = self.from_poly(poly_ring.one) | |
| self.zero_monom = poly_ring.zero_monom # type: ignore | |
| self.monomial_mul = poly_ring.monomial_mul # type: ignore | |
| def __repr__(self) -> str: | |
| return f"PuiseuxRing({self.symbols}, {self.domain})" | |
| def __eq__(self, other: Any) -> bool: | |
| if not isinstance(other, PuiseuxRing): | |
| return NotImplemented | |
| return self.symbols == other.symbols and self.domain == other.domain | |
| def from_poly(self, poly: PolyElement) -> PuiseuxPoly: | |
| """Create a Puiseux polynomial from a polynomial. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.rings import ring | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R1, x1 = ring('x', QQ) | |
| >>> R2, x2 = puiseux_ring('x', QQ) | |
| >>> R2.from_poly(x1**2) | |
| x**2 | |
| """ | |
| return PuiseuxPoly(poly, self) | |
| def from_dict(self, terms: dict[tuple[int, ...], Any]) -> PuiseuxPoly: | |
| """Create a Puiseux polynomial from a dictionary of terms. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x = puiseux_ring('x', QQ) | |
| >>> R.from_dict({(QQ(1,2),): QQ(3)}) | |
| 3*x**(1/2) | |
| """ | |
| return PuiseuxPoly.from_dict(terms, self) | |
| def from_int(self, n: int) -> PuiseuxPoly: | |
| """Create a Puiseux polynomial from an integer. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x = puiseux_ring('x', QQ) | |
| >>> R.from_int(3) | |
| 3 | |
| """ | |
| return self.from_poly(self.poly_ring(n)) | |
| def domain_new(self, arg: Any) -> Any: | |
| """Create a new element of the domain. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x = puiseux_ring('x', QQ) | |
| >>> R.domain_new(3) | |
| 3 | |
| >>> QQ.of_type(_) | |
| True | |
| """ | |
| return self.poly_ring.domain_new(arg) | |
| def ground_new(self, arg: Any) -> PuiseuxPoly: | |
| """Create a new element from a ground element. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring, PuiseuxPoly | |
| >>> R, x = puiseux_ring('x', QQ) | |
| >>> R.ground_new(3) | |
| 3 | |
| >>> isinstance(_, PuiseuxPoly) | |
| True | |
| """ | |
| return self.from_poly(self.poly_ring.ground_new(arg)) | |
| def __call__(self, arg: Any) -> PuiseuxPoly: | |
| """Coerce an element into the ring. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x = puiseux_ring('x', QQ) | |
| >>> R(3) | |
| 3 | |
| >>> R({(QQ(1,2),): QQ(3)}) | |
| 3*x**(1/2) | |
| """ | |
| if isinstance(arg, dict): | |
| return self.from_dict(arg) | |
| else: | |
| return self.from_poly(self.poly_ring(arg)) | |
| def index(self, x: PuiseuxPoly) -> int: | |
| """Return the index of a generator. | |
| >>> from sympy.polys.domains import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x, y = puiseux_ring('x y', QQ) | |
| >>> R.index(x) | |
| 0 | |
| >>> R.index(y) | |
| 1 | |
| """ | |
| return self.gens.index(x) | |
| def _div_poly_monom(poly: PolyElement, monom: Iterable[int]) -> PolyElement: | |
| ring = poly.ring | |
| div = ring.monomial_div | |
| return ring.from_dict({div(m, monom): c for m, c in poly.terms()}) | |
| def _mul_poly_monom(poly: PolyElement, monom: Iterable[int]) -> PolyElement: | |
| ring = poly.ring | |
| mul = ring.monomial_mul | |
| return ring.from_dict({mul(m, monom): c for m, c in poly.terms()}) | |
| def _div_monom(monom: Iterable[int], div: Iterable[int]) -> tuple[int, ...]: | |
| return tuple(mi - di for mi, di in zip(monom, div)) | |
| class PuiseuxPoly: | |
| """Puiseux polynomial. Represents a truncated Puiseux series. | |
| See the :class:`PuiseuxRing` class for more information. | |
| >>> from sympy import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x, y = puiseux_ring('x, y', QQ) | |
| >>> p = 5*x**2 + 7*y**3 | |
| >>> p | |
| 7*y**3 + 5*x**2 | |
| The internal representation of a Puiseux polynomial wraps a normal | |
| polynomial. To support negative powers the polynomial is considered to be | |
| divided by a monomial. | |
| >>> p2 = 1/x + 1/y**2 | |
| >>> p2.monom # x*y**2 | |
| (1, 2) | |
| >>> p2.poly | |
| x + y**2 | |
| >>> (y**2 + x) / (x*y**2) == p2 | |
| True | |
| To support fractional powers the polynomial is considered to be a function | |
| of ``x**(1/nx), y**(1/ny), ...``. The representation keeps track of a | |
| monomial and a list of exponent denominators so that the polynomial can be | |
| used to represent both negative and fractional powers. | |
| >>> p3 = x**QQ(1,2) + y**QQ(2,3) | |
| >>> p3.ns | |
| (2, 3) | |
| >>> p3.poly | |
| x + y**2 | |
| See Also | |
| ======== | |
| sympy.polys.puiseux.PuiseuxRing | |
| sympy.polys.rings.PolyElement | |
| """ | |
| ring: PuiseuxRing | |
| poly: PolyElement | |
| monom: tuple[int, ...] | None | |
| ns: tuple[int, ...] | None | |
| def __new__(cls, poly: PolyElement, ring: PuiseuxRing) -> PuiseuxPoly: | |
| return cls._new(ring, poly, None, None) | |
| def _new( | |
| cls, | |
| ring: PuiseuxRing, | |
| poly: PolyElement, | |
| monom: tuple[int, ...] | None, | |
| ns: tuple[int, ...] | None, | |
| ) -> PuiseuxPoly: | |
| poly, monom, ns = cls._normalize(poly, monom, ns) | |
| return cls._new_raw(ring, poly, monom, ns) | |
| def _new_raw( | |
| cls, | |
| ring: PuiseuxRing, | |
| poly: PolyElement, | |
| monom: tuple[int, ...] | None, | |
| ns: tuple[int, ...] | None, | |
| ) -> PuiseuxPoly: | |
| obj = object.__new__(cls) | |
| obj.ring = ring | |
| obj.poly = poly | |
| obj.monom = monom | |
| obj.ns = ns | |
| return obj | |
| def __eq__(self, other: Any) -> bool: | |
| if isinstance(other, PuiseuxPoly): | |
| return ( | |
| self.poly == other.poly | |
| and self.monom == other.monom | |
| and self.ns == other.ns | |
| ) | |
| elif self.monom is None and self.ns is None: | |
| return self.poly.__eq__(other) | |
| else: | |
| return NotImplemented | |
| def _normalize( | |
| cls, | |
| poly: PolyElement, | |
| monom: tuple[int, ...] | None, | |
| ns: tuple[int, ...] | None, | |
| ) -> tuple[PolyElement, tuple[int, ...] | None, tuple[int, ...] | None]: | |
| if monom is None and ns is None: | |
| return poly, None, None | |
| if monom is not None: | |
| degs = [max(d, 0) for d in poly.tail_degrees()] | |
| if all(di >= mi for di, mi in zip(degs, monom)): | |
| poly = _div_poly_monom(poly, monom) | |
| monom = None | |
| elif any(degs): | |
| poly = _div_poly_monom(poly, degs) | |
| monom = _div_monom(monom, degs) | |
| if ns is not None: | |
| factors_d, [poly_d] = poly.deflate() | |
| degrees = poly.degrees() | |
| monom_d = monom if monom is not None else [0] * len(degrees) | |
| ns_new = [] | |
| monom_new = [] | |
| inflations = [] | |
| for fi, ni, di, mi in zip(factors_d, ns, degrees, monom_d): | |
| if di == 0: | |
| g = gcd(ni, mi) | |
| else: | |
| g = gcd(fi, ni, mi) | |
| ns_new.append(ni // g) | |
| monom_new.append(mi // g) | |
| inflations.append(fi // g) | |
| if any(infl > 1 for infl in inflations): | |
| poly_d = poly_d.inflate(inflations) | |
| poly = poly_d | |
| if monom is not None: | |
| monom = tuple(monom_new) | |
| if all(n == 1 for n in ns_new): | |
| ns = None | |
| else: | |
| ns = tuple(ns_new) | |
| return poly, monom, ns | |
| def _monom_fromint( | |
| cls, | |
| monom: tuple[int, ...], | |
| dmonom: tuple[int, ...] | None, | |
| ns: tuple[int, ...] | None, | |
| ) -> tuple[Any, ...]: | |
| if dmonom is not None and ns is not None: | |
| return tuple(QQ(mi - di, ni) for mi, di, ni in zip(monom, dmonom, ns)) | |
| elif dmonom is not None: | |
| return tuple(QQ(mi - di) for mi, di in zip(monom, dmonom)) | |
| elif ns is not None: | |
| return tuple(QQ(mi, ni) for mi, ni in zip(monom, ns)) | |
| else: | |
| return tuple(QQ(mi) for mi in monom) | |
| def _monom_toint( | |
| cls, | |
| monom: tuple[Any, ...], | |
| dmonom: tuple[int, ...] | None, | |
| ns: tuple[int, ...] | None, | |
| ) -> tuple[int, ...]: | |
| if dmonom is not None and ns is not None: | |
| return tuple( | |
| int((mi * ni).numerator + di) for mi, di, ni in zip(monom, dmonom, ns) | |
| ) | |
| elif dmonom is not None: | |
| return tuple(int(mi.numerator + di) for mi, di in zip(monom, dmonom)) | |
| elif ns is not None: | |
| return tuple(int((mi * ni).numerator) for mi, ni in zip(monom, ns)) | |
| else: | |
| return tuple(int(mi.numerator) for mi in monom) | |
| def itermonoms(self) -> Iterator[tuple[Any, ...]]: | |
| """Iterate over the monomials of a Puiseux polynomial. | |
| >>> from sympy import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x, y = puiseux_ring('x, y', QQ) | |
| >>> p = 5*x**2 + 7*y**3 | |
| >>> list(p.itermonoms()) | |
| [(2, 0), (0, 3)] | |
| >>> p[(2, 0)] | |
| 5 | |
| """ | |
| monom, ns = self.monom, self.ns | |
| for m in self.poly.itermonoms(): | |
| yield self._monom_fromint(m, monom, ns) | |
| def monoms(self) -> list[tuple[Any, ...]]: | |
| """Return a list of the monomials of a Puiseux polynomial.""" | |
| return list(self.itermonoms()) | |
| def __iter__(self) -> Iterator[tuple[tuple[Any, ...], Any]]: | |
| return self.itermonoms() | |
| def __getitem__(self, monom: tuple[int, ...]) -> Any: | |
| monom = self._monom_toint(monom, self.monom, self.ns) | |
| return self.poly[monom] | |
| def __len__(self) -> int: | |
| return len(self.poly) | |
| def iterterms(self) -> Iterator[tuple[tuple[Any, ...], Any]]: | |
| """Iterate over the terms of a Puiseux polynomial. | |
| >>> from sympy import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x, y = puiseux_ring('x, y', QQ) | |
| >>> p = 5*x**2 + 7*y**3 | |
| >>> list(p.iterterms()) | |
| [((2, 0), 5), ((0, 3), 7)] | |
| """ | |
| monom, ns = self.monom, self.ns | |
| for m, coeff in self.poly.iterterms(): | |
| mq = self._monom_fromint(m, monom, ns) | |
| yield mq, coeff | |
| def terms(self) -> list[tuple[tuple[Any, ...], Any]]: | |
| """Return a list of the terms of a Puiseux polynomial.""" | |
| return list(self.iterterms()) | |
| def is_term(self) -> bool: | |
| """Return True if the Puiseux polynomial is a single term.""" | |
| return self.poly.is_term | |
| def to_dict(self) -> dict[tuple[int, ...], Any]: | |
| """Return a dictionary representation of a Puiseux polynomial.""" | |
| return dict(self.iterterms()) | |
| def from_dict( | |
| cls, terms: dict[tuple[Any, ...], Any], ring: PuiseuxRing | |
| ) -> PuiseuxPoly: | |
| """Create a Puiseux polynomial from a dictionary of terms. | |
| >>> from sympy import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring, PuiseuxPoly | |
| >>> R, x = puiseux_ring('x', QQ) | |
| >>> PuiseuxPoly.from_dict({(QQ(1,2),): QQ(3)}, R) | |
| 3*x**(1/2) | |
| >>> R.from_dict({(QQ(1,2),): QQ(3)}) | |
| 3*x**(1/2) | |
| """ | |
| ns = [1] * ring.ngens | |
| mon = [0] * ring.ngens | |
| for mo in terms: | |
| ns = [lcm(n, m.denominator) for n, m in zip(ns, mo)] | |
| mon = [min(m, n) for m, n in zip(mo, mon)] | |
| if not any(mon): | |
| monom = None | |
| else: | |
| monom = tuple(-int((m * n).numerator) for m, n in zip(mon, ns)) | |
| if all(n == 1 for n in ns): | |
| ns_final = None | |
| else: | |
| ns_final = tuple(ns) | |
| terms_p = {cls._monom_toint(m, monom, ns_final): coeff for m, coeff in terms.items()} | |
| poly = ring.poly_ring.from_dict(terms_p) | |
| return cls._new(ring, poly, monom, ns_final) | |
| def as_expr(self) -> Expr: | |
| """Convert a Puiseux polynomial to :class:`~sympy.core.expr.Expr`. | |
| >>> from sympy import QQ, Expr | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x = puiseux_ring('x', QQ) | |
| >>> p = 5*x**2 + 7*x**3 | |
| >>> p.as_expr() | |
| 7*x**3 + 5*x**2 | |
| >>> isinstance(_, Expr) | |
| True | |
| """ | |
| ring = self.ring | |
| dom = ring.domain | |
| symbols = ring.symbols | |
| terms = [] | |
| for monom, coeff in self.iterterms(): | |
| coeff_expr = dom.to_sympy(coeff) | |
| monoms_expr = [] | |
| for i, m in enumerate(monom): | |
| monoms_expr.append(symbols[i] ** m) | |
| terms.append(Mul(coeff_expr, *monoms_expr)) | |
| return Add(*terms) | |
| def __repr__(self) -> str: | |
| def format_power(base: str, exp: int) -> str: | |
| if exp == 1: | |
| return base | |
| elif exp >= 0 and int(exp) == exp: | |
| return f"{base}**{exp}" | |
| else: | |
| return f"{base}**({exp})" | |
| ring = self.ring | |
| dom = ring.domain | |
| syms = [str(s) for s in ring.symbols] | |
| terms_str = [] | |
| for monom, coeff in sorted(self.terms()): | |
| monom_str = "*".join(format_power(s, e) for s, e in zip(syms, monom) if e) | |
| if coeff == dom.one: | |
| if monom_str: | |
| terms_str.append(monom_str) | |
| else: | |
| terms_str.append("1") | |
| elif not monom_str: | |
| terms_str.append(str(coeff)) | |
| else: | |
| terms_str.append(f"{coeff}*{monom_str}") | |
| return " + ".join(terms_str) | |
| def _unify( | |
| self, other: PuiseuxPoly | |
| ) -> tuple[ | |
| PolyElement, PolyElement, tuple[int, ...] | None, tuple[int, ...] | None | |
| ]: | |
| """Bring two Puiseux polynomials to a common monom and ns.""" | |
| poly1, monom1, ns1 = self.poly, self.monom, self.ns | |
| poly2, monom2, ns2 = other.poly, other.monom, other.ns | |
| if monom1 == monom2 and ns1 == ns2: | |
| return poly1, poly2, monom1, ns1 | |
| if ns1 == ns2: | |
| ns = ns1 | |
| elif ns1 is not None and ns2 is not None: | |
| ns = tuple(lcm(n1, n2) for n1, n2 in zip(ns1, ns2)) | |
| f1 = [n // n1 for n, n1 in zip(ns, ns1)] | |
| f2 = [n // n2 for n, n2 in zip(ns, ns2)] | |
| poly1 = poly1.inflate(f1) | |
| poly2 = poly2.inflate(f2) | |
| if monom1 is not None: | |
| monom1 = tuple(m * f for m, f in zip(monom1, f1)) | |
| if monom2 is not None: | |
| monom2 = tuple(m * f for m, f in zip(monom2, f2)) | |
| elif ns2 is not None: | |
| ns = ns2 | |
| poly1 = poly1.inflate(ns) | |
| if monom1 is not None: | |
| monom1 = tuple(m * n for m, n in zip(monom1, ns)) | |
| elif ns1 is not None: | |
| ns = ns1 | |
| poly2 = poly2.inflate(ns) | |
| if monom2 is not None: | |
| monom2 = tuple(m * n for m, n in zip(monom2, ns)) | |
| else: | |
| assert False | |
| if monom1 == monom2: | |
| monom = monom1 | |
| elif monom1 is not None and monom2 is not None: | |
| monom = tuple(max(m1, m2) for m1, m2 in zip(monom1, monom2)) | |
| poly1 = _mul_poly_monom(poly1, _div_monom(monom, monom1)) | |
| poly2 = _mul_poly_monom(poly2, _div_monom(monom, monom2)) | |
| elif monom2 is not None: | |
| monom = monom2 | |
| poly1 = _mul_poly_monom(poly1, monom2) | |
| elif monom1 is not None: | |
| monom = monom1 | |
| poly2 = _mul_poly_monom(poly2, monom1) | |
| else: | |
| assert False | |
| return poly1, poly2, monom, ns | |
| def __pos__(self) -> PuiseuxPoly: | |
| return self | |
| def __neg__(self) -> PuiseuxPoly: | |
| return self._new_raw(self.ring, -self.poly, self.monom, self.ns) | |
| def __add__(self, other: Any) -> PuiseuxPoly: | |
| if isinstance(other, PuiseuxPoly): | |
| if self.ring != other.ring: | |
| raise ValueError("Cannot add Puiseux polynomials from different rings") | |
| return self._add(other) | |
| domain = self.ring.domain | |
| if isinstance(other, int): | |
| return self._add_ground(domain.convert_from(QQ(other), QQ)) | |
| elif domain.of_type(other): | |
| return self._add_ground(other) | |
| else: | |
| return NotImplemented | |
| def __radd__(self, other: Any) -> PuiseuxPoly: | |
| domain = self.ring.domain | |
| if isinstance(other, int): | |
| return self._add_ground(domain.convert_from(QQ(other), QQ)) | |
| elif domain.of_type(other): | |
| return self._add_ground(other) | |
| else: | |
| return NotImplemented | |
| def __sub__(self, other: Any) -> PuiseuxPoly: | |
| if isinstance(other, PuiseuxPoly): | |
| if self.ring != other.ring: | |
| raise ValueError( | |
| "Cannot subtract Puiseux polynomials from different rings" | |
| ) | |
| return self._sub(other) | |
| domain = self.ring.domain | |
| if isinstance(other, int): | |
| return self._sub_ground(domain.convert_from(QQ(other), QQ)) | |
| elif domain.of_type(other): | |
| return self._sub_ground(other) | |
| else: | |
| return NotImplemented | |
| def __rsub__(self, other: Any) -> PuiseuxPoly: | |
| domain = self.ring.domain | |
| if isinstance(other, int): | |
| return self._rsub_ground(domain.convert_from(QQ(other), QQ)) | |
| elif domain.of_type(other): | |
| return self._rsub_ground(other) | |
| else: | |
| return NotImplemented | |
| def __mul__(self, other: Any) -> PuiseuxPoly: | |
| if isinstance(other, PuiseuxPoly): | |
| if self.ring != other.ring: | |
| raise ValueError( | |
| "Cannot multiply Puiseux polynomials from different rings" | |
| ) | |
| return self._mul(other) | |
| domain = self.ring.domain | |
| if isinstance(other, int): | |
| return self._mul_ground(domain.convert_from(QQ(other), QQ)) | |
| elif domain.of_type(other): | |
| return self._mul_ground(other) | |
| else: | |
| return NotImplemented | |
| def __rmul__(self, other: Any) -> PuiseuxPoly: | |
| domain = self.ring.domain | |
| if isinstance(other, int): | |
| return self._mul_ground(domain.convert_from(QQ(other), QQ)) | |
| elif domain.of_type(other): | |
| return self._mul_ground(other) | |
| else: | |
| return NotImplemented | |
| def __pow__(self, other: Any) -> PuiseuxPoly: | |
| if isinstance(other, int): | |
| if other >= 0: | |
| return self._pow_pint(other) | |
| else: | |
| return self._pow_nint(-other) | |
| elif QQ.of_type(other): | |
| return self._pow_rational(other) | |
| else: | |
| return NotImplemented | |
| def __truediv__(self, other: Any) -> PuiseuxPoly: | |
| if isinstance(other, PuiseuxPoly): | |
| if self.ring != other.ring: | |
| raise ValueError( | |
| "Cannot divide Puiseux polynomials from different rings" | |
| ) | |
| return self._mul(other._inv()) | |
| domain = self.ring.domain | |
| if isinstance(other, int): | |
| return self._mul_ground(domain.convert_from(QQ(1, other), QQ)) | |
| elif domain.of_type(other): | |
| return self._div_ground(other) | |
| else: | |
| return NotImplemented | |
| def __rtruediv__(self, other: Any) -> PuiseuxPoly: | |
| if isinstance(other, int): | |
| return self._inv()._mul_ground(self.ring.domain.convert_from(QQ(other), QQ)) | |
| elif self.ring.domain.of_type(other): | |
| return self._inv()._mul_ground(other) | |
| else: | |
| return NotImplemented | |
| def _add(self, other: PuiseuxPoly) -> PuiseuxPoly: | |
| poly1, poly2, monom, ns = self._unify(other) | |
| return self._new(self.ring, poly1 + poly2, monom, ns) | |
| def _add_ground(self, ground: Any) -> PuiseuxPoly: | |
| return self._add(self.ring.ground_new(ground)) | |
| def _sub(self, other: PuiseuxPoly) -> PuiseuxPoly: | |
| poly1, poly2, monom, ns = self._unify(other) | |
| return self._new(self.ring, poly1 - poly2, monom, ns) | |
| def _sub_ground(self, ground: Any) -> PuiseuxPoly: | |
| return self._sub(self.ring.ground_new(ground)) | |
| def _rsub_ground(self, ground: Any) -> PuiseuxPoly: | |
| return self.ring.ground_new(ground)._sub(self) | |
| def _mul(self, other: PuiseuxPoly) -> PuiseuxPoly: | |
| poly1, poly2, monom, ns = self._unify(other) | |
| if monom is not None: | |
| monom = tuple(2 * e for e in monom) | |
| return self._new(self.ring, poly1 * poly2, monom, ns) | |
| def _mul_ground(self, ground: Any) -> PuiseuxPoly: | |
| return self._new_raw(self.ring, self.poly * ground, self.monom, self.ns) | |
| def _div_ground(self, ground: Any) -> PuiseuxPoly: | |
| return self._new_raw(self.ring, self.poly / ground, self.monom, self.ns) | |
| def _pow_pint(self, n: int) -> PuiseuxPoly: | |
| assert n >= 0 | |
| monom = self.monom | |
| if monom is not None: | |
| monom = tuple(m * n for m in monom) | |
| return self._new(self.ring, self.poly**n, monom, self.ns) | |
| def _pow_nint(self, n: int) -> PuiseuxPoly: | |
| return self._inv()._pow_pint(n) | |
| def _pow_rational(self, n: Any) -> PuiseuxPoly: | |
| if not self.is_term: | |
| raise ValueError("Only monomials can be raised to a rational power") | |
| [(monom, coeff)] = self.terms() | |
| domain = self.ring.domain | |
| if not domain.is_one(coeff): | |
| raise ValueError("Only monomials can be raised to a rational power") | |
| monom = tuple(m * n for m in monom) | |
| return self.ring.from_dict({monom: domain.one}) | |
| def _inv(self) -> PuiseuxPoly: | |
| if not self.is_term: | |
| raise ValueError("Only terms can be inverted") | |
| [(monom, coeff)] = self.terms() | |
| domain = self.ring.domain | |
| if not domain.is_Field and not domain.is_one(coeff): | |
| raise ValueError("Cannot invert non-unit coefficient") | |
| monom = tuple(-m for m in monom) | |
| coeff = 1 / coeff | |
| return self.ring.from_dict({monom: coeff}) | |
| def diff(self, x: PuiseuxPoly) -> PuiseuxPoly: | |
| """Differentiate a Puiseux polynomial with respect to a variable. | |
| >>> from sympy import QQ | |
| >>> from sympy.polys.puiseux import puiseux_ring | |
| >>> R, x, y = puiseux_ring('x, y', QQ) | |
| >>> p = 5*x**2 + 7*y**3 | |
| >>> p.diff(x) | |
| 10*x | |
| >>> p.diff(y) | |
| 21*y**2 | |
| """ | |
| ring = self.ring | |
| i = ring.index(x) | |
| g = {} | |
| for expv, coeff in self.iterterms(): | |
| n = expv[i] | |
| if n: | |
| e = list(expv) | |
| e[i] -= 1 | |
| g[tuple(e)] = coeff * n | |
| return ring(g) | |
Xet Storage Details
- Size:
- 26.5 kB
- Xet hash:
- 097492a679fa8ad0977b97f687d2abc4be729a8480ad4e83de4a899a16abdefa
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.