Skip to content

Commit

Permalink
Implement Cholesky::solve
Browse files Browse the repository at this point in the history
  • Loading branch information
Andlon committed Feb 18, 2017
1 parent 038f129 commit d243313
Showing 1 changed file with 51 additions and 1 deletion.
52 changes: 51 additions & 1 deletion src/matrix/decomposition/cholesky.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use matrix::{Matrix, BaseMatrix};
use error::{Error, ErrorKind};
use matrix::decomposition::Decomposition;
use matrix::forward_substitution;
use vector::Vector;
use utils::dot;

Expand All @@ -14,7 +15,7 @@ pub struct Cholesky<T> {
l: Matrix<T>
}

impl<T> Cholesky<T> where T: Float {
impl<T> Cholesky<T> where T: 'static + Float {
/// TODO
pub fn decompose(matrix: Matrix<T>) -> Result<Self, Error> {
assert!(matrix.rows() == matrix.cols(),
Expand Down Expand Up @@ -79,6 +80,19 @@ impl<T> Cholesky<T> where T: Float {
.fold(T::one(), |a, b| a * b);
l_det * l_det
}

/// TODO
pub fn solve(&self, b: Vector<T>) -> Vector<T> {
assert!(self.l.rows() == b.size(),
"RHS vector and coefficient matrix must be
dimensionally compatible.");
// Solve Ly = b
let y = forward_substitution(&self.l, b)
.expect("Internal error: L should be invertible.");
// Solve L^T x = y
transpose_back_substitution(&self.l, y)
.expect("Internal error: L^T should be invertible.")
}
}

impl<T: Zero> Decomposition for Cholesky<T> {
Expand Down Expand Up @@ -302,6 +316,42 @@ mod tests {
}
}

#[test]
fn cholesky_solve_examples() {
{
// TODO: Enable this test
// It is currently commented out because
// backward/forward substitution don't handle
// empty matrices. See PR #152 for more details.

// let a: Matrix<f64> = matrix![];
// let b: Vector<f64> = vector![];
// let expected: Vector<f64> = vector![];
// let cholesky = Cholesky::decompose(a).unwrap();
// let x = cholesky.solve(b);
// assert_eq!(x, expected);
}

{
let a = matrix![ 1.0 ];
let b = vector![ 4.0 ];
let expected = vector![ 4.0 ];
let cholesky = Cholesky::decompose(a).unwrap();
let x = cholesky.solve(b);
assert_vector_eq!(x, expected, comp = float);
}

{
let a = matrix![ 4.0, 6.0;
6.0, 25.0];
let b = vector![ 2.0, 4.0];
let expected = vector![ 0.40625, 0.0625 ];
let cholesky = Cholesky::decompose(a).unwrap();
let x = cholesky.solve(b);
assert_vector_eq!(x, expected, comp = float);
}
}

quickcheck! {
fn property_cholesky_of_identity_is_identity(n: usize) -> TestResult {
if n > 30 {
Expand Down

0 comments on commit d243313

Please sign in to comment.