桂誠
sympy というモジュールを用いると、数式をTeX形式で綺麗に出力したり、代数計算を行うこともできます。 このモジュールはなぜか、私のPCの一つにはインストールされていなかったようで、インストールする必要がありました。 pythonxyには入っていますので、インストールし忘れていたのかもしれません。
正式でない64ビット版 は見つかりますが、私自身は32ビットのWindows PCを利用しているので、こちらの動作確認はしていません。 winpythonの64ビット版にもこれが入っているのではないかと推察します。
%load_ext sympy.interactive.ipythonprinting
このコマンドでsympyというモジュールを用いて書かれた数式の画面出力が得られます。
import sympy
from sympy import var,Eq
var('a:z')#普通の小文字のaからzは全てsympyのシンボル(変数)として扱うことにしました。
eq1=Eq(a*x**2+b*x+c,0)
eq1
下記のように、方程式を解く事もできます。
eq2=eq1.subs({a:1,b:0,c:1})# 各係数に値を代入。
from sympy import solve
ans=solve(eq2)
ans
このように、iの上の点がありません。 これは虚数単位の$i$に\imathというTeXコマンドが使用されているのが原因のようです。 これは私には気持ち悪いので、以下のコマンドを定義してみました。
def print_eq(eq):
from IPython.display import display, Math
from sympy import latex
display(Math(latex(eq).replace('\imath','i')))
print_eq(ans)
こっちなら私は許容できます。
print ans
[-I, I]
単にprintとすれば、Sympyでのキャラクタが出力されます。以下も同様です。
print eq1
print eq2
a*x**2 + b*x + c == 0 x**2 + 1 == 0
少しだけ複雑な例を示します。
from sympy import atan, pi
y=2*x+1
exp0=atan(y**2/(2*y+10)**2)
exp1=sympy.integrals.Integral(exp0,(x,-10.0,pi))
print_eq(exp1)
print(exp1)
print(exp0)
Integral(atan((2*x + 1)**2/(4*x + 12)**2), (x, -10.0, pi)) atan((2*x + 1)**2/(4*x + 12)**2)
自動的にyを代入してくれるので、複雑な式を書くには便利です。
今度は、この式をNumpyで扱ってみましょう。 手で少し書き換えます。 上のprint文の出力をコピペして簡単な関数を定義します。
def exp0_func(x):
from numpy import arctan # numpyではarctan, sympyではatan
return arctan((2*x + 1)**2/(4*x + 12)**2)
_x=np.arange(-10.0,np.pi,0.1)
plt.plot(_x,exp0_func(_x))
[Line2D(_line0)]
このように関数をわざわざ定義して、x、yという変数を使わなかったのは、普通のアルファベットのaからzはsympyのシンボルとして予約してしまったからです。
次に、scipyで積分を実行してみましょう。
from scipy import integrate
integrate.quad(exp0_func,-10.0,np.pi)
最初の値が積分結果、2番目の値は誤差の見積もりです。 このように、Numpy,ScipyとSympyの間の式の変換は手動でそれほど面倒ではありません。
ところが、実は、
exp1.evalf()
これだけで積分が実行できてしまうので、今の場合ならScipyを使う必要はありませんでした。 プロットに関しても、
from sympy.plotting import plot
plot(exp0,(x,-10.0,pi))
Plot object containing: [0]: cartesian line: atan((2*x + 1)**2/(4*x + 12)**2) for x over (-10.0, 3.141 592653589793)
このようにMatplotlibを使わずにSympy内部の関数でも簡単なグラフ作成は可能です。
これまで見てきたように、Sympyはそれ単独で相当な事ができるモジュールであることが想像できます。 私自身は、現時点では、Sympyの全貌が把握できていません。 (他のモジュールだってそうですが。。)
しかし、複雑な数式を扱う必要がある場合にはSympyを利用し、それ以外の時にはNumpy,Scipyを用いるとすると、 私の場合にはSympyの使用頻度は今後もあまり高くならないと予想しています。
Sympyの代数計算の機能については殆ど触れませんでした。
チュートリアル にあるものを抜粋しただけでも、以下の通りです。
これ以外の重要な機能としては、計算式の単純化( simplify )があります。 どのように式を単純化すべきか、というのは自明ではない(人間の都合による)ので、色んな設定を必要とします。 手計算の補助という位置づけで考えておくと良いと思います。
また、physics というモジュールもあります。 ここには量子力学や力学の計算に使えるモジュールの他に、単位換算に利用できるようなモジュールもあり、以下のように便利に使えそうです。
import sympy.physics.units as unit
unit.find_unit("avogad")[1]
avogadro_number
unit.avogadro_number
unit.find_unit("planc")
[planck]
unit.planck
unit.planck.evalf()
unit.find_unit(unit.pressure)
[Pa, pa, atm, bar, kPa, psi, bars, mmHg, pascal, pascals, pressure, atmosphere , atmospheres]
3.5*unit.psi
しかし、Scipyにも同様に便利なモジュールがあります。
Sympyはこれだけ高機能です。 また、Sympyで得た数式オブジェクトをNumpy等で直接利用するはことはできませんので、コピー&ペーストと多少の書き換えを必要とします。
ですから、複雑な数式を取り扱う必要が生じた場合には、一つのNotebook内ではほぼSympyに徹し、 実験データを取り扱う場合には逆にSympyは使わないといった使い分けをした方が良いように思えます。
全てをSympyで行う可能性、また、 Sage などの巨大なソフトウェアを使うことなども将来的には考えてもよいのかも知れませんが、 Windows環境において、Numpy(+Scipy)+Matplotlibをメインとする実験データの解析とSympyをメインとする数式処理をある程度分けて行う事は、 多くの実験屋にとっては軽快で十分なやり方だろうと思っています。 そして、その両方がipython notebookという一つの環境で実行できるなんて、とても便利なことだと思います。