Пример #1
0
def mrv(e, x):
    """Returns a SubsSet of most rapidly varying (mrv) subexpressions of 'e',
       and e rewritten in terms of these"""
    e = powsimp(e, deep=True, combine='exp')
    assert isinstance(e, Basic)
    if not e.has(x):
        return SubsSet(), e
    elif e == x:
        s = SubsSet()
        return s, s[x]
    elif e.is_Mul or e.is_Add:
        i, d = e.as_independent(x)  # throw away x-independent terms
        if d.func != e.func:
            s, expr = mrv(d, x)
            return s, e.func(i, expr)
        a, b = d.as_two_terms()
        s1, e1 = mrv(a, x)
        s2, e2 = mrv(b, x)
        return mrv_max1(s1, s2, e.func(i, e1, e2), x)
    elif e.is_Pow:
        b, e = e.as_base_exp()
        if e.has(x):
            return mrv(exp(e * log(b)), x)
        else:
            s, expr = mrv(b, x)
            return s, expr**e
    elif e.func is log:
        s, expr = mrv(e.args[0], x)
        return s, log(expr)
    elif e.func is exp:
        # We know from the theory of this algorithm that exp(log(...)) may always
        # be simplified here, and doing so is vital for termination.
        if e.args[0].func is log:
            return mrv(e.args[0].args[0], x)
        if limitinf(e.args[0], x).is_unbounded:
            s1 = SubsSet()
            e1 = s1[e]
            s2, e2 = mrv(e.args[0], x)
            su = s1.union(s2)[0]
            su.rewrites[e1] = exp(e2)
            return mrv_max3(s1, e1, s2, exp(e2), su, e1, x)
        else:
            s, expr = mrv(e.args[0], x)
            return s, exp(expr)
    elif e.is_Function:
        l = [mrv(a, x) for a in e.args]
        l2 = [s for (s, _) in l if s != SubsSet()]
        if len(l2) != 1:
            # e.g. something like BesselJ(x, x)
            raise NotImplementedError("MRV set computation for functions in"
                                      " several variables not implemented.")
        s, ss = l2[0], SubsSet()
        args = [ss.do_subs(x[1]) for x in l]
        return s, e.func(*args)
    elif e.is_Derivative:
        raise NotImplementedError("MRV set computation for derviatives"
                                  " not implemented yet.")
        return mrv(e.args[0], x)
    raise NotImplementedError(
        "Don't know how to calculate the mrv of '%s'" % e)
Пример #2
0
def test_functions_basic():
    assert oclcode(abs(i)) == "abs(i)"
    assert oclcode(abs(x)) == "fabs(x)"
    assert oclcode(log(x)) == "log(x)"
    assert oclcode(log(x, 2)) == "log2(x)"
    assert oclcode(log(x, 10)) == "log10(x)"
    assert oclcode(log(x, 3)) == "log(x)/log(3)"
Пример #3
0
def _generate_patterns():
    """
    Generates patterns for transcendental equations.

    This is lazily calculated (called) in the tsolve() function and stored in
    the patterns global variable.
    """

    tmp1 = _f ** (_h-(_c*_g/_b))
    tmp2 = (-_e*tmp1/_a)**(1/_d)
    global _patterns
    _patterns = [
        (_a*(_b*_x+_c)**_d + _e   ,
            ((-(_e/_a))**(1/_d)-_c)/_b),
        (_b+_c*exp(_d*_x+_e) ,
            (log(-_b/_c)-_e)/_d),
        (_a*_x+_b+_c*exp(_d*_x+_e) ,
            -_b/_a-LambertW(_c*_d*exp(_e-_b*_d/_a)/_a)/_d),
        (_b+_c*_f**(_d*_x+_e) ,
            (log(-_b/_c)-_e*log(_f))/_d/log(_f)),
        (_a*_x+_b+_c*_f**(_d*_x+_e) ,
            -_b/_a-LambertW(_c*_d*_f**(_e-_b*_d/_a)*log(_f)/_a)/_d/log(_f)),
        (_b+_c*log(_d*_x+_e) ,
            (exp(-_b/_c)-_e)/_d),
        (_a*_x+_b+_c*log(_d*_x+_e) ,
            -_e/_d+_c/_a*LambertW(_a/_c/_d*exp(-_b/_c+_a*_e/_c/_d))),
        (_a*(_b*_x+_c)**_d + _e*_f**(_g*_x+_h) ,
            -_c/_b-_d*LambertW(-tmp2*_g*log(_f)/_b/_d)/_g/log(_f))
    ]
Пример #4
0
def test_2():
    test = [
        [(a + b*x)/x, x, S(2), b*x + a*log(x)],
        [x**S(5)/(a + b*x), x, S(2), a**S(4)*x/b**S(5) - S(1)/S(2)*a**S(3)*x**S(2)/b**S(4) + S(1)/S(3)*a**S(2)*x**S(3)/b**S(3) - S(1)/S(4)*a*x**S(4)/b**S(2) + S(1)/S(5)*x**S(5)/b - a**S(5)*log(a + b*x)/b**S(6)],
        [S(1)/(a + b*x)**S(2), x, S(1), ( - S(1))/(b*(a + b*x))],
        [S(1)/(x*(a + b*x)**S(3)), x, S(2), S(1)/S(2)/(a*(a + b*x)**S(2)) + S(1)/(a**S(2)*(a + b*x)) + log(x)/a**S(3) - log(a + b*x)/a**S(3)],
        [S(1)/(S(2) + S(2)*x), x, S(1), S(1)/S(2)*log(S(1) + x)],
        [S(1)/(x*(S(1) + b*x)), x, S(3), log(x) - log(S(1) + b*x)],
        [x**S(3)*sqrt(a + b*x), x, S(2), - S(2)/S(3)*a**S(3)*(a + b*x)**(S(3)/S(2))/b**S(4) + S(6)/S(5)*a**S(2)*(a + b*x)**(S(5)/S(2))/b**S(4) - S(6)/S(7)*a*(a + b*x)**(S(7)/S(2))/b**S(4) + S(2)/S(9)*(a + b*x)**(S(9)/S(2))/b**S(4)],
        [(a + b*x)**(S(3)/S(2)), x, S(1), S(2)/S(5)*(a + b*x)**(S(5)/S(2))/b],
        [x**S(4)/sqrt(a + b*x), x, S(2), - S(8)/S(3)*a**S(3)*(a + b*x)**(S(3)/S(2))/b**S(5) + S(12)/S(5)*a**S(2)*(a + b*x)**(S(5)/S(2))/b**S(5) - S(8)/S(7)*a*(a + b*x)**(S(7)/S(2))/b**S(5) + S(2)/S(9)*(a + b*x)**(S(9)/S(2))/b**S(5) + S(2)*a**S(4)*sqrt(a + b*x)/b**S(5)],
        [S(1)/sqrt(a + b*x), x, S(1), S(2)*sqrt(a + b*x)/b],
        [S(1)/(x*(a + b*x)**(S(3)/S(2))), x, S(3), - S(2)*arctanh(sqrt(a + b*x)/sqrt(a))/a**(S(3)/S(2)) + S(2)/(a*sqrt(a + b*x))],
        [S(1)/(x**S(2)*( - a + b*x)**(S(3)/S(2))), x, S(4), - S(3)*b*arctan(sqrt( - a + b*x)/sqrt(a))/a**(S(5)/S(2)) + ( - S(2))/(a*x*sqrt( - a + b*x)) - S(3)*sqrt( - a + b*x)/(a**S(2)*x)],
        [x**S(3)*(a + b*x)**(S(1)/S(3)), x, S(2), - S(3)/S(4)*a**S(3)*(a + b*x)**(S(4)/S(3))/b**S(4) + S(9)/S(7)*a**S(2)*(a + b*x)**(S(7)/S(3))/b**S(4) - S(9)/S(10)*a*(a + b*x)**(S(10)/S(3))/b**S(4) + S(3)/S(13)*(a + b*x)**(S(13)/S(3))/b**S(4)],
        [x**S(2)*(a + b*x)**(S(2)/S(3)), x, S(2), S(3)/S(5)*a**S(2)*(a + b*x)**(S(5)/S(3))/b**S(3) - S(3)/S(4)*a*(a + b*x)**(S(8)/S(3))/b**S(3) + S(3)/S(11)*(a + b*x)**(S(11)/S(3))/b**S(3)],
        [x**S(2)/(a + b*x)**(S(1)/S(3)), x, S(2), S(3)/S(2)*a**S(2)*(a + b*x)**(S(2)/S(3))/b**S(3) - S(6)/S(5)*a*(a + b*x)**(S(5)/S(3))/b**S(3) + S(3)/S(8)*(a + b*x)**(S(8)/S(3))/b**S(3)],
        [x**S(3)/( - a + b*x)**(S(1)/S(3)), x, S(2), S(3)/S(2)*a**S(3)*( - a + b*x)**(S(2)/S(3))/b**S(4) + S(9)/S(5)*a**S(2)*( - a + b*x)**(S(5)/S(3))/b**S(4) + S(9)/S(8)*a*( - a + b*x)**(S(8)/S(3))/b**S(4) + S(3)/S(11)*( - a + b*x)**(S(11)/S(3))/b**S(4)],
    ]

    for i in test:
        r = rubi_integrate(i[0], i[1])
        if len(i) == 5:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True) or rubi_test(r, i[1], i[4], expand=True, _diff=True)
        else:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True)
Пример #5
0
def test_log():
    R, x = ring('x', QQ)
    p = 1 + x
    p1 = rs_log(p, x, 4)/x**2
    assert p1 == S(1)/3*x - S(1)/2 + x**(-1)
    p = 1 + x +2*x**2/3
    p1 = rs_log(p, x, 9)
    assert p1 == -17*x**8/648 + 13*x**7/189 - 11*x**6/162 - x**5/45 + \
      7*x**4/36 - x**3/3 + x**2/6 + x
    p2 = rs_series_inversion(p, x, 9)
    p3 = rs_log(p2, x, 9)
    assert p3 == -p1

    R, x, y = ring('x, y', QQ)
    p = 1 + x + 2*y*x**2
    p1 = rs_log(p, x, 6)
    assert p1 == (4*x**5*y**2 - 2*x**5*y - 2*x**4*y**2 + x**5/5 + 2*x**4*y -
                  x**4/4 - 2*x**3*y + x**3/3 + 2*x**2*y - x**2/2 + x)

    # Constant term in series
    a = symbols('a')
    R, x, y = ring('x, y', EX)
    assert rs_log(x + a, x, 5) == -EX(1/(4*a**4))*x**4 + EX(1/(3*a**3))*x**3 \
        - EX(1/(2*a**2))*x**2 + EX(1/a)*x + EX(log(a))
    assert rs_log(x + x**2*y + a, x, 4) == -EX(a**(-2))*x**3*y + \
        EX(1/(3*a**3))*x**3 + EX(1/a)*x**2*y - EX(1/(2*a**2))*x**2 + \
        EX(1/a)*x + EX(log(a))

    p = x + x**2 + 3
    assert rs_log(p, x, 10).compose(x, 5) == EX(log(3) + S(19281291595)/9920232)
Пример #6
0
    def dig(self):
        """ Number of decimal digits that are guaranteed to be preserved in text.

        When converting text -> float -> text, you are guaranteed that at least ``dig``
        number of digits are preserved with respect to rounding or overflow.
        """
        from sympy.functions import floor, log
        return floor(self.nmant * log(2)/log(10))
Пример #7
0
def compare(a,b,x):
    """Returns "<" if a<b, "=" for a==b, ">" for a>b"""
    c = limitinf(log(a)/log(b), x)
    if c == 0:
        return "<"
    elif c in [oo,-oo]:
        return ">"
    else:
        return "="
Пример #8
0
    def decimal_dig(self):
        """ Number of digits needed to store & load without loss.

        Number of decimal digits needed to guarantee that two consecutive conversions
        (float -> text -> float) to be idempotent. This is useful when one do not want
        to loose precision due to rounding errors when storing a floating point value
        as text.
        """
        from sympy.functions import ceiling, log
        return ceiling((self.nmant + 1) * log(2)/log(10) + 1)
Пример #9
0
def test_trigintegrate_mixed():
    assert trigintegrate(sin(x)*sec(x), x) == -log(sin(x)**2 - 1)/2
    assert trigintegrate(sin(x)*csc(x), x) == x
    assert trigintegrate(sin(x)*cot(x), x) == sin(x)

    assert trigintegrate(cos(x)*sec(x), x) == x
    assert trigintegrate(cos(x)*csc(x), x) == log(cos(x)**2 - 1)/2
    assert trigintegrate(cos(x)*tan(x), x) == -cos(x)
    assert trigintegrate(cos(x)*cot(x), x) == log(cos(x) - 1)/2 \
        - log(cos(x) + 1)/2 + cos(x)
Пример #10
0
def rs_log(p, x, prec):
    """
    The Logarithm of ``p`` modulo ``O(x**prec)``

    Notes
    =====

    truncation of ``integral dx p**-1*d p/dx`` is used.

    Examples
    ========

    >>> from sympy.polys.domains import QQ
    >>> from sympy.polys.rings import ring
    >>> from sympy.polys.ring_series import rs_log
    >>> R, x = ring('x', QQ)
    >>> rs_log(1 + x, x, 8)
    1/7*x**7 - 1/6*x**6 + 1/5*x**5 - 1/4*x**4 + 1/3*x**3 - 1/2*x**2 + x
    >>> rs_log(x**QQ(3, 2) + 1, x, 5)
    1/3*x**(9/2) - 1/2*x**3 + x**(3/2)
    """
    if rs_is_puiseux(p, x):
        return rs_puiseux(rs_log, p, x, prec)
    R = p.ring
    if p == 1:
        return R.zero
    if _has_constant_term(p, x):
        const = 0
        zm = R.zero_monom
        c = p[zm]
        if c == 1:
            pass
        else:
            c_expr = c.as_expr()
            if R.domain is EX:
                const = log(c_expr)
            elif isinstance(c, PolyElement):
                try:
                    const = R(log(c_expr))
                except ValueError:
                    raise DomainError("The given series can't be expanded in "
                                      "this domain.")
            else:
                try:
                    const = R(log(c))
                except ValueError:
                    raise DomainError("The given series can't be expanded in "
                                      "this domain.")

        dlog = p.diff(x)
        dlog = rs_mul(dlog, _series_inversion1(p, x, prec), x, prec - 1)
        return rs_integrate(dlog, x) + const
    else:
        raise NotImplementedError
Пример #11
0
def test_variable_moment():
    E = Symbol('E')
    I = Symbol('I')

    b = Beam(4, E, 2*(4 - x))
    b.apply_load(20, 4, -1)
    R, M = symbols('R, M')
    b.apply_load(R, 0, -1)
    b.apply_load(M, 0, -2)
    b.bc_deflection = [(0, 0)]
    b.bc_slope = [(0, 0)]
    b.solve_for_reaction_loads(R, M)
    assert b.slope().expand() == ((10*x*SingularityFunction(x, 0, 0)
        - 10*(x - 4)*SingularityFunction(x, 4, 0))/E).expand()
    assert b.deflection().expand() == ((5*x**2*SingularityFunction(x, 0, 0)
        - 10*Piecewise((0, Abs(x)/4 < 1), (16*meijerg(((3, 1), ()), ((), (2, 0)), x/4), True))
        + 40*SingularityFunction(x, 4, 1))/E).expand()

    b = Beam(4, E - x, I)
    b.apply_load(20, 4, -1)
    R, M = symbols('R, M')
    b.apply_load(R, 0, -1)
    b.apply_load(M, 0, -2)
    b.bc_deflection = [(0, 0)]
    b.bc_slope = [(0, 0)]
    b.solve_for_reaction_loads(R, M)
    assert b.slope().expand() == ((-80*(-log(-E) + log(-E + x))*SingularityFunction(x, 0, 0)
        + 80*(-log(-E + 4) + log(-E + x))*SingularityFunction(x, 4, 0) + 20*(-E*log(-E)
        + E*log(-E + x) + x)*SingularityFunction(x, 0, 0) - 20*(-E*log(-E + 4) + E*log(-E + x)
        + x - 4)*SingularityFunction(x, 4, 0))/I).expand()
Пример #12
0
def test_rubi_integrate():
    assert rubi_integrate(x, x) == x**2/2
    assert rubi_integrate(x**a, x) == x**(a + S(1))/(a + S(1))
    assert rubi_integrate(S(1)/x, x) == log(x)
    assert rubi_integrate(a*x, x) == a*(S(1)/S(2))*x**S(2)
    assert rubi_integrate(1/(x**2*(a + b*x)**2), x) == -b/(a**2*(a + b*x)) - 1/(a**2*x) - 2*b*log(x)/a**3 + 2*b*log(a + b*x)/a**3
    assert rubi_integrate(x**6/(a + b*x)**2, x) == (-a**6/(b**7*(a + b*x)) - S(6)*a**5*log(a + b*x)/b**7 + 5*a**4*x/b**6 - S(2)*a**3*x**2/b**5 + a**2*x**3/b**4 - a*x**4/(S(2)*b**3) + x**5/(S(5)*b**2))
    assert rubi_integrate(1/(x**2*(a + b*x)**2), x) == -b/(a**2*(a + b*x)) - 1/(a**2*x) - 2*b*log(x)/a**3 + 2*b*log(a + b*x)/a**3
    assert rubi_integrate(a + S(1)/x, x) == a*x + log(x)
    assert rubi_integrate((a + b*x)**2/x**3, x) == -a**2/(2*x**2) - 2*a*b/x + b**2*log(x)
    assert rubi_integrate(a**3*x, x) == S(1)/S(2)*a**3*x**2
    assert rubi_integrate((a + b*x)**3/x**3, x) == -a**3/(2*x**2) - 3*a**2*b/x + 3*a*b**2*log(x) + b**3*x
    assert rubi_integrate(x**3*(a + b*x), x) == a*x**4/4 + b*x**5/5
    assert rubi_integrate((b*x)**m*(d*x + 2)**n, x) == 2**n*(b*x)**(m + 1)*hyper((-n, m + 1), (m + 2,), -d*x/2)/(b*(m + 1))
    assert rubi_test(rubi_integrate(1/(1 + x**5), x), x, log(x + S(1))/S(5) + S(2)*Sum(-log((S(2)*x - S(2)*cos(pi*(S(2)*k/S(5) + S(-1)/5)))**S(2) - S(4)*sin(S(2)*pi*k/S(5) + S(3)*pi/S(10))**S(2) + S(4))*cos(pi*(S(2)*k/S(5) + S(-1)/5))/S(2) - (-S(2)*cos(pi*(S(2)*k/S(5) + S(-1)/5))**S(2) + S(2))*atan((-x/cos(pi*(S(2)*k/S(5) + S(-1)/5)) + S(1))/sqrt(-(cos(S(2)*pi*k/S(5) - pi/S(5)) + S(-1))*(cos(S(2)*pi*k/S(5) - pi/S(5)) + S(1))/cos(S(2)*pi*k/S(5) - pi/S(5))**S(2)))/(S(2)*sqrt(-(cos(S(2)*pi*k/S(5) - pi/S(5)) + S(-1))*(cos(S(2)*pi*k/S(5) - pi/S(5)) + S(1))/cos(S(2)*pi*k/S(5) - pi/S(5))**S(2))*cos(pi*(S(2)*k/S(5) + S(-1)/5))), (k, S(1), S(2)))/S(5), _numerical=True)
Пример #13
0
def test_bounded():
    x, y = symbols('x,y')
    assert ask(Q.bounded(x)) == False
    assert ask(Q.bounded(x), Q.bounded(x)) == True
    assert ask(Q.bounded(x), Q.bounded(y)) == False
    assert ask(Q.bounded(x), Q.complex(x)) == False

    assert ask(Q.bounded(x+1)) == False
    assert ask(Q.bounded(x+1), Q.bounded(x)) == True
    assert ask(Q.bounded(x+y)) == None
    assert ask(Q.bounded(x+y), Q.bounded(x)) == False
    assert ask(Q.bounded(x+1), Q.bounded(x) & Q.bounded(y)) == True

    assert ask(Q.bounded(2*x)) == False
    assert ask(Q.bounded(2*x), Q.bounded(x)) == True
    assert ask(Q.bounded(x*y)) == None
    assert ask(Q.bounded(x*y), Q.bounded(x)) == False
    assert ask(Q.bounded(x*y), Q.bounded(x) & Q.bounded(y)) == True

    assert ask(Q.bounded(x**2)) == False
    assert ask(Q.bounded(2**x)) == False
    assert ask(Q.bounded(2**x), Q.bounded(x)) == True
    assert ask(Q.bounded(x**x)) == False
    assert ask(Q.bounded(Rational(1,2) ** x)) == None
    assert ask(Q.bounded(Rational(1,2) ** x), Q.positive(x)) == True
    assert ask(Q.bounded(Rational(1,2) ** x), Q.negative(x)) == False
    assert ask(Q.bounded(sqrt(x))) == False

    # sign function
    assert ask(Q.bounded(sign(x))) == True
    assert ask(Q.bounded(sign(x)), ~Q.bounded(x)) == True

    # exponential functions
    assert ask(Q.bounded(log(x))) == False
    assert ask(Q.bounded(log(x)), Q.bounded(x)) == True
    assert ask(Q.bounded(exp(x))) == False
    assert ask(Q.bounded(exp(x)), Q.bounded(x)) == True
    assert ask(Q.bounded(exp(2))) == True

    # trigonometric functions
    assert ask(Q.bounded(sin(x))) == True
    assert ask(Q.bounded(sin(x)), ~Q.bounded(x)) == True
    assert ask(Q.bounded(cos(x))) == True
    assert ask(Q.bounded(cos(x)), ~Q.bounded(x)) == True
    assert ask(Q.bounded(2*sin(x))) == True
    assert ask(Q.bounded(sin(x)**2)) == True
    assert ask(Q.bounded(cos(x)**2)) == True
    assert ask(Q.bounded(cos(x) + sin(x))) == True
Пример #14
0
def test_bounded():
    x, y = symbols('xy')
    assert ask(x, Q.bounded) == False
    assert ask(x, Q.bounded, Assume(x, Q.bounded)) == True
    assert ask(x, Q.bounded, Assume(y, Q.bounded)) == False
    assert ask(x, Q.bounded, Assume(x, Q.complex)) == False

    assert ask(x+1, Q.bounded) == False
    assert ask(x+1, Q.bounded, Assume(x, Q.bounded)) == True
    assert ask(x+y, Q.bounded) == None
    assert ask(x+y, Q.bounded, Assume(x, Q.bounded)) == False
    assert ask(x+1, Q.bounded, Assume(x, Q.bounded) & \
                Assume(y, Q.bounded)) == True

    assert ask(2*x, Q.bounded) == False
    assert ask(2*x, Q.bounded, Assume(x, Q.bounded)) == True
    assert ask(x*y, Q.bounded) == None
    assert ask(x*y, Q.bounded, Assume(x, Q.bounded)) == False
    assert ask(x*y, Q.bounded, Assume(x, Q.bounded) & \
                Assume(y, Q.bounded)) == True

    assert ask(x**2, Q.bounded) == False
    assert ask(2**x, Q.bounded) == False
    assert ask(2**x, Q.bounded, Assume(x, Q.bounded)) == True
    assert ask(x**x, Q.bounded) == False
    assert ask(Rational(1,2) ** x, Q.bounded) == True
    assert ask(x ** Rational(1,2), Q.bounded) == False

    # sign function
    assert ask(sign(x), Q.bounded) == True
    assert ask(sign(x), Q.bounded, Assume(x, Q.bounded, False)) == True

    # exponential functions
    assert ask(log(x), Q.bounded) == False
    assert ask(log(x), Q.bounded, Assume(x, Q.bounded)) == True
    assert ask(exp(x), Q.bounded) == False
    assert ask(exp(x), Q.bounded, Assume(x, Q.bounded)) == True
    assert ask(exp(2), Q.bounded) == True

    # trigonometric functions
    assert ask(sin(x), Q.bounded) == True
    assert ask(sin(x), Q.bounded, Assume(x, Q.bounded, False)) == True
    assert ask(cos(x), Q.bounded) == True
    assert ask(cos(x), Q.bounded, Assume(x, Q.bounded, False)) == True
    assert ask(2*sin(x), Q.bounded) == True
    assert ask(sin(x)**2, Q.bounded) == True
    assert ask(cos(x)**2, Q.bounded) == True
    assert ask(cos(x) + sin(x), Q.bounded) == True
Пример #15
0
def mrv_leadterm(e, x, Omega=[]):
    """Returns (c0, e0) for e."""
    if not e.has(x):
        return (e, S.Zero)
    Omega = [t for t in Omega if subexp(e, t)]
    if Omega == []:
        Omega = mrv(e, x)
    if not Omega:
        # e really does not depend on x after simplification
        series = calculate_series(e, x)
        c0, e0 = series.leadterm(x)
        assert e0 == 0
        return c0, e0
    if x in set(Omega):
        # move the whole omega up (exponentiate each term):
        Omega_up = set(moveup(Omega, x))
        e_up = moveup([e], x)[0]
        # calculate the lead term
        mrv_leadterm_up = mrv_leadterm(e_up, x, Omega_up)
        # move the result (c0, e0) down
        return tuple(movedown(mrv_leadterm_up, x))
    #
    # The positive dummy, w, is used here so log(w*2) etc. will expand;
    # a unique dummy is needed in this algorithm
    #
    # For limits of complex functions, the algorithm would have to be
    # improved, or just find limits of Re and Im components separately.
    #
    w = Dummy("w", real=True, positive=True)
    f, logw = rewrite(e, set(Omega), x, w)
    series = calculate_series(f, w)
    series = series.subs(log(w), logw)
    return series.leadterm(w)
Пример #16
0
def mrv_leadterm(e, x):
    """Returns (c0, e0) for e."""
    Omega = SubsSet()
    if not e.has(x):
        return (e, S.Zero)
    if Omega == SubsSet():
        Omega, exps = mrv(e, x)
    if not Omega:
        # e really does not depend on x after simplification
        series = calculate_series(e, x)
        c0, e0 = series.leadterm(x)
        assert e0 == 0
        return c0, e0
    if x in Omega:
        #move the whole omega up (exponentiate each term):
        Omega_up = moveup2(Omega, x)
        e_up = moveup([e], x)[0]
        exps_up = moveup([exps], x)[0]
        # NOTE: there is no need to move this down!
        e = e_up
        Omega = Omega_up
        exps = exps_up
    #
    # The positive dummy, w, is used here so log(w*2) etc. will expand;
    # a unique dummy is needed in this algorithm
    #
    # For limits of complex functions, the algorithm would have to be
    # improved, or just find limits of Re and Im components separately.
    #
    w = Dummy("w", real=True, positive=True, bounded=True)
    f, logw = rewrite(exps, Omega, x, w)
    series = calculate_series(f, w, logx=logw)
    series = series.subs(log(w), logw) # this should not be necessary
    return series.leadterm(w)
Пример #17
0
def compare(a, b, x):
    """Returns "<" if a<b, "=" for a == b, ">" for a>b"""
    # log(exp(...)) must always be simplified here for termination
    la, lb = log(a), log(b)
    if isinstance(a, Basic) and a.func is exp:
        la = a.args[0]
    if isinstance(b, Basic) and b.func is exp:
        lb = b.args[0]

    c = limitinf(la/lb, x)
    if c == 0:
        return "<"
    elif c.is_unbounded:
        return ">"
    else:
        return "="
Пример #18
0
def mrv(e, x):
    "Returns a python set of  most rapidly varying (mrv) subexpressions of 'e'"
    assert isinstance(e, Basic)
    if not e.has(x):
        return set([])
    elif e == x:
        return set([x])
    elif e.is_Mul:
        a, b = e.as_two_terms()
        return mrv_max(mrv(a,x), mrv(b,x), x)
    elif e.is_Add:
        a, b = e.as_two_terms()
        return mrv_max(mrv(a,x), mrv(b,x), x)
    elif e.is_Pow:
        if e.exp.has(x):
            return mrv(exp(e.exp * log(e.base)), x)
        else:
            return mrv(e.base, x)
    elif e.func is log:
        return mrv(e.args[0], x)
    elif e.func is exp:
        if limitinf(e.args[0], x) in [oo,-oo]:
            return mrv_max(set([e]), mrv(e.args[0], x), x)
        else:
            return mrv(e.args[0], x)
    elif e.is_Function:
        if len(e.args) == 1:
            return mrv(e.args[0], x)
        #only functions of 1 argument currently implemented
        raise NotImplementedError("Functions with more arguments: '%s'" % e)
    raise NotImplementedError("Don't know how to calculate the mrv of '%s'" % e)
Пример #19
0
def test_catalan():
    n = Symbol('n', integer=True)
    m = Symbol('n', integer=True, positive=True)

    catalans = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786]
    for i, c in enumerate(catalans):
        assert catalan(i) == c
        assert catalan(n).rewrite(factorial).subs(n, i) == c
        assert catalan(n).rewrite(Product).subs(n, i).doit() == c

    assert catalan(x) == catalan(x)
    assert catalan(2*x).rewrite(binomial) == binomial(4*x, 2*x)/(2*x + 1)
    assert catalan(Rational(1, 2)).rewrite(gamma) == 8/(3*pi)
    assert catalan(Rational(1, 2)).rewrite(factorial).rewrite(gamma) ==\
        8 / (3 * pi)
    assert catalan(3*x).rewrite(gamma) == 4**(
        3*x)*gamma(3*x + Rational(1, 2))/(sqrt(pi)*gamma(3*x + 2))
    assert catalan(x).rewrite(hyper) == hyper((-x + 1, -x), (2,), 1)

    assert catalan(n).rewrite(factorial) == factorial(2*n) / (factorial(n + 1)
                                                              * factorial(n))
    assert isinstance(catalan(n).rewrite(Product), catalan)
    assert isinstance(catalan(m).rewrite(Product), Product)

    assert diff(catalan(x), x) == (polygamma(
        0, x + Rational(1, 2)) - polygamma(0, x + 2) + log(4))*catalan(x)

    assert catalan(x).evalf() == catalan(x)
    c = catalan(S.Half).evalf()
    assert str(c) == '0.848826363156775'
    c = catalan(I).evalf(3)
    assert str((re(c), im(c))) == '(0.398, -0.0209)'
Пример #20
0
def test_trigintegrate_odd():
    assert trigintegrate(Rational(1), x) == x
    assert trigintegrate(x, x) is None
    assert trigintegrate(x**2, x) is None

    assert trigintegrate(sin(x), x) == -cos(x)
    assert trigintegrate(cos(x), x) == sin(x)

    assert trigintegrate(sin(3*x), x) == -cos(3*x)/3
    assert trigintegrate(cos(3*x), x) == sin(3*x)/3

    y = Symbol('y')
    assert trigintegrate(sin(y*x), x) == \
        Piecewise((0, Eq(y, 0)), (-cos(y*x)/y, True))
    assert trigintegrate(cos(y*x), x) == \
        Piecewise((x, Eq(y, 0)), (sin(y*x)/y, True))
    assert trigintegrate(sin(y*x)**2, x) == \
        Piecewise((0, Eq(y, 0)), ((x*y/2 - sin(x*y)*cos(x*y)/2)/y, True))
    assert trigintegrate(sin(y*x)*cos(y*x), x) == \
        Piecewise((0, Eq(y, 0)), (sin(x*y)**2/(2*y), True))
    assert trigintegrate(cos(y*x)**2, x) == \
        Piecewise((x, Eq(y, 0)), ((x*y/2 + sin(x*y)*cos(x*y)/2)/y, True))

    y = Symbol('y', positive=True)
    # TODO: remove conds='none' below. For this to work we would have to rule
    #       out (e.g. by trying solve) the condition y = 0, incompatible with
    #       y.is_positive being True.
    assert trigintegrate(sin(y*x), x, conds='none') == -cos(y*x)/y
    assert trigintegrate(cos(y*x), x, conds='none') == sin(y*x)/y

    assert trigintegrate(sin(x)*cos(x), x) == sin(x)**2/2
    assert trigintegrate(sin(x)*cos(x)**2, x) == -cos(x)**3/3
    assert trigintegrate(sin(x)**2*cos(x), x) == sin(x)**3/3

    # check if it selects right function to substitute,
    # so the result is kept simple
    assert trigintegrate(sin(x)**7 * cos(x), x) == sin(x)**8/8
    assert trigintegrate(sin(x) * cos(x)**7, x) == -cos(x)**8/8

    assert trigintegrate(sin(x)**7 * cos(x)**3, x) == \
        -sin(x)**10/10 + sin(x)**8/8
    assert trigintegrate(sin(x)**3 * cos(x)**7, x) == \
        cos(x)**10/10 - cos(x)**8/8

    # both n, m are odd and -ve, and not necessarily equal
    assert trigintegrate(sin(x)**-1*cos(x)**-1, x) == \
        -log(sin(x)**2 - 1)/2 + log(sin(x))
Пример #21
0
def test_ccode_math_macros():
    assert ccode(z + exp(1)) == 'z + M_E'
    assert ccode(z + log2(exp(1))) == 'z + M_LOG2E'
    assert ccode(z + 1/log(2)) == 'z + M_LOG2E'
    assert ccode(z + log(2)) == 'z + M_LN2'
    assert ccode(z + log(10)) == 'z + M_LN10'
    assert ccode(z + pi) == 'z + M_PI'
    assert ccode(z + pi/2) == 'z + M_PI_2'
    assert ccode(z + pi/4) == 'z + M_PI_4'
    assert ccode(z + 1/pi) == 'z + M_1_PI'
    assert ccode(z + 2/pi) == 'z + M_2_PI'
    assert ccode(z + 2/sqrt(pi)) == 'z + M_2_SQRTPI'
    assert ccode(z + 2/Sqrt(pi)) == 'z + M_2_SQRTPI'
    assert ccode(z + sqrt(2)) == 'z + M_SQRT2'
    assert ccode(z + Sqrt(2)) == 'z + M_SQRT2'
    assert ccode(z + 1/sqrt(2)) == 'z + M_SQRT1_2'
    assert ccode(z + 1/Sqrt(2)) == 'z + M_SQRT1_2'
Пример #22
0
def test_C99CodePrinter__precision():
    n = symbols('n', integer=True)
    f32_printer = C99CodePrinter(dict(type_aliases={real: float32}))
    f64_printer = C99CodePrinter(dict(type_aliases={real: float64}))
    f80_printer = C99CodePrinter(dict(type_aliases={real: float80}))
    assert f32_printer.doprint(sin(x+2.1)) == 'sinf(x + 2.1F)'
    assert f64_printer.doprint(sin(x+2.1)) == 'sin(x + 2.1000000000000001)'
    assert f80_printer.doprint(sin(x+Float('2.0'))) == 'sinl(x + 2.0L)'

    for printer, suffix in zip([f32_printer, f64_printer, f80_printer], ['f', '', 'l']):
        def check(expr, ref):
            assert printer.doprint(expr) == ref.format(s=suffix, S=suffix.upper())
        check(Abs(n), 'abs(n)')
        check(Abs(x + 2.0), 'fabs{s}(x + 2.0{S})')
        check(sin(x + 4.0)**cos(x - 2.0), 'pow{s}(sin{s}(x + 4.0{S}), cos{s}(x - 2.0{S}))')
        check(exp(x*8.0), 'exp{s}(8.0{S}*x)')
        check(exp2(x), 'exp2{s}(x)')
        check(expm1(x*4.0), 'expm1{s}(4.0{S}*x)')
        check(Mod(n, 2), '((n) % (2))')
        check(Mod(2*n + 3, 3*n + 5), '((2*n + 3) % (3*n + 5))')
        check(Mod(x + 2.0, 3.0), 'fmod{s}(1.0{S}*x + 2.0{S}, 3.0{S})')
        check(Mod(x, 2.0*x + 3.0), 'fmod{s}(1.0{S}*x, 2.0{S}*x + 3.0{S})')
        check(log(x/2), 'log{s}((1.0{S}/2.0{S})*x)')
        check(log10(3*x/2), 'log10{s}((3.0{S}/2.0{S})*x)')
        check(log2(x*8.0), 'log2{s}(8.0{S}*x)')
        check(log1p(x), 'log1p{s}(x)')
        check(2**x, 'pow{s}(2, x)')
        check(2.0**x, 'pow{s}(2.0{S}, x)')
        check(x**3, 'pow{s}(x, 3)')
        check(x**4.0, 'pow{s}(x, 4.0{S})')
        check(sqrt(3+x), 'sqrt{s}(x + 3)')
        check(Cbrt(x-2.0), 'cbrt{s}(x - 2.0{S})')
        check(hypot(x, y), 'hypot{s}(x, y)')
        check(sin(3.*x + 2.), 'sin{s}(3.0{S}*x + 2.0{S})')
        check(cos(3.*x - 1.), 'cos{s}(3.0{S}*x - 1.0{S})')
        check(tan(4.*y + 2.), 'tan{s}(4.0{S}*y + 2.0{S})')
        check(asin(3.*x + 2.), 'asin{s}(3.0{S}*x + 2.0{S})')
        check(acos(3.*x + 2.), 'acos{s}(3.0{S}*x + 2.0{S})')
        check(atan(3.*x + 2.), 'atan{s}(3.0{S}*x + 2.0{S})')
        check(atan2(3.*x, 2.*y), 'atan2{s}(3.0{S}*x, 2.0{S}*y)')

        check(sinh(3.*x + 2.), 'sinh{s}(3.0{S}*x + 2.0{S})')
        check(cosh(3.*x - 1.), 'cosh{s}(3.0{S}*x - 1.0{S})')
        check(tanh(4.0*y + 2.), 'tanh{s}(4.0{S}*y + 2.0{S})')
        check(asinh(3.*x + 2.), 'asinh{s}(3.0{S}*x + 2.0{S})')
        check(acosh(3.*x + 2.), 'acosh{s}(3.0{S}*x + 2.0{S})')
        check(atanh(3.*x + 2.), 'atanh{s}(3.0{S}*x + 2.0{S})')
        check(erf(42.*x), 'erf{s}(42.0{S}*x)')
        check(erfc(42.*x), 'erfc{s}(42.0{S}*x)')
        check(gamma(x), 'tgamma{s}(x)')
        check(loggamma(x), 'lgamma{s}(x)')

        check(ceiling(x + 2.), "ceil{s}(x + 2.0{S})")
        check(floor(x + 2.), "floor{s}(x + 2.0{S})")
        check(fma(x, y, -z), 'fma{s}(x, y, -z)')
        check(Max(x, 8.0, x**4.0), 'fmax{s}(8.0{S}, fmax{s}(x, pow{s}(x, 4.0{S})))')
        check(Min(x, 2.0), 'fmin{s}(2.0{S}, x)')
Пример #23
0
def _generate_patterns():
    """Generates patterns for transcendental equations.

    This is lazily calculated (called) in the tsolve() function and stored in
    the patterns global variable.
    """

    tmp1 = f ** (h-(c*g/b))
    tmp2 = (-e*tmp1/a)**(1/d)
    global patterns
    patterns = [
        (a*(b*x+c)**d + e   , ((-(e/a))**(1/d)-c)/b),
        (    b+c*exp(d*x+e) , (log(-b/c)-e)/d),
        (a*x+b+c*exp(d*x+e) , -b/a-LambertW(c*d*exp(e-b*d/a)/a)/d),
        (    b+c*f**(d*x+e) , (log(-b/c)-e*log(f))/d/log(f)),
        (a*x+b+c*f**(d*x+e) , -b/a-LambertW(c*d*f**(e-b*d/a)*log(f)/a)/d/log(f)),
        (    b+c*log(d*x+e) , (exp(-b/c)-e)/d),
        (a*x+b+c*log(d*x+e) , -e/d+c/a*LambertW(a/c/d*exp(-b/c+a*e/c/d))),
        (a*(b*x+c)**d + e*f**(g*x+h) , -c/b-d*LambertW(-tmp2*g*log(f)/b/d)/g/log(f))
    ]
Пример #24
0
    def __new__(cls, b, e, evaluate=True):
        from sympy.functions.elementary.exponential import exp_polar
        from sympy.functions import log
        # don't optimize "if e==0; return 1" here; it's better to handle that
        # in the calling routine so this doesn't get called
        b = _sympify(b)
        e = _sympify(e)
        if evaluate:
            if e is S.Zero:
                return S.One
            elif e is S.One:
                return b
            elif S.NaN in (b, e):
                if b is S.One:  # already handled e == 0 above
                    return S.One
                return S.NaN
            else:
                if e.func == log:
                    if len(e.args) == 2:
                        lbase = e.args[1]
                    else:
                        lbase = S.Exp1
                    if lbase == b:
                        return e.args[0]

                if e is Mul and e.args[1].func == log:
                    if len(e.args[1].args) == 2:
                        lbase = e.args[1].args[1]
                    else:
                        lbase = S.Exp1
                    if lbase == b:
                        return e.args[1].args[0] ** e.args[0]

                # recognize base as E
                if not e.is_Atom and b is not S.Exp1 and b.func is not exp_polar:
                    from sympy import numer, denom, log, sign, im, factor_terms
                    c, ex = factor_terms(e, sign=False).as_coeff_Mul()
                    den = denom(ex)
                    if den.func is log and den.args[0] == b:
                        return S.Exp1**(c*numer(ex))
                    elif den.is_Add:
                        s = sign(im(b))
                        if s.is_Number and s and den == \
                                log(-factor_terms(b, sign=False)) + s*S.ImaginaryUnit*S.Pi:
                            return S.Exp1**(c*numer(ex))

                obj = b._eval_power(e)
                if obj is not None:
                    return obj
        obj = Expr.__new__(cls, b, e)
        obj.is_commutative = (b.is_commutative and e.is_commutative)
        return obj
Пример #25
0
def test_Function():
    assert mcode(sin(x) ** cos(x)) == "sin(x).^cos(x)"
    assert mcode(sign(x)) == "sign(x)"
    assert mcode(exp(x)) == "exp(x)"
    assert mcode(log(x)) == "log(x)"
    assert mcode(factorial(x)) == "factorial(x)"
    assert mcode(floor(x)) == "floor(x)"
    assert mcode(atan2(y, x)) == "atan2(y, x)"
    assert mcode(beta(x, y)) == 'beta(x, y)'
    assert mcode(polylog(x, y)) == 'polylog(x, y)'
    assert mcode(harmonic(x)) == 'harmonic(x)'
    assert mcode(bernoulli(x)) == "bernoulli(x)"
    assert mcode(bernoulli(x, y)) == "bernoulli(x, y)"
Пример #26
0
    def integrate(field=None):
        irreducibles = set()

        for poly in reducibles:
            for z in poly.atoms(Symbol):
                if z in V:
                    break
            else:
                continue

            irreducibles |= set(root_factors(poly, z, domain=field))

        log_coeffs, log_part = [], []
        B = _symbols('B', len(irreducibles))

        for i, poly in enumerate(irreducibles):
            if poly.has(*V):
                log_coeffs.append(B[i])
                log_part.append(log_coeffs[-1] * log(poly))

        coeffs = poly_coeffs + log_coeffs

        candidate = poly_part/poly_denom + Add(*log_part)

        h = together(F - derivation(candidate) / denom)

        numer = h.as_numer_denom()[0].expand()

        if not numer.is_Add:
            numer = [numer]

        equations = {}

        for term in numer.args:
            coeff, dependent = term.as_independent(*V)

            if dependent in equations:
                equations[dependent] += coeff
            else:
                equations[dependent] = coeff

        solution = solve(equations.values(), *coeffs)

        if solution is not None:
            return (solution, candidate, coeffs)
        else:
            return None
Пример #27
0
 def ispow2(d, log2=False):
     if not d.is_Pow:
         return False
     e = d.exp
     if e.is_Rational and e.q == 2 or symbolic and denom(e) == 2:
         return True
     if log2:
         q = 1
         if e.is_Rational:
             q = e.q
         elif symbolic:
             d = denom(e)
             if d.is_Integer:
                 q = d
         if q != 1 and log(q, 2).is_Integer:
             return True
     return False
Пример #28
0
def test_catalan():
    assert catalan(1) == 1
    assert catalan(2) == 2
    assert catalan(3) == 5
    assert catalan(4) == 14

    assert catalan(x) == catalan(x)
    assert catalan(2*x).rewrite(binomial) == binomial(4*x, 2*x)/(2*x + 1)
    assert catalan(Rational(1, 2)).rewrite(gamma) == 8/(3*pi)
    assert catalan(3*x).rewrite(gamma) == 4**(
        3*x)*gamma(3*x + Rational(1, 2))/(sqrt(pi)*gamma(3*x + 2))
    assert catalan(x).rewrite(hyper) == hyper((-x + 1, -x), (2,), 1)

    assert diff(catalan(x), x) == (polygamma(
        0, x + Rational(1, 2)) - polygamma(0, x + 2) + log(4))*catalan(x)

    c = catalan(0.5).evalf()
    assert str(c) == '0.848826363156775'
Пример #29
0
def mrv_leadterm(e, x, Omega=[]):
    """Returns (c0, e0) for e."""
    if not e.has(x): return (e, Rational(0))
    Omega = [t for t in Omega if subexp(e,t)]
    if Omega == []:
        Omega = mrv(e,x)
    if x in set(Omega):
        #move the whole omega up (exponentiate each term):
        Omega_up = set(moveup(Omega,x))
        e_up = moveup([e],x)[0]
        #calculate the lead term
        mrv_leadterm_up = mrv_leadterm(e_up, x, Omega_up)
        #move the result (c0, e0) down
        return tuple(movedown(mrv_leadterm_up, x))
    wsym = Symbol("w", dummy=True)
    f, logw=rewrite(e, set(Omega), x, wsym)
    series = calculate_series(f, wsym)
    series=series.subs(log(wsym), logw)
    return calculate_leadterm(series, wsym)
Пример #30
0
def test_1():
    test = [
        [ - S(3)/S(2), x, S(1), - S(3)/S(2)*x],
        [Pi, x, S(1), Pi*x],
        [a, x, S(1), a*x],
        [x**m, x, S(1), x**(S(1) + m)/(S(1) + m)],
        [x**S(100), x, S(1), S(1)/S(101)*x**S(101)],
        [x**(S(5)/S(2)), x, S(1), S(2)/S(7)*x**(S(7)/S(2))],
        [x**(S(5)/S(3)), x, S(1), S(3)/S(8)*x**(S(8)/S(3))],
        [S(1)/x**(S(1)/S(3)), x, S(1), S(3)/S(2)*x**(S(2)/S(3))],
        [x**S(3)*(a + b*x), x, S(2), S(1)/S(4)*a*x**S(4) + S(1)/S(5)*b*x**S(5)],
        [(a + b*x)**S(2)/x**S(2), x, S(2), - a**S(2)/x + b**S(2)*x + S(2)*a*b*log(x)],
    ]

    for i in test:
        r = rubi_integrate(i[0], i[1])
        if len(i) == 5:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True) or rubi_test(r, i[1], i[4], expand=True, _diff=True)
        else:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True)
Пример #31
0
def test_rubi_integrate():
    from sympy.integrals.rubi.rubi import rubi_integrate

    assert rubi_integrate(x, x) == x**2 / 2
    assert rubi_integrate(x**2, x) == x**3 / 3
    assert rubi_integrate(x**3, x) == x**4 / 4
    assert rubi_integrate(x**a, x) == x**(a + S(1)) / (a + S(1))
    assert rubi_integrate(S(1) / x, x) == log(x)
    assert rubi_integrate(a * x, x) == a * (S(1) / S(2)) * x**S(2)
    assert rubi_integrate(
        1 / (x**2 * (a + b * x)**2), x) == -b / (a**2 * (a + b * x)) - 1 / (
            a**2 * x) - 2 * b * log(x) / a**3 + 2 * b * log(a + b * x) / a**3
    assert rubi_integrate(
        x**6 / (a + b * x)**2,
        x) == (-a**6 / (b**7 * (a + b * x)) -
               S(6) * a**5 * log(a + b * x) / b**7 + 5 * a**4 * x / b**6 -
               S(2) * a**3 * x**2 / b**5 + a**2 * x**3 / b**4 - a * x**4 /
               (S(2) * b**3) + x**5 / (S(5) * b**2))
    assert rubi_integrate(
        1 / (x**2 * (a + b * x)**2), x) == -b / (a**2 * (a + b * x)) - 1 / (
            a**2 * x) - 2 * b * log(x) / a**3 + 2 * b * log(a + b * x) / a**3
    assert rubi_integrate(a + S(1) / x, x) == a * x + log(x)
    assert rubi_integrate(
        (a + b * x)**2 / x**3,
        x) == -a**2 / (2 * x**2) - 2 * a * b / x + b**2 * log(x)
    assert rubi_integrate(a**3 * x, x) == S(1) / S(2) * a**3 * x**2
    assert rubi_integrate((a + b * x)**3 / x**3, x) == -a**3 / (
        2 * x**2) - 3 * a**2 * b / x + 3 * a * b**2 * log(x) + b**3 * x
    assert rubi_integrate(x**3 * (a + b * x), x) == a * x**4 / 4 + b * x**5 / 5
    assert rubi_integrate(
        (b * x)**m * (d * x + 2)**n, x) == 2**n * (b * x)**(m + 1) * hyper(
            (-n, m + 1), (m + 2, ), -d * x / 2) / (b * (m + 1))
    assert rubi_test(
        rubi_integrate(1 / (1 + x**5), x),
        x,
        log(x + S(1)) / S(5) + S(2) * Sum(
            -log((S(2) * x - S(2) * cos(pi *
                                        (S(2) * k / S(5) + S(-1) / 5)))**S(2) -
                 S(4) * sin(S(2) * pi * k / S(5) + S(3) * pi / S(10))**S(2) +
                 S(4)) * cos(pi * (S(2) * k / S(5) + S(-1) / 5)) / S(2) -
            (-S(2) * cos(pi * (S(2) * k / S(5) + S(-1) / 5))**S(2) + S(2)) *
            atan((-x / cos(pi * (S(2) * k / S(5) + S(-1) / 5)) + S(1)) /
                 sqrt(-(cos(S(2) * pi * k / S(5) - pi / S(5)) + S(-1)) *
                      (cos(S(2) * pi * k / S(5) - pi / S(5)) + S(1)) /
                      cos(S(2) * pi * k / S(5) - pi / S(5))**S(2))) /
            (S(2) * sqrt(-(cos(S(2) * pi * k / S(5) - pi / S(5)) + S(-1)) *
                         (cos(S(2) * pi * k / S(5) - pi / S(5)) + S(1)) /
                         cos(S(2) * pi * k / S(5) - pi / S(5))**S(2)) *
             cos(pi * (S(2) * k / S(5) + S(-1) / 5))), (k, S(1), S(2))) / S(5),
        _numerical=True)
Пример #32
0
 def _expr_small_minus(cls, z):
     return log(S.Half + sqrt(1 + z) / 2)
Пример #33
0
def test_harmonic_rational():
    ne = S(6)
    no = S(5)
    pe = S(8)
    po = S(9)
    qe = S(10)
    qo = S(13)

    Heee = harmonic(ne + pe / qe)
    Aeee = (-log(10) + 2 * (Rational(-1, 4) + sqrt(5) / 4) *
            log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 *
            (-sqrt(5) / 4 - Rational(1, 4)) *
            log(sqrt(sqrt(5) / 8 + Rational(5, 8))) +
            pi * sqrt(2 * sqrt(5) / 5 + 1) / 2 + Rational(13944145, 4720968))

    Heeo = harmonic(ne + pe / qo)
    Aeeo = (-log(26) +
            2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(4, 13)) +
            2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(32, 13)) +
            2 * log(sin(pi * Rational(5, 13))) * cos(pi * Rational(80, 13)) -
            2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(5, 13)) -
            2 * log(sin(pi * Rational(4, 13))) * cos(pi / 13) +
            pi * cot(pi * Rational(5, 13)) / 2 -
            2 * log(sin(pi / 13)) * cos(pi * Rational(3, 13)) +
            Rational(2422020029, 702257080))

    Heoe = harmonic(ne + po / qe)
    Aeoe = (
        -log(20) + 2 *
        (Rational(1, 4) + sqrt(5) / 4) * log(Rational(-1, 4) + sqrt(5) / 4) +
        2 * (Rational(-1, 4) + sqrt(5) / 4) *
        log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 *
        (-sqrt(5) / 4 - Rational(1, 4)) *
        log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + 2 *
        (-sqrt(5) / 4 + Rational(1, 4)) * log(Rational(1, 4) + sqrt(5) / 4) +
        Rational(11818877030, 4286604231) + pi * sqrt(2 * sqrt(5) + 5) / 2)

    Heoo = harmonic(ne + po / qo)
    Aeoo = (-log(26) +
            2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(54, 13)) +
            2 * log(sin(pi * Rational(4, 13))) * cos(pi * Rational(6, 13)) +
            2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(108, 13)) -
            2 * log(sin(pi * Rational(5, 13))) * cos(pi / 13) -
            2 * log(sin(pi / 13)) * cos(pi * Rational(5, 13)) +
            pi * cot(pi * Rational(4, 13)) / 2 -
            2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(3, 13)) +
            Rational(11669332571, 3628714320))

    Hoee = harmonic(no + pe / qe)
    Aoee = (-log(10) + 2 * (Rational(-1, 4) + sqrt(5) / 4) *
            log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 *
            (-sqrt(5) / 4 - Rational(1, 4)) *
            log(sqrt(sqrt(5) / 8 + Rational(5, 8))) +
            pi * sqrt(2 * sqrt(5) / 5 + 1) / 2 + Rational(779405, 277704))

    Hoeo = harmonic(no + pe / qo)
    Aoeo = (-log(26) +
            2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(4, 13)) +
            2 * log(sin(pi * Rational(2, 13))) * cos(pi * Rational(32, 13)) +
            2 * log(sin(pi * Rational(5, 13))) * cos(pi * Rational(80, 13)) -
            2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(5, 13)) -
            2 * log(sin(pi * Rational(4, 13))) * cos(pi / 13) +
            pi * cot(pi * Rational(5, 13)) / 2 -
            2 * log(sin(pi / 13)) * cos(pi * Rational(3, 13)) +
            Rational(53857323, 16331560))

    Hooe = harmonic(no + po / qe)
    Aooe = (
        -log(20) + 2 *
        (Rational(1, 4) + sqrt(5) / 4) * log(Rational(-1, 4) + sqrt(5) / 4) +
        2 * (Rational(-1, 4) + sqrt(5) / 4) *
        log(sqrt(-sqrt(5) / 8 + Rational(5, 8))) + 2 *
        (-sqrt(5) / 4 - Rational(1, 4)) *
        log(sqrt(sqrt(5) / 8 + Rational(5, 8))) + 2 *
        (-sqrt(5) / 4 + Rational(1, 4)) * log(Rational(1, 4) + sqrt(5) / 4) +
        Rational(486853480, 186374097) + pi * sqrt(2 * sqrt(5) + 5) / 2)

    Hooo = harmonic(no + po / qo)
    Aooo = (-log(26) +
            2 * log(sin(pi * Rational(3, 13))) * cos(pi * Rational(54, 13)) +
            2 * log(sin(pi * Rational(4, 13))) * cos(pi * Rational(6, 13)) +
            2 * log(sin(pi * Rational(6, 13))) * cos(pi * Rational(108, 13)) -
            2 * log(sin(pi * Rational(5, 13))) * cos(pi / 13) -
            2 * log(sin(pi / 13)) * cos(pi * Rational(5, 13)) +
            pi * cot(pi * Rational(4, 13)) / 2 -
            2 * log(sin(pi * Rational(2, 13))) * cos(3 * pi / 13) +
            Rational(383693479, 125128080))

    H = [Heee, Heeo, Heoe, Heoo, Hoee, Hoeo, Hooe, Hooo]
    A = [Aeee, Aeeo, Aeoe, Aeoo, Aoee, Aoeo, Aooe, Aooo]
    for h, a in zip(H, A):
        e = expand_func(h).doit()
        assert cancel(e / a) == 1
        assert abs(h.n() - a.n()) < 1e-12
Пример #34
0
def test_C99CodePrinter__precision():
    n = symbols('n', integer=True)
    p = symbols('p', integer=True, positive=True)
    f32_printer = C99CodePrinter(dict(type_aliases={real: float32}))
    f64_printer = C99CodePrinter(dict(type_aliases={real: float64}))
    f80_printer = C99CodePrinter(dict(type_aliases={real: float80}))
    assert f32_printer.doprint(sin(x + 2.1)) == 'sinf(x + 2.1F)'
    assert f64_printer.doprint(sin(x + 2.1)) == 'sin(x + 2.1000000000000001)'
    assert f80_printer.doprint(sin(x + Float('2.0'))) == 'sinl(x + 2.0L)'

    for printer, suffix in zip([f32_printer, f64_printer, f80_printer],
                               ['f', '', 'l']):

        def check(expr, ref):
            assert printer.doprint(expr) == ref.format(s=suffix,
                                                       S=suffix.upper())

        check(Abs(n), 'abs(n)')
        check(Abs(x + 2.0), 'fabs{s}(x + 2.0{S})')
        check(
            sin(x + 4.0)**cos(x - 2.0),
            'pow{s}(sin{s}(x + 4.0{S}), cos{s}(x - 2.0{S}))')
        check(exp(x * 8.0), 'exp{s}(8.0{S}*x)')
        check(exp2(x), 'exp2{s}(x)')
        check(expm1(x * 4.0), 'expm1{s}(4.0{S}*x)')
        check(Mod(p, 2), 'p % 2')
        check(Mod(2 * p + 3, 3 * p + 5, evaluate=False),
              '(2*p + 3) % (3*p + 5)')
        check(Mod(x + 2.0, 3.0), 'fmod{s}(1.0{S}*x + 2.0{S}, 3.0{S})')
        check(Mod(x, 2.0 * x + 3.0), 'fmod{s}(1.0{S}*x, 2.0{S}*x + 3.0{S})')
        check(log(x / 2), 'log{s}((1.0{S}/2.0{S})*x)')
        check(log10(3 * x / 2), 'log10{s}((3.0{S}/2.0{S})*x)')
        check(log2(x * 8.0), 'log2{s}(8.0{S}*x)')
        check(log1p(x), 'log1p{s}(x)')
        check(2**x, 'pow{s}(2, x)')
        check(2.0**x, 'pow{s}(2.0{S}, x)')
        check(x**3, 'pow{s}(x, 3)')
        check(x**4.0, 'pow{s}(x, 4.0{S})')
        check(sqrt(3 + x), 'sqrt{s}(x + 3)')
        check(Cbrt(x - 2.0), 'cbrt{s}(x - 2.0{S})')
        check(hypot(x, y), 'hypot{s}(x, y)')
        check(sin(3. * x + 2.), 'sin{s}(3.0{S}*x + 2.0{S})')
        check(cos(3. * x - 1.), 'cos{s}(3.0{S}*x - 1.0{S})')
        check(tan(4. * y + 2.), 'tan{s}(4.0{S}*y + 2.0{S})')
        check(asin(3. * x + 2.), 'asin{s}(3.0{S}*x + 2.0{S})')
        check(acos(3. * x + 2.), 'acos{s}(3.0{S}*x + 2.0{S})')
        check(atan(3. * x + 2.), 'atan{s}(3.0{S}*x + 2.0{S})')
        check(atan2(3. * x, 2. * y), 'atan2{s}(3.0{S}*x, 2.0{S}*y)')

        check(sinh(3. * x + 2.), 'sinh{s}(3.0{S}*x + 2.0{S})')
        check(cosh(3. * x - 1.), 'cosh{s}(3.0{S}*x - 1.0{S})')
        check(tanh(4.0 * y + 2.), 'tanh{s}(4.0{S}*y + 2.0{S})')
        check(asinh(3. * x + 2.), 'asinh{s}(3.0{S}*x + 2.0{S})')
        check(acosh(3. * x + 2.), 'acosh{s}(3.0{S}*x + 2.0{S})')
        check(atanh(3. * x + 2.), 'atanh{s}(3.0{S}*x + 2.0{S})')
        check(erf(42. * x), 'erf{s}(42.0{S}*x)')
        check(erfc(42. * x), 'erfc{s}(42.0{S}*x)')
        check(gamma(x), 'tgamma{s}(x)')
        check(loggamma(x), 'lgamma{s}(x)')

        check(ceiling(x + 2.), "ceil{s}(x + 2.0{S})")
        check(floor(x + 2.), "floor{s}(x + 2.0{S})")
        check(fma(x, y, -z), 'fma{s}(x, y, -z)')
        check(Max(x, 8.0, x**4.0),
              'fmax{s}(8.0{S}, fmax{s}(x, pow{s}(x, 4.0{S})))')
        check(Min(x, 2.0), 'fmin{s}(2.0{S}, x)')
Пример #35
0
 def _expr_big_minus(cls, x, n):
     return log(1 + x) + 2 * n * pi * I
Пример #36
0
    def _integrate(field=None):
        irreducibles = set()

        for poly in reducibles:
            for z in poly.atoms(Symbol):
                if z in V:
                    break
            else:
                continue

            irreducibles |= set(root_factors(poly, z, filter=field))

        log_coeffs, log_part = [], []
        B = _symbols('B', len(irreducibles))

        for i, poly in enumerate(irreducibles):
            if poly.has(*V):
                log_coeffs.append(B[i])
                log_part.append(log_coeffs[-1] * log(poly))

        coeffs = poly_coeffs + log_coeffs

        # TODO: Currently it's better to use symbolic expressions here instead
        # of rational functions, because it's simpler and FracElement doesn't
        # give big speed improvement yet. This is because cancelation is slow
        # due to slow polynomial GCD algorithms. If this gets improved then
        # revise this code.
        candidate = poly_part / poly_denom + Add(*log_part)
        h = F - _derivation(candidate) / denom
        raw_numer = h.as_numer_denom()[0]

        # Rewrite raw_numer as a polynomial in K[coeffs][V] where K is a field
        # that we have to determine. We can't use simply atoms() because log(3),
        # sqrt(y) and similar expressions can appear, leading to non-trivial
        # domains.
        syms = set(coeffs) | set(V)
        non_syms = set([])

        def find_non_syms(expr):
            if expr.is_Integer or expr.is_Rational:
                pass  # ignore trivial numbers
            elif expr in syms:
                pass  # ignore variables
            elif not expr.has(*syms):
                non_syms.add(expr)
            elif expr.is_Add or expr.is_Mul or expr.is_Pow:
                list(map(find_non_syms, expr.args))
            else:
                # TODO: Non-polynomial expression. This should have been
                # filtered out at an earlier stage.
                raise PolynomialError

        try:
            find_non_syms(raw_numer)
        except PolynomialError:
            return None
        else:
            ground, _ = construct_domain(non_syms, field=True)

        coeff_ring = PolyRing(coeffs, ground)
        ring = PolyRing(V, coeff_ring)

        numer = ring.from_expr(raw_numer)

        solution = solve_lin_sys(numer.coeffs(), coeff_ring)

        if solution is None:
            return None
        else:
            solution = [(k.as_expr(), v.as_expr())
                        for k, v in solution.items()]
            return candidate.subs(solution).subs(
                list(zip(coeffs, [S.Zero] * len(coeffs))))
Пример #37
0
def integrand_simplification(rubi):
    pattern1 = Pattern(Integral((a_ + x_**WC('n', S(1))*WC('b', S(1)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda a: ZeroQ(a)))
    rule1 = ReplacementRule(pattern1, lambda p, b, u, a, x, n : Int(u*(b*x**n)**p, x))
    rubi.add(rule1)

    pattern2 = Pattern(Integral((a_ + x_**WC('j', S(1))*WC('c', S(1)) + x_**WC('n', S(1))*WC('b', S(1)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda n, j: ZeroQ(j - S(2)*n)), CustomConstraint(lambda a: ZeroQ(a)))
    rule2 = ReplacementRule(pattern2, lambda j, b, p, u, a, x, n, c : Int(u*(b*x**n + c*x**(S(2)*n))**p, x))
    rubi.add(rule2)

    pattern3 = Pattern(Integral((x_**WC('j', S(1))*WC('c', S(1)) + x_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda n, j: ZeroQ(j - S(2)*n)), CustomConstraint(lambda b: ZeroQ(b)))
    rule3 = ReplacementRule(pattern3, lambda j, b, p, u, a, x, n, c : Int(u*(a + c*x**(S(2)*n))**p, x))
    rubi.add(rule3)

    pattern4 = Pattern(Integral((x_**WC('j', S(1))*WC('c', S(1)) + x_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda n, j: ZeroQ(j - S(2)*n)), CustomConstraint(lambda c: ZeroQ(c)))
    rule4 = ReplacementRule(pattern4, lambda j, b, p, u, a, x, n, c : Int(u*(a + b*x**n)**p, x))
    rubi.add(rule4)

    pattern5 = Pattern(Integral((v_*WC('a', S(1)) + v_*WC('b', S(1)) + WC('w', S(0)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda x, v: NFreeQ(v, x)))
    rule5 = ReplacementRule(pattern5, lambda p, b, v, u, a, x, w : Int(u*(v*(a + b) + w)**p, x))
    rubi.add(rule5)

    pattern6 = Pattern(Integral(Pm_**p_*WC('u', S(1)), x_), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda x, Pm: PolyQ(Pm, x)), CustomConstraint(lambda p: Not(RationalQ(p))), CustomConstraint(lambda p: RationalQ(p)))
    rule6 = ReplacementRule(pattern6, lambda u, x, p, Pm : Int(Pm**p*u, x))
    rubi.add(rule6)

    pattern7 = Pattern(Integral(a_, x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a, x: FreeQ(a, x)))
    rule7 = ReplacementRule(pattern7, lambda a, x : a*x)
    rubi.add(rule7)

    pattern8 = Pattern(Integral(a_*(b_ + x_*WC('c', S(1))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda a, c, b, x: FreeQ(List(a, b, c), x)))
    rule8 = ReplacementRule(pattern8, lambda a, c, b, x : a*(b + c*x)**S(2)/(S(2)*c))
    rubi.add(rule8)

    pattern9 = Pattern(Integral(-u_, x_))
    rule9 = ReplacementRule(pattern9, lambda u, x : I*Int(u, x))
    rubi.add(rule9)

    pattern10 = Pattern(Integral(u_*Complex(S(0), a_), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: EqQ(a**S(2), S(1))))
    rule10 = ReplacementRule(pattern10, lambda u, a, x : Int(u, x)*Complex(I, a))
    rubi.add(rule10)

    pattern11 = Pattern(Integral(a_*u_, x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a, x: FreeQ(a, x)))
    rule11 = ReplacementRule(pattern11, lambda u, a, x : a*Int(u, x))
    rubi.add(rule11)

    pattern12 = Pattern(Integral(u_, x_), CustomConstraint(lambda u: SumQ(u)))
    rule12 = ReplacementRule(pattern12, lambda u, x : IntSum(u, x))
    rubi.add(rule12)

    pattern13 = Pattern(Integral(v_**WC('m', S(1))*(b_*v_)**n_*WC('u', S(1)), x_), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda m: IntegerQ(m)))
    rule13 = ReplacementRule(pattern13, lambda b, v, u, m, x, n : b**(-m)*Int(u*(b*v)**(m + n), x))
    rubi.add(rule13)

    pattern14 = Pattern(Integral((v_*WC('a', S(1)))**m_*(v_*WC('b', S(1)))**n_*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda m: Not(IntegerQ(m))), CustomConstraint(lambda n: PositiveIntegerQ(n + S(1)/2)), CustomConstraint(lambda m, n: IntegerQ(m + n)))
    rule14 = ReplacementRule(pattern14, lambda b, v, u, m, a, x, n : a**(m + S(1)/2)*b**(n + S(-1)/2)*sqrt(b*v)*Int(u*v**(m + n), x)/sqrt(a*v))
    rubi.add(rule14)

    pattern15 = Pattern(Integral((v_*WC('a', S(1)))**m_*(v_*WC('b', S(1)))**n_*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda m: Not(IntegerQ(m))), CustomConstraint(lambda n: NegativeIntegerQ(n + S(-1)/2)), CustomConstraint(lambda m, n: IntegerQ(m + n)))
    rule15 = ReplacementRule(pattern15, lambda b, v, u, m, a, x, n : a**(m + S(-1)/2)*b**(n + S(1)/2)*sqrt(a*v)*Int(u*v**(m + n), x)/sqrt(b*v))
    rubi.add(rule15)

    pattern16 = Pattern(Integral((v_*WC('a', S(1)))**m_*(v_*WC('b', S(1)))**n_*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda m: Not(IntegerQ(m))), CustomConstraint(lambda n: Not(IntegerQ(n))), CustomConstraint(lambda m, n: IntegerQ(m + n)))
    rule16 = ReplacementRule(pattern16, lambda b, v, u, m, a, x, n : a**(m + n)*(a*v)**(-n)*(b*v)**n*Int(u*v**(m + n), x))
    rubi.add(rule16)

    pattern17 = Pattern(Integral((v_*WC('a', S(1)))**m_*(v_*WC('b', S(1)))**n_*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda m: Not(IntegerQ(m))), CustomConstraint(lambda n: Not(IntegerQ(n))), CustomConstraint(lambda m, n: Not(IntegerQ(m + n))))
    rule17 = ReplacementRule(pattern17, lambda b, v, u, m, a, x, n : a**(-IntPart(n))*b**IntPart(n)*(a*v)**(-FracPart(n))*(b*v)**FracPart(n)*Int(u*(a*v)**(m + n), x))
    rubi.add(rule17)

    pattern18 = Pattern(Integral((a_ + v_*WC('b', S(1)))**WC('m', S(1))*(c_ + v_*WC('d', S(1)))**WC('n', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda a, c, b, d: ZeroQ(-a*d + b*c)), CustomConstraint(lambda m: IntegerQ(m)), CustomConstraint(lambda b, a, x, d, n, c: Not(IntegerQ(n)) | SimplerQ(c + d*x, a + b*x)))
    rule18 = ReplacementRule(pattern18, lambda b, v, u, m, a, x, d, n, c : (b/d)**m*Int(u*(c + d*v)**(m + n), x))
    rubi.add(rule18)

    pattern19 = Pattern(Integral((a_ + v_*WC('b', S(1)))**m_*(c_ + v_*WC('d', S(1)))**n_*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda a, c, b, d: ZeroQ(-a*d + b*c)), CustomConstraint(lambda b, d: PositiveQ(b/d)), CustomConstraint(lambda m, n: Not(IntegerQ(m) | IntegerQ(n))))
    rule19 = ReplacementRule(pattern19, lambda b, v, u, m, a, x, d, n, c : (b/d)**m*Int(u*(c + d*v)**(m + n), x))
    rubi.add(rule19)

    pattern20 = Pattern(Integral((a_ + v_*WC('b', S(1)))**m_*(c_ + v_*WC('d', S(1)))**n_*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda a, c, b, d: ZeroQ(-a*d + b*c)), CustomConstraint(lambda m, n, b, d: Not(IntegerQ(m) | IntegerQ(n) | PositiveQ(b/d))))
    rule20 = ReplacementRule(pattern20, lambda b, v, u, m, a, x, d, n, c : (a + b*v)**m*(c + d*v)**(-m)*Int(u*(c + d*v)**(m + n), x))
    rubi.add(rule20)

    pattern21 = Pattern(Integral((v_*WC('a', S(1)))**m_*(v_**S(2)*WC('c', S(1)) + v_*WC('b', S(1)))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda m: RationalQ(m)), CustomConstraint(lambda m: LessEqual(m, S(-1))))
    rule21 = ReplacementRule(pattern21, lambda b, v, u, m, a, x, c : Int(u*(a*v)**(m + S(1))*(b + c*v), x)/a)
    rubi.add(rule21)

    pattern22 = Pattern(Integral((a_ + v_*WC('b', S(1)))**m_*(v_**S(2)*WC('C', S(1)) + v_*WC('B', S(1)) + WC('A', S(0)))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda A, x: FreeQ(A, x)), CustomConstraint(lambda B, x: FreeQ(B, x)), CustomConstraint(lambda C, x: FreeQ(C, x)), CustomConstraint(lambda b, A, B, a, C: ZeroQ(A*b**S(2) - B*a*b + C*a**S(2))), CustomConstraint(lambda m: RationalQ(m)), CustomConstraint(lambda m: LessEqual(m, S(-1))))
    rule22 = ReplacementRule(pattern22, lambda b, v, u, A, B, m, a, x, C : Int(u*(a + b*v)**(m + S(1))*Simp(B*b - C*a + C*b*v, x), x)/b**S(2))
    rubi.add(rule22)

    pattern23 = Pattern(Integral((a_ + x_**WC('n', S(1))*WC('b', S(1)))**WC('m', S(1))*(c_ + x_**WC('q', S(1))*WC('d', S(1)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda n, q: ZeroQ(n + q)), CustomConstraint(lambda p: IntegerQ(p)), CustomConstraint(lambda a, c, b, d: ZeroQ(a*c - b*d)), CustomConstraint(lambda m, n: Not(IntegerQ(m) & NegQ(n))))
    rule23 = ReplacementRule(pattern23, lambda q, p, b, u, m, a, x, d, n, c : (d/a)**p*Int(u*x**(-n*p)*(a + b*x**n)**(m + p), x))
    rubi.add(rule23)

    pattern24 = Pattern(Integral((a_ + x_**WC('n', S(1))*WC('b', S(1)))**WC('m', S(1))*(c_ + x_**j_*WC('d', S(1)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda n, j: ZeroQ(j - S(2)*n)), CustomConstraint(lambda m, p: ZeroQ(m + p)), CustomConstraint(lambda a, c, b, d: ZeroQ(a**S(2)*d + b**S(2)*c)), CustomConstraint(lambda a: PositiveQ(a)), CustomConstraint(lambda d: NegativeQ(d)))
    rule24 = ReplacementRule(pattern24, lambda p, b, j, u, m, a, x, d, n, c : (-b**S(2)/d)**m*Int(u*(a - b*x**n)**(-m), x))
    rubi.add(rule24)

    pattern25 = Pattern(Integral((a_ + x_**S(2)*WC('c', S(1)) + x_*WC('b', S(1)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda a, c, b: ZeroQ(-S(4)*a*c + b**S(2))), CustomConstraint(lambda p: IntegerQ(p)))
    rule25 = ReplacementRule(pattern25, lambda p, b, u, a, x, c : Int(S(2)**(-S(2)*p)*c**(-p)*u*(b + S(2)*c*x)**(S(2)*p), x))
    rubi.add(rule25)

    pattern26 = Pattern(Integral((a_ + x_**n_*WC('b', S(1)) + x_**WC('n2', S(1))*WC('c', S(1)))**WC('p', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda n, n2: ZeroQ(-S(2)*n + n2)), CustomConstraint(lambda a, c, b: ZeroQ(-S(4)*a*c + b**S(2))), CustomConstraint(lambda p: IntegerQ(p)))
    rule26 = ReplacementRule(pattern26, lambda n2, p, b, u, a, x, n, c : c**(-p)*Int(u*(b/S(2) + c*x**n)**(S(2)*p), x))
    rubi.add(rule26)

    pattern27 = Pattern(Integral((d_ + x_*WC('e', S(1)))*(x_**S(2)*WC('c', S(1)) + x_*WC('b', S(1)) + WC('a', S(0)))**WC('p', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda e, x: FreeQ(e, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda e, c, b, d: ZeroQ(-b*e + S(2)*c*d)))
    rule27 = ReplacementRule(pattern27, lambda p, b, a, x, d, e, c : d*Subst(Int(x**p, x), x, a + b*x + c*x**S(2))/b)
    rubi.add(rule27)

    pattern28 = Pattern(Integral((x_**WC('p', S(1))*WC('a', S(1)) + x_**WC('q', S(1))*WC('b', S(1)))**WC('m', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda q, x: FreeQ(q, x)), CustomConstraint(lambda m: IntegerQ(m)), CustomConstraint(lambda q, p: PosQ(-p + q)))
    rule28 = ReplacementRule(pattern28, lambda q, p, b, u, m, a, x : Int(u*x**(m*p)*(a + b*x**(-p + q))**m, x))
    rubi.add(rule28)

    pattern29 = Pattern(Integral((x_**WC('p', S(1))*WC('a', S(1)) + x_**WC('q', S(1))*WC('b', S(1)) + x_**WC('r', S(1))*WC('c', S(1)))**WC('m', S(1))*WC('u', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda q, x: FreeQ(q, x)), CustomConstraint(lambda r, x: FreeQ(r, x)), CustomConstraint(lambda m: IntegerQ(m)), CustomConstraint(lambda q, p: PosQ(-p + q)), CustomConstraint(lambda r, p: PosQ(-p + r)))
    rule29 = ReplacementRule(pattern29, lambda q, r, p, b, u, m, a, x, c : Int(u*x**(m*p)*(a + b*x**(-p + q) + c*x**(-p + r))**m, x))
    rubi.add(rule29)

    pattern30 = Pattern(Integral(x_**WC('m', S(1))/(a_ + x_**n_*WC('b', S(1))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda m, n: ZeroQ(m - n + S(1))))
    rule30 = ReplacementRule(pattern30, lambda b, m, a, x, n : log(RemoveContent(a + b*x**n, x))/(b*n))
    rubi.add(rule30)

    pattern31 = Pattern(Integral(x_**WC('m', S(1))*(a_ + x_**n_*WC('b', S(1)))**p_, x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda m, n: ZeroQ(m - n + S(1))), CustomConstraint(lambda p: NonzeroQ(p + S(1))))
    rule31 = ReplacementRule(pattern31, lambda p, b, m, a, x, n : (a + b*x**n)**(p + S(1))/(b*n*(p + S(1))))
    rubi.add(rule31)

    pattern32 = Pattern(Integral(x_**WC('m', S(1))*(a1_ + x_**WC('n', S(1))*WC('b1', S(1)))**p_*(a2_ + x_**WC('n', S(1))*WC('b2', S(1)))**p_, x_), CustomConstraint(lambda a1, x: FreeQ(a1, x)), CustomConstraint(lambda b1, x: FreeQ(b1, x)), CustomConstraint(lambda a2, x: FreeQ(a2, x)), CustomConstraint(lambda b2, x: FreeQ(b2, x)), CustomConstraint(lambda m, x: FreeQ(m, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda b2, b1, a1, a2: ZeroQ(a1*b2 + a2*b1)), CustomConstraint(lambda m, n: ZeroQ(m - S(2)*n + S(1))), CustomConstraint(lambda p: NonzeroQ(p + S(1))))
    rule32 = ReplacementRule(pattern32, lambda p, a1, b2, m, x, a2, n, b1 : (a1 + b1*x**n)**(p + S(1))*(a2 + b2*x**n)**(p + S(1))/(S(2)*b1*b2*n*(p + S(1))))
    rubi.add(rule32)
    '''
    pattern33 = Pattern(Integral(Qm_*(Pm_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)))**WC('p', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda x, Pm: PolyQ(Pm, x)), CustomConstraint(lambda Qm, x: PolyQ(Qm, x)), )
    def With33(p, b, a, x, n, Qm, Pm):
        m = Expon(Pm, x)
        if Equal(Expon(Qm, x), m + S(-1)) & ZeroQ(-Qm*m*Coeff(Pm, x, m) + Coeff(Qm, x, m + S(-1))*D(Pm, x)):
            return Coeff(Qm, x, m + S(-1))*Subst(Int((a + b*x**n)**p, x), x, Pm)/(m*Coeff(Pm, x, m))
        print("Unable to Integrate")
    rule33 = ReplacementRule(pattern33, lambda p, b, a, x, n, Qm, Pm : With33(p, b, a, x, n, Qm, Pm))
    rubi.add(rule33)

    pattern34 = Pattern(Integral(Qm_*(Pm_**WC('n', S(1))*WC('b', S(1)) + Pm_**WC('n2', S(1))*WC('c', S(1)) + WC('a', S(0)))**WC('p', S(1)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, x: FreeQ(n, x)), CustomConstraint(lambda p, x: FreeQ(p, x)), CustomConstraint(lambda n, n2: ZeroQ(-S(2)*n + n2)), CustomConstraint(lambda x, Pm: PolyQ(Pm, x)), CustomConstraint(lambda Qm, x: PolyQ(Qm, x)), )
    def With34(n2, p, b, a, x, n, Qm, c, Pm):
        m = Expon(Pm, x)
        if Equal(Expon(Qm, x), m + S(-1)) & ZeroQ(-Qm*m*Coeff(Pm, x, m) + Coeff(Qm, x, m + S(-1))*D(Pm, x)):
            return Coeff(Qm, x, m + S(-1))*Subst(Int((a + b*x**n + c*x**(S(2)*n))**p, x), x, Pm)/(m*Coeff(Pm, x, m))
        print("Unable to Integrate")
    rule34 = ReplacementRule(pattern34, lambda n2, p, b, a, x, n, Qm, c, Pm : With34(n2, p, b, a, x, n, Qm, c, Pm))
    rubi.add(rule34)

    pattern35 = Pattern(Integral(Pq_**m_*Qr_**p_*WC('u', S(1)), x_), CustomConstraint(lambda m: PositiveIntegerQ(m)), CustomConstraint(lambda p: NegativeIntegerQ(p)), CustomConstraint(lambda Pq, x: PolyQ(Pq, x)), CustomConstraint(lambda Qr, x: PolyQ(Qr, x)), )
    def With35(Qr, p, u, Pq, m, x):
        gcd = PolyGCD(Pq, Qr, x)
        if NonzeroQ(gcd + S(-1)):
            return Int(gcd**(m + p)*u*PolynomialQuotient(Pq, gcd, x)**m*PolynomialQuotient(Qr, gcd, x)**p, x)
        print("Unable to Integrate")
    rule35 = ReplacementRule(pattern35, lambda Qr, p, u, Pq, m, x : With35(Qr, p, u, Pq, m, x))
    rubi.add(rule35)

    pattern36 = Pattern(Integral(Pq_*Qr_**p_*WC('u', S(1)), x_), CustomConstraint(lambda p: NegativeIntegerQ(p)), CustomConstraint(lambda Pq, x: PolyQ(Pq, x)), CustomConstraint(lambda Qr, x: PolyQ(Qr, x)), )
    def With36(Qr, p, u, Pq, x):
        gcd = PolyGCD(Pq, Qr, x)
        if NonzeroQ(gcd + S(-1)):
            return Int(gcd**(p + S(1))*u*PolynomialQuotient(Pq, gcd, x)*PolynomialQuotient(Qr, gcd, x)**p, x)
        print("Unable to Integrate")
    rule36 = ReplacementRule(pattern36, lambda Qr, p, u, Pq, x : With36(Qr, p, u, Pq, x))
    rubi.add(rule36)
    '''
    return rubi
Пример #38
0
def test_rs_series():
    x, a, b, c = symbols('x, a, b, c')

    assert rs_series(a, a, 5).as_expr() == a
    assert rs_series(sin(a), a, 5).as_expr() == (sin(a).series(a, 0,
                                                               5)).removeO()
    assert rs_series(sin(a) + cos(a), a,
                     5).as_expr() == ((sin(a) + cos(a)).series(a, 0,
                                                               5)).removeO()
    assert rs_series(sin(a) * cos(a), a,
                     5).as_expr() == ((sin(a) * cos(a)).series(a, 0,
                                                               5)).removeO()

    p = (sin(a) - a) * (cos(a**2) + a**4 / 2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(
        p.series(a, 0, 10).removeO())

    p = sin(a**2 / 2 + a / 3) + cos(a / 5) * sin(a / 2)**3
    assert expand(rs_series(p, a, 5).as_expr()) == expand(
        p.series(a, 0, 5).removeO())

    p = sin(x**2 + a) * (cos(x**3 - 1) - a - a**2)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(
        p.series(a, 0, 5).removeO())

    p = sin(a**2 - a / 3 + 2)**5 * exp(a**3 - a / 2)
    assert expand(rs_series(p, a, 10).as_expr()) == expand(
        p.series(a, 0, 10).removeO())

    p = sin(a + b + c)
    assert expand(rs_series(p, a, 5).as_expr()) == expand(
        p.series(a, 0, 5).removeO())

    p = tan(sin(a**2 + 4) + b + c)
    assert expand(rs_series(p, a, 6).as_expr()) == expand(
        p.series(a, 0, 6).removeO())

    p = a**QQ(2, 5) + a**QQ(2, 3) + a

    r = rs_series(tan(p), a, 2)
    assert r.as_expr() == a**QQ(9,5) + a**QQ(26,15) + a**QQ(22,15) + a**QQ(6,5)/3 + \
        a + a**QQ(2,3) + a**QQ(2,5)

    r = rs_series(exp(p), a, 1)
    assert r.as_expr() == a**QQ(4, 5) / 2 + a**QQ(2, 3) + a**QQ(2, 5) + 1

    r = rs_series(sin(p), a, 2)
    assert r.as_expr() == -a**QQ(9,5)/2 - a**QQ(26,15)/2 - a**QQ(22,15)/2 - \
        a**QQ(6,5)/6 + a + a**QQ(2,3) + a**QQ(2,5)

    r = rs_series(cos(p), a, 2)
    assert r.as_expr() == a**QQ(28,15)/6 - a**QQ(5,3) + a**QQ(8,5)/24 - a**QQ(7,5) - \
        a**QQ(4,3)/2 - a**QQ(16,15) - a**QQ(4,5)/2 + 1

    assert rs_series(sin(a) / 7, a,
                     5).as_expr() == (sin(a) / 7).series(a, 0, 5).removeO()

    assert rs_series(log(1 + x), x, 5).as_expr() == -x**4/4 + x**3/3 - \
                    x**2/2 + x
    assert rs_series(log(1 + 4*x), x, 5).as_expr() == -64*x**4 + 64*x**3/3 - \
                    8*x**2 + 4*x
    assert rs_series(log(1 + x + x**2), x, 10).as_expr() == -2*x**9/9 + \
                    x**8/8 + x**7/7 - x**6/3 + x**5/5 + x**4/4 - 2*x**3/3 + \
                    x**2/2 + x
    assert rs_series(log(1 + x*a**2), x, 7).as_expr() == -x**6*a**12/6 + \
                    x**5*a**10/5 - x**4*a**8/4 + x**3*a**6/3 - \
                    x**2*a**4/2 + x*a**2
Пример #39
0
    def _diff_wrt_parameter(self, idx):
        # Differentiation wrt a parameter can only be done in very special
        # cases. In particular, if we want to differentiate with respect to
        # `a`, all other gamma factors have to reduce to rational functions.
        #
        # Let MT denote mellin transform. Suppose T(-s) is the gamma factor
        # appearing in the definition of G. Then
        #
        #   MT(log(z)G(z)) = d/ds T(s) = d/da T(s) + ...
        #
        # Thus d/da G(z) = log(z)G(z) - ...
        # The ... can be evaluated as a G function under the above conditions,
        # the formula being most easily derived by using
        #
        # d  Gamma(s + n)    Gamma(s + n) / 1    1                1     \
        # -- ------------ =  ------------ | - + ----  + ... + --------- |
        # ds Gamma(s)        Gamma(s)     \ s   s + 1         s + n - 1 /
        #
        # which follows from the difference equation of the digamma function.
        # (There is a similar equation for -n instead of +n).

        # We first figure out how to pair the parameters.
        an = list(self.an)
        ap = list(self.aother)
        bm = list(self.bm)
        bq = list(self.bother)
        if idx < len(an):
            an.pop(idx)
        else:
            idx -= len(an)
            if idx < len(ap):
                ap.pop(idx)
            else:
                idx -= len(ap)
                if idx < len(bm):
                    bm.pop(idx)
                else:
                    bq.pop(idx - len(bm))
        pairs1 = []
        pairs2 = []
        for l1, l2, pairs in [(an, bq, pairs1), (ap, bm, pairs2)]:
            while l1:
                x = l1.pop()
                found = None
                for i, y in enumerate(l2):
                    if not Mod((x - y).simplify(), 1):
                        found = i
                        break
                if found is None:
                    raise NotImplementedError('Derivative not expressible '
                                              'as G-function?')
                y = l2[i]
                l2.pop(i)
                pairs.append((x, y))

        # Now build the result.
        res = log(self.argument) * self

        for a, b in pairs1:
            sign = 1
            n = a - b
            base = b
            if n < 0:
                sign = -1
                n = b - a
                base = a
            for k in range(n):
                res -= sign * meijerg(self.an + (base + k + 1, ), self.aother,
                                      self.bm, self.bother +
                                      (base + k + 0, ), self.argument)

        for a, b in pairs2:
            sign = 1
            n = b - a
            base = a
            if n < 0:
                sign = -1
                n = a - b
                base = b
            for k in range(n):
                res -= sign * meijerg(
                    self.an, self.aother + (base + k + 1, ), self.bm +
                    (base + k + 0, ), self.bother, self.argument)

        return res
Пример #40
0
    def _integrate(field=None):
        irreducibles = set()
        atans = set()
        pairs = set()

        for poly in reducibles:
            for z in poly.free_symbols:
                if z in V:
                    break  # should this be: `irreducibles |= \
            else:  # set(root_factors(poly, z, filter=field))`
                continue  # and the line below deleted?
                #               |
                #               V
            irreducibles |= set(root_factors(poly, z, filter=field))

        log_part, atan_part = [], []

        for poly in list(irreducibles):
            m = collect(poly, I, evaluate=False)
            y = m.get(I, S.Zero)
            if y:
                x = m.get(S.One, S.Zero)
                if x.has(I) or y.has(I):
                    continue  # nontrivial x + I*y
                pairs.add((x, y))
                irreducibles.remove(poly)

        while pairs:
            x, y = pairs.pop()
            if (x, -y) in pairs:
                pairs.remove((x, -y))
                # Choosing b with no minus sign
                if y.could_extract_minus_sign():
                    y = -y
                irreducibles.add(x * x + y * y)
                atans.add(atan(x / y))
            else:
                irreducibles.add(x + I * y)

        B = _symbols('B', len(irreducibles))
        C = _symbols('C', len(atans))

        # Note: the ordering matters here
        for poly, b in reversed(list(zip(ordered(irreducibles), B))):
            if poly.has(*V):
                poly_coeffs.append(b)
                log_part.append(b * log(poly))

        for poly, c in reversed(list(zip(ordered(atans), C))):
            if poly.has(*V):
                poly_coeffs.append(c)
                atan_part.append(c * poly)

        # TODO: Currently it's better to use symbolic expressions here instead
        # of rational functions, because it's simpler and FracElement doesn't
        # give big speed improvement yet. This is because cancellation is slow
        # due to slow polynomial GCD algorithms. If this gets improved then
        # revise this code.
        candidate = poly_part / poly_denom + Add(*log_part) + Add(*atan_part)
        h = F - _derivation(candidate) / denom
        raw_numer = h.as_numer_denom()[0]

        # Rewrite raw_numer as a polynomial in K[coeffs][V] where K is a field
        # that we have to determine. We can't use simply atoms() because log(3),
        # sqrt(y) and similar expressions can appear, leading to non-trivial
        # domains.
        syms = set(poly_coeffs) | set(V)
        non_syms = set([])

        def find_non_syms(expr):
            if expr.is_Integer or expr.is_Rational:
                pass  # ignore trivial numbers
            elif expr in syms:
                pass  # ignore variables
            elif not expr.has(*syms):
                non_syms.add(expr)
            elif expr.is_Add or expr.is_Mul or expr.is_Pow:
                list(map(find_non_syms, expr.args))
            else:
                # TODO: Non-polynomial expression. This should have been
                # filtered out at an earlier stage.
                raise PolynomialError

        try:
            find_non_syms(raw_numer)
        except PolynomialError:
            return None
        else:
            ground, _ = construct_domain(non_syms, field=True)

        coeff_ring = PolyRing(poly_coeffs, ground)
        ring = PolyRing(V, coeff_ring)
        try:
            numer = ring.from_expr(raw_numer)
        except ValueError:
            raise PolynomialError
        solution = solve_lin_sys(numer.coeffs(), coeff_ring, _raw=False)

        if solution is None:
            return None
        else:
            return candidate.subs(solution).subs(
                list(zip(poly_coeffs, [S.Zero] * len(poly_coeffs))))
Пример #41
0
 def _expr_small(cls, x):
     return log(1 - x)
Пример #42
0
def _denest_pow(eq):
    """
    Denest powers.

    This is a helper function for powdenest that performs the actual
    transformation.
    """
    from sympy.simplify.simplify import logcombine

    b, e = eq.as_base_exp()
    if b.is_Pow or isinstance(b.func, exp) and e != 1:
        new = b._eval_power(e)
        if new is not None:
            eq = new
            b, e = new.as_base_exp()

    # denest exp with log terms in exponent
    if b is S.Exp1 and e.is_Mul:
        logs = []
        other = []
        for ei in e.args:
            if any(isinstance(ai, log) for ai in Add.make_args(ei)):
                logs.append(ei)
            else:
                other.append(ei)
        logs = logcombine(Mul(*logs))
        return Pow(exp(logs), Mul(*other))

    _, be = b.as_base_exp()
    if be is S.One and not (b.is_Mul or b.is_Rational and b.q != 1
                            or b.is_positive):
        return eq

    # denest eq which is either pos**e or Pow**e or Mul**e or
    # Mul(b1**e1, b2**e2)

    # handle polar numbers specially
    polars, nonpolars = [], []
    for bb in Mul.make_args(b):
        if bb.is_polar:
            polars.append(bb.as_base_exp())
        else:
            nonpolars.append(bb)
    if len(polars) == 1 and not polars[0][0].is_Mul:
        return Pow(polars[0][0], polars[0][1] * e) * powdenest(
            Mul(*nonpolars)**e)
    elif polars:
        return Mul(*[powdenest(bb**(ee*e)) for (bb, ee) in polars]) \
            *powdenest(Mul(*nonpolars)**e)

    if b.is_Integer:
        # use log to see if there is a power here
        logb = expand_log(log(b))
        if logb.is_Mul:
            c, logb = logb.args
            e *= c
            base = logb.args[0]
            return Pow(base, e)

    # if b is not a Mul or any factor is an atom then there is nothing to do
    if not b.is_Mul or any(s.is_Atom for s in Mul.make_args(b)):
        return eq

    # let log handle the case of the base of the argument being a Mul, e.g.
    # sqrt(x**(2*i)*y**(6*i)) -> x**i*y**(3**i) if x and y are positive; we
    # will take the log, expand it, and then factor out the common powers that
    # now appear as coefficient. We do this manually since terms_gcd pulls out
    # fractions, terms_gcd(x+x*y/2) -> x*(y + 2)/2 and we don't want the 1/2;
    # gcd won't pull out numerators from a fraction: gcd(3*x, 9*x/2) -> x but
    # we want 3*x. Neither work with noncommutatives.

    def nc_gcd(aa, bb):
        a, b = [i.as_coeff_Mul() for i in [aa, bb]]
        c = gcd(a[0], b[0]).as_numer_denom()[0]
        g = Mul(*(a[1].args_cnc(cset=True)[0] & b[1].args_cnc(cset=True)[0]))
        return _keep_coeff(c, g)

    glogb = expand_log(log(b))
    if glogb.is_Add:
        args = glogb.args
        g = reduce(nc_gcd, args)
        if g != 1:
            cg, rg = g.as_coeff_Mul()
            glogb = _keep_coeff(cg, rg * Add(*[a / g for a in args]))

    # now put the log back together again
    if isinstance(glogb, log) or not glogb.is_Mul:
        if glogb.args[0].is_Pow or isinstance(glogb.args[0], exp):
            glogb = _denest_pow(glogb.args[0])
            if (abs(glogb.exp) < 1) == True:
                return Pow(glogb.base, glogb.exp * e)
        return eq

    # the log(b) was a Mul so join any adds with logcombine
    add = []
    other = []
    for a in glogb.args:
        if a.is_Add:
            add.append(a)
        else:
            other.append(a)
    return Pow(exp(logcombine(Mul(*add))), e * Mul(*other))
Пример #43
0
    def f(rv):
        if not (rv.is_Add or rv.is_Mul):
            return rv

        def gooda(a):
            # bool to tell whether the leading ``a`` in ``a*log(x)``
            # could appear as log(x**a)
            return (a is not S.NegativeOne
                    and  # -1 *could* go, but we disallow
                    (a.is_real or force and a.is_real is not False))

        def goodlog(l):
            # bool to tell whether log ``l``'s argument can combine with others
            a = l.args[0]
            return a.is_positive or force and a.is_nonpositive is not False

        other = []
        logs = []
        log1 = defaultdict(list)
        for a in Add.make_args(rv):
            if a.func is log and goodlog(a):
                log1[()].append(([], a))
            elif not a.is_Mul:
                other.append(a)
            else:
                ot = []
                co = []
                lo = []
                for ai in a.args:
                    if ai.is_Rational and ai < 0:
                        ot.append(S.NegativeOne)
                        co.append(-ai)
                    elif ai.func is log and goodlog(ai):
                        lo.append(ai)
                    elif gooda(ai):
                        co.append(ai)
                    else:
                        ot.append(ai)
                if len(lo) > 1:
                    logs.append((ot, co, lo))
                elif lo:
                    log1[tuple(ot)].append((co, lo[0]))
                else:
                    other.append(a)

        # if there is only one log at each coefficient and none have
        # an exponent to place inside the log then there is nothing to do
        if not logs and all(
                len(log1[k]) == 1 and log1[k][0] == [] for k in log1):
            return rv

        # collapse multi-logs as far as possible in a canonical way
        # TODO: see if x*log(a)+x*log(a)*log(b) -> x*log(a)*(1+log(b))?
        # -- in this case, it's unambiguous, but if it were were a log(c) in
        # each term then it's arbitrary whether they are grouped by log(a) or
        # by log(c). So for now, just leave this alone; it's probably better to
        # let the user decide
        for o, e, l in logs:
            l = list(ordered(l))
            e = log(l.pop(0).args[0]**Mul(*e))
            while l:
                li = l.pop(0)
                e = log(li.args[0]**e)
            c, l = Mul(*o), e
            if l.func is log:  # it should be, but check to be sure
                log1[(c, )].append(([], l))
            else:
                other.append(c * l)

        # logs that have the same coefficient can multiply
        for k in list(log1.keys()):
            log1[Mul(*k)] = log(
                logcombine(Mul(*[l.args[0]**Mul(*c) for c, l in log1.pop(k)]),
                           force=force))

        # logs that have oppositely signed coefficients can divide
        for k in ordered(list(log1.keys())):
            if not k in log1:  # already popped as -k
                continue
            if -k in log1:
                # figure out which has the minus sign; the one with
                # more op counts should be the one
                num, den = k, -k
                if num.count_ops() > den.count_ops():
                    num, den = den, num
                other.append(
                    num * log(log1.pop(num).args[0] / log1.pop(den).args[0]))
            else:
                other.append(k * log1.pop(k))

        return Add(*other)
Пример #44
0
def _invert_real(f, g_ys, symbol):
    """Helper function for _invert."""

    if f == symbol:
        return (f, g_ys)

    n = Dummy('n', real=True)

    if hasattr(f, 'inverse') and not isinstance(f, (
            TrigonometricFunction,
            HyperbolicFunction,
    )):
        if len(f.args) > 1:
            raise ValueError("Only functions with one argument are supported.")
        return _invert_real(f.args[0], imageset(Lambda(n,
                                                       f.inverse()(n)), g_ys),
                            symbol)

    if isinstance(f, Abs):
        pos = Interval(0, S.Infinity)
        neg = Interval(S.NegativeInfinity, 0)
        return _invert_real(
            f.args[0],
            Union(
                imageset(Lambda(n, n), g_ys).intersect(pos),
                imageset(Lambda(n, -n), g_ys).intersect(neg)), symbol)

    if f.is_Add:
        # f = g + h
        g, h = f.as_independent(symbol)
        if g is not S.Zero:
            return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol)

    if f.is_Mul:
        # f = g*h
        g, h = f.as_independent(symbol)

        if g is not S.One:
            return _invert_real(h, imageset(Lambda(n, n / g), g_ys), symbol)

    if f.is_Pow:
        base, expo = f.args
        base_has_sym = base.has(symbol)
        expo_has_sym = expo.has(symbol)

        if not expo_has_sym:
            res = imageset(Lambda(n, real_root(n, expo)), g_ys)
            if expo.is_rational:
                numer, denom = expo.as_numer_denom()
                if numer == S.One or numer == -S.One:
                    return _invert_real(base, res, symbol)
                else:
                    if numer % 2 == 0:
                        n = Dummy('n')
                        neg_res = imageset(Lambda(n, -n), res)
                        return _invert_real(base, res + neg_res, symbol)
                    else:
                        return _invert_real(base, res, symbol)
            else:
                if not base.is_positive:
                    raise ValueError("x**w where w is irrational is not "
                                     "defined for negative x")
                return _invert_real(base, res, symbol)

        if not base_has_sym:
            return _invert_real(expo,
                                imageset(Lambda(n,
                                                log(n) / log(base)), g_ys),
                                symbol)

    if isinstance(f, TrigonometricFunction):
        if isinstance(g_ys, FiniteSet):

            def inv(trig):
                if isinstance(f, (sin, csc)):
                    F = asin if isinstance(f, sin) else acsc
                    return (lambda a: n * pi + (-1)**n * F(a), )
                if isinstance(f, (cos, sec)):
                    F = acos if isinstance(f, cos) else asec
                    return (
                        lambda a: 2 * n * pi + F(a),
                        lambda a: 2 * n * pi - F(a),
                    )
                if isinstance(f, (tan, cot)):
                    return (lambda a: n * pi + f.inverse()(a), )

            n = Dummy('n', integer=True)
            invs = S.EmptySet
            for L in inv(f):
                invs += Union(
                    *[imageset(Lambda(n, L(g)), S.Integers) for g in g_ys])
            return _invert_real(f.args[0], invs, symbol)

    return (f, g_ys)
Пример #45
0
 def _expr_small(cls, z):
     return log(S.Half + sqrt(1 - z) / 2)
Пример #46
0
 def _expr_small_minus(cls, z):
     return log(S(1) / 2 + sqrt(1 + z) / 2)
Пример #47
0
def _(expr, assumptions):
    """
    * Real**Integer              -> Real
    * Positive**Real             -> Real
    * Real**(Integer/Even)       -> Real if base is nonnegative
    * Real**(Integer/Odd)        -> Real
    * Imaginary**(Integer/Even)  -> Real
    * Imaginary**(Integer/Odd)   -> not Real
    * Imaginary**Real            -> ? since Real could be 0 (giving real)
                                    or 1 (giving imaginary)
    * b**Imaginary               -> Real if log(b) is imaginary and b != 0
                                    and exponent != integer multiple of
                                    I*pi/log(b)
    * Real**Real                 -> ? e.g. sqrt(-1) is imaginary and
                                    sqrt(2) is not
    """
    if expr.is_number:
        return _RealPredicate_number(expr, assumptions)

    if expr.base == E:
        return ask(
            Q.integer(expr.exp/I/pi) | Q.real(expr.exp), assumptions
        )

    if expr.base.func == exp or (expr.base.is_Pow and expr.base.base == E):
        if ask(Q.imaginary(expr.base.exp), assumptions):
            if ask(Q.imaginary(expr.exp), assumptions):
                return True
        # If the i = (exp's arg)/(I*pi) is an integer or half-integer
        # multiple of I*pi then 2*i will be an integer. In addition,
        # exp(i*I*pi) = (-1)**i so the overall realness of the expr
        # can be determined by replacing exp(i*I*pi) with (-1)**i.
        i = expr.base.exp/I/pi
        if ask(Q.integer(2*i), assumptions):
            return ask(Q.real(((-1)**i)**expr.exp), assumptions)
        return

    if ask(Q.imaginary(expr.base), assumptions):
        if ask(Q.integer(expr.exp), assumptions):
            odd = ask(Q.odd(expr.exp), assumptions)
            if odd is not None:
                return not odd
            return

    if ask(Q.imaginary(expr.exp), assumptions):
        imlog = ask(Q.imaginary(log(expr.base)), assumptions)
        if imlog is not None:
            # I**i -> real, log(I) is imag;
            # (2*I)**i -> complex, log(2*I) is not imag
            return imlog

    if ask(Q.real(expr.base), assumptions):
        if ask(Q.real(expr.exp), assumptions):
            if expr.exp.is_Rational and \
                    ask(Q.even(expr.exp.q), assumptions):
                return ask(Q.positive(expr.base), assumptions)
            elif ask(Q.integer(expr.exp), assumptions):
                return True
            elif ask(Q.positive(expr.base), assumptions):
                return True
            elif ask(Q.negative(expr.base), assumptions):
                return False
Пример #48
0
def mrv(e, x):
    """Returns a SubsSet of most rapidly varying (mrv) subexpressions of 'e',
       and e rewritten in terms of these"""
    e = powsimp(e, deep=True, combine='exp')
    if not isinstance(e, Basic):
        raise TypeError("e should be an instance of Basic")
    if not e.has(x):
        return SubsSet(), e
    elif e == x:
        s = SubsSet()
        return s, s[x]
    elif e.is_Mul or e.is_Add:
        i, d = e.as_independent(x)  # throw away x-independent terms
        if d.func != e.func:
            s, expr = mrv(d, x)
            return s, e.func(i, expr)
        a, b = d.as_two_terms()
        s1, e1 = mrv(a, x)
        s2, e2 = mrv(b, x)
        return mrv_max1(s1, s2, e.func(i, e1, e2), x)
    elif e.is_Pow:
        b, e = e.as_base_exp()
        if b == 1:
            return SubsSet(), b
        if e.has(x):
            return mrv(exp(e * log(b)), x)
        else:
            s, expr = mrv(b, x)
            return s, expr**e
    elif isinstance(e, log):
        s, expr = mrv(e.args[0], x)
        return s, log(expr)
    elif isinstance(e, exp):
        # We know from the theory of this algorithm that exp(log(...)) may always
        # be simplified here, and doing so is vital for termination.
        if isinstance(e.args[0], log):
            return mrv(e.args[0].args[0], x)
        # if a product has an infinite factor the result will be
        # infinite if there is no zero, otherwise NaN; here, we
        # consider the result infinite if any factor is infinite
        li = limitinf(e.args[0], x)
        if any(_.is_infinite for _ in Mul.make_args(li)):
            s1 = SubsSet()
            e1 = s1[e]
            s2, e2 = mrv(e.args[0], x)
            su = s1.union(s2)[0]
            su.rewrites[e1] = exp(e2)
            return mrv_max3(s1, e1, s2, exp(e2), su, e1, x)
        else:
            s, expr = mrv(e.args[0], x)
            return s, exp(expr)
    elif e.is_Function:
        l = [mrv(a, x) for a in e.args]
        l2 = [s for (s, _) in l if s != SubsSet()]
        if len(l2) != 1:
            # e.g. something like BesselJ(x, x)
            raise NotImplementedError("MRV set computation for functions in"
                                      " several variables not implemented.")
        s, ss = l2[0], SubsSet()
        args = [ss.do_subs(x[1]) for x in l]
        return s, e.func(*args)
    elif e.is_Derivative:
        raise NotImplementedError("MRV set computation for derviatives"
                                  " not implemented yet.")
        return mrv(e.args[0], x)
    raise NotImplementedError("Don't know how to calculate the mrv of '%s'" %
                              e)
Пример #49
0
#init_printing()

print numpy.arccos(-1)
print math.acos(-1)
print acos(-1)

print acos(0)
print acos(0)

print acos(S.One/2)

x,y,z = symbols('x,y,z')
alpha,beta,gamma = symbols('alpha,beta,gamma')
print x+1
print log(alpha ** beta) + gamma
print sin(x)**2 + cos(x)**2
print simplify(sin(x)**2 + cos(x)**2)

mu,sigma = symbols('mu,sigma')
bell = exp(-(x-mu)**2 / 2*sigma**2)
print bell.diff(x)
print bell.diff(sigma)
print bell.diff(x).diff(x).diff(x)
print simplify(bell.diff(x).diff(x).diff(x))


print (x**2).diff(x)
print sin(x).diff(x)
print (x**2+x*y+y**2).diff(x)
print (x**2+x*y+y**2).diff(y)
Пример #50
0
 def _expr_big(cls, z, n):
     if n.is_even:
         return (n - S(1)/2)*pi*I + log(sqrt(z)/2) + I*asin(1/sqrt(z))
     else:
         return (n - S(1)/2)*pi*I + log(sqrt(z)/2) - I*asin(1/sqrt(z))
Пример #51
0
def test_harmonic_rational():
    ne = S(6)
    no = S(5)
    pe = S(8)
    po = S(9)
    qe = S(10)
    qo = S(13)

    Heee = harmonic(ne + pe/qe)
    Aeee = (-log(10) + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8)))
             + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8)))
             + pi*(1/S(4) + sqrt(5)/4)/(2*sqrt(-sqrt(5)/8 + 5/S(8)))
             + 13944145/S(4720968))

    Heeo = harmonic(ne + pe/qo)
    Aeeo = (-log(26) + 2*log(sin(3*pi/13))*cos(4*pi/13) + 2*log(sin(2*pi/13))*cos(32*pi/13)
             + 2*log(sin(5*pi/13))*cos(80*pi/13) - 2*log(sin(6*pi/13))*cos(5*pi/13)
             - 2*log(sin(4*pi/13))*cos(pi/13) + pi*cot(5*pi/13)/2 - 2*log(sin(pi/13))*cos(3*pi/13)
             + 2422020029/S(702257080))

    Heoe = harmonic(ne + po/qe)
    Aeoe = (-log(20) + 2*(1/S(4) + sqrt(5)/4)*log(-1/S(4) + sqrt(5)/4)
             + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8)))
             + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8)))
             + 2*(-sqrt(5)/4 + 1/S(4))*log(1/S(4) + sqrt(5)/4)
             + 11818877030/S(4286604231) + pi*(sqrt(5)/8 + 5/S(8))/sqrt(-sqrt(5)/8 + 5/S(8)))

    Heoo = harmonic(ne + po/qo)
    Aeoo = (-log(26) + 2*log(sin(3*pi/13))*cos(54*pi/13) + 2*log(sin(4*pi/13))*cos(6*pi/13)
             + 2*log(sin(6*pi/13))*cos(108*pi/13) - 2*log(sin(5*pi/13))*cos(pi/13)
             - 2*log(sin(pi/13))*cos(5*pi/13) + pi*cot(4*pi/13)/2
             - 2*log(sin(2*pi/13))*cos(3*pi/13) + 11669332571/S(3628714320))

    Hoee = harmonic(no + pe/qe)
    Aoee = (-log(10) + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8)))
             + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8)))
             + pi*(1/S(4) + sqrt(5)/4)/(2*sqrt(-sqrt(5)/8 + 5/S(8)))
             + 779405/S(277704))

    Hoeo = harmonic(no + pe/qo)
    Aoeo = (-log(26) + 2*log(sin(3*pi/13))*cos(4*pi/13) + 2*log(sin(2*pi/13))*cos(32*pi/13)
             + 2*log(sin(5*pi/13))*cos(80*pi/13) - 2*log(sin(6*pi/13))*cos(5*pi/13)
             - 2*log(sin(4*pi/13))*cos(pi/13) + pi*cot(5*pi/13)/2
             - 2*log(sin(pi/13))*cos(3*pi/13) + 53857323/S(16331560))

    Hooe = harmonic(no + po/qe)
    Aooe = (-log(20) + 2*(1/S(4) + sqrt(5)/4)*log(-1/S(4) + sqrt(5)/4)
             + 2*(-1/S(4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + 5/S(8)))
             + 2*(-sqrt(5)/4 - 1/S(4))*log(sqrt(sqrt(5)/8 + 5/S(8)))
             + 2*(-sqrt(5)/4 + 1/S(4))*log(1/S(4) + sqrt(5)/4)
             + 486853480/S(186374097) + pi*(sqrt(5)/8 + 5/S(8))/sqrt(-sqrt(5)/8 + 5/S(8)))

    Hooo = harmonic(no + po/qo)
    Aooo = (-log(26) + 2*log(sin(3*pi/13))*cos(54*pi/13) + 2*log(sin(4*pi/13))*cos(6*pi/13)
             + 2*log(sin(6*pi/13))*cos(108*pi/13) - 2*log(sin(5*pi/13))*cos(pi/13)
             - 2*log(sin(pi/13))*cos(5*pi/13) + pi*cot(4*pi/13)/2
             - 2*log(sin(2*pi/13))*cos(3*pi/13) + 383693479/S(125128080))

    H = [Heee, Heeo, Heoe, Heoo, Hoee, Hoeo, Hooe, Hooo]
    A = [Aeee, Aeeo, Aeoe, Aeoo, Aoee, Aoeo, Aooe, Aooo]

    for h, a in zip(H, A):
        e = expand_func(h).doit()
        assert cancel(e/a) == 1
        assert abs(h.n() - a.n()) < 1e-12
Пример #52
0
 def _expr_big_minus(cls, z, n):
     if n.is_even:
         return pi * I * n + log(S(1) / 2 + sqrt(1 + z) / 2)
     else:
         return pi * I * n + log(sqrt(1 + z) / 2 - S(1) / 2)
def test_1():
    '''
    Tests for Rubi Algebraic 1.2 rules. Parsed from Maple syntax
    All tests: http://www.apmaths.uwo.ca/~arich/IntegrationProblems/MapleSyntaxFiles/MapleSyntaxFiles.html
    Note: Some tests are commented since they depend rules other than Algebraic1.2.
    '''
    test = [
        [(a + b*x)**S(2)*(e + f*x)*sqrt(c + d*x)/x, x, S(5), S(2)/S(7)*f*(a + b*x)**S(2)*(c + d*x)**(S(3)/S(2))/d + S(2)/S(105)*(c + d*x)**(S(3)/S(2))*(S(2)*(S(10)*a**S(2)*d**S(2)*f - b**S(2)*c*(S(7)*d*e - S(4)*c*f) + S(7)*a*b*d*(S(5)*d*e - S(2)*c*f)) + S(3)*b*d*(S(7)*b*d*e - S(4)*b*c*f + S(4)*a*d*f)*x)/d**S(3) - S(2)*a**S(2)*e*arctanh(sqrt(c + d*x)/sqrt(c))*sqrt(c) + S(2)*a**S(2)*e*sqrt(c + d*x)],
        [(a + b*x)*(e + f*x)*sqrt(c + d*x)/x, x, S(4), - S(2)/S(15)*(c + d*x)**(S(3)/S(2))*(S(2)*b*c*f - S(5)*d*(b*e + a*f) - S(3)*b*d*f*x)/d**S(2) - S(2)*a*e*arctanh(sqrt(c + d*x)/sqrt(c))*sqrt(c) + S(2)*a*e*sqrt(c + d*x)],
        [(c + d*x)**S(2)*(e + f*x)*sqrt(a + b*x)/x, x, S(5), S(2)/S(7)*f*(a + b*x)**(S(3)/S(2))*(c + d*x)**S(2)/b + S(2)/S(105)*(a + b*x)**(S(3)/S(2))*(S(2)*(S(4)*a**S(2)*d**S(2)*f - S(7)*a*b*d*(d*e + S(2)*c*f) + S(5)*b**S(2)*c*(S(7)*d*e + S(2)*c*f)) + S(3)*b*d*(S(7)*b*d*e + S(4)*b*c*f - S(4)*a*d*f)*x)/b**S(3) - S(2)*c**S(2)*e*arctanh(sqrt(a + b*x)/sqrt(a))*sqrt(a) + S(2)*c**S(2)*e*sqrt(a + b*x)],
        [(c + d*x)*(e + f*x)*sqrt(a + b*x)/x, x, S(4), - S(2)/S(15)*(a + b*x)**(S(3)/S(2))*(S(2)*a*d*f - S(5)*b*(d*e + c*f) - S(3)*b*d*f*x)/b**S(2) - S(2)*c*e*arctanh(sqrt(a + b*x)/sqrt(a))*sqrt(a) + S(2)*c*e*sqrt(a + b*x)],
        [x**S(4)*(e + f*x)**n/((a + b*x)*(c + d*x)), x, S(8), e**S(2)*(e + f*x)**(S(1) + n)/(b*d*f**S(3)*(S(1) + n)) + (b*c + a*d)*e*(e + f*x)**(S(1) + n)/(b**S(2)*d**S(2)*f**S(2)*(S(1) + n)) + (b**S(2)*c**S(2) + a*b*c*d + a**S(2)*d**S(2))*(e + f*x)**(S(1) + n)/(b**S(3)*d**S(3)*f*(S(1) + n)) - S(2)*e*(e + f*x)**(S(2) + n)/(b*d*f**S(3)*(S(2) + n)) - (b*c + a*d)*(e + f*x)**(S(2) + n)/(b**S(2)*d**S(2)*f**S(2)*(S(2) + n)) + (e + f*x)**(S(3) + n)/(b*d*f**S(3)*(S(3) + n)) - a**S(4)*(e + f*x)**(S(1) + n)*hypergeom([S(1), S(1) + n], [S(2) + n], b*(e + f*x)/(b*e - a*f))/(b**S(3)*(b*c - a*d)*(b*e - a*f)*(S(1) + n)) + c**S(4)*(e + f*x)**(S(1) + n)*hypergeom([S(1), S(1) + n], [S(2) + n], d*(e + f*x)/(d*e - c*f))/(d**S(3)*(b*c - a*d)*(d*e - c*f)*(S(1) + n))],
        [(a + b*x)*(c + d*x)*(e + f*x)*(g + h*x), x, S(2), a*c*e*g*x + S(1)/S(2)*(b*c*e*g + a*(d*e*g + c*f*g + c*e*h))*x**S(2) + S(1)/S(3)*(b*(d*e*g + c*f*g + c*e*h) + a*(d*f*g + d*e*h + c*f*h))*x**S(3) + S(1)/S(4)*(a*d*f*h + b*(d*f*g + d*e*h + c*f*h))*x**S(4) + S(1)/S(5)*b*d*f*h*x**S(5)],
        [(a + b*x)*(c + d*x)*(e + f*x)/(g + h*x), x, S(2), (b*(d*g - c*h)*(f*g - e*h) - a*h*(d*f*g - d*e*h - c*f*h))*x/h**S(3) + S(1)/S(2)*(a*d*f*h - b*(d*f*g - d*e*h - c*f*h))*x**S(2)/h**S(2) + S(1)/S(3)*b*d*f*x**S(3)/h - (b*g - a*h)*(d*g - c*h)*(f*g - e*h)*log(g + h*x)/h**S(4)],
        [(a + b*x)**m*(c + d*x)*(e + f*x)*(g + h*x), x, S(2), (b*c - a*d)*(b*e - a*f)*(b*g - a*h)*(a + b*x)**(S(1) + m)/(b**S(4)*(S(1) + m)) + (S(3)*a**S(2)*d*f*h + b**S(2)*(d*e*g + c*f*g + c*e*h) - S(2)*a*b*(d*f*g + d*e*h + c*f*h))*(a + b*x)**(S(2) + m)/(b**S(4)*(S(2) + m)) - (S(3)*a*d*f*h - b*(d*f*g + d*e*h + c*f*h))*(a + b*x)**(S(3) + m)/(b**S(4)*(S(3) + m)) + d*f*h*(a + b*x)**(S(4) + m)/(b**S(4)*(S(4) + m))],
        [(c + d*x)**( - S(4) - m)*(e + f*x)**m*(g + h*x), x, S(3), - (d*g - c*h)*(c + d*x)**( - S(3) - m)*(e + f*x)**(S(1) + m)/(d*(d*e - c*f)*(S(3) + m)) + (c*f*h*(S(1) + m) + d*(S(2)*f*g - e*h*(S(3) + m)))*(c + d*x)**( - S(2) - m)*(e + f*x)**(S(1) + m)/(d*(d*e - c*f)**S(2)*(S(2) + m)*(S(3) + m)) - f*(c*f*h*(S(1) + m) + d*(S(2)*f*g - e*h*(S(3) + m)))*(c + d*x)**( - S(1) - m)*(e + f*x)**(S(1) + m)/(d*(d*e - c*f)**S(3)*(S(1) + m)*(S(2) + m)*(S(3) + m))],
    ]
    for i in test:
        r = rubi_integrate(i[0], i[1])
        if len(i) == 5:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True) or rubi_test(r, i[1], i[4], expand=True, _diff=True)
        else:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True)
Пример #54
0
def _invert_real(f, g_ys, symbol):
    """ Helper function for invert_real """

    if not f.has(symbol):
        raise ValueError("Inverse of constant function doesn't exist")

    if f is symbol:
        return (f, g_ys)

    n = Dummy('n')
    if hasattr(f, 'inverse') and not isinstance(f, C.TrigonometricFunction):
        if len(f.args) > 1:
            raise ValueError("Only functions with one argument are supported.")
        return _invert_real(f.args[0], imageset(Lambda(n,
                                                       f.inverse()(n)), g_ys),
                            symbol)

    if isinstance(f, Abs):
        return _invert_real(f.args[0],
                            Union(g_ys, imageset(Lambda(n, -n), g_ys)), symbol)

    if f.is_Add:
        # f = g + h
        g, h = f.as_independent(symbol)
        if g != S.Zero:
            return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol)

    if f.is_Mul:
        # f = g*h
        g, h = f.as_independent(symbol)

        if g != S.One:
            return _invert_real(h, imageset(Lambda(n, n / g), g_ys), symbol)

    if f.is_Pow:
        base, expo = f.args
        base_has_sym = base.has(symbol)
        expo_has_sym = expo.has(symbol)

        if not expo_has_sym:
            res = imageset(Lambda(n, Pow(n, 1 / expo)), g_ys)
            if expo.is_rational:
                numer, denom = expo.as_numer_denom()
                if numer == S.One or numer == -S.One:
                    return _invert_real(base, res, symbol)
                else:
                    if numer % 2 == 0:
                        n = Dummy('n')
                        neg_res = imageset(Lambda(n, -n), res)
                        return _invert_real(base, res + neg_res, symbol)
                    else:
                        return _invert_real(base, res, symbol)
            else:
                if not base.is_positive:
                    raise ValueError("x**w where w is irrational is not"
                                     "defined for negative x")
                return _invert_real(base, res, symbol)

        if not base_has_sym:
            return _invert_real(expo,
                                imageset(Lambda(n,
                                                log(n) / log(base)), g_ys),
                                symbol)

    if isinstance(f, tan) or isinstance(f, cot):
        n = Dummy('n')
        if isinstance(g_ys, FiniteSet):
            tan_cot_invs = Union(*[
                imageset(Lambda(n, n * pi + f.inverse()(g_y)), S.Integers)
                for g_y in g_ys
            ])
            return _invert_real(f.args[0], tan_cot_invs, symbol)

    return (f, g_ys)
Пример #55
0
def heurisch(f,
             x,
             rewrite=False,
             hints=None,
             mappings=None,
             retries=3,
             degree_offset=0,
             unnecessary_permutations=None,
             _try_heurisch=None):
    """
    Compute indefinite integral using heuristic Risch algorithm.

    This is a heuristic approach to indefinite integration in finite
    terms using the extended heuristic (parallel) Risch algorithm, based
    on Manuel Bronstein's "Poor Man's Integrator".

    The algorithm supports various classes of functions including
    transcendental elementary or special functions like Airy,
    Bessel, Whittaker and Lambert.

    Note that this algorithm is not a decision procedure. If it isn't
    able to compute the antiderivative for a given function, then this is
    not a proof that such a functions does not exist.  One should use
    recursive Risch algorithm in such case.  It's an open question if
    this algorithm can be made a full decision procedure.

    This is an internal integrator procedure. You should use toplevel
    'integrate' function in most cases,  as this procedure needs some
    preprocessing steps and otherwise may fail.

    Specification
    =============

     heurisch(f, x, rewrite=False, hints=None)

       where
         f : expression
         x : symbol

         rewrite -> force rewrite 'f' in terms of 'tan' and 'tanh'
         hints   -> a list of functions that may appear in anti-derivate

          - hints = None          --> no suggestions at all
          - hints = [ ]           --> try to figure out
          - hints = [f1, ..., fn] --> we know better

    Examples
    ========

    >>> from sympy import tan
    >>> from sympy.integrals.heurisch import heurisch
    >>> from sympy.abc import x, y

    >>> heurisch(y*tan(x), x)
    y*log(tan(x)**2 + 1)/2

    See Manuel Bronstein's "Poor Man's Integrator":

    [1] http://www-sop.inria.fr/cafe/Manuel.Bronstein/pmint/index.html

    For more information on the implemented algorithm refer to:

    [2] K. Geddes, L. Stefanus, On the Risch-Norman Integration
       Method and its Implementation in Maple, Proceedings of
       ISSAC'89, ACM Press, 212-217.

    [3] J. H. Davenport, On the Parallel Risch Algorithm (I),
       Proceedings of EUROCAM'82, LNCS 144, Springer, 144-157.

    [4] J. H. Davenport, On the Parallel Risch Algorithm (III):
       Use of Tangents, SIGSAM Bulletin 16 (1982), 3-6.

    [5] J. H. Davenport, B. M. Trager, On the Parallel Risch
       Algorithm (II), ACM Transactions on Mathematical
       Software 11 (1985), 356-362.

    See Also
    ========

    sympy.integrals.integrals.Integral.doit
    sympy.integrals.integrals.Integral
    sympy.integrals.heurisch.components
    """
    f = sympify(f)

    # There are some functions that Heurisch cannot currently handle,
    # so do not even try.
    # Set _try_heurisch=True to skip this check
    if _try_heurisch is not True:
        if f.has(Abs, re, im, sign, Heaviside, DiracDelta, floor, ceiling,
                 arg):
            return

    if x not in f.free_symbols:
        return f * x

    if not f.is_Add:
        indep, f = f.as_independent(x)
    else:
        indep = S.One

    rewritables = {
        (sin, cos, cot): tan,
        (sinh, cosh, coth): tanh,
    }

    if rewrite:
        for candidates, rule in rewritables.items():
            f = f.rewrite(candidates, rule)
    else:
        for candidates in rewritables.keys():
            if f.has(*candidates):
                break
        else:
            rewrite = True

    terms = components(f, x)

    if hints is not None:
        if not hints:
            a = Wild('a', exclude=[x])
            b = Wild('b', exclude=[x])
            c = Wild('c', exclude=[x])

            for g in set(terms):  # using copy of terms
                if g.is_Function:
                    if isinstance(g, li):
                        M = g.args[0].match(a * x**b)

                        if M is not None:
                            terms.add(
                                x *
                                (li(M[a] * x**M[b]) -
                                 (M[a] * x**M[b])**(-1 / M[b]) * Ei(
                                     (M[b] + 1) * log(M[a] * x**M[b]) / M[b])))
                            #terms.add( x*(li(M[a]*x**M[b]) - (x**M[b])**(-1/M[b])*Ei((M[b]+1)*log(M[a]*x**M[b])/M[b])) )
                            #terms.add( x*(li(M[a]*x**M[b]) - x*Ei((M[b]+1)*log(M[a]*x**M[b])/M[b])) )
                            #terms.add( li(M[a]*x**M[b]) - Ei((M[b]+1)*log(M[a]*x**M[b])/M[b]) )

                    elif isinstance(g, exp):
                        M = g.args[0].match(a * x**2)

                        if M is not None:
                            if M[a].is_positive:
                                terms.add(erfi(sqrt(M[a]) * x))
                            else:  # M[a].is_negative or unknown
                                terms.add(erf(sqrt(-M[a]) * x))

                        M = g.args[0].match(a * x**2 + b * x + c)

                        if M is not None:
                            if M[a].is_positive:
                                terms.add(
                                    sqrt(pi / 4 * (-M[a])) *
                                    exp(M[c] - M[b]**2 / (4 * M[a])) * erfi(
                                        sqrt(M[a]) * x + M[b] /
                                        (2 * sqrt(M[a]))))
                            elif M[a].is_negative:
                                terms.add(
                                    sqrt(pi / 4 * (-M[a])) *
                                    exp(M[c] - M[b]**2 / (4 * M[a])) * erf(
                                        sqrt(-M[a]) * x - M[b] /
                                        (2 * sqrt(-M[a]))))

                        M = g.args[0].match(a * log(x)**2)

                        if M is not None:
                            if M[a].is_positive:
                                terms.add(
                                    erfi(
                                        sqrt(M[a]) * log(x) + 1 /
                                        (2 * sqrt(M[a]))))
                            if M[a].is_negative:
                                terms.add(
                                    erf(
                                        sqrt(-M[a]) * log(x) - 1 /
                                        (2 * sqrt(-M[a]))))

                elif g.is_Pow:
                    if g.exp.is_Rational and g.exp.q == 2:
                        M = g.base.match(a * x**2 + b)

                        if M is not None and M[b].is_positive:
                            if M[a].is_positive:
                                terms.add(asinh(sqrt(M[a] / M[b]) * x))
                            elif M[a].is_negative:
                                terms.add(asin(sqrt(-M[a] / M[b]) * x))

                        M = g.base.match(a * x**2 - b)

                        if M is not None and M[b].is_positive:
                            if M[a].is_positive:
                                terms.add(acosh(sqrt(M[a] / M[b]) * x))
                            elif M[a].is_negative:
                                terms.add((-M[b] / 2 * sqrt(-M[a]) * atan(
                                    sqrt(-M[a]) * x / sqrt(M[a] * x**2 - M[b]))
                                           ))

        else:
            terms |= set(hints)

    dcache = DiffCache(x)

    for g in set(terms):  # using copy of terms
        terms |= components(dcache.get_diff(g), x)

    # TODO: caching is significant factor for why permutations work at all. Change this.
    V = _symbols('x', len(terms))

    # sort mapping expressions from largest to smallest (last is always x).
    mapping = list(
        reversed(
            list(
                zip(*ordered(  #
                    [(a[0].as_independent(x)[1], a)
                     for a in zip(terms, V)])))[1]))  #
    rev_mapping = {v: k for k, v in mapping}  #
    if mappings is None:  #
        # optimizing the number of permutations of mapping              #
        assert mapping[-1][0] == x  # if not, find it and correct this comment
        unnecessary_permutations = [mapping.pop(-1)]
        mappings = permutations(mapping)
    else:
        unnecessary_permutations = unnecessary_permutations or []

    def _substitute(expr):
        return expr.subs(mapping)

    for mapping in mappings:
        mapping = list(mapping)
        mapping = mapping + unnecessary_permutations
        diffs = [_substitute(dcache.get_diff(g)) for g in terms]
        denoms = [g.as_numer_denom()[1] for g in diffs]
        if all(h.is_polynomial(*V)
               for h in denoms) and _substitute(f).is_rational_function(*V):
            denom = reduce(lambda p, q: lcm(p, q, *V), denoms)
            break
    else:
        if not rewrite:
            result = heurisch(
                f,
                x,
                rewrite=True,
                hints=hints,
                unnecessary_permutations=unnecessary_permutations)

            if result is not None:
                return indep * result
        return None

    numers = [cancel(denom * g) for g in diffs]

    def _derivation(h):
        return Add(*[d * h.diff(v) for d, v in zip(numers, V)])

    def _deflation(p):
        for y in V:
            if not p.has(y):
                continue

            if _derivation(p) is not S.Zero:
                c, q = p.as_poly(y).primitive()
                return _deflation(c) * gcd(q, q.diff(y)).as_expr()

        return p

    def _splitter(p):
        for y in V:
            if not p.has(y):
                continue

            if _derivation(y) is not S.Zero:
                c, q = p.as_poly(y).primitive()

                q = q.as_expr()

                h = gcd(q, _derivation(q), y)
                s = quo(h, gcd(q, q.diff(y), y), y)

                c_split = _splitter(c)

                if s.as_poly(y).degree() == 0:
                    return (c_split[0], q * c_split[1])

                q_split = _splitter(cancel(q / s))

                return (c_split[0] * q_split[0] * s, c_split[1] * q_split[1])

        return (S.One, p)

    special = {}

    for term in terms:
        if term.is_Function:
            if isinstance(term, tan):
                special[1 + _substitute(term)**2] = False
            elif isinstance(term, tanh):
                special[1 + _substitute(term)] = False
                special[1 - _substitute(term)] = False
            elif isinstance(term, LambertW):
                special[_substitute(term)] = True

    F = _substitute(f)

    P, Q = F.as_numer_denom()

    u_split = _splitter(denom)
    v_split = _splitter(Q)

    polys = set(list(v_split) + [u_split[0]] + list(special.keys()))

    s = u_split[0] * Mul(*[k for k, v in special.items() if v])
    polified = [p.as_poly(*V) for p in [s, P, Q]]

    if None in polified:
        return None

    #--- definitions for _integrate
    a, b, c = [p.total_degree() for p in polified]

    poly_denom = (s * v_split[0] * _deflation(v_split[1])).as_expr()

    def _exponent(g):
        if g.is_Pow:
            if g.exp.is_Rational and g.exp.q != 1:
                if g.exp.p > 0:
                    return g.exp.p + g.exp.q - 1
                else:
                    return abs(g.exp.p + g.exp.q)
            else:
                return 1
        elif not g.is_Atom and g.args:
            return max([_exponent(h) for h in g.args])
        else:
            return 1

    A, B = _exponent(f), a + max(b, c)

    if A > 1 and B > 1:
        monoms = tuple(ordered(itermonomials(V, A + B - 1 + degree_offset)))
    else:
        monoms = tuple(ordered(itermonomials(V, A + B + degree_offset)))

    poly_coeffs = _symbols('A', len(monoms))

    poly_part = Add(
        *[poly_coeffs[i] * monomial for i, monomial in enumerate(monoms)])

    reducibles = set()

    for poly in polys:
        if poly.has(*V):
            try:
                factorization = factor(poly, greedy=True)
            except PolynomialError:
                factorization = poly

            if factorization.is_Mul:
                factors = factorization.args
            else:
                factors = (factorization, )

            for fact in factors:
                if fact.is_Pow:
                    reducibles.add(fact.base)
                else:
                    reducibles.add(fact)

    def _integrate(field=None):
        irreducibles = set()
        atans = set()
        pairs = set()

        for poly in reducibles:
            for z in poly.free_symbols:
                if z in V:
                    break  # should this be: `irreducibles |= \
            else:  # set(root_factors(poly, z, filter=field))`
                continue  # and the line below deleted?
                #               |
                #               V
            irreducibles |= set(root_factors(poly, z, filter=field))

        log_part, atan_part = [], []

        for poly in list(irreducibles):
            m = collect(poly, I, evaluate=False)
            y = m.get(I, S.Zero)
            if y:
                x = m.get(S.One, S.Zero)
                if x.has(I) or y.has(I):
                    continue  # nontrivial x + I*y
                pairs.add((x, y))
                irreducibles.remove(poly)

        while pairs:
            x, y = pairs.pop()
            if (x, -y) in pairs:
                pairs.remove((x, -y))
                # Choosing b with no minus sign
                if y.could_extract_minus_sign():
                    y = -y
                irreducibles.add(x * x + y * y)
                atans.add(atan(x / y))
            else:
                irreducibles.add(x + I * y)

        B = _symbols('B', len(irreducibles))
        C = _symbols('C', len(atans))

        # Note: the ordering matters here
        for poly, b in reversed(list(zip(ordered(irreducibles), B))):
            if poly.has(*V):
                poly_coeffs.append(b)
                log_part.append(b * log(poly))

        for poly, c in reversed(list(zip(ordered(atans), C))):
            if poly.has(*V):
                poly_coeffs.append(c)
                atan_part.append(c * poly)

        # TODO: Currently it's better to use symbolic expressions here instead
        # of rational functions, because it's simpler and FracElement doesn't
        # give big speed improvement yet. This is because cancellation is slow
        # due to slow polynomial GCD algorithms. If this gets improved then
        # revise this code.
        candidate = poly_part / poly_denom + Add(*log_part) + Add(*atan_part)
        h = F - _derivation(candidate) / denom
        raw_numer = h.as_numer_denom()[0]

        # Rewrite raw_numer as a polynomial in K[coeffs][V] where K is a field
        # that we have to determine. We can't use simply atoms() because log(3),
        # sqrt(y) and similar expressions can appear, leading to non-trivial
        # domains.
        syms = set(poly_coeffs) | set(V)
        non_syms = set([])

        def find_non_syms(expr):
            if expr.is_Integer or expr.is_Rational:
                pass  # ignore trivial numbers
            elif expr in syms:
                pass  # ignore variables
            elif not expr.has(*syms):
                non_syms.add(expr)
            elif expr.is_Add or expr.is_Mul or expr.is_Pow:
                list(map(find_non_syms, expr.args))
            else:
                # TODO: Non-polynomial expression. This should have been
                # filtered out at an earlier stage.
                raise PolynomialError

        try:
            find_non_syms(raw_numer)
        except PolynomialError:
            return None
        else:
            ground, _ = construct_domain(non_syms, field=True)

        coeff_ring = PolyRing(poly_coeffs, ground)
        ring = PolyRing(V, coeff_ring)
        try:
            numer = ring.from_expr(raw_numer)
        except ValueError:
            raise PolynomialError
        solution = solve_lin_sys(numer.coeffs(), coeff_ring, _raw=False)

        if solution is None:
            return None
        else:
            return candidate.subs(solution).subs(
                list(zip(poly_coeffs, [S.Zero] * len(poly_coeffs))))

    if not (F.free_symbols - set(V)):
        solution = _integrate('Q')

        if solution is None:
            solution = _integrate()
    else:
        solution = _integrate()

    if solution is not None:
        antideriv = solution.subs(rev_mapping)
        antideriv = cancel(antideriv).expand(force=True)

        if antideriv.is_Add:
            antideriv = antideriv.as_independent(x)[1]

        return indep * antideriv
    else:
        if retries >= 0:
            result = heurisch(
                f,
                x,
                mappings=mappings,
                rewrite=rewrite,
                hints=hints,
                retries=retries - 1,
                unnecessary_permutations=unnecessary_permutations)

            if result is not None:
                return indep * result

        return None
Пример #56
0
def heurisch(f, x, **kwargs):
    """Compute indefinite integral using heuristic Risch algorithm.

       This is a heuristic approach to indefinite integration in finite
       terms using the extended heuristic (parallel) Risch algorithm, based
       on Manuel Bronstein's "Poor Man's Integrator".

       The algorithm supports various classes of functions including
       transcendental elementary or special functions like Airy,
       Bessel, Whittaker and Lambert.

       Note that this algorithm is not a decision procedure. If it isn't
       able to compute the antiderivative for a given function, then this is
       not a proof that such a functions does not exist.  One should use
       recursive Risch algorithm in such case.  It's an open question if
       this algorithm can be made a full decision procedure.

       This is an internal integrator procedure. You should use toplevel
       'integrate' function in most cases,  as this procedure needs some
       preprocessing steps and otherwise may fail.

       Specification
       ============

         heurisch(f, x, rewrite=False, hints=None)

           where
             f : expression
             x : symbol

             rewrite -> force rewrite 'f' in terms of 'tan' and 'tanh'
             hints   -> a list of functions that may appear in anti-derivate

              - hints = None          --> no suggestions at all
              - hints = [ ]           --> try to figure out
              - hints = [f1, ..., fn] --> we know better

       Examples
       ========

       >>> from sympy import tan
       >>> from sympy.integrals.risch import heurisch
       >>> from sympy.abc import x, y

       >>> heurisch(y*tan(x), x)
       y*log(tan(x)**2 + 1)/2

       See Manuel Bronstein's "Poor Man's Integrator":

       [1] http://www-sop.inria.fr/cafe/Manuel.Bronstein/pmint/index.html

       For more information on the implemented algorithm refer to:

       [2] K. Geddes, L. Stefanus, On the Risch-Norman Integration
           Method and its Implementation in Maple, Proceedings of
           ISSAC'89, ACM Press, 212-217.

       [3] J. H. Davenport, On the Parallel Risch Algorithm (I),
           Proceedings of EUROCAM'82, LNCS 144, Springer, 144-157.

       [4] J. H. Davenport, On the Parallel Risch Algorithm (III):
           Use of Tangents, SIGSAM Bulletin 16 (1982), 3-6.

       [5] J. H. Davenport, B. M. Trager, On the Parallel Risch
           Algorithm (II), ACM Transactions on Mathematical
           Software 11 (1985), 356-362.

    """
    f = sympify(f)

    if not f.is_Add:
        indep, f = f.as_independent(x)
    else:
        indep = S.One

    if not f.has(x):
        return indep * f * x

    rewritables = {
        (sin, cos, cot): tan,
        (sinh, cosh, coth): tanh,
    }

    rewrite = kwargs.pop('rewrite', False)

    if rewrite:
        for candidates, rule in rewritables.iteritems():
            f = f.rewrite(candidates, rule)
    else:
        for candidates in rewritables.iterkeys():
            if f.has(*candidates):
                break
        else:
            rewrite = True

    terms = components(f, x)

    hints = kwargs.get('hints', None)

    if hints is not None:
        if not hints:
            a = Wild('a', exclude=[x])
            b = Wild('b', exclude=[x])
            c = Wild('c', exclude=[x])

            for g in set(terms):
                if g.is_Function:
                    if g.func is exp:
                        M = g.args[0].match(a * x**2)

                        if M is not None:
                            terms.add(erf(sqrt(-M[a]) * x))

                        M = g.args[0].match(a * x**2 + b * x + c)

                        if M is not None:
                            if M[a].is_positive:
                                terms.add(sqrt(pi/4*(-M[a]))*exp(M[c]-M[b]**2/(4*M[a]))* \
                                          erf(-sqrt(-M[a])*x + M[b]/(2*sqrt(-M[a]))))
                            elif M[a].is_negative:
                                terms.add(sqrt(pi/4*(-M[a]))*exp(M[c]-M[b]**2/(4*M[a]))* \
                                          erf(sqrt(-M[a])*x - M[b]/(2*sqrt(-M[a]))))

                        M = g.args[0].match(a * log(x)**2)

                        if M is not None:
                            if M[a].is_positive:
                                terms.add(-I * erf(I *
                                                   (sqrt(M[a]) * log(x) + 1 /
                                                    (2 * sqrt(M[a])))))
                            if M[a].is_negative:
                                terms.add(
                                    erf(
                                        sqrt(-M[a]) * log(x) - 1 /
                                        (2 * sqrt(-M[a]))))

                elif g.is_Pow:
                    if g.exp.is_Rational and g.exp.q == 2:
                        M = g.base.match(a * x**2 + b)

                        if M is not None and M[b].is_positive:
                            if M[a].is_positive:
                                terms.add(asinh(sqrt(M[a] / M[b]) * x))
                            elif M[a].is_negative:
                                terms.add(asin(sqrt(-M[a] / M[b]) * x))

                        M = g.base.match(a * x**2 - b)

                        if M is not None and M[b].is_positive:
                            if M[a].is_positive:
                                terms.add(acosh(sqrt(M[a] / M[b]) * x))
                            elif M[a].is_negative:
                                terms.add((-M[b]/2*sqrt(-M[a])*\
                                           atan(sqrt(-M[a])*x/sqrt(M[a]*x**2-M[b]))))

        else:
            terms |= set(hints)

    for g in set(terms):
        terms |= components(cancel(g.diff(x)), x)

    V = _symbols('x', len(terms))

    mapping = dict(zip(terms, V))

    rev_mapping = {}

    for k, v in mapping.iteritems():
        rev_mapping[v] = k

    def substitute(expr):
        return expr.subs(mapping)

    diffs = [substitute(cancel(g.diff(x))) for g in terms]

    denoms = [g.as_numer_denom()[1] for g in diffs]
    try:
        denom = reduce(lambda p, q: lcm(p, q, *V), denoms)
    except PolynomialError:
        # lcm can fail with this. See issue 1418.
        return None

    numers = [cancel(denom * g) for g in diffs]

    def derivation(h):
        return Add(*[d * h.diff(v) for d, v in zip(numers, V)])

    def deflation(p):
        for y in V:
            if not p.has(y):
                continue

            if derivation(p) is not S.Zero:
                c, q = p.as_poly(y).primitive()
                return deflation(c) * gcd(q, q.diff(y)).as_expr()
        else:
            return p

    def splitter(p):
        for y in V:
            if not p.has(y):
                continue

            if derivation(y) is not S.Zero:
                c, q = p.as_poly(y).primitive()

                q = q.as_expr()

                h = gcd(q, derivation(q), y)
                s = quo(h, gcd(q, q.diff(y), y), y)

                c_split = splitter(c)

                if s.as_poly(y).degree() == 0:
                    return (c_split[0], q * c_split[1])

                q_split = splitter(cancel(q / s))

                return (c_split[0] * q_split[0] * s, c_split[1] * q_split[1])
        else:
            return (S.One, p)

    special = {}

    for term in terms:
        if term.is_Function:
            if term.func is tan:
                special[1 + substitute(term)**2] = False
            elif term.func is tanh:
                special[1 + substitute(term)] = False
                special[1 - substitute(term)] = False
            elif term.func is C.LambertW:
                special[substitute(term)] = True

    F = substitute(f)

    P, Q = F.as_numer_denom()

    u_split = splitter(denom)
    v_split = splitter(Q)

    polys = list(v_split) + [u_split[0]] + special.keys()

    s = u_split[0] * Mul(*[k for k, v in special.iteritems() if v])
    polified = [p.as_poly(*V) for p in [s, P, Q]]
    if None in polified:
        return
    a, b, c = [p.total_degree() for p in polified]

    poly_denom = (s * v_split[0] * deflation(v_split[1])).as_expr()

    def exponent(g):
        if g.is_Pow:
            if g.exp.is_Rational and g.exp.q != 1:
                if g.exp.p > 0:
                    return g.exp.p + g.exp.q - 1
                else:
                    return abs(g.exp.p + g.exp.q)
            else:
                return 1
        elif not g.is_Atom:
            return max([exponent(h) for h in g.args])
        else:
            return 1

    A, B = exponent(f), a + max(b, c)

    if A > 1 and B > 1:
        monoms = monomials(V, A + B - 1)
    else:
        monoms = monomials(V, A + B)

    poly_coeffs = _symbols('A', len(monoms))

    poly_part = Add(
        *[poly_coeffs[i] * monomial for i, monomial in enumerate(monoms)])

    reducibles = set()

    for poly in polys:
        if poly.has(*V):
            try:
                factorization = factor(poly, greedy=True)
            except PolynomialError:
                factorization = poly
            factorization = poly

            if factorization.is_Mul:
                reducibles |= set(factorization.args)
            else:
                reducibles.add(factorization)

    def integrate(field=None):
        irreducibles = set()

        for poly in reducibles:
            for z in poly.atoms(Symbol):
                if z in V:
                    break
            else:
                continue

            irreducibles |= set(root_factors(poly, z, filter=field))

        log_coeffs, log_part = [], []
        B = _symbols('B', len(irreducibles))

        for i, poly in enumerate(irreducibles):
            if poly.has(*V):
                log_coeffs.append(B[i])
                log_part.append(log_coeffs[-1] * log(poly))

        coeffs = poly_coeffs + log_coeffs

        candidate = poly_part / poly_denom + Add(*log_part)

        h = F - derivation(candidate) / denom

        numer = h.as_numer_denom()[0].expand(force=True)

        equations = {}

        for term in Add.make_args(numer):
            coeff, dependent = term.as_independent(*V)

            if dependent in equations:
                equations[dependent] += coeff
            else:
                equations[dependent] = coeff

        solution = solve(equations.values(), *coeffs)

        if solution is not None:
            return (solution, candidate, coeffs)
        else:
            return None

    if not (F.atoms(Symbol) - set(V)):
        result = integrate('Q')

        if result is None:
            result = integrate()
    else:
        result = integrate()

    if result is not None:
        (solution, candidate, coeffs) = result

        antideriv = candidate.subs(solution)

        for coeff in coeffs:
            if coeff not in solution:
                antideriv = antideriv.subs(coeff, S.Zero)

        antideriv = antideriv.subs(rev_mapping)
        antideriv = cancel(antideriv).expand(force=True)

        if antideriv.is_Add:
            antideriv = antideriv.as_independent(x)[1]

        return indep * antideriv
    else:
        if not rewrite:
            result = heurisch(f, x, rewrite=True, **kwargs)

            if result is not None:
                return indep * result

        return None
Пример #57
0
 def _expr_small_minus(cls, x):
     return log(1 + x)
Пример #58
0
 def _expr_small(cls, z):
     return log(S(1) / 2 + sqrt(1 - z) / 2)
Пример #59
0
 def _expr_big(cls, x, n):
     return log(x - 1) + (2 * n - 1) * pi * I
Пример #60
0
    def __init__(self):
        self.s,self.t,self.x,self.y,self.z = symbols('s,t,x,y,z')
        self.stack = []
        self.defs = {}
        self.mode = 0
        self.hist = [('',[])] # Innehåller en lista med (kommandorad, stack)
        self.lastx = ''
        self.clear = True

        self.op0 = {
            's': lambda : self.s,
            't': lambda : self.t,
            'x': lambda : self.x,
            'y': lambda : self.y,
            'z': lambda : self.z,
            'oo': lambda : S('oo'),
            'inf': lambda : S('oo'),
            'infinity': lambda : S('oo'),
            '?': lambda : self.help(),
            'help': lambda : self.help(),
            'hist': lambda : self.history(),
            'history': lambda : self.history(),
            'sketch': lambda : self.sketch(),
        }

        self.op1 = {
            'radians': lambda x : pi/180*x,
            'sin': lambda x : sin(x),
            'cos': lambda x : cos(x),
            'tan': lambda x : tan(x),
            'sq':  lambda x : x ** 2,
            'sqrt':  lambda x : sqrt(x),
            'ln':  lambda x : ln(x),
            'exp':  lambda x : exp(x),
            'log':  lambda x : log(x),
            'simplify': lambda x : simplify(x),
            'polynom': lambda x : self.polynom(x),
            'inv': lambda x : 1/x,
            'chs': lambda x : -x,
            'center': lambda x : x.center,
            'radius': lambda x : x.radius,
            'expand': lambda x : x.expand(),
            'factor': lambda x : x.factor(),
            'incircle': lambda x : x.incircle,
            'circumcircle': lambda x : x.circumcircle,
            'xdiff':  lambda x : x.diff(self.x),
            'ydiff': lambda x : x.diff(self.y),
            'xint': lambda x : x.integrate(self.x),
            'xsolve': lambda x : solve(x,self.x),
            'xapart': lambda x : apart(x,self.x),
            'xtogether': lambda x : together(x,self.x),
            'N': lambda x : N(x),
            'info': lambda x : [x.__class__.__name__, [m for m in dir(x) if m[0]!= '_']],
        }
        self.op2 = {
            '+': lambda x,y : y+x,
            '-': lambda x,y : y-x,
            '*': lambda x,y : y*x,
            '/': lambda x,y : y/x,
            '**': lambda x,y : y**x,
            'item': lambda x,y : y[x],
            'point': lambda x,y : Point(y,x),
            'line': lambda x,y : Line(y,x),
            'circle': lambda x,y : Circle(y,x),
            'tangent_lines': lambda x,y : y.tangent_lines(x),
            'intersection': lambda x,y : intersection(x,y),
            'perpendicular_line': lambda x,y : y.perpendicular_line(x),
            'diff':  lambda x,y : y.diff(x),
            'int': lambda x,y : y.integrate(x),
            'solve': lambda x,y : solve(y,x),
            'apart': lambda x,y : apart(y,x),
            'together': lambda x,y : together(y,x),
            'xeval': lambda x,y : y.subs(self.x,x),
        }
        self.op3 = {
            'triangle': lambda x,y,z : Triangle(x,y,z),
            'limit': lambda x,y,z : limit(z,y,x),  # limit(sin(x)/x,x,0) <=> x sin x / x 0 limit
            'eval': lambda x,y,z : z.subs(y,x),
        }
        self.op4 = {
            'sum': lambda x,y,z,t : Sum(t,(z,y,x)).doit()  # Sum(1/x**2,(x,1,oo)).doit() <=> 1 x x * / x 1 oo sum
        }
        self.lastx = ''