La Matriz Abstracta no Polimorfica:
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Amigas 'defines'
test_Gauss.cpp
Ir a la documentación de este archivo.
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