Commit fde49f246b2dbed746bddfad3212797d1697d511

Authored by David Mayerich
1 parent 89676102

integrated Rupali's changes - replaced OpenCV matrix math with LAPACK

Showing 1 changed file with 67 additions and 25 deletions   Show diff stats
@@ -50,6 +50,43 @@ typedef struct { @@ -50,6 +50,43 @@ typedef struct {
50 }gnome; 50 }gnome;
51 gnome gnom; 51 gnome gnom;
52 52
  53 +//computing matrix determinant using LU decomposition
  54 +template<typename T>
  55 +T mtxdeterminant(T* M, size_t r, size_t c) {
  56 + //----DETERMINANT using LU decomposition using LAPACK
  57 + /* DGETRF computes an LU factorization of a general M-by-N matrix A using partial pivoting with row interchanges.
  58 + The factorization has the form
  59 + A = P * L * U
  60 + where P is a permutation matrix, L is lower triangular with unit diagonal elements (lower trapezoidal if m > n), and U is upper triangular (upper trapezoidal if m < n).*/
  61 + int* ipiv = (int*)malloc(sizeof(int) * r);
  62 + memset(ipiv, 0, r * sizeof(int));
  63 + LAPACKE_sgetrf(LAPACK_COL_MAJOR, (int)r, (int)c, M, (int)r, ipiv);
  64 +
  65 + //determinant of U
  66 + T product = 1;
  67 + for (size_t i = 0; i < r; i++) {
  68 + for (size_t j = 0; j < r; j++) {
  69 + if (i == j) {
  70 + product = product * M[i * r + j];
  71 + }
  72 + }
  73 + }
  74 +
  75 + //determinant of P
  76 + int j;
  77 + double detp = 1.;
  78 + for (j = 0; j < r; j++) {
  79 + if (j + 1 != ipiv[j]) {
  80 + // j+1 : following feedback of ead : ipiv is from Fortran, hence starts at 1.
  81 + // hey ! This is a transpose !
  82 + detp = -detp;
  83 + }
  84 + }
  85 + T detSw = product * detp * 1; //det(U)*det(P)*det(L)
  86 + if (ipiv != NULL) std::free(ipiv);
  87 + return detSw;
  88 +
  89 +}
53 90
54 void gpuComputeEignS( size_t g, size_t fea){ 91 void gpuComputeEignS( size_t g, size_t fea){
55 //eigen value computation will return r = (nC-1) eigen vectors so new projected data will have dimension of r rather than f 92 //eigen value computation will return r = (nC-1) eigen vectors so new projected data will have dimension of r rather than f
@@ -87,7 +124,7 @@ void gpuComputeEignS( size_t g, size_t fea){ @@ -87,7 +124,7 @@ void gpuComputeEignS( size_t g, size_t fea){
87 int *IPIV = (int*) malloc(sizeof(int) * f); 124 int *IPIV = (int*) malloc(sizeof(int) * f);
88 //computing inverse of matrix Sw 125 //computing inverse of matrix Sw
89 memset(IPIV, 0, f * sizeof(int)); 126 memset(IPIV, 0, f * sizeof(int));
90 - LAPACKE_sgetrf(LAPACK_COL_MAJOR, (int)f, (int)f, gSw_a, (int)f, IPIV); 127 + LAPACKE_sgetrf(LAPACK_COL_MAJOR, (int)f, (int)f, gSw_a, (int)f, IPIV);
91 // DGETRI computes the inverse of a matrix using the LU factorization computed by DGETRF. 128 // DGETRI computes the inverse of a matrix using the LU factorization computed by DGETRF.
92 LAPACKE_sgetri(LAPACK_COL_MAJOR, (int)f, gSw_a, (int)f, IPIV); 129 LAPACKE_sgetri(LAPACK_COL_MAJOR, (int)f, gSw_a, (int)f, IPIV);
93 130
@@ -146,23 +183,22 @@ void gpuComputeEignS( size_t g, size_t fea){ @@ -146,23 +183,22 @@ void gpuComputeEignS( size_t g, size_t fea){
146 mtxMul(tempgSw, &gnom.lda[g * r * f], &gnom.Sw[g * f * f], r, f, f,f); 183 mtxMul(tempgSw, &gnom.lda[g * r * f], &gnom.Sw[g * f * f], r, f, f,f);
147 float* nSw = (float*)calloc(r * r, sizeof(float)); 184 float* nSw = (float*)calloc(r * r, sizeof(float));
148 mtxMultranspose(nSw, tempgSw, &gnom.lda[g * r * f], r, f, r, f); 185 mtxMultranspose(nSw, tempgSw, &gnom.lda[g * r * f], r, f, r, f);
149 - if(debug){  
150 - std::cout<<"From Eigen function: projected Sb sn Sw"<<std::endl; 186 +
  187 + //determinant of Sb and Sw
  188 + float detSw = mtxdeterminant(nSw, r, r);
  189 + float detSb = mtxdeterminant(nSb, r, r);
  190 +
  191 + if (debug) {
  192 + std::cout << "From Eigen function: projected Sb sn Sw" << std::endl;
151 displayS(nSb, r); //display Sb 193 displayS(nSb, r); //display Sb
152 displayS(nSw, r); //display Sw 194 displayS(nSw, r); //display Sw
153 - std::cout<<std::endl; 195 + std::cout << std::endl;
  196 + std::cout <<"det(Sb)= "<< detSb<< std::endl;
  197 + std::cout << "det(Sw)= " << detSw << std::endl;
154 } 198 }
155 199
156 - ///DETERMINANT CURRENTLY REQUIRES OPENCV  
157 - std::cout<<"ERROR: This code requires a fix to remove an OpenCV dependence."<<std::endl;  
158 - mtxOutputFile("newSw.csv", nSw, r, r);  
159 - exit(1);  
160 - //FIX BY REPLACING THE FOLLOWING THREE LINES OF CODE USING LAPACK  
161 - //cv::Mat newSw = cv::Mat((int)r, (int)r, CV_32FC1, nSw); //within scatter of gnome g in the population  
162 - //cv::Mat newSb = cv::Mat((int)r, (int)r, CV_32FC1, nSb); //within scatter of gnome g in the population  
163 -  
164 //fisher's ratio from ratio of projected sb and sw 200 //fisher's ratio from ratio of projected sb and sw
165 - float fisherRatio = 0;// = cv::determinant(newSb) /cv::determinant(newSw); 201 + float fisherRatio = detSb /detSw;
166 gnom.S[g] = 1/fisherRatio; 202 gnom.S[g] = 1/fisherRatio;
167 if (debug) { 203 if (debug) {
168 std::cout<<"Score["<<g<<"]: "<< gnom.S[g]<<std::endl; 204 std::cout<<"Score["<<g<<"]: "<< gnom.S[g]<<std::endl;
@@ -172,6 +208,7 @@ void gpuComputeEignS( size_t g, size_t fea){ @@ -172,6 +208,7 @@ void gpuComputeEignS( size_t g, size_t fea){
172 std::cout << ga.P[ga.f * g + i] << ", "; 208 std::cout << ga.P[ga.f * g + i] << ", ";
173 std::cout << std::endl; 209 std::cout << std::endl;
174 } 210 }
  211 +
175 212
176 213
177 if(IPIV!= NULL) std::free(IPIV); 214 if(IPIV!= NULL) std::free(IPIV);
@@ -430,27 +467,30 @@ int main(int argc, char* argv[]){ @@ -430,27 +467,30 @@ int main(int argc, char* argv[]){
430 467
431 468
432 //fitness values of best gnome is 469 //fitness values of best gnome is
433 - csv<<"best gnome's fitness value is "<<best_S[ga.gnrtn-1]<<std::endl; //output fitness value of best gnome in last generation  
434 - //output gnome i.e. band index of selected featurs 470 + csv<<"fitness value for best gnome: "<<best_S[ga.gnrtn-1]<<std::endl; //output fitness value of best gnome in last generation
  471 + /*//output gnome i.e. band index of selected featurs
435 csv<<(bestgnome.at(0)); //output feature subset 472 csv<<(bestgnome.at(0)); //output feature subset
436 for(size_t i = 1; i < ga.f; i++) 473 for(size_t i = 1; i < ga.f; i++)
437 csv<<","<<(bestgnome.at(i)); 474 csv<<","<<(bestgnome.at(i));
438 - csv<<std::endl; 475 + csv<<std::endl;*/
439 476
440 - //output LDA basis of size r X f, r is nC - 1 as LDA projection is rank limited by number of classes - 1  
441 - for (size_t i = 0; i < nC-1; i++){  
442 - csv<<lda[ldaindx + i * ga.f ];  
443 - for (size_t j = 1; j < ga.f; j++){  
444 - csv<<","<<lda[ldaindx + i * ga.f +j];  
445 - }  
446 - csv << std::endl;  
447 - }  
448 //output actual wavelenths corresponding to those band indices 477 //output actual wavelenths corresponding to those band indices
  478 + csv << "selected wavenumbers:"<<std::endl;
449 csv << (wavelengths[bestgnome.at(0)]); 479 csv << (wavelengths[bestgnome.at(0)]);
450 for (size_t i = 1; i < ga.f; i++) 480 for (size_t i = 1; i < ga.f; i++)
451 - csv << "," << (wavelengths[bestgnome.at(i)]); 481 + csv << ", " << (wavelengths[bestgnome.at(i)]);
452 csv << std::endl; 482 csv << std::endl;
453 483
  484 + //output LDA basis of size r X f, r is nC - 1 as LDA projection is rank limited by number of classes - 1
  485 + csv << "LDA basis:" << std::endl;
  486 + for (size_t i = 0; i < nC - 1; i++) {
  487 + csv << lda[ldaindx + i * ga.f];
  488 + for (size_t j = 1; j < ga.f; j++) {
  489 + csv << ", " << lda[ldaindx + i * ga.f + j];
  490 + }
  491 + csv << std::endl;
  492 + }
  493 +
454 494
455 if (args["trim"].is_set()) { 495 if (args["trim"].is_set()) {
456 csv << "trim info" << std::endl; 496 csv << "trim info" << std::endl;
@@ -489,6 +529,8 @@ int main(int argc, char* argv[]){ @@ -489,6 +529,8 @@ int main(int argc, char* argv[]){
489 ////output actual wavelenths corresponding to those trim indices 529 ////output actual wavelenths corresponding to those trim indices
490 ////these wavenumber are grouped in pairs, check each pair, if duplicated numbers are there in pair delete one and keep other as band to trim, if 2nd wavnumber is smaller than 1st in a pair ignore that pair 530 ////these wavenumber are grouped in pairs, check each pair, if duplicated numbers are there in pair delete one and keep other as band to trim, if 2nd wavnumber is smaller than 1st in a pair ignore that pair
491 ////e.g [1, 228, 230, 230, 232, 350,352, 351, 353, 1200] pairas [1(start)-228,230-230, 232-350, 352-351, 353-1200(end)], trimming wavenumbers are [1-228, 230, 233-350, 353-1200] 531 ////e.g [1, 228, 230, 230, 232, 350,352, 351, 353, 1200] pairas [1(start)-228,230-230, 232-350, 352-351, 353-1200(end)], trimming wavenumbers are [1-228, 230, 233-350, 353-1200]
  532 +
  533 +
492 csv << (wavelengths[finaltrim_ind.at(0)]); 534 csv << (wavelengths[finaltrim_ind.at(0)]);
493 for (size_t i = 1; i < ga.f * + 2 ; i++) 535 for (size_t i = 1; i < ga.f * + 2 ; i++)
494 csv << "," << (wavelengths[finaltrim_ind.at(i)]); 536 csv << "," << (wavelengths[finaltrim_ind.at(i)]);