Informática


Ecuaciones lineales. Métodos iterativo y directo


MÉTODO ITERATIVO (JACOBI)

Cuando hay muchas ecuaciones y , sobre todo , si hay muchos 0-s y no se puede resolver con el método directo, se empleará el MÉTODO ITERATIVO.

Los métodos iterativos se basan en la siguiente idea: La ecuación f(x)=0 se modificará para obtener ! X(n+1)=g(Xn)

Teniendo el siguiente sistema de n ecuaciones y n incógnitas:

a11x1+a12x2+...+a1nxn=b1

: : ! Ax=b

: :

an1x1+an2x2+...+annxn=bn

Se quiere calcular una solución para el sistema definido, para ello , consideramos A una matriz en cuya diagonal no tenga ningún elemento nulo.

Para poder realizar el calculo es recomendable dividir la matriz A en dos diferentes matrices: A= D+E

Considerando un sistema de 3 ecuaciónes:

a11 a12 a13 a11 0 0 0 a12 a13

a21 a22 a23 = 0 a22 0 + a21 0 a23

a31 a32 a33 0 0 a33 a31 a32 0

! ! !

A D E

Sustituyendo A por (D+E) en la ecuación Ax=b obtendremos la siguiente

manera de representar la ecuación (D+E)x=b. Transformando la ecuación a la siguiente forma (Dx=b-Ex) :

a11x1= b1-a12x2-a13x3

a22x2= b2-a21x1-a23x3

a33x3= b3-a31x1-a32x2

!

Términos de la diagonal

-1

(D+E)x=b ! Dx=b-Ex ! x=D (b-Ex)

-1 1/a11 0 0

Siendo D = 0 1/a22 0

0 0 1/a33

Sustituyendo de la manera que hemos deducido anteriormente, obtendremos el siguiente sistema de ecuaciones:

X1=1/a11 (b1-a12x2-a13x3)

X2=1/a22 (b2-a21x1-a23x3)

X3=1/a33 (b3-a31x1-a32x2)

Generalizando para “n” ecuaciónes:

(m+1) (m) (m)

x1 =1/a11 (b1-a12x2 -...-a1nxn )

(m+1) (m) (m)

X2 =1/a22 (b2-a21x21-...-a2nxn )

:

(m+1) (m) (m)

Xn =1/ann (bn-an1x1-...-ann-1xn-1 )

(m+1) -1 (m)

Representándolo en forma matricial: x = D (b-Ex ) !

(m+1) n (m)

! xi = 1/aii (bi- aij xj ) (i=1,2,3...n)

j=1

i"j

A continuación el programa que hemos realizado para calcular el método de Jacobi:

program jacobi;

type

lista=array [1..10,1..10] of real;

lista1=array [1..10] of real;

var

l:lista;

l1,l2:lista1;

fila,columna,i:integer;

error:real;

procedure introducir_datos (var l:lista;fila,columna:integer);

var

i,j:integer;

begin

for i:=1 to fila do

for j:=1 to columna do

begin

writeln ('Introduce valor de la fila ',i,' y de la columna ',j,':');

readln (l[i,j]);

end;

end;

function dominante (l:lista;fila,columna:integer):boolean;

var

cont:real;

i,j:integer;

resultado:boolean;

begin

resultado:=true;

for i:=1 to fila do

begin

cont:=0.0;

for j:=1 to (columna-1) do

if (j<>i) then

cont:=cont+abs(l[i,j]);

if (abs(l[i,i])>cont) and (resultado) then

resultado:=true

else

resultado:=false;

end;

dominante:=resultado;

end;

procedure calcular (l:lista;var l1:lista1;fila,columna:integer;error:real);

var

cont,i,j:integer;

resultado1,resultado:boolean;

begin

cont:=1;

if (dominante(l,fila,columna)) then

begin

resultado1:=false;

while (not resultado1) do

begin

for i:=1 to fila do

l2[i]:=0.0;

for i:=1 to fila do

begin

for j:=1 to columna do

if (i<>j) and (j<>columna) then

l2[i]:=l2[i]+((-1)*(l[i,j]*l1[j]))

else

if (i<>j) and (j=columna) then

l2[i]:=l2[i]-(l[i,j]);

l2[i]:=l2[i]/l[i,i];

end;

resultado:=true;

for i:=1 to fila do

if (abs((l2[i]-l1[i]))< error) and (resultado) then

begin

resultado:=true;

resultado1:=true;

end

else

begin

resultado:=false;

resultado1:=false;

end;

if (not resultado) then

begin

for i:=1 to fila do

l1[i]:=l2[i];

cont:=cont+1;

end;

end;

writeln ('EL NUMERO DE INTERACCIONES: ',cont);

for i:=1 to fila do

writeln ('EL VALOR DE X',i,' ES: ',l2[i]);

end

else

writeln ('ES DIVERGENTE');

end;

begin

writeln ('Introduce el numero de filas:');

readln (fila);

writeln ('Introduce el numero de columnas:');

readln (columna);

writeln ('Introduce el error:');

readln (error);

for i:=1 to fila do

begin

writeln ('Introduce el valor inicial de X',i,' :');

readln (l1[i]);

end;

introducir_datos (l,fila,columna);

calcular (l,l1,fila,columna,error);

end.

A continuación introduciremos tres ejemplos diferentes, analizando sus respectivas soluciones:

1/ x1+6x2-3x3=4 (0) (0) (0)

5x1+2x2-x3=6 ! x1=x2=x3=0 ! Error máximo= 0.005

2x1+x2+4x3=7

Solución: ES DIVERGENTE

Este problema no se puede resolver del modo que está planteado, para obtener una solución la matriz A tiene que ser diagonalmente dominante. Para ello debe cumplir la siguiente condición:

n

aii >  aij ( i=1...n)

j=1

j"i

2/ Si cambiamos el orden de las ecuaciones para que se cumpla dicha condición, obtendremos unos resultados.

Intercambiaremos las dos primeras ecuaciones obteniendo el siguiente sistema:

5x1+2x2-x3=6

x1+6x2-3x3=4

2x1+x2+4x3=7

Solución: NÚMERO DE INTERACCIONES: 11

EL VALOR DE X1 ES: 1.0007418833

EL VALOR DE X2 ES: 0.9998272877

EL VALOR DE X3 ES: 1.0017926613

3/ A continuación introduciremos un sistema de ecuaciones al azar, teniendo en cuenta que tiene que ser la matriz diagonalmente dominante:

5x1+x2-0.5x3=2 (0) (0) (0)

3x1+7.25x2+2.5x3=4 ! x1=x2=x3= 0 ! Error máximo= 0.005

-0.75x1-3.7x2+9x3=-7.5

Solución: NÚMERO DE INTERACCIONES: 5

EL VALOR DE X1 ES: 0.21537555233

EL VALOR DE X2 ES: 0.65072165553

EL VALOR DE X3 ES: -0.54767634828

MÉTODO DIRECTO (GAUSS)

Muchos de los problemas requieren de la solución de sistemas de ecuaciones lineales de la forma:

a11x1+a12x2+a13x3+...+a1nxn=b1

a21x1+a22x2+a23x3+...+a2nxn=b2

... ... ... ... ...

an1x1+an2x2+an3x3+...+annxn=bn

Donde aij y bi son las constantes, siendo xi los términos a calcular.

Mediante el método directo debemos procurar transformar el anterior sistema de ecuaciones a la siguiente forma:

A11x1+0+0+...+0= b1

0+a22x2+0+...+0= b2 ! creando un sistema, cuyos valores son

... ... nulos excepto en la diagonal.

0+0+0+...+annxn= bn

Como es muy complicado crear esta diagonal, se opta por ponerlo de forma triangular:

a11x1+a12x2+a13x3+...+a1nxn=b1

0 +a22x2+a23x3+...+a2nxn=b2

0 + 0 +a33x3+...+a3nxn=b3

... ... ...

0 + 0 + 0 +...+annxn=bn ! xn=bn/ann

Tal y como muestra la flecha , se debe resolver hacia atrás el sistema triangular superior.

Generalizando: xn-1= (b(n-1) - a(n-1)nxn) / a(n-1)(n-1)

!

MÉTODO DE GAUSS

Se debe tener en cuenta, que las ecuaciones deben ser independientes las unas de las otras, es decir, el determinante debe ser diferente a 0.

En primera instancia los pasos a seguir para lograr la solución serán:

1/ Triangularizar superiormente el sistema.

2/ Resolver hacia atrás el sistema triangular superior.

El programa diseñado para ello es el siguiente:

program metodo_directo;

type

lista=array [1..10,1..10] of real;

lista1=array [1..10] of real;

var

l:lista;

l1:lista1;

fila,columna,i,j:integer;

procedure introducir_datos (var l:lista;fila,columna:integer);

var

i,j:integer;

valor:real;

begin

for i:=1 to fila do

for j:=1 to columna do

begin

writeln ('Introduce el valor de la fila ',i,' y de la columna ',j);

readln (valor);

l[i,j]:=valor;

end;

end;

procedure hacer_ceros (var l:lista;fila,columna:integer);

var

j,i,u:integer;

resultado:real;

begin

for j:=1 to (fila-1) do

for i:=(j+1) to fila do

begin

resultado:=(l[i,j]/l[j,j]);

for u:=1 to columna do

l[i,u]:=(l[i,u]-(resultado*l[j,u]));

end;

end;

procedure calcular (l:lista;var l1:lista1;fila,columna:integer);

var

cont,resultado:real;

begin

for i:=1 to fila do

l1[i]:=1;

for i:=fila downto 1 do

begin

cont:=0.0;

resultado:=0.0;

for j:=(columna-1) downto (i+1) do

if (l[i,j]<>0.0) then

cont:=cont+(l1[j]*l[i,j]);

resultado:=((-1)*(l[i,columna])-cont)/l[i,i];

l1[i]:=resultado;

end;

end;

begin

writeln ('Introduce el numero de filas de la matriz:');

readln (fila);

writeln ('Introduce el numero de columnas de la matriz:');

readln (columna);

introducir_datos (l,fila,columna);

for i:=1 to fila do

begin

for j:=1 to columna do

write (l[i,j],' ');

writeln;

end;

hacer_ceros (l,fila,columna);

writeln ('La matriz despues de hacer los ceros:');

for i:=1 to fila do

begin

for j:=1 to columna do

write (l[i,j],' ');

writeln;

end;

calcular (l,l1,fila,columna);

for i:=1 to fila do

writeln ('El resultado de la X',i,' es: ',l1[i]);

end.

A continuación para comprobar la validez del programa realizaremos dos ejemplos:

1/ 2x1+x2+3x3=11

4x1+3x2+10x3=28

2x1+4x2+17x3=31

Solución: EL VALOR DE X1 ES=3

EL VALOR DE X2 ES=2

EL VALOR DE X3 ES=1

2/ 0.610x1+1.23x2+1.72x3=0.792

1.02x1+2.15x2-5.51x3=12.0

-4.34x1+11.2x2-4.25x3=16.3

Solución: EL VALOR DE X1 ES=1.6074749447

EL VALOR DE X2 ES=1.6019476216

EL VALOR DE X3 ES=-1.2552065644

¿ Y si intercambiásemos la tercera ecuación con la primera ?

-4.34x1+11.2x2-4.25x3=16.3

1.02x1+2.15x2-5.51x3=12.0

0.610x1+1.23x2+1.72x3=0.792

Solución: EL VALOR DE X1 ES=1.6074749448

EL VALOR DE X2 ES=1.6019476216

EL VALOR DE X3 ES=-1.2552065644

En nuestro caso, la diferencia es insignificante, pero si utilizáramos pocos dígitos significativos, el error cometido en el caso anterior sería enorme (casi del 100%), ya que la magnitud del error se multiplica por el mismo.

Para evitarlo, debemos colocar el coeficiente de mayor módulo en lo más alto.

Por lo tanto hay que volver a modificar el programa para que en cada fila que haya que hacer 0 se compare y se ponga el de mayor módulo en lo más alto: ( MÉTODO DE GAUSS CON PIVOTACIÓN PARCIAL )

program metodo_directo;

type

lista=array [1..9,1..10] of real;

lista1=array [1..10] of real;

var

l:lista;

l1:lista1;

fila,columna,i,j:integer;

procedure introducir_datos (var l:lista;fila,columna:integer);

var

i,j:integer;

valor:real;

begin

for i:=1 to fila do

for j:=1 to columna do

begin

writeln ('Introduce el valor de la fila ',i,' y de la columna ',j);

readln (valor);

l[i,j]:=valor;

end;

end;

procedure pivotear (var l:lista;fila,columna:integer;posfila:integer);

var

aux:lista1;

i,j:integer;

begin

for i:=posfila to fila do

if (abs(l[posfila,posfila])<abs(l[i,posfila])) then

for j:=1 to columna do

begin

aux[j]:=l[i,j];

l[i,j]:=l[posfila,j];

l[posfila,j]:=aux[j];

end;

end;

procedure hacer_ceros (var l:lista;fila,columna:integer);

var

j,i,u:integer;

resultado:real;

begin

for j:=1 to (fila-1) do

begin

pivotear (l,fila,columna,j);

for i:=(j+1) to fila do

begin

resultado:=(l[i,j]/l[j,j]);

for u:=1 to columna do

l[i,u]:=(l[i,u]-(resultado*l[j,u]));

end;

end;

end;

procedure calcular (l:lista;var l1:lista1;fila,columna:integer);

var

cont,resultado:real;

begin

for i:=1 to fila do

l1[i]:=1;

for i:=fila downto 1 do

begin

cont:=0.0;

resultado:=0.0;

for j:=(columna-1) downto (i+1) do

if (l[i,j]<>0.0) then

cont:=cont+(l1[j]*l[i,j]);

resultado:=((-1)*(l[i,columna])-cont)/l[i,i];

l1[i]:=resultado;

end;

end;

begin

writeln ('Introduce el numero de filas de la matriz:');

readln (fila);

writeln ('Introduce el numero de columnas de la matriz:');

readln (columna);

introducir_datos (l,fila,columna);

for i:=1 to fila do

begin

for j:=1 to columna do

write (l[i,j],' ');

writeln;

end;

hacer_ceros (l,fila,columna);

writeln ('La matriz despues de hacer los ceros:');

for i:=1 to fila do

begin

for j:=1 to columna do

write (l[i,j],' ');

writeln;

end;

calcular (l,l1,fila,columna);

for i:=1 to fila do

writeln ('El resultado de la X',i,' es: ',l1[i]);

end.

Nos basaremos en un sencillo ejemplo para explicar en que se basa y por qué es necesario el escalamiento:

Si tenemos ! x1+2x2=5

0.1x1+10x2=5.4

!

Estaría correctamente posicionado según la pivotación de GAUSS

Sin embargo si multiplicásemos por 100 la segunda ecuación obtendríamos:

x1+2x2=5

10x1+1000x2=540

!

Sería necesaria la modificación de posiciones

Para evitar estas ambigüedades, se deben poner todas las ecuaciones en el mismo orden de magnitud, es decir , en orden unitario.

Para ello se debe buscar el módulo más grande y el menor de cada ecuación y realizar la media geométrica (c*d). Una vez realizada, se divide cada ecuación por su media geométrica, logrando un orden unitario y evitando el problema anteriormente comentado. Esto se denomina escalamiento.

NOTA: El elemento bi no se tendrá en cuenta a hora de buscar el máximo y mínimo de cada ecuación, pero sí a la hora de dividirlo por la media.

Para solucionar el problema, y poner todas las ecuaciones en el mismo orden de magnitud, al programa anteriormente citado, le añadiremos la función que se denomina media_geometrica:

program metodo_directo;

type

lista=array [1..9,1..10] of real;

lista1=array [1..10] of real;

var

l:lista;

l1:lista1;

fila,columna,i,j:integer;

procedure introducir_datos (var l:lista;fila,columna:integer);

var

i,j:integer;

valor:real;

begin

for i:=1 to fila do

for j:=1 to columna do

begin

writeln ('Introduce el valor de la fila ',i,' y de la columna ',j);

readln (valor);

l[i,j]:=valor;

end;

end;

procedure media_geometrica (var l:lista;fila,columna:integer);

var

i,j:integer;

max,min,media:real;

begin

for i:=1 to fila do

begin

max:=abs(l[i,1]);

min:=abs(l[i,1]);

for j:=2 to (columna-1) do

if (abs(l[i,j])>max) then

max:=abs(l[i,j])

else

if (abs(l[i,j])<min) then

min:=abs(l[i,j]);

media:=sqrt(max*min);

for j:=1 to columna do

l[i,j]:=l[i,j]/media;

end;

end;

procedure pivotear (var l:lista;fila,columna:integer;posfila:integer);

var

aux:lista1;

i,j:integer;

begin

for i:=posfila to fila do

if (abs(l[posfila,posfila])<abs(l[i,posfila])) then

for j:=1 to columna do

begin

aux[j]:=l[i,j];

l[i,j]:=l[posfila,j];

l[posfila,j]:=aux[j];

end;

end;

procedure hacer_ceros (var l:lista;fila,columna:integer);

var

j,i,u:integer;

resultado:real;

begin

for j:=1 to (fila-1) do

begin

pivotear (l,fila,columna,j);

for i:=(j+1) to fila do

begin

resultado:=(l[i,j]/l[j,j]);

for u:=1 to columna do

l[i,u]:=(l[i,u]-(resultado*l[j,u]));

end;

end;

end;

procedure calcular (l:lista;var l1:lista1;fila,columna:integer);

var

cont,resultado:real;

begin

for i:=1 to fila do

l1[i]:=1;

for i:=fila downto 1 do

begin

cont:=0.0;

resultado:=0.0;

for j:=(columna-1) downto (i+1) do

if (l[i,j]<>0.0) then

cont:=cont+(l1[j]*l[i,j]);

resultado:=((-1)*(l[i,columna])-cont)/l[i,i];

l1[i]:=resultado;

end;

end;

begin

writeln ('Introduce el numero de filas de la matriz:');

readln (fila);

writeln ('Introduce el numero de columnas de la matriz:');

readln (columna);

introducir_datos (l,fila,columna);

for i:=1 to fila do

begin

for j:=1 to columna do

write (l[i,j],' ');

writeln;

end;

media_geometrica (l,fila,columna);

writeln ('La matriz despues de calcular la media geometrica:');

for i:=1 to fila do

begin

for j:=1 to columna do

write (l[i,j],' ');

writeln;

end;

hacer_ceros (l,fila,columna);

writeln ('La matriz despues de hacer los ceros:');

for i:=1 to fila do

begin

for j:=1 to columna do

write (l[i,j],' ');

writeln;

end;

calcular (l,l1,fila,columna);

for i:=1 to fila do

writeln ('El resultado de la X',i,' es: ',l1[i]);

end.

Para comprobar el correcto funcionamiento del programa realizado, introduciremos varios ejemplos, analizando los resultados obtenidos:

1/ -0.04x1+0.04x2+0.12x3=3

0.56x1-1.56x2+0.32x3=1

-0.24x1+1.24x2-0.28x3=0

Solución: EL VALOR DE X1 ES=7

EL VALOR DE X2 ES=7

EL VALOR DE X3 ES=25

2/ 5x1+x2-0.5x3=2

3x1+7.25x2+2.5x3=4

-0.75x1-3.7x2+9x3=-7.5

Solución: EL VALOR DE X1 ES=0.21492612704

EL VALOR DE X2 ES=0.65159742392

EL VALOR DE X3 ES=-0.5475438818

Para finalizar con este método sería apropiado mencionar que si se detecta en la diagonal en la cual voy a trabajar que hay un cero, debemos chequear en las ecuaciones que tiene debajo y cuando se encuentre alguna en la que no es cero, intercambiar ambas ecuaciones. Si no hay ninguna que no sea diferente de cero, significa que no se puede resolver ( No es compatible determinado ).




Descargar
Enviado por:El remitente no desea revelar su nombre
Idioma: castellano
País: España

Te va a interesar