Abstract non Polymorphyc Matrix:
|
00001 // test_Gauss.cpp (c) adolfo@di-mare.com 00002 00003 #include "Gaussian_Elimination.h" 00004 #include "rational.h" 00005 #include "BUnit.h" 00006 00007 #undef Matriz_Repeat 00008 #undef Matrix_Sparse 00009 #undef Matrix_Dense 00010 00011 #define USE_Matrix_List 00012 00013 #if defined(USE_Matrix_Dense) 00014 #include "Matrix_Dense.h" 00015 typedef Mx::Matrix_Dense< rational<long> > Rat_Matrix; 00016 #endif 00017 #if defined(USE_Matrix_List) 00018 #include "Matrix_List.h" 00019 typedef Mx::Matrix_List< rational<long> > Rat_Matrix; 00020 #endif 00021 #if defined(USE_Matrix_Sparse) 00022 #include "Matrix_Sparse.h" 00023 typedef Mx::Matrix_Sparse< rational<long> > Rat_Matrix; 00024 #endif 00025 #if defined(USE_Matriz_Repeat) 00026 #include "Matriz_Repeat.h" 00027 typedef Matriz_Repeat< rational<long> > Rat_Matrix; 00028 #endif 00029 00030 using namespace std; 00031 00032 /// Clase simple para probar \c Gauss(). 00033 class test_Gauss : public TestCase { 00034 Rat_Matrix ID; ///< Matriz identidad 00035 Rat_Matrix M1, M2, M3, M4; 00036 Rat_Matrix B1, B2, B3, B4; 00037 public: 00038 void do_cout(); 00039 void setUp(); 00040 bool run(); 00041 private: 00042 void Ejecutor(const Rat_Matrix& M, const Rat_Matrix& B); 00043 void test_makeMatrix_long(); 00044 }; // test_Gauss 00045 00046 /// Inicializa los valores para \c test_Gauss. 00047 void test_Gauss::setUp() { 00048 ID.reSize(3,3); // Matriz identidad 00049 B1.reSize( ID.rows(), 1 ); // B1 queda sincronizado con ID 00050 ID(0,0) = 1; ID(0,1) = 0; ID(0,2) = 0; B1(0,0) = 10; 00051 ID(1,0) = 0; ID(1,1) = 1; ID(1,2) = 0; B1(1,0) = 10; 00052 ID(2,0) = 0; ID(2,1) = 0; ID(2,2) = 1; B1(2,0) = 10; 00053 00054 M2.reSize(3,3); B2.reSize( M2.rows(), 1 ); 00055 M2(0,0) = 14; M2(0,1) = 21; M2(0,2) = 7; B2(0,0) = 1; 00056 M2(1,0) = -7; M2(1,1) = 14; M2(1,2) = 7; B2(1,0) = 0; 00057 M2(2,0) = 7; M2(2,1) = 35; M2(2,2) = 14; B2(2,0) = 14; 00058 00059 M3.reSize(3,3); B3.reSize( M3.rows(), 1 ); 00060 M3(0,0) = 0; M3(0,1) = 0; M3(0,2) = rational<long>(1,3); B3(0,0) = 4; 00061 M3(1,0) = 0; M3(1,1) = 0; M3(1,2) = rational<long>(2,3); B3(1,0) = 4; 00062 M3(2,0) = 0; M3(2,1) = 0; M3(2,2) = rational<long>(1,3); B3(2,0) = 4; 00063 00064 M4.reSize(3,3); B4.reSize( M4.rows(), 1 ); 00065 M4(0,0) = 13; M4(0,1) = 26; M4(0,1) = 39; B4(0,0) = 65; 00066 M4(1,0) = 52; M4(1,1) = 65; M4(1,1) = 78; B4(1,0) = -91; 00067 M4(2,0) = 91; M4(2,1) = 104; M4(2,2) = 130; B4(2,0) = -26; 00068 } 00069 /// <code>cout << M;</code> 00070 template <class MAT> 00071 void print( std::ostream &COUT , MAT & V ) { 00072 for (unsigned i=0; i < V.rows(); ++i) { 00073 for (unsigned j=0; j < V.cols(); ++j) { 00074 COUT << ' ' << V(i,j); 00075 } 00076 COUT << '\n'; 00077 } 00078 } 00079 00080 #if 0 00081 00082 template <class MAT > 00083 std::ostream& operator<< (std::ostream &COUT, const MAT& M) { 00084 print( COUT , M ); 00085 return COUT; 00086 } 00087 00088 /// Graba en \c cout el valor actual de las matrices de prueba. 00089 void test_Gauss::do_cout() { 00090 cout << endl << endl << "=============" << endl; 00091 cout << "ID " << ID << endl << "......" << endl; 00092 cout << "B1 " << B1 << endl << "======" << endl; 00093 00094 cout << endl << endl << "======" << endl; 00095 cout << "M2 " << M2 << endl << "======" << endl; 00096 cout << "B2 " << B2 << endl << "======" << endl; 00097 00098 cout << endl << endl << "======" << endl; 00099 cout << "M3 " << M3 << endl << "======" << endl; 00100 cout << "B3 " << B3 << endl << "======" << endl; 00101 00102 cout << endl << endl << "======" << endl; 00103 cout << "M4 " << M4 << endl << "======" << endl; 00104 cout << "B4 " << B4 << endl << "======" << endl; 00105 } 00106 #endif 00107 00108 /// Método auxiliar que permite hace pruebas con todas las matrices 00109 void test_Gauss::Ejecutor(const Rat_Matrix& M, const Rat_Matrix& B) { 00110 Rat_Matrix X; 00111 Rat_Matrix Bmod = B; 00112 if ( rational<long>(0) == Gaussian_Elimination(M, X, B) ) { 00113 fail_Msg("Matriz singular"); 00114 return; 00115 } 00116 assertTrue(M*X == B); // La matriz sabe multiplicar 00117 00118 assertTrue( check_ok( M ) ); 00119 for (unsigned i=1; i<12; ++i) { 00120 for (unsigned j=0; j<B1.rows(); ++j) { 00121 Bmod(j,0) = rational<long>( B(j,0).num() * j, B(j,0).den() + j); 00122 } 00123 Gaussian_Elimination(M, X, Bmod); 00124 assertTrue( check_ok( X ) ); 00125 assertTrue( check_ok( Bmod ) ); 00126 assertTrue(M*X == Bmod); 00127 } 00128 } 00129 00130 /// Ejecuta las pruebas para \c test_Gauss. 00131 bool test_Gauss::run() { 00132 Rat_Matrix X; 00133 assertTrue(ID*B1 == B1); 00134 Ejecutor(ID, B1); 00135 assertTrue( rational<long>(0) == Gaussian_Elimination(M2, X, B2) ); // M2 es singular 00136 assertTrue( rational<long>(0) == Gaussian_Elimination(M3, X, B3) ); // M3 es singular 00137 Ejecutor(M4, B4); 00138 B4.swap( M4 ); 00139 assertTrue( check_ok( M2 ) ); 00140 test_makeMatrix_long(); 00141 return wasSuccessful(); 00142 } 00143 00144 Rat_Matrix makeMatrix_long(const char **V , int rows , int cols); 00145 00146 /// Ejecuta las pruebas para \c makeMatrix_long(). 00147 void test_Gauss::test_makeMatrix_long() { 00148 {{ // test::makeMatrix_long() 00149 const char *M_val[3] = { 00150 " 0 1 2 3 4 5 6" , 00151 "10 11 12 13 14 15 16" , 00152 "20 21 22 23 24 25 26" 00153 }; 00154 Rat_Matrix M = makeMatrix_long( M_val, 3, 7 ); 00155 for (unsigned i=0; i<M.rows(); ++i) { 00156 for (unsigned j=0; j<M.cols(); ++j) { 00157 cout << M(i,j); 00158 } 00159 cout << endl; 00160 } 00161 }} 00162 } 00163 00164 /** Retorna una matriz de enteros \c "M" construida en base a la hilera \c "V". 00165 \dontinclude test_Gauss.cpp 00166 \skipline test::makeMatrix_long() 00167 \until }} 00168 \see std::test_Gauss<T>::test_makeMatrix_long() 00169 */ 00170 Rat_Matrix makeMatrix_long(const char **V , int rows , int cols) { 00171 Rat_Matrix M; 00172 if (V == 0 || rows<=0 || cols<=0) { 00173 return M; 00174 } 00175 if (*V == 0) { 00176 return M; 00177 } 00178 00179 enum { SI_Digito, NO_Digito }; 00180 00181 M.reSize(rows, cols); 00182 for ( int row=0; row<rows; ++row ) { 00183 const char* pCH = V[row]; 00184 for ( ;*pCH;pCH++ ) { cout << *pCH; } cout << "**"<< endl; pCH = V[row]; 00185 bool es_positivo = true; // manejo del cambio de signo 00186 int estado = NO_Digito; 00187 int num = 0, col = 0; 00188 do { 00189 switch (estado) { 00190 case SI_Digito: 00191 if (*pCH == '-') { 00192 es_positivo = !es_positivo; // cambio de signo 00193 ++pCH; 00194 } 00195 else if (*pCH == '+') { 00196 ++pCH; 00197 } 00198 else if ( isdigit(*pCH) ) { // Este es un autómata finito de 2 estados 00199 num = num*10 + (*pCH-'0'); // - nunca pregunta por '(' porque se lo brinca 00200 ++pCH; // - Tampoco le importa el ']' 00201 } // - Sólo trabaja con los dígitos y los signos 00202 else { 00203 num = ( es_positivo ? num : -num ); 00204 M(row,col) = num; 00205 num = 0; col++; 00206 es_positivo = true; 00207 estado = NO_Digito; 00208 } 00209 break; 00210 case NO_Digito: 00211 if (*pCH == '-') { 00212 es_positivo = false; 00213 num = 0; 00214 estado = SI_Digito; 00215 ++pCH; 00216 } 00217 else if (*pCH == '+') { 00218 es_positivo = true; 00219 num = 0; 00220 estado = SI_Digito; 00221 ++pCH; 00222 } 00223 else if ( isdigit(*pCH) ) { 00224 num = (*pCH-'0'); 00225 es_positivo = true; 00226 estado = SI_Digito; 00227 ++pCH; 00228 } 00229 else { 00230 ++pCH; 00231 break; 00232 } 00233 } 00234 } while (*pCH != 0); 00235 } 00236 return M; 00237 } 00238 00239 /// Programa principal para probar el algoritmo \c Gauss(). 00240 int main() { 00241 cout << "1) Prueba directa con \"TestCase\"" << endl; 00242 test_Gauss test_Gauss_Instance; 00243 test_Gauss_Instance.setUp(); 00244 test_Gauss_Instance.run(); 00245 if ( true ) { 00246 // test_Gauss_Instance.do_cout(); 00247 } 00248 cout << test_Gauss_Instance.report(); 00249 } 00250 // EOF: test_Gauss.cpp