Python
sympy
数学

SymPyにおいて関数を関数で置き換えて(≠代入)三角関数の加法定理を証明しよう

More than 1 year has passed since last update.

subs と replace

SymPyの subsreplace は代入と置き換えという似て非なる関数です.

from sympy import symbols, sin, cos, exp, I, sqrt, expand, init_printing
init_printing()
x = symbols('x')
f =  sin(x)+sin(x**2)

次の例は sin(x)cos(x) を代入します.

f.subs(sin(x), cos(x))

$$\sin{\left (x^{2} \right )} + \cos{\left (x \right )}$$

当たり前ですが,この場合,sin(x**2)cos(x**2) に置き換わりません.
これは意図した仕様なのかは知りませんが,.subs(sin, cos)sincos に置き換えられます.

f.subs(sin, cos)

$$\cos{\left (x \right )} + \cos{\left (x^{2} \right )}$$

しかし,.subs(sin, sqrt) では sinsqrt に置き換えられません.

f.subs(sin, sqrt)

$$\sin{\left (x \right )} + \sin{\left (x^{2} \right )}$$

よくは分かりませんが,sympy.core.function.FunctionClass 同士だったら置き換えられる気がします.

for func in [sin, cos, sqrt]:
    print(func.__class__)
<class 'sympy.core.function.FunctionClass'>
<class 'sympy.core.function.FunctionClass'>
<class 'function'>

本来,関数を関数に置き換えるには replace が本来の用法だと思います.

f.replace(sin, cos)

$$\cos{\left (x \right )} + \cos{\left (x^{2} \right )}$$

f.replace(sin, sqrt)

$$\sqrt{x} + \sqrt{x^{2}}$$

replace の引数には,自作の関数やlambda式でもOK.

f.replace(sin, lambda t: cos(t**2)) # sin(□) を cos(□**2) に置き換える

$$\cos{\left (x^{2} \right )} + \cos{\left (x^{4} \right )}$$

オイラーの公式から

オイラーの公式
$$
e^{\theta i} = \cos\theta + i\sin\theta\tag{1}
$$
において,$\theta$ を $-\theta$ に置き換えると,$\cos(-\theta) = \cos(\theta),\ \sin(-\theta) = -\sin\theta$ より
$$
e^{-\theta i} = \cos\theta - i\sin\theta\tag{2}
$$
です.したがって,$(1)+(2)$ より
$$
e^{\theta i} + e^{-\theta i} = 2\cos\theta\ \Longleftrightarrow\ \cos\theta = \frac{e^{\theta i} + e^{-\theta i}}{2}
$$
$(1)-(2)$ より
$$
e^{\theta i} - e^{-\theta i} = 2i\sin\theta\ \Longleftrightarrow\ \sin\theta = \frac{e^{\theta i} - e^{-\theta i}}{2i}
$$
が成り立ちます.すなわち,よく知られていることですが,$\cos$ や $\sin$ は指数関数で表すことができるのです.

cos2exp = lambda t: (exp(t*I) + exp(-t*I))/2
sin2exp = lambda t: (exp(t*I) - exp(-t*I))/(2*I)
(sin(x)+cos(x)).replace(cos, cos2exp).replace(sin, sin2exp)

$$- \frac{i}{2} \left(e^{i x} - e^{- i x}\right) + \frac{e^{i x}}{2} + \frac{1}{2} e^{- i x}$$

これを利用すれば,三角関数の種々の公式を証明(確認)できます.

alpha, beta = symbols(r'\alpha \beta')
A = sin(alpha+beta)
B = sin(alpha)*cos(beta) + cos(alpha)*sin(beta)
expand(A.replace(sin, sin2exp).replace(cos, cos2exp))

$$- \frac{i}{2} e^{i \alpha} e^{i \beta} + \frac{i}{2} e^{- i \alpha} e^{- i \beta}$$

expand(B.replace(sin, sin2exp).replace(cos, cos2exp))

$$- \frac{i}{2} e^{i \alpha} e^{i \beta} + \frac{i}{2} e^{- i \alpha} e^{- i \beta}$$

これで,A=B すなわち
$$
\sin(\alpha+\beta) = \sin\alpha\cos\beta + \cos\alpha\sin\beta
$$
が確認できました.