Дифуравнения символьно: dsolve

В разделе про SciPy мы решали дифуры численно — траекторией из точек. SymPy решает их символьно, выдавая точную формулу решения.

dsolve — функция SymPy для символьного решения дифференциальных уравнений: возвращает решение в виде формулы y(x) = ....

Численно vs символьно: две картины

Численный solve_ivp из SciPy даёт числа: «при t=2 величина равна 36.79». Символьный dsolve даёт формулу: «$y(t) = C \cdot e^{-0.5t}$». Формула мощнее: в неё можно подставить любое t, проанализировать поведение, продифференцировать. Но символьно решаются далеко не все дифуры — только определённые типы.

Решаем радиоактивный распад символьно

То самое уравнение $y' = -k \cdot y$ из урока про ОДУ. Численно мы получали приближение; символьно — точную экспоненту:

import sympy as sp

t = sp.symbols("t")
k = sp.symbols("k", positive=True)
y = sp.Function("y")

# уравнение y'(t) = -k * y(t)
eq = sp.Eq(y(t).diff(t), -k * y(t))
solution = sp.dsolve(eq, y(t))
print(solution)        # Eq(y(t), C1*exp(-k*t))

# с начальным условием y(0) = 100:
sol_ic = sp.dsolve(eq, y(t), ics={y(0): 100})
print(sol_ic)          # Eq(y(t), 100*exp(-k*t))

SymPy вывел точное решение $y(t) = 100 \cdot e^{-kt}$ — ту самую формулу, которую численный метод лишь приближал. Теперь её можно вычислить в любой точке без накопления ошибок.

Проверим формулу численно «руками»

SymPy утверждает: решение $y' = -0.5y,\ y(0)=100$ — это $y(t) = 100 \cdot e^{-0.5t}$. Проверим, что эта формула и впрямь удовлетворяет уравнению (производная равна $-0.5 \cdot y$) на чистом Python:

import math

def y(t):
    return 100 * math.exp(-0.5 * t)

# численно дифференцируем формулу в точке t=3
h = 1e-6
t0 = 3.0
y_prime = (y(t0 + h) - y(t0 - h)) / (2 * h)

print("y'(3) численно :", round(y_prime, 6))
print("-0.5 * y(3)    :", round(-0.5 * y(t0), 6))
print("Совпадают?     :", abs(y_prime - (-0.5 * y(t0))) < 1e-4)

Вывод:

y'(3) численно : -11.156508
-0.5 * y(3)    : -11.156508
Совпадают?     : True

Формула удовлетворяет уравнению: производная решения равна $-0.5 \cdot y$ в каждой точке. SymPy не просто угадал — он вывел и доказал решение.

Что dsolve умеет и не умеет

Тип уравненияdsolve
Линейные с постоянными коэффициентамирешает всегда
Разделяющиеся переменныеобычно решает
Многие классические типы (Бернулли, Риккати…)часто решает
Произвольные нелинейныечасто не может — нужен численный метод

Как работает под капотом

dsolve работает как умный «классификатор»: он распознаёт тип уравнения (разделяющиеся переменные, линейное, однородное, точное и т.д.) и применяет соответствующий известный метод решения из учебника по дифурам. Для каждого типа есть свой алгоритм: для линейных с постоянными коэффициентами — характеристическое уравнение, для разделяющихся — интегрирование обеих частей. Если ни один распознанный тип не подходит, SymPy честно сообщает, что решить символьно не может. Это фундаментально: большинство «реальных» нелинейных дифуров не имеют решения в замкнутой форме вообще — для них существует только численный путь (SciPy solve_ivp).

Частые ошибки

  • Забыть Function. Неизвестная функция объявляется через y = Function("y"), а в уравнении пишется y(t), а не просто y.
  • Ждать решения для любого дифура. Большинство нелинейных уравнений символьно не решаются — это нормально, переходите к численному методу.
  • Путать C1 с числом. Без начальных условий решение содержит произвольные константы; задайте ics, чтобы их определить.

Итог

  • dsolve решает дифуравнения символьно — выдаёт формулу $y(x)=\dots$, а не числа.
  • Начальные условия задаются через ics, определяя константы.
  • Работает для распознаваемых типов (линейные, разделяющиеся и др.); произвольные нелинейные — численно.
  • Формула мощнее траектории: точна в любой точке, поддаётся анализу.
Проверьте себя
1. Чем результат dsolve отличается от результата численного solve_ivp?
AНичем
Bdsolve даёт точную ФОРМУЛУ решения y(x)=…, а solve_ivp — приближённую траекторию из чисел
Cdsolve быстрее
Dsolve_ivp точнее
2. Как dsolve решает дифференциальное уравнение?
AЧисленным интегрированием
BРаспознаёт ТИП уравнения (линейное, разделяющееся и т.д.) и применяет соответствующий известный метод; если тип не распознан — не решает
CПеребором формул
DМашинным обучением
3. Что означает C1 в выводе dsolve без начальных условий?
AОшибку
BПроизвольную константу интегрирования; чтобы её определить, задают начальные условия через ics
CПервый корень
DКоэффициент уравнения
py
Курс по теме
Пройдите курс «Python с нуля» — по шагам, с проверкой
8 уроков · ~14 ч · теория, упражнения и экзамен с бейджем
Открыть курс →