checked の設計

このページでは、双対数上のどの演算がチェック付きの形式を持つか、それらのエラーが微分規則からどのように生じるか、そしてファサードが arithmetic のエラーモデルを再利用する理由を説明します。

設計目標

微分されるコードが、スカラーの Luna Flow コードと同じエラー型を使って不正な演算を値として報告できるようにし、チェック付き演算が有効な値と無効な導関数を同時に返すことがないようにします。

数学的背景

導関数が失敗する場所

チェック付き演算は、f(a+bε)=f(a)+f′(a) b εf(a + b\varepsilon) = f(a) + f'(a)\,b\,\varepsilon のいずれかの成分が定義されない場合に失敗しなければなりません。2 つのチェック付き演算について:

a+bεc+dε=ac+bc−adc2 εneeds c≠0,a+bε=a+b2a εneeds a>0.\begin{aligned} \frac{a + b\varepsilon}{c + d\varepsilon} &= \frac{a}{c} + \frac{bc - ad}{c^2}\,\varepsilon &&\text{needs } c \ne 0, \\ \sqrt{a + b\varepsilon} &= \sqrt a + \frac{b}{2\sqrt a}\,\varepsilon &&\text{needs } a > 0 . \end{aligned}

厳密な算術では c2≠0  ⟺  c≠0c^2 \ne 0 \iff c \ne 0 なので、商は値が失敗するところでちょうど失敗します。平方根は事情が異なります。a\sqrt a は a=0a = 0 で存在しますが、⋅\sqrt{\cdot} はそこで微分可能ではありません(差分商 h/h=h−1/2\sqrt h / h = h^{-1/2} が有界でない)。そのため双対数演算の定義域は開半直線 a>0a > 0 となり、スカラーの平方根の定義域 a≥0a \ge 0 より小さくなります。

浮動小数点数での定義域

Double では、0 でない cc に対しても c2c^2 が 0 になることがあります。∣c∣<2−537|c| < 2^{-537} では(最近接丸め、漸進的アンダーフローのもとで)a/ca/c が有限であっても c2c^2 はアンダーフローして 00 になります。このときチェック付きの商は接成分からのゼロ除算を報告します。このような入力はスケーリングし直すほうがよいでしょう。dual の設計 はアンダーフローが起きないことを仮定しています。

設計上の判断

両成分をチェックする

問題。 チェック付きのスカラー演算は、導関数が存在しない場合でも成功することがあります。

選択。 チェック付きの各双対数演算は、値にはチェック付きのスカラー演算を、接成分の除算には div_checked を呼び出し、最初のエラーを返します。これにより、上で導いたように双対数での定義域は ff と f′f' の定義域の共通部分になります。特に sqrt_checked は 00 で失敗します。

接成分が 0 の場合を特別扱いしない

a=0a = 0 かつ b=0b = 0 のとき、接成分は不定形 0/00/0 です。00 を返すこともできます(定数入力には報告すべき導関数がない)が、そうすると結果が定数の作られ方に依存してしまいます。実装は T に判断を委ね、Double ではこれは定義域エラーになります。

arithmetic を再利用する

Dual[T] は arithmetic の DivChecked と SqrtChecked を実装し、このファサードはまさにそれらのトレイトを ArithmeticContext、ArithmeticError、ArithmeticErrorKind、RoundingMode とともに再エクスポートします。そのため、ジェネリックなチェック付きコードは手を加えることなく Double 上でも Dual[Double] 上でも動作し、両方のレベルのエラーは 1 つの型になります。

除算と平方根のみ

arithmetic は除算、平方根、比較、パース、整数べきに対するチェック付きトレイトを定義しています。このうち、このリポジトリで微分規則を持つ T[ε]T[\varepsilon] 上の演算は除算と平方根だけなので、チェック付きの双対数形式を持つのもこの 2 つだけです。対数関数と三角関数は T のチェックなしの意味論に従います。

正しさと不変条件

  • div_checked(x, y) は、T の div_checked が a/ca/c と (bc−ad)/c2(bc - ad)/c^2 の両方で成功するときにちょうど成功します。そのとき結果は、同じ演算で計算した x / y に等しくなります。
  • sqrt_checked(x) は、T の sqrt_checked(a) と div_checked(b, 2√a) が成功するときにちょうど成功します。Double ではそれは a>0a > 0、または aa が NaN の場合です。
  • コンテキストはそのまま T に渡され、変更されることはありません。

却下した代替案

  • autodiff 専用のエラー型。 ArithmeticError と重複し、あらゆる境界で変換が必要になります。
  • Option による結果。 失敗の理由が失われます。
  • 値だけをチェックする。 「チェック付き」演算から無限大や NaN の導関数が返ることになります。

境界

  • チェック付きの対数・指数・三角関数の演算はありません。
  • コンテキスト付き(ArithmeticOutcome)の演算や丸めの診断はありません。
  • 非常に小さい除数の自動的なスケーリングは行いません。