poly API

poly パッケージは、Luna-Flow/luna-poly の多項式を Dual[T] 上で評価することで、ある点での微分を行います。密な 1 変数多項式と、1 変数の疎な多項式を扱います。手法は poly の設計 で説明しています。

ソース:src/poly/poly.mbt。

インポート

import {
  "Luna-Flow/autodiff/poly",
  "Luna-Flow/luna-poly/immut/dense",
  "Luna-Flow/luna-poly/immut/sparse",
}

例では、このパッケージに @poly を、luna-poly のパッケージに @dense と @sparse を使います。@poly.DensePolynomial と @poly.SparsePolynomial は @dense.DensePolynomial と @sparse.SparsePolynomial と同じ型です。

すべての関数は T : Eq + Semiring を必要とします。Semiring は算術のため、Eq は luna-poly が持ち上げた多項式を構築する際に係数を正規化するためです。NatHomomorphism や除算は不要なので、整数係数の多項式でも動作します。

密な多項式

eval_dual

密な多項式を双対数の入力で評価します。

pub fn[T : Eq + @luna-generic.Semiring] eval_dual(@dense.DensePolynomial[T], @dual.Dual[T]) -> @dual.Dual[T]

x=a+bεx = a + b\varepsilon に対して、結果は p(a)+p′(a) b εp(a) + p'(a)\,b\,\varepsilon です。係数は Dual::constant で持ち上げられ、持ち上げた多項式は DensePolynomial::eval(ホーナー法)で評価されます。コスト:O(deg⁡p)O(\deg p) 回の双対数演算と、持ち上げた係数の配列 1 つ。より大きな微分対象の計算の中に多項式を組み込むときに使います。たとえば eval_dual(p, x.sin()) のようにします。

dense_value_and_derivative_at

(p(x),p′(x))(p(x), p'(x)) を返します。

pub fn[T : Eq + @luna-generic.Semiring] dense_value_and_derivative_at(@dense.DensePolynomial[T], T) -> (T, T)

eval_dual(p, Dual::variable(x)) を成分に分けたものです。

dense_derivative_at

p′(x)p'(x) を返します。

pub fn[T : Eq + @luna-generic.Semiring] dense_derivative_at(@dense.DensePolynomial[T], T) -> T
test "dense polynomial derivative" {
  // p(x) = 1 + 2x + x^3
  let p = @dense.DensePolynomial::from_coefficients([1.0, 2.0, 0.0, 1.0])
  assert_eq(@poly.dense_value_and_derivative_at(p, 3.0), (34.0, 29.0))
  assert_eq(@poly.dense_derivative_at(p, 3.0), 29.0)
  let y = @poly.eval_dual(p, @autodiff.Dual::new(3.0, 4.0))
  assert_eq(y, @autodiff.Dual::new(34.0, 116.0)) // p'(3) * 4
}

1 変数の疎な多項式

これらの関数は SparsePolynomial を第 1 変数の多項式として扱います。すなわち単一の代入 [x] で評価します。

sparse_univariate_eval_dual

1 変数の疎な多項式を双対数の入力で評価します。

pub fn[T : Eq + @luna-generic.Semiring] sparse_univariate_eval_dual(@sparse.SparsePolynomial[T], @dual.Dual[T]) -> @dual.Dual[T]

結果は p(a)+p′(a) b εp(a) + p'(a)\,b\,\varepsilon です。係数は Dual::constant で持ち上げられ、各項 c xec\,x^e は二分累乗法で評価されます。そのためコストは O(∑termslog⁡e)O(\sum_{\text{terms}} \log e) 回の双対数演算で、欠けている次数にはコストがかかりません。

sparse_univariate_value_and_derivative_at

1 変数の疎な多項式について (p(x),p′(x))(p(x), p'(x)) を返します。

pub fn[T : Eq + @luna-generic.Semiring] sparse_univariate_value_and_derivative_at(@sparse.SparsePolynomial[T], T) -> (T, T)

sparse_univariate_derivative_at

1 変数の疎な多項式について p′(x)p'(x) を返します。

pub fn[T : Eq + @luna-generic.Semiring] sparse_univariate_derivative_at(@sparse.SparsePolynomial[T], T) -> T
test "sparse polynomial derivative" {
  // p(x) = 4 - x + 2x^3
  let p = @sparse.SparsePolynomial::from_array([
    ([3U], 2.0),
    ([1U], -1.0),
    ([0U], 4.0),
  ])
  assert_eq(@poly.sparse_univariate_value_and_derivative_at(p, 2.0), (18.0, 23.0))
  assert_eq(@poly.sparse_univariate_derivative_at(p, 2.0), 23.0)
}

互換用の名前

以前のリリースではより短い名前を使っていました。これらは引き続き利用でき、非推奨ではなく、上記の関数を呼び出します。

名前同等の関数
value_and_derivative_atdense_value_and_derivative_at
derivative_atdense_derivative_at
eval_sparse_dualsparse_univariate_eval_dual
sparse_value_and_derivative_atsparse_univariate_value_and_derivative_at
sparse_derivative_atsparse_univariate_derivative_at

value_and_derivative_at

pub fn[T : Eq + @luna-generic.Semiring] value_and_derivative_at(@dense.DensePolynomial[T], T) -> (T, T)

derivative_at

pub fn[T : Eq + @luna-generic.Semiring] derivative_at(@dense.DensePolynomial[T], T) -> T

eval_sparse_dual

pub fn[T : Eq + @luna-generic.Semiring] eval_sparse_dual(@sparse.SparsePolynomial[T], @dual.Dual[T]) -> @dual.Dual[T]

sparse_value_and_derivative_at

pub fn[T : Eq + @luna-generic.Semiring] sparse_value_and_derivative_at(@sparse.SparsePolynomial[T], T) -> (T, T)

sparse_derivative_at

pub fn[T : Eq + @luna-generic.Semiring] sparse_derivative_at(@sparse.SparsePolynomial[T], T) -> T

新しいコードでは長い名前を使うことを推奨します。どの表現とどの種類の微分を意味するかが明確になるためです。

再エクスポートされる型

DensePolynomial

pub using @dense {type DensePolynomial}

SparsePolynomial

pub using @sparse {type SparsePolynomial}

Dual

pub using @dual {type Dual}