背景
先日、とあるPythonのライブラリを見ていたところ、von Bertalanffy式についての記述でしばし悩んだので備忘録がてら書き残しておきます。
前提
von Bertalanffy式 (VBGF)とは主に生物(特に魚類など)の成長をモデル化するために用いられる式で、以下のような形をしています。
L(a) = L_\infty - (L_\infty - L_0)e^{-ka}
この式は生物のエネルギー収支に関する仮定を元に導出することができ、
- $ L(a) $はとある齢$ a $における体長
- $ L_0 $は$ a = 0$における体長
- $ L_\infty $は齢$ a $ が$ a \rightarrow 0 $のとき、体長が漸近する値
- $ k $はgrowth coefficientといい、成長率そのものを表すパラメータではないのですが、ざっくりと、生物がどれくらい急激に大きくなるかを制御するためのパラメータです。
参考
問題の式
問題の式は、ある年齢$ a $における体長$ L(a) $を表すvon Bertalanffy式を用いて、タイムステップdt
ごとにイテレーションを回す中で、次のタイムステップにおける体長を逐次的に求めるコードの中に現れました。
def von_bertalanffy_01(Length, l_inf, dt):
Length = Length + (l_inf - Length) * k * dt
Length
を、$L_\infty$、$k$、およびタイムステップ幅dt
を用いて更新しているのですが、一見上記の定義の式とは異なる形をしています。特に微分をした形跡もないのに$e$の肩に乗っていた$k$が降りてきてるあたりでちょっと戸惑いました。
そもそも、時刻t
における年齢$ a $がわかっているのであれば、わざわざ現在の体長を使って逐次的に計算しなくても上記のvon Bertalanffy式をそのまま突っ込んで、
def von_bertalanffy_02(a, l_inf, l_0, k):
Length = l_inf - (l_inf - l_0) * exp(-k * a)
return Length
とでもすれば良さそうです。
この式の理解にしばし悩んでしまったため、備忘録がわりに導出をメモすることを決めました。
導出
最初のvon Bertalanffy式の定義式を$ L_0$ について解いて、
L_0 = e^{ka} L(a) - e^{ka} L_\infty + L_\infty
次に、年齢$a$から$\Delta t$だけ進んだ時刻における体長を$L(a+\Delta t)$として、差分を取って整理すると
L(a+\Delta t) - L(a) = e^{-ka}(L_\infty - L0)(1-e^{-k \Delta t})
ここに$L_0$について解いたものを代入すると、
\displaylines{
\ L(a+\Delta t) - L(a) = e^{-ka}(L_\infty - e^{ka} L(a) + e^{ka} L_\infty - L_\infty)(1-e^{-k \Delta t}) \\
\therefore L(a+\Delta t) = L(a) + (L_\infty - L(a))(1-e^{-k \Delta t}) \\
}
を得ます。式から$e^{-ka}$が消えているので、明示的に年齢を与える必要はすでになくなっているのですが、ここで関数$f(x) = 1 - e^{x}$について、$x \rightarrow 0$のとき$f(x) \approx x$であることを用いると、$1-e^{-k \Delta t} \approx k \Delta t$と書けることから、
L(a + \Delta t) = L(a) + (L_\infty - L_(a))k \Delta t
を得ます。この式の$L(a)$は実際には$a$が不明の場合でもとにかく計測するなり仮定するなりすれば与えることが可能なので、年齢を明示的に与える必要がなくなっています。
実際に、von Bertalanffy式のパラメータ(とくに$k$)が年齢$a$について推定されている場合、タイムステップ$\Delta t$が1年よりも十分に小さなスケールであれば(例えば1時間後、あるいは1日後)上記の式は成り立つため、それくらいの時間幅で逐次的に計算する分には、ある程度はこのくらいの近似でも問題なさそうです。
おわりに
━━という理由で、私の出会ったコードはそういう形になっていたのかな、と想像したことのメモでした。どれくらいいい近似になっているかなどは確かめていないので、実際に使われる際はご自身の責任でお使いください。