Commit b1e2c6ca authored by Davis King's avatar Davis King

Added QR, LU, cholesky, and eigenvalue decomposition classes.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402845
parent 6309e821
......@@ -8,6 +8,7 @@
#include "matrix/matrix_subexp.h"
#include "matrix/matrix_math_functions.h"
#include "matrix/matrix_assign.h"
#include "matrix/matrix_la.h"
#ifdef DLIB_USE_BLAS
#include "matrix/matrix_blas_bindings.h"
......
// Copyright (C) 2009 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
// This code was adapted from code from the JAMA part of NIST's TNT library.
// See: http://math.nist.gov/tnt/
#ifndef DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H
#define DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H
#include "matrix.h"
#include "matrix_utilities.h"
#include "matrix_subexp.h"
#include <cmath>
namespace dlib
{
template <
typename matrix_exp_type
>
class cholesky_decomposition
{
public:
const static long NR = matrix_exp_type::NR;
const static long NC = matrix_exp_type::NC;
typedef typename matrix_exp_type::type type;
typedef typename matrix_exp_type::mem_manager_type mem_manager_type;
typedef typename matrix_exp_type::layout_type layout_type;
typedef typename matrix_exp_type::matrix_type matrix_type;
typedef matrix<type,NR,1,mem_manager_type,layout_type> column_vector_type;
// You have supplied an invalid type of matrix_exp_type. You have
// to use this object with matrices that contain float or double type data.
COMPILE_TIME_ASSERT((is_same_type<float, type>::value ||
is_same_type<double, type>::value ));
template <typename EXP>
cholesky_decomposition(
const matrix_exp<EXP>& A
);
bool is_spd(
) const;
const matrix_type& get_l(
) const;
template <typename EXP>
const matrix<type,matrix_exp_type::NR,EXP::NC,mem_manager_type,layout_type> solve (
const matrix_exp<EXP>& B
) const;
private:
matrix_type L_; // lower triangular factor
bool isspd; // true if matrix to be factored was SPD
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// Member functions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename matrix_exp_type>
bool cholesky_decomposition<matrix_exp_type>::
is_spd(
) const
{
return isspd;
}
// ----------------------------------------------------------------------------------------
template <typename matrix_exp_type>
const typename cholesky_decomposition<matrix_exp_type>::matrix_type& cholesky_decomposition<matrix_exp_type>::
get_l(
) const
{
return L_;
}
// ----------------------------------------------------------------------------------------
template <typename matrix_exp_type>
template <typename EXP>
cholesky_decomposition<matrix_exp_type>::
cholesky_decomposition(
const matrix_exp<EXP>& A_
)
{
using std::sqrt;
COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value));
// make sure requires clause is not broken
DLIB_ASSERT(A_.nr() == A_.nc() && A_.size() > 0,
"\tcholesky_decomposition::cholesky_decomposition(A_)"
<< "\n\tYou can only use this on square matrices"
<< "\n\tA_.nr(): " << A_.nr()
<< "\n\tA_.nc(): " << A_.nc()
<< "\n\tA_.size(): " << A_.size()
<< "\n\tthis: " << this
);
const_temp_matrix<EXP> A(A_);
isspd = true;
const long n = A.nc();
L_.set_size(n,n);
const type eps = max(abs(diag(A)))*std::sqrt(std::numeric_limits<type>::epsilon())/100;
// Main loop.
for (long j = 0; j < n; j++)
{
type d(0.0);
for (long k = 0; k < j; k++)
{
type s(0.0);
for (long i = 0; i < k; i++)
{
s += L_(k,i)*L_(j,i);
}
// if L_(k,k) != 0
if (std::abs(L_(k,k)) > eps)
{
s = (A(j,k) - s)/L_(k,k);
}
else
{
s = (A(j,k) - s);
isspd = false;
}
L_(j,k) = s;
d = d + s*s;
// this is approximately doing: isspd = isspd && ( A(k,j) == A(j,k))
isspd = isspd && (std::abs(A(k,j) - A(j,k)) < eps );
}
d = A(j,j) - d;
isspd = isspd && (d > eps);
L_(j,j) = sqrt(d > 0.0 ? d : 0.0);
for (long k = j+1; k < n; k++)
{
L_(j,k) = 0.0;
}
}
}
// ----------------------------------------------------------------------------------------
template <typename matrix_exp_type>
template <typename EXP>
const matrix<typename matrix_exp_type::type,
matrix_exp_type::NR,
EXP::NC,
typename matrix_exp_type::mem_manager_type,
typename matrix_exp_type::layout_type> cholesky_decomposition<matrix_exp_type>::
solve(
const matrix_exp<EXP>& B
) const
{
COMPILE_TIME_ASSERT((is_same_type<type, typename EXP::type>::value));
// make sure requires clause is not broken
DLIB_ASSERT(L_.nr() == B.nr(),
"\tconst matrix cholesky_decomposition::solve(B)"
<< "\n\tInvalid arguments were given to this function."
<< "\n\tL_.nr(): " << L_.nr()
<< "\n\tB.nr(): " << B.nr()
<< "\n\tthis: " << this
);
matrix<type, NR, EXP::NC, mem_manager_type, layout_type> X(B);
const long nx = B.nc();
const long n = L_.nr();
// Solve L*y = b;
for (long j=0; j< nx; j++)
{
for (long k = 0; k < n; k++)
{
for (long i = 0; i < k; i++)
X(k,j) -= X(i,j)*L_(k,i);
X(k,j) /= L_(k,k);
}
}
// Solve L'*X = Y;
for (long j=0; j<nx; j++)
{
for (long k = n-1; k >= 0; k--)
{
for (long i = k+1; i < n; i++)
X(k,j) -= X(i,j)*L_(i,k);
X(k,j) /= L_(k,k);
}
}
return X;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H
This diff is collapsed.
// Copyright (C) 2009 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIx_LA_FUNCTS_
#define DLIB_MATRIx_LA_FUNCTS_
#include "matrix_la_abstract.h"
#include "matrix_lu.h"
#include "matrix_qr.h"
#include "matrix_cholesky.h"
#include "matrix_eigenvalue.h"
namespace dlib
{
}
#endif // DLIB_MATRIx_LA_FUNCTS_
This diff is collapsed.
This diff is collapsed.
......@@ -312,6 +312,7 @@ namespace dlib
- R has the same dimensions as m
- for all valid r and c:
R(r,c) == std::norm(m(r,c))
(note that std::norm(val) == val.real()*val.real() + val.imag()*val.imag())
!*/
// ----------------------------------------------------------------------------------------
......
This diff is collapsed.
......@@ -2030,13 +2030,13 @@ convergence:
template <
typename EXP
>
inline const typename matrix_exp<EXP>::matrix_type cholesky_decomposition (
inline const typename matrix_exp<EXP>::matrix_type chol (
const matrix_exp<EXP>& A
)
{
DLIB_ASSERT(A.nr() == A.nc(),
"\tconst matrix cholesky_decomposition(const matrix_exp& A)"
<< "\n\tYou can only apply the cholesky_decomposition to a square matrix"
"\tconst matrix chol(const matrix_exp& A)"
<< "\n\tYou can only apply the chol to a square matrix"
<< "\n\tA.nr(): " << A.nr()
<< "\n\tA.nc(): " << A.nc()
);
......
......@@ -725,7 +725,7 @@ namespace dlib
// ----------------------------------------------------------------------------------------
const matrix_exp::matrix_type cholesky_decomposition (
const matrix_exp::matrix_type chol (
const matrix_exp& A
);
/*!
......
......@@ -44,6 +44,7 @@ set (tests
matrix.cpp
matrix2.cpp
matrix3.cpp
matrix_la.cpp
md5.cpp
member_function_pointer.cpp
metaprogramming.cpp
......
......@@ -608,7 +608,7 @@ namespace
// make m be symmetric
m = m*trans(m);
matrix<double> L = cholesky_decomposition(m);
matrix<double> L = chol(m);
DLIB_CASSERT(equal(L*trans(L), m), "");
DLIB_CASSERT(equal(inv(m), inv_upper_triangular(trans(L))*inv_lower_triangular((L))), "")
......@@ -633,7 +633,7 @@ namespace
// make m be symmetric
m = m*trans(m);
matrix<double> L = cholesky_decomposition(m);
matrix<double> L = chol(m);
DLIB_CASSERT(equal(L*trans(L), m, 1e-10), L*trans(L)-m);
DLIB_CASSERT(equal(inv(m), inv_upper_triangular(trans(L))*inv_lower_triangular((L))), "")
......@@ -667,7 +667,7 @@ namespace
matrix<double,6,6> m(identity_matrix<double>(6)*4.5);
matrix<double> L = cholesky_decomposition(m);
matrix<double> L = chol(m);
DLIB_CASSERT(equal(L*trans(L), m, 1e-10), L*trans(L)-m);
DLIB_CASSERT(equal(inv(m), inv_upper_triangular(trans(L))*inv_lower_triangular((L))), "")
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment