Function russell_lab::sv_decomp [−][src]
pub fn sv_decomp(
s: &mut Vector,
u: &mut Matrix,
vt: &mut Matrix,
a: &mut Matrix
) -> Result<(), &'static str>Expand description
Computes the singular value decomposition (SVD) of a matrix
Finds u, s, and v, such that:
a := u ⋅ s ⋅ vᵀ
(m,n) (m,m) (m,n) (n,n)Output
s– min(m,n) vector with the diagonal elementsu– (m,m) orthogonal matrixvt– (n,n) orthogonal matrix with the transpose of v
Input
a– (m,n) matrix, symmetric or not [will be modified]
Note
- The matrix
awill be modified
Examples
First - 2 x 3 rectangular matrix
// import
use russell_lab::*;
// set matrix
let mut a = Matrix::from(&[
[3.0, 2.0, 2.0],
[2.0, 3.0, -2.0],
]);
// allocate output structures
let (m, n) = a.dims();
let min_mn = if m < n { m } else { n };
let mut s = Vector::new(min_mn);
let mut u = Matrix::new(m, m);
let mut vt = Matrix::new(n, n);
// perform SVD
sv_decomp(&mut s, &mut u, &mut vt, &mut a)?;
// define correct data
let s_correct = "┌ ┐\n\
│ 5.000 │\n\
│ 3.000 │\n\
└ ┘";
let u_correct = "┌ ┐\n\
│ -0.707 -0.707 │\n\
│ -0.707 0.707 │\n\
└ ┘";
let vt_correct = "┌ ┐\n\
│ -0.707 -0.707 -0.000 │\n\
│ -0.236 0.236 -0.943 │\n\
│ -0.667 0.667 0.333 │\n\
└ ┘";
// check solution
assert_eq!(format!("{:.3}", s), s_correct);
assert_eq!(format!("{:.3}", u), u_correct);
assert_eq!(format!("{:.3}", vt), vt_correct);
// check SVD: a == u * s * vt
let mut usv = Matrix::new(m, n);
for i in 0..m {
for j in 0..n {
for k in 0..min_mn {
usv[i][j] += u[i][k] * s[k] * vt[k][j];
}
}
}
let usv_correct = "┌ ┐\n\
│ 3.000000 2.000000 2.000000 │\n\
│ 2.000000 3.000000 -2.000000 │\n\
└ ┘";
assert_eq!(format!("{:.6}", usv), usv_correct);Second - 4 x 2 rectangular matrix
// import
use russell_lab::*;
// set matrix
let mut a = Matrix::from(&[
[2.0, 4.0],
[1.0, 3.0],
[0.0, 0.0],
[0.0, 0.0],
]);
// allocate output structures
let (m, n) = a.dims();
let min_mn = if m < n { m } else { n };
let mut s = Vector::new(min_mn);
let mut u = Matrix::new(m, m);
let mut vt = Matrix::new(n, n);
// perform SVD
sv_decomp(&mut s, &mut u, &mut vt, &mut a)?;
// define correct data
let s_correct = "┌ ┐\n\
│ 5.46 │\n\
│ 0.37 │\n\
└ ┘";
let u_correct = "┌ ┐\n\
│ -0.82 -0.58 0.00 0.00 │\n\
│ -0.58 0.82 0.00 0.00 │\n\
│ 0.00 0.00 1.00 0.00 │\n\
│ 0.00 0.00 0.00 1.00 │\n\
└ ┘";
let vt_correct = "┌ ┐\n\
│ -0.40 -0.91 │\n\
│ -0.91 0.40 │\n\
└ ┘";
// check solution
assert_eq!(format!("{:.2}", s), s_correct);
assert_eq!(format!("{:.2}", u), u_correct);
assert_eq!(format!("{:.2}", vt), vt_correct);
// check SVD: a == u * s * vt
let mut usv = Matrix::new(m, n);
for i in 0..m {
for j in 0..n {
for k in 0..min_mn {
usv[i][j] += u[i][k] * s[k] * vt[k][j];
}
}
}
let usv_correct = "┌ ┐\n\
│ 2 4 │\n\
│ 1 3 │\n\
│ 0 0 │\n\
│ 0 0 │\n\
└ ┘";
assert_eq!(format!("{}", usv), usv_correct);