nalgebra/nalgebra-sparse/tests/unit_tests/left_looking_lu.rs
julianknodt 951ec4b190 Implement SparseLU factorization
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
2024-01-13 18:48:26 -08:00

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);
}