Упрощение: simplify, expand, factor

Одна и та же формула может выглядеть громоздко или красиво. SymPy умеет преобразовывать её — раскрывать, сворачивать, разлагать на множители.

Упрощение в SymPy — преобразование выражения к эквивалентной, но более удобной форме: раскрытию скобок (expand), разложению на множители (factor) или общему упрощению (simplify).

Зачем упрощать

Символьные выкладки быстро разрастаются: производная или интеграл часто выдаёт «простыню», которую глазом не прочесть. Упрощение приводит результат к человеческому виду, помогает заметить структуру (например, что выражение на самом деле равно нулю) и ускоряет дальнейшие вычисления. Но «простой» — понятие нечёткое: (x+1)² или x²+2x+1 — что проще? Зависит от задачи, поэтому инструментов несколько.

Три кита упрощения

ФункцияДействиеПример
expandраскрывает скобки(x+1)² → x²+2x+1
factorразлагает на множителиx²−1 → (x−1)(x+1)
simplifyпробует всё и выбирает «проще»sin²+cos² → 1

Есть и более точечные: collect (группирует по степеням), cancel (сокращает дроби), trigsimp (тригонометрия), together (приводит к общему знаменателю).

Как это в SymPy

import sympy as sp
x = sp.symbols("x")

print(sp.expand((x + 1)**3))         # x**3 + 3*x**2 + 3*x + 1
print(sp.factor(x**2 - 1))           # (x - 1)*(x + 1)
print(sp.simplify(sp.sin(x)**2 + sp.cos(x)**2))   # 1
print(sp.cancel((x**2 - 1)/(x - 1))) # x + 1 — сократили дробь

Обратите внимание на последнюю строку: SymPy знает алгебру и тригонометрию. sin²x + cos²x он сворачивает в 1 — не подставляя числа, а по тождеству.

Проверим тождество «руками»

SymPy упрощает (x+1)³ в x³+3x²+3x+1 по биному Ньютона. Убедимся, что это и правда одно и то же — на чистом Python, подставив несколько значений:

def left(x):
    return (x + 1) ** 3

def right(x):
    return x**3 + 3*x**2 + 3*x + 1

# проверяем на наборе точек — если совпадает везде, выражения равны
all_equal = all(left(t) == right(t) for t in range(-5, 6))
print("Формулы совпадают на всех точках:", all_equal)
print("Пример при x=2: левая =", left(2), ", правая =", right(2))

Вывод:

Формулы совпадают на всех точках: True
Пример при x=2: левая = 27 , правая = 27

Это, конечно, не доказательство (мы проверили лишь точки), но иллюстрация: expand даёт тождественно равную форму. SymPy же доказывает равенство символьно, преобразуя дерево.

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

Почему simplify называют «магией» и почему он медленный? Потому что не существует единого «самого простого» вида выражения — задача упрощения в общем случае неразрешима. simplify применяет десятки эвристик по очереди (раскрытие, факторизация, тригонометрические тождества, упрощение дробей и логарифмов), считает «меру сложности» каждого результата и возвращает наименьший. Поэтому он мощный, но непредсказуемый и небыстрый. Когда вы знаете, что нужно, лучше звать точечную функцию: expand, factor, trigsimp — они быстрее и предсказуемее.

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

  • Звать simplify на всё подряд. Он медленный; если знаете цель — берите expand/factor.
  • Ждать «канонической» формы. Что «проще» — субъективно; SymPy может вернуть не тот вид, что вы ожидали.
  • Сравнивать выражения через ==. (x+1)**2 == x**2+2*x+1 даст False (разные деревья!). Для проверки равенства используйте simplify(a - b) == 0.

Итог

  • expand раскрывает скобки, factor разлагает на множители, simplify пробует всё.
  • SymPy знает алгебру и тригонометрию: сворачивает sin²+cos² в 1.
  • simplify мощный, но медленный — для конкретной цели берите точечную функцию.
  • Равенство выражений проверяют через simplify(a−b)==0, а не ==.
Проверьте себя
1. Какая функция SymPy раскрывает скобки: (x+1)² → x²+2x+1?
Afactor
Bexpand
Csimplify
Dcollect
2. Почему simplify медленный и непредсказуемый?
AОн использует интернет
BЕдиного «простейшего» вида не существует — simplify перебирает десятки эвристик и выбирает наименьший по сложности результат
CОн всегда раскрывает скобки
DОн работает только с числами
3. Как правильно проверить, что два символьных выражения равны?
Aa == b
Bsimplify(a - b) == 0
Ca.subs(b)
Dexpand(a) > b