matrix.tests.hpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           matrix.tests.cpp  -  description
00003                              -------------------
00004     email                : georg.martius@web.de
00005 ***************************************************************************/
00006 // 
00007 // $Log: matrix.tests.hpp,v $
00008 // Revision 1.8  2009/02/02 15:21:52  martius
00009 // added pseudoinverse
00010 //
00011 // Revision 1.7  2008/12/22 14:40:47  martius
00012 // added & operator for multrowwise
00013 //
00014 // Revision 1.6  2008/11/14 09:15:29  martius
00015 // tried some autovectorization but without success
00016 // moved some function to CPP file
00017 //
00018 // Revision 1.5  2008/06/18 13:46:20  martius
00019 // beside and toBeside added
00020 // addColumns and addRows is now based on toAbove and toBeside
00021 // bug fix in removeColumns
00022 //
00023 // Revision 1.4  2007/07/17 07:28:06  martius
00024 // store and restore test
00025 //
00026 // Revision 1.3  2006/07/20 17:14:36  martius
00027 // removed std namespace from matrix.h
00028 // storable interface
00029 // abstract model and invertablemodel as superclasses for networks
00030 //
00031 // Revision 1.2  2006/07/14 12:24:01  martius
00032 // selforg becomes HEAD
00033 //
00034 // Revision 1.1.2.1  2006/07/10 12:01:02  martius
00035 // Matrixlib moved to selforg
00036 //
00037 // Revision 1.15  2005/10/21 11:58:25  martius
00038 // map2 (similar to map but for 2 matrices)
00039 // changed naming of functions to be more consistent.
00040 //  Functions with "to" in front indicate the change of this. (Still not consistent with add, mult ...)
00041 //
00042 // Revision 1.14  2005/10/06 17:10:06  martius
00043 // convertToList
00044 // above and toAbove
00045 //
00046 // Revision 1.13  2005/08/06 20:47:36  martius
00047 // Commented
00048 //
00049 // Revision 1.12  2005/06/17 15:18:09  martius
00050 // 2x2 Inversion tested
00051 //
00052 // Revision 1.11  2005/06/10 08:21:50  martius
00053 // mult???wise are copy operations now!
00054 // toMult???wise are inplace instead
00055 //
00056 // Revision 1.10  2005/06/09 11:52:03  martius
00057 // multMT (M * M^T) and multTM (M^T * M)
00058 //
00059 // Revision 1.9  2005/06/02 22:49:33  martius
00060 // speed tests extended
00061 //
00062 // Revision 1.8  2005/06/02 08:49:26  martius
00063 // mult_row/column_wise
00064 //
00065 // Revision 1.7  2005/05/30 22:40:56  martius
00066 // map becomes toMap and the new map returns a new matrix
00067 // exp becomes toExp
00068 //
00069 // Revision 1.6  2005/05/30 21:46:54  martius
00070 // *** empty log message ***
00071 //
00072 // Revision 1.5  2005/05/30 16:43:02  martius
00073 // map function included (component-wise function application)
00074 //
00075 // Revision 1.4  2005/05/30 10:15:47  martius
00076 // proper log entry in header
00077 //
00078 /***************************************************************************/
00079 
00080 // //////////////////////////////////////////////////////////////////////////////
00081 // ////////////////// UNIT TESTS for matrix lib /////////////////////////////////////////////////
00082 
00083 #ifdef UNITTEST
00084 #include "unit_test.hpp"
00085 using namespace matrix;
00086 using namespace std;
00087 
00088 const D EPS=1e-9;
00089 bool comparetoidentity(const Matrix& m)  {
00090   int worstdiagonal = 0;
00091   D maxunitydeviation = 0.0;
00092   D currentunitydeviation;
00093   for ( unsigned int i = 0; i < m.getM(); i++ )  {
00094     currentunitydeviation = m.val(i,i) - 1.;
00095     if ( currentunitydeviation < 0.0) currentunitydeviation *= -1.;
00096     if ( currentunitydeviation > maxunitydeviation )  {
00097       maxunitydeviation = currentunitydeviation;
00098       worstdiagonal = i;
00099     }
00100   }
00101   int worstoffdiagonalrow = 0;
00102   int worstoffdiagonalcolumn = 0;
00103   D maxzerodeviation = 0.0;
00104   D currentzerodeviation ;
00105   for ( unsigned int i = 0; i < m.getM(); i++ )  {
00106     for ( unsigned int j = 0; j < m.getN(); j++ )  {
00107       if ( i == j ) continue;  // we look only at non-diagonal terms
00108       currentzerodeviation = m.val(i,j);
00109       if ( currentzerodeviation < 0.0) currentzerodeviation *= -1.0;
00110       if ( currentzerodeviation > maxzerodeviation )  {
00111         maxzerodeviation = currentzerodeviation;
00112         worstoffdiagonalrow = i;
00113         worstoffdiagonalcolumn = j;
00114       }
00115 
00116     }
00117   }
00118 //   cout << "\tWorst diagonal value deviation from unity: " 
00119 //        << maxunitydeviation << " at row/column " << worstdiagonal << endl;
00120 //   cout << "\tWorst off-diagonal value deviation from zero: " 
00121 //        << maxzerodeviation << " at row = " << worstoffdiagonalrow 
00122 //        << ", column = " << worstoffdiagonalcolumn << endl;
00123   return (maxunitydeviation < EPS && maxzerodeviation < EPS); 
00124 }
00125 
00126 
00127 UNIT_TEST_DEFINES
00128 
00129 DEFINE_TEST( check_creation ) {  
00130   cout << "\n -[ Creation and Access ]-\n";
00131   Matrix M1(3,3);  
00132   D testdata[9]={1,0,0, 0,1,0, 0,0,1};
00133   Matrix M2(3,3);
00134   M2.set(testdata);
00135   M1.toId();
00136   unit_assert( "id=identity_set", M1 == M2 );
00137   D testdata2[12]={1,2,3, 4,5,6, 7,8,9, 10,11,12};
00138   Matrix M3(4,3, testdata2);
00139   unit_assert( "dimension of matrix", M3.getM() == 4 &&  M3.getN() == 3 );
00140   unit_assert( "field check", 
00141                M3.val(0,2) == 3 &&  M3.val(2,1) == 8 &&  M3.val(3,0) == 10 );
00142   Matrix M4(M3);  
00143   unit_assert( "copy constructor", M3 == M4 );
00144   Matrix M5(1,3,testdata2+3);  
00145   unit_assert( "row", M3.row(1) == M5 );
00146 
00147   unit_pass();
00148 }
00149 
00150 DEFINE_TEST( check_vector_operation ) {  
00151   cout << "\n -[ Vector Operations ]-\n";
00152   D testdata[3]={-1,3,2};
00153   const Matrix V1(1,3, testdata);
00154   const Matrix V2(3,1, testdata);  
00155   Matrix V3(V1);  
00156 
00157   V3.toTranspose();
00158   unit_assert( "transpose", V3 == V2 );
00159   V3.toTranspose();
00160   unit_assert( "double transpose", V3 == V1 );
00161   D testdata2[3]={-2,6,4};
00162   Matrix V4(1,3,testdata2);    
00163   V3.add(V1,V1);
00164   unit_assert( "add", V3 == V4 );
00165   D testdata3[3]={1,-3,-2};
00166   Matrix V5(1,3,testdata3);
00167   V4.sub(V1,V3);
00168   unit_assert( "sub", V4 == V5 );
00169 
00170   D testdata4[3]={3,-9,-6};
00171   V5.set(testdata4);
00172   V4.copy(V1);
00173   V4.toMult(-3.0);
00174   unit_assert( "mult with scalar I", V4 == V5 );
00175   V4.mult(V1,-3.0);
00176   unit_assert( "mult with scalar II", V4 == V5 );
00177 
00178   double f = 14;
00179   Matrix V6(1,1,&f);
00180   V3.copy(V1);  
00181   V3.toTranspose();
00182   V4.mult(V1,V3);
00183   unit_assert( "scalarproduct", V4 == V6 );
00184   V4.copy(V1);
00185   unit_assert( "scalarproduct with exp(2)", V4.multMT() == V6 );
00186   V4.mult(V3,V1);
00187   unit_assert( "vector^T*vector=matrix", V4.getM() == 3);
00188   unit_assert( "vector^T*vector=exp(2)", V3.multMT().getM() == 3);
00189     
00190   unit_pass();
00191 }
00192 
00193 DEFINE_TEST( check_matrix_operation ) {  
00194   cout << "\n -[ Matrix Operations ]-\n";
00195   D testdata[6]={1,2,3, 4,5,6 };
00196   const Matrix M1(2,3, testdata);
00197   D testdata2[6]={1,4, 2,5, 3,6 };
00198   const Matrix M2(3,2, testdata2);  
00199   Matrix M3(M1);  
00200 
00201   M3.toTranspose();
00202   unit_assert( "transpose", M3 == M2 );
00203   D testdata3[6]={2,4,6, 8,10,12};
00204   Matrix M4(2,3,testdata3);    
00205   M3.add(M1,M1);
00206   unit_assert( "add", M3 == M4 );
00207 
00208   D testdata4[6]={-0.5, -1, -1.5,  -2, -2.5, -3};
00209   M3.set(testdata4);
00210   M4.copy(M1);
00211   M4.toMult(-0.5);
00212   unit_assert( "mult with scalar", M4 == M3 );
00213 
00214   D testdata5[6] = {2, -1,  0, 3,  2, -2};
00215   D testdata6[4] = {8, -1,  20, -1};
00216   Matrix M5 (3,2, testdata5);
00217   Matrix M6(2,2,testdata6);
00218   M4.mult(M1,M5);
00219   unit_assert( "mult(matrix, matrix)", M4 == M6 );
00220 
00221   M3.copy(M1);  
00222   M4.copy(M1);  
00223   M4.toExp(1);
00224   unit_assert( "exp(1)", M3 == M4 );
00225   M3.toTranspose();
00226   M4.toExp(T);
00227   unit_assert( "exp(T)=transpose", M3 == M4 );
00228   M3.toId();
00229   M4.toExp(0);
00230   unit_assert( "exp(0)=id", M3 == M4 );
00231 
00232   D testdata7[16] = {1,2,3,4, -4,2,1,3, 0.3,-0.9, 4, -3, 1,0.5,0.3,5.0};
00233   Matrix M7(4,4,testdata7);
00234   Matrix M8(M7);  
00235   M7.toExp(-1);  
00236   M4.mult(M7,M8);
00237   unit_assert( "exp(-1)*exp(1)=id",   comparetoidentity(M4) );
00238   M7=M8.pseudoInverse(0);
00239   M4.mult(M7,M8);
00240   unit_assert( "pseudoinverse*exp(1)=id",   comparetoidentity(M4) );
00241 
00242   D testdata9[6] = {sin(1.0),sin(2.0),sin(3.0), sin(4.0),sin(5.0),sin(6.0) };
00243   Matrix M9(2,3,testdata9);  
00244   M4.copy(M1);
00245   M4.toMap(sin);
00246   unit_assert( "map(sin)",   M4 == M9 );
00247 
00248   D testdata10[6] = {2,4,6, -0.4,-0.5,-0.6 };
00249   D testdata11[2] = {2,-0.1};
00250   Matrix M10(2,3,testdata10);  
00251   Matrix M11(2,1,testdata11);  
00252   M4.copy(M1);
00253   M4.toMultrowwise(M11);
00254   unit_assert( "multrowwise()",   M4 == M10 );
00255   M4 = M1 & M11;
00256   unit_assert( "rowwise (&)  ",   M4 == M10 );
00257   D testdata12[6] = {2,1,0, 8, 2.5, 0 };
00258   D testdata13[3] = {2, 0.5, 0};
00259   M10.set(2,3,testdata12);  
00260   Matrix M12(3,1,testdata13);  
00261   M4.copy(M1);
00262   M4.toMultcolwise(M12);
00263   unit_assert( "multcolwise()",   M4 == M10 );
00264 
00265   M3.copy(M1);  
00266   M4.copy(M1);
00267   M4.toTranspose();
00268   M5 = M3.multMT();
00269   M6.mult(M1,M4);
00270   unit_assert( "multMT() ",   M5 == M6 );
00271   M5 = M3.multTM();
00272   M6.mult(M4,M1);
00273   unit_assert( "multTM() ",   M5 == M6 );
00274 
00275   D testdata20[12]={1,2,3, 4,5,6, 1,2,3, 4,5,6 };
00276   const Matrix M20(4,3, testdata20);
00277   const Matrix M21 = M1.above(M1);
00278   unit_assert( "above() ",   M20 == M21 );
00279   D testdata22[8]={1,2,3, 7, 4,5,6, 8};
00280   D testdata23[2]={7, 8};
00281   const Matrix M22(2,4, testdata22);
00282   const Matrix M23(2,1, testdata23);
00283   const Matrix M24 = M1.beside(M23);
00284   unit_assert( "beside() ",   M24 == M22 );
00285 
00286   Matrix M30 = M24;
00287   const Matrix M31 = M30.removeColumns(1);
00288   unit_assert( "removeColumns() ",   M31 == M1 );
00289   Matrix M32 = M20;  
00290   const Matrix M33 = M32.removeRows(2);
00291   unit_assert( "removeRows() ",  M33 == M1 );
00292    
00293   unit_pass();
00294 }
00295 
00296 DEFINE_TEST( check_matrix_operators ) {  
00297   cout << "\n -[ Matrix Operators (+ - * ^)]-\n";
00298   D testdata[6]={1,2,3, 4,5,6 };
00299   const Matrix M1(2,3, testdata);
00300   D testdata2[6]={1,4, 2,5, 3,6 };
00301   const Matrix M2(3,2, testdata2);  
00302   unit_assert( "^T ",  (M1^T) == M2 );
00303   D testdata3[6]={2,4,6, 8,10,12};
00304   Matrix M4(2,3,testdata3);    
00305   unit_assert( "+  ", M1+M1 == M4 );
00306   unit_assert( "-  ", M1+M1-M1 == M1 );
00307 
00308   D testdata4[6]={-0.5, -1, -1.5,  -2, -2.5, -3};
00309   Matrix M3(2,3, testdata4);
00310   unit_assert( "* scalar", M1*(-0.5) == M3 );
00311 
00312   D testdata5[6] = {2, -1,  0, 3,  2, -2};
00313   D testdata6[4] = {8, -1,  20, -1};
00314   Matrix M5 (3,2, testdata5);
00315   Matrix M6(2,2,testdata6);
00316   unit_assert( "*  ", M1*M5 == M6 );
00317 
00318   unit_assert( "^1 ", (M1^1) == M1 );
00319   M3.toId();
00320   unit_assert( "^0=id ", (M1^0) == M3 );
00321 
00322   D testdata7[16] = {1,2,3,4, -4,2,1,3, 0.3,-0.9, 4, -3, 1,0.5,0.3,5.0};
00323   Matrix M7(4,4,testdata7);
00324   unit_assert( "^1 * ^-1=id ",   comparetoidentity(M7*(M7^-1)) );
00325   unit_pass();
00326 }
00327 
00328 DEFINE_TEST( speed ) {  
00329   cout << "\n -[ Speed: Inverion]-\n";  
00330 #ifndef NDEBUG
00331   cout << "   DEBUG MODE! use -DNDEBUG -O3 (not -g) to get full performance\n";
00332 #endif
00333   Matrix M1;
00334   srand(time(0));
00335   D testdata0[9] = {1,2, -4,2}; 
00336   Matrix M2(2,2,testdata0);
00337   UNIT_MEASURE_START("2x2 Matrix inversion", 100000)
00338     M1 = (M2^-1);
00339   UNIT_MEASURE_STOP("");
00340   unit_assert( "validation", comparetoidentity(M1*M2));
00341   /* LU version:  555648/s */
00342   /* Explicit  : 1428775/s */
00343   D testdata1[9] = {1,2,3, -4,2,1, 0.3,-0.9}; 
00344   Matrix M3(3,3,testdata1);
00345   UNIT_MEASURE_START("3x3 Matrix inversion", 100000)
00346     M1 = (M3^-1);
00347   UNIT_MEASURE_STOP("");
00348   unit_assert( "validation", comparetoidentity(M1*M3));
00349 
00350   D testdata2[16] = {1,2,3,4, -4,2,1,3, 0.3,-0.9, 4, -3, 1,0.5,0.3,5.0};
00351   Matrix M4(4,4,testdata2);
00352   UNIT_MEASURE_START("4x4 Matrix inversion", 100000)
00353     M1 = (M4^-1);
00354   UNIT_MEASURE_STOP("");
00355   unit_assert( "validation", comparetoidentity(M1*M4));
00356 
00357   Matrix M20(20,20); 
00358   for (unsigned int i=0; i < M20.getM(); i++)  // define random values for initial matrix
00359     for (unsigned int j=0; j < M20.getN(); j++) {
00360       M20.val(i,j) = -22+(100. * rand())/RAND_MAX;
00361     }
00362   UNIT_MEASURE_START("20x20 Matrix inversion",1000)
00363     M1 = (M20^-1);  
00364   UNIT_MEASURE_STOP("");
00365   unit_assert( "validation", comparetoidentity(M1*M20));
00366 
00367   Matrix M200(200,200); 
00368   rand();  // eliminates the first (= zero) call
00369   for (unsigned int i=0; i < M200.getM(); i++)  // define random values for initial matrix
00370     for (unsigned int j=0; j < M200.getN(); j++) {
00371       M200.val(i,j) = -22+(100. * rand())/RAND_MAX;
00372     }
00373   UNIT_MEASURE_START("200x200 Matrix inversion",2)
00374     M1 = (M200^-1);  
00375   UNIT_MEASURE_STOP("");
00376   unit_assert( "validation", comparetoidentity(M1*M200));
00377 
00378   cout << "\n -[ Speed: Other Operations]-\n";    
00379   UNIT_MEASURE_START("20x20 Matrix multiplication with assignment",5000)
00380     M1 = M20*M20;  
00381   UNIT_MEASURE_STOP("");
00382   UNIT_MEASURE_START("20x20 Matrix addition with assignment",100000)
00383     M1= (M1 + M20);  
00384   UNIT_MEASURE_STOP("");
00385   UNIT_MEASURE_START("20x20 Matrix inplace addition",100000)
00386     M1 += M20;  
00387   UNIT_MEASURE_STOP("");
00388   UNIT_MEASURE_START("20x20 Matrix transposition",100000)
00389     M1 += M20;  
00390   UNIT_MEASURE_STOP("");
00391 
00392   unit_pass();  
00393 }
00394 
00395 
00396 DEFINE_TEST( store_restore ) {  
00397   cout << "\n -[ Store and Restore]-\n";  
00398   Matrix M1(32,1);
00399   for(int i =0; i<32; i++){
00400     M1.val(0,0) = (double)rand()/RAND_MAX;
00401   }
00402   Matrix M2(32,2);
00403   for(int i =0; i<64; i++){
00404     M2.val(i%32,i/32) = (double)rand()/RAND_MAX;
00405   }
00406   FILE* f;
00407   f=fopen("test.dat","wb");
00408   M1.store(f);
00409   M2.store(f);
00410   fclose(f);
00411   f=fopen("test.dat","rb");  
00412   Matrix M3,M4;
00413   M3.restore(f); 
00414   M4.restore(f); 
00415   fclose(f);  
00416   unit_assert( "validation", (M1-M3).map(fabs).elementSum()==0);
00417   unit_assert( "validation", (M2-M4).map(fabs).elementSum()==0);
00418 
00419   unit_pass();  
00420 }
00421 
00422 
00423 
00424 UNIT_TEST_RUN( "Matrix Tests" )
00425   ADD_TEST( check_creation )
00426   ADD_TEST( check_vector_operation )
00427   ADD_TEST( check_matrix_operation )
00428   ADD_TEST( check_matrix_operators )
00429   ADD_TEST( speed )
00430   ADD_TEST( store_restore )
00431 
00432   UNIT_TEST_END
00433 
00434 #endif // UNITTEST

Generated on Fri Oct 30 16:29:01 2009 for Robot Simulator of the Robotics Group for Self-Organization of Control by  doxygen 1.4.7