Make it compile: linear algebra exercises #1

Drashti Shah
Bioinformatics with Rust
3 min readDec 9, 2023
Generated with AI

Rust has a crate called ndarray. It’s like numpy in Python. These exercises are designed to help you get familiar with ndarray, so you can use it in your data science or bioinformatics workflows.

I mention the word tensor a few times below. A tensor is simply an n-dimensional data structure. A 0-dimensional tensor is a scalar, a 1-dimensional tensor is a vector, and a 2-dimensional tensor is a matrix. In this first part, we will start with element-wise operations.

Shapes are important when performing arithmetic operations on tensors. Some things about tensor shapes to keep in mind while you work through the problems:

  • If you are performing an arithmetic operation between a tensor and a scalar, the input tensor shape = output tensor shape.
  • If the operation is between 2 tensors with same shape, then the input tensor shape = output tensor shape.
  • If the input tensors are of different shapes, then one of the tensors should be compatible for broadcasting and the other tensor’s shape = output tensor shape.
  • If your tensor can’t broadcast, you will see ShapeError.

You can open Rust Playground and work on these there. You will see 5 problems. The first one is solved for you. This code will not compile until you solve all the problems. Your task is to make this compile.

use ndarray::array;

fn main() {
problem_one();
problem_two();
problem_three();
problem_four();
problem_five();
println!("{}", "Congrats! You solved all problems.")
}

// a tensor * a scalar
fn problem_one() {
let a1 = array![1, 2, 3, 4];
let scalar = 2;
let expected = array![2, 4, 6, 8];
assert_eq!(a1 * scalar, expected, "Check problem 1");
}

// a tensor + a scalar
fn problem_two() {
let a1 = array![1, 2, 3, 4];

// ADD CODE BELOW THIS LINE
// Define a scalar value, so the assert statement passes
let scalar = __;
// ADD CODE ABOVE THIS LINE

let expected = array![10, 11, 12, 13];
assert_eq!(a1 + scalar, expected, "Check problem 2");
}

// a tensor * another tensor (same shape)
fn problem_three() {
let a1 = array![1, 2, 3, 4];

// ADD CODE BELOW THIS LINE
// Define array/tensor, so the assert statement passes
let a2 = __;
// ADD CODE ABOVE THIS LINE

let expected = array![0, 0, 0, 0];
assert_eq!(a1 * a2, expected, "Check problem 3");
}

// a tensor + another tensor (same shape)
fn problem_four() {
let a1 = array![1, 2, 3, 4];

// ADD CODE BELOW THIS LINE
// Define array/tensor, so the assert statement passes
let a2 = __;
// ADD CODE ABOVE THIS LINE

let expected = array![0, 0, 0, 0];
assert_eq!(a1 + a2, expected, "Check problem 4");
}

// a tensor * another tensor (different shapes)
fn problem_five() {
let a1 = array![[1, 1]];

// ADD CODE BELOW THIS LINE
// Define array/tensor, so the assert statement passes
let a2 = __;
// ADD CODE ABOVE THIS LINE

let expected = array![[1, 2], [3, 4]];
assert_eq!(a1 * a2, expected, "Check problem 5");
}

--

--

Drashti Shah
Bioinformatics with Rust

ESG & climate data scientist by day. Aspiring computational biologist and game designer by night. A Rust fan who believes in an "open career".