【Rust】nalgebraで線形代数演算をしてみる

Rustでnalgebraを使って線形代数の演算をしてみようとしてるのですが、Webに情報が少なく苦労したので、備忘も兼ねて線形代数の演算(基本的なもの)を少し書いていこうと思います。

なお、Rustは 1.60.1、nalgebraは0.30.1のものを使用しています。

ゼロ行列、単位行列

以下のように書きます。

let mat_zero = Matrix2::<f32>::zeros();
let mat_one = Matrix2::<f32>::identity();

最初は下記のように書いたらエラーが出てしまい、どこがダメなのか悩んでました。ゼロ行列や単位行列を関数から宣言するときは型の指定まで行う必要があるみたいです。

// エラーが出てしまうパターン
let mat_zero = Matrix2::zero();
let mat_one = Matrix2::identity();

スカラーとの演算

// matは適当な行列
println!("mat * 2.0: {}", &mat * 2.0);
println!("mat / 2.0: {}", &mat / 2.0);

//println!("mat + 2.0: {}", &mat  + 2.0);  // エラーになる
println!("mat + 2.0: {}", &mat + Matrix2::repeat(2.0));

Pythonのnumpyっぽくいけるかなぁと思ったら、足し算(おそらく引き算も)は上手くいかず、全ての要素が同じ値の行列を作り、それと足し算をすることで実現しています。

転置、ランク、行列式

下記のように求めます。シンプルな形でいいですね。

// matは適当な行列
println!("転置: {}", mat.transpose());
println!("ランク: {}", mat.rank(1.0e-10));
println!("行列式: {}", mat.determinant());

逆行列

// matは適当な行列
println!("逆行列: {}", mat.try_inverse().unwrap());

逆行列を求める関数はOptionなので、unwrap()なりして取り出します。

固有値

以下のように書くことで求めることができます。

// matは適当な行列
println!("固有値: {}", Matrix::eigenvalues(&mat).unwrap());

また、以下のように書くことで(対称行列なら)固有値固有ベクトルの両方が求められそうなんですが、他の行列についての固有ベクトルの求め方は調査中です。

// matは適当な行列
println!("固有値と固有ベクトル: {:?}", Matrix::symmetric_eigen(mat));

以上です。

固有ベクトルの求め方、あとランダム初期化(new_random()で出来そうですがエラーになってしまう)は不明ですが、ここまで分かればRustでnalgebraを使って色々線形代数計算、機械学習を自分で実装することできそうです