Что такое SymPy
? Это библиотека символьной математики языка Python. Она является реальной альтернативой таким математическим пакетам как Mathematica или Maple и обладает очень простым и легко расширяемым кодом. SymPy
написана исключительно на языке Python и не требует никаких сторонних библиотек.
Документацию и исходный код этой библиотеки можно найти на ее официальной странице.
Первые шаги с SymPy
Используем SymPy как обычный калькулятор
В библиотеке SymPy есть три встроенных численных типа данных: Real
, Rational
и Integer
. С Real
и Integer
все понятно, а класс Rational
представляет рациональное число как пару чисел: числитель и знаменатель рациональной дроби. Таким образом, Rational(1, 2)
представляет собой 1/2
, а, например, Rational(5, 2)
— соответственно 5/2
.
import sympy as sym a = sym.Rational(1, 2) # дает 1/2 a * 2 # дает 1
Библиотека SymPy
использует библиотеку mpmath
, что позволяет производить вычисления с произвольной точностью. Таким образом, ряд констант (например, пи, e), которые в данной библиотеке рассматриваются как символы, могут быть вычислены с любой точностью.
sym.pi**2 # результат pi**2 sym.pi.evalf() # результат 3.14159265358979 (sym.pi + sym.exp(1)).evalf() # результат 5.85987448204884
Как можно заметить, функция evalf()
дает на выходе число с плавающей точкой.
В SymPy
есть также класс, представляющий такое понятие в математике, как бесконечность. Он обозначается следующим образом: oo
.
sym.oo > 99999 # результат True sym.oo + 1 # результат oo
Символы
В отличие от ряда других систем компьютерной алгебры, в SymPy
можно в явном виде задавать символьные переменные. Это происходит следующим образом:
x = sym.Symbol('x') y = sym.Symbol('y')
После их задания, с ними можно производить различные манипуляции.
x + y + x - y # результат 2*x (x + y) ** 2 # результат (x + y)**2
С символами можно производить преобразования с использованием некоторых операторов языка Python. А именно, арифметических (+
, -`
, ``*
, **
) и логических (&
, |
, ~
) .
Библиотека SymPy
позволяет задавать форму вывода результатов на экран. Обычно мы используем формат такого вида:
sym.init_printing(use_unicode=False, wrap_line=True)
Алгебраические преобразования
SymPy
способна на сложные алгебраические преобразования. Здесь мы рассмотрим наиболее востребованные из них, а именно раскрытие скобок и упрощение выражений.
Раскрытие скобок
Чтобы раскрыть скобки в алгебраических выражениях, используйте следующий синтаксис:
sym.expand((x + y) ** 3)
?3+3?2?+3??2+?3
3 * x * y ** 2 + 3 * y * x ** 2 + x ** 3 + y ** 3
?3+3?2?+3??2+?3
При помощи ключевого слова можно добавить поддержку работы с комплексными переменными, а также раскрытие скобок в тригонометрических функциях.
sym.expand(x + y, complex=True)#результат re(?)+re(?)+?im(?)+?im(?) sym.expand(sym.cos(x + y), trig=True) # результат −sin(?)sin(?)+cos(?)cos(?)
Упрощение выражений
Если вы хотите привести выражение к более простому виду (возможно, сократить какие-то члены), то используйте функцию simplify
.
sym.simplify((x + x * y) / x) # результат y + 1
Также надо сказать, что для определенных видов математических функций существуют альтернативные, более конкретные функции для упрощения выражений. Так, для упрощения степенных функций есть функция powsimp
, для тригонометрических —trigsimp
, а для логарифмических — logcombine
, radsimp
.
Вычисления
Вычисления пределов
Для вычисления пределов в SymPy предусмотрен очень простой синтаксис, а именно limit(function, variable, point)
. Например, если вы хотите вычислить предел функции f(x)
, где x -> 0
, то надо написать limit(f(x), x, 0)
.
sym.limit(sym.sin(x) / x, x, 0) # результат 1
Также можно вычислять пределы, которые стремятся к бесконечности.
sym.limit(x, x, sym.oo) # результат oo sym.limit(1 / x, x, sym.oo) # результат 0 sym.limit(x ** x, x, 0) # результат 1
Дифференцирование
Для дифференцирования выражений в SymPy
есть функция diff(func, var)
. Ниже даны примеры ее работы.
sym.diff(sym.sin(x), x) # результат cos(?) sym.diff(sym.sin(2 * x), x) # результат 2cos(2?) sym.diff(sym.tan(x), x)
tan2(?)+1
Проверим результат последней функции при помощи определения производной через предел.
sym.limit((sym.tan(x + y) - sym.tan(x)) / y, y, 0)
tan2(?)+1
Результат тот же.
Также при помощи этой же функции могут быть вычислены производные более высоких порядков. Синтаксис функции будет следующим: diff(func, var, n)
. Ниже приведено несколько примеров.
sym.diff(sym.sin(2 * x), x, 1) # результат 2cos(2?) sym.diff(sym.sin(2 * x), x, 2) # результат −4sin(2?) sym.diff(sym.sin(2 * x), x, 3) # результат −8cos(2?)
Разложение в ряд
Для разложения выражения в ряд Тейлора используется следующий синтаксис: series(expr, var)
.
sym.series(sym.cos(x), x)
1−?2/2+?4/24+?(?6)
sym.series(1/sym.cos(x), x)
1+?2/2+5?4/24+?(?6)
Интегрирование
В SymPy реализована поддержка определенных и неопределенных интегралов при помощи функции integrate()
. Интегрировать можно элементарные, трансцендентные и специальные функции. Интегрирование осуществляется с помощью расширенного алгоритма Риша-Нормана. Также используются различные эвристики и шаблоны. Вот примеры интегрирования элементарных функций:
sym.integrate(sym.sin(x), x) # результат −cos(?) sym.integrate(sym.log(x), x) # результат ?log(?)−?
Также несложно посчитать интеграл и от специальных функций. Возьмем, например, функцию Гаусса:
sym.integrate(sym.exp(-x ** 2) * sym.erf(x), x)
Результат вычисления можете посмотреть сами. Вот примеры вычисления определенных интегралов.
sym.integrate(x**3, (x, -1, 1)) # результат 0 sym.integrate(sym.sin(x), (x, 0, sym.pi / 2)) # результат 1 sym.integrate(sym.cos(x), (x, -sym.pi / 2, sym.pi / 2)) # результат 2
Также можно вычислять определенные интегралы с бесконечными пределами интегрирования (несобственные интегралы).
sym.integrate(sym.exp(-x), (x, 0, sym.oo)) # результат 1
Решение уравнений
При помощи SymPy
можно решать алгебраические уравнения с одной или несколькими переменными. Для этого используется функция solveset()
.
sym.solveset(x ** 4 - 1, x) # результат {−1,1,−?,?}
Как можно заметить, первое выражение функции solveset()
приравнивается к 0
и решается относительно х
. Также возможно решать некоторые уравнения с трансцендентными функциями.
sym.solveset(sym.exp(x) + 1, x) # результат {?(2??+?)|?∈ℤ}
Системы линейных уравнений
SymPy
способна решать широкий класс полиномиальных уравнений. Также при помощи данной библиотеки можно решать и системы уравнений. При этом переменные, относительно которых должна быть разрешена система, передаются в виде кортежа во втором аргументе функции solve()
, которая используется для таких задач.
solution = sym.solve((x + 5 * y - 2, -3 * x + 6 * y - 15), (x, y)) solution[x], solution[y] # результат (-3, 1)
Факторизация
Другим мощным методом исследования полиномиальных уравнений является факторизация многочленов (то есть представление многочлена в виде произведения многочленов меньших степеней). Для этого в SymPy
предусмотрена функция factor()
, которая способна производить факторизацию очень широкого класса полиномов.
f = x ** 4 - 3 * x ** 2 + 1 sym.factor(f)
(?2−?−1)(?2+?−1)
sym.factor(f, modulus=5)
(?−2)2(?+2)2
Булевы уравнения
Также в SymPy
реализована возможность решения булевых уравнений, что по сути означает проверку булевого выражения на истинность. Для этого используется функция satisfiable()
.
sym.satisfiable(x & y) # результат {x: True, y: True}
Данный результат говорит нам о том, что выражение (x & y)
будет истинным тогда и только тогда, когда x
и y
истинны. Если выражение не может быть истинным ни при каких значениях переменных, то функция вернет результат False
.
sym.satisfiable(x & ~x) # результат False
Линейная алгебра
Матрицы
Матрицы в SymPy
создаются как экземпляры класса Matrix
:
sym.Matrix([[1, 0], [0, 1]])
[10]
[01]
В отличие от NumPy
, мы можем использовать в матрицах символьные переменные:
x, y = sym.symbols('x, y') A = sym.Matrix([[1, x], [y, 1]]) A
[1 ?]
[? 1]
И производить с ними разные манипуляции:
A**2
[??+1 2?]
[2? ??+1]
Дифференциальные уравнения
При помощи библиотеки SymPy можно решать некоторые обыкновенные дифференциальные уравнения. Для этого используется функция dsolve()
. Для начала нам надо задать неопределенную функцию. Это можно сделать, передав параметр cls=Function
в функцию symbols()
.
f, g = sym.symbols('f g', cls=sym.Function)
Теперь f
и g
заданы как неопределенные функции. мы можем в этом убедиться, просто вызвав f(x)
.
f(x) # результат ?(?) f(x).diff(x, x) + f(x)
?(?)+?2/??2?(?)
Теперь решим следующее дифференциальное уравнение:
sym.dsolve(f(x).diff(x, x) + f(x), f(x)) # результат ?(?)=?1sin(?)+?2cos(?)
Чтобы улучшить решаемость и помочь этой функции в поиске решения, можно передавать в нее определенные ключевые аргументы. Например, если мы видим, что это уравнение с разделяемыми переменными, то мы можем передать в функцию аргумент hint='separable'
.
sym.dsolve(sym.sin(x) * sym.cos(f(x)) + sym.cos(x) * sym.sin(f(x)) * f(x).diff(x), f(x), hint='separable') # результат [Eq(f(x), -acos(C1/cos(x)) + 2*pi), Eq(f(x), # acos(C1/cos(x)))]