Python からはじめる数学入門 (Doing Math with Python)(まとめ記事)の第 4 章を読む。コンピュータ代数(数式処理) のパッケージ SymPy を利用して、数式を展開・因数分解したり、方程式を代数的に解いたりしながら、これまでの数値計算とは一味違った世界を垣間見る。
内容
- Symbols(記号、数学的な意味での変数)の定義
- Mathematical Expressions(数式)の定義
- 式変形
factor()
関数: 因数分解expand()
関数: 展開simplify()
関数: 全自動の簡約化 ← 全能ではない!subs()
メソッド: 式への置換(代入)- 数値を代入
- 式を代入
- 式の表示
pprint()
関数: 数式をアスキーアートで出力init_printing()
関数: 式の出力設定(項の表示順など)- 項を次数の昇順に並べたいが、
order="grevlex"
を指定しても思うように変化しない!
- 項を次数の昇順に並べたいが、
simplify()
関数: 文字列を式に変換(にも使える)- 無効な文字列を与えた時は、例外
SympifyError
が発生
- 無効な文字列を与えた時は、例外
solve()
関数: 方程式を解く- 2 次方程式
- 係数が数値の場合
- 係数も記号(変数)の場合(一般的に解く)
- 2 元 1 次連立方程式
- 2 次方程式
plot()
関数: グラフを描く- 変数 の 2 元方程式のグラフ
- について解いてから、
plot()
関数に渡す
- について解いてから、
- 複数の関数のグラフ
- 変数 の 2 元方程式のグラフ
ポイント
本章を読んで気になったり、感銘を受けた内容について。
式の表示
JupyterLab で SymPy を使う場合は、SymPy の数式が自動的に で美しく表示されるので素晴らしい!!
しかし従来の表示方法も一応確認しておく。
print()
関数: Python コードで表示sympy.pprint()
関数: アスキーアート
例えば積分
を考える。
expr = sympy.Integral(sympy.sqrt(1 / x), x)
print(expr)
→ Integral(sqrt(1/x), x)
sympy.pprint(expr)
⌠
⎮ ___
⎮ ╱ 1
⎮ ╱ ─ dx
⎮ ╲╱ x
⌡
項の表示順
数式は高次の項から降順に自動的に並び替えて表示される。
expr = 1 + x + 2 * x ** 2
expr
→
init_printing()
関数に order="grevlex"
を渡せば昇順で表示されるようになるはずだが、何故か思うように変化しない!
sympy.init_printing(order="grevlex")
expr = 1 + x + 2 * x ** 2
expr
→
ちなみにテイラー展開をする series()
メソッドを使うと、ちゃんと昇順に並ぶので何か正しい方法はあるはず。
expr = sympy.exp(x)
expr.series(x, 0, 5)
コマンドで表示
latex()
関数を利用すると、SymPy の式が コマンドに変換できる。コピペすると便利!!
expr = sympy.Integral(sympy.sqrt(1 / x), x)
print(sympy.latex(expr))
→ \int \sqrt{\frac{1}{x}}\, dx
有理数 Rational
Solving for One Variable in Terms of Others の運動方程式を解いていて気がついたのだが、本文にあるように (1 / 2) * x
と書くと、 と小数になってしまう。
SymPy には有理数を表す sympy.Rational
クラスがあるので、それを利用して sympy.Rational(1, 2) * x
と書くと良い。
https://docs.sympy.org/latest/modules/core.html#rational
プログラミング・チャレンジ(章末問題)
#1: Factor Finder→ スキップ- ユーザ入力を受けて数式を因数分解する
- #2: Graphical Equation Solver
- ユーザ入力(2 つの 2 元 1 次方程式)を受けて、グラフ表示して、方程式を解く
- → Jupyter ノートブック
- #3: Summing a Series
- ユーザ入力(数列の一般項)を受けて、数列の和を計算する
- に相当する
sympy.summation()
関数を利用 - → Jupyter ノートブック
- #4: Solving Single-Variable Inequalities
- ユーザ入力(1 変数の不等号式)を受けて、不等号を解く
- → Jupyter ノートブック
#3: Summing a Series
一般項を渡すと級数の和を計算してくれる sympy.summation()
関数を利用する。試しに自然対数の底 を計算してみる。一般項は次のように書ける。
term = 1 / sympy.factorial(n)
第 5 項まで計算する。小数点第 2 位まで一致する。
sum = sympy.summation(term, (n, 0, 5))
sum.evalf()
→ 2.71666666666667
次に第 10 項まで計算する。小数点第 7 位まで一致する。
sum = sympy.summation(term, (n, 0, 10))
sum.evalf()
→ 2.71828180114638
結構収束が速い事がわかる。
#4: Solving Single-Variable Inequalities
SymPy では、1 変数の不等号を解くができるが、式の種類によってソルバー関数が 3 種類に分かれる。
solve_poly_inequality()
: 多項式solve_rational_inequalities()
: 有理式solve_univariate_inequality
: それ以外
それは良いが、途中で式を poly
(多項式)に変換が必要だったり、有理式だけ [[ ... ]]
で式を渡す必要があったりと、ちょっと使いにくい気がする。
# 解きたい不等式(有理式)
ineq_obj = ((x ** 2 + x - 1) / (x + 2)) > 0
# 分母と分子に分ける
numer, denom = ineq_obj.lhs.as_numer_denom()
# 分母と分子を Poly(多項式)へ変換
p1 = sympy.Poly(numer)
p2 = sympy.Poly(denom)
# 不等号を取得
rel = ineq_obj.rel_op
# 不等号を解く
sympy.solve_rational_inequalities([[((p1, p2), rel)]])
→
ちゃんと代数的に解けている。グラフはこんなかんじ。
参考リンク
Sympy+Jupyter で最強の電卓環境を作る - Qiita
SymPy:計算機代数システム ←Python 数値計算入門 の一部
入力例で学ぶ Python (SymPy) の使い方(入門) - pianofisica
Chapter 5 のまとめ「Python からはじめる数学入門 - Chapter 5: Playing with Sets and Probability を読む)」を公開しました!テーマは 確率と乱数。準備として SymPy で集合を取り扱った上で、幾つかの確率計算と、乱数を用いた実験を行います。