def test_issue_5223(): assert series(1, x) == 1 assert next(S.Zero.lseries(x)) == 0 assert cos(x).series() == cos(x).series(x) raises(ValueError, lambda: cos(x + y).series()) raises(ValueError, lambda: x.series(dir="")) assert (cos(x).series(x, 1) - cos(x + 1).series(x).subs(x, x - 1)).removeO() == 0 e = cos(x).series(x, 1, n=None) assert [next(e) for i in range(2)] == [cos(1), -((x - 1) * sin(1))] e = cos(x).series(x, 1, n=None, dir='-') assert [next(e) for i in range(2)] == [cos(1), (1 - x) * sin(1)] # the following test is exact so no need for x -> x - 1 replacement assert abs(x).series(x, 1, dir='-') == x assert exp(x).series(x, 1, dir='-', n=3).removeO() == \ E - E*(-x + 1) + E*(-x + 1)**2/2 D = Derivative assert D(x**2 + x**3 * y**2, x, 2, y, 1).series(x).doit() == 12 * x * y assert next(D(cos(x), x).lseries()) == D(1, x) assert D(exp(x), x).series( n=3) == D(1, x) + D(x, x) + D(x**2 / 2, x) + D(x**3 / 6, x) + O(x**3) assert Integral(x, (x, 1, 3), (y, 1, x)).series(x) == -4 + 4 * x assert (1 + x + O(x**2)).getn() == 2 assert (1 + x).getn() is None raises(PoleError, lambda: ((1 / sin(x))**oo).series()) logx = Symbol('logx') assert ((sin(x))**y).nseries(x, n=1, logx=logx) == \ exp(y*logx) + O(x*exp(y*logx), x) assert sin(1 / x).series( x, oo, n=5) == 1 / x - 1 / (6 * x**3) + O(x**(-5), (x, oo)) assert abs(x).series(x, oo, n=5, dir='+') == x assert abs(x).series(x, -oo, n=5, dir='-') == -x assert abs(-x).series(x, oo, n=5, dir='+') == x assert abs(-x).series(x, -oo, n=5, dir='-') == -x assert exp(x*log(x)).series(n=3) == \ 1 + x*log(x) + x**2*log(x)**2/2 + O(x**3*log(x)**3) # XXX is this right? If not, fix "ngot > n" handling in expr. p = Symbol('p', positive=True) assert exp(sqrt(p)**3*log(p)).series(n=3) == \ 1 + p**S('3/2')*log(p) + O(p**3*log(p)**3) assert exp(sin(x) * log(x)).series(n=2) == 1 + x * log(x) + O(x**2 * log(x)**2)
def test_2nd_power_series_ordinary(): C1, C2 = symbols("C1 C2") eq = f(x).diff(x, 2) - x*f(x) assert classify_ode(eq) == ('2nd_linear_airy', '2nd_power_series_ordinary') sol = Eq(f(x), C2*(x**3/6 + 1) + C1*x*(x**3/12 + 1) + O(x**6)) assert dsolve(eq, hint='2nd_power_series_ordinary') == sol assert checkodesol(eq, sol) == (True, 0) sol = Eq(f(x), C2*((x + 2)**4/6 + (x + 2)**3/6 - (x + 2)**2 + 1) + C1*(x + (x + 2)**4/12 - (x + 2)**3/3 + S(2)) + O(x**6)) assert dsolve(eq, hint='2nd_power_series_ordinary', x0=-2) == sol # FIXME: Solution should be O((x+2)**6) # assert checkodesol(eq, sol) == (True, 0) sol = Eq(f(x), C2*x + C1 + O(x**2)) assert dsolve(eq, hint='2nd_power_series_ordinary', n=2) == sol assert checkodesol(eq, sol) == (True, 0) eq = (1 + x**2)*(f(x).diff(x, 2)) + 2*x*(f(x).diff(x)) -2*f(x) assert classify_ode(eq) == ('factorable', '2nd_hypergeometric', '2nd_hypergeometric_Integral', '2nd_power_series_ordinary') sol = Eq(f(x), C2*(-x**4/3 + x**2 + 1) + C1*x + O(x**6)) assert dsolve(eq, hint='2nd_power_series_ordinary') == sol assert checkodesol(eq, sol) == (True, 0) eq = f(x).diff(x, 2) + x*(f(x).diff(x)) + f(x) assert classify_ode(eq) == ('factorable', '2nd_power_series_ordinary',) sol = Eq(f(x), C2*(x**4/8 - x**2/2 + 1) + C1*x*(-x**2/3 + 1) + O(x**6)) assert dsolve(eq) == sol # FIXME: checkodesol fails for this solution... # assert checkodesol(eq, sol) == (True, 0) eq = f(x).diff(x, 2) + f(x).diff(x) - x*f(x) assert classify_ode(eq) == ('2nd_power_series_ordinary',) sol = Eq(f(x), C2*(-x**4/24 + x**3/6 + 1) + C1*x*(x**3/24 + x**2/6 - x/2 + 1) + O(x**6)) assert dsolve(eq) == sol # FIXME: checkodesol fails for this solution... # assert checkodesol(eq, sol) == (True, 0) eq = f(x).diff(x, 2) + x*f(x) assert classify_ode(eq) == ('2nd_linear_airy', '2nd_power_series_ordinary') sol = Eq(f(x), C2*(x**6/180 - x**3/6 + 1) + C1*x*(-x**3/12 + 1) + O(x**7)) assert dsolve(eq, hint='2nd_power_series_ordinary', n=7) == sol assert checkodesol(eq, sol) == (True, 0)
def test_series2x(): assert ((x + 1)**(-2)).nseries( x, 0, 4) == 1 - 2 * x + 3 * x**2 - 4 * x**3 + O(x**4, x) assert ((x + 1)**(-1)).nseries(x, 0, 4) == 1 - x + x**2 - x**3 + O(x**4, x) assert ((x + 1)**0).nseries(x, 0, 3) == 1 assert ((x + 1)**1).nseries(x, 0, 3) == 1 + x assert ((x + 1)**2).nseries(x, 0, 3) == x**2 + 2 * x + 1 assert ((x + 1)**3).nseries(x, 0, 3) == 1 + 3 * x + 3 * x**2 + O(x**3) assert (1 / (1 + x)).nseries(x, 0, 4) == 1 - x + x**2 - x**3 + O(x**4, x) assert (x + 3 / (1 + 2 * x)).nseries( x, 0, 4) == 3 - 5 * x + 12 * x**2 - 24 * x**3 + O(x**4, x) assert ((1 / x + 1)**3).nseries(x, 0, 3) == 1 + 3 / x + 3 / x**2 + x**(-3) assert (1 / (1 + 1 / x)).nseries(x, 0, 4) == x - x**2 + x**3 - O(x**4, x) assert (1 / (1 + 1 / x**2)).nseries(x, 0, 6) == x**2 - x**4 + O(x**6, x)
def test_series1(): e = sin(x) assert e.nseries(x, 0, 0) != 0 assert e.nseries(x, 0, 0) == O(1, x) assert e.nseries(x, 0, 1) == O(x, x) assert e.nseries(x, 0, 2) == x + O(x**2, x) assert e.nseries(x, 0, 3) == x + O(x**3, x) assert e.nseries(x, 0, 4) == x - x**3 / 6 + O(x**4, x) e = (exp(x) - 1) / x assert e.nseries(x, 0, 3) == 1 + x / 2 + x**2 / 6 + O(x**3) assert x.nseries(x, 0, 2) == x
def test_log_nseries(): assert log(x - 1)._eval_nseries( x, 4, None, I) == I * pi - x - x**2 / 2 - x**3 / 3 + O(x**4) assert log(x - 1)._eval_nseries( x, 4, None, -I) == -I * pi - x - x**2 / 2 - x**3 / 3 + O(x**4) assert log(I * x + I * x**3 - 1)._eval_nseries( x, 3, None, 1) == I * pi - I * x + x**2 / 2 + O(x**3) assert log(I * x + I * x**3 - 1)._eval_nseries( x, 3, None, -1) == -I * pi - I * x + x**2 / 2 + O(x**3) assert log(I * x**2 + I * x**3 - 1)._eval_nseries( x, 3, None, 1) == I * pi - I * x**2 + O(x**3) assert log(I * x**2 + I * x**3 - 1)._eval_nseries( x, 3, None, -1) == I * pi - I * x**2 + O(x**3)
def test_collect_order(): a, b, x, t = symbols('a,b,x,t') assert collect(t + t * x + t * x**2 + O(x**3), t) == t * (1 + x + x**2 + O(x**3)) assert collect(t + t*x + x**2 + O(x**3), t) == \ t*(1 + x + O(x**3)) + x**2 + O(x**3) f = a * x + b * x + c * x**2 + d * x**2 + O(x**3) g = x * (a + b) + x**2 * (c + d) + O(x**3) assert collect(f, x) == g assert collect(f, x, distribute_order_term=False) == g f = sin(a + b).series(b, 0, 10) assert collect(f, [sin(a), cos(a)]) == \ sin(a)*cos(b).series(b, 0, 10) + cos(a)*sin(b).series(b, 0, 10) assert collect(f, [sin(a), cos(a)], distribute_order_term=False) == \ sin(a)*cos(b).series(b, 0, 10).removeO() + \ cos(a)*sin(b).series(b, 0, 10).removeO() + O(b**10)
def test_si(): assert Si(I*x) == I*Shi(x) assert Shi(I*x) == I*Si(x) assert Si(-I*x) == -I*Shi(x) assert Shi(-I*x) == -I*Si(x) assert Si(-x) == -Si(x) assert Shi(-x) == -Shi(x) assert Si(exp_polar(2*pi*I)*x) == Si(x) assert Si(exp_polar(-2*pi*I)*x) == Si(x) assert Shi(exp_polar(2*pi*I)*x) == Shi(x) assert Shi(exp_polar(-2*pi*I)*x) == Shi(x) assert Si(oo) == pi/2 assert Si(-oo) == -pi/2 assert Shi(oo) is oo assert Shi(-oo) is -oo assert mytd(Si(x), sin(x)/x, x) assert mytd(Shi(x), sinh(x)/x, x) assert mytn(Si(x), Si(x).rewrite(Ei), -I*(-Ei(x*exp_polar(-I*pi/2))/2 + Ei(x*exp_polar(I*pi/2))/2 - I*pi) + pi/2, x) assert mytn(Si(x), Si(x).rewrite(expint), -I*(-expint(1, x*exp_polar(-I*pi/2))/2 + expint(1, x*exp_polar(I*pi/2))/2) + pi/2, x) assert mytn(Shi(x), Shi(x).rewrite(Ei), Ei(x)/2 - Ei(x*exp_polar(I*pi))/2 + I*pi/2, x) assert mytn(Shi(x), Shi(x).rewrite(expint), expint(1, x)/2 - expint(1, x*exp_polar(I*pi))/2 - I*pi/2, x) assert tn_arg(Si) assert tn_arg(Shi) assert Si(x).nseries(x, n=8) == \ x - x**3/18 + x**5/600 - x**7/35280 + O(x**9) assert Shi(x).nseries(x, n=8) == \ x + x**3/18 + x**5/600 + x**7/35280 + O(x**9) assert Si(sin(x)).nseries(x, n=5) == x - 2*x**3/9 + 17*x**5/450 + O(x**6) assert Si(x).nseries(x, 1, n=3) == \ Si(1) + (x - 1)*sin(1) + (x - 1)**2*(-sin(1)/2 + cos(1)/2) + O((x - 1)**3, (x, 1)) assert Si(x).series(x, oo) == pi/2 - (- 6/x**3 + 1/x \ + O(x**(-7), (x, oo)))*sin(x)/x - (24/x**4 - 2/x**2 + 1 \ + O(x**(-7), (x, oo)))*cos(x)/x t = Symbol('t', Dummy=True) assert Si(x).rewrite(sinc) == Integral(sinc(t), (t, 0, x)) assert limit(Shi(x), x, S.NegativeInfinity) == -I*pi/2
def test_fps__compose(): f1, f2, f3 = fps(exp(x)), fps(sin(x)), fps(cos(x)) raises(ValueError, lambda: f1.compose(sin(x), x)) raises(ValueError, lambda: f1.compose(fps(sin(x), dir=-1), x, 4)) raises(ValueError, lambda: f1.compose(fps(sin(x), x0=1), x, 4)) raises(ValueError, lambda: f1.compose(fps(sin(y)), x, 4)) raises(ValueError, lambda: f1.compose(f3, x)) raises(ValueError, lambda: f2.compose(f3, x)) fcomp = f1.compose(f2, x) assert isinstance(fcomp, FormalPowerSeriesCompose) assert isinstance(fcomp.ffps, FormalPowerSeries) assert isinstance(fcomp.gfps, FormalPowerSeries) assert fcomp.f == exp(x) assert fcomp.g == sin(x) assert fcomp.function == exp(sin(x)) assert fcomp._eval_terms(6) == 1 + x + x**2/2 - x**4/8 - x**5/15 assert fcomp.truncate() == 1 + x + x**2/2 - x**4/8 - x**5/15 + O(x**6) assert fcomp.truncate(5) == 1 + x + x**2/2 - x**4/8 + O(x**5) raises(NotImplementedError, lambda: fcomp._eval_term(5)) raises(NotImplementedError, lambda: fcomp.infinite) raises(NotImplementedError, lambda: fcomp._eval_derivative(x)) raises(NotImplementedError, lambda: fcomp.integrate(x)) assert f1.compose(f2, x).truncate(4) == 1 + x + x**2/2 + O(x**4) assert f1.compose(f2, x).truncate(8) == \ 1 + x + x**2/2 - x**4/8 - x**5/15 - x**6/240 + x**7/90 + O(x**8) assert f1.compose(f2, x).truncate(6) == \ 1 + x + x**2/2 - x**4/8 - x**5/15 + O(x**6) assert f2.compose(f2, x).truncate(4) == x - x**3/3 + O(x**4) assert f2.compose(f2, x).truncate(8) == x - x**3/3 + x**5/10 - 8*x**7/315 + O(x**8) assert f2.compose(f2, x).truncate(6) == x - x**3/3 + x**5/10 + O(x**6)
def test_fps__asymptotic(): f = exp(x) assert fps(f, x, oo) == f assert fps(f, x, -oo).truncate() == O(1/x**6, (x, oo)) f = erf(x) assert fps(f, x, oo).truncate() == 1 + O(1/x**6, (x, oo)) assert fps(f, x, -oo).truncate() == -1 + O(1/x**6, (x, oo)) f = atan(x) assert fps(f, x, oo, full=True).truncate() == \ -1/(5*x**5) + 1/(3*x**3) - 1/x + pi/2 + O(1/x**6, (x, oo)) assert fps(f, x, -oo, full=True).truncate() == \ -1/(5*x**5) + 1/(3*x**3) - 1/x - pi/2 + O(1/x**6, (x, oo)) f = log(1 + x) assert fps(f, x, oo) != \ (-1/(5*x**5) - 1/(4*x**4) + 1/(3*x**3) - 1/(2*x**2) + 1/x - log(1/x) + O(1/x**6, (x, oo))) assert fps(f, x, -oo) != \ (-1/(5*x**5) - 1/(4*x**4) + 1/(3*x**3) - 1/(2*x**2) + 1/x + I*pi - log(-1/x) + O(1/x**6, (x, oo)))
def test_fps_symbolic(): f = x**n*sin(x**2) assert fps(f, x).truncate(8) == x**(n + 2) - x**(n + 6)/6 + O(x**(n + 8), x) f = x**n*log(1 + x) fp = fps(f, x) k = fp.ak.variables[0] assert fp.infinite == \ Sum((-(-1)**(-k)*x**(k + n))/k, (k, 1, oo)) f = (x - 2)**n*log(1 + x) assert fps(f, x, 2).truncate() == \ ((x - 2)**n*log(3) + (x - 2)**(n + 1)/3 - (x - 2)**(n + 2)/18 + (x - 2)**(n + 3)/81 - (x - 2)**(n + 4)/324 + (x - 2)**(n + 5)/1215 + O((x - 2)**(n + 6), (x, 2))) f = x**(n - 2)*cos(x) assert fps(f, x).truncate() == \ (x**(n - 2) - x**n/2 + x**(n + 2)/24 - x**(n + 4)/720 + O(x**(n + 6), x)) f = x**(n - 2)*sin(x) + x**n*exp(x) assert fps(f, x).truncate() == \ (x**(n - 1) + x**n + 5*x**(n + 1)/6 + x**(n + 2)/2 + 7*x**(n + 3)/40 + x**(n + 4)/24 + 41*x**(n + 5)/5040 + O(x**(n + 6), x)) f = x**n*atan(x) assert fps(f, x, oo).truncate() == \ (-x**(n - 5)/5 + x**(n - 3)/3 + x**n*(pi/2 - 1/x) + O((1/x)**(-n)/x**6, (x, oo))) f = x**(n/2)*cos(x) assert fps(f, x).truncate() == \ x**(n/2) - x**(n/2 + 2)/2 + x**(n/2 + 4)/24 + O(x**(n/2 + 6), x) f = x**(n + m)*sin(x) assert fps(f, x).truncate() == \ x**(m + n + 1) - x**(m + n + 3)/6 + x**(m + n + 5)/120 + O(x**(m + n + 6), x)
def test_2nd_power_series_regular(): C1, C2, a = symbols("C1 C2 a") eq = x**2*(f(x).diff(x, 2)) - 3*x*(f(x).diff(x)) + (4*x + 4)*f(x) sol = Eq(f(x), C1*x**2*(-16*x**3/9 + 4*x**2 - 4*x + 1) + O(x**6)) assert dsolve(eq, hint='2nd_power_series_regular') == sol assert checkodesol(eq, sol) == (True, 0) eq = 4*x**2*(f(x).diff(x, 2)) -8*x**2*(f(x).diff(x)) + (4*x**2 + 1)*f(x) sol = Eq(f(x), C1*sqrt(x)*(x**4/24 + x**3/6 + x**2/2 + x + 1) + O(x**6)) assert dsolve(eq, hint='2nd_power_series_regular') == sol assert checkodesol(eq, sol) == (True, 0) eq = x**2*(f(x).diff(x, 2)) - x**2*(f(x).diff(x)) + ( x**2 - 2)*f(x) sol = Eq(f(x), C1*(-x**6/720 - 3*x**5/80 - x**4/8 + x**2/2 + x/2 + 1)/x + C2*x**2*(-x**3/60 + x**2/20 + x/2 + 1) + O(x**6)) assert dsolve(eq) == sol assert checkodesol(eq, sol) == (True, 0) eq = x**2*(f(x).diff(x, 2)) + x*(f(x).diff(x)) + (x**2 - Rational(1, 4))*f(x) sol = Eq(f(x), C1*(x**4/24 - x**2/2 + 1)/sqrt(x) + C2*sqrt(x)*(x**4/120 - x**2/6 + 1) + O(x**6)) assert dsolve(eq, hint='2nd_power_series_regular') == sol assert checkodesol(eq, sol) == (True, 0) eq = x*f(x).diff(x, 2) + f(x).diff(x) - a*x*f(x) sol = Eq(f(x), C1*(a**2*x**4/64 + a*x**2/4 + 1) + O(x**6)) assert dsolve(eq, f(x), hint="2nd_power_series_regular") == sol assert checkodesol(eq, sol) == (True, 0) eq = f(x).diff(x, 2) + ((1 - x)/x)*f(x).diff(x) + (a/x)*f(x) sol = Eq(f(x), C1*(-a*x**5*(a - 4)*(a - 3)*(a - 2)*(a - 1)/14400 + \ a*x**4*(a - 3)*(a - 2)*(a - 1)/576 - a*x**3*(a - 2)*(a - 1)/36 + \ a*x**2*(a - 1)/4 - a*x + 1) + O(x**6)) assert dsolve(eq, f(x), hint="2nd_power_series_regular") == sol assert checkodesol(eq, sol) == (True, 0)
def test_issue_3554(): x = Symbol('x') assert (1 / sqrt(1 + cos(x) * sin(x**2))).series(x, 0, 7) == \ 1 - x**2/2 + 5*x**4/8 - 5*x**6/8 + O(x**7) assert (1 / sqrt(1 + cos(x) * sin(x**2))).series(x, 0, 8) == \ 1 - x**2/2 + 5*x**4/8 - 5*x**6/8 + O(x**8)
def test_issue_3554s(): x = Symbol('x') assert (1 / sqrt(1 + cos(x) * sin(x**2))).series(x, 0, 15) == \ 1 - x**2/2 + 5*x**4/8 - 5*x**6/8 + 4039*x**8/5760 - 5393*x**10/6720 + \ 13607537*x**12/14515200 - 532056047*x**14/479001600 + O(x**15)
def test_fresnel(): assert fresnels(0) is S.Zero assert fresnels(oo) is S.Half assert fresnels(-oo) == Rational(-1, 2) assert fresnels(I*oo) == -I*S.Half assert unchanged(fresnels, z) assert fresnels(-z) == -fresnels(z) assert fresnels(I*z) == -I*fresnels(z) assert fresnels(-I*z) == I*fresnels(z) assert conjugate(fresnels(z)) == fresnels(conjugate(z)) assert fresnels(z).diff(z) == sin(pi*z**2/2) assert fresnels(z).rewrite(erf) == (S.One + I)/4 * ( erf((S.One + I)/2*sqrt(pi)*z) - I*erf((S.One - I)/2*sqrt(pi)*z)) assert fresnels(z).rewrite(hyper) == \ pi*z**3/6 * hyper([Rational(3, 4)], [Rational(3, 2), Rational(7, 4)], -pi**2*z**4/16) assert fresnels(z).series(z, n=15) == \ pi*z**3/6 - pi**3*z**7/336 + pi**5*z**11/42240 + O(z**15) assert fresnels(w).is_extended_real is True assert fresnels(w).is_finite is True assert fresnels(z).is_extended_real is None assert fresnels(z).is_finite is None assert fresnels(z).as_real_imag() == (fresnels(re(z) - I*im(z))/2 + fresnels(re(z) + I*im(z))/2, -I*(-fresnels(re(z) - I*im(z)) + fresnels(re(z) + I*im(z)))/2) assert fresnels(z).as_real_imag(deep=False) == (fresnels(re(z) - I*im(z))/2 + fresnels(re(z) + I*im(z))/2, -I*(-fresnels(re(z) - I*im(z)) + fresnels(re(z) + I*im(z)))/2) assert fresnels(w).as_real_imag() == (fresnels(w), 0) assert fresnels(w).as_real_imag(deep=True) == (fresnels(w), 0) assert fresnels(2 + 3*I).as_real_imag() == ( fresnels(2 + 3*I)/2 + fresnels(2 - 3*I)/2, -I*(fresnels(2 + 3*I) - fresnels(2 - 3*I))/2 ) assert expand_func(integrate(fresnels(z), z)) == \ z*fresnels(z) + cos(pi*z**2/2)/pi assert fresnels(z).rewrite(meijerg) == sqrt(2)*pi*z**Rational(9, 4) * \ meijerg(((), (1,)), ((Rational(3, 4),), (Rational(1, 4), 0)), -pi**2*z**4/16)/(2*(-z)**Rational(3, 4)*(z**2)**Rational(3, 4)) assert fresnelc(0) is S.Zero assert fresnelc(oo) == S.Half assert fresnelc(-oo) == Rational(-1, 2) assert fresnelc(I*oo) == I*S.Half assert unchanged(fresnelc, z) assert fresnelc(-z) == -fresnelc(z) assert fresnelc(I*z) == I*fresnelc(z) assert fresnelc(-I*z) == -I*fresnelc(z) assert conjugate(fresnelc(z)) == fresnelc(conjugate(z)) assert fresnelc(z).diff(z) == cos(pi*z**2/2) assert fresnelc(z).rewrite(erf) == (S.One - I)/4 * ( erf((S.One + I)/2*sqrt(pi)*z) + I*erf((S.One - I)/2*sqrt(pi)*z)) assert fresnelc(z).rewrite(hyper) == \ z * hyper([Rational(1, 4)], [S.Half, Rational(5, 4)], -pi**2*z**4/16) assert fresnelc(w).is_extended_real is True assert fresnelc(z).as_real_imag() == \ (fresnelc(re(z) - I*im(z))/2 + fresnelc(re(z) + I*im(z))/2, -I*(-fresnelc(re(z) - I*im(z)) + fresnelc(re(z) + I*im(z)))/2) assert fresnelc(z).as_real_imag(deep=False) == \ (fresnelc(re(z) - I*im(z))/2 + fresnelc(re(z) + I*im(z))/2, -I*(-fresnelc(re(z) - I*im(z)) + fresnelc(re(z) + I*im(z)))/2) assert fresnelc(2 + 3*I).as_real_imag() == ( fresnelc(2 - 3*I)/2 + fresnelc(2 + 3*I)/2, -I*(fresnelc(2 + 3*I) - fresnelc(2 - 3*I))/2 ) assert expand_func(integrate(fresnelc(z), z)) == \ z*fresnelc(z) - sin(pi*z**2/2)/pi assert fresnelc(z).rewrite(meijerg) == sqrt(2)*pi*z**Rational(3, 4) * \ meijerg(((), (1,)), ((Rational(1, 4),), (Rational(3, 4), 0)), -pi**2*z**4/16)/(2*(-z)**Rational(1, 4)*(z**2)**Rational(1, 4)) from sympy.core.random import verify_numerically verify_numerically(re(fresnels(z)), fresnels(z).as_real_imag()[0], z) verify_numerically(im(fresnels(z)), fresnels(z).as_real_imag()[1], z) verify_numerically(fresnels(z), fresnels(z).rewrite(hyper), z) verify_numerically(fresnels(z), fresnels(z).rewrite(meijerg), z) verify_numerically(re(fresnelc(z)), fresnelc(z).as_real_imag()[0], z) verify_numerically(im(fresnelc(z)), fresnelc(z).as_real_imag()[1], z) verify_numerically(fresnelc(z), fresnelc(z).rewrite(hyper), z) verify_numerically(fresnelc(z), fresnelc(z).rewrite(meijerg), z) raises(ArgumentIndexError, lambda: fresnels(z).fdiff(2)) raises(ArgumentIndexError, lambda: fresnelc(z).fdiff(2)) assert fresnels(x).taylor_term(-1, x) is S.Zero assert fresnelc(x).taylor_term(-1, x) is S.Zero assert fresnelc(x).taylor_term(1, x) == -pi**2*x**5/40
def test_issue_3683(): x = Symbol('x') assert sqrt(sin(x**3)).series(x, 0, 7) == sqrt(x**3) + O(x**7) assert sqrt(sin(x**4)).series(x, 0, 3) == sqrt(x**4) + O(x**3)
def test_erfi_series(): assert erfi(x).series(x, 0, 7) == 2*x/sqrt(pi) + \ 2*x**3/3/sqrt(pi) + x**5/5/sqrt(pi) + O(x**7) assert erfi(x).series(x, oo) == \ (3/(4*x**5) + 1/(2*x**3) + 1/x + O(x**(-6), (x, oo)))*exp(x**2)/sqrt(pi) - I
def test_issue_9192(): assert O(1) * O(1) == O(1) assert O(1)**O(1) == O(1)
def test_issue_9910(): assert O(x * log(x) + sin(x), (x, oo)) == O(x * log(x), (x, oo))
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 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 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_ignore_order_terms(): eq = exp(x).series(x, 0, 3) + sin(y + x**3) - 1 assert cse(eq) == ([], [sin(x**3 + y) + x + x**2 / 2 + O(x**3)])
def test_factorial_series(): n = Symbol('n', integer=True) assert factorial(n).series(n, 0, 3) == \ 1 - n*EulerGamma + n**2*(EulerGamma**2/2 + pi**2/12) + O(n**3)
def test_issue_6782(): x = Symbol('x') assert sqrt(sin(x**3)).series(x, 0, 7) == x**Rational(3, 2) + O(x**7) assert sqrt(sin(x**4)).series(x, 0, 3) == x**2 + O(x**3)
def test_issue_15539(): assert O(1 / x**2 + 1 / x**4, (x, -oo)) == O(1 / x**2, (x, -oo)) assert O(1 / x**4 + exp(x), (x, -oo)) == O(1 / x**4, (x, -oo)) assert O(1 / x**4 + exp(-x), (x, -oo)) == O(exp(-x), (x, -oo)) assert O(1 / x, (x, oo)).subs(x, -x) == O(-1 / x, (x, -oo))
def test_performance_of_adding_order(): l = list(x**i for i in range(1000)) l.append(O(x**1001)) assert Add(*l).subs(x, 1) == O(1)
def test_issue_22165(): assert O(log(x)).contains(2)
def test_simple_8(): assert O(sqrt(-x)) == O(sqrt(x)) assert O(x**2 * sqrt(x)) == O(x**Rational(5, 2)) assert O(x**3 * sqrt(-(-x)**3)) == O(x**Rational(9, 2)) assert O(x**Rational(3, 2) * sqrt((-x)**3)) == O(x**3) assert O(x * (-2 * x)**(I / 2)) == O(x * (-x)**(I / 2))
def test_issue_6653(): x = Symbol('x') assert (1 / sqrt(1 + sin(x**2))).series(x, 0, 3) == 1 - x**2 / 2 + O(x**3)
def test_issue_9917(): assert O(x * sin(x) + 1, (x, oo)) == O(x, (x, oo))
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, 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) ---------- ### 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 ### ------------- 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_simple_7(): assert 1 + O(1) == O(1) assert 2 + O(1) == O(1) assert x + O(1) == O(1) assert 1 / x + O(1) == 1 / x + O(1)