Перейти к содержимому

Выражения в SymPy

Выражения в SymPy

В прошлом уроке мы вспомнили базовые понятия анализа функций: что такое функция, производная и интеграл, а также как выглядят простейшие дифференциальные уравнения. Теперь перейдём к практике: разберём библиотеку SymPy, которая позволяет делать математические преобразования в символьном виде.

В этом уроке вы научитесь создавать в SymPy числа, символы и выражения, брать производные и интегралы, решать некоторые уравнения (в том числе численно), получать решения дифференциальных уравнений, строить разложения в ряды и строить графики. В конце — практика с готовыми решениями и чек‑лист.

Главная мысль: SymPy — это “математика как объекты”, где выражение вроде \((x-y)(x-y)\) понимается именно как математика и может автоматически преобразовываться в \((x-y)^2\), а производная и интеграл возвращают не числа, а новые символические выражения.

Содержание

1. Цели урока

  • Понять, из каких базовых объектов состоит SymPy: числа, символы, выражения, уравнения и функции.
  • Научиться делать символьные преобразования: упрощение, раскрытие скобок, подстановки значений.
  • Освоить символьное дифференцирование (diff) и интегрирование (integrate) для выражений.
  • Познакомиться с решением уравнений (solve) и численным решением (nsolve).
  • Увидеть, как решаются простые дифференциальные уравнения через dsolve.
  • Научиться получать разложения в ряд (например, ряд Тейлора) и строить графики.
Что особенно важно запомнить: SymPy старается сохранять точность и смысл выражений. Если вы можете записать математику “в формульном виде”, SymPy чаще всего сможет с ней работать именно как с математикой, а не как с набором чисел.
↑ К оглавлению

2. Что такое SymPy и зачем она нужна

В любой формальной системе — программировании, математике, логике — есть “базовые кирпичики”, из которых строится всё остальное. В Python мы уже видели, что огромную роль играют базовые типы, а также функции и классы. В математике фундамент — это множества, числа, точки и операции над ними.

В SymPy тоже есть набор ключевых объектов, вокруг которых строится работа с библиотекой. В первую очередь это числа (ведь SymPy создана для математики), а также символы и выражения.

Частая путаница: SymPy и обычный Python

Запомните: SymPy — это не “быстрее посчитать”, а “понять и преобразовать формулу”. Поэтому выражения в SymPy обычно живут как объекты (их можно печатать, упрощать, дифференцировать), а не как моментально вычисленные числа. Если вы слишком рано превратите всё в float, вы потеряете часть преимуществ SymPy.
↑ К оглавлению

3. Объекты SymPy: числа и константы

3.1. Какие численные типы есть в SymPy

SymPy реализует собственные численные типы, чтобы поддерживать символьную математику и точные рациональные значения. Среди часто используемых объектов можно выделить:

  • Integer: целые числа;
  • Rational: рациональные числа в виде дроби;
  • RealNumber: вещественные числа (внутренние представления вещественных);
  • Float: числа с плавающей точкой (приближённые значения).

Например, можно создать целое число как обычный int Python, а можно — как sympy.Integer. Визуально они выглядят одинаково, но “внутренне” это разные типы.

import sympy as sp

a = 42
print(a, type(a))  # 42 <class 'int'>

b = sp.Integer(42)  # 42 <class 'sympy.core.numbers.Integer'>
print(b, type(b))
Python

3.2. Рациональные числа, арифметика и точность

Рациональные числа удобно задавать как дроби: \(\frac{p}{q}\), где \(p\) и \(q\) — целые, \(q\ne 0\). В обычном Python для “точной дроби” нужно отдельное решение, а SymPy даёт это прямо из коробки через Rational.

import sympy as sp

c = sp.Rational(3, 7)
print(c, type(c))      # 3/7

print(c**2)             # 9/49 (и числитель, и знаменатель возводятся в квадрат)
Python

В SymPy есть и известные константы, например \(\pi\) и золотое сечение. Если нужно получить численное приближение, используют float(...) или sp.N(...).

import sympy as sp

print("Pi (sym):", sp.pi)
print("Pi (float):", float(sp.pi))

print("Golden ratio (sym):", sp.GoldenRatio)
print("Golden ratio (float):", float(sp.GoldenRatio))

# Более контролируемо:
print(sp.N(sp.pi, 50))  # 50 знаков
Python
Практический вывод: если вы хотите точную математику (особенно с дробями), держите значения в SymPy-типах. В float переходите тогда, когда вам действительно нужно приблизительное число (например, для численного вывода или графика).

3.3. Типичные ошибки

Ошибка 1: “сразу всё превратить в float”

Если вы делаете float(sp.Rational(1, 3)), вы превращаете точное значение \(\frac{1}{3}\) в приближённое число. После этого SymPy уже не сможет “восстановить” точность, и в дальнейших преобразованиях могут появиться округления.

Ошибка 2: ожидать, что Float ведёт себя как точная дробь

sp.Float — это приближённое число, как и float в Python. Оно удобно, но это не “точная рациональная дробь”. Если нужна дробь — используйте Rational.

↑ К оглавлению

4. Символы, выражения и подстановки

4.1. Символы (Symbol)

Кроме чисел SymPy работает с математическими объектами, где есть неизвестные — переменные и параметры. В обычном Python выражение без конкретных чисел “не живёт” само по себе: интерпретатор должен всё посчитать. SymPy, наоборот, умеет хранить выражение как объект, даже если в нём есть неизвестные.

Базовый “кирпичик” для неизвестной переменной — это символ, который создаётся через Symbol.

import sympy as sp

x = sp.Symbol('x')
y = sp.Symbol('y')

print(x, type(x))  # x <class 'sympy.core.symbol.Symbol'>
print(y, type(y))  # y <class 'sympy.core.symbol.Symbol'>
Python

4.2. Выражения и преобразования

Из символов можно собирать выражения. SymPy старается интерпретировать их “по-математически”. Например, произведение одинаковых скобок естественно преобразуется в квадрат.

import sympy as sp

x, y = sp.symbols('x y')

expr = (x - y) * (x - y)
print(expr)            # (x - y)**2

expanded = sp.expand(expr)
print(expanded)        # x**2 - 2*x*y + y**2
Python

Внутренних типов у выражений много (сумма, произведение, степень и т.д.). Для нас ключевая идея такая: выражение — это объект SymPy, который можно передавать в функции библиотеки. При необходимости можно явно привести к “общему типу выражений” через Expr.

import sympy as sp

x, y = sp.symbols('x y')
e = sp.Expr(x*y)
print(e, type(e))  # Expr(x*y) <class 'sympy.core.expr.Expr'>
Python

Ещё один полезный момент: SymPy умеет превращать выражение в LaTeX‑строку. Это удобно для красивого вывода в конспектах и ноутбуках.

import sympy as sp

x = sp.Symbol('x')
expr = (x + 1)**3
print(sp.latex(expr))  # \left(x + 1\right)^{3}
Python

4.3. Подстановка значений (subs) и замены (replace)

Когда выражение содержит символы, мы часто хотим подставить конкретные значения или заменить часть выражения на другую часть. Для этого обычно используют:

  • subs — подстановка (замена символа/подвыражения на значение);
  • replace — более общий механизм замены выражения на выражение по правилу.
import sympy as sp

x, y = sp.symbols('x y')
expr = x**2 + 2*x*y + y**2   # (x+y)^2

# Подставим конкретные значения:
val = expr.subs({x: 3, y: -1})
print(val)        # 4
print(int(val))   # 4

# Замена подвыражения на другое:
expr2 = expr.replace(x**2, 10)
print(expr2)      # 2*x*y + y**2 + 10
Python
Запомните: subs — это “подставить значения/выражения”, а replace — это “заменить по правилу”. Иногда обе операции дают похожий вид результата, но логика у них разная.

4.4. Типичные ошибки

Ошибка 1: использовать math вместо sympy для символьных выражений

Функции из модуля math работают с числами, а не с символами. Если вы напишете math.sin(x), где x — символ SymPy, будет ошибка. Для символики используйте sp.sin(x), sp.log(x) и т.д.

Ошибка 2: путать “равенство Python” и “уравнение SymPy”

Запись x == 2 в Python — это булево сравнение. Для уравнения в SymPy используйте sp.Eq(левая_часть, правая_часть). Это особенно важно перед решением через solve или nsolve.

↑ К оглавлению

5. Уравнения: solve и nsolve

5.1. Как задавать уравнение

Уравнение — это два выражения, соединённые знаком равенства. В SymPy для этого есть класс‑обёртка Eq.

import sympy as sp

x = sp.Symbol('x')
eq = sp.Eq(x**2 - x - 1, 0)
print(eq)
Python

5.2. Аналитическое решение (solve)

Если уравнение относится к типам, для которых в SymPy реализованы алгоритмы аналитического решения, можно использовать solve. Тогда результатом будет список корней.

import sympy as sp

x = sp.Symbol('x')
eq = sp.Eq(x**2 - x - 1, 0)

roots = sp.solve(eq, x)
print(roots)  # [-sqrt(5)/2 + 1/2, sqrt(5)/2 + 1/2]
Python

Но важно помнить: далеко не для всех уравнений SymPy умеет выдавать точную формулу решения. Для некоторых выражений (особенно с несколькими “генераторами” вроде \(x\) и \(\sin(x)\) одновременно) может не быть реализованного алгоритма.

import sympy as sp

x = sp.Symbol('x')
eq2 = sp.Eq(sp.sin(x), x**2)

try:
    print(sp.solve(eq2, x))
except NotImplementedError as e:
    print("NotImplementedError:", e)
# NotImplementedError: multiple generators [x, sin(x)]
# No algorithms are implemented to solve equation -x**2 + sin(x)
Python

5.3. Численное решение (nsolve) и стартовая точка

Даже если аналитическое решение недоступно, часто можно найти корни численно. Для этого используют nsolve. Принцип важный: численный метод обычно требует стартовую точку, с которой начинается поиск.

import sympy as sp

x = sp.Symbol('x')
eq2 = sp.Eq(sp.sin(x), x**2)

r1 = sp.nsolve(eq2, -1)  # стартуем слева
r2 = sp.nsolve(eq2, 1)   # стартуем справа

print(float(r1))  #  -2.8548207047493545e-55
print(float(r2))  #  0.8767262153950625
Python

Разные стартовые точки могут привести к разным найденным корням (если уравнение имеет несколько решений). Это нормальная ситуация для численных методов: вы фактически “подводите” алгоритм к нужному корню.

5.4. Типичные ошибки

Ошибка 1: забыть указать переменную в solve

Для простых случаев SymPy иногда “догадается”, но лучше всегда писать явно: sp.solve(eq, x). Это делает код понятнее и снижает шанс неожиданных результатов.

Ошибка 2: ждать от nsolve “все корни сразу”

nsolve обычно находит один корень рядом со стартовой точкой. Если решений несколько, запускайте nsolve с разными стартовыми приближениями и сравнивайте результаты.

↑ К оглавлению

6. Дифференцирование, интегрирование, диф. уравнения, ряды и графики

6.1. Дифференцирование: diff

Любое выражение SymPy зависит от некоторых символов. Если рассматривать его как функцию от этих символов, можно применять дифференцирование. Для этого используется sp.diff.

Важно: нужно явно указывать переменную дифференцирования, особенно если переменных несколько.

import sympy as sp

x, y = sp.symbols('x y')
expr = x**2 + x*y + y**2

dx = sp.diff(expr, x)
dy = sp.diff(expr, y)

print(dx)  # 2*x + y
print(dy)  # x + 2*y
Python

Производные высших порядков можно получать, передавая кортеж (переменная, порядок). Например, вторая производная по \(y\):

import sympy as sp

x, y = sp.symbols('x y')
expr = x**2 + x*y + y**2

d2y = sp.diff(expr, (y, 2))
print(d2y)  # 2
Python

6.2. Интегрирование: integrate

Интеграл, как мы вспоминали ранее, бывает двух основных типов: неопределённый (возвращает выражение‑первообразную с точностью до константы) и определённый (даёт число, соответствующее площади/сумме на интервале).

В SymPy для интегрирования используют sp.integrate. Для неопределённого интеграла достаточно указать выражение и переменную.

import sympy as sp

x = sp.Symbol('x')
expr = 3*x**2 - 3*x

F = sp.integrate(expr, x)
print(F)  # x**3 - 3*x**2/2
Python

Для определённого интеграла передают кортеж (переменная, левая граница, правая граница).

import sympy as sp

x = sp.Symbol('x')
expr = x**2 - 3*x

res = sp.integrate(expr, (x, -2, 4))
print(res)  # 6
Python
Практический вывод: integrate умеет и неопределённые, и определённые интегралы. Если вы видите, что результат — дробь вроде \( \frac{a}{b} \), это хорошая новость: SymPy сохранил точность.

6.3. Функции как символы: Function

SymPy умеет создавать не только переменные‑символы, но и “неизвестные функции” — функции как символические объекты. Это нужно, чтобы записывать дифференциальные уравнения, интегральные уравнения и их комбинации.

import sympy as sp

x = sp.Symbol('x')
f = sp.Function('f')

expr = f(x)
print(expr)                # f(x)
print(sp.diff(expr, x))    # Derivative(f(x), x)
print(sp.diff(expr, x, 2)) # Derivative(f(x), (x, 2))
Python

6.4. Дифференциальные уравнения: dsolve

Если неизвестная величина — это функция, мы получаем дифференциальное уравнение. Для некоторых типов таких уравнений SymPy умеет находить общее решение через dsolve.

Рассмотрим пример уравнения второго порядка: \[ y''(x) - y(x) = 0. \] Здесь порядок — 2, поэтому в общем решении обычно появляется две произвольные константы.

import sympy as sp

x = sp.Symbol('x')
y = sp.Function('y')

ode = sp.Eq(sp.diff(y(x), x, 2) - y(x), 0)
sol = sp.dsolve(ode)

print(sol)  # Eq(y(x), C1*exp(-x) + C2*exp(x))
Python

В решениях вы часто увидите константы вида C1, C2. Их количество связано с максимальным порядком производной в уравнении: для уравнения второго порядка обычно появляется две константы.

6.5. Ряды: series и summation

SymPy умеет строить разложения в ряд (например, ряд Тейлора около точки). Обычно используют метод series, указывая переменную, точку разложения и порядок.

import sympy as sp

x = sp.Symbol('x')
expr = sp.sin(x) / x

# Разложение около 0 до членов порядка x^6 (включая O(x^7))
s = sp.series(expr, x, 0, 7)
print(s)

# Если нужно убрать "O(...)":
print(s.removeO())

#  1 - x**2/6 + x**4/120 - x**6/5040 + O(x**7)
#  -x**6/5040 + x**4/120 - x**2/6 + 1
Python

Кроме разложений в ряд, часто полезно вычислять суммы рядов. Для этого используют summation.

import sympy as sp

k = sp.Symbol('k', integer=True, positive=True)
S = sp.summation(1 / k**2, (k, 1, sp.oo))
print(S)        # pi**2/6
print(sp.N(S))  # 1.64493406684823   <-  численное приближение
Python

6.6. Построение графиков

В SymPy есть модуль построения графиков. Он удобен тем, что принимает символьные выражения. На практике чаще всего графики смотрят в Jupyter/IDE, где есть окно вывода. Ниже — базовый пример построения графика без использования изображений в конспекте (код вы запускаете у себя).

import sympy as sp
from sympy.plotting import plot

x = sp.Symbol('x')
p = plot(sp.sin(x), (x, -2*sp.pi, 2*sp.pi), show=False)
p.show()
Python

graff_sin_plot_0d1d2.jpeg

Если вы строите графики через matplotlib, можно сначала превратить выражение в “обычную функцию” через lambdify. Это мост между символьным миром SymPy и численным миром NumPy/Matplotlib.

import sympy as sp

x = sp.Symbol('x')
expr = sp.sin(x) / (1 + x**2)

f_num = sp.lambdify(x, expr, 'math')
print(f_num(0.5))  # 0.3835404308833624
Python

6.7. Типичные ошибки

Ошибка 1: не указать переменную в diff

Если выражение зависит от нескольких символов, SymPy не должен угадывать, по чему вы дифференцируете. Всегда пишите sp.diff(expr, x) или sp.diff(expr, y).

Ошибка 2: ожидать, что integrate всегда найдёт “красивую первообразную”

SymPy очень мощная, но не всесильная. Иногда первообразная выражается через специальные функции, а иногда SymPy не может найти её в замкнутом виде. В таких случаях приходится менять подход: упрощать выражение, использовать подстановку вручную или переходить к численным методам.

Ошибка 3: путать “функцию как символ” и “функцию как выражение”

y = sp.Function('y') задаёт неизвестную функцию. А выражение вроде sp.sin(x) — это уже конкретная функция, заданная формулой. В дифференциальных уравнениях часто нужна именно неизвестная функция.

Ошибка 4: пытаться “показать график” там, где окружение не поддерживает вывод

В некоторых окружениях (например, в консоли без GUI) plot(...) не сможет отобразить окно. Тогда используйте Jupyter, IDE с поддержкой графиков или экспорт в файл.

↑ К оглавлению

7. Практика: типовые задачи (с решениями)

Блок 1: числа и точность

Задача 1: создать точную дробь и выполнить вычисления без округлений

Создайте число 5/12 как Rational и вычислите квадрат. Убедитесь, что ответ тоже рациональный.

import sympy as sp

r = sp.Rational(5, 12)
print(r)      # 5/12
print(r**2)   # 25/144
print(type(r))
Python

Задача 2: численное приближение с контролем точности

Возьмите pi и выведите 6 знаков после запятой через sp.N.

import sympy as sp

print(sp.N(sp.pi, 7))  # 3.141593
Python

Блок 2: выражения и подстановки

Задача 3: раскрыть скобки и упростить выражение

Постройте (x+2y)^2, раскройте скобки, затем проверьте, что factor возвращает форму квадрата выражения.

import sympy as sp

x, y = sp.symbols('x y')
expr = (x + 2*y)**2

expanded = sp.expand(expr)
factored = sp.factor(expanded)

print("expr:", expr)  #  expr: (x + 2*y)**2
print("expanded:", expanded) #  expanded: x**2 + 4*x*y + 4*y**2
print("factored:", factored) #  factored: (x + 2*y)**2
Python

Задача 4: подстановка значений через subs

Подставьте x=1, y=3 в выражение x^2 + 2xy + y^2.

import sympy as sp

x, y = sp.symbols('x y')
expr = x**2 + 2*x*y + y**2

print(expr.subs({x: 1, y: 3}))  # 16
Python

Блок 3: производные/интегралы/уравнения

Задача 5: производные по разным переменным

Для f(x, y) = x^2 + xy + y^2 найдите ∂f/∂x и ∂f/∂y.

import sympy as sp

x, y = sp.symbols('x y')
f = x**2 + x*y + y**2

print(sp.diff(f, x))  # 2*x + y
print(sp.diff(f, y))  # x + 2*y
Python

Задача 6: определённый интеграл

Вычислите ∫ от -2 до 4 для (x^2 - 3x) dx.

import sympy as sp

x = sp.Symbol('x')
expr = x**2 - 3*x

print(sp.integrate(expr, (x, -2, 4)))  # 6
Python

Задача 7: решить уравнение аналитически и численно

Решите x^2 - x - 1 = 0 через solve. Затем решите sin(x) = x^2 через nsolve с двумя стартовыми точками.

import sympy as sp

x = sp.Symbol('x')

# Аналитическое решение:
eq1 = sp.Eq(x**2 - x - 1, 0)
print(sp.solve(eq1, x))

# Численное решение:
eq2 = sp.Eq(sp.sin(x), x**2)
print(float(sp.nsolve(eq2, -1)))
print(float(sp.nsolve(eq2, 1)))
Python

Блок 4: диф. уравнения/ряды/графики

Задача 8: решить дифференциальное уравнение второго порядка

Найдите общее решение y''(x) - y(x) = 0 через dsolve.

import sympy as sp

x = sp.Symbol('x')
y = sp.Function('y')

ode = sp.Eq(sp.diff(y(x), x, 2) - y(x), 0)
print(sp.dsolve(ode))
Python

Задача 9: получить разложение в ряд

Постройте ряд для sin(x)/x около 0 до порядка 6 (включая O(x^7)), затем удалите O(...).

import sympy as sp

x = sp.Symbol('x')
s = sp.series(sp.sin(x)/x, x, 0, 7)
print(s)
print(s.removeO())
Python

Задача 10: подготовить выражение к построению графика через lambdify

Сделайте численную функцию для sin(x)/(1+x^2) и посчитайте значение в точке x=0.5.

import sympy as sp

x = sp.Symbol('x')
expr = sp.sin(x) / (1 + x**2)

f_num = sp.lambdify(x, expr, 'math')
print(f_num(0.5))
Python
↑ К оглавлению

8. Чек‑лист самопроверки знаний

Отметьте пункты, которые вы действительно понимаете и можете применить без подсказок.

НавыкПроверка
Типы чисел SymPy Могу объяснить разницу между Integer, Rational и приближёнными числами (Float).
Рациональные дроби Могу создать дробь через Rational(p, q) и получить точный результат вычислений.
Символы Могу создать переменные через Symbol/symbols и использовать их в выражениях.
Преобразования выражений Могу раскрывать скобки (expand), факторизовать (factor), упрощать (simplify).
Подстановки Могу подставлять значения в выражение через subs и отличать это от replace.
Уравнения Могу правильно задавать уравнение через Eq и решать его через solve, если возможно.
Численное решение Могу применять nsolve и понимаю, зачем нужна стартовая точка.
Дифференцирование Могу взять производную выражения по нужной переменной через diff, в том числе высшего порядка.
Интегрирование Могу вычислять неопределённые и определённые интегралы через integrate.
Дифференциальные уравнения Могу задать неизвестную функцию через Function и получить общее решение через dsolve (для поддерживаемых типов уравнений).
Ряды Могу получить разложение в ряд через series и интерпретировать остаток \(O(\cdot)\).
Графики Могу построить график символьной функции через sympy.plotting или подготовить численную функцию через lambdify.
Итоги: SymPy — большая библиотека, и в одном уроке её возможности не исчерпать. Но вы познакомились с основой: числа, символы, выражения, уравнения и функции. Эти “кирпичики” лежат в основе большинства практических сценариев SymPy и позволяют дальше уверенно изучать более специализированные темы. В следующем материале мы перейдём к применению SymPy в линейной алгебре.
↑ К оглавлению

Ссылки по теме

Суббота, 28 февраля 2026
Выражения в SymPy