SymPy dsolve возвращает разные результаты для математически эквивалентных дифференциальных уравнений - PullRequest
0 голосов
/ 19 мая 2018

Вот содержимое моего скрипта:

from sympy import *
x = symbols('x')
init_printing(use_unicode=True)

f = symbols('f', cls=Function)
diffeq = Eq(x**2 * f(x).diff(x, x) + x * f(x).diff(x) - f(x) , 1/((1+x**2)**(3)) )
print dsolve(diffeq, f(x))

Эта программа возвращает следующий вывод:

Eq(f(x), (C1*x**2 + C1 + C2*x**4 + C2*x**2 - 15*x**4*atan(x) - 15*x**3 - 18*x**2*atan(x) - 13*x - 3*atan(x))/(16*x*(x**2 + 1)))

Но когда я определяю переменную diffeq следующим образом:

diffeq = Eq(f(x).diff(x, x) + f(x).diff(x)/x - f(x)/x**(2) , 1 / ((1+x**2)**(3) * x**(2)) )

затем я получаю вывод:

Traceback (most recent call last):
  File "/home/foo/odeSympyTrial01.py", line 12, in <module>
print dsolve(diffeq, f(x))
  File "/usr/lib/python2.7/dist-packages/sympy/solvers/ode.py", line 625, in dsolve
    x0=x0, n=n, **kwargs)
  File "/usr/lib/python2.7/dist-packages/sympy/solvers/deutils.py", line 235, in _desolve
    raise NotImplementedError(dummy + "solve" + ": Cannot solve " + str(eq))
NotImplementedError: solve: Cannot solve Derivative(f(x), x, x) + Derivative(f(x), x)/x - f(x)/x**2 - 1/(x**2*(x**2 + 1)**3)

И когда я определяю переменную diffeq следующим образом:

diffeq = Eq(f(x).diff(x, x) * x**(2) + f(x).diff(x) * x**(2) /x - f(x) * x**(2) /x**(2) , 1* x**(2)/((1+x**2)**(3) * x**(2)) )

, тогда я получаю вывод:

Eq(f(x), (C1*x**2 + C1 + C2*x**4 + C2*x**2 - 15*x**4*atan(x) - 15*x**3 - 18*x**2*atan(x) - 13*x - 3*atan(x))/(16*x*(x**2 + 1)))

В каждом из этих случаев дифференциальные уравнения diffeq математически равны.Поэтому, по моему мнению, dsolve() должен возвращать один и тот же результат для каждого случая.Кто-нибудь, пожалуйста, помогите мне понять, почему dsolve() возвращает ошибку во втором случае.Как следует выражать неоднородное линейное обыкновенное дифференциальное уравнение, чтобы dsolve() не возвращало ошибку?

1 Ответ

0 голосов
/ 19 мая 2018

Краткое объяснение: логика модуля SymPy ODE часто наивна, а иногда и неверна.

Как написано изначально, с

x**2 * f(x).diff(x, x) + x * f(x).diff(x) - f(x)

это соответствует форме уравнения Коши – Эйлера (также известного как уравнение Эйлера): степень x в каждом коэффициентеэто порядок производной.SymPy обнаруживает эту структуру и применяет соответствующий метод.Но если вы поделите на x**2,

f(x).diff(x, x) + f(x).diff(x)/x - f(x)/x**(2) 

, это уже не так: вторая производная не имеет мощности x**2, поэтому совпадение не удастся.Более тщательная проверка может обнаружить здесь скрытую структуру Коши-Эйлера, но она не реализована, как можно увидеть, посмотрев на источник .

Вы можете проверить, что это действительно то, что происходит с

classify_ode(diffeq, f(x))

, который вернет 'nth_linear_euler_eq_nonhomogene_variation_of_parameters' в первом случае, но не во втором.


Глядя на источник, можно также увидеть пример неправильной логики.

        if coeff.is_Mul:
            if coeff.has(f(x)):
                return False
            return x**order in coeff.args

Например, x**2*sin(x) пройдет эту проверку с order = 2, чтоозначает, что SymPy будет принимать x**2*sin(x)*f(x).diff(x, x) - f(x) = 0 за уравнение Эйлера.И действительно,

dsolve(x**2*sin(x)*f(x).diff(x, x) - f(x), f(x))

«неправильно» решает уравнение.Не доверяйте решениям ODE от SymPy.

...