Código En C++ Para Calcular El Determinante Y La Inversa De Una Matriz

Hola, siguiendo mi autoaprendizaje con las librerías matemáticas os dejo un sencillo y corto programa escrito en C++ para calcular el determinante y la inversa de una matriz cualquiera. Se sobreentiende que la matriz tiene determinante no nulo para poder calcular su matriz inversa.
Para poderlo hacer he utilizado GSL, en concreto, dos órdenes que se basan sobre la descomposición LU de una matriz.
Me explico, toda matriz cuadrada, llamémosla A, se puede descomponer de la siguiente forma:

PA=LU

Siendo P una matriz permutación, L una matriz triangular inferior en la que los elementos de su diagonal principal son todos uno; y U es una matriz triangular superior. (( L porque low es inferior y U porque upper es superior, en inglés ))

Así pues utilizando GSL tenemos la función:

gsl_linalg_LU_decomp(gsl_matrix *A, gsl_permutation *p, int *signum)

la cual nos calculará la descomposición LU de una matriz cuadrada no singular (( su determinante es no nulo )) A cualquiera, utilizando para ello una matriz permutación p que irá cambiando en las sucesivas iteraciones que realice la función, al igual que la variable entera signum. signum es el signo de la permutación, el cuasl toma el valor de (-1) n, siendo n el número de intercambios de la permutación.

Una vez calculada la descomposición LU ya podremos calcular el determinante y la matriz inversa de A con las funciones:

double gsl_linalg_LU_det (gsl_matrix *LU, int signum)
gsl_linalg_LU_invert (const gsl_matrix *LU, const gsl_permutation *p, gsl_matrix *inverse)

La primera es la que nos permite calcular el determinante, pasándole LU y signum; que los hemos calculado con la función gsl_linalg_LU_decomp. Y la segunda es la que nos permite calcular la inversa de A y guardarla en inverse, que es de tipo gsl_matrix

Para poder utilizar estas funciones bastará que en la cabecera de nuestro código introduzcamos el siguiente include:

#include <gsl/gsl_linalg.h>

Yo al programa le he llamado detinv.cpp (( vosotros llamadle como queráis, pero para C cambiad .cpp por .c )) , y el código es el siguiente:

C++:
  1. #include <iostream>
  2. #include <iomanip> //La utilizo para setw(int)
  3. #include <gsl/gsl_linalg.h> //Librería gsl para calcular lo que queremos
  4.  
  5. using namespace std;  //Instrucción para no tener que escribir std::cin
  6.  
  7. int main (int argc, char **argv)
  8. {
  9. size_t i,j,m; //size_t es un tipo específico de GSL, de tipo entero
  10. // i,j son variables contador, m es el tamaño u orden de la matriz
  11. int s; // s es la variable signum de las permutaciones
  12. cout<<"\nIntroduce el orden de la matriz: ";
  13. cin>>m;
  14. // Declaramos las matrices A, p y invA de forma dinámica para así poder destruirlas
  15. // cuando acabemos con ellas y así; liberar memoria. invA es la inversa y p es
  16. // la permutación
  17. gsl_matrix * A = gsl_matrix_alloc(m,m);
  18. gsl_permutation * p = gsl_permutation_alloc(m);
  19. gsl_matrix *invA = gsl_matrix_alloc(m,m);
  20. cout<<"\nIntroduce los elementos de la matriz:"<<endl;
  21. for(i=0; i<m*m; i++)
  22. {
  23. cout<<"A("<<i+1<<")"<<"=";
  24. cin>>A->data[i];
  25. }
  26. gsl_linalg_LU_decomp (A, p, &s); //Calculo la descomposición LU
  27. gsl_linalg_LU_invert(A,p,invA)// Calculo la inversa de A y la guardo en invA
  28. // Calculamos y visualizamos por terminal el determinante de A
  29. cout<<"\ndet(A) = "<<gsl_linalg_LU_det(A, s)<<endl;
  30. // Visualizamos por terminal la inversa de A
  31. cout<<"\nLa inversa de A es:"<<endl;
  32. for(i=0; i<m; i++)
  33. {
  34. for(j=0;j<m; j++)
  35. {
  36. cout<<gsl_matrix_get(invA,i,j)<<setw(10);
  37. }
  38. cout<<endl;
  39. }
  40. // Liberamos memoria destruyendo la que ocupan A, p e invA
  41. gsl_matrix_free(A);
  42. gsl_matrix_free(invA);
  43. gsl_permutation_free(p);
  44. return(0);
  45. }

Yo lo he escrito con gedit y lo he compilado y ejecutado con las siguientes órdenes:

g++ detinv.cpp -o detinv -lgsl -lgslcblas -lm
./detinv

Ahora sólo falta que me contéis cómo os ha ido el tema, espero que a alguien le sirva de ayuda. He de decir que los resultados de la inversa vienen en forma decimal y no en fracciones, espero pronto implementar una clase para que aparezca en forma de fracciones y publicarla en el blog, hace tiempo que la hice en Windows pero me temo que la perdí.
Os aconsejo que os leáis los siguientes enlaces para entenderlo mejor:

Código En C++ Para Multiplicar Matrices

Descomposición LU en la Wikipedia

La matriz Permutación En La Wikipedia

Saludos :)

Tags: , , ,

Post relacionados

11 Comentarios.

  1. Hola, me intereso mucho este ejemplo, disculpa es que soy nuevo en esto de linux, espero me puedas ayudar :

    Tengo unos errores:

    error: expected namespace-name before ‘;’ token
    detinv.cpp: In function ‘int main(int, char**)’:
    detinv.cpp:14: error: ‘lt’ no se declaró en este ámbito
    detinv.cpp:14: error: ‘nIntroduce’ no se declaró en este ámbito
    detinv.cpp:14: error: expected `;’ before ‘el’
    detinv.cpp:15: error: ‘gt’ no se declaró en este ámbito
    detinv.cpp:21: error: ‘gsl_matrix’ no se declaró en este ámbito
    detinv.cpp:21: error: ‘A’ no se declaró en este ámbito
    detinv.cpp:21: error: ‘gsl_matrix_alloc’ no se declaró en este ámbito
    detinv.cpp:22: error: ‘gsl_permutation’ no se declaró en este ámbito
    detinv.cpp:22: error: ‘p’ no se declaró en este ámbito
    detinv.cpp:22: error: ‘gsl_permutation_alloc’ no se declaró en este ámbito
    detinv.cpp:23: error: ‘invA’ no se declaró en este ámbito
    detinv.cpp:25: error: expected `;’ before ‘los’
    detinv.cpp:25: error: expected primary-expression before ‘’ token
    detinv.cpp:26: error: expected primary-expression before ‘for’
    detinv.cpp:26: error: expected `;’ before ‘for’
    detinv.cpp:26: error: expected primary-expression before ‘>’ token
    detinv.cpp:27: error: expected primary-expression before ‘{’ token
    detinv.cpp:27: error: expected `;’ before ‘{’ token
    detinv.cpp:31: error: ‘amp’ no se declaró en este ámbito
    detinv.cpp:31: error: expected `;’ before ‘)’ token
    detinv.cpp:32: error: ‘gsl_linalg_LU_invert’ no se declaró en este ámbito
    detinv.cpp:35: error: ‘ndet’ no se declaró en este ámbito
    detinv.cpp:35: error: expected primary-expression before ‘’ token
    detinv.cpp:35: error: expected primary-expression before ‘’ token
    detinv.cpp:35: error: expected primary-expression before ‘’ token
    detinv.cpp:35: error: expected primary-expression before ‘’ token
    detinv.cpp:38: error: ‘nLa’ no se declaró en este ámbito
    detinv.cpp:38: error: expected `;’ before ‘inversa’
    detinv.cpp:38: error: expected primary-expression before ‘’ token
    detinv.cpp:38: error: expected primary-expression before ‘’ token
    detinv.cpp:40: error: expected primary-expression before ‘for’
    detinv.cpp:40: error: expected `;’ before ‘for’
    detinv.cpp:40: error: expected primary-expression before ‘>’ token
    detinv.cpp:41: error: expected primary-expression before ‘{’ token
    detinv.cpp:41: error: expected `;’ before ‘{’ token
    detinv.cpp:47: error: expected primary-expression before ‘’ token
    detinv.cpp:47: error: expected primary-expression before ‘’ token
    detinv.cpp:47: error: expected primary-expression before ‘<’ token
    detinv.cpp:47: error: expected primary-expression before ‘/’ token
    detinv.cpp:47: error: ‘inva’ no se declaró en este ámbito
    detinv.cpp:47: error: ‘gsl_matrix_get’ no se declaró en este ámbito
    detinv.cpp:47: error: expected primary-expression before ‘’ token
    detinv.cpp:47: error: expected primary-expression before ‘’ token
    detinv.cpp:50: error: ‘gsl_matrix_free’ no se declaró en este ámbito
    detinv.cpp:52: error: ‘gsl_permutation_free’ no se declaró en este ámbito

    uso el kate para crear programas.

    Gracias por tu atencion: :-SS

  2. detinv.cpp:41: error: expected primary-expression before ‘{’ token. que significa?

  3. Mauricio seguramente te has dejado alguna llave por abrir o cerrar en algún sitio, revísalas.

  4. =D> Gracias mano no sabes ke ayudota me diste con la tarea

  5. :) )
    VAYA NIVEL D C++ HAY EN SUDAMERICA
    :) )

  6. Me costó un poquito echarlo a andar (faltaba instalar libgsl0-dev; lo averigué Googleando) pero por fin compiló en Debian. Yo había hecho por mi cuenta, como ejercicio, mi propia rutina para invertir matrices pero es agradable saber que existe esta forma. Felicitaciones por tu blog.

    Saludos

  7. hola!!!
    necesito este programita pero con funciones mas basicas???
    donde lo puedo encontrar???

  8. lola en el mismo artículo tienes la respuesta, mira los enlaces del final, y lee detenidamente el artículo ;-)

  9. hola disculpa a mi tambien me marca muchos errores y no se porque..
    mira me dice:
    gsl/gsl_linalg.h: No such file or directory.
    17 gsl_matrix’ undeclared (first use this function)
    17`A’ undeclared (first use this function)
    17 `gsl_matrix_alloc’ undeclared (first use this function)

    y asi muchas…..
    como otros 10 errores similares…
    y no se que estoy haciendo mal @.@
    tambien los estoy poniendo en C++ y locopie tal y como esta arriba
    si me pudieras ayudar te lo agradeceria muchisimo
    .de antemano muchas gracias

  10. Hola, ¿en qué sistema operativo lo estás haciendo? ¿Has instalado antes las librerías gsl? Revisa todas las comillas del código, porque al hacer copy&paste no se hacen correctamente.
    ¿Lo estás compilando por terminal, con Geany o con algún otro IDE?

    Saludos :-)

  11. Zeka, gracias por lo de libgsl0-dev, me pasó lo mismo en Debian Lenny. Es necesario instalar este paquete, ahí se encuentran todos los .h.