Examples on ndarray-linalg

Hello All,

I'm trying to get started on using rust, and in particular the available linear algebra libraries.
From what I've found the best resource seems to be ndarray-linalg. I've tried running some of their examples codes, found here, but none of them seem
to be functional.

Considering the example function

// Solve `Ax=b` for tridiagonal matrix
fn solve() -> Result<(), error::LinalgError> {
    let mut a: Array2<f64> = random((3, 3));
    let b: Array1<f64> = random(3);
    a[[0, 2]] = 0.0;
    a[[2, 0]] = 0.0;
    let _x = a.solve_tridiagonal(&b)?;
    Ok(())
}

it seems that "solve_tridiagonal" is not defined on an Array2 type. Could you please point me
into some direction? The trait SolveTridiagonal is implemented for a range of Array types and
I would like to understand how I may use it.

Best wishes,

Choeppke

Import that trait to use it in your code.

1 Like

Hello RedDoc,

I've imported the trait via use, resulting in

use ndarray::*;
use ndarray_linalg::*;
use ndarray_rand::*;
use ndarray_rand::rand_distr::Uniform;
use ndarray_linalg::tridiagonal::SolveTridiagonal;

// Solve `Ax=b` for tridiagonal matrix
fn solve() {
    let mut a: Array2<f64> = Array::random((3, 3), Uniform::new(0.0, 1.0));
    let b: Array1<f64> = Array::random(3, Uniform::new(0.0, 1.0));
    a[[0, 2]] = 0.0;
    a[[2, 0]] = 0.0;
    let res = a.solve_tridiagonal(&b)?;
    println!("{:?}", a);
    println!("{:?}", b);
    println!("{:?}", c);
}

fn main() {
    solve();
}

Could you please explain what you mean by how I can use it?

Best,
Choeppke

Hi @choeppke,

I hope this helps, even if it's a bit late.

I was able to make your code compile with two small modifications; your last println! needs to be commented out (c doesn't exist) and changing the ? to unwrap() (solve() doesn't return errors). The full code is below:

use ndarray::*;
use ndarray_linalg::*;
use ndarray_rand::*;
use ndarray_rand::rand_distr::Uniform;
use ndarray_linalg::tridiagonal::SolveTridiagonal;

// Solve `Ax=b` for tridiagonal matrix
fn solve() {
    let mut a: Array2<f64> = Array::random((3, 3), Uniform::new(0.0, 1.0));
    let b: Array1<f64> = Array::random(3, Uniform::new(0.0, 1.0));
    a[[0, 2]] = 0.0;
    a[[2, 0]] = 0.0;
    let res = a.solve_tridiagonal(&b).unwrap();
    println!("{:?}", a);
    println!("{:?}", b);
    // println!("{:?}", c);
}

fn main() {
    solve();
}

For completeness, here's my Cargo.toml:

[package]
name = "linalg"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
ndarray = "0.15.4"
ndarray-linalg = { version = "0.14.1", features = ["openblas-system"] }
ndarray-rand = "0.14.0"

Note that I'm using the openblas-system feature for ndarray-linalg. You should choose what works for you based on this page.

My results of cargo run:

warning: unused import: `ndarray_linalg::*`
 --> src/main.rs:2:5
  |
2 | use ndarray_linalg::*;
  |     ^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused variable: `res`
  --> src/main.rs:13:9
   |
13 |     let res = a.solve_tridiagonal(&b).unwrap();
   |         ^^^ help: if this is intentional, prefix it with an underscore: `_res`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: `linalg` (bin "linalg") generated 2 warnings
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/linalg`
[[0.9663789024107372, 0.35955842232653223, 0.0],
 [0.006253186281878653, 0.3396009826675137, 0.2136267149637281],
 [0.0, 0.7372859347625886, 0.24160310345096114]], shape=[3, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2
[0.7127561709438837, 0.9017411157024657, 0.24626367229188184], shape=[3], strides=[1], layout=CFcf (0xf), const ndim=1

Thank you @chjordan for this great solution! I've found that many examples, specifically on ndarray and ndarray-linalg, seem to be out of date and don't compile anymore when copy-pasted, so this leg-up is much appreciated.

You're welcome. I don't check out the Rust forums too often, but it is a good community, and I encourage you to keep learning. It can be difficult to wrap your head around things but I've found the effort well worth it.