container/adapters チュートリアル

このチュートリアルでは、リポジトリの各型に適した既製の辞書を選び、@mutable.Matrix の動的なビューも含めて container のアルゴリズムで使う方法を示します。自作の型の辞書を書きたい場合は、代わりに container のチュートリアル を読んでください。

クイックスタート

moon add Luna-Flow/linear-algebra@0.5.0
///|
import {
  "Luna-Flow/linear-algebra/container",
  "Luna-Flow/linear-algebra/container/adapters" @container_adapters,
  "Luna-Flow/linear-algebra/immut",
  "Luna-Flow/linear-algebra/mutable",
}

ファクトリの名前から、型と能力がわかります。

///|
test "read one entry through an adapter" {
  let v = @immut.Vector::from_array([10, 20, 30])
  let ops = @container_adapters.immutable_vector_read_ops()
  inspect((ops.length)(v), content="3")
  inspect((ops.get)(v, 2).unwrap(), content="30")
}

日常的なタスク

行列から行をコピーして取り出す

行ビューはベクトルのソースなので、どのベクトルのターゲットでも受け取れます。

///|
test "copy a row view into an immutable vector" {
  let m = @mutable.Matrix::from_2d_array([[1, 2, 3], [4, 5, 6]])
  let row : @immut.Vector[Int] = @container.vector_convert(
    m.row_view(1),
    @container_adapters.mutable_row_view_read_ops(),
    @container_adapters.immutable_vector_build_ops(),
  ).unwrap()
  m.set(1, 0, 40)
  inspect(row, content="|4, 5, 6|")
}

転置ビューを実体化する

@mutable.Matrix の転置ビューは行列のソースなので、matrix_convert で任意の表現に実体化できます。

///|
test "materialize a transpose view" {
  let m = @mutable.Matrix::from_2d_array([[1, 2, 3], [4, 5, 6]])
  let t : @immut.Matrix[Int] = @container.matrix_convert(
    m.to_transpose(),
    @container_adapters.mutable_transpose_read_ops(),
    @container_adapters.immutable_matrix_build_ops(),
  ).unwrap()
  inspect(t, content="|1, 4|\n|2, 5|\n|3, 6|")
}

列ビューを通じて書き込む

///|
test "clear a column through its view" {
  let m = @mutable.Matrix::from_2d_array([[1, 2], [3, 4], [5, 6]])
  let col = m.col_view(0)
  let edit = @container_adapters.mutable_col_view_mutable_edit_ops()
  for i in 0..<col.length() {
    (edit.set)(col, i, 0).unwrap()
  }
  inspect(m, content="|0, 2|\n|0, 4|\n|0, 6|")
}

既定のバックエンドのラッパー間で移す

///|
test "mutable dense wrapper to immutable dense wrapper" {
  let source = @default.DenseVector::from_array([1.5, 2.5])
  let target : @default.ImmutableDenseVector[Double] = @container.vector_convert(
    source,
    @container_adapters.dense_vector_read_ops(),
    @container_adapters.immutable_dense_vector_build_ops(),
  ).unwrap()
  inspect(target[1], content="2.5")
}

さらに進んで

編集形式の選び方。 値の意味論を持つ型(@immut、Immutable* ラッパー)には *_persistent_edit_ops だけが、インプレースの意味論を持つ型(@mutable、ビュー、DenseVector、DenseMatrix)には *_mutable_edit_ops だけがあります。編集を行う汎用コードは、想定する所有モデルに合ったレコードを受け取るべきです。

ターゲットとしてのビュー。 ビューには構築辞書がありません。既存の行列の行を別のベクトルから埋めるには、ソースを読み取り、ループで mutable_row_view_mutable_edit_ops を通じて書き込んでください。

よくある落とし穴

  • 変換結果がつながったままだと期待する。 ビューを変換するとコピーされます。行の例が示すように、その後の行列への書き込みはコピーには届きません。
  • 既定のラッパーに immutable_* を使う。 immutable_matrix_* は @immut.Matrix を適応するものです。ラッパー @default.ImmutableDenseMatrix には専用の immutable_dense_matrix_* ファクトリがあります。

次のステップ