def test_atoms(): m = PropertiesOnlyMatrix(2, 2, [1, 2, x, 1 - 1 / x]) assert m.atoms() == {S.One, S(2), S.NegativeOne, x} assert m.atoms(Symbol) == {x}
def test_rational_laurent_series(): """ This function tests the computation of coefficients of Laurent series of a rational function. Each test case has 5 values - 1. num - Numerator of the rational function. 2. den - Denominator of the rational function. 3. x0 - Point about which Laurent series is to be calculated. 4. mul - Multiplicity of x0 if x0 is a pole of the rational function (0 otherwise). 5. n - Number of terms upto which the series is to be calcuated. """ tests = [ # Laurent series about simple pole (Multiplicity = 1) ( Poly(x**2 - 3*x + 9, x, extension=True), Poly(x**2 - x, x, extension=True), S(1), 1, 6, {1: 7, 0: -8, -1: 9, -2: -9, -3: 9, -4: -9} ), # Laurent series about multiple pole (Multiplicty > 1) ( Poly(64*x**3 - 1728*x + 1216, x, extension=True), Poly(64*x**4 - 80*x**3 - 831*x**2 + 1809*x - 972, x, extension=True), S(9)/8, 2, 3, {0: S(32177152)/46521675, 2: S(1019)/984, -1: S(11947565056)/28610830125, \ 1: S(209149)/75645} ), ( Poly(1, x, extension=True), Poly(x**5 + (-4*sqrt(2) - 1)*x**4 + (4*sqrt(2) + 12)*x**3 + (-12 - 8*sqrt(2))*x**2 \ + (4 + 8*sqrt(2))*x - 4, x, extension=True), sqrt(2), 4, 6, {4: 1 + sqrt(2), 3: -3 - 2*sqrt(2), 2: Mul(-1, -3 - 2*sqrt(2), evaluate=False)/(-1 \ + sqrt(2)), 1: (-3 - 2*sqrt(2))/(-1 + sqrt(2))**2, 0: Mul(-1, -3 - 2*sqrt(2), evaluate=False \ )/(-1 + sqrt(2))**3, -1: (-3 - 2*sqrt(2))/(-1 + sqrt(2))**4} ), # Laurent series about oo ( Poly(x**5 - 4*x**3 + 6*x**2 + 10*x - 13, x, extension=True), Poly(x**2 - 5, x, extension=True), oo, 3, 6, {3: 1, 2: 0, 1: 1, 0: 6, -1: 15, -2: 17} ), # Laurent series at x0 where x0 is not a pole of the function # Using multiplicity as 0 (as x0 will not be a pole) ( Poly(3*x**3 + 6*x**2 - 2*x + 5, x, extension=True), Poly(9*x**4 - x**3 - 3*x**2 + 4*x + 4, x, extension=True), S(2)/5, 0, 1, {0: S(3345)/3304, -1: S(399325)/2729104, -2: S(3926413375)/4508479808, \ -3: S(-5000852751875)/1862002160704, -4: S(-6683640101653125)/6152055138966016} ), ( Poly(-7*x**2 + 2*x - 4, x, extension=True), Poly(7*x**5 + 9*x**4 + 8*x**3 + 3*x**2 + 6*x + 9, x, extension=True), oo, 0, 6, {0: 0, -2: 0, -5: -S(71)/49, -1: 0, -3: -1, -4: S(11)/7} )] for num, den, x0, mul, n, ser in tests: assert ser == rational_laurent_series(num, den, x, x0, mul, n)
def test_solve_riccati(): """ This function tests the computation of rational particular solutions for a Riccati ODE. Each test case has 2 values - 1. eq - Riccati ODE to be solved. 2. sol - Expected solution to the equation. Some examples have been taken from the paper - "Statistical Investigation of First-Order Algebraic ODEs and their Rational General Solutions" by Georg Grasegger, N. Thieu Vo, Franz Winkler https://www3.risc.jku.at/publications/download/risc_5197/RISCReport15-19.pdf """ C0 = Dummy('C0') # Type: 1st Order Rational Riccati, dy/dx = a + b*y + c*y**2, # a, b, c are rational functions of x tests = [ # a(x) is a constant ( Eq(f(x).diff(x) + f(x)**2 - 2, 0), [Eq(f(x), sqrt(2)), Eq(f(x), -sqrt(2))] ), # a(x) is a constant ( f(x)**2 + f(x).diff(x) + 4*f(x)/x + 2/x**2, [Eq(f(x), (-2*C0 - x)/(C0*x + x**2))] ), # a(x) is a constant ( 2*x**2*f(x).diff(x) - x*(4*f(x) + f(x).diff(x) - 4) + (f(x) - 1)*f(x), [Eq(f(x), (C0 + 2*x**2)/(C0 + x))] ), # Pole with multiplicity 1 ( Eq(f(x).diff(x), -f(x)**2 - 2/(x**3 - x**2)), [Eq(f(x), 1/(x**2 - x))] ), # One pole of multiplicity 2 ( x**2 - (2*x + 1/x)*f(x) + f(x)**2 + f(x).diff(x), [Eq(f(x), (C0*x + x**3 + 2*x)/(C0 + x**2)), Eq(f(x), x)] ), ( x**4*f(x).diff(x) + x**2 - x*(2*f(x)**2 + f(x).diff(x)) + f(x), [Eq(f(x), (C0*x**2 + x)/(C0 + x**2)), Eq(f(x), x**2)] ), # Multiple poles of multiplicity 2 ( -f(x)**2 + f(x).diff(x) + (15*x**2 - 20*x + 7)/((x - 1)**2*(2*x \ - 1)**2), [Eq(f(x), (9*C0*x - 6*C0 - 15*x**5 + 60*x**4 - 94*x**3 + 72*x**2 \ - 30*x + 6)/(6*C0*x**2 - 9*C0*x + 3*C0 + 6*x**6 - 29*x**5 + \ 57*x**4 - 58*x**3 + 30*x**2 - 6*x)), Eq(f(x), (3*x - 2)/(2*x**2 \ - 3*x + 1))] ), # Regression: Poles with even multiplicity > 2 fixed ( f(x)**2 + f(x).diff(x) - (4*x**6 - 8*x**5 + 12*x**4 + 4*x**3 + \ 7*x**2 - 20*x + 4)/(4*x**4), [Eq(f(x), (2*x**5 - 2*x**4 - x**3 + 4*x**2 + 3*x - 2)/(2*x**4 \ - 2*x**2))] ), # Regression: Poles with even multiplicity > 2 fixed ( Eq(f(x).diff(x), (-x**6 + 15*x**4 - 40*x**3 + 45*x**2 - 24*x + 4)/\ (x**12 - 12*x**11 + 66*x**10 - 220*x**9 + 495*x**8 - 792*x**7 + 924*x**6 - \ 792*x**5 + 495*x**4 - 220*x**3 + 66*x**2 - 12*x + 1) + f(x)**2 + f(x)), [Eq(f(x), 1/(x**6 - 6*x**5 + 15*x**4 - 20*x**3 + 15*x**2 - 6*x + 1))] ), # More than 2 poles with multiplicity 2 # Regression: Fixed mistake in necessary conditions ( Eq(f(x).diff(x), x*f(x) + 2*x + (3*x - 2)*f(x)**2/(4*x + 2) + \ (8*x**2 - 7*x + 26)/(16*x**3 - 24*x**2 + 8) - S(3)/2), [Eq(f(x), (1 - 4*x)/(2*x - 2))] ), # Regression: Fixed mistake in necessary conditions ( Eq(f(x).diff(x), (-12*x**2 - 48*x - 15)/(24*x**3 - 40*x**2 + 8*x + 8) \ + 3*f(x)**2/(6*x + 2)), [Eq(f(x), (2*x + 1)/(2*x - 2))] ), # Imaginary poles ( f(x).diff(x) + (3*x**2 + 1)*f(x)**2/x + (6*x**2 - x + 3)*f(x)/(x*(x \ - 1)) + (3*x**2 - 2*x + 2)/(x*(x - 1)**2), [Eq(f(x), (-C0 - x**3 + x**2 - 2*x)/(C0*x - C0 + x**4 - x**3 + x**2 \ - x)), Eq(f(x), -1/(x - 1))], ), # Imaginary coefficients in equation ( f(x).diff(x) - 2*I*(f(x)**2 + 1)/x, [Eq(f(x), (-I*C0 + I*x**4)/(C0 + x**4)), Eq(f(x), -I)] ), # Regression: linsolve returning empty solution # Large value of m (> 10) ( Eq(f(x).diff(x), x*f(x)/(S(3)/2 - 2*x) + (x/2 - S(1)/3)*f(x)**2/\ (2*x/3 - S(1)/2) - S(5)/4 + (281*x**2 - 1260*x + 756)/(16*x**3 - 12*x**2)), [Eq(f(x), (9 - x)/x), Eq(f(x), (40*x**14 + 28*x**13 + 420*x**12 + 2940*x**11 + \ 18480*x**10 + 103950*x**9 + 519750*x**8 + 2286900*x**7 + 8731800*x**6 + 28378350*\ x**5 + 76403250*x**4 + 163721250*x**3 + 261954000*x**2 + 278326125*x + 147349125)/\ ((24*x**14 + 140*x**13 + 840*x**12 + 4620*x**11 + 23100*x**10 + 103950*x**9 + \ 415800*x**8 + 1455300*x**7 + 4365900*x**6 + 10914750*x**5 + 21829500*x**4 + 32744250\ *x**3 + 32744250*x**2 + 16372125*x)))] ), # Regression: Fixed bug due to a typo in paper ( Eq(f(x).diff(x), 18*x**3 + 18*x**2 + (-x/2 - S(1)/2)*f(x)**2 + 6), [Eq(f(x), 6*x)] ), # Regression: Fixed bug due to a typo in paper ( Eq(f(x).diff(x), -3*x**3/4 + 15*x/2 + (x/3 - S(4)/3)*f(x)**2 \ + 9 + (1 - x)*f(x)/x + 3/x), [Eq(f(x), -3*x/2 - 3)] )] for eq, sol in tests: check_dummy_sol(eq, sol, C0)
def test_Min(): from sympy.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', real=True) assert Min(5, 4) == 4 assert Min(-oo, -oo) == -oo assert Min(-oo, n) == -oo assert Min(n, -oo) == -oo assert Min(-oo, np) == -oo assert Min(np, -oo) == -oo assert Min(-oo, 0) == -oo assert Min(0, -oo) == -oo assert Min(-oo, nn) == -oo assert Min(nn, -oo) == -oo assert Min(-oo, p) == -oo assert Min(p, -oo) == -oo assert Min(-oo, oo) == -oo assert Min(oo, -oo) == -oo assert Min(n, n) == n assert unchanged(Min, n, np) assert Min(np, n) == Min(n, np) assert Min(n, 0) == n assert Min(0, n) == n assert Min(n, nn) == n assert Min(nn, n) == n assert Min(n, p) == n assert Min(p, n) == n assert Min(n, oo) == n assert Min(oo, n) == n assert Min(np, np) == np assert Min(np, 0) == np assert Min(0, np) == np assert Min(np, nn) == np assert Min(nn, np) == np assert Min(np, p) == np assert Min(p, np) == np assert Min(np, oo) == np assert Min(oo, np) == np assert Min(0, 0) == 0 assert Min(0, nn) == 0 assert Min(nn, 0) == 0 assert Min(0, p) == 0 assert Min(p, 0) == 0 assert Min(0, oo) == 0 assert Min(oo, 0) == 0 assert Min(nn, nn) == nn assert unchanged(Min, nn, p) assert Min(p, nn) == Min(nn, p) assert Min(nn, oo) == nn assert Min(oo, nn) == nn assert Min(p, p) == p assert Min(p, oo) == p assert Min(oo, p) == p assert Min(oo, oo) == oo assert Min(n, n_).func is Min assert Min(nn, nn_).func is Min assert Min(np, np_).func is Min assert Min(p, p_).func is Min # lists assert Min() == S.Infinity assert Min(x) == x assert Min(x, y) == Min(y, x) assert Min(x, y, z) == Min(z, y, x) assert Min(x, Min(y, z)) == Min(z, y, x) assert Min(x, Max(y, -oo)) == Min(x, y) assert Min(p, oo, n, p, p, p_) == n assert Min(p_, n_, p) == n_ assert Min(n, oo, -7, p, p, 2) == Min(n, -7) assert Min(2, x, p, n, oo, n_, p, 2, -2, -2) == Min(-2, x, n, n_) assert Min(0, x, 1, y) == Min(0, x, y) assert Min(1000, 100, -100, x, p, n) == Min(n, x, -100) assert unchanged(Min, sin(x), cos(x)) assert Min(sin(x), cos(x)) == Min(cos(x), sin(x)) assert Min(cos(x), sin(x)).subs(x, 1) == cos(1) assert Min(cos(x), sin(x)).subs(x, S(1) / 2) == sin(S(1) / 2) raises(ValueError, lambda: Min(cos(x), sin(x)).subs(x, I)) raises(ValueError, lambda: Min(I)) raises(ValueError, lambda: Min(I, x)) raises(ValueError, lambda: Min(S.ComplexInfinity, x)) assert Min(1, x).diff(x) == Heaviside(1 - x) assert Min(x, 1).diff(x) == Heaviside(1 - x) assert Min(0, -x, 1 - 2*x).diff(x) == -Heaviside(x + Min(0, -2*x + 1)) \ - 2*Heaviside(2*x + Min(0, -x) - 1) # issue 7619 f = Function('f') assert Min(1, 2 * Min(f(1), 2)) # doesn't fail # issue 7233 e = Min(0, x) assert e.evalf == e.n assert e.n().args == (0, x) # issue 8643 m = Min(n, p_, n_, r) assert m.is_positive is False assert m.is_nonnegative is False assert m.is_negative is True m = Min(p, p_) assert m.is_positive is True assert m.is_nonnegative is True assert m.is_negative is False m = Min(p, nn_, p_) assert m.is_positive is None assert m.is_nonnegative is True assert m.is_negative is False m = Min(nn, p, r) assert m.is_positive is None assert m.is_nonnegative is None assert m.is_negative is None
def test_construct_c_case_2(): """ This function tests the Case 2 in the step to calculate coefficients of c-vectors. Each test case has 5 values - 1. num - Numerator of the rational function a(x). 2. den - Denominator of the rational function a(x). 3. pole - Pole of a(x) for which c-vector is being calculated. 4. mul - The multiplicity of the pole. 5. c - The c-vector for the pole. """ tests = [ # Testing poles with multiplicity 2 ( Poly(1, x, extension=True), Poly((x - 1)**2*(x - 2), x, extension=True), 1, 2, [[-I*(-1 - I)/2], [I*(-1 + I)/2]] ), ( Poly(3*x**5 - 12*x**4 - 7*x**3 + 1, x, extension=True), Poly((3*x - 1)**2*(x + 2)**2, x, extension=True), S(1)/3, 2, [[-S(89)/98], [-S(9)/98]] ), # Testing poles with multiplicity 4 ( Poly(x**3 - x**2 + 4*x, x, extension=True), Poly((x - 2)**4*(x + 5)**2, x, extension=True), 2, 4, [[7*sqrt(3)*(S(60)/343 - 4*sqrt(3)/7)/12, 2*sqrt(3)/7], \ [-7*sqrt(3)*(S(60)/343 + 4*sqrt(3)/7)/12, -2*sqrt(3)/7]] ), ( Poly(3*x**5 + x**4 + 3, x, extension=True), Poly((4*x + 1)**4*(x + 2), x, extension=True), -S(1)/4, 4, [[128*sqrt(439)*(-sqrt(439)/128 - S(55)/14336)/439, sqrt(439)/256], \ [-128*sqrt(439)*(sqrt(439)/128 - S(55)/14336)/439, -sqrt(439)/256]] ), # Testing poles with multiplicity 6 ( Poly(x**3 + 2, x, extension=True), Poly((3*x - 1)**6*(x**2 + 1), x, extension=True), S(1)/3, 6, [[27*sqrt(66)*(-sqrt(66)/54 - S(131)/267300)/22, -2*sqrt(66)/1485, sqrt(66)/162], \ [-27*sqrt(66)*(sqrt(66)/54 - S(131)/267300)/22, 2*sqrt(66)/1485, -sqrt(66)/162]] ), ( Poly(x**2 + 12, x, extension=True), Poly((x - sqrt(2))**6, x, extension=True), sqrt(2), 6, [[sqrt(14)*(S(6)/7 - 3*sqrt(14))/28, sqrt(7)/7, sqrt(14)], \ [-sqrt(14)*(S(6)/7 + 3*sqrt(14))/28, -sqrt(7)/7, -sqrt(14)]] )] for num, den, pole, mul, c in tests: assert construct_c_case_2(num, den, x, pole, mul) == c
def _eval_rewrite_as_log(self, x): return S.ImaginaryUnit / 2 * (C.log( (S(1) - S.ImaginaryUnit * x) / (S(1) + S.ImaginaryUnit * x)))
def _monotonic_sign(self): """Return the value closest to 0 that ``self`` may have if all symbols are signed and the result is uniformly the same sign for all values of symbols. If a symbol is only signed but not known to be an integer or the result is 0 then a symbol representative of the sign of self will be returned. Otherwise, None is returned if a) the sign could be positive or negative or b) self is not in one of the following forms: - L(x, y, ...) + A: a function linear in all symbols x, y, ... with an additive constant; if A is zero then the function can be a monomial whose sign is monotonic over the range of the variables, e.g. (x + 1)**3 if x is nonnegative. - A/L(x, y, ...) + B: the inverse of a function linear in all symbols x, y, ... that does not have a sign change from positive to negative for any set of values for the variables. - M(x, y, ...) + A: a monomial M whose factors are all signed and a constant, A. - A/M(x, y, ...) + B: the inverse of a monomial and constants A and B. - P(x): a univariate polynomial Examples ======== >>> from sympy.core.exprtools import _monotonic_sign as F >>> from sympy import Dummy, S >>> nn = Dummy(integer=True, nonnegative=True) >>> p = Dummy(integer=True, positive=True) >>> p2 = Dummy(integer=True, positive=True) >>> F(nn + 1) 1 >>> F(p - 1) _nneg >>> F(nn*p + 1) 1 >>> F(p2*p + 1) 2 >>> F(nn - 1) # could be negative, zero or positive """ if not self.is_real: return if (-self).is_Symbol: rv = _monotonic_sign(-self) return rv if rv is None else -rv if not self.is_Add and self.as_numer_denom()[1].is_number: s = self if s.is_prime: if s.is_odd: return S(3) else: return S(2) elif s.is_positive: if s.is_even: return S(2) elif s.is_integer: return S.One else: return _eps elif s.is_negative: if s.is_even: return S(-2) elif s.is_integer: return S.NegativeOne else: return -_eps if s.is_zero or s.is_nonpositive or s.is_nonnegative: return S.Zero return None # univariate polynomial free = self.free_symbols if len(free) == 1: if self.is_polynomial(): from sympy.polys.polytools import real_roots from sympy.polys.polyroots import roots from sympy.polys.polyerrors import PolynomialError x = free.pop() x0 = _monotonic_sign(x) if x0 == _eps or x0 == -_eps: x0 = S.Zero if x0 is not None: d = self.diff(x) if d.is_number: roots = [] else: try: roots = real_roots(d) except (PolynomialError, NotImplementedError): roots = [r for r in roots(d, x) if r.is_real] y = self.subs(x, x0) if x.is_nonnegative and all(r <= x0 for r in roots): if y.is_nonnegative and d.is_positive: if y: return y if y.is_positive else Dummy('pos', positive=True) else: return Dummy('nneg', nonnegative=True) if y.is_nonpositive and d.is_negative: if y: return y if y.is_negative else Dummy('neg', negative=True) else: return Dummy('npos', nonpositive=True) elif x.is_nonpositive and all(r >= x0 for r in roots): if y.is_nonnegative and d.is_negative: if y: return Dummy('pos', positive=True) else: return Dummy('nneg', nonnegative=True) if y.is_nonpositive and d.is_positive: if y: return Dummy('neg', negative=True) else: return Dummy('npos', nonpositive=True) else: n, d = self.as_numer_denom() den = None if n.is_number: den = _monotonic_sign(d) elif not d.is_number: if _monotonic_sign(n) is not None: den = _monotonic_sign(d) if den is not None and (den.is_positive or den.is_negative): v = n * den if v.is_positive: return Dummy('pos', positive=True) elif v.is_nonnegative: return Dummy('nneg', nonnegative=True) elif v.is_negative: return Dummy('neg', negative=True) elif v.is_nonpositive: return Dummy('npos', nonpositive=True) return None # multivariate c, a = self.as_coeff_Add() v = None if not a.is_polynomial(): # F/A or A/F where A is a number and F is a signed, rational monomial n, d = a.as_numer_denom() if not (n.is_number or d.is_number): return if ( a.is_Mul or a.is_Pow) and \ a.is_rational and \ all(p.exp.is_Integer for p in a.atoms(Pow) if p.is_Pow) and \ (a.is_positive or a.is_negative): v = S(1) for ai in Mul.make_args(a): if ai.is_number: v *= ai continue reps = {} for x in ai.free_symbols: reps[x] = _monotonic_sign(x) if reps[x] is None: return v *= ai.subs(reps) elif c: # signed linear expression if not any(p for p in a.atoms(Pow) if not p.is_number) and ( a.is_nonpositive or a.is_nonnegative): free = list(a.free_symbols) p = {} for i in free: v = _monotonic_sign(i) if v is None: return p[i] = v or (_eps if i.is_nonnegative else -_eps) v = a.xreplace(p) if v is not None: rv = v + c if v.is_nonnegative and rv.is_positive: return rv.subs(_eps, 0) if v.is_nonpositive and rv.is_negative: return rv.subs(_eps, 0)
def test_harmonic_rational(): ne = S(6) no = S(5) pe = S(8) po = S(9) qe = S(10) qo = S(13) Heee = harmonic(ne + pe / qe) Aeee = (-log(10) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + pi * sqrt(2 * sqrt(5) / 5 + 1) / 2 + Rational(13944145, 4720968)) Heeo = harmonic(ne + pe / qo) Aeeo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(4, 13)) + 2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(32, 13)) + 2 * log(sin(pi * Rational(5, 13))) * cos(pi * Rational(80, 13)) - 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(5, 13)) - 2 * log(sin(pi * Rational(4, 13))) * cos(pi / 13) + pi * cot(pi * Rational(5, 13)) / 2 - 2 * log(sin(pi / 13)) * cos(pi * Rational(3, 13)) + Rational(2422020029, 702257080)) Heoe = harmonic(ne + po / qe) Aeoe = ( -log(20) + 2 * (Rational(1, 4) + sqrt(5) / 4) * log(Rational(-1, 4) + sqrt(5) / 4) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 + Rational(1, 4)) * log(Rational(1, 4) + sqrt(5) / 4) + Rational(11818877030, 4286604231) + pi * sqrt(2 * sqrt(5) + 5) / 2) Heoo = harmonic(ne + po / qo) Aeoo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(54, 13)) + 2 * log(sin(pi * Rational(4, 13))) * cos(pi * Rational(6, 13)) + 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(108, 13)) - 2 * log(sin(pi * Rational(5, 13))) * cos(pi / 13) - 2 * log(sin(pi / 13)) * cos(pi * Rational(5, 13)) + pi * cot(pi * Rational(4, 13)) / 2 - 2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(3, 13)) + Rational(11669332571, 3628714320)) Hoee = harmonic(no + pe / qe) Aoee = (-log(10) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + pi * sqrt(2 * sqrt(5) / 5 + 1) / 2 + Rational(779405, 277704)) Hoeo = harmonic(no + pe / qo) Aoeo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(4, 13)) + 2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(32, 13)) + 2 * log(sin(pi * Rational(5, 13))) * cos(pi * Rational(80, 13)) - 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(5, 13)) - 2 * log(sin(pi * Rational(4, 13))) * cos(pi / 13) + pi * cot(pi * Rational(5, 13)) / 2 - 2 * log(sin(pi / 13)) * cos(pi * Rational(3, 13)) + Rational(53857323, 16331560)) Hooe = harmonic(no + po / qe) Aooe = ( -log(20) + 2 * (Rational(1, 4) + sqrt(5) / 4) * log(Rational(-1, 4) + sqrt(5) / 4) + 2 * (Rational(-1, 4) + sqrt(5) / 4) * log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 - Rational(1, 4)) * log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + 2 * (-sqrt(5) / 4 + Rational(1, 4)) * log(Rational(1, 4) + sqrt(5) / 4) + Rational(486853480, 186374097) + pi * sqrt(2 * sqrt(5) + 5) / 2) Hooo = harmonic(no + po / qo) Aooo = (-log(26) + 2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(54, 13)) + 2 * log(sin(pi * Rational(4, 13))) * cos(pi * Rational(6, 13)) + 2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(108, 13)) - 2 * log(sin(pi * Rational(5, 13))) * cos(pi / 13) - 2 * log(sin(pi / 13)) * cos(pi * Rational(5, 13)) + pi * cot(pi * Rational(4, 13)) / 2 - 2 * log(sin(pi * Rational(2, 13))) * cos(3 * pi / 13) + Rational(383693479, 125128080)) H = [Heee, Heeo, Heoe, Heoo, Hoee, Hoeo, Hooe, Hooo] A = [Aeee, Aeeo, Aeoe, Aeoo, Aoee, Aoeo, Aooe, Aooo] for h, a in zip(H, A): e = expand_func(h).doit() assert cancel(e / a) == 1 assert abs(h.n() - a.n()) < 1e-12
def test_zeta(): s = S(5) x = Zeta('x', s) assert E(x) == zeta(s - 1) / zeta(s) assert simplify( variance(x)) == (zeta(s) * zeta(s - 2) - zeta(s - 1)**2) / zeta(s)**2
def test_dmp_from_sympy(): assert dmp_from_sympy([[S(1), S(2)], [S(0)]], 1, ZZ) == \ [[ZZ(1), ZZ(2)], []] assert dmp_from_sympy([[S(1)/2, S(2)]], 1, QQ) == \ [[QQ(1, 2), QQ(2, 1)]]
def test_issue_6121(): eq = -I * exp(-3 * I * pi / 4) / (4 * pi**(S(3) / 2) * sqrt(x)) assert eq.expand(complex=True) # does not give oo recursion eq = -I * exp(-3 * I * pi / 4) / (4 * pi**(R(3, 2)) * sqrt(x)) assert eq.expand(complex=True) # does not give oo recursion
def test_dup_from_sympy(): assert dup_from_sympy([S(1), S(2)], ZZ) == \ [ZZ(1), ZZ(2)] assert dup_from_sympy([S(1)/2, S(3)], QQ) == \ [QQ(1, 2), QQ(3, 1)]
def as_base_exp(self): # XXX exp_polar(0) is special! if self.args[0] == 0: return self, S(1) return ExpBase.as_base_exp(self)
def test_div(): n = ArithmeticOnlyMatrix(1, 2, [1, 2]) assert n / 2 == ArithmeticOnlyMatrix(1, 2, [S.Half, S(2) / 2])
def test_settings(): raises(TypeError, lambda: sstr(S(4), method="garbage"))
def __init__(self, factors=None): # Factors """Initialize Factors from dict or expr. Examples ======== >>> from sympy.core.exprtools import Factors >>> from sympy.abc import x >>> from sympy import I >>> e = 2*x**3 >>> Factors(e) Factors({2: 1, x: 3}) >>> Factors(e.as_powers_dict()) Factors({2: 1, x: 3}) >>> f = _ >>> f.factors # underlying dictionary {2: 1, x: 3} >>> f.gens # base of each factor frozenset([2, x]) >>> Factors(0) Factors({0: 1}) >>> Factors(I) Factors({I: 1}) Notes ===== Although a dictionary can be passed, no checking will be done to ensure that -1 is split from Rationals. This will then affect gcd and normal caclulations: >>> Factors(-2*x).factors {-1: 1, 2: 1, x: 1} >>> Factors((-2*x).as_powers_dict()).factors {-2: 1, x: 1} """ if factors is None or factors == 1: factors = {} elif factors is S.Zero or factors == 0: factors = {S.Zero: S.One} elif isinstance( factors, Number) and factors < 0 and not factors is S.NegativeOne: factors = {-factors: S.One, S.NegativeOne: S.One} elif isinstance(factors, Expr): c, nc = factors.args_cnc() factors = dict(Mul(*c, **dict(evaluate=False)).as_powers_dict()) if nc: factors[Mul(*nc, **dict(evaluate=False))] = S.One # sanitizing if factors.get(S.NegativeOne, S.One) is not S.One: e = factors.pop(S.NegativeOne) factors[S.ImaginaryUnit] = 1 if e == S(3) / 2: factors[S.NegativeOne] = S.One elif e is not S.Half: raise ValueError('unanticipated value for exponent of -1') self.factors = factors try: self.gens = frozenset(factors.keys()) except AttributeError: raise TypeError('expecting Expr or dictionary')
def is_convergent(self): r"""Checks for the convergence of a Sum. We divide the study of convergence of infinite sums and products in two parts. First Part: One part is the question whether all the terms are well defined, i.e., they are finite in a sum and also non-zero in a product. Zero is the analogy of (minus) infinity in products as :math:`e^{-\infty} = 0`. Second Part: The second part is the question of convergence after infinities, and zeros in products, have been omitted assuming that their number is finite. This means that we only consider the tail of the sum or product, starting from some point after which all terms are well defined. For example, in a sum of the form: .. math:: \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b} where a and b are numbers. The routine will return true, even if there are infinities in the term sequence (at most two). An analogous product would be: .. math:: \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}} This is how convergence is interpreted. It is concerned with what happens at the limit. Finding the bad terms is another independent matter. Note: It is responsibility of user to see that the sum or product is well defined. There are various tests employed to check the convergence like divergence test, root test, integral test, alternating series test, comparison tests, Dirichlet tests. It returns true if Sum is convergent and false if divergent and NotImplementedError if it can not be checked. References ========== .. [1] https://en.wikipedia.org/wiki/Convergence_tests Examples ======== >>> from sympy import factorial, S, Sum, Symbol, oo >>> n = Symbol('n', integer=True) >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent() True >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() False >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() False >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent() True See Also ======== Sum.is_absolutely_convergent() sympy.concrete.products.Product.is_convergent() """ from sympy import Interval, Integral, log, symbols, simplify p, q, r = symbols('p q r', cls=Wild) sym = self.limits[0][0] lower_limit = self.limits[0][1] upper_limit = self.limits[0][2] sequence_term = self.function if len(sequence_term.free_symbols) > 1: raise NotImplementedError( "convergence checking for more than one symbol " "containing series is not handled") if lower_limit.is_finite and upper_limit.is_finite: return S.true # transform sym -> -sym and swap the upper_limit = S.Infinity # and lower_limit = - upper_limit if lower_limit is S.NegativeInfinity: if upper_limit is S.Infinity: return Sum(sequence_term, (sym, 0, S.Infinity)).is_convergent() and \ Sum(sequence_term, (sym, S.NegativeInfinity, 0)).is_convergent() sequence_term = simplify(sequence_term.xreplace({sym: -sym})) lower_limit = -upper_limit upper_limit = S.Infinity sym_ = Dummy(sym.name, integer=True, positive=True) sequence_term = sequence_term.xreplace({sym: sym_}) sym = sym_ interval = Interval(lower_limit, upper_limit) # Piecewise function handle if sequence_term.is_Piecewise: for func, cond in sequence_term.args: # see if it represents something going to oo if cond == True or cond.as_set().sup is S.Infinity: s = Sum(func, (sym, lower_limit, upper_limit)) return s.is_convergent() return S.true ### -------- Divergence test ----------- ### try: lim_val = limit_seq(sequence_term, sym) if lim_val is not None and lim_val.is_zero is False: return S.false except NotImplementedError: pass try: lim_val_abs = limit_seq(abs(sequence_term), sym) if lim_val_abs is not None and lim_val_abs.is_zero is False: return S.false except NotImplementedError: pass order = O(sequence_term, (sym, S.Infinity)) ### --------- p-series test (1/n**p) ---------- ### p_series_test = order.expr.match(sym**p) if p_series_test is not None: if p_series_test[p] < -1: return S.true if p_series_test[p] >= -1: return S.false ### ------------- comparison test ------------- ### # 1/(n**p*log(n)**q*log(log(n))**r) comparison n_log_test = order.expr.match( 1 / (sym**p * log(sym)**q * log(log(sym))**r)) if n_log_test is not None: if (n_log_test[p] > 1 or (n_log_test[p] == 1 and n_log_test[q] > 1) or (n_log_test[p] == n_log_test[q] == 1 and n_log_test[r] > 1)): return S.true return S.false ### ------------- Limit comparison test -----------### # (1/n) comparison try: lim_comp = limit_seq(sym * sequence_term, sym) if lim_comp is not None and lim_comp.is_number and lim_comp > 0: return S.false except NotImplementedError: pass ### ----------- ratio test ---------------- ### next_sequence_term = sequence_term.xreplace({sym: sym + 1}) ratio = combsimp(powsimp(next_sequence_term / sequence_term)) try: lim_ratio = limit_seq(ratio, sym) if lim_ratio is not None and lim_ratio.is_number: if abs(lim_ratio) > 1: return S.false if abs(lim_ratio) < 1: return S.true except NotImplementedError: pass ### ----------- root test ---------------- ### # lim = Limit(abs(sequence_term)**(1/sym), sym, S.Infinity) try: lim_evaluated = limit_seq(abs(sequence_term)**(1 / sym), sym) if lim_evaluated is not None and lim_evaluated.is_number: if lim_evaluated < 1: return S.true if lim_evaluated > 1: return S.false except NotImplementedError: pass ### ------------- alternating series test ----------- ### dict_val = sequence_term.match((-1)**(sym + p) * q) if not dict_val[p].has(sym) and is_decreasing(dict_val[q], interval): return S.true ### ------------- integral test -------------- ### check_interval = None maxima = solveset(sequence_term.diff(sym), sym, interval) if not maxima: check_interval = interval elif isinstance(maxima, FiniteSet) and maxima.sup.is_number: check_interval = Interval(maxima.sup, interval.sup) if (check_interval is not None and (is_decreasing(sequence_term, check_interval) or is_decreasing(-sequence_term, check_interval))): integral_val = Integral(sequence_term, (sym, lower_limit, upper_limit)) try: integral_val_evaluated = integral_val.doit() if integral_val_evaluated.is_number: return S(integral_val_evaluated.is_finite) except NotImplementedError: pass ### ----- Dirichlet and bounded times convergent tests ----- ### # TODO # # Dirichlet_test # https://en.wikipedia.org/wiki/Dirichlet%27s_test # # Bounded times convergent test # It is based on comparison theorems for series. # In particular, if the general term of a series can # be written as a product of two terms a_n and b_n # and if a_n is bounded and if Sum(b_n) is absolutely # convergent, then the original series Sum(a_n * b_n) # is absolutely convergent and so convergent. # # The following code can grows like 2**n where n is the # number of args in order.expr # Possibly combined with the potentially slow checks # inside the loop, could make this test extremely slow # for larger summation expressions. if order.expr.is_Mul: args = order.expr.args argset = set(args) ### -------------- Dirichlet tests -------------- ### m = Dummy('m', integer=True) def _dirichlet_test(g_n): try: ing_val = limit_seq( Sum(g_n, (sym, interval.inf, m)).doit(), m) if ing_val is not None and ing_val.is_finite: return S.true except NotImplementedError: pass ### -------- bounded times convergent test ---------### def _bounded_convergent_test(g1_n, g2_n): try: lim_val = limit_seq(g1_n, sym) if lim_val is not None and ( lim_val.is_finite or (isinstance(lim_val, AccumulationBounds) and (lim_val.max - lim_val.min).is_finite)): if Sum(g2_n, (sym, lower_limit, upper_limit)).is_absolutely_convergent(): return S.true except NotImplementedError: pass for n in range(1, len(argset)): for a_tuple in itertools.combinations(args, n): b_set = argset - set(a_tuple) a_n = Mul(*a_tuple) b_n = Mul(*b_set) if is_decreasing(a_n, interval): dirich = _dirichlet_test(b_n) if dirich is not None: return dirich bc_test = _bounded_convergent_test(a_n, b_n) if bc_test is not None: return bc_test _sym = self.limits[0][0] sequence_term = sequence_term.xreplace({sym: _sym}) raise NotImplementedError( "The algorithm to find the Sum convergence of %s " "is not yet implemented" % (sequence_term))
def test_lattice_make_args(): assert join.make_args(join(2, 3, 4)) == {S(2), S(3), S(4)} assert join.make_args(0) == {0} assert list(join.make_args(0))[0] is S.Zero assert Add.make_args(0)[0] is S.Zero
def __init__(self, factors=None): # Factors """Initialize Factors from dict or expr. Examples ======== >>> from sympy.core.exprtools import Factors >>> from sympy.abc import x >>> from sympy import I >>> e = 2*x**3 >>> Factors(e) Factors({2: 1, x: 3}) >>> Factors(e.as_powers_dict()) Factors({2: 1, x: 3}) >>> f = _ >>> f.factors # underlying dictionary {2: 1, x: 3} >>> f.gens # base of each factor frozenset([2, x]) >>> Factors(0) Factors({0: 1}) >>> Factors(I) Factors({I: 1}) Notes ===== Although a dictionary can be passed, only minimal checking is performed: powers of -1 and I are made canonical. """ if isinstance(factors, (SYMPY_INTS, float)): factors = S(factors) if isinstance(factors, Factors): factors = factors.factors.copy() elif factors is None or factors is S.One: factors = {} elif factors is S.Zero or factors == 0: factors = {S.Zero: S.One} elif isinstance(factors, Number): n = factors factors = {} if n < 0: factors[S.NegativeOne] = S.One n = -n if n is not S.One: if n.is_Float or n.is_Integer or n is S.Infinity: factors[n] = S.One elif n.is_Rational: # since we're processing Numbers, the denominator is # stored with a negative exponent; all other factors # are left . if n.p != 1: factors[Integer(n.p)] = S.One factors[Integer(n.q)] = S.NegativeOne else: raise ValueError( 'Expected Float|Rational|Integer, not %s' % n) elif isinstance(factors, Basic) and not factors.args: factors = {factors: S.One} elif isinstance(factors, Expr): c, nc = factors.args_cnc() i = c.count(I) for _ in range(i): c.remove(I) factors = dict(Mul._from_args(c).as_powers_dict()) if i: factors[I] = S.One * i if nc: factors[Mul(*nc, evaluate=False)] = S.One else: factors = factors.copy() # /!\ should be dict-like # tidy up -/+1 and I exponents if Rational handle = [] for k in factors: if k is I or k in (-1, 1): handle.append(k) if handle: i1 = S.One for k in handle: if not _isnumber(factors[k]): continue i1 *= k**factors.pop(k) if i1 is not S.One: for a in i1.args if i1.is_Mul else [ i1 ]: # at worst, -1.0*I*(-1)**e if a is S.NegativeOne: factors[a] = S.One elif a is I: factors[I] = S.One elif a.is_Pow: if S.NegativeOne not in factors: factors[S.NegativeOne] = S.Zero factors[S.NegativeOne] += a.exp elif a == 1: factors[a] = S.One elif a == -1: factors[-a] = S.One factors[S.NegativeOne] = S.One else: raise ValueError('unexpected factor in i1: %s' % a) self.factors = factors try: self.gens = frozenset(factors.keys()) except AttributeError: raise TypeError('expecting Expr or dictionary')
def test_evalf_bugs(): assert NS(sin(1) + exp(-10**10), 10) == NS(sin(1), 10) assert NS(exp(10**10) + sin(1), 10) == NS(exp(10**10), 10) assert NS('expand_log(log(1+1/10**50))', 20) == '1.0000000000000000000e-50' assert NS('log(10**100,10)', 10) == '100.0000000' assert NS('log(2)', 10) == '0.6931471806' assert NS('(sin(x)-x)/x**3', 15, subs={x: '1/10**50'}) == '-0.166666666666667' assert NS(sin(1) + Rational(1, 10**100) * I, 15) == '0.841470984807897 + 1.00000000000000e-100*I' assert x.evalf() == x assert NS((1 + I)**2 * I, 6) == '-2.00000' d = { n: (-1)**Rational(6, 7), y: (-1)**Rational(4, 7), x: (-1)**Rational(2, 7) } assert NS((x * (1 + y * (1 + n))).subs(d).evalf(), 6) == '0.346011 + 0.433884*I' assert NS(((-I - sqrt(2) * I)**2).evalf()) == '-5.82842712474619' assert NS((1 + I)**2 * I, 15) == '-2.00000000000000' # issue 4758 (1/2): assert NS(pi.evalf(69) - pi) == '-4.43863937855894e-71' # issue 4758 (2/2): With the bug present, this still only fails if the # terms are in the order given here. This is not generally the case, # because the order depends on the hashes of the terms. assert NS(20 - 5008329267844 * n**25 - 477638700 * n**37 - 19 * n, subs={n: .01}) == '19.8100000000000' assert NS( ((x - 1) * (1 - x)** 1000).n()) == '(1.00000000000000 - x)**1000*(x - 1.00000000000000)' assert NS((-x).n()) == '-x' assert NS((-2 * x).n()) == '-2.00000000000000*x' assert NS((-2 * x * y).n()) == '-2.00000000000000*x*y' assert cos(x).n(subs={x: 1 + I}) == cos(x).subs(x, 1 + I).n() # issue 6660. Also NaN != mpmath.nan # In this order: # 0*nan, 0/nan, 0*inf, 0/inf # 0+nan, 0-nan, 0+inf, 0-inf # >>> n = Some Number # n*nan, n/nan, n*inf, n/inf # n+nan, n-nan, n+inf, n-inf assert (0 * E**(oo)).n() is S.NaN assert (0 / E**(oo)).n() is S.Zero assert (0 + E**(oo)).n() is S.Infinity assert (0 - E**(oo)).n() is S.NegativeInfinity assert (5 * E**(oo)).n() is S.Infinity assert (5 / E**(oo)).n() is S.Zero assert (5 + E**(oo)).n() is S.Infinity assert (5 - E**(oo)).n() is S.NegativeInfinity #issue 7416 assert as_mpmath(0.0, 10, {'chop': True}) == 0 #issue 5412 assert ((oo * I).n() == S.Infinity * I) assert ((oo + oo * I).n() == S.Infinity + S.Infinity * I) #issue 11518 assert NS(2 * x**2.5, 5) == '2.0000*x**2.5000' #issue 13076 assert NS(Mul(Max(0, y), x, evaluate=False).evalf()) == 'x*Max(0, y)' #issue 18516 assert NS( log( S(3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376 ) / 36360291795869936842385267079543319118023385026001623040346035832580600191583895484198508262979388783308179702534403855752855931517013066142992430916562025780021771247847643450125342836565813209972590371590152578728008385990139795377610001 ).evalf(15, chop=True)) == '-oo'
def test_Max(): from sympy.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) r = Symbol('r', real=True) assert Max(5, 4) == 5 # lists assert Max() == S.NegativeInfinity assert Max(x) == x 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, S(1) / 2) == cos(S(1) / 2) raises(ValueError, lambda: Max(cos(x), sin(x)).subs(x, I)) raises(ValueError, lambda: Max(I)) raises(ValueError, lambda: Max(I, x)) raises(ValueError, lambda: Max(S.ComplexInfinity, 1)) assert Max(n, -oo, n_, p, 2) == Max(p, 2) assert Max(n, -oo, n_, p, 1000) == Max(p, 1000) 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) e = Max(0, x) assert e.evalf == e.n assert e.n().args == (0, x) # issue 8643 m = Max(p, p_, n, r) assert m.is_positive is True assert m.is_nonnegative is True assert m.is_negative is False m = Max(n, n_) assert m.is_positive is False assert m.is_nonnegative is False assert m.is_negative is True m = Max(n, n_, r) assert m.is_positive is None assert m.is_nonnegative is None assert m.is_negative is None m = Max(n, nn, r) assert m.is_positive is None assert m.is_nonnegative is True assert m.is_negative is False
def test_to_mpmath(): assert sqrt(3)._to_mpmath(20)._mpf_ == (0, int(908093), -19, 20) assert S(3.2)._to_mpmath(20)._mpf_ == (0, int(838861), -18, 20)
def test_match_riccati(): """ This function tests if an ODE is Riccati or not. Each test case has 5 values - 1. eq - The Riccati ODE. 2. match - Boolean indicating if eq is a Riccati ODE. 3. b0 - 4. b1 - Coefficient of f(x) in eq. 5. b2 - Coefficient of f(x)**2 in eq. """ tests = [ # Test Rational Riccati ODEs ( f(x).diff(x) - (405*x**3 - 882*x**2 - 78*x + 92)/(243*x**4 \ - 945*x**3 + 846*x**2 + 180*x - 72) - 2 - f(x)**2/(3*x + 1) \ - (S(1)/3 - x)*f(x)/(S(1)/3 - 3*x/2), True, 45*x**3/(27*x**4 - 105*x**3 + 94*x**2 + 20*x - 8) - 98*x**2/ \ (27*x**4 - 105*x**3 + 94*x**2 + 20*x - 8) - 26*x/(81*x**4 - \ 315*x**3 + 282*x**2 + 60*x - 24) + 2 + 92/(243*x**4 - 945*x**3 \ + 846*x**2 + 180*x - 72), Mul(-1, 2 - 6*x, evaluate=False)/(9*x - 2), 1/(3*x + 1) ), ( f(x).diff(x) + 4*x/27 - (x/3 - 1)*f(x)**2 - (2*x/3 + \ 1)*f(x)/(3*x + 2) - S(10)/27 - (265*x**2 + 423*x + 162) \ /(324*x**3 + 216*x**2), True, -4*x/27 + S(10)/27 + 3/(6*x**3 + 4*x**2) + 47/(36*x**2 \ + 24*x) + 265/(324*x + 216), Mul(-1, -2*x - 3, evaluate=False)/(9*x + 6), x/3 - 1 ), ( f(x).diff(x) - (304*x**5 - 745*x**4 + 631*x**3 - 876*x**2 \ + 198*x - 108)/(36*x**6 - 216*x**5 + 477*x**4 - 567*x**3 + \ 360*x**2 - 108*x) - S(17)/9 - (x - S(3)/2)*f(x)/(x/2 - \ S(3)/2) - (x/3 - 3)*f(x)**2/(3*x), True, 304*x**4/(36*x**5 - 216*x**4 + 477*x**3 - 567*x**2 + 360*x - \ 108) - 745*x**3/(36*x**5 - 216*x**4 + 477*x**3 - 567*x**2 + \ 360*x - 108) + 631*x**2/(36*x**5 - 216*x**4 + 477*x**3 - 567* \ x**2 + 360*x - 108) - 292*x/(12*x**5 - 72*x**4 + 159*x**3 - \ 189*x**2 + 120*x - 36) + S(17)/9 - 12/(4*x**6 - 24*x**5 + \ 53*x**4 - 63*x**3 + 40*x**2 - 12*x) + 22/(4*x**5 - 24*x**4 \ + 53*x**3 - 63*x**2 + 40*x - 12), Mul(-1, 3 - 2*x, evaluate=False)/(x - 3), Mul(-1, 9 - x, evaluate=False)/(9*x) ), # Test Non-Rational Riccati ODEs ( f(x).diff(x) - x**(S(3)/2)/(x**(S(1)/2) - 2) + x**2*f(x) + \ x*f(x)**2/(x**(S(3)/4)), False, 0, 0, 0 ), ( f(x).diff(x) - sin(x**2) + exp(x)*f(x) + log(x)*f(x)**2, False, 0, 0, 0 ), ( f(x).diff(x) - tanh(x + sqrt(x)) + f(x) + x**4*f(x)**2, False, 0, 0, 0 ), # Test Non-Riccati ODEs ( (1 - x**2)*f(x).diff(x, 2) - 2*x*f(x).diff(x) + 20*f(x), False, 0, 0, 0 ), ( f(x).diff(x) - x**2 + x**3*f(x) + (x**2/(x + 1))*f(x)**3, False, 0, 0, 0 ), ( f(x).diff(x)*f(x)**2 + (x**2 - 1)/(x**3 + 1)*f(x) + 1/(2*x \ + 3) + f(x)**2, False, 0, 0, 0 )] for eq, res, b0, b1, b2 in tests: match, funcs = match_riccati(eq, f, x) assert match == res if res: assert [b0, b1, b2] == funcs
def test_issue_13098(): assert floor(log(S('9.' + '9' * 20), 10)) == 0 assert ceiling(log(S('9.' + '9' * 20), 10)) == 1 assert floor(log(20 - S('9.' + '9' * 20), 10)) == 1 assert ceiling(log(20 - S('9.' + '9' * 20), 10)) == 2
def test_construct_d_case_4(): """ This function tests the Case 4 in the step to calculate coefficients of the d-vector. Each test case has 4 values - 1. num - Numerator of the rational function a(x). 2. den - Denominator of the rational function a(x). 3. mul - Multiplicity of oo as a pole. 4. d - The d-vector. """ tests = [ # Tests with multiplicity at oo = 2 ( Poly(-x**5 - 2*x**4 + 4*x**3 + 2*x + 5, x, extension=True), Poly(9*x**3 - 2*x**2 + 10*x - 2, x, extension=True), 2, [[10*I/27, I/3, -3*I*(S(158)/243 - I/3)/2], \ [-10*I/27, -I/3, 3*I*(S(158)/243 + I/3)/2]] ), ( Poly(-x**6 + 9*x**5 + 5*x**4 + 6*x**3 + 5*x**2 + 6*x + 7, x, extension=True), Poly(x**4 + 3*x**3 + 12*x**2 - x + 7, x, extension=True), 2, [[-6*I, I, -I*(17 - I)/2], [6*I, -I, I*(17 + I)/2]] ), # Tests with multiplicity at oo = 4 ( Poly(-2*x**6 - x**5 - x**4 - 2*x**3 - x**2 - 3*x - 3, x, extension=True), Poly(3*x**2 + 10*x + 7, x, extension=True), 4, [[269*sqrt(6)*I/288, -17*sqrt(6)*I/36, sqrt(6)*I/3, -sqrt(6)*I*(S(16969)/2592 \ - 2*sqrt(6)*I/3)/4], [-269*sqrt(6)*I/288, 17*sqrt(6)*I/36, -sqrt(6)*I/3, \ sqrt(6)*I*(S(16969)/2592 + 2*sqrt(6)*I/3)/4]] ), ( Poly(-3*x**5 - 3*x**4 - 3*x**3 - x**2 - 1, x, extension=True), Poly(12*x - 2, x, extension=True), 4, [[41*I/192, 7*I/24, I/2, -I*(-S(59)/6912 - I)], \ [-41*I/192, -7*I/24, -I/2, I*(-S(59)/6912 + I)]] ), # Tests with multiplicity at oo = 4 ( Poly(-x**7 - x**5 - x**4 - x**2 - x, x, extension=True), Poly(x + 2, x, extension=True), 6, [[-5*I/2, 2*I, -I, I, -I*(-9 - 3*I)/2], [5*I/2, -2*I, I, -I, I*(-9 + 3*I)/2]] ), ( Poly(-x**7 - x**6 - 2*x**5 - 2*x**4 - x**3 - x**2 + 2*x - 2, x, extension=True), Poly(2*x - 2, x, extension=True), 6, [[3*sqrt(2)*I/4, 3*sqrt(2)*I/4, sqrt(2)*I/2, sqrt(2)*I/2, -sqrt(2)*I*(-S(7)/8 - \ 3*sqrt(2)*I/2)/2], [-3*sqrt(2)*I/4, -3*sqrt(2)*I/4, -sqrt(2)*I/2, -sqrt(2)*I/2, \ sqrt(2)*I*(-S(7)/8 + 3*sqrt(2)*I/2)/2]] )] for num, den, mul, d in tests: ser = rational_laurent_series(num, den, x, oo, mul, 1) assert construct_d_case_4(ser, mul // 2) == d
def is_convergent(self): r"""Checks for the convergence of a Sum. We divide the study of convergence of infinite sums and products in two parts. First Part: One part is the question whether all the terms are well defined, i.e., they are finite in a sum and also non-zero in a product. Zero is the analogy of (minus) infinity in products as :math:`e^{-\infty} = 0`. Second Part: The second part is the question of convergence after infinities, and zeros in products, have been omitted assuming that their number is finite. This means that we only consider the tail of the sum or product, starting from some point after which all terms are well defined. For example, in a sum of the form: .. math:: \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b} where a and b are numbers. The routine will return true, even if there are infinities in the term sequence (at most two). An analogous product would be: .. math:: \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}} This is how convergence is interpreted. It is concerned with what happens at the limit. Finding the bad terms is another independent matter. Note: It is responsibility of user to see that the sum or product is well defined. There are various tests employed to check the convergence like divergence test, root test, integral test, alternating series test, comparison tests, Dirichlet tests. It returns true if Sum is convergent and false if divergent and NotImplementedError if it can not be checked. References ========== .. [1] https://en.wikipedia.org/wiki/Convergence_tests Examples ======== >>> from sympy import factorial, S, Sum, Symbol, oo >>> n = Symbol('n', integer=True) >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent() True >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() False >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() False >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent() True See Also ======== Sum.is_absolutely_convergent() Product.is_convergent() """ from sympy import Interval, Integral, Limit, log, symbols, Ge, Gt, simplify p, q = symbols('p q', cls=Wild) sym = self.limits[0][0] lower_limit = self.limits[0][1] upper_limit = self.limits[0][2] sequence_term = self.function if len(sequence_term.free_symbols) > 1: raise NotImplementedError( "convergence checking for more that one symbol " "containing series is not handled") if lower_limit.is_finite and upper_limit.is_finite: return S.true # transform sym -> -sym and swap the upper_limit = S.Infinity # and lower_limit = - upper_limit if lower_limit is S.NegativeInfinity: if upper_limit is S.Infinity: return Sum(sequence_term, (sym, 0, S.Infinity)).is_convergent() and \ Sum(sequence_term, (sym, S.NegativeInfinity, 0)).is_convergent() sequence_term = simplify(sequence_term.xreplace({sym: -sym})) lower_limit = -upper_limit upper_limit = S.Infinity interval = Interval(lower_limit, upper_limit) # Piecewise function handle if sequence_term.is_Piecewise: for func_cond in sequence_term.args: if func_cond[1].func is Ge or func_cond[ 1].func is Gt or func_cond[1] == True: return Sum( func_cond[0], (sym, lower_limit, upper_limit)).is_convergent() return S.true ### -------- Divergence test ----------- ### try: lim_val = limit(sequence_term, sym, upper_limit) if lim_val.is_number and lim_val is not S.Zero: return S.false except NotImplementedError: pass try: lim_val_abs = limit(abs(sequence_term), sym, upper_limit) if lim_val_abs.is_number and lim_val_abs is not S.Zero: return S.false except NotImplementedError: pass order = O(sequence_term, (sym, S.Infinity)) ### --------- p-series test (1/n**p) ---------- ### p1_series_test = order.expr.match(sym**p) if p1_series_test is not None: if p1_series_test[p] < -1: return S.true if p1_series_test[p] > -1: return S.false p2_series_test = order.expr.match((1 / sym)**p) if p2_series_test is not None: if p2_series_test[p] > 1: return S.true if p2_series_test[p] < 1: return S.false ### ----------- root test ---------------- ### lim = Limit(abs(sequence_term)**(1 / sym), sym, S.Infinity) lim_evaluated = lim.doit() if lim_evaluated.is_number: if lim_evaluated < 1: return S.true if lim_evaluated > 1: return S.false ### ------------- alternating series test ----------- ### dict_val = sequence_term.match((-1)**(sym + p) * q) if not dict_val[p].has(sym) and is_decreasing(dict_val[q], interval): return S.true ### ------------- comparison test ------------- ### # (1/log(n)**p) comparison log_test = order.expr.match(1 / (log(sym)**p)) if log_test is not None: return S.false # (1/(n*log(n)**p)) comparison log_n_test = order.expr.match(1 / (sym * (log(sym))**p)) if log_n_test is not None: if log_n_test[p] > 1: return S.true return S.false # (1/(n*log(n)*log(log(n))*p)) comparison log_log_n_test = order.expr.match(1 / (sym * (log(sym) * log(log(sym))**p))) if log_log_n_test is not None: if log_log_n_test[p] > 1: return S.true return S.false # (1/(n**p*log(n))) comparison n_log_test = order.expr.match(1 / (sym**p * log(sym))) if n_log_test is not None: if n_log_test[p] > 1: return S.true return S.false ### ------------- integral test -------------- ### if is_decreasing(sequence_term, interval): integral_val = Integral(sequence_term, (sym, lower_limit, upper_limit)) try: integral_val_evaluated = integral_val.doit() if integral_val_evaluated.is_number: return S(integral_val_evaluated.is_finite) except NotImplementedError: pass ### -------------- Dirichlet tests -------------- ### if order.expr.is_Mul: a_n, b_n = order.expr.args[0], order.expr.args[1] m = Dummy('m', integer=True) def _dirichlet_test(g_n): try: ing_val = limit( Sum(g_n, (sym, interval.inf, m)).doit(), m, S.Infinity) if ing_val.is_finite: return S.true except NotImplementedError: pass if is_decreasing(a_n, interval): dirich1 = _dirichlet_test(b_n) if dirich1 is not None: return dirich1 if is_decreasing(b_n, interval): dirich2 = _dirichlet_test(a_n) if dirich2 is not None: return dirich2 raise NotImplementedError( "The algorithm to find the Sum convergence of %s " "is not yet implemented" % (sequence_term))
def test_riccati_transformation(): """ This function tests the transformation of the solution of a Riccati ODE to the solution of its corresponding normal Riccati ODE. Each test case 4 values - 1. w - The solution to be transformed 2. b1 - The coefficient of f(x) in the ODE. 3. b2 - The coefficient of f(x)**2 in the ODE. 4. y - The solution to the normal Riccati ODE. """ tests = [ ( x/(x - 1), (x**2 + 7)/3*x, x, -x**2/(x - 1) - x*(x**2/3 + S(7)/3)/2 - 1/(2*x) ), ( (2*x + 3)/(2*x + 2), (3 - 3*x)/(x + 1), 5*x, -5*x*(2*x + 3)/(2*x + 2) - (3 - 3*x)/(Mul(2, x + 1, evaluate=False)) - 1/(2*x) ), ( -1/(2*x**2 - 1), 0, (2 - x)/(4*x - 2), (2 - x)/((4*x - 2)*(2*x**2 - 1)) - (4*x - 2)*(Mul(-4, 2 - x, evaluate=False)/(4*x - \ 2)**2 - 1/(4*x - 2))/(Mul(2, 2 - x, evaluate=False)) ), ( x, (8*x - 12)/(12*x + 9), x**3/(6*x - 9), -x**4/(6*x - 9) - (8*x - 12)/(Mul(2, 12*x + 9, evaluate=False)) - (6*x - 9)*(-6*x**3/(6*x \ - 9)**2 + 3*x**2/(6*x - 9))/(2*x**3) )] for w, b1, b2, y in tests: assert y == riccati_normal(w, x, b1, b2) assert w == riccati_inverse_normal(y, x, b1, b2).cancel() # Test bp parameter in riccati_inverse_normal tests = [ ( (-2*x - 1)/(2*x**2 + 2*x - 2), -2/x, (-x - 1)/(4*x), 8*x**2*(1/(4*x) + (-x - 1)/(4*x**2))/(-x - 1)**2 + 4/(-x - 1), -2*x*(-1/(4*x) - (-x - 1)/(4*x**2))/(-x - 1) - (-2*x - 1)*(-x - 1)/(4*x*(2*x**2 + 2*x \ - 2)) + 1/x ), ( 3/(2*x**2), -2/x, (-x - 1)/(4*x), 8*x**2*(1/(4*x) + (-x - 1)/(4*x**2))/(-x - 1)**2 + 4/(-x - 1), -2*x*(-1/(4*x) - (-x - 1)/(4*x**2))/(-x - 1) + 1/x - Mul(3, -x - 1, evaluate=False)/(8*x**3) )] for w, b1, b2, bp, y in tests: assert y == riccati_normal(w, x, b1, b2) assert w == riccati_inverse_normal(y, x, b1, b2, bp).cancel()
def _eval_is_extended_real(self): if self.args[0].is_extended_real: return True elif self.args[0].is_imaginary: arg2 = -S(2) * S.ImaginaryUnit * self.args[0] / S.Pi return arg2.is_even
def _eval_is_finite(self): if (self.args[0] + S.One).is_zero: return False return self.args[0].is_finite def _eval_is_positive(self): return self.args[0].is_positive def _eval_is_zero(self): return self.args[0].is_zero def _eval_is_nonnegative(self): return self.args[0].is_nonnegative _Two = S(2) def _exp2(x): return Pow(_Two, x) class exp2(Function): """ Represents the exponential function with base two. The benefit of using ``exp2(x)`` over ``2**x`` is that the latter is not as efficient under finite precision arithmetic. Examples
def test_expr_fns(): expr = x + y**3 e = bottom_up(lambda v: v + 1, expr_fns)(expr) b = bottom_up(lambda v: Basic.__new__(Add, v, S(1)), basic_fns)(expr) assert rebuild(b) == e