Add `solve_upper_triangular` to `CsrMatrix` This allows a sparse matrix to be used for efficient solving with a dense LU decomposition. Add CscBuilder For partial construction of Csc matrices Start working on actual LU factorization Complete basic version of sparse LU factorization Reformat to compile in old version Add LU tests Add upper triangular solve Complete tests of Sparse LU factorization
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);
|
|
}
|