mutable/term チュートリアル
このチュートリアルでは、常にソート済みかつ正規形に保たれるミュータブルなコンテナの中で多変数多項式を項ごとに構築する方法と、代わりに多項式全体の演算を使うべき場面を示します。
クイックスタート
moon add Luna-Flow/luna-poly@0.2.0
import {
"Luna-Flow/luna-poly/mutable",
}
test "mutable term quick start" {
let p : @mutable.TermPolynomial[Int] = @mutable.TermPolynomial::zero()
p.add_term_inplace(@mutable.ExponentVector::from_array([1U, 1]), 3)
p.add_term_inplace(@mutable.ExponentVector::from_array([2U]), 1)
inspect(p, content="3 * xx_1 + 1 * x^2")
}
コンテナは挿入のたびにソートし直すので、常に先頭項から表示されます。
日常的なタスク
ループで項を集める
同じ指数ベクトルを持つ項はマージされ、打ち消し合う項は消えます。
test "collect" {
let p : @mutable.TermPolynomial[Int] = @mutable.TermPolynomial::zero()
for i in 0..<4 {
p.add_term_inplace(@mutable.ExponentVector::from_array([(i % 2).reinterpret_as_uint()]), 1)
}
inspect(p, content="2 * x + 2")
p.add_term_inplace(@mutable.ExponentVector::one(), -2)
inspect(p, content="2 * x")
}
インプレースで乗算・スケーリングする
test "multiply" {
let p = @mutable.TermPolynomial::from_array([([1U], 1), ([0U, 1], 1)])
p.mul_inplace(p)
inspect(p, content="1 * x_1^2 + 2 * xx_1 + 1 * x^2")
p.scale_inplace(@mutable.ExponentVector::from_array([0U, 0, 1]), -1)
inspect(p.total_degree().unwrap(), content="3")
}
構築しながら評価する
コンテナは常に正規形なので、問い合わせはいつでも行えます。
test "evaluate" {
let p = @mutable.TermPolynomial::from_array([([2U], 1)])
inspect(p.eval([3]), content="9")
p.add_term_inplace(@mutable.ExponentVector::from_array([0U, 1]), 10)
assert_true(p.eval_checked([3]) is None)
inspect(p.eval([3, 1]), content="19")
}
を含む項を加えた後は、多項式の評価に 2 つの値が必要になります。
さらに進む
大きな和
add_inplace は項を 1 つずつ挿入します。オペランドが大きい場合は、和を一度に構築してください。
test "large sums" {
let parts = Array::makei(50, i => @mutable.TermPolynomial::from_array([([i.reinterpret_as_uint()], 1)]))
let all_terms : Array[(@mutable.ExponentVector, Int)] = []
for part in parts {
for t in part.to_terms() {
all_terms.push(t)
}
}
let sum = @mutable.TermPolynomial::from_terms(all_terms)
inspect(sum.size(), content="50")
}
1 回の from_terms ですべての項を で正規化します。
イミュータブルなコードに引き渡す
test "freeze" {
let p = @mutable.TermPolynomial::from_array([([1U], 2)])
let frozen = p.to_immut()
p.clear()
inspect(frozen, content="2 * x")
assert_true(p.is_zero())
}
よくある落とし穴
add_inplaceのコスト。 オペランドが大きいとほぼ二次になります。上を参照してください。- 共有されるコンテナ。 代入は共有します。独立したコンテナには
copy()を使ってください。 - 順序。 イミュータブルな型と同様に、順序は次数付きで、同次数の場合は最も高い変数で比較します。
次のステップ
- mutable/term API と mutable/term の設計。
- 数学的な背景は immut/term チュートリアル、安価な単一項の更新は mutable/sparse。