『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

【SymPy】級数展開

ベキ級数展開

ある関数 $f(x)$ を $x$ のベキ級数(整級数)
 \[a_0+a_1(x-x_0)^1+a_2(x-x_0)^2+\cdots\]
で表すことを 関数の 級数展開 といいます。無限に項をとることによって、理論上は関数と級数展開は厳密に一致しますが、実用のために有限項で打ち切っても、適切な数の項をとることによって、ベキ級数は $x=x_0$ の近くで関数の良い近似を与えます (ただし、$x$ が $x_0$ から離れるほどその精度は下がっていきます)。たとえば、$\sin x$ のマクローリン級数
 \[\sin x=x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\: \cdots\]
などは級数展開の代表的な例の1つです。

sympy.series()

SymPy パッケージsympy.series() を使うと任意の関数をベキ級数展開できます。
以下のコードは Jupyter notebook の使用を前提に記述されています。
最初に必要な関数をまとめてインポートしておきます。

# SYMPY_SERIES

# In[1]

from sympy import init_printing, var, series, poly, cos, sin

# 数式をLaTeX表示
init_printing()

# シンボルxを定義
var('x')

$\sin x$ を $x=0$ の近くで級数展開してみましょう。

# In[2]

# sinxをx=0の周りで級数展開
series(sin(x), x)
\[x – \frac{x^{3}}{6} + \frac{x^{5}}{120} + O\left(x^{6}\right)\]

デフォルト設定では、$x^6$ 以降の項はすべて O(x**6) にまとめられています。オプション引数 n でこの設定を変更することができます。たとえば、O(x**7) まで級数を表示したい場合は次のように記述します。

# In[3]

# sinxをx=0の周りで級数展開
series(sin(x), x, n=8)
\[x – \frac{x^{3}}{6} + \frac{x^{5}}{120} – \frac{x^{7}}{5040} + O\left(x^{8}\right)\]

オプション引数 x0 で展開の中心点を指定できます (デフォルトは 0)。$\sin x$ を $x=1$ のまわりで展開してみます。

# In[4]

# sinxをx=1の周りで級数展開
series(sin(x), x, x0=1)
\[\begin{align*}
\sin{\left (1 \right )} &+ \left(x – 1\right) \cos{\left (1 \right )} – \frac{\left(x – 1\right)^{2} \sin{\left (1 \right )}}{2} – \frac{\left(x – 1\right)^{3} \cos{\left (1 \right )}}{6}\\[6pt]
&+ \frac{\left(x – 1\right)^{4} \sin{\left (1 \right )}}{24} + \frac{\left(x – 1\right)^{5} \cos{\left (1 \right )}}{120} + O\left(\left(x – 1\right)^{6}; x\rightarrow 1\right)\end{align*}\]

sympy.series() で得た式を sympy.poly() で多項式クラス (sympy.polys.polytools.Polyクラス) のオブジェクトに変換しておくと、色々なメソッドが使えるようになって便利です。$\cos x$ を級数展開して、coeffs()メソッドで $x^n$ の係数をすべて取り出してみます。

# In[5]

# cosxをx=0の周りで級数展開
f = series(cos(x), x, n=10)

# 級数展開された多項式fを表示
display(f)

# fを多項式オブジェクトに変換
g = poly(f)

# 級数の係数をすべて取得
c = g.coeffs()
c.reverse()

# 級数の係数を表示
display(c)
\[\begin{align*}&1 – \frac{x^{2}}{2} + \frac{x^{4}}{24} -\frac{x^{6}}{720} + \frac{x^{8}}{40320} + O\left(x^{10}\right)\\[6pt]&\left [ 1, \quad 1, \quad – \frac{1}{2}, \quad \frac{1}{24}, \quad – \frac{1}{720}, \quad\frac{1}{40320}\right ]\end{align*}\]

母関数の級数展開

級数 $a_n$ が関数 $p(x)$ を級数展開したときの $x^n$ の係数となっているとき、$p(x)$ は級数 $a_n$ の母関数であるといいます(「級数を生み出す関数」という意味です)。たとえば、前の $2$ つの項を足して次の項をつくるフィボナッチ数列
 \[1,\ 1,\ 2,\ 3,\ 5,\ 8,\ 13,\ 21,\ 34,\ \cdots\]
の母関数は
 \[p(x)=\frac{1}{1-x-x^2}\]
で与えられることが知られています。$p(x)$ を sympy.series() で展開して確認してみましょう。

# In[6]

# フィボナッチ数列の母関数
p = 1/(1 - x - x**2)

# フィボナッチ数列の母関数を級数展開
f = series(p, x, n=10)

display(f)
\[1 + x + 2 x^{2} + 3 x^{3} + 5 x^{4} + 8 x^{5} + 13 x^{6} + 21 x^{7} + 34 x^{8} + 55 x^{9} + O\left(x^{10}\right)\]

係数は確かにフィボナッチ数列となっていることがわかります。

# In[7]

# fを多項式オブジェクトに変換
g = poly(f)

# フィボナッチ級数のすべての係数を取得
c = g.coeffs()
c.reverse()

display(c)
\[\left [ 1, \quad 1, \quad 1, \quad 2, \quad 3, \quad 5,\quad 8, \quad 13, \quad 21, \quad 34, \quad 55\right ]\]

コメント

  1. tiida より:

    お尋ねしますが,
    オーダーの記号の設定をすることは可能でしょうか?
    例えば,上記であれば,
    sin xのx=1のまわりのテイラー展開で最後の項が
    O((x-1)^6;x→1)
    となっていますが,これを
    O((x-1)^5)
    等に変更できるのでしょうか?できればOも\mathcal{O}ではなく小文字のoに変更できればなおよいのですが.

    • BlogCat より:

      sympy.sereis() はオプション引数 n で展開打ち切り次数を設定できます。
      デフォルトで n=6 に設定されていますが、たとえば
      series(sin(x), x, x0=1, n=5)
      とすれば、最後の項が O((x-1)^5) となります。
      O を小文字にする方法はわかりません。申し訳ないです。