00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <Base/cmtkMathUtil.h>
00034 #include <Base/cmtkMatrix.h>
00035
00036 #include <System/cmtkConsole.h>
00037
00038 #include "Numerics/sevd.h"
00039 #include "Numerics/spddet.h"
00040 #include "Numerics/svd.h"
00041
00042 #include <math.h>
00043 #include <algorithm>
00044 #include <vector>
00045
00046 namespace
00047 cmtk
00048 {
00049
00052
00053 template<class T>
00054 void
00055 MathUtil::ComputeEigensystem
00056 ( const Matrix2D<T>& matrix, Matrix2D<T>& eigenvectors, std::vector<T>& eigenvalues )
00057 {
00058 const size_t n = matrix.GetNumberOfColumns();
00059
00060
00061
00062
00063 ap::real_2d_array apMatrix;
00064 apMatrix.setbounds(0, (int)matrix.GetNumberOfRows(), 0, (int)matrix.GetNumberOfColumns());
00065 for (size_t j = 0; j < n; j++)
00066 for (size_t i = 0; i < n; i++)
00067 apMatrix(i,j) = (double)(1.0 * matrix[i][j]);
00068
00069 ap::real_1d_array apEigenvalues;
00070 apEigenvalues.setbounds(0, eigenvalues.size());
00071 for (size_t i = 0; i < eigenvalues.size(); i++)
00072 apEigenvalues(i) = (double)(1.0 * eigenvalues[i]);
00073
00074
00075 ap::real_2d_array apEigenvectors;
00076 apEigenvectors.setbounds(0, (int)matrix.GetNumberOfRows(), 0, (int)matrix.GetNumberOfColumns());
00077
00078
00079
00080 if ( ! smatrixevd(apMatrix, (int)n, 1, true, apEigenvalues, apEigenvectors) )
00081 {
00082 StdErr << "WARNING: Something went wrong in smatrixevd\n";
00083 }
00084
00085
00086
00087
00088
00089 for (size_t j = 0; j < n; j++)
00090 for (size_t i = 0; i < n; i++)
00091 eigenvectors[i][j] = static_cast<T>( apEigenvectors(i,j) );
00092
00093 for (size_t i = 0; i < eigenvalues.size(); i++)
00094 eigenvalues[i] = static_cast<T>( apEigenvalues(i) );
00095 }
00096
00097 template void MathUtil::ComputeEigensystem<float>( const Matrix2D<float>& matrix, Matrix2D<float>& eigensystem, std::vector<float>& eigenvalues );
00098 template void MathUtil::ComputeEigensystem<double>( const Matrix2D<double>& matrix, Matrix2D<double>& eigensystem, std::vector<double>& eigenvalues );
00099
00100 template<class T>
00101 void
00102 MathUtil::ComputeEigenvalues
00103 ( const Matrix2D<T>& matrix, std::vector<T>& eigenvalues )
00104 {
00105 const size_t n = matrix.GetNumberOfColumns();
00106
00107
00108
00109
00110 ap::real_2d_array apMatrix;
00111 apMatrix.setbounds(0, (int)matrix.GetNumberOfRows(), 0, (int)matrix.GetNumberOfColumns());
00112 for (size_t j = 0; j < n; j++)
00113 for (size_t i = 0; i < n; i++)
00114 apMatrix(i,j) = (double)(1.0 * matrix[i][j]);
00115
00116 ap::real_1d_array apEigenvalues;
00117 apEigenvalues.setbounds(0, eigenvalues.size());
00118 for (size_t i = 0; i < eigenvalues.size(); i++)
00119 apEigenvalues(i) = (double)(1.0 * eigenvalues[i]);
00120
00121 ap::real_2d_array nullArray;
00122
00123
00124
00125 if ( !smatrixevd(apMatrix, (int)n, 0, true, apEigenvalues, nullArray) )
00126 {
00127 StdErr << "WARNING: Something went wrong in smatrixevd\n";
00128 }
00129
00130
00131
00132
00133
00134 for (size_t i = 0; i < n; i++)
00135 for (size_t j = 0; j < n; j++)
00136 matrix[i][j] = static_cast<T>( apMatrix(i,j) );
00137
00138 for (size_t i = 0; i < eigenvalues.size(); i++)
00139 eigenvalues[i] = static_cast<T>( apEigenvalues(i) );
00140 }
00141
00142 template void MathUtil::ComputeEigenvalues<float>( const Matrix2D<float>& matrix, std::vector<float>& eigenvalues );
00143 template void MathUtil::ComputeEigenvalues<double>( const Matrix2D<double>& matrix, std::vector<double>& eigenvalues );
00144
00145 void
00146 MathUtil::SVD( Matrix2D<double> *U, size_t m, size_t n, std::vector<double> *W, Matrix2D<double> *V )
00147 {
00148 ap::real_2d_array apA;
00149 apA.setbounds(0, m-1, 0, n-1);
00150 for (size_t j = 0; j < n; j++)
00151 for (size_t i = 0; i < m; i++)
00152 apA(i,j) = (double) (*U)[i][j];
00153
00154 ap::real_1d_array w;
00155 ap::real_2d_array u;
00156 ap::real_2d_array vt;
00157
00158 rmatrixsvd( apA, m, n,
00159 true ,
00160 true ,
00161 2 ,
00162 w, u, vt);
00163
00164
00165 for (size_t j = 0; j < n; j++)
00166 for (size_t i = 0; i < m; i++)
00167 (*U)[i][j] = u(i,j);
00168
00169
00170 for (size_t i = 0; i < n; i++)
00171 (*W)[i] = w(i);
00172
00173
00174 for (size_t j = 0; j < n; j++)
00175 for (size_t i = 0; i < n; i++)
00176 (*V)[i][j] = vt(j,i);
00177
00178 }
00179
00182 void
00183 MathUtil::SVDLinearRegression( Matrix2D<double> *U, size_t m, size_t n, std::vector<double> *W, Matrix2D<double> *V, double *b, std::vector<double>& lm_params )
00184 {
00185
00186
00187
00188 double epstol = 1000;
00189 ap::real_1d_array svi;
00190 svi.setbounds( 0, n-1 );
00191 for( size_t i = 0; i < n; i++ )
00192 if( (*W)[i] > epstol*ap::machineepsilon * (*W)[0] )
00193 svi(i) = 1 / (*W)[i];
00194 else
00195 svi(i) = 0;
00196
00197
00198
00199 for ( size_t i = 0; i < n; i++ )
00200 lm_params[i] = 0.0;
00201 double ut_times_b;
00202
00203 for ( size_t i = 0; i < n; i++ )
00204 {
00205 ut_times_b = 0.0;
00206 for ( size_t j = 0; j < m; j++ )
00207 ut_times_b += (*U)[j][i] * b[j];
00208 ut_times_b *= svi(i);
00209 for ( size_t j = 0; j < n; j++ )
00210 lm_params[j] += ut_times_b * (*V)[j][i];
00211 }
00212 }
00213
00215
00217
00218 template<class T>
00219 T
00220 MathUtil::CholeskyDeterminant
00221 (const Matrix2D<T>& matrix, int n)
00222 {
00223 ap::real_2d_array apMatrix;
00224 apMatrix.setbounds(0, n-1, 0, n-1);
00225 for (int j = 0; j < n; j++)
00226 for (int i = 0; i < n; i++)
00227 apMatrix(i,j) = (double)(1.0 * matrix[i][j]);
00228 spdmatrixcholesky( apMatrix, n, false );
00229 T determinant = (T) spdmatrixcholeskydet( apMatrix, n );
00230 return determinant;
00231 }
00232
00233 template double MathUtil::CholeskyDeterminant<double>(const Matrix2D<double>& matrix, int n);
00234 template float MathUtil::CholeskyDeterminant<float>(const Matrix2D<float>& matrix, int n);
00235
00236 }
00237