前回の記事が適当すぎたので仕切り直しを。
「値と微分係数を同時に計算する型」AutoDiff
型は,R×Rに適当な演算を入れたものと考えられる。微分を考える変数を x,微分を計算したい点を t とするとき,第一成分を「x=t における値」,第二成分を「x=t における微分係数」と考える。AutoDiff
型の値を y=(y0,y1) とすると,y はある関数 f について y=(f(t),f′(t)) となっている。h(x)=g(f(x)) という関数があったとき,すでに得られている f(t),f′(t) の値を使って h(t),h′(t) を計算したいとする。合成関数の微分はh′(x)=g′(f(x))f′(x)で与えられるので、ここに x=t を代入すればh′(t)=g′(f(t))f′(t)=g′(y0)y1となる。h(t) はもちろん h(t)=g(y0) で与えられる。
今度は k(x)=g(l(x)) という関数を考えてみよう。x=t における l の値と l′ の値はすでに計算されているとして、これを z=(z0,z1)=(l(t),l′(t)) とおく。このとき,先ほどと同じように k(t)=g(z0),k′(t)=g′(z0)z1 がわかる。
このようにして,g という関数は、AutoDiff
型からAutoDiff
型への関数を定める。この関数を g∗ とすると,AutoDiff
型の値 (y0,y1) を与えた時の g∗ の値はg∗(y0,y1)=(g(y0),g′(y0)y1)となる。AutoDiff
型が「これまで計算した関数の値と微分係数」を表す型だとすれば,g∗ という関数は「これまで計算した関数に g という関数を合成した時の、関数の値と微分係数」を表す型である。
上の説明では g と g∗ を区別して書いたが、実際のプログラミングでは関数や演算子のオーバーロード、あるいは型クラスを使って、g∗ に相当する関数も同じ演算子・関数名で書けるようにするのが普通である。
いくつかの演算について、AutoDiff
型を R×R とみなしたときの計算方法を与えておく。(x0,x1)±(y0,y1)=(x0±y0,x1±y1)(x0,x1)⋅(y0,y1)=(x0y0,x1y0+x0y1)(x0,x1)/(y0,y1)=(x0/y0,(x1y0−x0y1)/y20),g:R→R(微分可能) に対し、g∗((x0,x1))=(g(x0),g′(x0)x1),g:R×R→R(微分可能) に対し、g∗((x0,x1),(y0,y1))=(g(x0,y0),gx(x0,y0)x1+gy(x0,y0)y1),となる。
文章書くのだるい。気が向いたら続く。