つれづれなる備忘録

日々の発見をあるがままに綴る

SymPyの使い方3 ~ 数式の簡素化

 今回はSymPyを用いて数式を簡素化するための方法を中心に紹介したい。簡素化は一般的な数式処理ソフトと同様だが、どのようにすれば簡単になるかは事前に判断して、どのようなコマンドを用いるか決める必要があり扱いが比較的難しい。

atatat.hatenablog.com

1. 一般的な簡素化

 どうやって簡素化するかわからないときはsimplifyをまず試してみる。

simplify(cos(x)**2+sin(x)**2)
>1

これ以上簡素化できない場合は以下のように入力した式がそのまま出力される。

simplify(cos(x)**2)
>cos(x)**2

以下は分子は(x-1)*(x+1)**2を展開したもの、分母は(x+1)**2であるが

 simplify((x**3 + x**2 - x - 1)/(x**2 + 2*x + 1))
>x-1

分母分子の共通項が消去されて簡素化された。

特殊関数の計算も有効でガンマ関数の場合は

simplify(gamma(x)/gamma(x - 2))
>(x-2)*(x-1)

このようにsimplifyは強力なコマンドだが、最も簡単な表現になるわけではない。例えば

simplify(x**2+2*x+1)
>x**2 + 2*x + 1

この場合はsimplifyよりも因数分解を行うfactorを指定すると簡単になる。

factor(x**2+2*x+1)
>(x + 1)**2

ただし、以下の例だとsimplifyでも因数分解される。

simplify(x**2+2*x)
>x*(x + 2)

2. 式の整理

 式の簡素化よりも式を具体的に整理するコマンドとして展開expand,因数分解 factor,べき乗ごとに整理するcollect, 有理表現cancel がある。

式の展開:expand

前回も紹介したように、式を展開して多項式を表示するコマンド。3角関数の展開にも有効で

expand((cos(x) + sin(x))**2)
>sin(x)**2 + 2*sin(x)*cos(x) + cos(x)**2

ただし、cos(x)**2+sin(x)**2の部分は1に置き換えてくれないので、さらにsimplifyと組み合わせると

f=expand((cos(x) + sin(x))**2)
simplify(f)
>sin(2*x) + 1

簡素化された表現になる。

因数分解:factor

factorも以前に紹介したが、多項式因数分解するのに用いる。

factor(x**2*z + 4*x*y*z + 4*y**2*z)
>z*(x + 2*y)**2

factor_listを用いると因数成分のみを表示する。

factor_list(x**2*z + 4*x*y*z + 4*y**2*z)
>(1, [(z, 1), (x + 2*y, 2)])

1以外は(要素,次数)のリストが出力される。

べき乗ごとに整理:collect

collectを用いると指定した変数のべき乗で整理される。例えば、

expr = x*y + x - 3 + 2*x**2 - z*x**2 + x**3
expr
>x**3 - x**2*z + 2*x**2 + x*y + x - 3
collect(expr,x)
>x**3 + x**2*(-z + 2) + x*(y + 1) - 3

さらに.coeff(x,2)とするとxの2乗にかかる係数を出力する。

collect(expr,y).coeff(x,2)
>-z + 2

有理表現:cancel

cancelを用いるとq/pにように有理表現で式を表示する。例えば、

 cancel((x**2 + 2*x + 1)/(x**2 + x))
>(x + 1)/x

有理表現にしつつ、共通因子の(x+1)を打ち消している。

cancel(1/x + (3*x/2 - 2)/(x - 4))
>(3*x**2 - 2*x - 8)/(2*x**2 - 8*x)

べき乗としては増えてしまうが有理表現でまとめている。

3. まとめ

 SymPyを用いて式を簡素化する方法について今回は紹介した。汎用的にはsimplifyだが、必ずしも簡素化できるわけではなく状況に応じてexpand,factor,cancelなどを使い分ける必要がある。