mutable API

Luna-Flow/linear-algebra/mutable は実行指向の密な線形代数を提供します。Matrix[T] は要素を行優先の 1 本の Array[T] に格納してインプレースに更新でき、Vector[T] は Array[T] をラップし、RowView、ColView、Transpose は行列への動的なビューです。このストレージの上に、本パッケージはリポジトリの数値ルーチンを実装しています。LU 分解に基づく行列式・逆行列・階数(ランク)、Cholesky 分解、対称行列の固有値、べき乗法、行簡約、簡単な統計量です。

ソース: src/mutable。アルゴリズムとその数値的性質は mutable の設計 で導出しています。immut は同じ中核名を持つ値指向の対応パッケージです。

インポート

///|
import {
  "Luna-Flow/linear-algebra/mutable",
}

規約

  • 形状とストレージ。 行列は row() 行 col() 列を持ち、どちらも非負です。0×n0 \times n と n×0n \times 0 はどちらも有効で、互いに区別されます。要素 (i,j)(i, j) はオフセット i⋅col+ji \cdot \mathrm{col} + j に格納されます。
  • 変更。 Unit を返すメソッド(set、swap_rows、*_inplace、ビューへの書き込み)は行列をインプレースに変更し、その行列のすべてのビューとエイリアスに変更が見えます。それ以外のメソッドは新しい値を返し、引数を変更しません。例外は reduce_row_elimination で、インプレースに処理してレシーバー自身を返します。
  • エイリアスを作るコンストラクタ。 Matrix::from_array と Vector::from_array は渡された配列をコピーせずにそのまま採用します。from_2d_array、copy、および配列へのすべての変換はコピーします。
  • 範囲。 すべての公開アクセサは行と列を別々に検査し、範囲外のインデックスでは中断します。これはイテレータ、ビュー、転置ビューにも当てはまります。
  • 検査付きと検査なし。 実行時に失敗しうる操作は Result[_, LinearAlgebraError] を返し、中断する(unchecked_inverse の場合は Option を返す)unchecked_* 版を対として持ちます。エラーの設計 を参照してください。
  • 数値ルーチン は T : Compare + Field + Num + Tolerance を要求します(平方根を取るものはさらに Sqrt も)。Tolerance は Double と Float にしか実装されていないため、これらのルーチンは浮動小数点行列向けです。
  • ターゲット。 カーネルは native、js、wasm、wasm-gc ごとに個別に調整されています。公開されている意味論はどのターゲットでも同じですが、カーネルの総和の順序が異なる場合、浮動小数点の結果が最下位ビットで異なることがあります。

型

Matrix

Matrix[T] は可変な密行列です。

type Matrix[T] derive(Eq)

この型は抽象型です。対応するメソッドの要素制約のもとで、Eq(形状と要素)、Show、Add、Sub、Neg、Mul(行列積)を実装しています。

Lens

Lens[T] は m[r] が返す行アクセサで、m[r][c] と m[r][c] = x を支えます。

type Lens[T]

Lens::at, Lens::set

Lens::at(l, c) はレンズが指す行の列 c を読み取り、Lens::set(l, c, x) は書き込みます。

#alias("_[_]")
pub fn[T] Lens::at(Self[T], Int) -> T
#alias("_[_]=_")
pub fn[T] Lens::set(Self[T], Int, T) -> Unit

Transpose から得たレンズは転置された行列を指します。範囲外の列では中断します。

RowView, ColView

RowView[T] と ColView[T] は、1 つの行または 1 つの列に対する動的なビューです。

pub struct RowView[T] {
  data : Matrix[T]
  row : Int
}
pub struct ColView[T] {
  data : Matrix[T]
  col : Int
}

フィールドは読み取り可能です。ビューを通じた書き込みは元の行列を変更します。

Transpose

Transpose[T] は行列の動的な転置ビューです。

pub struct Transpose[T](Matrix[T])

ラップした行列とストレージを共有します。そのメソッドは転置された行列を対象とし、ビューの要素 (i,j)(i, j) は行列の要素 (j,i)(j, i) です。

Vector

Vector[A] は可変な密ベクトルで、Array[A] のラッパーです。

pub struct Vector[A](Array[A])

配列は v.0 として読み取れます。Eq、Show(|a, b, c|)、Add、Mul(要素ごと)、Neg、Debug、および quickcheck の Arbitrary を実装しています。

Tolerance

Tolerance は数値ルーチンが使う絶対しきい値を提供します。

pub trait Tolerance {
  fn tolerance() -> Self
}
pub impl Tolerance for Float
pub impl Tolerance for Double

どちらのインスタンスも 10−1110^{-11} を返します。この trait はオープンではないため、他のパッケージはインスタンスを追加できません。しきい値をどこでどのように適用するかは mutable の設計 で説明しています。

Sqrt

Sqrt は Luna-Flow/arithmetic.Sqrt の再エクスポートで、cholesky_decomposition、eigen、is_positive_definite、frobenius_norm、std_dev で必要になります。

pub using @arithmetic {trait Sqrt}

構築

Matrix::make

Matrix::make(r, c, f) は要素が f(i,j)f(i, j) である r×cr \times c 行列を構築します。

pub fn[A] Matrix::make(Int, Int, (Int, Int) -> A) -> Self[A]

負の次元では中断します。f は純粋であるべきです。1 つの要素に対して呼び出される回数は規定されていません。

Matrix::new

Matrix::new(r, c, x) は x で埋めた r×cr \times c 行列を構築します。

pub fn[T] Matrix::new(Int, Int, T) -> Self[T]

Matrix::from_2d_array

Matrix::from_2d_array(rows) は入れ子の行を新しい行列にコピーします。

pub fn[T] Matrix::from_2d_array(Array[Array[T]]) -> Self[T]

[] は 0×00 \times 0 になります。行の長さが揃っていない場合は中断します。

Matrix::from_array

Matrix::from_array(r, c, data) は data を r×cr \times c 行列の行優先ストレージとして採用します。

pub fn[T] Matrix::from_array(Int, Int, Array[T]) -> Self[T]

負の次元、または data.length() != r * c の場合は中断します。配列はコピーされません。その後 data に書き込むと行列も変わり、その逆も同様です。

identity

identity(n) は n×nn \times n 単位行列を構築します。これはトップレベル関数 @mutable.identity(n) です。

pub fn[T : @luna-generic.Zero + @luna-generic.One] identity(Int) -> Matrix[T]

Matrix::copy

Matrix::copy(m) は独自のストレージを持つディープコピーを返します。

pub fn[T] Matrix::copy(Self[T]) -> Self[T]
///|
test "mutable construction and aliasing" {
  let data = [1, 2, 3, 4]
  let shared = @mutable.Matrix::from_array(2, 2, data)
  data[0] = 100
  inspect(shared.get(0, 0), content="100")
  let separate = shared.copy()
  shared.set(0, 0, 1)
  inspect(separate.get(0, 0), content="100")
  let id : @mutable.Matrix[Double] = @mutable.identity(2)
  inspect(id, content="|1, 0|\n|0, 1|")
  inspect(
    @mutable.Matrix::make(2, 3, (i, j) => i * 3 + j),
    content="|0, 1, 2|\n|3, 4, 5|",
  )
}

形状と要素へのアクセス

Matrix::row, Matrix::col, Matrix::shape

行数、列数、および (row, col)。

pub fn[T] Matrix::row(Self[T]) -> Int
pub fn[T] Matrix::col(Self[T]) -> Int
pub fn[T] Matrix::shape(Self[T]) -> (Int, Int)

Matrix::is_square

Matrix::is_square(m) は row() == col() を返します。

pub fn[T] Matrix::is_square(Self[T]) -> Bool

Matrix::get, Matrix::set

get(r, c) は要素 (r,c)(r, c) を読み取り、set(r, c, x) はそれをインプレースに書き込みます。

pub fn[T] Matrix::get(Self[T], Int, Int) -> T
pub fn[T] Matrix::set(Self[T], Int, Int, T) -> Unit

どちらも O(1)O(1) で、範囲外のインデックスでは中断します。個々の要素にアクセスする最も高速な方法です。

Matrix::at

Matrix::at(m, r) は行 r の Lens を返し、m[r][c] と m[r][c] = x を支えます。

#alias("_[_]")
pub fn[T] Matrix::at(Self[T], Int) -> Lens[T]

Matrix::row_view, Matrix::col_view

row_view(r) と col_view(c) は 1 つの行または列の動的なビューを返します。

pub fn[T] Matrix::row_view(Self[T], Int) -> RowView[T]
pub fn[T] Matrix::col_view(Self[T], Int) -> ColView[T]

インデックスはビューの作成時に検査されます。

Matrix::to_transpose

Matrix::to_transpose(m) は m とストレージを共有する動的な転置ビューを O(1)O(1) で返します。

pub fn[T] Matrix::to_transpose(Self[T]) -> Transpose[T]

Matrix::equal, Matrix::to_string

equal は形状と要素を比較し(== を支えます)、to_string は各行を |a, b| 形式の行として出力します。

pub fn[T : Eq] Matrix::equal(Self[T], Self[T]) -> Bool
pub fn[T : Show] Matrix::to_string(Self[T]) -> String
///|
test "mutable access" {
  let m = @mutable.Matrix::from_2d_array([[1, 2, 3], [4, 5, 6]])
  m[0][2] = 30
  m.set(1, 0, 40)
  inspect(m.get(0, 2), content="30")
  inspect(m[1][0], content="40")
  let r = m.row_view(1)
  r[2] = 60
  inspect(m, content="|1, 2, 30|\n|40, 5, 60|")
  debug_inspect(m.shape(), content="(2, 3)")
}

走査とインプレース変換

Matrix::each, Matrix::eachi

each(f) はすべての要素に対して行優先順に f を呼び出します。eachi(f) は行優先の平坦なインデックスも渡します。

pub fn[T] Matrix::each(Self[T], (T) -> Unit) -> Unit
pub fn[T] Matrix::eachi(Self[T], (Int, T) -> Unit) -> Unit

Matrix::each_row_col

each_row_col(f) はすべての要素について行優先順に f(i, j, a_ij) を呼び出します。

pub fn[T] Matrix::each_row_col(Self[T], (Int, Int, T) -> Unit) -> Unit

Matrix::each_row, Matrix::eachi_row, Matrix::each_col, Matrix::eachi_col

1 つの行(左から右)または 1 つの列(上から下)を走査します。eachi_* 形式は行または列の中での位置を渡します。

pub fn[T] Matrix::each_row(Self[T], Int, (T) -> Unit) -> Unit
pub fn[T] Matrix::eachi_row(Self[T], Int, (Int, T) -> Unit) -> Unit
pub fn[T] Matrix::each_col(Self[T], Int, (T) -> Unit) -> Unit
pub fn[T] Matrix::eachi_col(Self[T], Int, (Int, T) -> Unit) -> Unit

Matrix::iter, Matrix::iter_row, Matrix::iter_col

全要素(行優先)、1 つの行、または 1 つの列に対するイテレータです。

pub fn[T] Matrix::iter(Self[T]) -> Iter[T]
pub fn[T] Matrix::iter_row(Self[T], Int) -> Iter[T]
pub fn[T] Matrix::iter_col(Self[T], Int) -> Iter[T]

Matrix::map, Matrix::mapi

map(f) と mapi(f) はすべての要素に f を適用した新しい行列を返します。mapi は (i, j) も受け取ります。

pub fn[T, U] Matrix::map(Self[T], (T) -> U) -> Self[U]
pub fn[T, U] Matrix::mapi(Self[T], (Int, Int, T) -> U) -> Self[U]

Matrix::map_inplace, Matrix::map_row_inplace, Matrix::map_col_inplace

すべての要素、1 つの行のすべての要素、または 1 つの列のすべての要素を、インプレースで f(entry) に置き換えます。

#alias(map_in_place, deprecated)
pub fn[T] Matrix::map_inplace(Self[T], (T) -> T) -> Unit
#alias(map_row_in_place, deprecated)
pub fn[T] Matrix::map_row_inplace(Self[T], Int, (T) -> T) -> Unit
#alias(map_col_in_place, deprecated)
pub fn[T] Matrix::map_col_inplace(Self[T], Int, (T) -> T) -> Unit

Matrix::swap_rows, Matrix::swap_cols

2 つの行または 2 つの列をインプレースで交換します。

pub fn[T] Matrix::swap_rows(Self[T], Int, Int) -> Unit
pub fn[T] Matrix::swap_cols(Self[T], Int, Int) -> Unit

範囲外のインデックスでは中断します。同じインデックスを指定した場合、行列は変わりません。

///|
test "mutable traversal" {
  let m = @mutable.Matrix::from_2d_array([[1, 2], [3, 4]])
  let mut sum = 0
  m.each(x => sum = sum + x)
  inspect(sum, content="10")
  m.map_col_inplace(1, x => x * 10)
  m.swap_rows(0, 1)
  inspect(m, content="|3, 40|\n|1, 20|")
  debug_inspect(m.iter_col(0).to_array(), content="[3, 1]")
}

変換

Matrix::to_array, Matrix::to_2d_array, Matrix::to_vector

すべての要素を、行優先の平坦な配列、入れ子の行、または平坦な Vector にコピーします。

pub fn[T] Matrix::to_array(Self[T]) -> Array[T]
pub fn[T] Matrix::to_2d_array(Self[T]) -> Array[Array[T]]
pub fn[T] Matrix::to_vector(Self[T]) -> Vector[T]

Matrix::row_to_array, Matrix::col_to_array, Matrix::row_to_vector, Matrix::col_to_vector

1 つの行または列を配列または Vector にコピーします。

pub fn[T] Matrix::row_to_array(Self[T], Int) -> Array[T]
pub fn[T] Matrix::col_to_array(Self[T], Int) -> Array[T]
pub fn[T] Matrix::row_to_vector(Self[T], Int) -> Vector[T]
pub fn[T] Matrix::col_to_vector(Self[T], Int) -> Vector[T]

Matrix::transpose

Matrix::transpose(m) は実体化した新しい転置行列を返します。ビューを返す to_transpose と比較してください。

pub fn[T] Matrix::transpose(Self[T]) -> Self[T]

Matrix::horizontal_combine, Matrix::vertical_combine

ブロック連結 [A  B][A \; B] と [AB]\begin{bmatrix} A \\ B \end{bmatrix} です。行数(後者は列数)が異なる場合は中断します。

pub fn[T] Matrix::horizontal_combine(Self[T], Self[T]) -> Self[T]
pub fn[T] Matrix::vertical_combine(Self[T], Self[T]) -> Self[T]

算術

Matrix::add, Matrix::sub, Matrix::neg

要素ごとの A+BA + B、A−BA - B、−A-A です。演算子を支えており、形状が異なる場合は中断します。

pub fn[T : Add] Matrix::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] Matrix::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] Matrix::neg(Self[T]) -> Self[T]

Matrix::scale, Matrix::add_constant

すべての要素に右からスカラーを掛けるか、すべての要素にスカラーを加えます。

pub fn[T : Mul] Matrix::scale(Self[T], T) -> Self[T]
pub fn[T : Add] Matrix::add_constant(Self[T], T) -> Self[T]

Matrix::adjoint

Matrix::adjoint(m) は共役転置 A∗A^{*} を返します。Conjugate を持つスカラー型が必要です。

pub fn[T : @luna-generic.Conjugate] Matrix::adjoint(Self[T]) -> Self[T]

Matrix::null

Matrix::null(m) は、すべての要素が Zero::zero() と厳密に等しいときに true を返します。

pub fn[T : Compare + @luna-generic.Zero] Matrix::null(Self[T]) -> Bool

Matrix::mul

Matrix::mul(a, b) は a * b の背後にある行列積です。

pub fn[T : @luna-generic.AddMonoid + Mul] Matrix::mul(Self[T], Self[T]) -> Self[T]

cols⁡(A)=rows⁡(B)\operatorname{cols}(A) = \operatorname{rows}(B) を検査し、成り立たなければ Matrix::mul: dimension mismatch で中断し、成り立てば unchecked_matmul を呼び出します。このパッケージには Result を返す matmul はありません。先に形状を検査するか、@immut.Matrix::matmul を使ってください。

Matrix::unchecked_matmul

Matrix::unchecked_matmul(a, b) は 形状を検証せずに ABAB を返します。

pub fn[T : @luna-generic.AddMonoid + Mul] Matrix::unchecked_matmul(Self[T], Self[T]) -> Self[T]

コスト: rcnrcn 回の積和。大きな積(4×16×164 \times 16 \times 16 以上)では、乗算の前に BB の列を連続領域にパックします。

Matrix::mul_vec

Matrix::mul_vec(a, x) は、cols⁡(A)=len⁡(x)\operatorname{cols}(A) = \operatorname{len}(x) のとき Ok(Ax) を、そうでなければ DimensionMismatch を返します。

pub fn[T : @luna-generic.AddMonoid + Mul] Matrix::mul_vec(Self[T], Vector[T]) -> Result[Vector[T], @error.LinearAlgebraError]

Matrix::unchecked_mul_vec

Matrix::unchecked_mul_vec(a, x) は AxAx を返し、長さが一致しない場合は中断します。

pub fn[T : @luna-generic.AddMonoid + Mul] Matrix::unchecked_mul_vec(Self[T], Vector[T]) -> Vector[T]

Matrix::pow, Matrix::matrix_power

pow(k) は正方行列 AA と k≥0k \ge 0 に対して、二分累乗法により Ok(A^k) を返します(A0=IA^0 = I)。matrix_power は同じ関数の別名です。

pub fn[T : @luna-generic.Semiring] Matrix::pow(Self[T], Int) -> Result[Self[T], @error.LinearAlgebraError]
pub fn[T : @luna-generic.Semiring] Matrix::matrix_power(Self[T], Int) -> Result[Self[T], @error.LinearAlgebraError]

エラー: NonSquareMatrix(最初に検査)、次に NegativeExponent。

Matrix::unchecked_pow, Matrix::unchecked_matrix_power

pow と matrix_power の中断する形式です。

pub fn[T : @luna-generic.Semiring] Matrix::unchecked_pow(Self[T], Int) -> Self[T]
pub fn[T : @luna-generic.Semiring] Matrix::unchecked_matrix_power(Self[T], Int) -> Self[T]

Matrix::trace, Matrix::unchecked_trace

trace() は正方行列に対して Ok(Σ a_ii) を返し、それ以外では NonSquareMatrix を返します。unchecked_trace は代わりに中断します。

pub fn[T : @luna-generic.AddMonoid] Matrix::trace(Self[T]) -> Result[T, @error.LinearAlgebraError]
pub fn[T : @luna-generic.AddMonoid] Matrix::unchecked_trace(Self[T]) -> T
///|
test "mutable arithmetic" {
  let a = @mutable.Matrix::from_2d_array([[1.0, 2.0], [3.0, 4.0]])
  let x = @mutable.Vector::from_array([1.0, 1.0])
  inspect(a.mul_vec(x).unwrap(), content="|3, 7|")
  inspect(a * a, content="|7, 10|\n|15, 22|")
  inspect(a.pow(0).unwrap(), content="|1, 0|\n|0, 1|")
  inspect(a.trace().unwrap(), content="5")
  inspect(
    a.mul_vec(@mutable.Vector::from_array([1.0])) is Err(_),
    content="true",
  )
}

連立一次方程式と分解

この節のルーチンはすべて Float と Double の行列向けです。「このピボットはゼロである」といった判定は、絶対値を Tolerance::tolerance()(10−1110^{-11})と比較して行います。アルゴリズム、コスト、誤差限界については 設計ページ を参照してください。

Matrix::determinant

Matrix::determinant(a) は正方行列に対して Ok(det A) を、それ以外では NonSquareMatrix を返します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::determinant(Self[T]) -> Result[T, @error.LinearAlgebraError]

n≤4n \le 4 では閉じた余因子公式を使います。n≥5n \ge 5 では、行列が許容誤差の範囲で三角行列なら対角要素の積を、そうでなければ部分ピボット選択付き LU 分解を使い、行交換が ss 回のとき det⁡A=(−1)s∏iuii\det A = (-1)^{s} \prod_i u_{ii} とします。ピボットが許容誤差を下回った場合、結果は厳密にゼロです。0×00 \times 0 行列の det⁡\det は 11 です。

Matrix::unchecked_determinant

determinant の中断する形式です。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::unchecked_determinant(Self[T]) -> T

Matrix::inverse

Matrix::inverse(a) は Ok(A^{-1}) を返します。非正方行列では NonSquareMatrix を、ピボットが許容誤差を下回る場合は SingularMatrix を返します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::inverse(Self[T]) -> Result[Self[T], @error.LinearAlgebraError]

単位行列、対角行列、置換行列は判別されて直接反転されます(P−1=PTP^{-1} = P^{\mathsf T})。それ以外の行列は、部分ピボット選択付き LU 分解から列ごとに解きます。コストは ≈83n3\approx \tfrac{8}{3} n^3 flops です。0×00 \times 0 行列の逆行列は 0×00 \times 0 行列です。

Matrix::unchecked_inverse

Matrix::unchecked_inverse(a) は Some(A^{-1}) を、特異行列では None を返し、非正方行列では中断します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::unchecked_inverse(Self[T]) -> Self[T]?

Matrix::is_invertible, Matrix::unchecked_is_invertible

is_invertible() は、LU 分解で許容誤差を下回るピボットが見つからなければ Ok(true) を、見つかれば Ok(false) を、非正方行列では NonSquareMatrix を返します。unchecked_is_invertible は代わりに中断します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::is_invertible(Self[T]) -> Result[Bool, @error.LinearAlgebraError]
pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::unchecked_is_invertible(Self[T]) -> Bool

Matrix::rank

Matrix::rank(a) は、a のコピーに対して部分ピボット選択付き Gauss 消去を行い、見つかったピボットの数を返します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::rank(Self[T]) -> Int

残りの要素の最大値が許容誤差を下回る列はピボットに寄与しません。任意の形状で動作し、a は変更されません。コストは O(min⁡(r,c) rc)O(\min(r, c)\, r c) です。

Matrix::reduce_row_elimination

Matrix::reduce_row_elimination(a) は、部分ピボット選択付き Gauss–Jordan 消去によって a を インプレースで 被約行階段形に変換し、a 自身を返します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::reduce_row_elimination(Self[T]) -> Self[T]

ピボットは厳密に 1、ピボット列のそれ以外の要素は厳密に 0 となり、途中で絶対値が許容誤差以下の要素は 0 に設定されます。元の行列が必要な場合は先にコピーしてください。

Matrix::cholesky_decomposition

Matrix::cholesky_decomposition(a) は、LL が正の対角要素を持つ下三角行列で LLT=AL L^{\mathsf T} = A を満たす Some(L)、または None を返します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + @arithmetic.Sqrt + Tolerance] Matrix::cholesky_decomposition(Self[T]) -> Self[T]?

None は、a が正方でない、許容誤差の範囲で対称でない、または対角ピボット ajj−∑k<jljk2a_{jj} - \sum_{k<j} l_{jk}^2 が許容誤差以下である(行列が正定値でないか、ほぼ特異である)ことを意味します。コストは ≈n3/3\approx n^3/3 flops です。

Matrix::is_positive_definite

Matrix::is_positive_definite(a) は cholesky_decomposition が成功するかどうかを返します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + @arithmetic.Sqrt + Tolerance] Matrix::is_positive_definite(Self[T]) -> Bool

Matrix::is_symmetric

Matrix::is_symmetric(a) は、a が正方で、すべての i<ji < j について ∣aij−aji∣≤tol|a_{ij} - a_{ji}| \le \mathrm{tol} であるときに true を返します。

pub fn[T : Compare + @luna-generic.Num + Tolerance] Matrix::is_symmetric(Self[T]) -> Bool
///|
test "solving and factorizing" {
  let a = @mutable.Matrix::from_2d_array([[4.0, 2.0], [2.0, 3.0]])
  inspect(a.determinant().unwrap(), content="8")
  inspect(a.inverse().unwrap(), content="|0.375, -0.25|\n|-0.25, 0.5|")
  let l = a.cholesky_decomposition().unwrap()
  inspect(l, content="|2, 0|\n|1, 1.4142135623730951|")
  inspect(a.is_positive_definite(), content="true")
  let r = @mutable.Matrix::from_2d_array([
    [1.0, 2.0, 3.0],
    [2.0, 4.0, 6.0],
    [7.0, 8.0, 9.0],
  ])
  inspect(r.rank(), content="2")
  inspect(r.is_invertible().unwrap(), content="false")
}

固有値

Matrix::eigen

Matrix::eigen(a) は実対称行列の固有値と固有ベクトルを (values, vectors) として返します。vectors の列 kk は values[k] に対する固有ベクトルです。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + @arithmetic.Sqrt + Tolerance] Matrix::eigen(Self[T]) -> (Vector[T], Self[T])
  • a が正方でない場合、許容誤差の範囲で対称でない場合、またはある固有値が 60 回の反復以内に収束しない場合は中断します。
  • 2×22 \times 2 の入力では、固有値は特性多項式から λ1,2=m±m2−det⁡A\lambda_{1,2} = m \pm \sqrt{m^2 - \det A}(m=12tr⁡Am = \tfrac12 \operatorname{tr} A)として求め、λ1≥λ2\lambda_1 \ge \lambda_2 の順に並べます。固有ベクトルの列は 正規化されません。
  • それ以外のサイズでは、Householder 鏡映で三重対角形に簡約し、Wilkinson シフト付きの陰的 QL 法で対角化します。固有ベクトルの列は丸め誤差を除いて正規直交です。固有値はソートされません。
  • コストは O(n3)O(n^3) です。

Matrix::power_method

Matrix::power_method(a, max_iterations) は、べき乗反復により優勢な固有対 (λ,x)(\lambda, x) を近似し、∥Ax−λx∥∞≤tol\lVert A x - \lambda x \rVert_\infty \le \mathrm{tol} となった時点で Some((λ, x)) を返します。

pub fn[T : Compare + @luna-generic.Field + @luna-generic.Num + Tolerance] Matrix::power_method(Self[T], Int) -> (T, Vector[T])?
  • xx は ∥x∥∞=1\lVert x \rVert_\infty = 1 となるようにスケーリングされます。λ\lambda は Rayleigh 商 xTAx/xTxx^{\mathsf T} A x / x^{\mathsf T} x です。
  • max_iterations ステップ以内に反復が残差判定を満たさない場合、または反復ベクトルが数値的にゼロになった場合(たとえば冪零行列)は None を返します。±1\pm 1 のように絶対値が等しく符号が逆の 2 つの優勢固有値があると収束しません。
  • 非正方行列または空行列では中断します。
  • 各反復のコストは行列ベクトル積 1 回分、O(n2)O(n^2) です。
///|
test "eigenvalues" {
  let a = @mutable.Matrix::from_2d_array([[2.0, 1.0], [1.0, 2.0]])
  let (values, vectors) = a.eigen()
  inspect(values, content="|3, 1|")
  inspect(vectors, content="|1, 1|\n|1, -1|")
  let b = @mutable.Matrix::from_2d_array([[2.0, 1.0], [1.0, 3.0]])
  let (lambda, x) = b.power_method(200).unwrap()
  inspect((lambda - 3.618033988749895).abs() < 1.0e-9, content="true")
  inspect(x[1], content="1")
  let flip = @mutable.Matrix::from_2d_array([[1.0, 0.0], [0.0, -1.0]])
  inspect(flip.power_method(100) is None, content="true")
}

統計量とノルム

統計量は、行列を N=rcN = rc 個の要素からなる平坦なリストとして扱います。

Matrix::mean, Matrix::unchecked_mean

mean() は Ok(\bar a)(aˉ=1N∑aij\bar a = \tfrac1N \sum a_{ij})を返し、N=0N = 0 のときは EmptyMatrix を返します。unchecked_mean は代わりに中断します。

pub fn[T : @luna-generic.Field] Matrix::mean(Self[T]) -> Result[T, @error.LinearAlgebraError]
pub fn[T : @luna-generic.Field] Matrix::unchecked_mean(Self[T]) -> T

Matrix::variance, Matrix::unchecked_variance

variance() は母分散 1N∑(aij−aˉ)2\tfrac1N \sum (a_{ij} - \bar a)^2(2 パス)を返すか、EmptyMatrix を返します。

pub fn[T : @luna-generic.Field] Matrix::variance(Self[T]) -> Result[T, @error.LinearAlgebraError]
pub fn[T : @luna-generic.Field] Matrix::unchecked_variance(Self[T]) -> T

Matrix::std_dev, Matrix::unchecked_std_dev

std_dev() は母分散の平方根を返すか、EmptyMatrix を返します。

pub fn[T : @luna-generic.Field + @arithmetic.Sqrt] Matrix::std_dev(Self[T]) -> Result[T, @error.LinearAlgebraError]
pub fn[T : @luna-generic.Field + @arithmetic.Sqrt] Matrix::unchecked_std_dev(Self[T]) -> T

Matrix::max_element, Matrix::min_element

Compare による最大または最小の要素を返します。空なら EmptyMatrix です。

pub fn[T : Compare] Matrix::max_element(Self[T]) -> Result[T, @error.LinearAlgebraError]
pub fn[T : Compare] Matrix::min_element(Self[T]) -> Result[T, @error.LinearAlgebraError]

NaN の要素があると、結果はその位置に依存します。先に取り除いてください。

Matrix::unchecked_max_element, Matrix::unchecked_min_element

max_element と min_element の中断する形式です。

pub fn[T : Compare] Matrix::unchecked_max_element(Self[T]) -> T
pub fn[T : Compare] Matrix::unchecked_min_element(Self[T]) -> T

Matrix::frobenius_norm

Matrix::frobenius_norm(a) は ∥A∥F=∑aij2\lVert A \rVert_F = \sqrt{\sum a_{ij}^2} を返します。

pub fn[T : @luna-generic.AddMonoid + Mul + @arithmetic.Sqrt] Matrix::frobenius_norm(Self[T]) -> T

二乗和はスケーリングし直さないため、Double ではおよそ 1015410^{154} を超える要素でオーバーフローします。空行列のノルムは 00 です。

///|
test "statistics" {
  let m = @mutable.Matrix::from_2d_array([[1.0, 2.0], [3.0, 4.0]])
  inspect(m.mean().unwrap(), content="2.5")
  inspect(m.variance().unwrap(), content="1.25")
  inspect(m.max_element().unwrap(), content="4")
  inspect(
    @mutable.Matrix::from_2d_array([[3.0, 4.0]]).frobenius_norm(),
    content="5",
  )
}

ビュー

RowView::get, RowView::set, ColView::get, ColView::set

ビューが指す行または列の位置 i を読み書きします。view[i] と view[i] = x を支えます。

#alias("_[_]")
pub fn[T] RowView::get(Self[T], Int) -> T
#alias("_[_]=_")
pub fn[T] RowView::set(Self[T], Int, T) -> Unit
#alias("_[_]")
pub fn[T] ColView::get(Self[T], Int) -> T
#alias("_[_]=_")
pub fn[T] ColView::set(Self[T], Int, T) -> Unit

RowView::length, ColView::length

行列の列数(行ビュー)または行数(列ビュー)です。

pub fn[T] RowView::length(Self[T]) -> Int
pub fn[T] ColView::length(Self[T]) -> Int

RowView::each, RowView::eachi, RowView::iter, ColView::each, ColView::eachi, ColView::iter

ビューが指す要素を順に走査します。

pub fn[T] RowView::each(Self[T], (T) -> Unit) -> Unit
pub fn[T] RowView::eachi(Self[T], (Int, T) -> Unit) -> Unit
pub fn[T] RowView::iter(Self[T]) -> Iter[T]
pub fn[T] ColView::each(Self[T], (T) -> Unit) -> Unit
pub fn[T] ColView::eachi(Self[T], (Int, T) -> Unit) -> Unit
pub fn[T] ColView::iter(Self[T]) -> Iter[T]

RowView::map_inplace, ColView::map_inplace

ビューが指す各要素を、元の行列の中で f(entry) に置き換えます。

pub fn[T] RowView::map_inplace(Self[T], (T) -> T) -> Unit
pub fn[T] ColView::map_inplace(Self[T], (T) -> T) -> Unit

RowView::to_array, RowView::to_vector, ColView::to_array, ColView::to_vector

ビューが指す要素をコピーして取り出します。

pub fn[T] RowView::to_array(Self[T]) -> Array[T]
pub fn[T] RowView::to_vector(Self[T]) -> Vector[T]
pub fn[T] ColView::to_array(Self[T]) -> Array[T]
pub fn[T] ColView::to_vector(Self[T]) -> Vector[T]

RowView::to_string, ColView::to_string

ビューが指す要素を |a, b, c| として出力します。

pub fn[T : Show] RowView::to_string(Self[T]) -> String
pub fn[T : Show] ColView::to_string(Self[T]) -> String

転置ビュー

Transpose のメソッドはすべて転置された行列を対象とし、新しい値を返すと明記されていない限り共有ストレージ上で動作します。

Transpose::row, Transpose::col

ビューの形状です。row() はラップした行列の列数、col() はその行数です。

pub fn[T] Transpose::row(Self[T]) -> Int
pub fn[T] Transpose::col(Self[T]) -> Int

Transpose::get, Transpose::set, Transpose::at

get(i, j) と set(i, j, x) はビューの要素 (i,j)(i, j)、すなわち行列の (j,i)(j, i) にアクセスします。at は t[i][j] と t[i][j] = x を支えます。

pub fn[T] Transpose::get(Self[T], Int, Int) -> T
pub fn[T] Transpose::set(Self[T], Int, Int, T) -> Unit
#alias("_[_]")
pub fn[T] Transpose::at(Self[T], Int) -> Lens[T]

Transpose::transpose

Transpose::transpose(t) はコピーではなく、ラップした行列そのものを返します。

pub fn[T] Transpose::transpose(Self[T]) -> Matrix[T]

Transpose::materialize

Transpose::materialize(t) はビューを、転置した形状の新しい行列にコピーします。

pub fn[T] Transpose::materialize(Self[T]) -> Matrix[T]

Transpose::copy

Transpose::copy(t) は、ラップした行列のディープコピーに対するビューを返します。

pub fn[T] Transpose::copy(Self[T]) -> Self[T]

走査: Transpose::each、Transpose::eachi、Transpose::each_row_col、Transpose::each_row、Transpose::eachi_row、Transpose::each_col、Transpose::eachi_col

ビューを走査します。

pub fn[T] Transpose::each(Self[T], (T) -> Unit) -> Unit
pub fn[T] Transpose::eachi(Self[T], (Int, T) -> Unit) -> Unit
pub fn[T] Transpose::each_row_col(Self[T], (Int, Int, T) -> Unit) -> Unit
pub fn[T] Transpose::each_row(Self[T], Int, (T) -> Unit) -> Unit
pub fn[T] Transpose::eachi_row(Self[T], Int, (Int, T) -> Unit) -> Unit
pub fn[T] Transpose::each_col(Self[T], Int, (T) -> Unit) -> Unit
pub fn[T] Transpose::eachi_col(Self[T], Int, (Int, T) -> Unit) -> Unit

each、eachi、each_row_col は、ラップした行列のストレージ順(ビューにとっては列優先)に要素を訪れます。eachi は ビューの 行優先インデックスを渡し、each_row_col はビューの座標を渡します。行と列の形式は、ビューの 1 つの行または列を順に訪れます。

Transpose::row_to_array, Transpose::col_to_array, Transpose::row_to_vector, Transpose::col_to_vector

ビューの 1 つの行または列をコピーします。

pub fn[T] Transpose::row_to_array(Self[T], Int) -> Array[T]
pub fn[T] Transpose::col_to_array(Self[T], Int) -> Array[T]
pub fn[T] Transpose::row_to_vector(Self[T], Int) -> Vector[T]
pub fn[T] Transpose::col_to_vector(Self[T], Int) -> Vector[T]

Transpose::map, Transpose::map_inplace, Transpose::map_row_inplace, Transpose::map_col_inplace

map は新しい行列に対する新しいビューを返します。*_inplace 形式は共有ストレージを変更します。

pub fn[T] Transpose::map(Self[T], (T) -> T) -> Self[T]
#alias(map_in_place, deprecated)
pub fn[T] Transpose::map_inplace(Self[T], (T) -> T) -> Unit
#alias(map_row_in_place, deprecated)
pub fn[T] Transpose::map_row_inplace(Self[T], Int, (T) -> T) -> Unit
#alias(map_col_in_place, deprecated)
pub fn[T] Transpose::map_col_inplace(Self[T], Int, (T) -> T) -> Unit

Transpose::swap_rows, Transpose::swap_cols

ビューの 2 つの行または列(ラップした行列にとっては列または行)をインプレースで交換します。

pub fn[T] Transpose::swap_rows(Self[T], Int, Int) -> Unit
pub fn[T] Transpose::swap_cols(Self[T], Int, Int) -> Unit

Transpose::horizontal_combine, Transpose::vertical_combine

ビューのブロック連結で、新しい行列に対するビューを返します。

pub fn[T] Transpose::horizontal_combine(Self[T], Self[T]) -> Self[T]
pub fn[T] Transpose::vertical_combine(Self[T], Self[T]) -> Self[T]

Transpose::add, Transpose::sub, Transpose::neg, Transpose::scale, Transpose::add_constant

要素ごとの算術演算で、新しい行列に対するビューを返します。

pub fn[T : Add] Transpose::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] Transpose::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] Transpose::neg(Self[T]) -> Self[T]
pub fn[T : Mul] Transpose::scale(Self[T], T) -> Self[T]
pub fn[T : Add] Transpose::add_constant(Self[T], T) -> Self[T]

Transpose::mul

Transpose::mul(s, t) は 2 つのビューの積を返します。データを移動せずに ATBT=(BA)TA^{\mathsf T} B^{\mathsf T} = (BA)^{\mathsf T} として計算します。

pub fn[T : @luna-generic.AddMonoid + Mul] Transpose::mul(Self[T], Self[T]) -> Self[T]

Transpose::equal, Transpose::to_string

equal はラップした行列どうしを比較し、to_string はビューを行ごとに出力します。

pub fn[T : Eq] Transpose::equal(Self[T], Self[T]) -> Bool
pub fn[T : Show] Transpose::to_string(Self[T]) -> String
///|
test "transpose view" {
  let m = @mutable.Matrix::from_2d_array([[1, 2, 3], [4, 5, 6]])
  let t = m.to_transpose()
  inspect(t, content="|1, 4|\n|2, 5|\n|3, 6|")
  t[2][0] = 30
  inspect(m.get(0, 2), content="30")
  let s = @mutable.Matrix::from_2d_array([[1, 0], [0, 1], [1, 1]]).to_transpose()
  let product = t * s
  debug_inspect((product.row(), product.col()), content="(3, 3)")
  inspect(t.materialize().row(), content="3")
  let order = []
  t.each(x => order.push(x))
  debug_inspect(order, content="[1, 2, 30, 4, 5, 6]")
}

ベクトル

Vector::from_array

Vector::from_array(xs) は xs をコピーせずにベクトルのストレージとして採用します。

pub fn[A] Vector::from_array(Array[A]) -> Self[A]

Vector::make, Vector::makei

値の nn 個のコピー、または (f(0),…,f(n−1))(f(0), \dots, f(n-1)) です。

pub fn[A] Vector::make(Int, A) -> Self[A]
pub fn[A] Vector::makei(Int, (Int) -> A) -> Self[A]

Vector::length, Vector::copy, Vector::iter

長さ、ディープコピー、イテレータです。

pub fn[A] Vector::length(Self[A]) -> Int
pub fn[A] Vector::copy(Self[A]) -> Self[A]
pub fn[T] Vector::iter(Self[T]) -> Iter[T]

Vector::at, Vector::set

要素 i をインプレースで読み書きします。v[i] と v[i] = x を支えます。範囲外のインデックスでは中断します。

#alias("_[_]")
pub fn[A] Vector::at(Self[A], Int) -> A
#alias("_[_]=_")
pub fn[A] Vector::set(Self[A], Int, A) -> Unit

Vector::map, Vector::zip_with, Vector::map_inplace

map と zip_with は新しいベクトルを返します(zip_with は長さが異なると中断します)。map_inplace はすべての要素を書き換えます。

pub fn[A, B] Vector::map(Self[A], (A) -> B) -> Self[B]
pub fn[A, U, V] Vector::zip_with(Self[A], Self[U], (A, U) -> V) -> Self[V]
#alias(map_in_place, deprecated)
pub fn[A] Vector::map_inplace(Self[A], (A) -> A) -> Unit

Vector::add, Vector::mul, Vector::neg, Vector::add_constant

要素ごとの u+vu + v、Hadamard 積 u⊙vu \odot v、−u-u、u+au + a です。長さが異なる場合は中断します。Sub はないので、u + -v と書いてください。

pub fn[T : Add] Vector::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Mul] Vector::mul(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] Vector::neg(Self[T]) -> Self[T]
pub fn[T : Add] Vector::add_constant(Self[T], T) -> Self[T]

Vector::left_scale, Vector::right_scale, Vector::left_scale_inplace, Vector::right_scale_inplace

(avi)(a v_i) と (via)(v_i a) を、新しいベクトルとして、またはインプレースで求めます。

pub fn[A : Mul] Vector::left_scale(Self[A], A) -> Self[A]
pub fn[A : Mul] Vector::right_scale(Self[A], A) -> Self[A]
#alias(left_scale_in_place, deprecated)
pub fn[A : Mul] Vector::left_scale_inplace(Self[A], A) -> Unit
#alias(right_scale_in_place, deprecated)
pub fn[A : Mul] Vector::right_scale_inplace(Self[A], A) -> Unit

Vector::dot

Vector::dot(u, v) は左から右へ足し合わせた ∑iuivi\sum_i u_i v_i を返します。長さが異なる場合は中断します。

pub fn[T : @luna-generic.AddMonoid + Mul] Vector::dot(Self[T], Self[T]) -> T

Vector::lerp

Vector::lerp(u, v, t) は (1−t)u+tv(1 - t) u + t v を返します。

pub fn[T : @luna-generic.MulMonoid + Add + Neg] Vector::lerp(Self[T], Self[T], T) -> Self[T]

Vector::lin_comb

Vector::lin_comb(weights, vectors) は ∑kwkvk\sum_k w_k v_k を 1 パスで返します。

pub fn[T : Mul + Add + @luna-generic.Zero] Vector::lin_comb(Array[T], Array[Self[T]]) -> Self[T]

入力が空の場合、重みとベクトルの個数が異なる場合、またはベクトルの長さが異なる場合は中断します。

lin_comb

lin_comb(a, u, b, v) は au+bva u + b v を返します。これはトップレベル関数です。

pub fn[T : Add + Mul] lin_comb(T, Vector[T], T, Vector[T]) -> Vector[T]

Vector::to_row_matrix, Vector::to_col_matrix, Vector::scaled_matrix, Vector::tensor_product

ベクトルを 1×n1 \times n または n×1n \times 1 行列として(コピーして)返すもの、対角行列 diag⁡(v)\operatorname{diag}(v)、外積 uvTu v^{\mathsf T} です。

pub fn[T] Vector::to_row_matrix(Self[T]) -> Matrix[T]
pub fn[T] Vector::to_col_matrix(Self[T]) -> Matrix[T]
pub fn[T : @luna-generic.Zero] Vector::scaled_matrix(Self[T]) -> Matrix[T]
pub fn[T : Mul] Vector::tensor_product(Self[T], Self[T]) -> Matrix[T]

Vector::equal, Vector::to_string

equal は要素を比較し(== を支えます)、to_string は |a, b, c| を出力します。

pub fn[T : Eq] Vector::equal(Self[T], Self[T]) -> Bool
pub fn[T : Show] Vector::to_string(Self[T]) -> String
///|
test "mutable vectors" {
  let v = @mutable.Vector::from_array([1, 2, 3])
  v[0] = 10
  v.left_scale_inplace(2)
  inspect(v, content="|20, 4, 6|")
  inspect(v.dot(@mutable.Vector::make(3, 1)), content="30")
  let w = @mutable.Vector::lin_comb([1, 2], [
    v,
    @mutable.Vector::makei(3, i => i),
  ])
  inspect(w, content="|20, 6, 10|")
  inspect(@mutable.lin_comb(1, v, -1, w), content="|0, -2, -4|")
}

非推奨

項目代替
Matrix::map_in_place、map_row_in_place、map_col_in_place(別名)map_inplace, map_row_inplace, map_col_inplace
Transpose::map_in_place、map_row_in_place、map_col_in_place(別名)*_inplace の名前
Vector::map_in_place、left_scale_in_place、right_scale_in_place(別名)map_inplace, left_scale_inplace, right_scale_inplace
Matrix、Transpose、Vector の not_equal メソッド形式(非公開)!=
Matrix、Transpose、RowView、ColView、Vector の output メソッド形式(非公開)文字列補間または Show::output(x, logger)
Vector::to_repr(非公開)Repr(v) または @debug.Debug::to_repr(v)
Vector::arbitrary(非公開)@quickcheck.Arbitrary::arbitrary