Logo Studenta
¡Este material tiene más páginas!

Vista previa del material en texto

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
 ij
 
	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
 ji
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 seguirpara 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 ).