⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mat.cpp

📁 这是个人脸识别程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			*pSmallestPivot = fabs(LU(i,i));	}if (0 != (iRet = gsl_linalg_LU_solve(LU.m, pPerm, &bVec.vector, xVec)))	SysErr("LUSolve gsl_linalg_LU_solve returned %d", iRet);Vec x(xVec->data, nrows);	// convert gsl_vector to Vecgsl_vector_free(xVec);*ppPerm = pPerm;return x;}//-----------------------------------------------------------------------------// Same as above but with no LU or Perm params// pSmallestPivot can be NULL, as aboveVec SolveWithLU (const Mat &A, Vec &b, double *pSmallestPivot){#if GSL_RANGE_CHECKCheckIsVector(b, "SolveWithLU b");if (A.nrows() != b.nelems())	SysErr("LUSolve b %dx%d doesn't conform to A %dx%d",		b.nrows(), b.ncols(), A.nrows(), A.ncols());#endifint	Sign, iRet, nrows = A.nrows();gsl_permutation *pPerm = gsl_permutation_alloc(nrows);gsl_vector 		*xVec  = gsl_vector_alloc(nrows);gsl_vector_view  bVec  = gsl_vector_view_array(b.m->data, nrows);gsl_matrix		*pLU   = gsl_matrix_alloc(nrows, A.ncols());gsl_matrix_memcpy(pLU, A.m);	// use copy not view because decomp destroys Aif (0 != (iRet = gsl_linalg_LU_decomp(pLU, pPerm, &Sign)))	SysErr("LUSolve gsl_linalg_LU_decomp returned %d", iRet);if (pSmallestPivot)		// find and store the smallest pivot?	{	*pSmallestPivot = GSL_POSINF;	for (int i = A.nrows()-1; i >= 0; i--)	// smallest last so reduce nbr assignments		if (fabs(gsl_matrix_get(pLU, i, i)) < *pSmallestPivot)			*pSmallestPivot = fabs(gsl_matrix_get(pLU, i, i));	}if (0 != (iRet = gsl_linalg_LU_solve(pLU, pPerm, &bVec.vector, xVec)))	SysErr("LUSolve gsl_linalg_LU_solve returned %d", iRet);Vec x(xVec->data, nrows);	// convert gsl_vector to Vecgsl_permutation_free(pPerm);gsl_vector_free(xVec);gsl_matrix_free(pLU);return x;}//-----------------------------------------------------------------------------// Like LUsolve but A must already be in LU form and pPerm must be initialized// by a previous call to LUsolve.//// Calling this instead of LUSolve again is faster.Vec SolveWithLUAgain (Mat &LU, Vec &b, gsl_permutation *pPerm){#if GSL_RANGE_CHECKCheckIsVector(b, "SolveWithLUAgain b");if (LU.nrows() != b.nelems())	SysErr("LUSolveAgain b %dx%d doesn't conform to LU %dx%d",		b.nrows(), b.ncols(), LU.nrows(), LU.ncols());#endifint	iRet, nrows = LU.nrows();gsl_vector *xVec = gsl_vector_alloc(nrows);gsl_vector_view  bVec = gsl_vector_view_array(b.m->data, nrows);if (0 != (iRet = gsl_linalg_LU_solve(LU.m, pPerm, &bVec.vector, xVec)))	SysErr("LUSolveAgain gsl_linalg_LU_solve returned %d", iRet);Vec x(xVec->data, nrows);	// convert gsl_vector to Vecgsl_vector_free(xVec);return x;}//-----------------------------------------------------------------------------// A is not changedVec RefineLU (Mat &A, Mat &LU, gsl_permutation *pPerm, Vec &x, Vec &b){int	iRet, nrows = A.nrows();#if GSL_RANGE_CHECKif (!b.fVector())	SysErr("LURefine b %dx%d is not a vector", b.nrows(), b.ncols());if (LU.nrows() != nrows || LU.ncols() != A.ncols())	SysErr("LURefine A %dx%d EA %dx%d incompatible",		nrows, A.ncols(), LU.nrows(), LU.ncols());if (b.nrows() != nrows && b.ncols() != nrows)	SysErr("LURefine neither b size %d %d != A.nrows %d", b.nrows(), b.ncols(), nrows);if (pPerm->size != nrows)	SysErr("LURefine pPerm->size %d != A.nrows %d", pPerm->size, nrows);#endifgsl_vector_view bVec = gsl_vector_view_array(b.m->data, nrows);gsl_vector_view xVec = gsl_vector_view_array(x.m->data, nrows);gsl_vector *resVec = gsl_vector_alloc(nrows);if (0 != (iRet = gsl_linalg_LU_refine(A.m, LU.m, pPerm, &bVec.vector, &xVec.vector, resVec)))	SysErr("LURefine gsl_linalg_LU_refine returned %d", iRet);gsl_vector_free(resVec);return x;}//-----------------------------------------------------------------------------// This destroys A, or rather puts U into Avoid SingularValDecomp (Mat &A, 		// io			Mat &VTranspose, Vec &S)	// out{int iRet;if (A.M() < A.N())	// check against GSL library limitation	SysErr("SingularValDecomp: m < n not yet implemented A %dx%d", A.M(), A.N());// if (A.N() == 1)		// check against GSL 1.4 library limitation, fixed in GSL 1.6//	SysErr("SingularValDecomp: n == 1 not yet implemented A %dx%d", A.M(), A.N());gsl_vector_view DVec = gsl_vector_view_array(S.m->data, A.N());gsl_vector *W = gsl_vector_alloc(A.N());			// working vectorif (A.M() < (5 * A.N()) / 3)	// Golub & vanLoan p253 tells us the fastest SVD func to use	{	if (0 != (iRet = gsl_linalg_SV_decomp(A.m, VTranspose.m, &DVec.vector, W)))		SysErr("SingularValDecomp gsl_linalg_SV_decomp returned %d", iRet);	}else	{	gsl_matrix *X = gsl_matrix_alloc(A.N(), A.N());		// working matrix	if (0 != (iRet = gsl_linalg_SV_decomp_mod(A.m, X, VTranspose.m, &DVec.vector, W)))		SysErr("SingularValDecomp gsl_linalg_SV_decomp_mod returned %d", iRet);	gsl_matrix_free(X);	}gsl_vector_free(W);}//-----------------------------------------------------------------------------// Solves Ax=b for x and returns x.// A gets destroyed (actually it gets changed to the U in UDV).//// This returns the best answer in a least squares sense if no exact solution exists// i.e if b is not in the column space of A or A is not invertible.Vec SolveWithSVD (Mat &A, const Vec &b, bool fVerbose){if (fVerbose)	lprintf("SolveWithSVD %dx%d        ", A.nrows(), A.ncols());int iRet;Mat VTrans(A.N(), A.N());Vec S(A.N());Vec x(A.M());SingularValDecomp(A, VTrans, S);gsl_vector_view SVec = gsl_vector_view_array(S.m->data, A.N());gsl_vector_view bVec = gsl_vector_view_array(b.m->data, A.M());gsl_vector_view xVec = gsl_vector_view_array(x.m->data, A.M());iRet = gsl_linalg_SV_solve(A.m, VTrans.m, &SVec.vector, &bVec.vector, &xVec.vector);DASSERT(iRet == 0);return x;}//-----------------------------------------------------------------------------// returns true if the diag elements of square matrix A are strictly positivestatic bool fStrictlyPositiveDiag (Mat &A){for (int i = 0; i < A.nrows(); i++)	if (A(i,i) <= 0)		return false;return true;}//-----------------------------------------------------------------------------// Solves Ax=b for x and returns x.  Destroys A.// This routine silently sets pfPosDef to false and immediately returns// if A is not symmetric positive definite and it can't be solved by Cholesky.Vec SolveWithCholesky (Mat &A, const Vec &b, bool fVerbose, bool *pfPosDef){Vec x(A.nrows());*pfPosDef = false;	// assumeif (0 == gsl_linalg_cholesky_decomp_return_on_EDOM(A.m))	{	int iRet;	if (fVerbose)		lprintf("SolveWithCholesky %dx%d   ", A.nrows(), A.ncols());	gsl_vector_view bVec = gsl_vector_view_array(b.m->data, A.M());	gsl_vector_view xVec = gsl_vector_view_array(x.m->data, A.M());	if (0 != (iRet = gsl_linalg_cholesky_solve(A.m, &bVec.vector, &xVec.vector)))		SysErr("SolveWithCholesky gsl_linalg_cholesky_solve returned %d", iRet);	*pfPosDef = true;	}return x;}//-----------------------------------------------------------------------------// Return true if A is positive definitebool fPosDef (const Mat &A){Mat ACopy(A); 	// SolveWithCholesky destroys A, so make a copyVec b(A.nrows());bool fPosDef;SolveWithCholesky(ACopy, b, false, &fPosDef);return fPosDef;}//-----------------------------------------------------------------------------// Like fPosDef() but uses the eig val method, and allows up to nAllowedZeroEigs eigs to near 0.// Much slower than fPosDef() because has to find the eigs of A.bool fPosDef1 (const Mat &A, int nAllowedZeroEigs){int nelems = A.nrows();Vec EigVals(nelems);double Min = EigVals(0) / 1e6;GetEigsForSymMat(A, EigVals, true, true);for (int i = 0; i < nelems - nAllowedZeroEigs; i++)	if (EigVals(i) <= Min)		return false;return true;}//-----------------------------------------------------------------------------// Returns a matrix of eigenvectors for the symmetric matrix A.// Eigenvectors not normalized. Also returns the eigen vals in EigenVals.// If fSort is set, then eigenvecs and eigenvals are sorted, largest eigenval first.// A must be a symmetric matrix. If fTestForSymmetry then SysErr if A not symmetric.// A is not modifiedMat GetEigsForSymMat (const Mat &A, Vec &EigVals, bool fSort, bool fTestForSymmetry){int iRet;// some preliminary checks, GSL funcs will do moreDASSERT(A.nrows() == A.ncols());DASSERT(EigVals.nrows() == A.nrows());if (fTestForSymmetry && !fIsMatrixSymmetric(A, A(0,0) / 1e5))		//TODO magic 1e5 chosen based for ASM model building, make it a parameter?	{	//A.print("\nNon symmetric matrix\n", "%16.6g ");	SysErr("GetEigsForSymMat matrix %dx%d not symmetric", A.nrows(), A.ncols());	}Mat EigVecs(A.ncols(), A.ncols());Mat Work(A);		// gsl_eigen_symmv() destoys the A->m.data, so we use a temporary variablegsl_eigen_symmv_workspace *W = gsl_eigen_symmv_alloc(Work.ncols());gsl_vector_view EigValsVec = gsl_vector_view_array(EigVals.m->data, EigVals.nrows());if (0 != (iRet = gsl_eigen_symmv(Work.m, &EigValsVec.vector, EigVecs.m, W)))	SysErr("GetEigsForSymMat matrix %dx%d gsl_eigen_symmv returned %d", Work.nrows(), Work.ncols(), iRet);gsl_eigen_symmv_free(W);// if asked to, sort the eigenvalues and corresponding eigenvectorsif (fSort && 0 != (iRet =		gsl_eigen_symmv_sort(&EigValsVec.vector, EigVecs.m, GSL_EIGEN_SORT_VAL_DESC)))	{	SysErr("GetEigsForSymMat matrix %dx%d gsl_eigen_symmv_sort returned %d", Work.nrows(), Work.ncols(), iRet);	}return EigVecs;}//-----------------------------------------------------------------------------Mat NormalizeCols (const Mat &A)	// returns the mat but with cols normalized (length 1){for (int iCol = 0; iCol < A.ncols(); iCol++)	{	MatView col = A.col(iCol);	double norm = col.len();	col /= norm;	}return A;}//-----------------------------------------------------------------------------Mat HilbertMat (size_t n)		// returns a hilbert mat of the given size{Mat result(n, n);for (int iRow = 0; iRow < n; iRow++)	for (int iCol = 0; iCol < n; iCol++)		gsl_matrix_set(result.m, iRow, iCol, 1.0 / (iRow + iCol + 1.0));return result;}//-----------------------------------------------------------------------------Mat IdentMat (size_t n)		// returns an identity mat of the given size{Mat result(n, n);result.diagMe(1);return result;}//-----------------------------------------------------------------------------Vec AllOnesMat (size_t n, const char *sIsRowVec)	// returns an all ones mat of the given size{Vec result(n, sIsRowVec);result.fill(1);return result;}//-----------------------------------------------------------------------------// This returns x * A * x.// x is a vector.// A is assumed to be a symmetric matrix (but only the upper right triangle of A is actually used).//// This function is equivalent to OneElemToDouble(x * A * x.t()), but is// optimized for speed and is much faster.//// It's faster because we use the fact that A is symmetric to roughly// halve the number of operations.// We also bypass the overhead of normal matrix routines, which can be slow.double xAx (const Vec &x, const Mat &A){double xTemp[MAX_TEMP_ARRAY_LEN];	// copy x into here because it's faster accessing an array than a Vecconst int nelems = x.nelems();ASSERT(nelems < MAX_TEMP_ARRAY_LEN);DASSERT(A.nrows() == nelems);DASSERT(A.ncols() == nelems);DASSERT(x.nrows() == 1);double DiagResult = 0, Result = 0;// init xTemp and sum diag elementsfor (int i = 0; i < nelems; i++)	{	xTemp[i] = x(i);	DiagResult += A(i, i) * xTemp[i] * xTemp[i];	}// sum upper right triangle elemsfor (i = 0; i < nelems; i++)	{	double xi = xTemp[i];	for (int j = i+1; j < nelems; j++)		Result += A(i, j) * xi * xTemp[j];	}Result *= 2;						// incorporate lower left triangle elementsreturn DiagResult + Result;}//-----------------------------------------------------------------------------// This function is like DASSERT(A == A.t()) but tells you where the difference is, if any// It's also quicker than testig A == A.t().bool fIsMatrixSymmetric (const Mat &A, double Min){bool fExact = (Min == 0.0);if (A.nrows() != A.ncols())	{	lprintf("\nMatrix not square\n");	return false;	}for (int iRow = 0; iRow < A.nrows(); iRow++)	for (int iCol = iRow+1; iCol < A.ncols(); iCol++)		if ((fExact && A(iRow, iCol) != A(iCol, iRow)) ||		   (!fExact && !fEqual(A(iRow, iCol), A(iCol, iRow), Min)))			{			lprintf("\nMatrix not symmetric: A(%d,%d)=%.12g != A(%d,%d)=%.12g\n", iRow, iCol, A(iRow, iCol), iCol, iRow, A(iCol, iRow));			//TODO PrintMat(A);			return false;			}return true;}//-----------------------------------------------------------------------------double SumElems (const Mat &m){double sum = 0;for (int iRow = 0; iRow < m.nrows(); iRow++)	for (int iCol = 0; iCol < m.ncols(); iCol++)		sum += m(iRow, iCol);return sum;}//-----------------------------------------------------------------------------double AbsSumElems (const Mat &m){double sum = 0;for (int iRow = 0; iRow < m.nrows(); iRow++)	for (int iCol = 0; iCol < m.ncols(); iCol++)		sum += fabs(m(iRow, iCol));return sum;}}	// end namespace GslMat

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -