Cholesky分解

Cholesky分解(Cholesky decomposition) 是矩阵分解的一种。

可记作A = L L*。其中A是正定矩阵。L是下三角矩阵。L*是L的共轭转置矩阵。(共轭不记得啥意思了。)

举例来说:


Cholesky分解_第1张图片

那么我们需要求得的L是:



通过wiki查到了计算公式及其推导。非常简单。

以A为[3,3]大小的矩阵为例。



上面这个Li,j其实很简单,比如i=3,j=1的时候式子就是: L(3,1) = ((A(3,1) - 0) / L(1,1)。其它的类似

计算顺序是先求左上角的那个L11,然后利用L11的值顺序得求出下面一行行的数值。

测试代码如下。测试的矩阵就是上面例子中的矩阵。代码利用了OpenCV

#include "stdio.h"

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;


static void cholesky_decomposition( const Mat& A, Mat& L )
{
	L = Mat::zeros( A.size(), CV_32F );
	int rows = A.rows;

	for( int i = 0; i < rows; ++i )
	{
		int j;
		float sum;

		for(j=0; j < i; ++j)//只求下三角 (i>j)
		{
			sum = 0;
			for(int k=0; k<j; ++k)
			{
				sum += L.at<float>(i,k) * L.at<float>(j,k);
			}
			L.at<float>(i,j) = (A.at<float>(i,j) - sum) / L.at<float>(j,j);
		}
		sum = 0;
		assert(i == j);
		for (int k=0; k<j; ++k)//i == j
		{
			sum += L.at<float>(j,k) * L.at<float>(j,k);
		}
		L.at<float>(j,j) = sqrt(A.at<float>(j,j) - sum);

	}

}

void print_mat(Mat &m)
{
	float sum = 0.;
	for(int r=0; r<m.rows; r++)
	{
		for(int c=0; c<m.cols; c++)
		{
			printf("%.2lf	", m.at<float>(r,c));
			sum += m.at<float>(r,c);
		}
		printf("\n");
	}

	printf("\n");
}

int main(int argc, char* argv[])
{

	float f[4][4] = {
		{16., 4., 4., -4.},
		{4., 10., 4., 2.},
		{4., 4., 6., -2.},
		{-4., 2., -2., 4.},
	};
	Mat A;
	A = Mat(4,4,CV_32F, f);
	printf("Matrix A = \n");
	print_mat(A);
	Mat L;
	cholesky_decomposition(A, L);
	printf("After cholesky decomposition, L = \n");
	print_mat(L);
	Mat p;
	p = L * L.t();
	printf("Confirm: L * L_t = \n");
	print_mat(p);
	

	
	return 0;
}

 




你可能感兴趣的:(Cholesky分解)