76 lines
2.4 KiB
Rust
76 lines
2.4 KiB
Rust
|
use crate::unit_tests::cholesky::positive_definite;
|
||
|
|
||
|
use nalgebra_sparse::factorization::LeftLookingLUFactorization;
|
||
|
|
||
|
use matrixcompare::{assert_matrix_eq, prop_assert_matrix_eq};
|
||
|
use proptest::prelude::*;
|
||
|
|
||
|
use crate::common::value_strategy;
|
||
|
use nalgebra::proptest::matrix;
|
||
|
use nalgebra_sparse::CscMatrix;
|
||
|
|
||
|
proptest! {
|
||
|
// Note that positive definite matrices are guaranteed to be invertible.
|
||
|
// That's why they're used here, but it's not necessary for a matrix to be pd to be
|
||
|
// invertible.
|
||
|
#[test]
|
||
|
fn lu_for_positive_def_matrices(
|
||
|
matrix in positive_definite()
|
||
|
) {
|
||
|
let lu = LeftLookingLUFactorization::new(&matrix);
|
||
|
|
||
|
let l = lu.l();
|
||
|
prop_assert!(l.triplet_iter().all(|(i, j, _)| j <= i));
|
||
|
let u = lu.u();
|
||
|
prop_assert!(u.triplet_iter().all(|(i, j, _)| j >= i));
|
||
|
prop_assert_matrix_eq!(l * u, matrix, comp = abs, tol = 1e-7);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn lu_solve_correct_for_positive_def_matrices(
|
||
|
(matrix, b) in positive_definite()
|
||
|
.prop_flat_map(|csc| {
|
||
|
let rhs = matrix(value_strategy::<f64>(), csc.nrows(), 1);
|
||
|
(Just(csc), rhs)
|
||
|
})
|
||
|
) {
|
||
|
let lu = LeftLookingLUFactorization::new(&matrix);
|
||
|
|
||
|
let l = lu.l();
|
||
|
prop_assert!(l.triplet_iter().all(|(i, j, _)| j <= i));
|
||
|
|
||
|
let mut x_l = b.clone_owned();
|
||
|
l.dense_lower_triangular_solve(b.as_slice(), x_l.as_mut_slice(), true);
|
||
|
|
||
|
prop_assert_matrix_eq!(l * x_l, b, comp=abs, tol=1e-12);
|
||
|
|
||
|
let u = lu.u();
|
||
|
prop_assert!(u.triplet_iter().all(|(i, j, _)| j >= i));
|
||
|
|
||
|
let mut x_u = b.clone_owned();
|
||
|
u.dense_upper_triangular_solve(b.as_slice(), x_u.as_mut_slice());
|
||
|
prop_assert_matrix_eq!(u * x_u, b, comp = abs, tol = 1e-7);
|
||
|
|
||
|
let x = lu.solve(b.as_slice());
|
||
|
prop_assert_matrix_eq!(&matrix * &x, b, comp=abs, tol=1e-12);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn minimized_lu() {
|
||
|
let major_offsets = vec![0, 1, 3, 4, 5, 8];
|
||
|
let minor_indices = vec![0, 1, 4, 2, 3, 1, 2, 4];
|
||
|
let values = vec![1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0, 1.0];
|
||
|
assert_eq!(minor_indices.len(), values.len());
|
||
|
let mat = CscMatrix::try_from_unsorted_csc_data(5, 5, major_offsets, minor_indices, values);
|
||
|
let mat = mat.unwrap();
|
||
|
|
||
|
let lu = LeftLookingLUFactorization::new(&mat);
|
||
|
|
||
|
let l = lu.l();
|
||
|
assert!(l.triplet_iter().all(|(i, j, _)| j <= i));
|
||
|
let u = lu.u();
|
||
|
assert!(u.triplet_iter().all(|(i, j, _)| j >= i));
|
||
|
assert_matrix_eq!(l * u, mat, comp = abs, tol = 1e-7);
|
||
|
}
|