[SymPy] 数式の簡略化

[SymPy] 数式の簡略化

simplify()による数式の簡略化

 SymPy には数式を 簡略化 (simplification) するための色々な関数が用意されています。
 sympy.simplify() は、その中から最も適切だと思われる関数を自動選択して適用します。

 アバウトな指定方法なので、必ずしも思った通りの結果が得られるとは限りませんが、簡略化の傾向を知っておけば、それなりに使い勝手の良い関数です。最初に simplify() をトライして、必要であれば個々の簡略化関数で細かな微調整を施すようにします。下に simplify() による簡約化の例をいくつか挙げておきます。

 多項式はベキ乗順に並び替えられます:

# SIMPLIFY-1

from sympy import *

# a,b,c,d,x,yを記号として定義
var ("a b c d x y")

expr = d + b*x**2 + a*x**3 + c*x

# 数式を簡略化
expr = simplify(expr)

print(expr)
a*x**3 + b*x**2 + c*x + d

 数式全体の共通因子があれば括ります:

# SIMPLIFY-2

expr = a*x + a*b*y + a*b + a

# 数式を簡略化
expr = simplify(expr)

print(expr)
a*(b*y + b + x + 1)

 約分可能であれば、約分して返します:

# SIMPLIFY-3

# 分数式を定義
expr = (x**3 - 7*x**2 + 7*x + 15) / (x + 1)

# 簡略化(約分)
expr = simplify(expr)

print(y)
x**2 - 8*x + 15

 指数関数の積を渡すと指数部分を1つにまとめます:

# SIMPLIFIY-4

# 指数関数の積
expr = exp(a)*exp(2*a)*exp(b)

# 簡略化(指数をまとめる)
expr = simplify(expr)

print(y)
exp(3*a + b)

 三角関数の公式が適用できるところはまとめます:

# SIMPLIFY-5

# 三角関数の積
expr = 2*sin(x)*cos(x)

# 簡略化(倍角公式)
expr = simplify(expr)

print(expr)
sin(2*x)

 分数式の分母に無理数が含まれていれば有理化します:

# SIMPLIFY-6

expr = 1 / (3 + sqrt(5))

# 分母を有理化
expr = simplify(expr)

print(expr)
3/4 - sqrt(5)/4

 
 simplify() は trigsimp() や radsimp() などの簡略化関数を複合的に適用します。

# SIMPLIFY-7

expr = (cos(x)**2 + sin(x)**2 + log(x) + log(a)) / (1 + sqrt(2))

# 数式を簡略化
expr = simplify(expr)

print(expr)
-log(a) + sqrt(2)*log(a) - log(x) + sqrt(2)*log(x) - 1 + sqrt(2)

 とはいえ、simplify() だけですべてが解決するわけではありません。
 上のコードの実行結果は共通項でまとまっていません。
 こういう場合は結果を見てから必要な簡略化関数を適用します。
 因数分解が可能かもしれないので、factor() を試します。

# SIMPLIFY-8

# 因数分解
expr = factor(expr)

print(expr)
(-1 + sqrt(2))*(log(a) + log(x) + 1)

 simplify() は対数関数の簡略化はしないので、必要であれば logcombine() で明示的に結合します。

# SIMPLIFY-9

# 対数関数を結合
expr = logcombine(expr, force=True)

print(expr)
(-1 + sqrt(2))*(log(a*x) + 1)

 こうした手続きを毎回実行するのは面倒なので、1つの関数としてまとめておくと便利です。

# SIMPLIFY-10

def simplify_2(expr):
    f = simplify(expr)
    g = factor(f)
    h = logcombine(g, force=True)
    return h

# 数式を定義
expr = (cos(x)**2 + sin(x)**2 + log(x) + log(a)) / (1 + sqrt(2))

# 数式を整理
expr = simplify_2(expr)

print(expr)
(-1 + sqrt(2))*(log(a*x) + 1)