subs と replace
SymPyの subs
と replace
は代入と置き換えという似て非なる関数です.
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)
で sin
を cos
に置き換えられます.
f.subs(sin, cos)
$$\cos{\left (x \right )} + \cos{\left (x^{2} \right )}$$
しかし,.subs(sin, sqrt)
では sin
を sqrt
に置き換えられません.
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
$$
が確認できました.