回答編集履歴

1 誤記

KSwordOfHaste

KSwordOfHaste score 18148

2019/01/07 12:13  投稿

根本的なところからコメントを試みます。
計算機における微分には概ね2つのアプローチがあります。
- (1) 数値微分
任意のf(x)に対してxがある値X0のとき、f(X0)とf(X0+delta)を求めその傾きの近似値
(f(X0 + delta) - f(X0))/delta
により数値計算的に求める手法です。例えばf(x)=x**2のとき、x=1における微分をdelta=1E3ぐらいにとって計算すると2.0009999999996975ぐらいの値が求まります。正確な値には遠いですがf(x)がどのような複雑な式であってもこういう具体値を簡単に求められるのが利点です。
- (2) 代数的な微分
f(x) = x**2
のような代数式を代数式のまま微分する手法です。ご存じのとおり
f(x)/dx = 2 * x
になりますが、これと同様のことを計算で求めるのですね。得られた結果 2 * x という式そのものに任意のxを与えると具体的な微分値がわかります。例えばx=1を代入すれば結果は2となり、(1)の数値微分と比べて「代数的な微分式が求まりさえすれば」より正確な値を求めることができます。微分値の具体的な値を求めるのではなく代数的な微分結果を求めること自体が目的のこともあるでしょう。
さて、ご質問の課題(?)は(2)の方にあたります。Expressionのdiffの定義をよくごらんください。
> '''式を変数 x で微分した式に対応する Expression オブジェクト を返すメソッド'''
これが「代数式を微分してそれを代数式として返すのがExpressionの機能(目的)」という点を質問者さんは充分把握できていなかったようです。
質問者さんはこのメソッドの仕様を表す文章が「代数式を微分してそれを代数式として返すのがExpressionの機能(目的)」であることを充分把握できていなかったようです。
Xの定義の前に四則演算(Add, Sub, Mul, Div)のdiffの定義をどうすべきかもう一度よく考えなおしてください。例えばAddですが
```Python
class Add(BinalyExpression):
   ...
   def diff(self):
       return self.a.diff() + self.b.diff()
```
これでは目的を果たしていないことがおわかりでしょうか?この定義ではdiffの結果がPythonの数値であると仮定してしまってます。そうではなく元の式を微分した代数式を表すようなExpressionを返さなければなりません。つまり本来diffメソッドは次のようになっているべきです。
```Python
class Add(BinalyExpression):
   ...
   def diff(self):
       return Add(self.a.diff(), self.b.diff())
```
また上記は
f(x) = f1(x) + f2(x)
のときの微分の公式
f'(x) = f1'(x) + f2'(x)
に基づいているという点に注意してください。質問者さんのMul, Divのdiffメソッドの定義は微分の定義そのものからかけ離れています。例えば乗算の微分は
f(x) = f1(x) * f2(x)
のときの公式
f'(x) = f1(x) * f2'(x) + f1'(x) * f2(x)
に従ってません。
以上の点に注意し代数的な微分公式を適用して四則演算の全てを考えなおせば、自ずとXをどう定義すべきかがおわかりになると思います。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る