Example #1
0
def test_nth_algebraic():
    eqn = f(x) + f(x) * f(x).diff(x)
    solns = [Eq(f(x), exp(x)), Eq(f(x), C1 * exp(C2 * x))]
    solns_final = _remove_redundant_solutions(eqn, solns, 2, x)
    assert solns_final == [Eq(f(x), C1 * exp(C2 * x))]

    _ode_solver_test(_get_examples_ode_sol_nth_algebraic())
Example #2
0
def test_nth_algebraic_redundant_solutions():
    # This one has a redundant solution that should be removed
    eqn = f(x) * f(x).diff(x)
    soln = Eq(f(x), C1)
    assert checkodesol(eqn, soln, order=1, solve_for_func=False)[0]
    assert soln == dsolve(eqn, f(x), hint='nth_algebraic')
    assert soln == dsolve(eqn, f(x))

    # This has two integral solutions and no algebraic solutions
    eqn = (diff(f(x)) - x) * (diff(f(x)) + x)
    sol = [Eq(f(x), C1 - x**2 / 2), Eq(f(x), C1 + x**2 / 2)]
    assert all(c[0]
               for c in checkodesol(eqn, sol, order=1, solve_for_func=False))
    assert set(sol) == set(dsolve(eqn, f(x), hint='nth_algebraic'))
    assert set(sol) == set(dsolve(eqn, f(x)))

    eqn = f(x) + f(x) * f(x).diff(x)
    solns = [Eq(f(x), 0), Eq(f(x), C1 - x)]
    assert all(c[0]
               for c in checkodesol(eqn, solns, order=1, solve_for_func=False))
    assert set(solns) == set(dsolve(eqn, f(x)))

    solns = [Eq(f(x), exp(x)), Eq(f(x), C1 * exp(C2 * x))]
    solns_final = _remove_redundant_solutions(eqn, solns, 2, x)
    assert solns_final == [Eq(f(x), C1 * exp(C2 * x))]

    # This one needs a substitution f' = g.
    eqn = -exp(x) + (x * Derivative(f(x), (x, 2)) + Derivative(f(x), x)) / x
    sol = Eq(f(x), C1 + C2 * log(x) + exp(x) - Ei(x))
    assert checkodesol(eqn, sol, order=2, solve_for_func=False)[0]
    assert sol == dsolve(eqn, f(x))
def find_kovacic_sol(eq):
    z = list(eq.atoms(Derivative))[0].args[0]
    x = list(z.free_symbols)[0]
    eq = eq.expand().collect(z)
    a, b, c = match_2nd_order(eq, z, x)

    # Transform the differential equation to a simpler form
    # using z(x) = y(x)*exp(Integral(-b/(2*a))) and find its solution
    ysol = find_kovacic_simple(x, a, b, c)

    zsol = list(map(lambda sol: sol*exp(Integral(-b/(2*a), x).doit()), ysol))
    zsol = _remove_redundant_solutions(Eq(eq, 0), list(map(lambda sol: Eq(z, sol), zsol)), 2, x)

    C1, C2 = symbols('C1 C2')
    if len(zsol) == 2:
        return constantsimp(Eq(z, C1*zsol[0].rhs + C2*zsol[1].rhs), [C1, C2])
    if len(zsol) == 1:
        sol1 = zsol[0].rhs
        sol2 = sol1*Integral(exp(Integral(-b, x).doit())/sol1**2, x)
        zsol.append(Eq(z, sol2))
        return constantsimp(Eq(z, C1*zsol[0].rhs + C2*zsol[1].rhs), [C1, C2])
    return zsol