def swinnerton_dyer_poly(n, x=None, **args): """Generates n-th Swinnerton-Dyer polynomial in `x`. """ from .numberfields import minimal_polynomial if n <= 0: raise ValueError( "can't generate Swinnerton-Dyer polynomial of order %s" % n) if x is not None: sympify(x) else: x = Dummy('x') if n > 3: p = 2 a = [sqrt(2)] for i in range(2, n + 1): p = nextprime(p) a.append(sqrt(p)) return minimal_polynomial(Add(*a), x, polys=args.get('polys', False)) if n == 1: ex = x**2 - 2 elif n == 2: ex = x**4 - 10 * x**2 + 1 elif n == 3: ex = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576 if not args.get('polys', False): return ex else: return PurePoly(ex, x)
def eval(cls, x, k): x = sympify(x) k = sympify(k) if k.is_Integer: if k is S.Zero: return S.One else: if k.is_positive: if x is S.Infinity: return S.Infinity elif x is S.NegativeInfinity: if k.is_odd: return S.NegativeInfinity else: return S.Infinity else: return reduce(lambda r, i: r*(x - i), range(0, int(k)), 1) else: if x is S.Infinity: return S.Infinity elif x is S.NegativeInfinity: return S.Infinity else: return 1/reduce(lambda r, i: r*(x + i), range(1, abs(int(k)) + 1), 1)
def singularities(f, x): """Find singularities of real-valued function `f` with respect to `x`. Examples ======== >>> from diofant import Symbol, exp, log >>> from diofant.abc import x >>> singularities(1/(1 + x), x) == {-1} True >>> singularities(exp(1/x) + log(x + 1), x) == {-1, 0} True >>> singularities(exp(1/log(x + 1)), x) == {0} True Notes ===== Removable singularities are not supported now. References ========== .. [1] http://en.wikipedia.org/wiki/Mathematical_singularity """ f, x = sympify(f), sympify(x) guess, res = set(), set() assert x.is_Symbol if f.is_number: return set() elif f.is_polynomial(x): return set() elif f.func in (Add, Mul): guess = guess.union(*[singularities(a, x) for a in f.args]) elif f.func is Pow: if f.exp.is_number and f.exp.is_negative: guess = {v for v in solve(f.base, x) if v.is_real} else: guess |= singularities(log(f.base)*f.exp, x) elif f.func in (log, sign) and len(f.args) == 1: guess |= singularities(f.args[0], x) guess |= {v for v in solve(f.args[0], x) if v.is_real} else: # pragma: no cover raise NotImplementedError for s in guess: l = Limit(f, x, s, dir="real") try: r = l.doit() if r == l or f.subs(x, s) != r: # pragma: no cover raise NotImplementedError except PoleError: res.add(s) return res
def bisect(f, a, b, tol): """ Implements bisection. This function is used in RootOf.eval_rational() and it needs to be robust. Examples ======== >>> from diofant import Rational >>> bisect(lambda x: x**2-1, -10, 0, Rational(1, 10)**2) -1025/1024 >>> bisect(lambda x: x**2-1, -10, 0, Rational(1, 10)**4) -131075/131072 """ a = sympify(a) b = sympify(b) fa = f(a) fb = f(b) if fa * fb >= 0: raise ValueError("bisect: f(a) and f(b) must have opposite signs") while (b - a > tol): c = (a + b) / 2 fc = f(c) if (fc == 0): return c # We need to make sure f(c) is not zero below if (fa * fc < 0): b = c fb = fc else: a = c fa = fc return (a + b) / 2
def nthroot(expr, n, max_len=4, prec=15): """ compute a real nth-root of a sum of surds Parameters ========== expr : sum of surds n : integer max_len : maximum number of surds passed as constants to ``nsimplify`` Notes ===== First ``nsimplify`` is used to get a candidate root; if it is not a root the minimal polynomial is computed; the answer is one of its roots. Examples ======== >>> from diofant.simplify.simplify import nthroot >>> from diofant import sqrt >>> nthroot(90 + 34*sqrt(7), 3) sqrt(7) + 3 """ expr = sympify(expr) n = sympify(n) p = expr**Rational(1, n) if not n.is_integer: return p if not _is_sum_surds(expr): return p surds = [] coeff_muls = [x.as_coeff_Mul() for x in expr.args] for x, y in coeff_muls: if not x.is_rational: return p if y is S.One: continue if not (y.is_Pow and y.exp == S.Half and y.base.is_integer): return p surds.append(y) surds.sort() surds = surds[:max_len] if expr < 0 and n % 2 == 1: p = (-expr)**Rational(1, n) a = nsimplify(p, constants=surds) res = a if _mexpand(a**n) == _mexpand(-expr) else p return -res a = nsimplify(p, constants=surds) if _mexpand(a) is not _mexpand(p) and _mexpand(a**n) == _mexpand(expr): return _mexpand(a) expr = _nthroot_solve(expr, n, prec) if expr is None: return p return expr
def eval(cls, arg, k=0): k = sympify(k) if not k.is_Integer or k.is_negative: raise ValueError( "Error: the second argument of DiracDelta must be \ a non-negative integer, %s given instead." % (k, )) arg = sympify(arg) if arg.is_positive or arg.is_negative: return S.Zero
def test_trick_indent_with_end_else_words(): # words starting with "end" or "else" do not confuse the indenter t1 = sympify('endless') t2 = sympify('elsewhere') pw = Piecewise((t1, x < 0), (t2, x <= 1), (1, True)) assert mcode(pw, inline=False) == ("if (x < 0)\n" " endless\n" "elseif (x <= 1)\n" " elsewhere\n" "else\n" " 1\n" "end")
def eval(cls, n, k=1): n = sympify(n) k = sympify(k) if n.is_prime: return 1 + n**k if n.is_Integer: if n <= 0: raise ValueError("n must be a positive integer") else: return Mul(*[(p**(k * (e + 1)) - 1) / (p**k - 1) if k != 0 else e + 1 for p, e in factorint(n).items()])
def __new__(cls, f, x, index=None, radicals=True, expand=True): """Construct a new ``RootOf`` object for ``k``-th root of ``f``. """ x = sympify(x) if index is None and x.is_Integer: x, index = None, x else: index = sympify(index) if index is not None and index.is_Integer: index = int(index) else: raise ValueError("expected an integer root index, got %s" % index) poly = PurePoly(f, x, greedy=False, expand=expand) if not poly.is_univariate: raise PolynomialError("only univariate polynomials are allowed") degree = poly.degree() if degree <= 0: raise PolynomialError("can't construct RootOf object for %s" % f) if index < -degree or index >= degree: raise IndexError("root index out of [%d, %d] range, got %d" % (-degree, degree - 1, index)) elif index < 0: index += degree dom = poly.get_domain() if not dom.is_Exact: poly = poly.to_exact() roots = cls._roots_trivial(poly, radicals) if roots is not None: return roots[index] coeff, poly = preprocess_roots(poly) dom = poly.get_domain() if not dom.is_ZZ: raise NotImplementedError("RootOf is not supported over %s" % dom) root = cls._indexed_root(poly, index) return coeff * cls._postprocess_root(root, radicals)
def use(expr, func, level=0, args=(), kwargs={}): """ Use ``func`` to transform ``expr`` at the given level. Examples ======== >>> from diofant import use, expand >>> from diofant.abc import x, y >>> f = (x + y)**2*x + 1 >>> use(f, expand, level=2) x*(x**2 + 2*x*y + y**2) + 1 >>> expand(f) x**3 + 2*x**2*y + x*y**2 + 1 """ def _use(expr, level): if not level: return func(expr, *args, **kwargs) else: if expr.is_Atom: return expr else: level -= 1 _args = [] for arg in expr.args: _args.append(_use(arg, level)) return expr.__class__(*_args) return _use(sympify(expr), level)
def reps_toposort(r): """Sort replacements `r` so (k1, v1) appears before (k2, v2) if k2 is in v1's free symbols. This orders items in the way that cse returns its results (hence, in order to use the replacements in a substitution option it would make sense to reverse the order). Examples ======== >>> from diofant.simplify.cse_main import reps_toposort >>> from diofant.abc import x, y >>> from diofant import Eq >>> for l, r in reps_toposort([(x, y + 1), (y, 2)]): ... print(Eq(l, r)) ... Eq(y, 2) Eq(x, y + 1) """ r = sympify(r) E = [] for c1, (k1, v1) in enumerate(r): for c2, (k2, v2) in enumerate(r): if k1 in v2.free_symbols: E.append((c1, c2)) return [r[i] for i in topological_sort((range(len(r)), E))]
def eval(cls, n): n = sympify(n) if n.is_Number: if n is S.Zero: return S.One elif n is S.Infinity: return S.Infinity elif n.is_Integer: if n.is_negative: return S.ComplexInfinity else: n, result = n.p, 1 if n < 20: for i in range(2, n + 1): result *= i else: N, bits = n, 0 while N != 0: if N & 1 == 1: bits += 1 N = N >> 1 result = cls._recursive(n)*2**(n - bits) return Integer(result)
def nsimplify_real(x): orig = mpmath.mp.dps xv = x._to_mpmath(bprec) try: # We'll be happy with low precision if a simple fraction if not (tolerance or full): mpmath.mp.dps = 15 rat = mpmath.findpoly(xv, 1) if rat is not None: return Rational(-int(rat[1]), int(rat[0])) mpmath.mp.dps = prec newexpr = mpmath.identify(xv, constants=constants_dict, tol=tolerance, full=full) if not newexpr: raise ValueError if full: newexpr = newexpr[0] expr = sympify(newexpr) if x and not expr: # don't let x become 0 raise ValueError if expr.is_finite is False and xv not in [mpmath.inf, mpmath.ninf]: raise ValueError return expr finally: # even though there are returns above, this is executed # before leaving mpmath.mp.dps = orig
def sqrtdenest(expr, max_iter=3): """Denests sqrts in an expression that contain other square roots if possible, otherwise returns the expr unchanged. This is based on the algorithms of [1]. Examples ======== >>> from diofant.simplify.sqrtdenest import sqrtdenest >>> from diofant import sqrt >>> sqrtdenest(sqrt(5 + 2 * sqrt(6))) sqrt(2) + sqrt(3) See Also ======== diofant.solvers.solvers.unrad References ========== [1] http://researcher.watson.ibm.com/researcher/files/us-fagin/symb85.pdf [2] D. J. Jeffrey and A. D. Rich, 'Symplifying Square Roots of Square Roots by Denesting' (available at http://www.cybertester.com/data/denest.pdf) """ expr = expand_mul(sympify(expr)) for i in range(max_iter): z = _sqrtdenest0(expr) if expr == z: return expr expr = z return expr
def __new__(cls, p1, pt=None, slope=None, **kwargs): if isinstance(p1, LinearEntity): p1, pt = p1.args else: p1 = Point(p1) if pt is not None and slope is None: try: p2 = Point(pt) except NotImplementedError: raise ValueError('The 2nd argument was not a valid Point. ' 'If it was a slope, enter it with keyword "slope".') elif slope is not None and pt is None: slope = sympify(slope) if slope.is_finite is False: # when infinite slope, don't change x dx = 0 dy = 1 else: # go over 1 up slope dx = 1 dy = slope # XXX avoiding simplification by adding to coords directly p2 = Point(p1.x + dx, p1.y + dy) else: raise ValueError('A 2nd Point or keyword "slope" must be used.') return LinearEntity.__new__(cls, p1, p2, **kwargs)
def preprocess(cls, modulus): modulus = sympify(modulus) if modulus.is_Integer and modulus > 0: return int(modulus) else: raise OptionError("'modulus' must a positive integer, got %s" % modulus)
def posify(eq): """Return eq (with generic symbols made positive) and a dictionary containing the mapping between the old and new symbols. Any symbol that has positive=None will be replaced with a positive dummy symbol having the same name. This replacement will allow more symbolic processing of expressions, especially those involving powers and logarithms. A dictionary that can be sent to subs to restore eq to its original symbols is also returned. >>> from diofant import posify, Symbol, log, solve >>> from diofant.abc import x >>> posify(x + Symbol('p', positive=True) + Symbol('n', negative=True)) (n + p + _x, {_x: x}) >>> eq = 1/x >>> log(eq).expand() log(1/x) >>> log(posify(eq)[0]).expand() -log(_x) >>> p, rep = posify(eq) >>> log(p).expand().subs(rep) -log(x) It is possible to apply the same transformations to an iterable of expressions: >>> eq = x**2 - 4 >>> solve(eq, x) [-2, 2] >>> eq_x, reps = posify([eq, x]); eq_x [_x**2 - 4, _x] >>> solve(*eq_x) [2] """ eq = sympify(eq) if iterable(eq): f = type(eq) eq = list(eq) syms = set() for e in eq: syms = syms.union(e.atoms(Symbol)) reps = {} for s in syms: reps.update({v: k for k, v in posify(s)[1].items()}) for i, e in enumerate(eq): eq[i] = e.subs(reps) return f(eq), {r: s for s, r in reps.items()} reps = { s: Dummy(s.name, positive=True) for s in eq.free_symbols if s.is_positive is None } eq = eq.subs(reps) return eq, {r: s for s, r in reps.items()}
def __init__(self, monom, gens=None): if not iterable(monom): rep, gens = dict_from_expr(sympify(monom), gens=gens) if len(rep) == 1 and list(rep.values())[0] == 1: monom = list(rep.keys())[0] else: raise ValueError("Expected a monomial got %s" % monom) self.exponents = tuple(map(int, monom)) self.gens = gens
def __new__(cls, function, limits): fun = sympify(function) if not is_sequence(fun) or len(fun) != 2: raise ValueError("Function argument should be (x(t), y(t)) " "but got %s" % str(function)) if not is_sequence(limits) or len(limits) != 3: raise ValueError("Limit argument should be (t, tmin, tmax) " "but got %s" % str(limits)) return GeometryEntity.__new__(cls, Tuple(*fun), Tuple(*limits))
def eval(cls, n): n = sympify(n) if n.is_Integer: if n < 1: raise ValueError("n must be a positive integer") factors = factorint(n) t = 1 for p, k in factors.items(): t *= (p - 1) * p**(k - 1) return t
def _eval_Eq(self, other): # RootOf represents a Root, so if other is that root, it should set # the expression to zero *and* it should be in the interval of the # RootOf instance. It must also be a number that agrees with the # is_real value of the RootOf instance. if type(self) == type(other): return sympify(self.__eq__(other)) if not (other.is_number and not other.has(AppliedUndef)): return S.false if not other.is_finite: return S.false z = self.expr.subs(self.expr.free_symbols.pop(), other).is_zero if z is False: # all roots will make z True but we don't know # whether this is the right root if z is True return S.false o = other.is_extended_real, other.is_imaginary s = self.is_extended_real, self.is_imaginary if o != s and None not in o and None not in s: return S.false i = self._get_interval() was = i.a, i.b need = [True] * 2 # make sure it would be distinct from others while any(need): i = i.refine() a, b = i.a, i.b if need[0] and a != was[0]: need[0] = False if need[1] and b != was[1]: need[1] = False re, im = other.as_real_imag() if not im: if self.is_extended_real: a, b = [Rational(str(i)) for i in (a, b)] return sympify(a < other and other < b) return S.false if self.is_extended_real: return S.false z = r1, r2, i1, i2 = [ Rational(str(j)) for j in (i.ax, i.bx, i.ay, i.by) ] return sympify((r1 < re and re < r2) and (i1 < im and im < i2))
def eval(cls, n, m, theta, phi): n, m, th, ph = [sympify(x) for x in (n, m, theta, phi)] if m.is_positive: zz = (Ynm(n, m, th, ph) + Ynm_c(n, m, th, ph)) / sqrt(2) return zz elif m.is_zero: return Ynm(n, m, th, ph) elif m.is_negative: zz = (Ynm(n, m, th, ph) - Ynm_c(n, m, th, ph)) / (sqrt(2)*I) return zz
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 diofant.polys.domains import PythonIntegerRing, GMPYIntegerRing, GMPYRationalField, RealField, ComplexField if isinstance(element, int): 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_diofant(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_diofant(element) except (TypeError, ValueError): pass raise CoercionFailed("can't convert %s of type %s to %s" % (element, type(element), self))
def eval(cls, arg): arg = sympify(arg) if im(arg).is_nonzero: raise ValueError( "Function defined only for Real Values. Complex part: %s found in %s ." % (repr(im(arg)), repr(arg))) elif arg.is_negative: return S.Zero elif arg.is_zero: return S.Half elif arg.is_positive: return S.One
def eval(cls, n, m, theta, phi): n, m, theta, phi = [sympify(x) for x in (n, m, theta, phi)] # Handle negative index m and arguments theta, phi if m.could_extract_minus_sign(): m = -m return S.NegativeOne**m * exp(-2*I*m*phi) * Ynm(n, m, theta, phi) if theta.could_extract_minus_sign(): theta = -theta return Ynm(n, m, theta, phi) if phi.could_extract_minus_sign(): phi = -phi return exp(-2*I*m*phi) * Ynm(n, m, theta, phi)
def __new__(cls, e, z, z0, dir="+"): e = sympify(e) z = sympify(z) z0 = sympify(z0) if z0 is S.Infinity: dir = "-" elif z0 is S.NegativeInfinity: dir = "+" if isinstance(dir, str): dir = Symbol(dir) elif not isinstance(dir, Symbol): raise TypeError("direction must be of type str or Symbol, not %s" % type(dir)) if str(dir) not in ('+', '-', 'real'): raise ValueError( "direction must be either '+' or '-' or 'real', not %s" % dir) obj = Expr.__new__(cls) obj._args = (e, z, z0, dir) return obj
def __new__(cls, label, shape=None, **kw_args): if isinstance(label, str): label = Symbol(label) elif isinstance(label, (Dummy, Symbol)): pass else: raise TypeError("Base label should be a string or Symbol.") obj = Expr.__new__(cls, label, **kw_args) if is_sequence(shape): obj._shape = Tuple(*shape) else: obj._shape = sympify(shape) return obj
def __new__(cls, center=None, hradius=None, vradius=None, eccentricity=None, **kwargs): hradius = sympify(hradius) vradius = sympify(vradius) eccentricity = sympify(eccentricity) if center is None: center = Point(0, 0) else: center = Point(center) if len(center) != 2: raise ValueError( 'The center of "{0}" must be a two dimensional point'.format( cls)) if len(list(filter(None, (hradius, vradius, eccentricity)))) != 2: raise ValueError( 'Exactly two arguments of "hradius", ' '"vradius", and "eccentricity" must not be None."') if eccentricity is not None: if hradius is None: hradius = vradius / sqrt(1 - eccentricity**2) elif vradius is None: vradius = hradius * sqrt(1 - eccentricity**2) if hradius == vradius: return Circle(center, hradius, **kwargs) return GeometryEntity.__new__(cls, center, hradius, vradius, **kwargs)
def __lt__(self, other): """ Checks if a partition is less than the other. Examples ======== >>> from diofant.combinatorics.partitions import Partition >>> a = Partition([1, 2], [3, 4, 5]) >>> b = Partition([1], [2, 3], [4], [5]) >>> a.rank, b.rank (9, 34) >>> a < b true """ return self.sort_key() < sympify(other).sort_key()
def _eval_Eq(self, other): """Helper method for Equality with matrices. Relational automatically converts matrices to ImmutableMatrix instances, so this method only applies here. Returns True if the matrices are definitively the same, False if they are definitively different, and None if undetermined (e.g. if they contain Symbols). Returning None triggers default handling of Equalities. """ if not hasattr(other, 'shape') or self.shape != other.shape: return S.false if isinstance(other, MatrixExpr) and not isinstance(other, ImmutableMatrix): return diff = self - other return sympify(diff.is_zero)