def rs_sin(p, x, prec): """ Sine of a series Returns the series expansion of the sin of p, about 0. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_sin >>> R, x, y = ring('x, y', QQ) >>> rs_sin(x + x*y, x, 4) -1/6*x**3*y**3 - 1/2*x**3*y**2 - 1/2*x**3*y - 1/6*x**3 + x*y + x See Also ======== sin """ R = x.ring if not p: return R(0) if _has_constant_term(p, x): zm = R.zero_monom c = p[zm] c_expr = c.as_expr() if R.domain is EX: t1, t2 = sin(c_expr), cos(c_expr) elif isinstance(c, PolyElement): try: t1, t2 = R(sin(c_expr)), R(cos(c_expr)) except ValueError: raise DomainError("The given series can't be expanded in this " "domain.") else: raise DomainError("The given series can't be expanded in this " "domain") raise NotImplementedError p1 = p - c # Makes use of sympy cos, sin fuctions to evaluate the values of the cos/sin # of the constant term. return rs_sin(p1, x, prec) * t2 + rs_cos(p1, x, prec) * t1 # Series is calculated in terms of tan as its evaluation is fast. if len(p) > 20 and p.ngens == 1: t = rs_tan(p / 2, x, prec) t2 = rs_square(t, x, prec) p1 = rs_series_inversion(1 + t2, x, prec) return rs_mul(p1, 2 * t, x, prec) one = R(1) n = 1 c = [0] for k in range(2, prec + 2, 2): c.append(one / n) c.append(0) n *= -k * (k + 1) return rs_series_from_list(p, c, x, prec)
def dup_factor_list(f, K0, **args): """Factor polynomials into irreducibles in `K[x]`. """ if not K0.has_CharacteristicZero: # pragma: no cover raise DomainError('only characteristic zero allowed') if K0.is_Algebraic: coeff, factors = dup_ext_factor(f, K0) else: if not K0.is_Exact: K0_inexact, K0 = K0, K0.get_exact() f = dup_convert(f, K0_inexact, K0) else: K0_inexact = None if K0.has_Field: K = K0.get_ring() denom, f = dup_ground_to_ring(f, K0, K) f = dup_convert(f, K0, K) else: K = K0 if K.is_ZZ: coeff, factors = dup_zz_factor(f, K, **args) elif K.is_Poly: f, u = dmp_inject(f, 0, K) coeff, factors = dmp_factor_list(f, u, K.dom, **args) for i, (f, k) in enumerate(factors): factors[i] = (dmp_eject(f, u, K), k) coeff = K.convert(coeff, K.dom) else: # pragma: no cover raise DomainError('factorization not supported over %s' % K0) if K0.has_Field: for i, (f, k) in enumerate(factors): factors[i] = (dup_convert(f, K, K0), k) coeff = K0.convert(coeff, K) denom = K0.convert(denom, K) coeff = K0.quo(coeff, denom) if K0_inexact is not None: for i, (f, k) in enumerate(factors): factors[i] = (dup_convert(f, K0, K0_inexact), k) coeff = K0_inexact.convert(coeff, K0) if not args.get('include', False): return coeff, factors else: if not factors: return [(dup_strip([coeff]), 1)] else: g = dup_mul_ground(factors[0][0], coeff, K) return [(g, factors[0][1])] + factors[1:]
def rs_tan(p, x, prec): """ Tangent of a series Returns the series expansion of the tan of p, about 0. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_tan >>> R, x, y = ring('x, y', QQ) >>> rs_tan(x + x*y, x, 4) 1/3*x**3*y**3 + x**3*y**2 + x**3*y + 1/3*x**3 + x*y + x See Also ======== tan """ if rs_is_puiseux(p, x): r = rs_puiseux(rs_tan, p, x, prec) return r R = p.ring const = 0 if _has_constant_term(p, x): zm = R.zero_monom c = p[zm] if R.domain is EX: c_expr = c.as_expr() const = tan(c_expr) elif isinstance(c, PolyElement): try: c_expr = c.as_expr() const = R(tan(c_expr)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") else: try: const = R(tan(c)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") p1 = p - c # Makes use of sympy fuctions to evaluate the values of the cos/sin # of the constant term. t2 = rs_tan(p1, x, prec) t = rs_series_inversion(1 - const * t2, x, prec) return rs_mul(const + t2, t, x, prec) if R.ngens == 1: return _tan1(p, x, prec) else: return rs_fun(p, rs_tan, x, prec)
def rs_exp(p, x, prec): """ Exponentiation of a series modulo ``O(x**prec)`` Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_exp >>> R, x = ring('x', QQ) >>> rs_exp(x**2, x, 7) 1/6*x**6 + 1/2*x**4 + x**2 + 1 """ if rs_is_puiseux(p, x): return rs_puiseux(rs_exp, p, x, prec) R = p.ring if _has_constant_term(p, x): zm = R.zero_monom c = p[zm] if R.domain is EX: c_expr = c.as_expr() const = exp(c_expr) elif isinstance(c, PolyElement): try: c_expr = c.as_expr() const = R(exp(c_expr)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") else: try: const = R(exp(c)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") p1 = p - c # Makes use of sympy fuctions to evaluate the values of the cos/sin # of the constant term. return const * rs_exp(p1, x, prec) if len(p) > 20: return _exp1(p, x, prec) one = R(1) n = 1 k = 1 c = [] for k in range(prec): c.append(one / n) k += 1 n *= k r = rs_series_from_list(p, c, x, prec) return r
def rs_log(p, x, prec): """ The Logarithm of ``p`` modulo ``O(x**prec)`` Notes ===== truncation of ``integral dx p**-1*d p/dx`` is used. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_log >>> R, x = ring('x', QQ) >>> rs_log(1 + x, x, 8) 1/7*x**7 - 1/6*x**6 + 1/5*x**5 - 1/4*x**4 + 1/3*x**3 - 1/2*x**2 + x >>> rs_log(x**QQ(3, 2) + 1, x, 5) 1/3*x**(9/2) - 1/2*x**3 + x**(3/2) """ if rs_is_puiseux(p, x): return rs_puiseux(rs_log, p, x, prec) if p == 1: return 0 R = p.ring if _has_constant_term(p, x): const = 0 zm = R.zero_monom c = p[zm] if c == 1: pass else: c_expr = c.as_expr() if R.domain is EX: const = log(c_expr) elif isinstance(c, PolyElement): try: const = R(log(c_expr)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") else: try: const = R(log(c)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") dlog = p.diff(x) dlog = rs_mul(dlog, _series_inversion1(p, x, prec), x, prec - 1) return rs_integrate(dlog, x) + const else: raise NotImplementedError
def rs_tanh(p, x, prec): """ Hyperbolic tangent of a series Returns the series expansion of the tanh of p, about 0. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_tanh >>> R, x, y = ring('x, y', QQ) >>> rs_tanh(x + x*y, x, 4) -1/3*x**3*y**3 - x**3*y**2 - x**3*y - 1/3*x**3 + x*y + x See Also ======== tanh """ if rs_is_puiseux(p, x): return rs_puiseux(rs_tanh, p, x, prec) R = p.ring const = 0 if _has_constant_term(p, x): zm = R.zero_monom c = p[zm] if R.domain is EX: c_expr = c.as_expr() const = tanh(c_expr) elif isinstance(c, PolyElement): try: c_expr = c.as_expr() const = R(tanh(c_expr)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") else: try: const = R(tanh(c)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") p1 = p - c t1 = rs_tanh(p1, x, prec) t = rs_series_inversion(1 + const * t1, x, prec) return rs_mul(const + t1, t, x, prec) if R.ngens == 1: return _tanh(p, x, prec) else: return rs_fun(p, _tanh, x, prec)
def rs_atanh(p, x, prec): """ Hyperbolic arctangent of a series Returns the series expansion of the atanh of p, about 0. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.rings import ring >>> from sympy.polys.ring_series import rs_atanh >>> R, x, y = ring('x, y', QQ) >>> rs_atanh(x + x*y, x, 4) 1/3*x**3*y**3 + x**3*y**2 + x**3*y + 1/3*x**3 + x*y + x See Also ======== atanh """ if rs_is_puiseux(p, x): return rs_puiseux(rs_atanh, p, x, prec) R = p.ring const = 0 if _has_constant_term(p, x): zm = R.zero_monom c = p[zm] if R.domain is EX: c_expr = c.as_expr() const = atanh(c_expr) elif isinstance(c, PolyElement): try: c_expr = c.as_expr() const = R(atanh(c_expr)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") else: try: const = R(atanh(c)) except ValueError: raise DomainError("The given series can't be expanded in " "this domain.") # Instead of using a closed form formula, we differentiate atanh(p) to get # `1/(1-p**2) * dp`, whose series expansion is much easier to calculate. # Finally we integrate to get back atanh dp = rs_diff(p, x) p1 = -rs_square(p, x, prec) + 1 p1 = rs_series_inversion(p1, x, prec - 1) p1 = rs_mul(dp, p1, x, prec - 1) return rs_integrate(p1, x) + const
def dup_half_gcdex(f, g, K): """ Half extended Euclidean algorithm in `F[x]`. Returns ``(s, h)`` such that ``h = gcd(f, g)`` and ``s*f = h (mod g)``. Examples ======== >>> from sympy.polys.domains import QQ >>> from sympy.polys.euclidtools import dup_half_gcdex >>> f = QQ.map([1, -2, -6, 12, 15]) >>> g = QQ.map([1, 1, -4, -4]) >>> dup_half_gcdex(f, g, QQ) ([-1/5, 3/5], [1/1, 1/1]) """ if not (K.has_Field or not K.is_Exact): raise DomainError("can't compute half extended GCD over %s" % K) a, b = [K.one], [] while g: q, r = dup_div(f, g, K) f, g = g, r a, b = b, dup_sub_mul(a, q, b, K) a = dup_quo_ground(a, dup_LC(f, K), K) f = dup_monic(f, K) return a, f
def dup_factor_list(f, K0): """Factor univariate polynomials into irreducibles in `K[x]`. """ j, f = dup_terms_gcd(f, K0) cont, f = dup_primitive(f, K0) if K0.is_FiniteField: coeff, factors = dup_gf_factor(f, K0) elif K0.is_Algebraic: coeff, factors = dup_ext_factor(f, K0) else: if not K0.is_Exact: K0_inexact, K0 = K0, K0.get_exact() f = dup_convert(f, K0_inexact, K0) else: K0_inexact = None if K0.is_Field: K = K0.get_ring() denom, f = dup_clear_denoms(f, K0, K) f = dup_convert(f, K0, K) else: K = K0 if K.is_ZZ: coeff, factors = dup_zz_factor(f, K) elif K.is_Poly: f, u = dmp_inject(f, 0, K) coeff, factors = dmp_factor_list(f, u, K.dom) for i, (f, k) in enumerate(factors): factors[i] = (dmp_eject(f, u, K), k) coeff = K.convert(coeff, K.dom) else: # pragma: no cover raise DomainError('factorization not supported over %s' % K0) if K0.is_Field: for i, (f, k) in enumerate(factors): factors[i] = (dup_convert(f, K, K0), k) coeff = K0.convert(coeff, K) coeff = K0.quo(coeff, denom) if K0_inexact: for i, (f, k) in enumerate(factors): max_norm = dup_max_norm(f, K0) f = dup_quo_ground(f, max_norm, K0) f = dup_convert(f, K0, K0_inexact) factors[i] = (f, k) coeff = K0.mul(coeff, K0.pow(max_norm, k)) coeff = K0_inexact.convert(coeff, K0) K0 = K0_inexact if j: factors.insert(0, ([K0.one, K0.zero], j)) return coeff*cont, _sort_factors(factors)
def iter_groebner(seq, n, ring, method=None): """ Computes Groebner basis for a set of polynomials in `K[X]`. Wrapper around the (default) improved Buchberger and the other algorithms for computing Groebner bases. The choice of algorithm can be changed via ``method`` argument or :func:`setup` from :mod:`sympy.polys.polyconfig`, where ``method`` can be either ``buchberger`` or ``f5b``. """ domain, orig = ring.domain, None if not domain.is_Field or not domain.has_assoc_Field: try: orig, ring = ring, ring.clone(domain=domain.get_field()) except DomainError: raise DomainError("can't compute a Groebner basis over %s" % domain) else: seq = [s.set_ring(ring) for s in seq] G = _incr_buch(seq, n, ring) if orig is not None: G = [g.clear_denoms()[1].set_ring(orig) for g in G] return G
def dup_half_gcdex(f, g, K): """ Half extended Euclidean algorithm in `F[x]`. Returns ``(s, h)`` such that ``h = gcd(f, g)`` and ``s*f = h (mod g)``. Examples ======== >>> from sympy.polys import ring, QQ >>> R, x = ring("x", QQ) >>> f = x**4 - 2*x**3 - 6*x**2 + 12*x + 15 >>> g = x**3 + x**2 - 4*x - 4 >>> R.dup_half_gcdex(f, g) (-1/5*x + 3/5, x + 1) """ if not K.has_Field: raise DomainError("can't compute half extended GCD over %s" % K) a, b = [K.one], [] while g: q, r = dup_div(f, g, K) f, g = g, r a, b = b, dup_sub_mul(a, q, b, K) a = dup_quo_ground(a, dup_LC(f, K), K) f = dup_monic(f, K) return a, f
def dup_factor_list(f, K0): """Factor polynomials into irreducibles in `K[x]`. """ j, f = dup_terms_gcd(f, K0) if not K0.has_CharacteristicZero: coeff, factors = dup_gf_factor(f, K0) elif K0.is_Algebraic: coeff, factors = dup_ext_factor(f, K0) else: if not K0.is_Exact: K0_inexact, K0 = K0, K0.get_exact() f = dup_convert(f, K0_inexact, K0) else: K0_inexact = None if K0.has_Field: K = K0.get_ring() denom, f = dup_clear_denoms(f, K0, K) f = dup_convert(f, K0, K) else: K = K0 if K.is_ZZ: coeff, factors = dup_zz_factor(f, K) elif K.is_Poly: f, u = dmp_inject(f, 0, K) coeff, factors = dmp_factor_list(f, u, K.dom) for i, (f, k) in enumerate(factors): factors[i] = (dmp_eject(f, u, K), k) coeff = K.convert(coeff, K.dom) else: # pragma: no cover raise DomainError('factorization not supported over %s' % K0) if K0.has_Field: for i, (f, k) in enumerate(factors): factors[i] = (dup_convert(f, K, K0), k) coeff = K0.convert(coeff, K) denom = K0.convert(denom, K) coeff = K0.quo(coeff, denom) if K0_inexact is not None: for i, (f, k) in enumerate(factors): factors[i] = (dup_convert(f, K0, K0_inexact), k) coeff = K0_inexact.convert(coeff, K0) if j: factors.insert(0, ([K0.one, K0.zero], j)) return coeff, _sort_factors(factors)
def dmp_norm(f, u, K): """ Norm of ``f`` in ``K[X1, ..., Xn]``, often not square-free. """ if not K.is_Algebraic: raise DomainError("ground domain must be algebraic") g = dmp_raise(K.mod.rep, u + 1, 0, K.dom) h, _ = dmp_inject(f, u, K, front=True) return dmp_resultant(g, h, u + 1, K.dom)
def __init__(self, dom, *ext): if not dom.is_QQ: raise DomainError("ground domain must be a rational field") from sympy.polys.numberfields import to_number_field if len(ext) == 1 and isinstance(ext[0], tuple): orig_ext = ext[0][1:] else: orig_ext = ext self.orig_ext = orig_ext """ Original elements given to generate the extension. >>> from sympy import QQ, sqrt >>> K = QQ.algebraic_field(sqrt(2), sqrt(3)) >>> K.orig_ext (sqrt(2), sqrt(3)) """ self.ext = to_number_field(ext) """ Primitive element used for the extension. >>> from sympy import QQ, sqrt >>> K = QQ.algebraic_field(sqrt(2), sqrt(3)) >>> K.ext sqrt(2) + sqrt(3) """ self.mod = self.ext.minpoly.rep """ Minimal polynomial for the primitive element of the extension. >>> from sympy import QQ, sqrt >>> K = QQ.algebraic_field(sqrt(2)) >>> K.mod DMP([1, 0, -2], QQ, None) """ self.domain = self.dom = dom self.ngens = 1 self.symbols = self.gens = (self.ext, ) self.unit = self([dom(1), dom(0)]) self.zero = self.dtype.zero(self.mod.rep, dom) self.one = self.dtype.one(self.mod.rep, dom) self._maximal_order = None self._discriminant = None self._nilradicals_mod_p = {}
def __init__(self, dom, *ext): if not dom.is_QQ: raise DomainError("ground domain must be a rational field") from sympy.polys.numberfields import to_number_field self.ext = to_number_field(ext) self.mod = self.ext.minpoly.rep self.dom = dom self.gens = (self.ext, ) self.unit = self([dom(1), dom(0)]) self.zero = self.dtype.zero(self.mod.rep, dom) self.one = self.dtype.one(self.mod.rep, dom)
def dmp_sqf_norm(f, u, K): """ Square-free norm of ``f`` in ``K[X]``, useful over algebraic domains. Returns ``s``, ``f``, ``r``, such that ``g(x) = f(x-sa)`` and ``r(x) = Norm(g(x))`` is a square-free polynomial over K, where ``a`` is the algebraic extension of ``K``. Examples ======== >>> from sympy.polys import ring, QQ >>> from sympy import I >>> K = QQ.algebraic_field(I) >>> R, x, y = ring("x,y", K) >>> _, X, Y = ring("x,y", QQ) >>> s, f, r = R.dmp_sqf_norm(x*y + y**2) >>> s == 1 True >>> f == x*y + y**2 + K([QQ(-1), QQ(0)])*y True >>> r == X**2*Y**2 + 2*X*Y**3 + Y**4 + Y**2 True """ if not u: return dup_sqf_norm(f, K) if not K.is_Algebraic: raise DomainError("ground domain must be algebraic") g = dmp_raise(K.mod.rep, u + 1, 0, K.dom) F = dmp_raise([K.one, -K.unit], u, 0, K) s = 0 while True: h, _ = dmp_inject(f, u, K, front=True) r = dmp_resultant(g, h, u + 1, K.dom) if dmp_sqf_p(r, u, K.dom): break else: f, s = dmp_compose(f, F, u, K), s + 1 return s, f, r
def dmp_sqf_norm(f, u, K): """ Square-free norm of ``f`` in ``K[X]``, useful over algebraic domains. Returns ``s``, ``f``, ``r``, such that ``g(x) = f(x-sa)`` and ``r(x) = Norm(g(x))`` is a square-free polynomial over K, where ``a`` is the algebraic extension of ``K``. Examples ======== >>> from sympy import I >>> from sympy.polys.domains import QQ >>> from sympy.polys.sqfreetools import dmp_sqf_norm >>> K = QQ.algebraic_field(I) >>> s, f, r = dmp_sqf_norm([[K(1), K(0)], [K(1), K(0), K(0)]], 1, K) >>> s == 1 True >>> f == [[K(1), K(0)], [K(1), K([QQ(-1), QQ(0)]), K(0)]] True >>> r == [[1, 0, 0], [2, 0, 0, 0], [1, 0, 1, 0, 0]] True """ if not u: return dup_sqf_norm(f, K) if not K.is_Algebraic: raise DomainError("ground domain must be algebraic") g = dmp_raise(K.mod.rep, u + 1, 0, K.dom) F = dmp_raise([K.one, -K.unit], u, 0, K) s = 0 while True: h, _ = dmp_inject(f, u, K, front=True) r = dmp_resultant(g, h, u + 1, K.dom) if dmp_sqf_p(r, u, K.dom): break else: f, s = dmp_compose(f, F, u, K), s + 1 return s, f, r
def dup_real_imag(f, K): """ Return bivariate polynomials ``f1`` and ``f2``, such that ``f = f1 + f2*I``. Examples ======== >>> from sympy.polys.domains import ZZ >>> from sympy.polys.densetools import dup_real_imag >>> dup_real_imag([ZZ(1), ZZ(1), ZZ(1), ZZ(1)], ZZ) ([[1], [1], [-3, 0, 1], [-1, 0, 1]], [[3, 0], [2, 0], [-1, 0, 1, 0]]) """ if not K.is_ZZ and not K.is_QQ: raise DomainError( "computing real and imaginary parts is not supported over %s" % K) f1 = dmp_zero(1) f2 = dmp_zero(1) if not f: return f1, f2 g = [[[K.one, K.zero]], [[K.one], []]] h = dmp_ground(f[0], 2) for c in f[1:]: h = dmp_mul(h, g, 2, K) h = dmp_add_term(h, dmp_ground(c, 1), 0, 2, K) H = dup_to_raw_dict(h) for k, h in H.iteritems(): m = k % 4 if not m: f1 = dmp_add(f1, h, 1, K) elif m == 1: f2 = dmp_add(f2, h, 1, K) elif m == 2: f1 = dmp_sub(f1, h, 1, K) else: f2 = dmp_sub(f2, h, 1, K) return f1, f2
def dup_real_imag(f, K): """ Return bivariate polynomials ``f1`` and ``f2``, such that ``f = f1 + f2*I``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> R.dup_real_imag(x**3 + x**2 + x + 1) (x**3 + x**2 - 3*x*y**2 + x - y**2 + 1, 3*x**2*y + 2*x*y - y**3 + y) """ if not K.is_ZZ and not K.is_QQ: raise DomainError( "computing real and imaginary parts is not supported over %s" % K) f1 = dmp_zero(1) f2 = dmp_zero(1) if not f: return f1, f2 g = [[[K.one, K.zero]], [[K.one], []]] h = dmp_ground(f[0], 2) for c in f[1:]: h = dmp_mul(h, g, 2, K) h = dmp_add_term(h, dmp_ground(c, 1), 0, 2, K) H = dup_to_raw_dict(h) for k, h in H.items(): m = k % 4 if not m: f1 = dmp_add(f1, h, 1, K) elif m == 1: f2 = dmp_add(f2, h, 1, K) elif m == 2: f1 = dmp_sub(f1, h, 1, K) else: f2 = dmp_sub(f2, h, 1, K) return f1, f2
def dmp_lift(f, u, K): """ Convert algebraic coefficients to integers in ``K[X]``. Examples ======== >>> from sympy.polys import ring, QQ >>> from sympy import I >>> K = QQ.algebraic_field(I) >>> R, x = ring("x", K) >>> f = x**2 + K([QQ(1), QQ(0)])*x + K([QQ(2), QQ(0)]) >>> R.dmp_lift(f) x**8 + 2*x**6 + 9*x**4 - 8*x**2 + 16 """ if K.is_GaussianField: K1 = K.as_AlgebraicField() f = dmp_convert(f, u, K, K1) K = K1 if not K.is_Algebraic: raise DomainError( 'computation can be done only in an algebraic domain') F, monoms, polys = dmp_to_dict(f, u), [], [] for monom, coeff in F.items(): if not coeff.is_ground: monoms.append(monom) perms = variations([-1, 1], len(monoms), repetition=True) for perm in perms: G = dict(F) for sign, monom in zip(perm, monoms): if sign == -1: G[monom] = -G[monom] polys.append(dmp_from_dict(G, u, K)) return dmp_convert(dmp_expand(polys, u, K), u, K, K.dom)
def __init__(self, dom, *ext): if not dom.is_QQ: raise DomainError("ground domain must be a rational field") from sympy.polys.numberfields import to_number_field if len(ext) == 1 and isinstance(ext[0], tuple): self.orig_ext = ext[0][1:] else: self.orig_ext = ext self.ext = to_number_field(ext) self.mod = self.ext.minpoly.rep self.domain = self.dom = dom self.ngens = 1 self.symbols = self.gens = (self.ext, ) self.unit = self([dom(1), dom(0)]) self.zero = self.dtype.zero(self.mod.rep, dom) self.one = self.dtype.one(self.mod.rep, dom)
def dup_sqf_norm(f, K): """ Square-free norm of ``f`` in ``K[x]``, useful over algebraic domains. Returns ``s``, ``f``, ``r``, such that ``g(x) = f(x-sa)`` and ``r(x) = Norm(g(x))`` is a square-free polynomial over K, where ``a`` is the algebraic extension of ``K``. Examples ======== >>> from sympy.polys import ring, QQ >>> from sympy import sqrt >>> K = QQ.algebraic_field(sqrt(3)) >>> R, x = ring("x", K) >>> _, X = ring("x", QQ) >>> s, f, r = R.dup_sqf_norm(x**2 - 2) >>> s == 1 True >>> f == x**2 + K([QQ(-2), QQ(0)])*x + 1 True >>> r == X**4 - 10*X**2 + 1 True """ if not K.is_Algebraic: raise DomainError("ground domain must be algebraic") s, g = 0, dmp_raise(K.mod.rep, 1, 0, K.dom) while True: h, _ = dmp_inject(f, 0, K, front=True) r = dmp_resultant(g, h, 1, K.dom) if dup_sqf_p(r, K.dom): break else: f, s = dup_shift(f, -K.unit, K), s + 1 return s, f, r
def groebner(seq, ring, method=None): """ Computes Groebner basis for a set of polynomials in `K[X]`. Wrapper around the (default) improved Buchberger and the other algorithms for computing Groebner bases. The choice of algorithm can be changed via ``method`` argument or :func:`setup` from :mod:`sympy.polys.polyconfig`, where ``method`` can be either ``buchberger`` or ``f5b``. """ if method is None: method = query('groebner') _groebner_methods = { 'buchberger': _buchberger, 'f5b': _f5b, } try: _groebner = _groebner_methods[method] except KeyError: raise ValueError( "'%s' is not a valid Groebner bases algorithm (valid are 'buchberger' and 'f5b')" % method) domain, orig = ring.domain, None if not domain.is_Field or not domain.has_assoc_Field: try: orig, ring = ring, ring.clone(domain=domain.get_field()) except DomainError: raise DomainError("can't compute a Groebner basis over %s" % domain) else: seq = [s.set_ring(ring) for s in seq] G = _groebner(seq, ring) if orig is not None: G = [g.clear_denoms()[1].set_ring(orig) for g in G] return G
def dup_sqf_norm(f, K): """ Square-free norm of ``f`` in ``K[x]``, useful over algebraic domains. Returns ``s``, ``f``, ``r``, such that ``g(x) = f(x-sa)`` and ``r(x) = Norm(g(x))`` is a square-free polynomial over K, where ``a`` is the algebraic extension of ``K``. **Examples** >>> from sympy import sqrt >>> from sympy.polys.domains import QQ >>> from sympy.polys.sqfreetools import dup_sqf_norm >>> K = QQ.algebraic_field(sqrt(3)) >>> s, f, r = dup_sqf_norm([K(1), K(0), K(-2)], K) >>> s == 1 True >>> f == [K(1), K([QQ(-2), QQ(0)]), K(1)] True >>> r == [1, 0, -10, 0, 1] True """ if not K.is_Algebraic: raise DomainError("ground domain must be algebraic") s, g = 0, dmp_raise(K.mod.rep, 1, 0, K.dom) while True: h, _ = dmp_inject(f, 0, K, front=True) r = dmp_resultant(g, h, 1, K.dom) if dup_sqf_p(r, K.dom): break else: f, s = dup_shift(f, -K.unit, K), s+1 return s, f, r
def dmp_lift(f, u, K): """ Convert algebraic coefficients to integers in ``K[X]``. Examples ======== >>> from sympy import I >>> from sympy.polys.domains import QQ >>> from sympy.polys.densetools import dmp_lift >>> K = QQ.algebraic_field(I) >>> f = [K(1), K([QQ(1), QQ(0)]), K([QQ(2), QQ(0)])] >>> dmp_lift(f, 0, K) [1/1, 0/1, 2/1, 0/1, 9/1, 0/1, -8/1, 0/1, 16/1] """ if not K.is_Algebraic: raise DomainError( 'computation can be done only in an algebraic domain') F, monoms, polys = dmp_to_dict(f, u), [], [] for monom, coeff in F.iteritems(): if not coeff.is_ground: monoms.append(monom) perms = variations([-1, 1], len(monoms), repetition=True) for perm in perms: G = dict(F) for sign, monom in zip(perm, monoms): if sign == -1: G[monom] = -G[monom] polys.append(dmp_from_dict(G, u, K)) return dmp_convert(dmp_expand(polys, u, K), u, K, K.dom)
def dmp_factor_list(f, u, K0): """Factor polynomials into irreducibles in `K[X]`. """ if not u: return dup_factor_list(f, K0) J, f = dmp_terms_gcd(f, u, K0) if not K0.has_CharacteristicZero: # pragma: no cover coeff, factors = dmp_gf_factor(f, u, K0) elif K0.is_Algebraic: coeff, factors = dmp_ext_factor(f, u, K0) else: if not K0.is_Exact: K0_inexact, K0 = K0, K0.get_exact() f = dmp_convert(f, u, K0_inexact, K0) else: K0_inexact = None if K0.has_Field: K = K0.get_ring() denom, f = dmp_clear_denoms(f, u, K0, K) f = dmp_convert(f, u, K0, K) else: K = K0 if K.is_ZZ: levels, f, v = dmp_exclude(f, u, K) coeff, factors = dmp_zz_factor(f, v, K) for i, (f, k) in enumerate(factors): factors[i] = (dmp_include(f, levels, v, K), k) elif K.is_Poly: f, v = dmp_inject(f, u, K) coeff, factors = dmp_factor_list(f, v, K.dom) for i, (f, k) in enumerate(factors): factors[i] = (dmp_eject(f, v, K), k) coeff = K.convert(coeff, K.dom) else: # pragma: no cover raise DomainError('factorization not supported over %s' % K0) if K0.has_Field: for i, (f, k) in enumerate(factors): factors[i] = (dmp_convert(f, u, K, K0), k) coeff = K0.convert(coeff, K) denom = K0.convert(denom, K) coeff = K0.quo(coeff, denom) if K0_inexact is not None: for i, (f, k) in enumerate(factors): factors[i] = (dmp_convert(f, u, K0, K0_inexact), k) coeff = K0_inexact.convert(coeff, K0) for i, j in enumerate(reversed(J)): if not j: continue term = {(0, ) * (u - i) + (1, ) + (0, ) * i: K0.one} factors.insert(0, (dmp_from_dict(term, u, K0), j)) return coeff, _sort_factors(factors)
def dmp_gf_factor(f, u, K): """Factor multivariate polynomials over finite fields. """ raise DomainError('multivariate polynomials over %s' % K)
def get_ring(self): """Returns a ring associated with ``self``. """ raise DomainError('there is no ring associated with %s' % self)
def algebraic_field(self, *extension): """Returns an algebraic field, i.e. `K(\\alpha, \dots)`. """ raise DomainError("can't create algebraic field over %s" % self)
def get_field(self): """Returns a field associated with ``self``. """ raise DomainError('there is no field associated with %s' % self)