I am trying to use Rust to perform sequential kronecker product to multiple matrices, i.e. I want to do

In python, I know I can do
import numpy as np
from functools import reduce
X = np.array([[0, 1], [1, 0])
matrices = [X for _ in range(8)]
product = reduce(np.kron, matrices)
and get the desired result. How to do the same in Rust?
My Rust code look like the following for now:
use ndarray::{array, ArrayBase, OwnedRepr, Dim};
use ndarray::linalg::kron;
use num::complex::Complex64 as Complex;
fn X() -> ArrayBase<OwnedRepr<Complex>, Dim<[usize; 2]>> {
array![
[Complex::new(0.0, 0.0), Complex::new(1.0, 0.0)],
[Complex::new(1.0, 0.0), Complex::new(0.0, 0.0)]
]
}
fn main() {
let mut matrices = Vec::new();
for _ in 0..8 {
matrices.push(X());
}
let product = matrices
.iter()
.reduce(|g1, g2| kron(g1, g2));
}
Here's the error matrix I got:

Here's the things I don't understand:
OwnedRepr: I'm not sure what this is for exactly, but this is what the rust-analyzer suggested me to do
with no further suggestions on how to process.How can I achieve this?
Unlike Python, in Rust you are required to think about ownership.
ndarray includes multiple version of arrays: Array, ArrayView, ArrayViewMut, ArcArray and CowArray. They are analogous to the many ways one can view a data in Rust: owned (T or Box<T>) - this is Array which is an alias of ArrayBase<OwnedRepr>, shared reference (&T) - ArrayView, mutable reference (&mut T) - ArrayViewMut, shared ownership (Rc<T> and Arc<T>) - ArcArray, and copy-on-write (Cow<T>) - CowArray.
iter() gives you an iterator over references to the elements, that is, &Array, while kron() returns owned arrays - Array. But reduce() requires both the inputs and the output to be of the same type, because the output becomes the input of the next item. So you need to unify them.
There are multiple ways you can do that. For example, by using into_iter() instead of iter():
let product = matrices.into_iter().reduce(|g1, g2| kron(&g1, &g2));
Or by cloning the first matrix and using fold():
fn kron_many(matrices: &[Array2<Complex>]) -> Option<Array2<Complex>> {
let (first, rest) = matrices.split_first()?;
let first = first.clone();
Some(rest.iter().fold(first, |g1, g2| kron(&g1, g2)))
}
fn main() {
let mut matrices = Vec::new();
for _ in 0..8 {
matrices.push(X());
}
let product = kron_many(&matrices);
}
Or without cloning, by using CowArray to represent a maybe-owned array:
let product = matrices
.iter()
.map(|matrix| CowArray::from(matrix))
.reduce(|g1, g2| kron(&g1, &g2).into());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With