Esempio n. 1
0
def test_constant_multiple():
    assert constant_renumber(constantsimp(C1 * 2 + 2, [C1])) == C1
    assert constant_renumber(constantsimp(x * 2 / C1, [C1])) == C1 * x
    assert constant_renumber(constantsimp(C1**2 * 2 + 2, [C1])) == C1
    assert constant_renumber(constantsimp(sin(2 * C1) + x + sqrt(2),
                                          [C1])) == C1 + x
    assert constant_renumber(constantsimp(2 * C1 + C2, [C1, C2])) == C1
Esempio n. 2
0
def test_constant_renumber_order_issue_5308():
    from sympy.utilities.iterables import variations

    assert constant_renumber(C1*x + C2*y) == \
        constant_renumber(C1*y + C2*x) == \
        C1*x + C2*y
    e = C1 * (C2 + x) * (C3 + y)
    for a, b, c in variations([C1, C2, C3], 3):
        assert constant_renumber(a * (b + x) * (c + y)) == e
Esempio n. 3
0
def test_constant_renumber():
    e1, e2, x, y = symbols("e1:3 x y")
    exprs = [e2*x, e1*x + e2*y]

    assert constant_renumber(exprs[0]) == e2*x
    assert constant_renumber(exprs[0], variables=[x]) == C1*x
    assert constant_renumber(exprs[0], variables=[x], newconstants=[C2]) == C2*x
    assert constant_renumber(exprs, variables=[x, y]) == [C1*x, C1*y + C2*x]
    assert constant_renumber(exprs, variables=[x, y], newconstants=symbols("C3:5")) == [C3*x, C3*y + C4*x]
Esempio n. 4
0
def test_ode_solutions():
    # only a few examples here, the rest will be tested in the actual dsolve tests
    assert constant_renumber(constantsimp(C1*exp(2*x) + exp(x)*(C2 + C3), [C1, C2, C3])) == \
        constant_renumber(C1*exp(x) + C2*exp(2*x))
    assert constant_renumber(
        constantsimp(Eq(f(x),
                        I * C1 * sinh(x / 3) + C2 * cosh(x / 3)),
                     [C1, C2])) == constant_renumber(
                         Eq(f(x),
                            C1 * sinh(x / 3) + C2 * cosh(x / 3)))
    assert constant_renumber(constantsimp(Eq(f(x), acos((-C1)/cos(x))), [C1])) == \
        Eq(f(x), acos(C1/cos(x)))
    assert constant_renumber(
        constantsimp(Eq(log(f(x) / C1) + 2 * exp(x / f(x)), 0),
                     [C1])) == Eq(log(C1 * f(x)) + 2 * exp(x / f(x)), 0)
    assert constant_renumber(constantsimp(Eq(log(x*sqrt(2)*sqrt(1/x)*sqrt(f(x))
        /C1) + x**2/(2*f(x)**2), 0), [C1])) == \
        Eq(log(C1*sqrt(x)*sqrt(f(x))) + x**2/(2*f(x)**2), 0)
    assert constant_renumber(constantsimp(Eq(-exp(-f(x)/x)*sin(f(x)/x)/2 + log(x/C1) -
        cos(f(x)/x)*exp(-f(x)/x)/2, 0), [C1])) == \
        Eq(-exp(-f(x)/x)*sin(f(x)/x)/2 + log(C1*x) - cos(f(x)/x)*
           exp(-f(x)/x)/2, 0)
    assert constant_renumber(constantsimp(Eq(-Integral(-1/(sqrt(1 - u2**2)*u2),
        (u2, _a, x/f(x))) + log(f(x)/C1), 0), [C1])) == \
        Eq(-Integral(-1/(u2*sqrt(1 - u2**2)), (u2, _a, x/f(x))) +
        log(C1*f(x)), 0)
    assert [constantsimp(i, [C1]) for i in [Eq(f(x), sqrt(-C1*x + x**2)), Eq(f(x), -sqrt(-C1*x + x**2))]] == \
        [Eq(f(x), sqrt(x*(C1 + x))), Eq(f(x), -sqrt(x*(C1 + x)))]
Esempio n. 5
0
def test_constant_power_as_base():
    assert constant_renumber(constantsimp(C1**C1, [C1])) == C1
    assert constant_renumber(constantsimp(Pow(C1, C1), [C1])) == C1
    assert constant_renumber(constantsimp(C1**C1, [C1])) == C1
    assert constant_renumber(constantsimp(C1**C2, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C2**C1, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C2**C2, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C1**y, [C1, y])) == C1
    assert constant_renumber(constantsimp(C1**x, [C1])) == C1**x
    assert constant_renumber(constantsimp(C1**2, [C1])) == C1
    assert constant_renumber(constantsimp(C1**(x * y), [C1])) == C1**(x * y)
Esempio n. 6
0
def test_constant_function():
    assert constant_renumber(constantsimp(sin(C1), [C1])) == C1
    assert constant_renumber(constantsimp(f(C1), [C1])) == C1
    assert constant_renumber(constantsimp(f(C1, C1), [C1])) == C1
    assert constant_renumber(constantsimp(f(C1, C2), [C1, C2])) == C1
    assert constant_renumber(constantsimp(f(C2, C1), [C1, C2])) == C1
    assert constant_renumber(constantsimp(f(C2, C2), [C1, C2])) == C1
    assert constant_renumber(constantsimp(f(C1, x), [C1])) == f(C1, x)
    assert constant_renumber(constantsimp(f(C1, y), [C1, y])) == C1
    assert constant_renumber(constantsimp(f(y, C1), [C1, y])) == C1
    assert constant_renumber(constantsimp(f(C1, y, C2), [C1, C2, y])) == C1
Esempio n. 7
0
def test_constant_add():
    assert constant_renumber(constantsimp(C1 + C1, [C1])) == C1
    assert constant_renumber(constantsimp(C1 + 2, [C1])) == C1
    assert constant_renumber(constantsimp(2 + C1, [C1])) == C1
    assert constant_renumber(constantsimp(C1 + y, [C1, y])) == C1
    assert constant_renumber(constantsimp(C1 + x, [C1])) == C1 + x
    assert constant_renumber(constantsimp(C1 + C1, [C1])) == C1
    assert constant_renumber(constantsimp(C1 + C2, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C2 + C1, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C1 + C2 + C1, [C1, C2])) == C1
Esempio n. 8
0
def test_constant_power_as_exp():
    assert constant_renumber(constantsimp(x**C1, [C1])) == x**C1
    assert constant_renumber(constantsimp(y**C1, [C1, y])) == C1
    assert constant_renumber(constantsimp(x**y**C1, [C1, y])) == x**C1
    assert constant_renumber(constantsimp((x**y)**C1, [C1])) == (x**y)**C1
    assert constant_renumber(constantsimp(x**(y**C1), [C1, y])) == x**C1
    assert constant_renumber(constantsimp(x**C1**y, [C1, y])) == x**C1
    assert constant_renumber(constantsimp(x**(C1**y), [C1, y])) == x**C1
    assert constant_renumber(constantsimp((x**C1)**y, [C1])) == (x**C1)**y
    assert constant_renumber(constantsimp(2**C1, [C1])) == C1
    assert constant_renumber(constantsimp(S(2)**C1, [C1])) == C1
    assert constant_renumber(constantsimp(exp(C1), [C1])) == C1
    assert constant_renumber(constantsimp(exp(C1 + x), [C1])) == C1 * exp(x)
    assert constant_renumber(constantsimp(Pow(2, C1), [C1])) == C1
Esempio n. 9
0
def test_constant_mul():
    # We want C1 (Constant) below to absorb the y's, but not the x's
    assert constant_renumber(constantsimp(y * C1, [C1])) == C1 * y
    assert constant_renumber(constantsimp(C1 * y, [C1])) == C1 * y
    assert constant_renumber(constantsimp(x * C1, [C1])) == x * C1
    assert constant_renumber(constantsimp(C1 * x, [C1])) == x * C1
    assert constant_renumber(constantsimp(2 * C1, [C1])) == C1
    assert constant_renumber(constantsimp(C1 * 2, [C1])) == C1
    assert constant_renumber(constantsimp(y * C1 * x, [C1, y])) == C1 * x
    assert constant_renumber(constantsimp(x * y * C1, [C1, y])) == x * C1
    assert constant_renumber(constantsimp(y * x * C1, [C1, y])) == x * C1
    assert constant_renumber(constantsimp(C1 * x * y, [C1, y])) == C1 * x
    assert constant_renumber(constantsimp(x * C1 * y, [C1, y])) == x * C1
    assert constant_renumber(constantsimp(C1 * y * (y + 1),
                                          [C1])) == C1 * y * (y + 1)
    assert constant_renumber(constantsimp(y * C1 * (y + 1),
                                          [C1])) == C1 * y * (y + 1)
    assert constant_renumber(constantsimp(x * (y * C1), [C1])) == x * y * C1
    assert constant_renumber(constantsimp(x * (C1 * y), [C1])) == x * y * C1
    assert constant_renumber(constantsimp(C1 * (x * y), [C1, y])) == C1 * x
    assert constant_renumber(constantsimp((x * y) * C1, [C1, y])) == x * C1
    assert constant_renumber(constantsimp((y * x) * C1, [C1, y])) == x * C1
    assert constant_renumber(constantsimp(y * (y + 1) * C1, [C1, y])) == C1
    assert constant_renumber(constantsimp((C1 * x) * y, [C1, y])) == C1 * x
    assert constant_renumber(constantsimp(y * (x * C1), [C1, y])) == x * C1
    assert constant_renumber(constantsimp((x * C1) * y, [C1, y])) == x * C1
    assert constant_renumber(constantsimp(C1 * x * y * x * y * 2,
                                          [C1, y])) == C1 * x**2
    assert constant_renumber(constantsimp(C1 * x * y * z,
                                          [C1, y, z])) == C1 * x
    assert constant_renumber(constantsimp(C1 * x * y**2 * sin(z),
                                          [C1, y, z])) == C1 * x
    assert constant_renumber(constantsimp(C1 * C1, [C1])) == C1
    assert constant_renumber(constantsimp(C1 * C2, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C2 * C2, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C1 * C1 * C2, [C1, C2])) == C1
    assert constant_renumber(constantsimp(C1 * x * 2**x,
                                          [C1])) == C1 * x * 2**x
Esempio n. 10
0
def test_constant_repeated():
    assert C1 + C1 * x == constant_renumber(C1 + C1 * x)
Esempio n. 11
0
def test_constant_function_multiple():
    # The rules to not renumber in this case would be too complicated, and
    # dsolve is not likely to ever encounter anything remotely like this.
    assert constant_renumber(constantsimp(f(C1, C1, x), [C1])) == f(C1, C1, x)
Esempio n. 12
0
def dsolve_system(eqs, funcs=None, t=None, ics=None, doit=False):
    r"""
    Solves any(supported) system of Ordinary Differential Equations

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

    This function takes a system of ODEs as an input, determines if the
    it is solvable by this function, and returns the solution if found any.

    This function can handle:
    1. Linear, First Order, Constant coefficient homogeneous system of ODEs
    2. Linear, First Order, Constant coefficient non-homogeneous system of ODEs
    3. Linear, First Order, non-constant coefficient homogeneous system of ODEs
    4. Linear, First Order, non-constant coefficient non-homogeneous system of ODEs
    5. Any implicit system which can be divided into system of ODEs which is of the above 4 forms

    The types of systems described above aren't limited by the number of equations, i.e. this
    function can solve the above types irrespective of the number of equations in the system passed.

    This function returns a list of solutions. Each solution is a list of equations where LHS is
    the dependent variable and RHS is an expression in terms of the independent variable.

    Parameters
    ==========

    eqs : List
        system of ODEs to be solved
    funcs : List or None
        List of dependent variables that make up the system of ODEs
    t : Symbol
        Independent variable in the system of ODEs
    ics : Dict or None
        Set of initial boundary/conditions for the system of ODEs
    doit : Boolean
        Evaluate the solutions if True. Default value is False

    Examples
    ========

    >>> from sympy import symbols, Eq, Function
    >>> from sympy.solvers.ode.systems import dsolve_system
    >>> f, g = symbols("f g", cls=Function)
    >>> x = symbols("x")

    >>> eqs = [Eq(f(x).diff(x), g(x)), Eq(g(x).diff(x), f(x))]
    >>> dsolve_system(eqs)
    [[Eq(f(x), -C1*exp(-x) + C2*exp(x)), Eq(g(x), C1*exp(-x) + C2*exp(x))]]

    You can also pass the initial conditions for the system of ODEs:
    >>> dsolve_system(eqs, ics={f(0): 1, g(0): 0})
    [[Eq(f(x), exp(x)/2 + exp(-x)/2), Eq(g(x), exp(x)/2 - exp(-x)/2)]]

    Optionally, you can pass the dependent variables and the independent
    variable for which the system is to be solved:
    >>> funcs = [f(x), g(x)]
    >>> dsolve_system(eqs, funcs=funcs, t=x)
    [[Eq(f(x), -C1*exp(-x) + C2*exp(x)), Eq(g(x), C1*exp(-x) + C2*exp(x))]]

    Lets look at an implicit system of ODEs:
    >>> eqs = [Eq(f(x).diff(x)**2, g(x)**2), Eq(g(x).diff(x), g(x))]
    >>> dsolve_system(eqs)
    [[Eq(f(x), C1 - C2*exp(x)), Eq(g(x), C2*exp(x))], [Eq(f(x), C1 + C2*exp(x)), Eq(g(x), C2*exp(x))]]

    Returns
    =======

    List of List of Equations

    Raises
    ======

    NotImplementedError
        When the system of ODEs is not solvable by this function.
    ValueError
        When the parameters passed aren't in the required form.

    """
    from sympy.solvers.ode.ode import solve_ics, _extract_funcs, constant_renumber

    if not iterable(eqs):
        raise ValueError(
            filldedent('''
            List of equations should be passed. The input is not valid.
        '''))

    eqs = _preprocess_eqs(eqs)

    if funcs is not None and not isinstance(funcs, list):
        raise ValueError(
            filldedent('''
            Input to the funcs should be a list of functions.
        '''))

    if funcs is None:
        funcs = _extract_funcs(eqs)

    if any(len(func.args) != 1 for func in funcs):
        raise ValueError(
            filldedent('''
            dsolve_system can solve a system of ODEs with only one independent
            variable.
        '''))

    if len(eqs) != len(funcs):
        raise ValueError(
            filldedent('''
            Number of equations and number of functions don't match
        '''))

    if t is not None and not isinstance(t, Symbol):
        raise ValueError(
            filldedent('''
            The indepedent variable must be of type Symbol
        '''))

    if t is None:
        t = list(list(eqs[0].atoms(Derivative))[0].atoms(Symbol))[0]

    sys_order = _get_func_order(eqs, funcs)

    # To add higher order to first order reduction later
    if not all(sys_order[func] == 1 for func in funcs):
        raise NotImplementedError(
            filldedent('''
            Higher order ODEs aren't solvable by dsolve_system
        '''))

    canon_eqs = canonical_odes(eqs, funcs, t)
    sols = []

    for canon_eq in canon_eqs:
        sol = _strong_component_solver(canon_eq, funcs, t)
        if sol is None:
            sol = _component_solver(canon_eq, funcs, t)
        sols.append(sol)

    if sols:
        final_sols = []

        for sol in sols:

            # To preserve the order corresponding to the
            # funcs list.
            sol_dict = {s.lhs: s.rhs for s in sol}
            sol = [Eq(var, sol_dict[var]) for var in funcs]

            variables = Tuple(*eqs).free_symbols
            sol = constant_renumber(sol, variables=variables)

            if ics:
                constants = Tuple(*sol).free_symbols - variables
                solved_constants = solve_ics(sol, funcs, constants, ics)
                sol = [s.subs(solved_constants) for s in sol]

            if doit:
                sol = [s.doit() for s in sol]

            final_sols.append(sol)

        sols = final_sols

    return sols
Esempio n. 13
0
def dsolve_system(eqs, funcs=None, t=None, ics=None, doit=False):
    r"""
    Solves any(supported) system of Ordinary Differential Equations

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

    This function takes a system of ODEs as an input, determines if the
    it is solvable by this function, and returns the solution if found any.

    This function can handle:
    1. Linear, First Order, Constant coefficient homogeneous system of ODEs
    2. Linear, First Order, Constant coefficient non-homogeneous system of ODEs
    3. Linear, First Order, non-constant coefficient homogeneous system of ODEs
    4. Linear, First Order, non-constant coefficient non-homogeneous system of ODEs
    5. Any implicit system which can be divided into system of ODEs which is of the above 4 forms

    The types of systems described above aren't limited by the number of equations, i.e. this
    function can solve the above types irrespective of the number of equations in the system passed.

    This function returns a list of solutions. Each solution is a list of equations where LHS is
    the dependent variable and RHS is an expression in terms of the independent variable.

    Parameters
    ==========

    eqs : List
        system of ODEs to be solved
    funcs : List or None
        List of dependent variables that make up the system of ODEs
    t : Symbol
        Independent variable in the system of ODEs
    ics : Dict or None
        Set of initial boundary/conditions for the system of ODEs
    doit : Boolean
        Evaluate the solutions if True. Default value is False

    Examples
    ========

    >>> from sympy import symbols, Eq, Function
    >>> from sympy.solvers.ode.systems import dsolve_system
    >>> f, g = symbols("f g", cls=Function)
    >>> x = symbols("x")

    >>> eqs = [Eq(f(x).diff(x), g(x)), Eq(g(x).diff(x), f(x))]
    >>> dsolve_system(eqs)
    [[Eq(f(x), -C1*exp(-x) + C2*exp(x)), Eq(g(x), C1*exp(-x) + C2*exp(x))]]

    You can also pass the initial conditions for the system of ODEs:
    >>> dsolve_system(eqs, ics={f(0): 1, g(0): 0})
    [[Eq(f(x), exp(x)/2 + exp(-x)/2), Eq(g(x), exp(x)/2 - exp(-x)/2)]]

    Optionally, you can pass the dependent variables and the independent
    variable for which the system is to be solved:
    >>> funcs = [f(x), g(x)]
    >>> dsolve_system(eqs, funcs=funcs, t=x)
    [[Eq(f(x), -C1*exp(-x) + C2*exp(x)), Eq(g(x), C1*exp(-x) + C2*exp(x))]]

    Lets look at an implicit system of ODEs:
    >>> eqs = [Eq(f(x).diff(x)**2, g(x)**2), Eq(g(x).diff(x), g(x))]
    >>> dsolve_system(eqs)
    [[Eq(f(x), C1 - C2*exp(x)), Eq(g(x), C2*exp(x))], [Eq(f(x), C1 + C2*exp(x)), Eq(g(x), C2*exp(x))]]

    Returns
    =======

    List of List of Equations

    Raises
    ======

    NotImplementedError
        When the system of ODEs is not solvable by this function.
    ValueError
        When the parameters passed aren't in the required form.

    """
    from sympy.solvers.ode.ode import solve_ics, _extract_funcs, constant_renumber

    if not iterable(eqs):
        raise ValueError(
            filldedent('''
            List of equations should be passed. The input is not valid.
        '''))

    eqs = _preprocess_eqs(eqs)

    if funcs is not None and not isinstance(funcs, list):
        raise ValueError(
            filldedent('''
            Input to the funcs should be a list of functions.
        '''))

    # Note: This is added to solve a major problem encountered.
    # Might be best to make a function for this functions
    # extraction later.
    if funcs is None:
        funcs = _extract_funcs(eqs)
    if len(eqs) != len(funcs):
        raise ValueError(
            filldedent('''
            Number of equations and number of functions don't match
        '''))

    if t is not None and not isinstance(t, Symbol):
        raise ValueError(
            filldedent('''
            The indepedent variable must be of type Symbol
        '''))

    if t is None:
        t = list(list(eqs[0].atoms(Derivative))[0].atoms(Symbol))[0]

    match = neq_nth_linear_constant_coeff_match(eqs, funcs, t)

    sols = []

    if match is None or match.get('is_implicit', False):
        canon_eqs = [eqs] if match is None else match['canon_eqs']

        # Note: Assuming a canon_eq has a single
        # solution.
        for canon_eq in canon_eqs:
            sols.append(_component_solver(canon_eq, funcs, t))

    # Note: It is advantageous to
    # divide a system of ODEs since smaller
    # the matrices, faster the solution
    # computation. Has to be considered in
    # future PR when component division function
    # is added.
    elif match.get('is_general', False):
        if match.get('is_linear', False):
            match['t'] = t
            sols.append(_linear_ode_solver(match))

    if sols:
        final_sols = []

        # This is assuming that all the solutions
        # have the same funcs. This may have to
        # be changed when system division is
        # added.
        funcs = [s.lhs for s in sols[0]]

        for sol in sols:
            variables = Tuple(*eqs).free_symbols
            sol = constant_renumber(sol, variables=variables)

            if ics:
                constants = Tuple(*sol).free_symbols - variables
                solved_constants = solve_ics(sol, funcs, constants, ics)
                sol = [s.subs(solved_constants) for s in sol]

            if doit:
                sol = [s.doit() for s in sol]

            final_sols.append(sol)

        sols = final_sols

    return sols