Home > gmmbayestb-v1.0 > gmmb_covfixer.m

gmmb_covfixer

PURPOSE ^

GMMB_COVFIXER - force matrix to be a valid covariance matrix

SYNOPSIS ^

function [nsigma, varargout] = gmmb_covfixer(sigma);

DESCRIPTION ^

GMMB_COVFIXER   - force matrix to be a valid covariance matrix

 covmatrix = GMMB_COVFIXER(matrix)
 Matrix is forced (complex conjugate) symmetric,
 positive definite and its diagonal real valued.

 [covmatrix, loops] = GMMB_COVFIXER(...)
    loops - number of rounds the positive definite fixer had to run.

 [covmatrix, loops, symerr] = GMMB_COVFIXER(...)
    symerr - symmetry error matrix

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 %GMMB_COVFIXER   - force matrix to be a valid covariance matrix
0002 %
0003 % covmatrix = GMMB_COVFIXER(matrix)
0004 % Matrix is forced (complex conjugate) symmetric,
0005 % positive definite and its diagonal real valued.
0006 %
0007 % [covmatrix, loops] = GMMB_COVFIXER(...)
0008 %    loops - number of rounds the positive definite fixer had to run.
0009 %
0010 % [covmatrix, loops, symerr] = GMMB_COVFIXER(...)
0011 %    symerr - symmetry error matrix
0012 
0013 %
0014 % $Name:  $
0015 % $Id: gmmb_covfixer.m,v 1.2 2004/11/02 09:00:18 paalanen Exp $
0016 % Copyright 2003, Pekka Paalanen <pekka.paalanen@lut.fi>
0017 
0018 % except isspd() function which is from The MathWorks Matlab mvnpdf.m.
0019 
0020 function [nsigma, varargout] = gmmb_covfixer(sigma);
0021 
0022 D = size(sigma, 1);
0023 fixrate = 0.01;
0024 covfixmat = ones(D) + fixrate*eye(D);
0025 loops = 0;
0026 min_limit = eps*10;
0027 
0028 if ~all( isfinite(sigma(:))  )
0029     error('covariance matrix is not finite');
0030 end
0031 
0032 % Running imagfixer is not counted as covariance fixing,
0033 % the changes are assumed to be so small.
0034 nsigma = imagfixer(sigma);
0035 
0036 if nargout>2
0037     varargout(2) = {(sigma-nsigma)};
0038 end
0039 
0040 while isspd(nsigma) == 0
0041     % covariance matrix is not positive definite
0042     % fix it
0043     loops  = loops+1;
0044     d = diag(nsigma);
0045     if any(d <= min_limit)
0046         % negative or zero (<eps) on the diagonal
0047         m = max(abs(d)) * fixrate;
0048         neg = min(d);
0049         if neg < 0
0050             % there is a negative component on the diagonal
0051             % get rid of it.
0052             addit = (m-neg)*eye(D);
0053         else
0054             if m < min_limit
0055                 m = min_limit;
0056             end
0057             addit = m*eye(D);
0058         end
0059         nsigma = nsigma + addit;
0060     else
0061         % increase diagonal values by 1 percent
0062         nsigma = nsigma .* covfixmat;
0063     end
0064 end
0065 
0066 if nargout>1
0067     varargout(1) = {loops};
0068 end
0069 
0070 
0071 % ------------------
0072 
0073 function [t,R] = isspd(Sigma)
0074 %ISPDS Test if a matrix is positive definite symmetric
0075 % T = ISPDS(SIGMA) returns a logical indicating whether the matrix SIGMA is
0076 % square, symmetric, and positive definite, i.e., it is a valid full rank
0077 % covariance matrix.
0078 %
0079 % [T,R] = ISPDS(SIGMA) returns the cholesky factor of SIGMA in R.  If SIGMA
0080 % is not square symmetric, ISPDS returns [] in R.
0081 
0082 %   Copyright 1993-2002 The MathWorks, Inc.
0083 %   Revision: 1.2   Date: 2002/03/28 16:51:27
0084 
0085 % Test for square, symmetric
0086 % NOTE: imagfixer already enforces squareness and symmetricity,
0087 % and fixing affects only the diagonal, so this is not necessary
0088 %[n,m] = size(Sigma);
0089 %if (n == m) & all(all(abs(Sigma - Sigma') < 10*eps*max(abs(diag(Sigma)))));
0090 
0091     % Test for positive definiteness
0092     [R,p] = chol(Sigma);
0093     if p == 0
0094         t = 1;
0095     else
0096         t = 0;
0097     end
0098 
0099 %else
0100 %    R = [];
0101 %    t = 0;
0102 %end
0103 
0104 % ------------------
0105 
0106 function nsigma = imagfixer(sigma);
0107 
0108 % force symmetric
0109 nsigma = sigma - (sigma - sigma')/2;
0110 % purge imag
0111 purge = imag(diag(nsigma));
0112 nsigma = nsigma - diag(purge)*1i;
0113 
0114 if max(purge) > 1e-4
0115     warning_wrap('gmmbayes:covfixer:imagfixer', 'Quite big imaginary components removed from the diagonal');
0116 end

Generated on Thu 14-Apr-2005 13:50:22 by m2html © 2003