mirror of
https://github.com/rust-lang-nursery/rust-cookbook
synced 2024-11-21 19:13:07 +00:00
Update to ndarray 0.13 (#560)
This commit is contained in:
parent
3fcb08bee2
commit
d7c291151f
7 changed files with 92 additions and 77 deletions
|
@ -29,7 +29,7 @@ log4rs = "0.8"
|
|||
memmap = "0.7"
|
||||
mime = "0.3"
|
||||
nalgebra = "0.16.12"
|
||||
ndarray = "0.12"
|
||||
ndarray = { version = "0.13", features = ["approx"] }
|
||||
num = "0.2"
|
||||
num_cpus = "1.8"
|
||||
percent-encoding = "2.1"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# Linear Algebra
|
||||
|
||||
{{#include linear_algebra/vector-sum.md}}
|
||||
{{#include linear_algebra/vector-norm.md}}
|
||||
{{#include linear_algebra/add-matrices.md}}
|
||||
{{#include linear_algebra/multiply-matrices.md}}
|
||||
{{#include linear_algebra/multiply-scalar-vector-matrix.md}}
|
||||
{{#include linear_algebra/vector-comparison.md}}
|
||||
{{#include linear_algebra/vector-norm.md}}
|
||||
{{#include linear_algebra/invert-matrix.md}}
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
## Adding matrices
|
||||
[![ndarray-badge]][ndarray] [![cat-science-badge]][cat-science]
|
||||
|
||||
Creates two matrices with [`ndarray::arr2`] and adds them together.
|
||||
Creates two 2-D matrices with [`ndarray::arr2`] and sums them element-wise.
|
||||
|
||||
Note the sum is computed as `let sum = &a + &b`. The `&` operator is used to avoid consuming `a` and `b`, making them available later for display. A new array is created containing their sum.
|
||||
|
||||
```rust
|
||||
extern crate ndarray;
|
||||
|
@ -15,7 +17,13 @@ fn main() {
|
|||
let b = arr2(&[[6, 5, 4],
|
||||
[3, 2, 1]]);
|
||||
|
||||
println!("Sum: {}", a + b);
|
||||
let sum = &a + &b;
|
||||
|
||||
println!("{}", a);
|
||||
println!("+");
|
||||
println!("{}", b);
|
||||
println!("=");
|
||||
println!("{}", sum);
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -2,14 +2,18 @@
|
|||
[![ndarray-badge]][ndarray] [![cat-science-badge]][cat-science]
|
||||
|
||||
Creates a 1-D array (vector) with [`ndarray::arr1`] and a 2-D array (matrix)
|
||||
with [`ndarray::arr2`]. First, a scalar is multiplied by the vector to get
|
||||
with [`ndarray::arr2`].
|
||||
|
||||
First, a scalar is multiplied by the vector to get
|
||||
another vector. Then, the matrix is multiplied by the new vector with
|
||||
[`ndarray::Array2::dot`]. (`dot` performs matrix multiplication, while the `*`
|
||||
operator performs element-wise multiplication.) In `ndarray`, 1-D arrays can be
|
||||
interpreted as either row or column vectors depending on context. If
|
||||
representing the orientation of a vector is important, a 2-D array with one row
|
||||
or one column must be used instead. In this example, the vector is a 1-D array
|
||||
on the right-hand side, so `dot` handles it as a column vector.
|
||||
[`ndarray::Array2::dot`]. (Matrix multiplication is performed using `dot`, while
|
||||
the `*` operator performs element-wise multiplication.)
|
||||
|
||||
In `ndarray`, 1-D arrays can be interpreted as either row or column vectors
|
||||
depending on context. If representing the orientation of a vector is important,
|
||||
a 2-D array with one row or one column must be used instead. In this example,
|
||||
the vector is a 1-D array on the right-hand side, so `dot` handles it as a column
|
||||
vector.
|
||||
|
||||
```rust
|
||||
extern crate ndarray;
|
||||
|
@ -32,6 +36,6 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
[`ndarray::Array2::dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1
|
||||
[`ndarray::arr1`]: https://docs.rs/ndarray/*/ndarray/fn.arr1.html
|
||||
[`ndarray::arr2`]: https://docs.rs/ndarray/*/ndarray/fn.arr2.html
|
||||
[`ndarray::Array2::dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1
|
50
src/science/mathematics/linear_algebra/vector-comparison.md
Normal file
50
src/science/mathematics/linear_algebra/vector-comparison.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
## Vector comparison
|
||||
[![ndarray-badge]][ndarray]
|
||||
|
||||
The [ndarray] crate supports a number of ways to create arrays -- this recipe creates
|
||||
[`ndarray::Array`]s from `std::Vec` using `from`. Then, it sums the arrays element-wise.
|
||||
|
||||
This recipe contains an example of comparing two floating-point vectors element-wise.
|
||||
Floating-point numbers are often stored inexactly, making exact comparisons difficult.
|
||||
However, the [`assert_abs_diff_eq!`] macro from the [`approx`] crate allows for convenient
|
||||
element-wise comparisons. To use the `approx` crate with `ndarray`, the `approx`
|
||||
feature must be added to the `ndarray` dependency in `Cargo.toml`. For example,
|
||||
`ndarray = { version = "0.13", features = ["approx"] }`.
|
||||
|
||||
This recipe also contains additional ownership examples. Here, `let z = a + b` consumes
|
||||
`a` and `b`, updates `a` with the result, then moves ownership to `z`. Alternatively,
|
||||
`let w = &c + &d` creates a new vector without consuming `c` or `d`, allowing
|
||||
their modification later. See [Binary Operators With Two Arrays] for additional detail.
|
||||
|
||||
```rust
|
||||
#[macro_use(assert_abs_diff_eq)]
|
||||
extern crate approx;
|
||||
extern crate ndarray;
|
||||
|
||||
use ndarray::Array;
|
||||
|
||||
fn main() {
|
||||
let a = Array::from(vec![1., 2., 3., 4., 5.]);
|
||||
let b = Array::from(vec![5., 4., 3., 2., 1.]);
|
||||
let mut c = Array::from(vec![1., 2., 3., 4., 5.]);
|
||||
let mut d = Array::from(vec![5., 4., 3., 2., 1.]);
|
||||
|
||||
let z = a + b;
|
||||
let w = &c + &d;
|
||||
|
||||
assert_abs_diff_eq!(z, Array::from(vec![6., 6., 6., 6., 6.]));
|
||||
|
||||
println!("c = {}", c);
|
||||
c[0] = 10.;
|
||||
d[1] = 10.;
|
||||
|
||||
assert_abs_diff_eq!(w, Array::from(vec![6., 6., 6., 6., 6.]));
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
[`approx`]: https://docs.rs/approx/*/approx/index.html
|
||||
[`assert_abs_diff_eq!`]: https://docs.rs/approx/*/approx/macro.assert_abs_diff_eq.html
|
||||
[Binary Operators With Two Arrays]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#binary-operators-with-two-arrays
|
||||
[ndarray]: https://docs.rs/crate/ndarray/*
|
||||
[`ndarray::Array`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html
|
|
@ -1,26 +1,30 @@
|
|||
## Vector Norm
|
||||
## Vector norm
|
||||
[![ndarray-badge]][ndarray]
|
||||
|
||||
This recipe demonstrates use of the [`Array1`] type, [`ArrayView1`] type,
|
||||
[`fold`] method, and [`dot`] method in computing the [l1] and [l2] norms of a
|
||||
given vector. The l2 norm calculation is the simpler of the two, as it is the
|
||||
square root of the dot product of a vector with itself, shown in the function
|
||||
`l2_norm`. The l1 norm, shown in the function `l1_norm`, is computed by a `fold`
|
||||
given vector.
|
||||
+ The `l2_norm` function is the simpler of the two, as it computes the
|
||||
square root of the dot product of a vector with itself.
|
||||
+ The `l1_norm` function is computed by a `fold`
|
||||
operation that sums the absolute values of the elements. (This could also be
|
||||
performed with `x.mapv(f64::abs).scalar_sum()`, but that would allocate a new
|
||||
array for the result of the `mapv`.)
|
||||
|
||||
Note that both `l1_norm` and `l2_norm` take the [`ArrayView1`] type. This recipe
|
||||
considers vector norms, so the norm functions only need to accept one
|
||||
dimensional views (hence [`ArrayView1`]). While the functions could take a
|
||||
considers vector norms, so the norm functions only need to accept one-dimensional
|
||||
views (hence [`ArrayView1`]). While the functions could take a
|
||||
parameter of type `&Array1<f64>` instead, that would require the caller to have
|
||||
a reference to an owned array, which is more restrictive than just having access
|
||||
to a view (since a view can be created from any array or view, not just an owned
|
||||
array). The most convenient argument type for the caller would be
|
||||
`&ArrayBase<S, Ix1> where S: Data`, because then the caller could use `&array`
|
||||
or `&view` instead of `x.view()`. If the function is part of your public API,
|
||||
that may be a better choice for the benefit of your users, but for internal
|
||||
functions, the more concise `ArrayView1<f64>` may be preferable.
|
||||
array).
|
||||
|
||||
`Array` and `ArrayView` are both type aliases for `ArrayBase`. So, the most
|
||||
general argument type for the caller would be `&ArrayBase<S, Ix1> where S: Data`,
|
||||
because then the caller could use `&array` or `&view` instead of `x.view()`.
|
||||
If the function is part of a public API, that may be a better choice for the
|
||||
benefit of users. For internal functions, the more concise `ArrayView1<f64>`
|
||||
may be preferable.
|
||||
|
||||
```rust
|
||||
#[macro_use(array)]
|
||||
|
@ -50,9 +54,9 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
[l1]: http://mathworld.wolfram.com/L1-Norm.html
|
||||
[l2]: http://mathworld.wolfram.com/L2-Norm.html
|
||||
[`Array1`]: https://docs.rs/ndarray/*/ndarray/type.Array1.html
|
||||
[`ArrayView1`]: https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html
|
||||
[`dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot
|
||||
[`fold`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.fold
|
||||
[l1]: http://mathworld.wolfram.com/L1-Norm.html
|
||||
[l2]: http://mathworld.wolfram.com/L2-Norm.html
|
|
@ -1,51 +0,0 @@
|
|||
## Vector Sum
|
||||
[![ndarray-badge]][ndarray]
|
||||
|
||||
The [ndarray] crate supports a number of ways to create arrays -- this recipe
|
||||
focuses on creating [`ndarray::Array`]s from `std::Vec` via [`from_vec`]. Adding two
|
||||
arrays together is no different than adding two numbers together. Using the `&`
|
||||
operand on the arrays within an arithmetic operation prevents the operation from
|
||||
consuming the arrays. Without `&`, the arrays are consumed.
|
||||
|
||||
In the first example, arrays `a` and `b` are moved in the let-statement `z = a +
|
||||
b`. In the second example, the arrays `c` and `d` are not moved and instead, a
|
||||
new array is created for `w`. Updating either of `c` or `d` after the vector sum
|
||||
has no effect the value of `w`. Additionally, while printing `c` works as
|
||||
expected, it would be an error to print `b` due to the move. See [Binary
|
||||
Operators With Two Arrays] for additional detail.
|
||||
|
||||
```rust
|
||||
extern crate ndarray;
|
||||
use ndarray::Array;
|
||||
|
||||
fn main() {
|
||||
let a = Array::from_vec(vec![1., 2., 3., 4., 5.]);
|
||||
let b = Array::from_vec(vec![5., 4., 3., 2., 1.]);
|
||||
let mut c = Array::from_vec(vec![1., 2., 3., 4., 5.]);
|
||||
let mut d = Array::from_vec(vec![5., 4., 3., 2., 1.]);
|
||||
|
||||
let z = a + b;
|
||||
let w = &c + &d;
|
||||
|
||||
let epsilon = 1e-8;
|
||||
for elem in z.iter() {
|
||||
let diff: f32 = *elem - 6.;
|
||||
assert!(diff.abs() < epsilon);
|
||||
}
|
||||
|
||||
println!("c = {}", c);
|
||||
c[0] = 10.;
|
||||
d[1] = 10.;
|
||||
|
||||
for elem in w.iter() {
|
||||
let diff: f32 = *elem - 6.;
|
||||
assert!(diff.abs() < epsilon);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
[Binary Operators With Two Arrays]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#binary-operators-with-two-arrays
|
||||
[`from_vec`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.from_vec
|
||||
[ndarray]: https://docs.rs/crate/ndarray/*
|
||||
[`ndarray::Array`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html
|
Loading…
Reference in a new issue