読者です 読者をやめる 読者になる 読者になる

車輪を再発明

プログラミングは趣味です。PythonとかGoogle App Engineとか触りますが、映画とかゲームとかの感想も書くかもしれません。。。

SymPyを使ってみる

Python SymPy

SymPyは記号計算を行うためのPythonパッケージです。

最近、勾配法などの最適化手法を勉強中なのですが、関数の微分や、関数とその接線を図示するといったことが簡単にできるようなパッケージはないのかな、とさがして見つけたものです。

まだ使い始めたばかりなので、今後追記していくと思います。行列の使い方を追記したので、これで終わりかもです。

SymPy

SymPyとは

SymPyは記号計算に特化したパッケージです。
関数の微分積分や、matplotlibと連携して関数をプロットすることもできます。

基本的な使い方

symbolを宣言することで、symbol同士の演算ができるようになります。

>> from sympy import *

# symbolの宣言
>> x, y = symbols("x y")

# symbol同士の演算
>> x + y
x + y

# 省略可能な表現は省略される
>> x + y - x
y

関数の表現と代入

記号の演算によって、関数を表現することができます。

# 関数の定義
>> f = 2 * x ** 2 - 3 * x + 1

# 因数分解
>> f.factor()
(x - 1)*(2*x - 1)

# f(x) = 0となるようなxを求める
>> solve(Eq(f, 0), x)
[1/2, 1]

# x = 0を代入する
>> f.subs([(x, 0)])
1

微分積分

diffとintegrateによって、微分積分が計算できます。
微分の結果に値を代入することもできます。

# 関数の定義
>> f = 2 * x ** 2 - 3 * x + 1

# 微分する
>> grad = diff(f, x)
>> grad
4*x - 3

## 傾きを求める
>> grad.subs([(x, 0)])
-3

# 不定積分する(積分定数はつきません)
>> integrate(f, x)
2*x**3/3 - 3*x**2/2 + x

# 定積分する
>> integrate(f, (x, 0, 1))
1/6

# symbolを用いて定積分する
>> integrate(f, (x, a, b))
-2*a**3/3 + 3*a**2/2 - a + 2*b**3/3 - 3*b**2/2 + b

行列

行列を作ることもできます。
行列の微分積分は、専用のメソッドが用意されています。

>> from sympy import Matrix, symbols
>> x, y = symbols("x y")
>> f = x ** 2 + 2 * x * y + y ** 2
>> m = Matrix([[1, 2 * x],[3 * y, f]])
>> m
Matrix([
[  1,                 2*x],
[3*y, x**2 + 2*x*y + y**2]])

# 行列の微分
>> m.diff(x)
Matrix([
[0,         2],
[0, 2*x + 2*y]])

# 行列の積分
>> m.integrate(y)
Matrix([
[       y,                    2*x*y],
[3*y**2/2, x**2*y + x*y**2 + y**3/3]])

関数のプロット

matplotlibへのapiが用意されています。
関数のまま渡すだけでプロットしてくれます。
3次元のプロットもできます。

>> from sympy.plotting import plot

# 関数の定義
# xが[-1, 2]の範囲を図示する
>> plot(f, (x, -1, 2))

f:id:taromaru-kun:20150314201106p:plain

2次元に限りますが、f(x,y) = 0というような陰関数であっても図示できます。

>> from sympy.plotting import plot_implicit
>> x, y = symbols("x y")

# f(x, y)は半径1の円を表す
>> f = x ** 2 + y ** 2 - 1

# f(x, y)を図示する
>> plot_implicit(f, (x, -2, 2), (y, -2, 2))

f:id:taromaru-kun:20150314202056p:plain