Está en la página 1de 6

Apuntes de la clase de Programación Fecha: 13 de mayo de 2013

MSc. José Colbes

Solución de sistemas de ecuaciones lineales


En esta clase se mostrarán tres métodos para dar solución a sistemas de ecuaciones lineales (donde se tiene
). El método de Gauss-Jordan es exacto, mientras que el de Jacobi y el Gauss-Seidel son aproximados.
Obs: Siempre supondremos que la matriz es cuadrada.

Método de Gauss-Jordan

Un sistema de ecuaciones se resuelve por el método de Gauss cuando se obtienen sus soluciones mediante la
reducción del sistema dado a otro equivalente. El método de Gauss transforma la matriz de coeficientes en una
matriz triangular superior. El método de Gauss-Jordan continúa el proceso de transformación hasta obtener
una matriz diagonal unitaria.

El algoritmo es el siguiente:
1. Ir a la columna extrema izquierda que tenga algún elemento distinto de cero. Obs: si se aumentan las
columnas de manera secuencial, y se llega a una columna con ningún elemento distinto de cero,
pueden ocurrir dos cosas: el sistema no tiene solución o tiene infinitas soluciones
2. Si el primer renglón tiene un cero en esta columna, intercambiarlo con otro que no lo tenga.
3. Luego, obtener ceros debajo de este elemento delantero, sumando múltiplos adecuados del renglón
superior a los renglones debajo de él.
4. Cubrir el renglón superior y repetir el proceso anterior con la submatriz restante. Repetir con el resto
de los renglones (en este punto la matriz se encuentra en la forma de escalón).
5. Comenzando con el último renglón no cero, avanzar hacia arriba: para cada renglón obtener un 1
delantero e introducir ceros arriba de éste sumando múltiplos correspondientes a los renglones
correspondientes.

La implementación del algoritmo se muestra a continuación (se utilizan punteros para los intercambios de
filas):
#include<stdio.h>
int main(){
int i,n,j,k;
printf("Ingrese la cantidad de variables: "); scanf("%d",&n);
int A[n][n+1];
printf("Este programa resuelve el sistema de ecuaciones Ax=b\n");
printf("Ingrese los valores de la matriz A\n");
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("Ingrese A[%d][%d]: ",i,j);scanf("%d",&A[i][j]);
}
}
printf("\nIngrese los valores del vector b\n");
for(i=0;i<n;i++){
printf("Ingrese b[%d]: ",i);scanf("%d",&A[i][n]);
}
int *p[n],*q;
//Situación inicial
for(i=0;i<n;i++) *(p+i)=*(A+i);
//Proceso
int band,piv,ref;
for(j=0;j<n;j++){
band=1;
for(i=j;i<n;i++){
piv=*(*(p+i)+j);
if(piv!=0){
band=0;
break;
}
}
if(band){
printf("\nEl sistema no tiene solucion o no es unica\n");
for(i=0;i<n;i++){
for(j=0;j<=n;j++){
printf("%d\t",*(*(p+i)+j));
}
printf("\n");
}
return 0;
}
else{
q=*(p+i);
*(p+i)=*(p+j);
*(p+j)=q;
for(i=(j+1);i<n;i++){
ref=*(*(p+i)+j);
for(k=j;k<=n;k++){
*(*(p+i)+k) = ref*(*(*(p+j)+k)) - piv*(*(*(p+i)+k));
}
}
}
}
//Hasta aquí, la matriz está escalonada. Ahora se avanza hacia arriba
for(j=(n-1);j>0;j--){
piv=*(*(p+j)+j);
for(i=0;i<j;i++){
ref=*(*(p+i)+j);
for(k=0;k<=n;k++){
*(*(p+i)+k) = ref*(*(*(p+j)+k)) - piv*(*(*(p+i)+k));
}
}
}
for(i=0;i<n;i++){
piv=(*(*(p+i)+i));
for(k=0;k<=n;k++){
*(*(p+i)+k)/=piv;
}
}
//Impresion de resultados
printf("\nEl resultado es:\n");
for(i=0;i<n;i++){
for(j=0;j<=n;j++){
printf("%d\t",*(*(p+i)+j));
}
printf("\n");
}
return 0;
}

Aplicando el programa al siguiente problema:

Se tiene que:

Método de Jacobi (Extraído de http://www.mty.itesm.mx/dmti/materias/ma2008/lecturas/ma2008-09a.pdf)

El método de Jacobi es el método iterativo para resolver sistemas de ecuaciones lineales más simple y se aplica
sólo a sistemas cuadrados, es decir a sistemas con tantas incógnitas como ecuaciones.
1. Primero se determina la ecuación de recurrencia. Para ello se ordenan las ecuaciones y las incógnitas.
De la ecuación se despeja la incógnita . En notación matricial se escribe como:

2. Se toma una aproximación para las soluciones y a esta se le designa por .


3. Se repite iterativamente el procedimiento. Para obtener , se utilizan los valores de . Aquí se
debe tener en cuenta un criterio de parada (en el programa que se presenta, se verifica que el valor
absoluto de las diferencia entre el valor actual y anterior de cada variable sea menor que TOL, y la
misma indica la precisión del procedimiento).

El programa que implementa el método es el siguiente:


#include<stdio.h>
double valabs(double num){
if(num>=0.0) return num;
else return ((-1.0)*num);
}
int verificacion(double x[], double h[], int n){
int i;
double TOL=0.0001;
for(i=0;i<n;i++){
if(valabs(x[i]-h[i])>TOL) return 1;
}
return 0;
}
int main(){
int i,n,j,k;
printf("Ingrese la cantidad de variables: "); scanf("%d",&n);
double A[n][n+1];
double x[n],h[n],TOL=0.0001;
printf("Este programa resuelve el sistema de ecuaciones Ax=b\n");
printf("Ingrese los valores de la matriz A\n");
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("Ingrese A[%d][%d]: ",i,j);scanf("%lf",&A[i][j]);
}
}
printf("\nIngrese los valores del vector b\n");
for(i=0;i<n;i++){
printf("Ingrese b[%d]: ",i);scanf("%lf",&A[i][n]);
}
printf("\nIngrese los valores iniciales de x\n");
for(i=0;i<n;i++){
printf("Ingrese x[%d]: ",i);scanf("%lf",&x[i]);
}
int band=1,iter=0;
double sum;
while(band){
iter++;
for(i=0;i<n;i++){
sum=1.0*A[i][n];
for(j=0;j<n;j++){
if(j!=i){
sum+=((-1.0)*A[i][j]*x[j]);
}
}
h[i]=sum/A[i][i];
}
band=verificacion(x,h,n);
for(i=0;i<n;i++) x[i]=h[i];
printf("\nIteracion %d:\n",iter);
for(i=0;i<n;i++){
printf("x[%i] = %lf\t",i,x[i]);
}
}
//Impresion de resultados
printf("\n\nEl resultado es:\n");
for(i=0;i<n;i++){
printf("x[%i] = %lf\n",i,x[i]);
}
printf("\nLa cantidad de iteraciones es: %d\n",iter);
return 0;
}

Observación: el método de Jacobi necesita de una aproximación inicial.

Se considera su aplicación en el siguiente sistema de ecuaciones lineales:

Considerando valores iniciales y , se tiene que:


Convergencia del método de Jacobi

Uno de los principales problemas de los métodos iterativos es la garantía de que el método va a converger, es
decir, va a producir una sucesión de aproximaciones cada vez efectivamente más próximas a la solución. En el
caso del método de Jacobi no existe una condición exacta para la convergencia. Lo mejor que se tiene es una
condición que garantiza la convergencia, pero en caso de no cumplirse puede o no haberla. La condición es la
siguiente: si la matriz de coeficientes original del sistema de ecuaciones es diagonalmente dominante, el
método de Jacobi seguro converge (esto mismo se puede afirmar para el método de Gauss-Seidel).

Matriz diagonalmente dominante

Una matriz se dice matriz diagonalmente dominante, si en cada uno de los renglones, el valor absoluto del
elemento de la diagonal principal es mayor que la suma de los valores absolutos de los elementos restantes del
mismo renglón. A veces la matriz de un sistema de ecuaciones no es diagonalmente dominante pero cuando se
cambian el orden de las ecuaciones y las incógnitas el nuevo sistema puede tener matriz de coeficientes
diagonalmente dominante.
Orden conveniente para Jacobi

En ciertas ocasiones al aplicar Jacobi la matriz no es diagonalmente dominante y por tanto no existirá garantía
de convergencia. Sin embargo, en algunos casos será posible reordenar las incógnitas en otra manera de forma
que la nueva matriz de coeficientes sea diagonalmente dominante. Esto se puede detectar revisando todos los
posibles ordenamientos de las incógnitas y ver cómo es la matriz resultante. Esto conlleva un buen número de
pruebas, pues el número posible de ordenamientos en variables es . Pero cuando es reducido, es
sencillo.

Método de Gauss-Seidel

El método de Gauss-Seidel es muy semejante al método de Jacobi. Mientras que en el de Jacobi se utiliza el
valor de las incógnitas para determinar una nueva aproximación, en el de Gauss-Seidel se van utilizando los
valores de las incógnitas recién calculados en la misma iteración, y no en la siguiente. Por ejemplo, en el
método de Jacobi se obtiene en el primer cálculo , pero este valor de no se utiliza sino hasta la
siguiente iteración. En el método de Gauss-Seidel en lugar de eso se utiliza de en lugar de en forma
inmediata para calcular el valor de las siguientes incógnitas; de igual manera procede con las siguientes
variables: siempre se utilizan las variables recién calculadas.

El programa que lo implementa es el siguiente:


#include<stdio.h>
double valabs(double num){
if(num>=0.0) return num;
else return ((-1.0)*num);
}
int verificacion(double x[], double h[], int n){
int i;
double TOL=0.0001;
for(i=0;i<n;i++){
if(valabs(x[i]-h[i])>TOL) return 1;
}
return 0;
}
int main(){
int i,n,j,k;
printf("Ingrese la cantidad de variables: "); scanf("%d",&n);
double A[n][n+1];
double x[n],h[n],TOL=0.0001;
printf("Este programa resuelve el sistema de ecuaciones Ax=b\n");
printf("Ingrese los valores de la matriz A\n");
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("Ingrese A[%d][%d]: ",i,j);scanf("%lf",&A[i][j]);
}
}
printf("\nIngrese los valores del vector b\n");
for(i=0;i<n;i++){
printf("Ingrese b[%d]: ",i);scanf("%lf",&A[i][n]);
}
printf("\nIngrese los valores iniciales de x\n");
for(i=0;i<n;i++){
printf("Ingrese x[%d]: ",i);scanf("%lf",&x[i]);
}
int band=1,iter=0;
double sum;
while(band){
iter++;
for(i=0;i<n;i++) h[i]=x[i];
for(i=0;i<n;i++){
sum=1.0*A[i][n];
for(j=0;j<n;j++){
if(j!=i){
sum+=((-1.0)*A[i][j]*x[j]);
}
}
x[i]=sum/A[i][i];
}
band=verificacion(x,h,n);
printf("\nIteracion %d:\n",iter);
for(i=0;i<n;i++){
printf("x[%i] = %lf\t",i,x[i]);
}
}
//Impresion de resultados
printf("\n\nEl resultado es:\n");
for(i=0;i<n;i++){
printf("x[%i] = %lf\n",i,x[i]);
}
printf("\nLa cantidad de iteraciones es: %d\n",iter);
return 0;
}

Aplicando este programa al mismo caso considerado para el método de Jacobi:

Se puede notar que el método de Gauss-Seidel converge más rápido que el método de Jacobi. Esto es debido a
que se usan los valores actuales en lugar de los valores de la iteración anterior.

También podría gustarte