def evolute(self, x='x', y='y'): """The equation of evolute of the ellipse. Parameters ========== x : str, optional Label for the x-axis. Default value is 'x'. y : str, optional Label for the y-axis. Default value is 'y'. Returns ======= equation : diofant expression Examples ======== >>> from diofant import Point, Ellipse >>> e1 = Ellipse(Point(1, 0), 3, 2) >>> e1.evolute() 2**(2/3)*y**(2/3) + (3*x - 3)**(2/3) - 5**(2/3) """ if len(self.args) != 3: raise NotImplementedError( 'Evolute of arbitrary Ellipse is not supported.') x = _symbol(x) y = _symbol(y) t1 = (self.hradius * (x - self.center.x))**Rational(2, 3) t2 = (self.vradius * (y - self.center.y))**Rational(2, 3) return t1 + t2 - (self.hradius**2 - self.vradius**2)**Rational(2, 3)
def test_egyptian_fraction(): pytest.raises(ValueError, lambda: egyptian_fraction(S.Half, "spam")) def test_equality(r, alg="Greedy"): return r == Add(*[Rational(1, i) for i in egyptian_fraction(r, alg)]) r = random_complex_number(a=0, c=1, b=0, d=0, rational=True) assert test_equality(r) assert egyptian_fraction(1) == [1] assert egyptian_fraction(Rational(4, 17)) == [5, 29, 1233, 3039345] assert egyptian_fraction(Rational(7, 13), "Greedy") == [2, 26] assert egyptian_fraction(Rational(23, 101), "Greedy") == \ [5, 37, 1438, 2985448, 40108045937720] assert egyptian_fraction(Rational(18, 23), "Takenouchi") == \ [2, 6, 12, 35, 276, 2415] assert egyptian_fraction(Rational(5, 6), "Graham Jewett") == \ [6, 7, 8, 9, 10, 42, 43, 44, 45, 56, 57, 58, 72, 73, 90, 1806, 1807, 1808, 1892, 1893, 1980, 3192, 3193, 3306, 5256, 3263442, 3263443, 3267056, 3581556, 10192056, 10650056950806] assert egyptian_fraction(Rational(5, 6), "Golomb") == [2, 6, 12, 20, 30] assert egyptian_fraction(Rational(5, 121), "Golomb") == [25, 1225, 3577, 7081, 11737] pytest.raises(ValueError, lambda: egyptian_fraction(Rational(-4, 9))) assert egyptian_fraction(Rational(8, 3), "Golomb") == [ 1, 2, 3, 4, 5, 6, 7, 14, 574, 2788, 6460, 11590, 33062, 113820 ] assert egyptian_fraction(Rational(355, 113)) == [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 744, 893588, 1251493536607, 20361068938197002344405230 ]
def test_root(): from diofant.abc import x n = Symbol('n', integer=True) k = Symbol('k', integer=True) assert root(2, 2) == sqrt(2) assert root(2, 1) == 2 assert root(2, 3) == 2**Rational(1, 3) assert root(2, 3) == cbrt(2) assert root(2, -5) == 2**Rational(4, 5) / 2 assert root(-2, 1) == -2 assert root(-2, 2) == sqrt(2) * I assert root(-2, 1) == -2 assert root(x, 2) == sqrt(x) assert root(x, 1) == x assert root(x, 3) == x**Rational(1, 3) assert root(x, 3) == cbrt(x) assert root(x, -5) == x**Rational(-1, 5) assert root(x, n) == x**(1 / n) assert root(x, -n) == x**(-1 / n) assert root(x, n, k) == x**(1 / n) * (-1)**(2 * k / n)
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 test_Number(): assert precedence(Integer(0)) == PRECEDENCE["Atom"] assert precedence(Integer(1)) == PRECEDENCE["Atom"] assert precedence(Integer(-1)) == PRECEDENCE["Add"] assert precedence(Integer(10)) == PRECEDENCE["Atom"] assert precedence(Rational(5, 2)) == PRECEDENCE["Mul"] assert precedence(Rational(-5, 2)) == PRECEDENCE["Add"] assert precedence(Float(5)) == PRECEDENCE["Atom"] assert precedence(Float(-5)) == PRECEDENCE["Add"] assert precedence(oo) == PRECEDENCE["Atom"] assert precedence(-oo) == PRECEDENCE["Add"]
def test_Max(): from diofant.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) nn_ = Symbol('nn_', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) np = Symbol('np', nonpositive=True) np_ = Symbol('np_', nonpositive=True) r = Symbol('r', extended_real=True) assert Max(5, 4) == 5 # lists pytest.raises(ValueError, lambda: Max()) assert Max(x, y) == Max(y, x) assert Max(x, y, z) == Max(z, y, x) assert Max(x, Max(y, z)) == Max(z, y, x) assert Max(x, Min(y, oo)) == Max(x, y) assert Max(n, -oo, n_, p, 2) == Max(p, 2) assert Max(n, -oo, n_, p) == p assert Max(2, x, p, n, -oo, S.NegativeInfinity, n_, p, 2) == Max(2, x, p) assert Max(0, x, 1, y) == Max(1, x, y) assert Max(r, r + 1, r - 1) == 1 + r assert Max(1000, 100, -100, x, p, n) == Max(p, x, 1000) assert Max(cos(x), sin(x)) == Max(sin(x), cos(x)) assert Max(cos(x), sin(x)).subs(x, 1) == sin(1) assert Max(cos(x), sin(x)).subs(x, Rational(1, 2)) == cos(Rational(1, 2)) pytest.raises(ValueError, lambda: Max(cos(x), sin(x)).subs(x, I)) pytest.raises(ValueError, lambda: Max(I)) pytest.raises(ValueError, lambda: Max(I, x)) pytest.raises(ValueError, lambda: Max(S.ComplexInfinity, 1)) # interesting: # Max(n, -oo, n_, p, 2) == Max(p, 2) # True # Max(n, -oo, n_, p, 1000) == Max(p, 1000) # False assert Max(1, x).diff(x) == Heaviside(x - 1) assert Max(x, 1).diff(x) == Heaviside(x - 1) assert Max(x**2, 1 + x, 1).diff(x) == \ 2*x*Heaviside(x**2 - Max(1, x + 1)) \ + Heaviside(x - Max(1, x**2) + 1) a, b = Symbol('a', extended_real=True), Symbol('b', extended_real=True) # a and b are both real, Max(a, b) should be real assert Max(a, b).is_extended_real # issue 7233 e = Max(0, x) assert e.evalf == e.n assert e.n().args == (0, x)
def parse_derivative(deriv): # scan derivatives tower in the input expression and return # underlying function and maximal differentiation order expr, sym, order = deriv.expr, deriv.variables[0], 1 for s in deriv.variables[1:]: if s == sym: order += 1 else: raise NotImplementedError( 'Improve MV Derivative support in collect') while isinstance(expr, Derivative): s0 = expr.variables[0] for s in expr.variables: if s != s0: raise NotImplementedError( 'Improve MV Derivative support in collect') if s0 == sym: expr, order = expr.expr, order + len(expr.variables) else: break return expr, (sym, Rational(order))
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 __iter__(self): seen = [] for n, d in cantor_product(S.Integers, S.Naturals): r = Rational(n, d) if r not in seen: seen.append(r) yield r
def _eval_expand_func(self, **hints): n, z = self.args if n.is_Integer and n.is_nonnegative: if z.is_Add: coeff = z.args[0] if coeff.is_Integer: e = -(n + 1) if coeff > 0: tail = Add( *[Pow(z - i, e) for i in range(1, int(coeff) + 1)]) else: tail = -Add( *[Pow(z + i, e) for i in range(0, int(-coeff))]) return polygamma(n, z - coeff) + (-1)**n * factorial(n) * tail elif z.is_Mul: coeff, z = z.as_two_terms() if coeff.is_Integer and coeff.is_positive: tail = [ polygamma(n, z + Rational(i, coeff)) for i in range(0, int(coeff)) ] if n == 0: return Add(*tail) / coeff + log(coeff) else: return Add(*tail) / coeff**(n + 1) z *= coeff return polygamma(n, z)
def _delta(p, k): B = S.One D = p.subs(n, a + k) for i in range(1, k + 1): B *= -Rational(k - i + 1, i) D += B * p.subs(n, a + k - i) return D
def test_Singletons(): protocols = [0, 1, 2, 3] copiers = [copy.copy, copy.deepcopy] copiers += [lambda x: pickle.loads(pickle.dumps(x, p)) for p in protocols] for obj in (Integer(-1), Integer(0), Integer(1), Rational(1, 2), pi, E, I, oo, -oo, zoo, nan, GoldenRatio, EulerGamma, Catalan, S.EmptySet, S.IdentityFunction): for func in copiers: assert func(obj) is obj
def repl(nu, z): if (nu % 1) == Rational(1, 2): return exptrigsimp( trigsimp( unpolarify( fro(nu, z0).rewrite(besselj).rewrite(jn).expand( func=True)).subs(z0, z))) elif nu.is_Integer and nu > 1: return fro(nu, z).expand(func=True) return fro(nu, z)
def _real_to_rational(expr, tolerance=None): """ Replace all reals in expr with rationals. >>> from diofant import nsimplify >>> from diofant.abc import x >>> nsimplify(.76 + .1*x**.5, rational=True) sqrt(x)/10 + 19/25 """ p = expr reps = {} reduce_num = None if tolerance is not None and tolerance < 1: reduce_num = ceiling(1 / tolerance) for float in p.atoms(Float): key = float if reduce_num is not None: r = Rational(float).limit_denominator(reduce_num) elif (tolerance is not None and tolerance >= 1 and float.is_Integer is False): r = Rational(tolerance * round(float / tolerance)).limit_denominator( int(tolerance)) else: r = nsimplify(float, rational=False) # e.g. log(3).n() -> log(3) instead of a Rational if float and not r: r = Rational(float) elif not r.is_Rational: if float < 0: float = -float d = Pow(10, int((mpmath.log(float) / mpmath.log(10)))) r = -Rational(str(float / d)) * d elif float > 0: d = Pow(10, int((mpmath.log(float) / mpmath.log(10)))) r = Rational(str(float / d)) * d else: r = Integer(0) reps[key] = r return p.subs(reps, simultaneous=True)
def _eval_aseries(self, n, args0, x, logx): from diofant import Order if args0[0] != oo: return super(loggamma, self)._eval_aseries(n, args0, x, logx) z = self.args[0] m = min(n, ceiling((n + Integer(1)) / 2)) r = log(z) * (z - Rational(1, 2)) - z + log(2 * pi) / 2 l = [ bernoulli(2 * k) / (2 * k * (2 * k - 1) * z**(2 * k - 1)) for k in range(1, m) ] o = None if m == 0: o = Order(1, x) else: o = Order(1 / z**(2 * m - 1), x) # It is very inefficient to first add the order and then do the nseries return (r + Add(*l))._eval_nseries(x, n, logx) + o
def components(f, x): """ Returns a set of all functional components of the given expression which includes symbols, function applications and compositions and non-integer powers. Fractional powers are collected with with minimal, positive exponents. >>> from diofant import cos, sin >>> from diofant.abc import x, y >>> from diofant.integrals.heurisch import components >>> components(sin(x)*cos(x)**2, x) == {x, sin(x), cos(x)} True See Also ======== diofant.integrals.heurisch.heurisch """ result = set() if x in f.free_symbols: if f.is_Symbol: result.add(f) elif f.is_Function or f.is_Derivative: for g in f.args: result |= components(g, x) result.add(f) elif f.is_Pow: result |= components(f.base, x) if not f.exp.is_Integer: if f.exp.is_Rational: result.add(f.base**Rational(1, f.exp.q)) else: result |= components(f.exp, x) | {f} else: for g in f.args: result |= components(g, x) return result
def _eval_expand_func(self, **hints): arg = self.args[0] if arg.is_Rational: if abs(arg.p) > arg.q: x = Dummy('x') n = arg.p // arg.q p = arg.p - n * arg.q return gamma(x + n)._eval_expand_func().subs( x, Rational(p, arg.q)) if arg.is_Add: coeff, tail = arg.as_coeff_add() if coeff and coeff.q != 1: intpart = floor(coeff) tail = (coeff - intpart, ) + tail coeff = intpart tail = arg._new_rawargs(*tail, reeval=False) return gamma(tail) * RisingFactorial(tail, coeff) return self.func(*self.args)
def test_multiplicity(): for b in range(2, 20): for i in range(100): assert multiplicity(b, b**i) == i assert multiplicity(b, (b**i) * 23) == i assert multiplicity(b, (b**i) * 1000249) == i # Should be fast assert multiplicity(10, 10**10023) == 10023 # Should exit quickly assert multiplicity(10**10, 10**10) == 1 # Should raise errors for bad input pytest.raises(ValueError, lambda: multiplicity(1, 1)) pytest.raises(ValueError, lambda: multiplicity(1, 2)) pytest.raises(ValueError, lambda: multiplicity(1.3, 2)) pytest.raises(ValueError, lambda: multiplicity(2, 0)) pytest.raises(ValueError, lambda: multiplicity(1.3, 0)) # handles Rationals assert multiplicity(10, Rational(30, 7)) == 0 assert multiplicity(Rational(2, 7), Rational(4, 7)) == 1 assert multiplicity(Rational(1, 7), Rational(3, 49)) == 2 assert multiplicity(Rational(2, 7), Rational(7, 2)) == -1 assert multiplicity(3, Rational(1, 9)) == -2
def _nthroot_solve(p, n, prec): """ helper function for ``nthroot`` It denests ``p**Rational(1, n)`` using its minimal polynomial """ from diofant.polys.numberfields import _minimal_polynomial_sq from diofant.solvers import solve while n % 2 == 0: p = sqrtdenest(sqrt(p)) n = n // 2 if n == 1: return p pn = p**Rational(1, n) x = Symbol('x') f = _minimal_polynomial_sq(p, n, x) if f is None: return sols = solve(f, x) for sol in sols: if abs(sol - pn).n() < 1. / 10**prec: sol = sqrtdenest(sol) if _mexpand(sol**n) == p: return sol
def test_continued_fraction(): pytest.raises(ValueError, lambda: cf_p(1, 0, 0)) pytest.raises(ValueError, lambda: cf_p(1, 1, -1)) assert cf_p(4, 3, 0) == [1, 3] assert cf_p(0, 3, 5) == [0, 1, [2, 1, 12, 1, 2, 2]] assert cf_p(1, 1, 0) == [1] assert cf_p(3, 4, 0) == [0, 1, 3] assert cf_p(4, 5, 0) == [0, 1, 4] assert cf_p(5, 6, 0) == [0, 1, 5] assert cf_p(11, 13, 0) == [0, 1, 5, 2] assert cf_p(16, 19, 0) == [0, 1, 5, 3] assert cf_p(27, 32, 0) == [0, 1, 5, 2, 2] assert cf_p(1, 2, 5) == [[1]] assert cf_p(0, 1, 2) == [1, [2]] assert cf_p(6, 7, 49) == [1, 1, 6] assert cf_p(3796, 1387, 0) == [2, 1, 2, 1, 4] assert cf_p(3245, 10000) == [0, 3, 12, 4, 13] assert cf_p(1932, 2568) == [0, 1, 3, 26, 2] assert cf_p(6589, 2569) == [2, 1, 1, 3, 2, 1, 3, 1, 23] assert list(itertools.islice(cf_i(Phi), 7)) == [1, 1, 1, 1, 1, 1, 1] assert list(itertools.islice(cf_i(pi), 7)) == [3, 7, 15, 1, 292, 1, 1] assert list(cf_i(Rational(17, 12))) == [1, 2, 2, 2] assert list(cf_i(Rational(-17, 12))) == [-2, 1, 1, 2, 2] assert list(cf_c([1, 6, 1, 8])) == [Integer(1), Rational(7, 6), Rational(8, 7), Rational(71, 62)] assert list(cf_c([2])) == [Integer(2)] assert list(cf_c([1, 1, 1, 1, 1, 1, 1])) == [1, Integer(2), Rational(3, 2), Rational(5, 3), Rational(8, 5), Rational(13, 8), Rational(21, 13)] assert list(cf_c([1, 6, Rational(-1, 2), 4])) == [1, Rational(7, 6), Rational(5, 4), Rational(3, 2)] assert cf_r([1, 6, 1, 8]) == Rational(71, 62) assert cf_r([3]) == Integer(3) assert cf_r([-1, 5, 1, 4]) == Rational(-24, 29) assert (cf_r([0, 1, 1, 7, [24, 8]]) - (sqrt(3) + 2)/7).expand() == 0 assert cf_r([1, 5, 9]) == Rational(55, 46) assert (cf_r([[1]]) - (sqrt(5) + 1)/2).expand() == 0
def test_factorrat(): assert str(factorrat(Rational(12, 1), visual=True)) == '2**2*3**1' assert str(factorrat(Rational(1, 1), visual=True)) == '1' assert str(factorrat(Rational(25, 14), visual=True)) == '5**2/(2*7)' assert str(factorrat(Rational(-25, 14)/9, visual=True)) == '-5**2/(2*3**2*7)'
def test_equality(r, alg="Greedy"): return r == Add(*[Rational(1, i) for i in egyptian_fraction(r, alg)])
def roots_quartic(f): r""" Returns a list of roots of a quartic polynomial. There are many references for solving quartic expressions available [1-5]. This reviewer has found that many of them require one to select from among 2 or more possible sets of solutions and that some solutions work when one is searching for real roots but don't work when searching for complex roots (though this is not always stated clearly). The following routine has been tested and found to be correct for 0, 2 or 4 complex roots. The quasisymmetric case solution [6] looks for quartics that have the form `x**4 + A*x**3 + B*x**2 + C*x + D = 0` where `(C/A)**2 = D`. Although no general solution that is always applicable for all coefficients is known to this reviewer, certain conditions are tested to determine the simplest 4 expressions that can be returned: 1) `f = c + a*(a**2/8 - b/2) == 0` 2) `g = d - a*(a*(3*a**2/256 - b/16) + c/4) = 0` 3) if `f != 0` and `g != 0` and `p = -d + a*c/4 - b**2/12` then a) `p == 0` b) `p != 0` Examples ======== >>> from diofant import Poly, symbols, I >>> r = roots_quartic(Poly('x**4-6*x**3+17*x**2-26*x+20')) >>> # 4 complex roots: 1+-I*sqrt(3), 2+-I >>> sorted(str(tmp.evalf(n=2)) for tmp in r) ['1.0 + 1.7*I', '1.0 - 1.7*I', '2.0 + 1.0*I', '2.0 - 1.0*I'] References ========== .. [1] http://mathforum.org/dr.math/faq/faq.cubic.equations.html .. [2] http://en.wikipedia.org/wiki/Quartic_function#Summary_of_Ferrari.27s_method .. [3] http://planetmath.org/encyclopedia/GaloisTheoreticDerivationOfTheQuarticFormula.html .. [4] http://staff.bath.ac.uk/masjhd/JHD-CA.pdf .. [5] http://www.albmath.org/files/Math_5713.pdf .. [6] http://www.statemaster.com/encyclopedia/Quartic-equation .. [7] eqworld.ipmnet.ru/en/solutions/ae/ae0108.pdf """ _, a, b, c, d = f.monic().all_coeffs() if not d: return [S.Zero] + roots([1, a, b, c], multiple=True) elif (c/a)**2 == d: x, m = f.gen, c/a g = Poly(x**2 + a*x + b - 2*m, x) z1, z2 = roots_quadratic(g) h1 = Poly(x**2 - z1*x + m, x) h2 = Poly(x**2 - z2*x + m, x) r1 = roots_quadratic(h1) r2 = roots_quadratic(h2) return r1 + r2 else: a2 = a**2 e = b - 3*a2/8 f = c + a*(a2/8 - b/2) g = d - a*(a*(3*a2/256 - b/16) + c/4) aon4 = a/4 if f is S.Zero: y1, y2 = [sqrt(tmp) for tmp in roots([1, e, g], multiple=True)] return [tmp - aon4 for tmp in [-y1, -y2, y1, y2]] if g is S.Zero: y = [S.Zero] + roots([1, 0, e, f], multiple=True) return [tmp - aon4 for tmp in y] else: # Descartes-Euler method, see [7] sols = _roots_quartic_euler(e, f, g, aon4) if sols: return sols # Ferrari method, see [1, 2] a2 = a**2 e = b - 3*a2/8 f = c + a*(a2/8 - b/2) g = d - a*(a*(3*a2/256 - b/16) + c/4) p = -e**2/12 - g q = -e**3/108 + e*g/3 - f**2/8 TH = Rational(1, 3) def _ans(y): w = sqrt(e + 2*y) arg1 = 3*e + 2*y arg2 = 2*f/w ans = [] for s in [-1, 1]: root = sqrt(-(arg1 + s*arg2)) for t in [-1, 1]: ans.append((s*w - t*root)/2 - aon4) return ans # p == 0 case y1 = -5*e/6 - q**TH if p.is_zero: return _ans(y1) # if p != 0 then u below is not 0 root = sqrt(q**2/4 + p**3/27) r = -q/2 + root # or -q/2 - root u = r**TH # primary root of solve(x**3 - r, x) y2 = -5*e/6 + u - p/u/3 if p.is_nonzero: return _ans(y2) # sort it out once they know the values of the coefficients return [Piecewise((a1, Eq(p, 0)), (a2, True)) for a1, a2 in zip(_ans(y1), _ans(y2))]
def continued_fraction_periodic(p, q, d=0): r"""Find the periodic continued fraction [1]_ expansion. Compute the continued fraction expansion of a rational or a quadratic surd, i.e. `\frac{p + \sqrt{d}}{q}`, where `p`, `q` and `d \ge 0` are integers. Returns ======= list the continued fraction representation (canonical form) as a list of integers, optionally ending (for quadratic irrationals) with repeating block as the last term of this list. Parameters ========== p : int the rational part of the number's numerator q : int the denominator of the number d : int, optional the irrational part (discriminator) of the number's numerator Examples ======== >>> from diofant.ntheory.continued_fraction import continued_fraction_periodic >>> continued_fraction_periodic(3, 2, 7) [2, [1, 4, 1, 1]] Golden ratio has the simplest continued fraction expansion: >>> continued_fraction_periodic(1, 2, 5) [[1]] If the discriminator is zero or a perfect square then the number will be a rational number: >>> continued_fraction_periodic(4, 3, 0) [1, 3] >>> continued_fraction_periodic(4, 3, 49) [3, 1, 2] See Also ======== continued_fraction_iterator, continued_fraction_reduce References ========== .. [1] http://en.wikipedia.org/wiki/Periodic_continued_fraction .. [2] K. Rosen. Elementary Number theory and its applications. Addison-Wesley, 3 Sub edition, pages 379-381, January 1992. """ from diofant.core.compatibility import as_int from diofant.functions import sqrt p, q, d = list(map(as_int, [p, q, d])) sd = sqrt(d) if q == 0: raise ValueError("The denominator is zero.") if d < 0: raise ValueError("Delta supposed to be a non-negative " "integer, got %d" % d) elif d == 0 or sd.is_integer: # the number is a rational number return list(continued_fraction_iterator(Rational(p + sd, q))) if (d - p**2) % q: d *= q**2 sd *= q p *= abs(q) q *= abs(q) terms = [] pq = {} while (p, q) not in pq: pq[(p, q)] = len(terms) terms.append(int((p + sd) / q)) p = terms[-1] * q - p q = (d - p**2) / q i = pq[(p, q)] return terms[:i] + [terms[i:]]
def multiplicity(p, n): """Find the greatest integer m such that p**m divides n. Examples ======== >>> from diofant.ntheory import multiplicity >>> from diofant.core.numbers import Rational as R >>> [multiplicity(5, n) for n in [8, 5, 25, 125, 250]] [0, 1, 2, 3, 3] >>> multiplicity(3, R(1, 9)) -2 """ try: p, n = as_int(p), as_int(n) except ValueError: if all(isinstance(i, (DIOFANT_INTS, Rational)) for i in (p, n)): try: p = Rational(p) n = Rational(n) if p.q == 1: if n.p == 1: return -multiplicity(p.p, n.q) return S.Zero elif p.p == 1: return multiplicity(p.q, n.q) else: like = min(multiplicity(p.p, n.p), multiplicity(p.q, n.q)) cross = min(multiplicity(p.q, n.p), multiplicity(p.p, n.q)) return like - cross except AttributeError: pass raise ValueError('expecting ints or fractions, got %s and %s' % (p, n)) if n == 0: raise ValueError('multiplicity of 0 is not defined') if p == 2: return trailing(n) if p < 2: raise ValueError('p must be an integer, 2 or larger, but got %s' % p) if p == n: return 1 m = 0 n, rem = divmod(n, p) while not rem: m += 1 if m > 5: # The multiplicity could be very large. Better # to increment in powers of two e = 2 while 1: ppow = p**e if ppow < n: nnew, rem = divmod(n, ppow) if not rem: m += e e *= 2 n = nnew continue return m + multiplicity(p, n) n, rem = divmod(n, p) return m
from diofant.polys.rootoftools import RootOf, RootSum from diofant.printing.latex import LatexPrinter from diofant.printing.mathml import MathMLPrinter from diofant.printing.pretty.pretty import PrettyPrinter from diofant.printing.pretty.stringpict import prettyForm, stringPict from diofant.printing.printer import Printer from diofant.printing.python import PythonPrinter from diofant.series.limits import Limit from diofant.series.order import Order from diofant.sets.sets import Interval from diofant.utilities.exceptions import DiofantDeprecationWarning __all__ = () # XXX we need this to initialize singleton registry properly half = Rational(1, 2) ø = S.EmptySet ℕ = S.Naturals0 def check(a, exclude=[], check_attr=True): """ Check that pickling and copying round-trips. """ # Python 2.6+ warns about BasicException.message, for example. warnings.filterwarnings("ignore", category=DeprecationWarning) protocols = list(range(5)) + [copy.copy, copy.deepcopy] for protocol in protocols: if protocol in exclude: continue
def random_point(self, seed=None): """A random point on the ellipse. Returns ======= point : Point See Also ======== diofant.geometry.point.Point arbitrary_point : Returns parameterized point on ellipse Notes ----- A random point may not appear to be on the ellipse, ie, `p in e` may return False. This is because the coordinates of the point will be floating point values, and when these values are substituted into the equation for the ellipse the result may not be zero because of floating point rounding error. Examples ======== >>> from diofant import Point, Ellipse, Segment >>> e1 = Ellipse(Point(0, 0), 3, 2) >>> e1.random_point() # gives some random point Point2D(...) >>> p1 = e1.random_point(seed=0); p1.n(2) Point2D(2.1, 1.4) The random_point method assures that the point will test as being in the ellipse: >>> p1 in e1 True Notes ===== An arbitrary_point with a random value of t substituted into it may not test as being on the ellipse because the expression tested that a point is on the ellipse doesn't simplify to zero and doesn't evaluate exactly to zero: >>> from diofant.abc import t >>> e1.arbitrary_point(t) Point2D(3*cos(t), 2*sin(t)) >>> p2 = _.subs(t, 0.1) >>> p2 in e1 False Note that arbitrary_point routine does not take this approach. A value for cos(t) and sin(t) (not t) is substituted into the arbitrary point. There is a small chance that this will give a point that will not test as being in the ellipse, so the process is repeated (up to 10 times) until a valid point is obtained. """ from diofant import sin, cos, Rational t = _symbol('t') x, y = self.arbitrary_point(t).args # get a random value in [-1, 1) corresponding to cos(t) # and confirm that it will test as being in the ellipse if seed is not None: rng = random.Random(seed) else: rng = random for i in range(10): # should be enough? # simplify this now or else the Float will turn s into a Float c = 2 * Rational(rng.random()) - 1 s = sqrt(1 - c**2) p1 = Point(x.subs(cos(t), c), y.subs(sin(t), s)) if p1 in self: return p1 raise GeometryError( 'Having problems generating a point in the ellipse.')
def test_core_numbers(): for c in (Integer(2), Rational(2, 3), Float("1.2")): check(c)
def powsimp(expr, deep=False, combine='all', force=False, measure=count_ops): """ reduces expression by combining powers with similar bases and exponents. Notes ===== If deep is True then powsimp() will also simplify arguments of functions. By default deep is set to False. If force is True then bases will be combined without checking for assumptions, e.g. sqrt(x)*sqrt(y) -> sqrt(x*y) which is not true if x and y are both negative. You can make powsimp() only combine bases or only combine exponents by changing combine='base' or combine='exp'. By default, combine='all', which does both. combine='base' will only combine:: a a a 2x x x * y => (x*y) as well as things like 2 => 4 and combine='exp' will only combine :: a b (a + b) x * x => x combine='exp' will strictly only combine exponents in the way that used to be automatic. Also use deep=True if you need the old behavior. When combine='all', 'exp' is evaluated first. Consider the first example below for when there could be an ambiguity relating to this. This is done so things like the second example can be completely combined. If you want 'base' combined first, do something like powsimp(powsimp(expr, combine='base'), combine='exp'). Examples ======== >>> from diofant import powsimp, exp, log, symbols >>> from diofant.abc import x, y, z, n >>> powsimp(x**y*x**z*y**z, combine='all') x**(y + z)*y**z >>> powsimp(x**y*x**z*y**z, combine='exp') x**(y + z)*y**z >>> powsimp(x**y*x**z*y**z, combine='base', force=True) x**y*(x*y)**z >>> powsimp(x**z*x**y*n**z*n**y, combine='all', force=True) (n*x)**(y + z) >>> powsimp(x**z*x**y*n**z*n**y, combine='exp') n**(y + z)*x**(y + z) >>> powsimp(x**z*x**y*n**z*n**y, combine='base', force=True) (n*x)**y*(n*x)**z >>> x, y = symbols('x y', positive=True) >>> powsimp(log(exp(x)*exp(y))) log(E**x*E**y) >>> powsimp(log(exp(x)*exp(y)), deep=True) x + y Radicals with Mul bases will be combined if combine='exp' >>> from diofant import sqrt, Mul >>> x, y = symbols('x y') Two radicals are automatically joined through Mul: >>> a=sqrt(x*sqrt(y)) >>> a*a**3 == a**4 True But if an integer power of that radical has been autoexpanded then Mul does not join the resulting factors: >>> a**4 # auto expands to a Mul, no longer a Pow x**2*y >>> _*a # so Mul doesn't combine them x**2*y*sqrt(x*sqrt(y)) >>> powsimp(_) # but powsimp will (x*sqrt(y))**(5/2) >>> powsimp(x*y*a) # but won't when doing so would violate assumptions x*y*sqrt(x*sqrt(y)) """ from diofant.matrices.expressions.matexpr import MatrixSymbol def recurse(arg, **kwargs): _deep = kwargs.get('deep', deep) _combine = kwargs.get('combine', combine) _force = kwargs.get('force', force) _measure = kwargs.get('measure', measure) return powsimp(arg, _deep, _combine, _force, _measure) expr = sympify(expr) if (not isinstance(expr, Basic) or isinstance(expr, MatrixSymbol) or (expr.is_Atom or expr in (exp_polar(0), exp_polar(1)))): return expr if deep or expr.is_Add or expr.is_Mul and _y not in expr.args: expr = expr.func(*[recurse(w) for w in expr.args]) if expr.is_Pow: return recurse(expr * _y, deep=False) / _y if not expr.is_Mul: return expr # handle the Mul if combine in ('exp', 'all'): # Collect base/exp data, while maintaining order in the # non-commutative parts of the product c_powers = defaultdict(list) nc_part = [] newexpr = [] coeff = S.One for term in expr.args: if term.is_Rational: coeff *= term continue if term.is_Pow: term = _denest_pow(term) if term.is_commutative: b, e = term.as_base_exp() if deep: b, e = [recurse(i) for i in [b, e]] if b.is_Pow: # don't let smthg like sqrt(x**a) split into x**a, 1/2 # or else it will be joined as x**(a/2) later b, e = b**e, S.One c_powers[b].append(e) else: # This is the logic that combines exponents for equal, # but non-commutative bases: A**x*A**y == A**(x+y). if nc_part: b1, e1 = nc_part[-1].as_base_exp() b2, e2 = term.as_base_exp() if (b1 == b2 and e1.is_commutative and e2.is_commutative): nc_part[-1] = Pow(b1, Add(e1, e2)) continue nc_part.append(term) # add up exponents of common bases for b, e in ordered(iter(c_powers.items())): # allow 2**x/4 -> 2**(x - 2); don't do this when b and e are # Numbers since autoevaluation will undo it, e.g. # 2**(1/3)/4 -> 2**(1/3 - 2) -> 2**(1/3)/4 if (b and b.is_Number and not all(ei.is_Number for ei in e) and coeff is not S.One and b not in (S.One, S.NegativeOne)): m = multiplicity(abs(b), abs(coeff)) if m: e.append(m) coeff /= b**m c_powers[b] = Add(*e) if coeff is not S.One: if coeff in c_powers: c_powers[coeff] += S.One else: c_powers[coeff] = S.One # convert to plain dictionary c_powers = dict(c_powers) # check for base and inverted base pairs be = list(c_powers.items()) skip = set() # skip if we already saw them for b, e in be: if b in skip: continue bpos = b.is_positive or b.is_polar if bpos: binv = 1 / b if b != binv and binv in c_powers: if b.as_numer_denom()[0] is S.One: c_powers.pop(b) c_powers[binv] -= e else: skip.add(binv) e = c_powers.pop(binv) c_powers[b] -= e # check for base and negated base pairs be = list(c_powers.items()) _n = S.NegativeOne for i, (b, e) in enumerate(be): if ((-b).is_Symbol or b.is_Add) and -b in c_powers: if (b.is_positive in (0, 1) or e.is_integer): c_powers[-b] += c_powers.pop(b) if _n in c_powers: c_powers[_n] += e else: c_powers[_n] = e # filter c_powers and convert to a list c_powers = [(b, e) for b, e in c_powers.items() if e] # ============================================================== # check for Mul bases of Rational powers that can be combined with # separated bases, e.g. x*sqrt(x*y)*sqrt(x*sqrt(x*y)) -> # (x*sqrt(x*y))**(3/2) # ---------------- helper functions def ratq(x): '''Return Rational part of x's exponent as it appears in the bkey. ''' return bkey(x)[0][1] def bkey(b, e=None): '''Return (b**s, c.q), c.p where e -> c*s. If e is not given then it will be taken by using as_base_exp() on the input b. e.g. x**3/2 -> (x, 2), 3 x**y -> (x**y, 1), 1 x**(2*y/3) -> (x**y, 3), 2 exp(x/2) -> (exp(a), 2), 1 ''' if e is not None: # coming from c_powers or from below if e.is_Integer: return (b, S.One), e elif e.is_Rational: return (b, Integer(e.q)), Integer(e.p) else: c, m = e.as_coeff_Mul(rational=True) if c is not S.One and b.is_positive: return (b**m, Integer(c.q)), Integer(c.p) else: return (b**e, S.One), S.One else: return bkey(*b.as_base_exp()) def update(b): '''Decide what to do with base, b. If its exponent is now an integer multiple of the Rational denominator, then remove it and put the factors of its base in the common_b dictionary or update the existing bases if necessary. If it has been zeroed out, simply remove the base. ''' newe, r = divmod(common_b[b], b[1]) if not r: common_b.pop(b) if newe: for m in Mul.make_args(b[0]**newe): b, e = bkey(m) if b not in common_b: common_b[b] = 0 common_b[b] += e if b[1] != 1: bases.append(b) # ---------------- end of helper functions # assemble a dictionary of the factors having a Rational power common_b = {} done = [] bases = [] for b, e in c_powers: b, e = bkey(b, e) if b in common_b.keys(): common_b[b] = common_b[b] + e else: common_b[b] = e if b[1] != 1 and b[0].is_Mul: bases.append(b) c_powers = [(b, e) for b, e in common_b.items() if e] bases.sort(key=default_sort_key) # this makes tie-breaking canonical bases.sort(key=measure, reverse=True) # handle longest first for base in bases: if base not in common_b: # it may have been removed already continue b, exponent = base last = False # True when no factor of base is a radical qlcm = 1 # the lcm of the radical denominators while True: bstart = b qstart = qlcm bb = [] # list of factors ee = [] # (factor's expo. and it's current value in common_b) for bi in Mul.make_args(b): bib, bie = bkey(bi) if bib not in common_b or common_b[bib] < bie: ee = bb = [] # failed break ee.append([bie, common_b[bib]]) bb.append(bib) if ee: # find the number of extractions possible # e.g. [(1, 2), (2, 2)] -> min(2/1, 2/2) -> 1 min1 = ee[0][1] / ee[0][0] for i in range(len(ee)): rat = ee[i][1] / ee[i][0] if rat < 1: break min1 = min(min1, rat) else: # update base factor counts # e.g. if ee = [(2, 5), (3, 6)] then min1 = 2 # and the new base counts will be 5-2*2 and 6-2*3 for i in range(len(bb)): common_b[bb[i]] -= min1 * ee[i][0] update(bb[i]) # update the count of the base # e.g. x**2*y*sqrt(x*sqrt(y)) the count of x*sqrt(y) # will increase by 4 to give bkey (x*sqrt(y), 2, 5) common_b[base] += min1 * qstart * exponent if (last # no more radicals in base or len(common_b) == 1 # nothing left to join with or all(k[1] == 1 for k in common_b) # no rad's in common_b ): break # see what we can exponentiate base by to remove any radicals # so we know what to search for # e.g. if base were x**(1/2)*y**(1/3) then we should # exponentiate by 6 and look for powers of x and y in the ratio # of 2 to 3 qlcm = lcm([ratq(bi) for bi in Mul.make_args(bstart)]) if qlcm == 1: break # we are done b = bstart**qlcm qlcm *= qstart if all(ratq(bi) == 1 for bi in Mul.make_args(b)): last = True # we are going to be done after this next pass # this base no longer can find anything to join with and # since it was longer than any other we are done with it b, q = base done.append((b, common_b.pop(base) * Rational(1, q))) # update c_powers and get ready to continue with powsimp c_powers = done # there may be terms still in common_b that were bases that were # identified as needing processing, so remove those, too for (b, q), e in common_b.items(): if b.is_Pow and q is not S.One and not b.exp.is_Rational: b, be = b.as_base_exp() b = b**(be / q) else: b = root(b, q) c_powers.append((b, e)) check = len(c_powers) c_powers = dict(c_powers) assert len(c_powers) == check # there should have been no duplicates # ============================================================== # rebuild the expression newexpr = expr.func(*(newexpr + [Pow(b, e) for b, e in c_powers.items()])) if combine == 'exp': return expr.func(newexpr, expr.func(*nc_part)) else: return recurse(expr.func(*nc_part), combine='base') * \ recurse(newexpr, combine='base') elif combine == 'base': # Build c_powers and nc_part. These must both be lists not # dicts because exp's are not combined. c_powers = [] nc_part = [] for term in expr.args: if term.is_commutative: c_powers.append(list(term.as_base_exp())) else: # This is the logic that combines bases that are # different and non-commutative, but with equal and # commutative exponents: A**x*B**x == (A*B)**x. if nc_part: b1, e1 = nc_part[-1].as_base_exp() b2, e2 = term.as_base_exp() if (e1 == e2 and e2.is_commutative): nc_part[-1] = Pow(b1 * b2, e1) continue nc_part.append(term) # Pull out numerical coefficients from exponent if assumptions allow # e.g., 2**(2*x) => 4**x for i in range(len(c_powers)): b, e = c_powers[i] if not (all(x.is_nonnegative for x in b.as_numer_denom()) or e.is_integer or force or b.is_polar): continue exp_c, exp_t = e.as_coeff_Mul(rational=True) if exp_c is not S.One and exp_t is not S.One: c_powers[i] = [Pow(b, exp_c), exp_t] # Combine bases whenever they have the same exponent and # assumptions allow # first gather the potential bases under the common exponent c_exp = defaultdict(list) for b, e in c_powers: if deep: e = recurse(e) c_exp[e].append(b) del c_powers # Merge back in the results of the above to form a new product c_powers = defaultdict(list) for e in c_exp: bases = c_exp[e] # calculate the new base for e if len(bases) == 1: new_base = bases[0] elif e.is_integer or force: new_base = expr.func(*bases) else: # see which ones can be joined unk = [] nonneg = [] neg = [] for bi in bases: if bi.is_negative: neg.append(bi) elif bi.is_nonnegative: nonneg.append(bi) elif bi.is_polar: nonneg.append( bi) # polar can be treated like non-negative else: unk.append(bi) if len(unk) == 1 and not neg or len(neg) == 1 and not unk: # a single neg or a single unk can join the rest nonneg.extend(unk + neg) unk = neg = [] elif neg: # their negative signs cancel in groups of 2*q if we know # that e = p/q else we have to treat them as unknown israt = False if e.is_Rational: israt = True else: p, d = e.as_numer_denom() if p.is_integer and d.is_integer: israt = True if israt: neg = [-w for w in neg] unk.extend([S.NegativeOne] * len(neg)) else: unk.extend(neg) neg = [] del israt # these shouldn't be joined for b in unk: c_powers[b].append(e) # here is a new joined base new_base = expr.func(*(nonneg + neg)) # if there are positive parts they will just get separated # again unless some change is made def _terms(e): # return the number of terms of this expression # when multiplied out -- assuming no joining of terms if e.is_Add: return sum(_terms(ai) for ai in e.args) if e.is_Mul: return prod([_terms(mi) for mi in e.args]) return 1 xnew_base = expand_mul(new_base, deep=False) if len(Add.make_args(xnew_base)) < _terms(new_base): new_base = factor_terms(xnew_base) c_powers[new_base].append(e) # break out the powers from c_powers now c_part = [Pow(b, ei) for b, e in c_powers.items() for ei in e] # we're done return expr.func(*(c_part + nc_part)) else: raise ValueError("combine must be one of ('all', 'exp', 'base').")
def eval(cls, n, z): n, z = list(map(sympify, (n, z))) from diofant import unpolarify if n.is_integer: if n.is_nonnegative: nz = unpolarify(z) if z != nz: return polygamma(n, nz) if n == -1: return loggamma(z) else: if z.is_Number: if z is S.Infinity: if n.is_Number: if n is S.Zero: return S.Infinity else: return S.Zero elif z.is_Integer: if z.is_nonpositive: return S.ComplexInfinity else: if n is S.Zero: return -S.EulerGamma + harmonic(z - 1, 1) elif n.is_odd: return (-1)**(n + 1) * factorial(n) * zeta( n + 1, z) if n == 0: if z.is_Rational: # TODO actually *any* n/m can be done, but that is messy lookup = { Rational(1, 2): -2 * log(2) - S.EulerGamma, Rational(1, 3): -S.Pi / 2 / sqrt(3) - 3 * log(3) / 2 - S.EulerGamma, Rational(1, 4): -S.Pi / 2 - 3 * log(2) - S.EulerGamma, Rational(3, 4): -3 * log(2) - S.EulerGamma + S.Pi / 2, Rational(2, 3): -3 * log(3) / 2 + S.Pi / 2 / sqrt(3) - S.EulerGamma } if z > 0: n = floor(z) z0 = z - n if z0 in lookup: return lookup[z0] + Add( *[1 / (z0 + k) for k in range(n)]) elif z < 0: n = floor(1 - z) z0 = z + n if z0 in lookup: return lookup[z0] - Add( *[1 / (z0 - 1 - k) for k in range(n)]) elif z in (S.Infinity, S.NegativeInfinity): return S.Infinity else: t = z.extract_multiplicatively(S.ImaginaryUnit) if t in (S.Infinity, S.NegativeInfinity): return S.Infinity