最近は、AIによる愚にも付かないPRが氾濫して、コントリビュートとするモチベーションがなくなっていたのだが、先輩と会話したのをきっかけに、再度やる気を出してみた。
やったこと
注意
この変更は、SymPy 1.15 以降に適用される予定です。
内容
SymPyでは、sin(x).diff(x)のように書くと、$\sin(x)$を微分して$\cos(x)$にしてくれる。2階以上の微分を行いたいときは、sin(x).diff((x, n))のように書く。sin(x).diff(x, n)だと別の意味になるから注意が必要だ。
どういう実装になっているかというと、
というように、関数クラスにfdiffメソッドを実装して、ここに微分するとどうなるかを記述する。n階微分を行う場合は、ざっくりこれをn回繰り返しているだけ。
よく知られているように、$\sin$などは微分し続けると周期的になる。これをn回繰り返すのは馬鹿らしいし、nが記号の場合、sin(x).diff((x, n))を実行しても、
$$
\frac{d^n}{dx^n}\sin(x)
$$
となっていい感じに処理してくれない。一応、Basic._eval_derivative_n_timesというメソッドがあって、これをオーバーライドすることでn階微分を各関数で実装できるのだが、やっていない。ということで、実装したというのが、今回のPR。
例えば、$\sin(x)$なら、
$$
\frac{d^n}{dx^n}\sin(x) = \sin\left(x + \frac{\pi n}{2}\right)
$$
なので、
というメソッドを、sinクラスに追加した。これで、sin(x).diff((x, n))はsin(x + pi*n/2)と評価される。ただし、nは非負整数という条件付きだ。なので、n = symbols('n')というように宣言したnでは展開されないが、n = symbols('n', integer=True, nonnegative=True)というように宣言したnでは展開される。
これをsinの他にcos, sinh, cosh, logにも同様のメソッドを実装した。