예제 #1
0
def test_rewrite():
    x, y, z = symbols('x y z')
    f1 = sin(x) + cos(x)
    assert f1.rewrite(cos,exp) == exp(I*x)/2 + sin(x) + exp(-I*x)/2
    assert f1.rewrite([cos],sin) == sin(x) + sin(x + pi/2, evaluate=False)
    f2 = sin(x) + cos(y)/gamma(z)
    assert f2.rewrite(sin,exp) == -I*(exp(I*x) - exp(-I*x))/2 + cos(y)/gamma(z)
예제 #2
0
def test_issue_3109():
    from sympy import root, Rational
    I = S.ImaginaryUnit
    assert sqrt(33**(9*I/10)) == -33**(9*I/20)
    assert root((6*I)**(2*I), 3).as_base_exp()[1] == Rational(1, 3) # != 2*I/3
    assert root((6*I)**(I/3), 3).as_base_exp()[1] == I/9
    assert sqrt(exp(3*I)) == exp(3*I/2)
    assert sqrt(-sqrt(3)*(1 + 2*I)) == sqrt(sqrt(3))*sqrt(-1 - 2*I)
예제 #3
0
    def eval(cls, n, m, theta, phi):
        n, m, theta, phi = [sympify(x) for x in (n, m, theta, phi)]

        # Handle negative index m and arguments theta, phi
        if m.could_extract_minus_sign():
            m = -m
            return S.NegativeOne**m * exp(-2*I*m*phi) * Ynm(n, m, theta, phi)
        if theta.could_extract_minus_sign():
            theta = -theta
            return Ynm(n, m, theta, phi)
        if phi.could_extract_minus_sign():
            phi = -phi
            return exp(-2*I*m*phi) * Ynm(n, m, theta, phi)
예제 #4
0
def test_rewrite():
    x, y, z = symbols('x y z')
    a, b = symbols('a b')
    f1 = sin(x) + cos(x)
    assert f1.rewrite(cos,exp) == exp(I*x)/2 + sin(x) + exp(-I*x)/2
    assert f1.rewrite([cos],sin) == sin(x) + sin(x + pi/2, evaluate=False)
    f2 = sin(x) + cos(y)/gamma(z)
    assert f2.rewrite(sin,exp) == -I*(exp(I*x) - exp(-I*x))/2 + cos(y)/gamma(z)
    assert Max(a, b).rewrite(Piecewise) == Piecewise((a, a >= b), (b, True))
    assert Max(x, y, z).rewrite(Piecewise) == Piecewise((x, (x >= y) & (x >= z)), (y, y >= z), (z, True))
    assert Max(x, y, a, b).rewrite(Piecewise) == Piecewise((a, (a >= b) & (a >= x) & (a >= y)),
        (b, (b >= x) & (b >= y)), (x, x >= y), (y, True))
    assert Min(a, b).rewrite(Piecewise) == Piecewise((a, a <= b), (b, True))
    assert Min(x, y, z).rewrite(Piecewise) == Piecewise((x, (x <= y) & (x <= z)), (y, y <= z), (z, True))
    assert Min(x,  y, a, b).rewrite(Piecewise) ==  Piecewise((a, (a <= b) & (a <= x) & (a <= y)),
        (b, (b <= x) & (b <= y)), (x, x <= y), (y, True))
예제 #5
0
def test_custom_codegen():
    from sympy.printing.ccode import C99CodePrinter
    from sympy.functions.elementary.exponential import exp

    printer = C99CodePrinter(settings={'user_functions': {'exp': 'fastexp'}})
    gen = C99CodeGen(printer=printer)
    gen.preprocessor_statements.append('#include "fastexp.h"')

    x, y = symbols('x y')
    expr = exp(x + y)

    expected = (
        '#include "expr.h"\n'
        '#include <math.h>\n'
        '#include "fastexp.h"\n'
        'double expr(double x, double y) {\n'
        '   double expr_result;\n'
        '   expr_result = fastexp(x + y);\n'
        '   return expr_result;\n'
        '}\n'
    )

    result = codegen(('expr', expr), header=False, empty=False, code_gen=gen)
    source = result[0][1]
    assert source == expected
예제 #6
0
def test_conditional():
    X = Geometric('X', S(2)/3)
    Y = Poisson('Y', 3)
    assert P(X > 2, X > 3) == 1
    assert P(X > 3, X > 2) == S(1)/3
    assert P(Y > 2, Y < 2) == 0
    assert P(Eq(Y, 3), Y >= 0) == 9*exp(-3)/2
예제 #7
0
파일: complexes.py 프로젝트: asmeurer/sympy
 def _eval_evalf(self, prec):
     from sympy import exp, pi, I
     z, period = self.args
     p = periodic_argument(z, period)._eval_evalf(prec)
     if abs(p) > pi or p == -pi:
         return self  # Cannot evalf for this argument.
     return (abs(z)*exp(I*p))._eval_evalf(prec)
예제 #8
0
파일: complexes.py 프로젝트: asmeurer/sympy
def _unpolarify(eq, exponents_only, pause=False):
    if not isinstance(eq, Basic) or eq.is_Atom:
        return eq

    if not pause:
        if isinstance(eq, exp_polar):
            return exp(_unpolarify(eq.exp, exponents_only))
        if isinstance(eq, principal_branch) and eq.args[1] == 2*pi:
            return _unpolarify(eq.args[0], exponents_only)
        if (
            eq.is_Add or eq.is_Mul or eq.is_Boolean or
            eq.is_Relational and (
                eq.rel_op in ('==', '!=') and 0 in eq.args or
                eq.rel_op not in ('==', '!='))
        ):
            return eq.func(*[_unpolarify(x, exponents_only) for x in eq.args])
        if isinstance(eq, polar_lift):
            return _unpolarify(eq.args[0], exponents_only)

    if eq.is_Pow:
        expo = _unpolarify(eq.exp, exponents_only)
        base = _unpolarify(eq.base, exponents_only,
            not (expo.is_integer and not pause))
        return base**expo

    if eq.is_Function and getattr(eq.func, 'unbranched', False):
        return eq.func(*[_unpolarify(x, exponents_only, exponents_only)
            for x in eq.args])

    return eq.func(*[_unpolarify(x, exponents_only, True) for x in eq.args])
예제 #9
0
def test_twave():
    A1, phi1, A2, phi2, f = symbols('A1, phi1, A2, phi2, f')
    n = Symbol('n')  # Refractive index
    t = Symbol('t')  # Time
    x = Symbol('x')  # Spatial varaible
    k = Symbol('k')  # Wave number
    E = Function('E')
    w1 = TWave(A1, f, phi1)
    w2 = TWave(A2, f, phi2)
    assert w1.amplitude == A1
    assert w1.frequency == f
    assert w1.phase == phi1
    assert w1.wavelength == c/(f*n)
    assert w1.time_period == 1/f
    w3 = w1 + w2
    assert w3.amplitude == sqrt(A1**2 + 2*A1*A2*cos(phi1 - phi2) + A2**2)
    assert w3.frequency == f
    assert w3.wavelength == c/(f*n)
    assert w3.time_period == 1/f
    assert w3.angular_velocity == 2*pi*f
    assert w3.wavenumber == 2*pi*f*n/c
    assert simplify(w3.rewrite('sin') - sqrt(A1**2 + 2*A1*A2*cos(phi1 - phi2)
    + A2**2)*sin(pi*f*n*x*s/(149896229*m) - 2*pi*f*t + atan2(A1*cos(phi1)
    + A2*cos(phi2), A1*sin(phi1) + A2*sin(phi2)) + pi/2)) == 0
    assert w3.rewrite('pde') == epsilon*mu*Derivative(E(x, t), t, t) + Derivative(E(x, t), x, x)
    assert w3.rewrite(cos) == sqrt(A1**2 + 2*A1*A2*cos(phi1 - phi2)
    + A2**2)*cos(pi*f*n*x*s/(149896229*m) - 2*pi*f*t + atan2(A1*cos(phi1)
    + A2*cos(phi2), A1*sin(phi1) + A2*sin(phi2)))
    assert w3.rewrite('exp') == sqrt(A1**2 + 2*A1*A2*cos(phi1 - phi2)
    + A2**2)*exp(I*(pi*f*n*x*s/(149896229*m) - 2*pi*f*t
    + atan2(A1*cos(phi1) + A2*cos(phi2), A1*sin(phi1) + A2*sin(phi2))))
예제 #10
0
파일: bivariate.py 프로젝트: ChaliZhg/sympy
def _lambert(eq, x):
    """
    Given an expression assumed to be in the form
        ``F(X, a..f) = a*log(b*X + c) + d*X + f = 0``
    where X = g(x) and x = g^-1(X), return the Lambert solution if possible:
        ``x = g^-1(-c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(-f/a)))``.
    """
    eq = _mexpand(expand_log(eq))
    mainlog = _mostfunc(eq, log, x)
    if not mainlog:
        return []  # violated assumptions
    other = eq.subs(mainlog, 0)
    if (-other).func is log:
        eq = (eq - other).subs(mainlog, mainlog.args[0])
        mainlog = mainlog.args[0]
        if mainlog.func is not log:
            return []  # violated assumptions
        other = -(-other).args[0]
        eq += other
    if not x in other.free_symbols:
        return [] # violated assumptions
    d, f, X2 = _linab(other, x)
    logterm = collect(eq - other, mainlog)
    a = logterm.as_coefficient(mainlog)
    if a is None or x in a.free_symbols:
        return []  # violated assumptions
    logarg = mainlog.args[0]
    b, c, X1 = _linab(logarg, x)
    if X1 != X2:
        return []  # violated assumptions

    u = Dummy('rhs')
    sol = []
    # check only real solutions:
    for k in [-1, 0]:
        l = LambertW(d/(a*b)*exp(c*d/a/b)*exp(-f/a), k)
        # if W's arg is between -1/e and 0 there is
        # a -1 branch real solution, too.
        if k and not l.is_real:
            continue
        rhs = -c/b + (a/d)*l

        solns = solve(X1 - u, x)
        for i, tmp in enumerate(solns):
            solns[i] = tmp.subs(u, rhs)
            sol.append(solns[i])
    return sol
예제 #11
0
파일: cfunctions.py 프로젝트: Lenqth/sympy
 def fdiff(self, argindex=1):
     """
     Returns the first derivative of this function.
     """
     if argindex == 1:
         return exp(*self.args)
     else:
         raise ArgumentIndexError(self, argindex)
예제 #12
0
    def eval(cls, a, x):
        # For lack of a better place, we use this one to extract branching
        # information. The following can be
        # found in the literature (c/f references given above), albeit scattered:
        # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s
        # 2) For fixed positive integers s, lowergamma(s, x) is an entire
        #    function of x.
        # 3) For fixed non-positive integers s,
        #    lowergamma(s, exp(I*2*pi*n)*x) =
        #              2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x)
        #    (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)).
        # 4) For fixed non-integral s,
        #    lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x),
        #    where lowergamma_unbranched(s, x) is an entire function (in fact
        #    of both s and x), i.e.
        #    lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x)
        from sympy import unpolarify, I
        if x == 0:
            return S.Zero
        nx, n = x.extract_branch_factor()
        if a.is_integer and a.is_positive:
            nx = unpolarify(x)
            if nx != x:
                return lowergamma(a, nx)
        elif a.is_integer and a.is_nonpositive:
            if n != 0:
                return 2*pi*I*n*(-1)**(-a)/factorial(-a) + lowergamma(a, nx)
        elif n != 0:
            return exp(2*pi*I*n*a)*lowergamma(a, nx)

        # Special values.
        if a.is_Number:
            if a is S.One:
                return S.One - exp(-x)
            elif a is S.Half:
                return sqrt(pi)*erf(sqrt(x))
            elif a.is_Integer or (2*a).is_Integer:
                b = a - 1
                if b.is_positive:
                    if a.is_integer:
                        return factorial(b) - exp(-x) * factorial(b) * Add(*[x ** k / factorial(k) for k in range(a)])
                    else:
                        return gamma(a) * (lowergamma(S.Half, x)/sqrt(pi) - exp(-x) * Add(*[x**(k-S.Half) / gamma(S.Half+k) for k in range(1, a+S.Half)]))

                if not a.is_Integer:
                    return (-1)**(S.Half - a) * pi*erf(sqrt(x)) / gamma(1-a) + exp(-x) * Add(*[x**(k+a-1)*gamma(a) / gamma(a+k) for k in range(1, S(3)/2-a)])
예제 #13
0
def test_discrete_probability():
    X = Geometric('X', S(1)/5)
    Y = Poisson('Y', 4)
    assert P(Eq(X, 3)) == S(16)/125
    assert P(X < 3) == S(9)/25
    assert P(X > 3) == S(64)/125
    assert P(X >= 3) == S(16)/25
    assert P(X <= 3) == S(61)/125
    assert P(Ne(X, 3)) == S(109)/125
    assert P(Eq(Y, 3)) == 32*exp(-4)/3
    assert P(Y < 3) == 13*exp(-4)
    assert P(Y > 3).equals(32*(-S(71)/32 + 3*exp(4)/32)*exp(-4)/3)
    assert P(Y >= 3).equals(32*(-39/32 + 3*exp(4)/32)*exp(-4)/3)
    assert P(Y <= 3) == 71*exp(-4)/3
    assert P(Ne(Y, 3)).equals(
        13*exp(-4) + 32*(-71/32 + 3*exp(4)/32)*exp(-4)/3)
    assert P(X < S.Infinity) is S.One
    assert P(X > S.Infinity) is S.Zero
예제 #14
0
    def eval(cls, a, x):
        # For lack of a better place, we use this one to extract branching
        # information. The following can be
        # found in the literature (c/f references given above), albeit scattered:
        # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s
        # 2) For fixed positive integers s, lowergamma(s, x) is an entire
        #    function of x.
        # 3) For fixed non-positive integers s,
        #    lowergamma(s, exp(I*2*pi*n)*x) =
        #              2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x)
        #    (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)).
        # 4) For fixed non-integral s,
        #    lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x),
        #    where lowergamma_unbranched(s, x) is an entire function (in fact
        #    of both s and x), i.e.
        #    lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x)
        from sympy import unpolarify, I
        if x == 0:
            return S.Zero
        nx, n = x.extract_branch_factor()
        if a.is_integer and a.is_positive:
            nx = unpolarify(x)
            if nx != x:
                return lowergamma(a, nx)
        elif a.is_integer and a.is_nonpositive:
            if n != 0:
                return 2*pi*I*n*(-1)**(-a)/factorial(-a) + lowergamma(a, nx)
        elif n != 0:
            return exp(2*pi*I*n*a)*lowergamma(a, nx)

        # Special values.
        if a.is_Number:
            # TODO this should be non-recursive
            if a is S.One:
                return S.One - exp(-x)
            elif a is S.Half:
                return sqrt(pi)*erf(sqrt(x))
            elif a.is_Integer or (2*a).is_Integer:
                b = a - 1
                if b.is_positive:
                    return b*cls(b, x) - x**b * exp(-x)

                if not a.is_Integer:
                    return (cls(a + 1, x) + x**a * exp(-x))/a
예제 #15
0
 def fdiff(self, argindex=2):
     from sympy import meijerg, unpolarify
     if argindex == 2:
         a, z = self.args
         return -exp(-unpolarify(z))*z**(a - 1)
     elif argindex == 1:
         a, z = self.args
         return uppergamma(a, z)*log(z) + meijerg([], [1, 1], [0, 0, a], [], z)
     else:
         raise ArgumentIndexError(self, argindex)
예제 #16
0
def test_expand():
    m0 = OperationsOnlyMatrix([[x*(x + y), 2], [((x + y)*y)*x, x*(y + x*(x + y))]])
    # Test if expand() returns a matrix
    m1 = m0.expand()
    assert m1 == Matrix(
        [[x*y + x**2, 2], [x*y**2 + y*x**2, x*y + y*x**2 + x**3]])

    a = Symbol('a', real=True)

    assert OperationsOnlyMatrix(1, 1, [exp(I*a)]).expand(complex=True) == \
           Matrix([cos(a) + I*sin(a)])
예제 #17
0
    def eval(cls, a, z):
        from sympy import unpolarify, I, expint
        if z.is_Number:
            if z is S.NaN:
                return S.NaN
            elif z is S.Infinity:
                return S.Zero
            elif z is S.Zero:
                # TODO: Holds only for Re(a) > 0:
                return gamma(a)

        # We extract branching information here. C/f lowergamma.
        nx, n = z.extract_branch_factor()
        if a.is_integer and (a > 0) == True:
            nx = unpolarify(z)
            if z != nx:
                return uppergamma(a, nx)
        elif a.is_integer and (a <= 0) == True:
            if n != 0:
                return -2*pi*I*n*(-1)**(-a)/factorial(-a) + uppergamma(a, nx)
        elif n != 0:
            return gamma(a)*(1 - exp(2*pi*I*n*a)) + exp(2*pi*I*n*a)*uppergamma(a, nx)

        # Special values.
        if a.is_Number:
            # TODO this should be non-recursive
            if a is S.One:
                return exp(-z)
            elif a is S.Half:
                return sqrt(pi)*(1 - erf(sqrt(z)))  # TODO could use erfc...
            elif a.is_Integer or (2*a).is_Integer:
                b = a - 1
                if b.is_positive:
                    return b*cls(b, z) + z**b * exp(-z)
                elif b.is_Integer:
                    return expint(-b, z)*unpolarify(z)**(b + 1)

                if not a.is_Integer:
                    return (cls(a + 1, z) - z**a * exp(-z))/a
예제 #18
0
 def fdiff(self, argindex=4):
     if argindex == 1:
         # Diff wrt n
         raise ArgumentIndexError(self, argindex)
     elif argindex == 2:
         # Diff wrt m
         raise ArgumentIndexError(self, argindex)
     elif argindex == 3:
         # Diff wrt theta
         n, m, theta, phi = self.args
         return (m * cot(theta) * Ynm(n, m, theta, phi) +
                 sqrt((n - m)*(n + m + 1)) * exp(-I*phi) * Ynm(n, m + 1, theta, phi))
     elif argindex == 4:
         # Diff wrt phi
         n, m, theta, phi = self.args
         return I * m * Ynm(n, m, theta, phi)
     else:
         raise ArgumentIndexError(self, argindex)
예제 #19
0
    def test_cf(dist, support_lower_limit, support_upper_limit):
        pdf = density(dist)
        t = S('t')
        x = S('x')

        # first function is the hardcoded CF of the distribution
        cf1 = lambdify([t], characteristic_function(dist)(t), 'mpmath')

        # second function is the Fourier transform of the density function
        f = lambdify([x, t], pdf(x)*exp(I*x*t), 'mpmath')
        cf2 = lambda t: mpmath.nsum(lambda x: f(x, t), [support_lower_limit, support_upper_limit], maxdegree=10)

        # compare the two functions at various points
        for test_point in [2, 5, 8, 11]:
            n1 = cf1(test_point)
            n2 = cf2(test_point)

            assert abs(re(n1) - re(n2)) < 1e-12
            assert abs(im(n1) - im(n2)) < 1e-12
예제 #20
0
파일: holonomic.py 프로젝트: Carreau/sympy
    def _shift(func, s):
        z = func.args[-1]
        d = z.collect(x, evaluate=False)
        b = list(d)[0]
        a = d[b]

        if isinstance(a, exp_polar):
            a = exp(a.as_base_exp()[1])
            z = a * b

        t = b.as_base_exp()
        b = t[1] if t[0] is x else S(0)
        r = s / b
        an = (i + r for i in func.args[0][0])
        ap = (i + r for i in func.args[0][1])
        bm = (i + r for i in func.args[1][0])
        bq = (i + r for i in func.args[1][1])

        return a**-r, meijerg((an, ap), (bm, bq), z)
예제 #21
0
 def eval(cls, n, x):
     if not n.is_Number:
         # Symbolic result L_n(x)
         # L_{n}(-x)  --->  exp(-x) * L_{-n-1}(x)
         # L_{-n}(x)  --->  exp(x) * L_{n-1}(-x)
         if n.could_extract_minus_sign():
             return exp(x) * laguerre(n - 1, -x)
         # We can evaluate for some special values of x
         if x == S.Zero:
             return S.One
         elif x == S.NegativeInfinity:
             return S.Infinity
         elif x == S.Infinity:
             return S.NegativeOne**n * S.Infinity
     else:
         # n is a given fixed integer, evaluate into polynomial
         if n.is_negative:
             raise ValueError(
                 "The index n must be nonnegative integer (got %r)" % n)
         else:
             return laguerre_poly(n, x, 0)
예제 #22
0
def _create_table(table):
    """
    Creates the look-up table. For a similar implementation
    see meijerint._create_lookup_table.
    """

    def add(formula, annihilator, arg, x0=0, y0=[]):
        """
        Adds a formula in the dictionary
        """
        table.setdefault(_mytype(formula, x_1), []).append((formula,
            HolonomicFunction(annihilator, arg, x0, y0)))

    R = QQ.old_poly_ring(x_1)
    _, Dx = DifferentialOperators(R, 'Dx')

    from sympy import (sin, cos, exp, log, erf, sqrt, pi,
        sinh, cosh, sinc, erfc, Si, Ci, Shi, erfi)

    # add some basic functions
    add(sin(x_1), Dx**2 + 1, x_1, 0, [0, 1])
    add(cos(x_1), Dx**2 + 1, x_1, 0, [1, 0])
    add(exp(x_1), Dx - 1, x_1, 0, 1)
    add(log(x_1), Dx + x_1*Dx**2, x_1, 1, [0, 1])

    add(erf(x_1), 2*x_1*Dx + Dx**2, x_1, 0, [0, 2/sqrt(pi)])
    add(erfc(x_1), 2*x_1*Dx + Dx**2, x_1, 0, [1, -2/sqrt(pi)])
    add(erfi(x_1), -2*x_1*Dx + Dx**2, x_1, 0, [0, 2/sqrt(pi)])

    add(sinh(x_1), Dx**2 - 1, x_1, 0, [0, 1])
    add(cosh(x_1), Dx**2 - 1, x_1, 0, [1, 0])

    add(sinc(x_1), x_1 + 2*Dx + x_1*Dx**2, x_1)

    add(Si(x_1), x_1*Dx + 2*Dx**2 + x_1*Dx**3, x_1)
    add(Ci(x_1), x_1*Dx + 2*Dx**2 + x_1*Dx**3, x_1)

    add(Shi(x_1), -x_1*Dx + 2*Dx**2 + x_1*Dx**3, x_1)
예제 #23
0
    def eval(cls, a, z):
        from sympy import unpolarify, I, expint
        if z.is_Number:
            if z is S.NaN:
                return S.NaN
            elif z is S.Infinity:
                return S.Zero
            elif z is S.Zero:
                # TODO: Holds only for Re(a) > 0:
                return gamma(a)

        # We extract branching information here. C/f lowergamma.
        nx, n = z.extract_branch_factor()
        if a.is_integer and (a > 0) == True:
            nx = unpolarify(z)
            if z != nx:
                return uppergamma(a, nx)
        elif a.is_integer and (a <= 0) == True:
            if n != 0:
                return -2*pi*I*n*(-1)**(-a)/factorial(-a) + uppergamma(a, nx)
        elif n != 0:
            return gamma(a)*(1 - exp(2*pi*I*n*a)) + exp(2*pi*I*n*a)*uppergamma(a, nx)

        # Special values.
        if a.is_Number:
            if a is S.One:
                return exp(-z)
            elif a is S.Half:
                return sqrt(pi)*erfc(sqrt(z))
            elif a.is_Integer or (2*a).is_Integer:
                b = a - 1
                if b.is_positive:
                    if a.is_integer:
                        return exp(-z) * factorial(b) * Add(*[z**k / factorial(k) for k in range(a)])
                    else:
                        return gamma(a) * erfc(sqrt(z)) + (-1)**(a - S(3)/2) * exp(-z) * sqrt(z) * Add(*[gamma(-S.Half - k) * (-z)**k / gamma(1-a) for k in range(a - S.Half)])
                elif b.is_Integer:
                    return expint(-b, z)*unpolarify(z)**(b + 1)

                if not a.is_Integer:
                    return (-1)**(S.Half - a) * pi*erfc(sqrt(z))/gamma(1-a) - z**a * exp(-z) * Add(*[z**k * gamma(a) / gamma(a+k+1) for k in range(S.Half - a)])
예제 #24
0
def test_DiscreteMarkovChain():

    # pass only the name
    X = DiscreteMarkovChain("X")
    assert isinstance(X.state_space, Range)
    assert X.index_set == S.Naturals0
    assert isinstance(X.transition_probabilities, MatrixSymbol)
    t = symbols('t', positive=True, integer=True)
    assert isinstance(X[t], RandomIndexedSymbol)
    assert E(X[0]) == Expectation(X[0])
    raises(TypeError, lambda: DiscreteMarkovChain(1))
    raises(NotImplementedError, lambda: X(t))
    raises(NotImplementedError, lambda: X.communication_classes())
    raises(NotImplementedError, lambda: X.canonical_form())
    raises(NotImplementedError, lambda: X.decompose())

    nz = Symbol('n', integer=True)
    TZ = MatrixSymbol('M', nz, nz)
    SZ = Range(nz)
    YZ = DiscreteMarkovChain('Y', SZ, TZ)
    assert P(Eq(YZ[2], 1), Eq(YZ[1], 0)) == TZ[0, 1]

    raises(ValueError, lambda: sample_stochastic_process(t))
    raises(ValueError, lambda: next(sample_stochastic_process(X)))
    # pass name and state_space
    # any hashable object should be a valid state
    # states should be valid as a tuple/set/list/Tuple/Range
    sym, rainy, cloudy, sunny = symbols('a Rainy Cloudy Sunny', real=True)
    state_spaces = [(1, 2, 3),
                    [Str('Hello'), sym,
                     DiscreteMarkovChain("Y", (1, 2, 3))],
                    Tuple(S(1), exp(sym), Str('World'), sympify=False),
                    Range(-1, 5, 2), [rainy, cloudy, sunny]]
    chains = [
        DiscreteMarkovChain("Y", state_space) for state_space in state_spaces
    ]

    for i, Y in enumerate(chains):
        assert isinstance(Y.transition_probabilities, MatrixSymbol)
        assert Y.state_space == state_spaces[i] or Y.state_space == FiniteSet(
            *state_spaces[i])
        assert Y.number_of_states == 3

        with ignore_warnings(
                UserWarning):  # TODO: Restore tests once warnings are removed
            assert P(Eq(Y[2], 1), Eq(Y[0], 2),
                     evaluate=False) == Probability(Eq(Y[2], 1), Eq(Y[0], 2))
        assert E(Y[0]) == Expectation(Y[0])

        raises(ValueError, lambda: next(sample_stochastic_process(Y)))

    raises(TypeError, lambda: DiscreteMarkovChain("Y", dict((1, 1))))
    Y = DiscreteMarkovChain("Y", Range(1, t, 2))
    assert Y.number_of_states == ceiling((t - 1) / 2)

    # pass name and transition_probabilities
    chains = [
        DiscreteMarkovChain("Y", trans_probs=Matrix([[]])),
        DiscreteMarkovChain("Y", trans_probs=Matrix([[0, 1], [1, 0]])),
        DiscreteMarkovChain("Y",
                            trans_probs=Matrix([[pi, 1 - pi], [sym, 1 - sym]]))
    ]
    for Z in chains:
        assert Z.number_of_states == Z.transition_probabilities.shape[0]
        assert isinstance(Z.transition_probabilities, ImmutableMatrix)

    # pass name, state_space and transition_probabilities
    T = Matrix([[0.5, 0.2, 0.3], [0.2, 0.5, 0.3], [0.2, 0.3, 0.5]])
    TS = MatrixSymbol('T', 3, 3)
    Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
    YS = DiscreteMarkovChain("Y", ['One', 'Two', 3], TS)
    assert Y.joint_distribution(1, Y[2],
                                3) == JointDistribution(Y[1], Y[2], Y[3])
    raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol))
    assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2)
    assert (P(Eq(YS[3], 2), Eq(YS[1], 1)) -
            (TS[0, 2] * TS[1, 0] + TS[1, 1] * TS[1, 2] +
             TS[1, 2] * TS[2, 2])).simplify() == 0
    assert P(Eq(YS[1], 1), Eq(YS[2], 2)) == Probability(Eq(YS[1], 1))
    assert P(Eq(YS[3], 3), Eq(
        YS[1],
        1)) == TS[0, 2] * TS[1, 0] + TS[1, 1] * TS[1, 2] + TS[1, 2] * TS[2, 2]
    TO = Matrix([[0.25, 0.75, 0], [0, 0.25, 0.75], [0.75, 0, 0.25]])
    assert P(Eq(Y[3], 2),
             Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float(
                 0.375, 3)
    with ignore_warnings(
            UserWarning):  ### TODO: Restore tests once warnings are removed
        assert E(Y[3], evaluate=False) == Expectation(Y[3])
        assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3)
    TSO = MatrixSymbol('T', 4, 4)
    raises(
        ValueError,
        lambda: str(P(Eq(YS[3], 2),
                      Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO))))
    raises(TypeError,
           lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M')))
    raises(
        ValueError,
        lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4)))
    raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6)))
    raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1)))

    # extended tests for probability queries
    TO1 = Matrix([[Rational(1, 4), Rational(3, 4), 0],
                  [Rational(1, 3),
                   Rational(1, 3),
                   Rational(1, 3)], [0, Rational(1, 4),
                                     Rational(3, 4)]])
    assert P(
        And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)),
        Eq(Probability(Eq(Y[0], 0)), Rational(1, 4))
        & TransitionMatrixOf(Y, TO1)) == Rational(1, 16)
    assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \
            Probability(Eq(Y[0], 0))/4
    assert P(
        Lt(X[1], 2) & Gt(X[1], 0),
        Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2])
        & TransitionMatrixOf(X, TO1)) == Rational(1, 4)
    assert P(
        Lt(X[1], 2) & Gt(X[1], 0),
        Eq(X[0], 2) & StochasticStateSpaceOf(X, [S(0), '0', 1])
        & TransitionMatrixOf(X, TO1)) == Rational(1, 4)
    assert P(
        Ne(X[1], 2) & Ne(X[1], 1),
        Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2])
        & TransitionMatrixOf(X, TO1)) is S.Zero
    assert P(
        Ne(X[1], 2) & Ne(X[1], 1),
        Eq(X[0], 2) & StochasticStateSpaceOf(X, [S(0), '0', 1])
        & TransitionMatrixOf(X, TO1)) is S.Zero
    assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)),
             Eq(Y[1], 1)) == 0.1 * Probability(Eq(Y[0], 0))

    # testing properties of Markov chain
    TO2 = Matrix([[S.One, 0, 0],
                  [Rational(1, 3),
                   Rational(1, 3),
                   Rational(1, 3)], [0, Rational(1, 4),
                                     Rational(3, 4)]])
    TO3 = Matrix([[Rational(1, 4), Rational(3, 4), 0],
                  [Rational(1, 3),
                   Rational(1, 3),
                   Rational(1, 3)], [0, Rational(1, 4),
                                     Rational(3, 4)]])
    Y2 = DiscreteMarkovChain('Y', trans_probs=TO2)
    Y3 = DiscreteMarkovChain('Y', trans_probs=TO3)
    assert Y3.fundamental_matrix() == ImmutableMatrix(
        [[176, 81, -132], [36, 141, -52], [-44, -39, 208]]) / 125
    assert Y2.is_absorbing_chain() == True
    assert Y3.is_absorbing_chain() == False
    assert Y2.canonical_form() == ([0, 1, 2], TO2)
    assert Y3.canonical_form() == ([0, 1, 2], TO3)
    assert Y2.decompose() == ([0, 1,
                               2], TO2[0:1, 0:1], TO2[1:3, 0:1], TO2[1:3, 1:3])
    assert Y3.decompose() == ([0, 1, 2], TO3, Matrix(0, 3,
                                                     []), Matrix(0, 0, []))
    TO4 = Matrix([[Rational(1, 5),
                   Rational(2, 5),
                   Rational(2, 5)], [Rational(1, 10), S.Half,
                                     Rational(2, 5)],
                  [Rational(3, 5),
                   Rational(3, 10),
                   Rational(1, 10)]])
    Y4 = DiscreteMarkovChain('Y', trans_probs=TO4)
    w = ImmutableMatrix([[Rational(11, 39),
                          Rational(16, 39),
                          Rational(4, 13)]])
    assert Y4.limiting_distribution == w
    assert Y4.is_regular() == True
    assert Y4.is_ergodic() == True
    TS1 = MatrixSymbol('T', 3, 3)
    Y5 = DiscreteMarkovChain('Y', trans_probs=TS1)
    assert Y5.limiting_distribution(w, TO4).doit() == True
    assert Y5.stationary_distribution(condition_set=True).subs(
        TS1, TO4).contains(w).doit() == S.true
    TO6 = Matrix([[S.One, 0, 0, 0, 0], [S.Half, 0, S.Half, 0, 0],
                  [0, S.Half, 0, S.Half, 0], [0, 0, S.Half, 0, S.Half],
                  [0, 0, 0, 0, 1]])
    Y6 = DiscreteMarkovChain('Y', trans_probs=TO6)
    assert Y6.fundamental_matrix() == ImmutableMatrix(
        [[Rational(3, 2), S.One, S.Half], [S.One, S(2), S.One],
         [S.Half, S.One, Rational(3, 2)]])
    assert Y6.absorbing_probabilities() == ImmutableMatrix(
        [[Rational(3, 4), Rational(1, 4)], [S.Half, S.Half],
         [Rational(1, 4), Rational(3, 4)]])
    TO7 = Matrix([[Rational(1, 2),
                   Rational(1, 4),
                   Rational(1, 4)], [Rational(1, 2), 0,
                                     Rational(1, 2)],
                  [Rational(1, 4),
                   Rational(1, 4),
                   Rational(1, 2)]])
    Y7 = DiscreteMarkovChain('Y', trans_probs=TO7)
    assert Y7.is_absorbing_chain() == False
    assert Y7.fundamental_matrix() == ImmutableMatrix(
        [[Rational(86, 75),
          Rational(1, 25),
          Rational(-14, 75)],
         [Rational(2, 25), Rational(21, 25),
          Rational(2, 25)],
         [Rational(-14, 75),
          Rational(1, 25),
          Rational(86, 75)]])

    # test for zero-sized matrix functionality
    X = DiscreteMarkovChain('X', trans_probs=Matrix([[]]))
    assert X.number_of_states == 0
    assert X.stationary_distribution() == Matrix([[]])
    assert X.communication_classes() == []
    assert X.canonical_form() == ([], Matrix([[]]))
    assert X.decompose() == ([], Matrix([[]]), Matrix([[]]), Matrix([[]]))
    assert X.is_regular() == False
    assert X.is_ergodic() == False

    # test communication_class
    # see https://drive.google.com/drive/folders/1HbxLlwwn2b3U8Lj7eb_ASIUb5vYaNIjg?usp=sharing
    # tutorial 2.pdf
    TO7 = Matrix([[0, 5, 5, 0, 0], [0, 0, 0, 10, 0], [5, 0, 5, 0, 0],
                  [0, 10, 0, 0, 0], [0, 3, 0, 3, 4]]) / 10
    Y7 = DiscreteMarkovChain('Y', trans_probs=TO7)
    tuples = Y7.communication_classes()
    classes, recurrence, periods = list(zip(*tuples))
    assert classes == ([1, 3], [0, 2], [4])
    assert recurrence == (True, False, False)
    assert periods == (2, 1, 1)

    TO8 = Matrix([[0, 0, 0, 10, 0, 0], [5, 0, 5, 0, 0, 0], [0, 4, 0, 0, 0, 6],
                  [10, 0, 0, 0, 0, 0], [0, 10, 0, 0, 0, 0], [0, 0, 0, 5, 5, 0]
                  ]) / 10
    Y8 = DiscreteMarkovChain('Y', trans_probs=TO8)
    tuples = Y8.communication_classes()
    classes, recurrence, periods = list(zip(*tuples))
    assert classes == ([0, 3], [1, 2, 5, 4])
    assert recurrence == (True, False)
    assert periods == (2, 2)

    TO9 = Matrix(
        [[2, 0, 0, 3, 0, 0, 3, 2, 0, 0], [0, 10, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 2, 2, 0, 0, 0, 0, 0, 3, 3], [0, 0, 0, 3, 0, 0, 6, 1, 0, 0],
         [0, 0, 0, 0, 5, 5, 0, 0, 0, 0], [0, 0, 0, 0, 0, 10, 0, 0, 0, 0],
         [4, 0, 0, 5, 0, 0, 1, 0, 0, 0], [2, 0, 0, 4, 0, 0, 2, 2, 0, 0],
         [3, 0, 1, 0, 0, 0, 0, 0, 4, 2], [0, 0, 4, 0, 0, 0, 0, 0, 3, 3]]) / 10
    Y9 = DiscreteMarkovChain('Y', trans_probs=TO9)
    tuples = Y9.communication_classes()
    classes, recurrence, periods = list(zip(*tuples))
    assert classes == ([0, 3, 6, 7], [1], [2, 8, 9], [5], [4])
    assert recurrence == (True, True, False, True, False)
    assert periods == (1, 1, 1, 1, 1)

    # test canonical form
    # see https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
    # example 11.13
    T = Matrix([[1, 0, 0, 0, 0], [S(1) / 2, 0, S(1) / 2, 0, 0],
                [0, S(1) / 2, 0, S(1) / 2, 0], [0, 0,
                                                S(1) / 2, 0,
                                                S(1) / 2], [0, 0, 0, 0,
                                                            S(1)]])
    DW = DiscreteMarkovChain('DW', [0, 1, 2, 3, 4], T)
    states, A, B, C = DW.decompose()
    assert states == [0, 4, 1, 2, 3]
    assert A == Matrix([[1, 0], [0, 1]])
    assert B == Matrix([[S(1) / 2, 0], [0, 0], [0, S(1) / 2]])
    assert C == Matrix([[0, S(1) / 2, 0], [S(1) / 2, 0, S(1) / 2],
                        [0, S(1) / 2, 0]])
    states, new_matrix = DW.canonical_form()
    assert states == [0, 4, 1, 2, 3]
    assert new_matrix == Matrix([[1, 0, 0, 0, 0], [0, 1, 0, 0, 0],
                                 [S(1) / 2, 0, 0, S(1) / 2, 0],
                                 [0, 0, S(1) / 2, 0,
                                  S(1) / 2], [0, S(1) / 2, 0,
                                              S(1) / 2, 0]])

    # test regular and ergodic
    # https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
    T = Matrix([[0, 4, 0, 0, 0], [1, 0, 3, 0, 0], [0, 2, 0, 2, 0],
                [0, 0, 3, 0, 1], [0, 0, 0, 4, 0]]) / 4
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert not X.is_regular()
    assert X.is_ergodic()
    T = Matrix([[0, 1], [1, 0]])
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert not X.is_regular()
    assert X.is_ergodic()
    # http://www.math.wisc.edu/~valko/courses/331/MC2.pdf
    T = Matrix([[2, 1, 1], [2, 0, 2], [1, 1, 2]]) / 4
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_regular()
    assert X.is_ergodic()
    # https://docs.ufpr.br/~lucambio/CE222/1S2014/Kemeny-Snell1976.pdf
    T = Matrix([[1, 1], [1, 1]]) / 2
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_regular()
    assert X.is_ergodic()

    # test is_absorbing_chain
    T = Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]])
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert not X.is_absorbing_chain()
    # https://en.wikipedia.org/wiki/Absorbing_Markov_chain
    T = Matrix([[1, 1, 0, 0], [0, 1, 1, 0], [1, 0, 0, 1], [0, 0, 0, 2]]) / 2
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_absorbing_chain()
    T = Matrix([[2, 0, 0, 0, 0], [1, 0, 1, 0, 0], [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 1], [0, 0, 0, 0, 2]]) / 2
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_absorbing_chain()

    # test custom state space
    Y10 = DiscreteMarkovChain('Y', [1, 2, 3], TO2)
    tuples = Y10.communication_classes()
    classes, recurrence, periods = list(zip(*tuples))
    assert classes == ([1], [2, 3])
    assert recurrence == (True, False)
    assert periods == (1, 1)
    assert Y10.canonical_form() == ([1, 2, 3], TO2)
    assert Y10.decompose() == ([1, 2, 3], TO2[0:1, 0:1], TO2[1:3,
                                                             0:1], TO2[1:3,
                                                                       1:3])

    # testing miscellaneous queries
    T = Matrix([[S.Half, Rational(1, 4),
                 Rational(1, 4)], [Rational(1, 3), 0,
                                   Rational(2, 3)], [S.Half, S.Half, 0]])
    X = DiscreteMarkovChain('X', [0, 1, 2], T)
    assert P(
        Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0),
        Eq(P(Eq(X[1], 0)), Rational(1, 4))
        & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12)
    assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3)
    assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero
    assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3)
    assert E(X[1]**2, Eq(X[0], 1)) == Rational(8, 3)
    assert variance(X[1], Eq(X[0], 1)) == Rational(8, 9)
    raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))
    raises(ValueError, lambda: DiscreteMarkovChain('X', [0, 1], T))

    # testing miscellaneous queries with different state space
    X = DiscreteMarkovChain('X', ['A', 'B', 'C'], T)
    assert P(
        Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0),
        Eq(P(Eq(X[1], 0)), Rational(1, 4))
        & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12)
    assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3)
    assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero
    assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3)
    a = X.state_space.args[0]
    c = X.state_space.args[2]
    assert (E(X[1]**2, Eq(X[0], 1)) -
            (a**2 / 3 + 2 * c**2 / 3)).simplify() == 0
    assert (variance(X[1], Eq(X[0], 1)) -
            (2 * (-a / 3 + c / 3)**2 / 3 +
             (2 * a / 3 - 2 * c / 3)**2 / 3)).simplify() == 0
    raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))

    #testing queries with multiple RandomIndexedSymbols
    T = Matrix([[Rational(5, 10),
                 Rational(3, 10),
                 Rational(2, 10)],
                [Rational(2, 10),
                 Rational(7, 10),
                 Rational(1, 10)],
                [Rational(3, 10),
                 Rational(3, 10),
                 Rational(4, 10)]])
    Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
    assert P(Eq(Y[7], Y[5]), Eq(Y[2], 0)).round(5) == Float(0.44428, 5)
    assert P(Gt(Y[3], Y[1]), Eq(Y[0], 0)).round(2) == Float(0.36, 2)
    assert P(Le(Y[5], Y[10]), Eq(Y[4], 2)).round(6) == Float(0.583120, 6)
    assert Float(P(Eq(Y[10], Y[5]), Eq(Y[4], 1)),
                 14) == Float(1 - P(Ne(Y[10], Y[5]), Eq(Y[4], 1)), 14)
    assert Float(P(Gt(Y[8], Y[9]), Eq(Y[3], 2)),
                 14) == Float(1 - P(Le(Y[8], Y[9]), Eq(Y[3], 2)), 14)
    assert Float(P(Lt(Y[1], Y[4]), Eq(Y[0], 0)),
                 14) == Float(1 - P(Ge(Y[1], Y[4]), Eq(Y[0], 0)), 14)
    assert P(Eq(Y[5], Y[10]), Eq(Y[2], 1)) == P(Eq(Y[10], Y[5]), Eq(Y[2], 1))
    assert P(Gt(Y[1], Y[2]), Eq(Y[0], 1)) == P(Lt(Y[2], Y[1]), Eq(Y[0], 1))
    assert P(Ge(Y[7], Y[6]), Eq(Y[4], 1)) == P(Le(Y[6], Y[7]), Eq(Y[4], 1))

    #test symbolic queries
    a, b, c, d = symbols('a b c d')
    T = Matrix([[Rational(1, 10),
                 Rational(4, 10),
                 Rational(5, 10)],
                [Rational(3, 10),
                 Rational(4, 10),
                 Rational(3, 10)],
                [Rational(7, 10),
                 Rational(2, 10),
                 Rational(1, 10)]])
    Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
    query = P(Eq(Y[a], b), Eq(Y[c], d))
    assert query.subs({
        a: 10,
        b: 2,
        c: 5,
        d: 1
    }).evalf().round(4) == P(Eq(Y[10], 2), Eq(Y[5], 1)).round(4)
    assert query.subs({
        a: 15,
        b: 0,
        c: 10,
        d: 1
    }).evalf().round(4) == P(Eq(Y[15], 0), Eq(Y[10], 1)).round(4)
    query_gt = P(Gt(Y[a], b), Eq(Y[c], d))
    query_le = P(Le(Y[a], b), Eq(Y[c], d))
    assert query_gt.subs({
        a: 5,
        b: 2,
        c: 1,
        d: 0
    }).evalf() + query_le.subs({
        a: 5,
        b: 2,
        c: 1,
        d: 0
    }).evalf() == 1
    query_ge = P(Ge(Y[a], b), Eq(Y[c], d))
    query_lt = P(Lt(Y[a], b), Eq(Y[c], d))
    assert query_ge.subs({
        a: 4,
        b: 1,
        c: 0,
        d: 2
    }).evalf() + query_lt.subs({
        a: 4,
        b: 1,
        c: 0,
        d: 2
    }).evalf() == 1

    #test issue 20078
    assert (2 * Y[1] + 3 * Y[1]).simplify() == 5 * Y[1]
    assert (2 * Y[1] - 3 * Y[1]).simplify() == -Y[1]
    assert (2 * (0.25 * Y[1])).simplify() == 0.5 * Y[1]
    assert ((2 * Y[1]) * (0.25 * Y[1])).simplify() == 0.5 * Y[1]**2
    assert (Y[1]**2 + Y[1]**3).simplify() == (Y[1] + 1) * Y[1]**2
예제 #25
0
 def _eval_rewrite_as_exp(self, arg, **kwargs):
     return (exp(arg) + exp(-arg)) / 2
예제 #26
0
파일: cfunctions.py 프로젝트: Lenqth/sympy
 def _eval_rewrite_as_exp(self, arg):
     return exp(arg) - S.One
예제 #27
0
def test_issue_3109_fail():
    from sympy import root, Rational
    I = S.ImaginaryUnit
    assert sqrt(exp(5*I)) == -exp(5*I/2)
    assert root(exp(5*I), 3).exp == Rational(1, 3)
예제 #28
0
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'
예제 #29
0
def test_issue_21938():
    expr = sin(1 / x + exp(-x)) - sin(1 / x)
    assert expr.series(x, oo) == (1 / (24 * x**4) - 1 /
                                  (2 * x**2) + 1 + O(x**(-6),
                                                     (x, oo))) * exp(-x)
예제 #30
0
def test_exponential_domain():
    K = ZZ[E]
    eK = K.from_sympy(E)
    assert K.from_sympy(exp(3)) == eK**3
    assert K.convert(exp(3)) == eK**3
예제 #31
0
 def _characteristic_function(self, t):
     p = self.p
     return p * exp(I * t) / (1 - (1 - p) * exp(I * t))
예제 #32
0
def guess_generating_function(v, X=Symbol('x'), types=['all'], maxsqrtn=2):
    """
    Tries to "guess" a generating function for a sequence of rational numbers v.
    Only a few patterns are implemented yet.

    Explanation
    ===========

    The function returns a dictionary where keys are the name of a given type of
    generating function. Six types are currently implemented:

         type  |  formal definition
        -------+----------------------------------------------------------------
        ogf    | f(x) = Sum(            a_k * x^k       ,  k: 0..infinity )
        egf    | f(x) = Sum(            a_k * x^k / k!  ,  k: 0..infinity )
        lgf    | f(x) = Sum( (-1)^(k+1) a_k * x^k / k   ,  k: 1..infinity )
               |        (with initial index being hold as 1 rather than 0)
        hlgf   | f(x) = Sum(            a_k * x^k / k   ,  k: 1..infinity )
               |        (with initial index being hold as 1 rather than 0)
        lgdogf | f(x) = derivate( log(Sum( a_k * x^k, k: 0..infinity )), x)
        lgdegf | f(x) = derivate( log(Sum( a_k * x^k / k!, k: 0..infinity )), x)

    In order to spare time, the user can select only some types of generating
    functions (default being ['all']). While forgetting to use a list in the
    case of a single type may seem to work most of the time as in: types='ogf'
    this (convenient) syntax may lead to unexpected extra results in some cases.

    Discarding a type when calling the function does not mean that the type will
    not be present in the returned dictionary; it only means that no extra
    computation will be performed for that type, but the function may still add
    it in the result when it can be easily converted from another type.

    Two generating functions (lgdogf and lgdegf) are not even computed if the
    initial term of the sequence is 0; it may be useful in that case to try
    again after having removed the leading zeros.

    Examples
    ========

    >>> from sympy.concrete.guess import guess_generating_function as ggf
    >>> ggf([k+1 for k in range(12)], types=['ogf', 'lgf', 'hlgf'])
    {'hlgf': 1/(1 - x), 'lgf': 1/(x + 1), 'ogf': 1/(x**2 - 2*x + 1)}

    >>> from sympy import sympify
    >>> l = sympify("[3/2, 11/2, 0, -121/2, -363/2, 121]")
    >>> ggf(l)
    {'ogf': (x + 3/2)/(11*x**2 - 3*x + 1)}

    >>> from sympy import fibonacci
    >>> ggf([fibonacci(k) for k in range(5, 15)], types=['ogf'])
    {'ogf': (3*x + 5)/(-x**2 - x + 1)}

    >>> from sympy import factorial
    >>> ggf([factorial(k) for k in range(12)], types=['ogf', 'egf', 'lgf'])
    {'egf': 1/(1 - x)}

    >>> ggf([k+1 for k in range(12)], types=['egf'])
    {'egf': (x + 1)*exp(x), 'lgdegf': (x + 2)/(x + 1)}

    N-th root of a rational function can also be detected (below is an example
    coming from the sequence A108626 from http://oeis.org).
    The greatest n-th root to be tested is specified as maxsqrtn (default 2).

    >>> ggf([1, 2, 5, 14, 41, 124, 383, 1200, 3799, 12122, 38919])['ogf']
    sqrt(1/(x**4 + 2*x**2 - 4*x + 1))

    References
    ==========

    .. [1] "Concrete Mathematics", R.L. Graham, D.E. Knuth, O. Patashnik
    .. [2] https://oeis.org/wiki/Generating_functions

    """
    # List of all types of all g.f. known by the algorithm
    if 'all' in types:
        types = ['ogf', 'egf', 'lgf', 'hlgf', 'lgdogf', 'lgdegf']

    result = {}

    # Ordinary Generating Function (ogf)
    if 'ogf' in types:
        # Perform some convolutions of the sequence with itself
        t = [1 if k == 0 else 0 for k in range(len(v))]
        for d in range(max(1, maxsqrtn)):
            t = [
                sum(t[n - i] * v[i] for i in range(n + 1))
                for n in range(len(v))
            ]
            g = guess_generating_function_rational(t, X=X)
            if g:
                result['ogf'] = g**Rational(1, d + 1)
                break

    # Exponential Generating Function (egf)
    if 'egf' in types:
        # Transform sequence (division by factorial)
        w, f = [], S.One
        for i, k in enumerate(v):
            f *= i if i else 1
            w.append(k / f)
        # Perform some convolutions of the sequence with itself
        t = [1 if k == 0 else 0 for k in range(len(w))]
        for d in range(max(1, maxsqrtn)):
            t = [
                sum(t[n - i] * w[i] for i in range(n + 1))
                for n in range(len(w))
            ]
            g = guess_generating_function_rational(t, X=X)
            if g:
                result['egf'] = g**Rational(1, d + 1)
                break

    # Logarithmic Generating Function (lgf)
    if 'lgf' in types:
        # Transform sequence (multiplication by (-1)^(n+1) / n)
        w, f = [], S.NegativeOne
        for i, k in enumerate(v):
            f = -f
            w.append(f * k / Integer(i + 1))
        # Perform some convolutions of the sequence with itself
        t = [1 if k == 0 else 0 for k in range(len(w))]
        for d in range(max(1, maxsqrtn)):
            t = [
                sum(t[n - i] * w[i] for i in range(n + 1))
                for n in range(len(w))
            ]
            g = guess_generating_function_rational(t, X=X)
            if g:
                result['lgf'] = g**Rational(1, d + 1)
                break

    # Hyperbolic logarithmic Generating Function (hlgf)
    if 'hlgf' in types:
        # Transform sequence (division by n+1)
        w = []
        for i, k in enumerate(v):
            w.append(k / Integer(i + 1))
        # Perform some convolutions of the sequence with itself
        t = [1 if k == 0 else 0 for k in range(len(w))]
        for d in range(max(1, maxsqrtn)):
            t = [
                sum(t[n - i] * w[i] for i in range(n + 1))
                for n in range(len(w))
            ]
            g = guess_generating_function_rational(t, X=X)
            if g:
                result['hlgf'] = g**Rational(1, d + 1)
                break

    # Logarithmic derivative of ordinary generating Function (lgdogf)
    if v[0] != 0 and ('lgdogf' in types or
                      ('ogf' in types and 'ogf' not in result)):
        # Transform sequence by computing f'(x)/f(x)
        # because log(f(x)) = integrate( f'(x)/f(x) )
        a, w = sympify(v[0]), []
        for n in range(len(v) - 1):
            w.append((v[n + 1] * (n + 1) - sum(w[-i - 1] * v[i + 1]
                                               for i in range(n))) / a)
        # Perform some convolutions of the sequence with itself
        t = [1 if k == 0 else 0 for k in range(len(w))]
        for d in range(max(1, maxsqrtn)):
            t = [
                sum(t[n - i] * w[i] for i in range(n + 1))
                for n in range(len(w))
            ]
            g = guess_generating_function_rational(t, X=X)
            if g:
                result['lgdogf'] = g**Rational(1, d + 1)
                if 'ogf' not in result:
                    result['ogf'] = exp(integrate(result['lgdogf'], X))
                break

    # Logarithmic derivative of exponential generating Function (lgdegf)
    if v[0] != 0 and ('lgdegf' in types or
                      ('egf' in types and 'egf' not in result)):
        # Transform sequence / step 1 (division by factorial)
        z, f = [], Integer(1)
        for i, k in enumerate(v):
            f *= i if i else 1
            z.append(k / f)
        # Transform sequence / step 2 by computing f'(x)/f(x)
        # because log(f(x)) = integrate( f'(x)/f(x) )
        a, w = z[0], []
        for n in range(len(z) - 1):
            w.append((z[n + 1] * (n + 1) - sum(w[-i - 1] * z[i + 1]
                                               for i in range(n))) / a)
        # Perform some convolutions of the sequence with itself
        t = [1 if k == 0 else 0 for k in range(len(w))]
        for d in range(max(1, maxsqrtn)):
            t = [
                sum(t[n - i] * w[i] for i in range(n + 1))
                for n in range(len(w))
            ]
            g = guess_generating_function_rational(t, X=X)
            if g:
                result['lgdegf'] = g**Rational(1, d + 1)
                if 'egf' not in result:
                    result['egf'] = exp(integrate(result['lgdegf'], X))
                break

    return result
예제 #33
0
def test_power_rewrite_exp():
    assert (I**I).rewrite(exp) == exp(-pi / 2)

    expr = (2 + 3 * I)**(4 + 5 * I)
    assert expr.rewrite(exp) == exp(
        (4 + 5 * I) * (log(sqrt(13)) + I * atan(Rational(3, 2))))
    assert expr.rewrite(exp).expand() == \
        169*exp(5*I*log(13)/2)*exp(4*I*atan(Rational(3, 2)))*exp(-5*atan(Rational(3, 2)))

    assert ((6 + 7 * I)**5).rewrite(exp) == 7225 * sqrt(85) * exp(
        5 * I * atan(Rational(7, 6)))

    expr = 5**(6 + 7 * I)
    assert expr.rewrite(exp) == exp((6 + 7 * I) * log(5))
    assert expr.rewrite(exp).expand() == 15625 * exp(7 * I * log(5))

    assert Pow(123, 789, evaluate=False).rewrite(exp) == 123**789
    assert (1**I).rewrite(exp) == 1**I
    assert (0**I).rewrite(exp) == 0**I

    expr = (-2)**(2 + 5 * I)
    assert expr.rewrite(exp) == exp((2 + 5 * I) * (log(2) + I * pi))
    assert expr.rewrite(exp).expand() == 4 * exp(-5 * pi) * exp(5 * I * log(2))

    assert ((-2)**S(-5)).rewrite(exp) == (-2)**S(-5)

    x, y = symbols('x y')
    assert (x**y).rewrite(exp) == exp(y * log(x))
    assert (7**x).rewrite(exp) == exp(x * log(7), evaluate=False)
    assert ((2 + 3 * I)**x).rewrite(exp) == exp(
        x * (log(sqrt(13)) + I * atan(Rational(3, 2))))
    assert (y**(5 + 6 * I)).rewrite(exp) == exp(log(y) * (5 + 6 * I))

    assert all((1 / func(x)).rewrite(exp) == 1 / (func(x).rewrite(exp))
               for func in (sin, cos, tan, sec, csc, sinh, cosh, tanh))
예제 #34
0
 def _eval_rewrite_as_exp(self, arg, **kwargs):
     neg_exp, pos_exp = exp(-arg), exp(arg)
     return (pos_exp + neg_exp)/(pos_exp - neg_exp)
예제 #35
0
 def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
     neg_exp, pos_exp = exp(-arg), exp(arg)
     return (pos_exp + neg_exp)/(pos_exp - neg_exp)
예제 #36
0
 def _eval_rewrite_as_exp(self, arg, **kwargs):
     return (exp(arg) + exp(-arg)) / 2
예제 #37
0
def test_exp():
    e1 = exp(x).series(x, 0)
    e2 = series(exp(x), x, 0)
    assert e1 == e2
예제 #38
0
    def eval(cls, a, x):
        # For lack of a better place, we use this one to extract branching
        # information. The following can be
        # found in the literature (c/f references given above), albeit scattered:
        # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s
        # 2) For fixed positive integers s, lowergamma(s, x) is an entire
        #    function of x.
        # 3) For fixed non-positive integers s,
        #    lowergamma(s, exp(I*2*pi*n)*x) =
        #              2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x)
        #    (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)).
        # 4) For fixed non-integral s,
        #    lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x),
        #    where lowergamma_unbranched(s, x) is an entire function (in fact
        #    of both s and x), i.e.
        #    lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x)
        from sympy import unpolarify, I

        if x is S.Zero:
            return S.Zero
        nx, n = x.extract_branch_factor()
        if a.is_integer and a.is_positive:
            nx = unpolarify(x)
            if nx != x:
                return lowergamma(a, nx)
        elif a.is_integer and a.is_nonpositive:
            if n != 0:
                return 2 * pi * I * n * (-1) ** (-a) / factorial(-a) + lowergamma(a, nx)
        elif n != 0:
            return exp(2 * pi * I * n * a) * lowergamma(a, nx)

        # Special values.
        if a.is_Number:
            if a is S.One:
                return S.One - exp(-x)
            elif a is S.Half:
                return sqrt(pi) * erf(sqrt(x))
            elif a.is_Integer or (2 * a).is_Integer:
                b = a - 1
                if b.is_positive:
                    if a.is_integer:
                        return factorial(b) - exp(-x) * factorial(b) * Add(
                            *[x ** k / factorial(k) for k in range(a)]
                        )
                    else:
                        return gamma(a) * (
                            lowergamma(S.Half, x) / sqrt(pi)
                            - exp(-x)
                            * Add(
                                *[
                                    x ** (k - S.Half) / gamma(S.Half + k)
                                    for k in range(1, a + S.Half)
                                ]
                            )
                        )

                if not a.is_Integer:
                    return (-1) ** (S.Half - a) * pi * erf(sqrt(x)) / gamma(
                        1 - a
                    ) + exp(-x) * Add(
                        *[
                            x ** (k + a - 1) * gamma(a) / gamma(a + k)
                            for k in range(1, Rational(3, 2) - a)
                        ]
                    )

        if x.is_zero:
            return S.Zero
예제 #39
0
 def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs):
     return (exp(arg) + exp(-arg)) / 2
예제 #40
0
    def eval(cls, a, z):
        from sympy import unpolarify, I, expint

        if z.is_Number:
            if z is S.NaN:
                return S.NaN
            elif z is S.Infinity:
                return S.Zero
            elif z.is_zero:
                if re(a).is_positive:
                    return gamma(a)

        # We extract branching information here. C/f lowergamma.
        nx, n = z.extract_branch_factor()
        if a.is_integer and a.is_positive:
            nx = unpolarify(z)
            if z != nx:
                return uppergamma(a, nx)
        elif a.is_integer and a.is_nonpositive:
            if n != 0:
                return -2 * pi * I * n * (-1) ** (-a) / factorial(-a) + uppergamma(
                    a, nx
                )
        elif n != 0:
            return gamma(a) * (1 - exp(2 * pi * I * n * a)) + exp(
                2 * pi * I * n * a
            ) * uppergamma(a, nx)

        # Special values.
        if a.is_Number:
            if a is S.Zero and z.is_positive:
                return -Ei(-z)
            elif a is S.One:
                return exp(-z)
            elif a is S.Half:
                return sqrt(pi) * erfc(sqrt(z))
            elif a.is_Integer or (2 * a).is_Integer:
                b = a - 1
                if b.is_positive:
                    if a.is_integer:
                        return (
                            exp(-z)
                            * factorial(b)
                            * Add(*[z ** k / factorial(k) for k in range(a)])
                        )
                    else:
                        return gamma(a) * erfc(sqrt(z)) + (-1) ** (a - S(3) / 2) * exp(
                            -z
                        ) * sqrt(z) * Add(
                            *[
                                gamma(-S.Half - k) * (-z) ** k / gamma(1 - a)
                                for k in range(a - S.Half)
                            ]
                        )
                elif b.is_Integer:
                    return expint(-b, z) * unpolarify(z) ** (b + 1)

                if not a.is_Integer:
                    return (-1) ** (S.Half - a) * pi * erfc(sqrt(z)) / gamma(
                        1 - a
                    ) - z ** a * exp(-z) * Add(
                        *[
                            z ** k * gamma(a) / gamma(a + k + 1)
                            for k in range(S.Half - a)
                        ]
                    )

        if a.is_zero and z.is_positive:
            return -Ei(-z)

        if z.is_zero and re(a).is_positive:
            return gamma(a)
예제 #41
0
 def _moment_generating_function(self, t):
     p = self.p
     return p * exp(t) / (1 - (1 - p) * exp(t))
예제 #42
0
def _expm1(x):
    return exp(x) - S.One
예제 #43
0
 def _eval_rewrite_as_Sum(self, *args):
     from sympy.concrete.summations import Sum
     return exp(Sum(log(self.function), *self.limits))
예제 #44
0
 def _eval_rewrite_as_exp(self, arg, **kwargs):
     return exp(arg) - S.One
예제 #45
0
def test_issue_20551():
    expr = (exp(x) / x).series(x, n=None)
    terms = [next(expr) for i in range(3)]
    assert terms == [1 / x, 1, x / 2]
예제 #46
0
 def _eval_evalf(self, prec):
     z, period = self.args
     p = periodic_argument(z, period)._eval_evalf(prec)
     if abs(p) > pi or p == -pi:
         return self  # Cannot evalf for this argument.
     return (abs(z) * exp(I * p))._eval_evalf(prec)
예제 #47
0
def test_exp2():
    e1 = exp(cos(x)).series(x, 0)
    e2 = series(exp(cos(x)), x, 0)
    assert e1 == e2
예제 #48
0
    def eval(cls, arg):
        from sympy.simplify.simplify import signsimp
        from sympy.core.function import expand_mul
        from sympy.core.power import Pow

        if hasattr(arg, '_eval_Abs'):
            obj = arg._eval_Abs()
            if obj is not None:
                return obj
        if not isinstance(arg, Expr):
            raise TypeError("Bad argument type for Abs(): %s" % type(arg))

        # handle what we can
        arg = signsimp(arg, evaluate=False)
        n, d = arg.as_numer_denom()
        if d.free_symbols and not n.free_symbols:
            return cls(n) / cls(d)

        if arg.is_Mul:
            known = []
            unk = []
            for t in arg.args:
                if t.is_Pow and t.exp.is_integer and t.exp.is_negative:
                    bnew = cls(t.base)
                    if isinstance(bnew, cls):
                        unk.append(t)
                    else:
                        known.append(Pow(bnew, t.exp))
                else:
                    tnew = cls(t)
                    if isinstance(tnew, cls):
                        unk.append(t)
                    else:
                        known.append(tnew)
            known = Mul(*known)
            unk = cls(Mul(*unk), evaluate=False) if unk else S.One
            return known * unk
        if arg is S.NaN:
            return S.NaN
        if arg is S.ComplexInfinity:
            return S.Infinity
        if arg.is_Pow:
            base, exponent = arg.as_base_exp()
            if base.is_extended_real:
                if exponent.is_integer:
                    if exponent.is_even:
                        return arg
                    if base is S.NegativeOne:
                        return S.One
                    return Abs(base)**exponent
                if base.is_extended_nonnegative:
                    return base**re(exponent)
                if base.is_extended_negative:
                    return (-base)**re(exponent) * exp(-S.Pi * im(exponent))
                return
            elif not base.has(Symbol):  # complex base
                # express base**exponent as exp(exponent*log(base))
                a, b = log(base).as_real_imag()
                z = a + I * b
                return exp(re(exponent * z))
        if isinstance(arg, exp):
            return exp(re(arg.args[0]))
        if isinstance(arg, AppliedUndef):
            if arg.is_positive:
                return arg
            elif arg.is_negative:
                return -arg
            return
        if arg.is_Add and arg.has(S.Infinity, S.NegativeInfinity):
            if any(a.is_infinite for a in arg.as_real_imag()):
                return S.Infinity
        if arg.is_zero:
            return S.Zero
        if arg.is_extended_nonnegative:
            return arg
        if arg.is_extended_nonpositive:
            return -arg
        if arg.is_imaginary:
            arg2 = -S.ImaginaryUnit * arg
            if arg2.is_extended_nonnegative:
                return arg2
        if arg.is_extended_real:
            return
        # reject result if all new conjugates are just wrappers around
        # an expression that was already in the arg
        conj = signsimp(arg.conjugate(), evaluate=False)
        new_conj = conj.atoms(conjugate) - arg.atoms(conjugate)
        if new_conj and all(arg.has(i.args[0]) for i in new_conj):
            return
        if arg != conj and arg != -conj:
            ignore = arg.atoms(Abs)
            abs_free_arg = arg.xreplace({i: Dummy(real=True) for i in ignore})
            unk = [
                a for a in abs_free_arg.free_symbols
                if a.is_extended_real is None
            ]
            if not unk or not all(conj.has(conjugate(u)) for u in unk):
                return sqrt(expand_mul(arg * conj))
예제 #49
0
 def _eval_rewrite_as_Sum(self, *args, **kwargs):
     from sympy.concrete.summations import Sum
     return exp(Sum(log(self.function), *self.limits))
예제 #50
0
파일: complexes.py 프로젝트: asmeurer/sympy
    def eval(cls, arg):
        from sympy.simplify.simplify import signsimp
        from sympy.core.function import expand_mul

        if hasattr(arg, '_eval_Abs'):
            obj = arg._eval_Abs()
            if obj is not None:
                return obj
        if not isinstance(arg, Expr):
            raise TypeError("Bad argument type for Abs(): %s" % type(arg))
        # handle what we can
        arg = signsimp(arg, evaluate=False)
        if arg.is_Mul:
            known = []
            unk = []
            for t in arg.args:
                tnew = cls(t)
                if isinstance(tnew, cls):
                    unk.append(tnew.args[0])
                else:
                    known.append(tnew)
            known = Mul(*known)
            unk = cls(Mul(*unk), evaluate=False) if unk else S.One
            return known*unk
        if arg is S.NaN:
            return S.NaN
        if arg is S.ComplexInfinity:
            return S.Infinity
        if arg.is_Pow:
            base, exponent = arg.as_base_exp()
            if base.is_real:
                if exponent.is_integer:
                    if exponent.is_even:
                        return arg
                    if base is S.NegativeOne:
                        return S.One
                    if isinstance(base, cls) and exponent is S.NegativeOne:
                        return arg
                    return Abs(base)**exponent
                if base.is_nonnegative:
                    return base**re(exponent)
                if base.is_negative:
                    return (-base)**re(exponent)*exp(-S.Pi*im(exponent))
                return
            elif not base.has(Symbol): # complex base
                # express base**exponent as exp(exponent*log(base))
                a, b = log(base).as_real_imag()
                z = a + I*b
                return exp(re(exponent*z))

        if isinstance(arg, exp):
            return exp(re(arg.args[0]))
        if isinstance(arg, AppliedUndef):
            return
        if arg.is_Add and arg.has(S.Infinity, S.NegativeInfinity):
            if any(a.is_infinite for a in arg.as_real_imag()):
                return S.Infinity
        if arg.is_zero:
            return S.Zero
        if arg.is_nonnegative:
            return arg
        if arg.is_nonpositive:
            return -arg
        if arg.is_imaginary:
            arg2 = -S.ImaginaryUnit * arg
            if arg2.is_nonnegative:
                return arg2
        # reject result if all new conjugates are just wrappers around
        # an expression that was already in the arg
        conj = signsimp(arg.conjugate(), evaluate=False)
        new_conj = conj.atoms(conjugate) - arg.atoms(conjugate)
        if new_conj and all(arg.has(i.args[0]) for i in new_conj):
            return
        if arg != conj and arg != -conj:
            ignore = arg.atoms(Abs)
            abs_free_arg = arg.xreplace({i: Dummy(real=True) for i in ignore})
            unk = [a for a in abs_free_arg.free_symbols if a.is_real is None]
            if not unk or not all(conj.has(conjugate(u)) for u in unk):
                return sqrt(expand_mul(arg*conj))
예제 #51
0
 def _eval_rewrite_as_tractable(self, arg, **kwargs):
     return (exp(arg) - exp(-arg)) / 2
예제 #52
0
def test_ContinuousMarkovChain():
    T1 = Matrix([[S(-2), S(2), S.Zero], [S.Zero, S.NegativeOne, S.One],
                 [Rational(3, 2), Rational(3, 2),
                  S(-3)]])
    C1 = ContinuousMarkovChain('C', [0, 1, 2], T1)
    assert C1.limiting_distribution() == ImmutableMatrix(
        [[Rational(3, 19), Rational(12, 19),
          Rational(4, 19)]])

    T2 = Matrix([[-S.One, S.One, S.Zero], [S.One, -S.One, S.Zero],
                 [S.Zero, S.One, -S.One]])
    C2 = ContinuousMarkovChain('C', [0, 1, 2], T2)
    A, t = C2.generator_matrix, symbols('t', positive=True)
    assert C2.transition_probabilities(A)(t) == Matrix(
        [[S.Half + exp(-2 * t) / 2, S.Half - exp(-2 * t) / 2, 0],
         [S.Half - exp(-2 * t) / 2, S.Half + exp(-2 * t) / 2, 0],
         [
             S.Half - exp(-t) + exp(-2 * t) / 2, S.Half - exp(-2 * t) / 2,
             exp(-t)
         ]])
    with ignore_warnings(
            UserWarning):  ### TODO: Restore tests once warnings are removed
        assert P(Eq(C2(1), 1), Eq(C2(0), 1),
                 evaluate=False) == Probability(Eq(C2(1), 1), Eq(C2(0), 1))
    assert P(Eq(C2(1), 1), Eq(C2(0), 1)) == exp(-2) / 2 + S.Half
    assert P(
        Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 1),
        Eq(P(Eq(C2(1), 0)),
           S.Half)) == (Rational(1, 4) - exp(-2) / 4) * (exp(-2) / 2 + S.Half)
    assert P(
        Not(Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 2)) |
        (Eq(C2(1), 0) & Eq(C2(2), 1) & Eq(C2(3), 2)),
        Eq(P(Eq(C2(1), 0)), Rational(1, 4))
        & Eq(P(Eq(C2(1), 1)), Rational(1, 4))) is S.One
    assert E(C2(Rational(3, 2)),
             Eq(C2(0), 2)) == -exp(-3) / 2 + 2 * exp(Rational(-3, 2)) + S.Half
    assert variance(C2(Rational(3, 2)), Eq(
        C2(0),
        1)) == ((S.Half - exp(-3) / 2)**2 * (exp(-3) / 2 + S.Half) +
                (Rational(-1, 2) - exp(-3) / 2)**2 * (S.Half - exp(-3) / 2))
    raises(KeyError, lambda: P(Eq(C2(1), 0), Eq(P(Eq(C2(1), 1)), S.Half)))
    assert P(Eq(C2(1), 0), Eq(P(Eq(C2(5), 1)),
                              S.Half)) == Probability(Eq(C2(1), 0))
    TS1 = MatrixSymbol('G', 3, 3)
    CS1 = ContinuousMarkovChain('C', [0, 1, 2], TS1)
    A = CS1.generator_matrix
    assert CS1.transition_probabilities(A)(t) == exp(t * A)

    C3 = ContinuousMarkovChain(
        'C', [Symbol('0'), Symbol('1'), Symbol('2')], T2)
    assert P(Eq(C3(1), 1), Eq(C3(0), 1)) == exp(-2) / 2 + S.Half
    assert P(Eq(C3(1), Symbol('1')), Eq(C3(0),
                                        Symbol('1'))) == exp(-2) / 2 + S.Half

    #test probability queries
    G = Matrix([[-S(1), Rational(1, 10),
                 Rational(9, 10)], [Rational(2, 5), -S(1),
                                    Rational(3, 5)],
                [Rational(1, 2), Rational(1, 2), -S(1)]])
    C = ContinuousMarkovChain('C', state_space=[0, 1, 2], gen_mat=G)
    assert P(Eq(C(7.385), C(3.19)), Eq(C(0.862),
                                       0)).round(5) == Float(0.35469, 5)
    assert P(Gt(C(98.715), C(19.807)), Eq(C(11.314),
                                          2)).round(5) == Float(0.32452, 5)
    assert P(Le(C(5.9), C(10.112)), Eq(C(4), 1)).round(6) == Float(0.675214, 6)
    assert Float(P(Eq(C(7.32), C(2.91)), Eq(C(2.63), 1)),
                 14) == Float(1 - P(Ne(C(7.32), C(2.91)), Eq(C(2.63), 1)), 14)
    assert Float(P(Gt(C(3.36), C(1.101)), Eq(C(0.8), 2)),
                 14) == Float(1 - P(Le(C(3.36), C(1.101)), Eq(C(0.8), 2)), 14)
    assert Float(P(Lt(C(4.9), C(2.79)), Eq(C(1.61), 0)),
                 14) == Float(1 - P(Ge(C(4.9), C(2.79)), Eq(C(1.61), 0)), 14)
    assert P(Eq(C(5.243), C(10.912)), Eq(C(2.174),
                                         1)) == P(Eq(C(10.912), C(5.243)),
                                                  Eq(C(2.174), 1))
    assert P(Gt(C(2.344), C(9.9)), Eq(C(1.102),
                                      1)) == P(Lt(C(9.9), C(2.344)),
                                               Eq(C(1.102), 1))
    assert P(Ge(C(7.87), C(1.008)), Eq(C(0.153),
                                       1)) == P(Le(C(1.008), C(7.87)),
                                                Eq(C(0.153), 1))

    #test symbolic queries
    a, b, c, d = symbols('a b c d')
    query = P(Eq(C(a), b), Eq(C(c), d))
    assert query.subs({
        a: 3.65,
        b: 2,
        c: 1.78,
        d: 1
    }).evalf().round(10) == P(Eq(C(3.65), 2), Eq(C(1.78), 1)).round(10)
    query_gt = P(Gt(C(a), b), Eq(C(c), d))
    query_le = P(Le(C(a), b), Eq(C(c), d))
    assert query_gt.subs({
        a: 13.2,
        b: 0,
        c: 3.29,
        d: 2
    }).evalf() + query_le.subs({
        a: 13.2,
        b: 0,
        c: 3.29,
        d: 2
    }).evalf() == 1
    query_ge = P(Ge(C(a), b), Eq(C(c), d))
    query_lt = P(Lt(C(a), b), Eq(C(c), d))
    assert query_ge.subs({
        a: 7.43,
        b: 1,
        c: 1.45,
        d: 0
    }).evalf() + query_lt.subs({
        a: 7.43,
        b: 1,
        c: 1.45,
        d: 0
    }).evalf() == 1

    #test issue 20078
    assert (2 * C(1) + 3 * C(1)).simplify() == 5 * C(1)
    assert (2 * C(1) - 3 * C(1)).simplify() == -C(1)
    assert (2 * (0.25 * C(1))).simplify() == 0.5 * C(1)
    assert (2 * C(1) * 0.25 * C(1)).simplify() == 0.5 * C(1)**2
    assert (C(1)**2 + C(1)**3).simplify() == (C(1) + 1) * C(1)**2
예제 #53
0
 def _eval_rewrite_as_exp(self, arg, **kwargs):
     neg_exp, pos_exp = exp(-arg), exp(arg)
     return (pos_exp + neg_exp)/(pos_exp - neg_exp)
예제 #54
0
    def __new__(cls, expr, *args, **kwargs):
        expr = sympify(expr)

        if not args:
            if expr.is_Order:
                variables = expr.variables
                point = expr.point
            else:
                variables = list(expr.free_symbols)
                point = [S.Zero]*len(variables)
        else:
            args = list(args if is_sequence(args) else [args])
            variables, point = [], []
            if is_sequence(args[0]):
                for a in args:
                    v, p = list(map(sympify, a))
                    variables.append(v)
                    point.append(p)
            else:
                variables = list(map(sympify, args))
                point = [S.Zero]*len(variables)

        if not all(v.is_symbol for v in variables):
            raise TypeError('Variables are not symbols, got %s' % variables)

        if len(list(uniq(variables))) != len(variables):
            raise ValueError('Variables are supposed to be unique symbols, got %s' % variables)

        if expr.is_Order:
            expr_vp = dict(expr.args[1:])
            new_vp = dict(expr_vp)
            vp = dict(zip(variables, point))
            for v, p in vp.items():
                if v in new_vp.keys():
                    if p != new_vp[v]:
                        raise NotImplementedError(
                            "Mixing Order at different points is not supported.")
                else:
                    new_vp[v] = p
            if set(expr_vp.keys()) == set(new_vp.keys()):
                return expr
            else:
                variables = list(new_vp.keys())
                point = [new_vp[v] for v in variables]

        if expr is S.NaN:
            return S.NaN

        if any(x in p.free_symbols for x in variables for p in point):
            raise ValueError('Got %s as a point.' % point)

        if variables:
            if any(p != point[0] for p in point):
                raise NotImplementedError(
                    "Multivariable orders at different points are not supported.")
            if point[0] is S.Infinity:
                s = {k: 1/Dummy() for k in variables}
                rs = {1/v: 1/k for k, v in s.items()}
                ps = [S.Zero for p in point]
            elif point[0] is S.NegativeInfinity:
                s = {k: -1/Dummy() for k in variables}
                rs = {-1/v: -1/k for k, v in s.items()}
                ps = [S.Zero for p in point]
            elif point[0] is not S.Zero:
                s = {k: Dummy() + point[0] for k in variables}
                rs = {(v - point[0]).together(): k - point[0] for k, v in s.items()}
                ps = [S.Zero for p in point]
            else:
                s = ()
                rs = ()
                ps = list(point)

            expr = expr.subs(s)

            if expr.is_Add:
                expr = expr.factor()

            if s:
                args = tuple([r[0] for r in rs.items()])
            else:
                args = tuple(variables)

            if len(variables) > 1:
                # XXX: better way?  We need this expand() to
                # workaround e.g: expr = x*(x + y).
                # (x*(x + y)).as_leading_term(x, y) currently returns
                # x*y (wrong order term!).  That's why we want to deal with
                # expand()'ed expr (handled in "if expr.is_Add" branch below).
                expr = expr.expand()

            old_expr = None
            while old_expr != expr:
                old_expr = expr
                if expr.is_Add:
                    lst = expr.extract_leading_order(args)
                    expr = Add(*[f.expr for (e, f) in lst])

                elif expr:
                    try:
                        expr = expr.as_leading_term(*args)
                    except PoleError:
                        if isinstance(expr, Function) or\
                                all(isinstance(arg, Function) for arg in expr.args):
                            # It is not possible to simplify an expression
                            # containing only functions (which raise error on
                            # call to leading term) further
                            pass
                        else:
                            orders = []
                            pts = tuple(zip(args, ps))
                            for arg in expr.args:
                                try:
                                    lt = arg.as_leading_term(*args)
                                except PoleError:
                                    lt = arg
                                if lt not in args:
                                    order = Order(lt)
                                else:
                                    order = Order(lt, *pts)
                                orders.append(order)
                            if expr.is_Add:
                                new_expr = Order(Add(*orders), *pts)
                                if new_expr.is_Add:
                                    new_expr = Order(Add(*[a.expr for a in new_expr.args]), *pts)
                                expr = new_expr.expr
                            elif expr.is_Mul:
                                expr = Mul(*[a.expr for a in orders])
                            elif expr.is_Pow:
                                e = expr.exp
                                b = expr.base
                                expr = exp(e * log(b))

                    # It would probably be better to handle this somewhere
                    # else. This is needed for a testcase in which there is a
                    # symbol with the assumptions zero=True.
                    if expr.is_zero:
                        expr = S.Zero
                    else:
                        expr = expr.as_independent(*args, as_Add=False)[1]

                    expr = expand_power_base(expr)
                    expr = expand_log(expr)

                    if len(args) == 1:
                        # The definition of O(f(x)) symbol explicitly stated that
                        # the argument of f(x) is irrelevant.  That's why we can
                        # combine some power exponents (only "on top" of the
                        # expression tree for f(x)), e.g.:
                        # x**p * (-x)**q -> x**(p+q) for real p, q.
                        x = args[0]
                        margs = list(Mul.make_args(
                            expr.as_independent(x, as_Add=False)[1]))

                        for i, t in enumerate(margs):
                            if t.is_Pow:
                                b, q = t.args
                                if b in (x, -x) and q.is_real and not q.has(x):
                                    margs[i] = x**q
                                elif b.is_Pow and not b.exp.has(x):
                                    b, r = b.args
                                    if b in (x, -x) and r.is_real:
                                        margs[i] = x**(r*q)
                                elif b.is_Mul and b.args[0] is S.NegativeOne:
                                    b = -b
                                    if b.is_Pow and not b.exp.has(x):
                                        b, r = b.args
                                        if b in (x, -x) and r.is_real:
                                            margs[i] = x**(r*q)

                        expr = Mul(*margs)

            expr = expr.subs(rs)

        if expr.is_Order:
            expr = expr.expr

        if not expr.has(*variables) and not expr.is_zero:
            expr = S.One

        # create Order instance:
        vp = dict(zip(variables, point))
        variables.sort(key=default_sort_key)
        point = [vp[v] for v in variables]
        args = (expr,) + Tuple(*zip(variables, point))
        obj = Expr.__new__(cls, *args)
        return obj
예제 #55
0
def R_nl(n, l, r, Z=1):
    """
    Returns the Hydrogen radial wavefunction R_{nl}.

    Parameters
    ==========

    n : integer
        Principal Quantum Number which is
        an integer with possible values as 1, 2, 3, 4,...
    l : integer
        ``l`` is the Angular Momentum Quantum Number with
        values ranging from 0 to ``n-1``.
    r :
        Radial coordinate.
    Z :
        Atomic number (1 for Hydrogen, 2 for Helium, ...)

    Everything is in Hartree atomic units.

    Examples
    ========

    >>> from sympy.physics.hydrogen import R_nl
    >>> from sympy.abc import r, Z
    >>> R_nl(1, 0, r, Z)
    2*sqrt(Z**3)*exp(-Z*r)
    >>> R_nl(2, 0, r, Z)
    sqrt(2)*(-Z*r + 2)*sqrt(Z**3)*exp(-Z*r/2)/4
    >>> R_nl(2, 1, r, Z)
    sqrt(6)*Z*r*sqrt(Z**3)*exp(-Z*r/2)/12

    For Hydrogen atom, you can just use the default value of Z=1:

    >>> R_nl(1, 0, r)
    2*exp(-r)
    >>> R_nl(2, 0, r)
    sqrt(2)*(2 - r)*exp(-r/2)/4
    >>> R_nl(3, 0, r)
    2*sqrt(3)*(2*r**2/9 - 2*r + 3)*exp(-r/3)/27

    For Silver atom, you would use Z=47:

    >>> R_nl(1, 0, r, Z=47)
    94*sqrt(47)*exp(-47*r)
    >>> R_nl(2, 0, r, Z=47)
    47*sqrt(94)*(2 - 47*r)*exp(-47*r/2)/4
    >>> R_nl(3, 0, r, Z=47)
    94*sqrt(141)*(4418*r**2/9 - 94*r + 3)*exp(-47*r/3)/27

    The normalization of the radial wavefunction is:

    >>> from sympy import integrate, oo
    >>> integrate(R_nl(1, 0, r)**2 * r**2, (r, 0, oo))
    1
    >>> integrate(R_nl(2, 0, r)**2 * r**2, (r, 0, oo))
    1
    >>> integrate(R_nl(2, 1, r)**2 * r**2, (r, 0, oo))
    1

    It holds for any atomic number:

    >>> integrate(R_nl(1, 0, r, Z=2)**2 * r**2, (r, 0, oo))
    1
    >>> integrate(R_nl(2, 0, r, Z=3)**2 * r**2, (r, 0, oo))
    1
    >>> integrate(R_nl(2, 1, r, Z=4)**2 * r**2, (r, 0, oo))
    1

    """
    # sympify arguments
    n, l, r, Z = map(S, [n, l, r, Z])
    # radial quantum number
    n_r = n - l - 1
    # rescaled "r"
    a = 1 / Z  # Bohr radius
    r0 = 2 * r / (n * a)
    # normalization coefficient
    C = sqrt((S(2) / (n * a))**3 * factorial(n_r) / (2 * n * factorial(n + l)))
    # This is an equivalent normalization coefficient, that can be found in
    # some books. Both coefficients seem to be the same fast:
    # C =  S(2)/n**2 * sqrt(1/a**3 * factorial(n_r) / (factorial(n+l)))
    return C * r0**l * assoc_laguerre(n_r, 2 * l + 1, r0).expand() * exp(
        -r0 / 2)
예제 #56
0
def test_PoissonProcess():
    X = PoissonProcess("X", 3)
    assert X.state_space == S.Naturals0
    assert X.index_set == Interval(0, oo)
    assert X.lamda == 3

    t, d, x, y = symbols('t d x y', positive=True)
    assert isinstance(X(t), RandomIndexedSymbol)
    assert X.distribution(t) == PoissonDistribution(3 * t)
    raises(ValueError, lambda: PoissonProcess("X", -1))
    raises(NotImplementedError, lambda: X[t])
    raises(IndexError, lambda: X(-5))

    assert X.joint_distribution(X(2), X(3)) == JointDistributionHandmade(
        Lambda((X(2), X(3)), 6**X(2) * 9**X(3) * exp(-15) /
               (factorial(X(2)) * factorial(X(3)))))

    assert X.joint_distribution(4, 6) == JointDistributionHandmade(
        Lambda((X(4), X(6)), 12**X(4) * 18**X(6) * exp(-30) /
               (factorial(X(4)) * factorial(X(6)))))

    assert P(X(t) < 1) == exp(-3 * t)
    assert P(Eq(X(t), 0),
             Contains(t, Interval.Lopen(3, 5))) == exp(-6)  # exp(-2*lamda)
    res = P(Eq(X(t), 1), Contains(t, Interval.Lopen(3, 4)))
    assert res == 3 * exp(-3)

    # Equivalent to P(Eq(X(t), 1))**4 because of non-overlapping intervals
    assert P(
        Eq(X(t), 1) & Eq(X(d), 1) & Eq(X(x), 1) & Eq(X(y), 1),
        Contains(t, Interval.Lopen(0, 1))
        & Contains(d, Interval.Lopen(1, 2)) & Contains(x, Interval.Lopen(2, 3))
        & Contains(y, Interval.Lopen(3, 4))) == res**4

    # Return Probability because of overlapping intervals
    assert P(Eq(X(t), 2) & Eq(X(d), 3), Contains(t, Interval.Lopen(0, 2))
    & Contains(d, Interval.Ropen(2, 4))) == \
                Probability(Eq(X(d), 3) & Eq(X(t), 2), Contains(t, Interval.Lopen(0, 2))
                & Contains(d, Interval.Ropen(2, 4)))

    raises(ValueError, lambda: P(
        Eq(X(t), 2) & Eq(X(d), 3),
        Contains(t, Interval.Lopen(0, 4)) & Contains(d, Interval.Lopen(3, oo)))
           )  # no bound on d
    assert P(Eq(X(3), 2)) == 81 * exp(-9) / 2
    assert P(Eq(X(t), 2), Contains(t, Interval.Lopen(0,
                                                     5))) == 225 * exp(-15) / 2

    # Check that probability works correctly by adding it to 1
    res1 = P(X(t) <= 3, Contains(t, Interval.Lopen(0, 5)))
    res2 = P(X(t) > 3, Contains(t, Interval.Lopen(0, 5)))
    assert res1 == 691 * exp(-15)
    assert (res1 + res2).simplify() == 1

    # Check Not and  Or
    assert P(Not(Eq(X(t), 2) & (X(d) > 3)), Contains(t, Interval.Ropen(2, 4)) & \
            Contains(d, Interval.Lopen(7, 8))).simplify() == -18*exp(-6) + 234*exp(-9) + 1
    assert P(Eq(X(t), 2) | Ne(X(t), 4),
             Contains(t, Interval.Ropen(2, 4))) == 1 - 36 * exp(-6)
    raises(ValueError, lambda: P(X(t) > 2, X(t) + X(d)))
    assert E(
        X(t)) == 3 * t  # property of the distribution at a given timestamp
    assert E(
        X(t)**2 + X(d) * 2 + X(y)**3,
        Contains(t, Interval.Lopen(0, 1))
        & Contains(d, Interval.Lopen(1, 2))
        & Contains(y, Interval.Ropen(3, 4))) == 75
    assert E(X(t)**2, Contains(t, Interval.Lopen(0, 1))) == 12
    assert E(x*(X(t) + X(d))*(X(t)**2+X(d)**2), Contains(t, Interval.Lopen(0, 1))
    & Contains(d, Interval.Ropen(1, 2))) == \
            Expectation(x*(X(d) + X(t))*(X(d)**2 + X(t)**2), Contains(t, Interval.Lopen(0, 1))
            & Contains(d, Interval.Ropen(1, 2)))

    # Value Error because of infinite time bound
    raises(ValueError, lambda: E(X(t)**3, Contains(t, Interval.Lopen(1, oo))))

    # Equivalent to E(X(t)**2) - E(X(d)**2) == E(X(1)**2) - E(X(1)**2) == 0
    assert E((X(t) + X(d)) * (X(t) - X(d)),
             Contains(t, Interval.Lopen(0, 1))
             & Contains(d, Interval.Lopen(1, 2))) == 0
    assert E(X(2) + x * E(X(5))) == 15 * x + 6
    assert E(x * X(1) + y) == 3 * x + y
    assert P(Eq(X(1), 2) & Eq(X(t), 3),
             Contains(t, Interval.Lopen(1, 2))) == 81 * exp(-6) / 4
    Y = PoissonProcess("Y", 6)
    Z = X + Y
    assert Z.lamda == X.lamda + Y.lamda == 9
    raises(ValueError,
           lambda: X + 5)  # should be added be only PoissonProcess instance
    N, M = Z.split(4, 5)
    assert N.lamda == 4
    assert M.lamda == 5
    raises(ValueError, lambda: Z.split(3, 2))  # 2+3 != 9

    raises(
        ValueError, lambda: P(Eq(X(t), 0),
                              Contains(t, Interval.Lopen(1, 3)) & Eq(X(1), 0)))
    # check if it handles queries with two random variables in one args
    res1 = P(Eq(N(3), N(5)))
    assert res1 == P(Eq(N(t), 0), Contains(t, Interval(3, 5)))
    res2 = P(N(3) > N(1))
    assert res2 == P((N(t) > 0), Contains(t, Interval(1, 3)))
    assert P(N(3) < N(1)) == 0  # condition is not possible
    res3 = P(N(3) <= N(1))  # holds only for Eq(N(3), N(1))
    assert res3 == P(Eq(N(t), 0), Contains(t, Interval(1, 3)))

    # tests from https://www.probabilitycourse.com/chapter11/11_1_2_basic_concepts_of_the_poisson_process.php
    X = PoissonProcess('X', 10)  # 11.1
    assert P(Eq(X(S(1) / 3), 3)
             & Eq(X(1), 10)) == exp(-10) * Rational(8000000000, 11160261)
    assert P(Eq(X(1), 1), Eq(X(S(1) / 3), 3)) == 0
    assert P(Eq(X(1), 10), Eq(X(S(1) / 3), 3)) == P(Eq(X(S(2) / 3), 7))

    X = PoissonProcess('X', 2)  # 11.2
    assert P(X(S(1) / 2) < 1) == exp(-1)
    assert P(X(3) < 1, Eq(X(1), 0)) == exp(-4)
    assert P(Eq(X(4), 3), Eq(X(2), 3)) == exp(-4)

    X = PoissonProcess('X', 3)
    assert P(Eq(X(2), 5) & Eq(X(1), 2)) == Rational(81, 4) * exp(-6)

    # check few properties
    assert P(
        X(2) <= 3,
        X(1) >= 1) == 3 * P(Eq(X(1), 0)) + 2 * P(Eq(X(1), 1)) + P(Eq(X(1), 2))
    assert P(X(2) <= 3, X(1) > 1) == 2 * P(Eq(X(1), 0)) + 1 * P(Eq(X(1), 1))
    assert P(Eq(X(2), 5) & Eq(X(1), 2)) == P(Eq(X(1), 3)) * P(Eq(X(1), 2))
    assert P(Eq(X(3), 4), Eq(X(1), 3)) == P(Eq(X(2), 1))

    #test issue 20078
    assert (2 * X(t) + 3 * X(t)).simplify() == 5 * X(t)
    assert (2 * X(t) - 3 * X(t)).simplify() == -X(t)
    assert (2 * (0.25 * X(t))).simplify() == 0.5 * X(t)
    assert (2 * X(t) * 0.25 * X(t)).simplify() == 0.5 * X(t)**2
    assert (X(t)**2 + X(t)**3).simplify() == (X(t) + 1) * X(t)**2
예제 #57
0
 def _characteristic_function(self, t):
     a = self.a
     return a**2 * exp(I * t) / ((1 + (a - 1) * exp(I * t))**2)
예제 #58
0
 def _moment_generating_function(self, t):
     a = self.a
     return a**2 * exp(t) / ((1 + (a - 1) * exp(t))**2)
예제 #59
0
 def _eval_rewrite_as_tractable(self, z, **kwargs):
     return exp(loggamma(z))
 def _eval_expand_func(self, **hints):
     n, m, theta, phi = self.args
     rv = (sqrt((2*n + 1)/(4*pi) * factorial(n - m)/factorial(n + m)) *
             exp(I*m*phi) * assoc_legendre(n, m, cos(theta)))
     # We can do this because of the range of theta
     return rv.subs(sqrt(-cos(theta)**2 + 1), sin(theta))