Está en la página 1de 15

SEXTO TRABAJO DE FÍSICA

COMPUTACIONAL 2
MÉTODO DE JACOBI
Quispe Chuquitarqui Henry Nicolás CUI:20162704
31 de diciembre de 2017

1. Introducción

1.1. MÉTODO ITERATIVO:


Un método iterativo trata de resolver un problema matemático (como
una ecuación o un sistema de ecuaciones) mediante aproximaciones sucesivas
a la solución, empezando desde una estimación inicial. Esta aproximación
contrasta con los métodos directos, que tratan de resolver el problema de
una sola vez (como resolver un sistema de ecuaciones Ax = b encontrando
la inversa de la matriz A). Los métodos iterativos son útiles para resolver
problemas que involucran un número grande de variables (a veces del orden
de millones), donde los métodos directos tendrı́an un coste prohibitivo incluso
con la potencia del mejor computador disponible.

1.2. MÉTODO DE JACOBI


Muchos problemas relacionados con el campo de la ingenierı́a se pueden
expresar en términos de sistemas de ecuaciones algebraicas lineales.
Cuando se resuelven numéricamente ecuaciones diferenciales pueden surgir
sistemas lineales con 20,000 variables. Los equipos de cómputo disponibles
en la actualidad podrı́an requerir incluso dı́as para resolver estos sistemas

1
por métodos directos (como eliminación o factorización).
El método de Jácobi es un método iterativo con el cual se resuelve el sistema
lineal

Ax = b
Comienza con una aproximación inicial x(0) a la solución x y genera una
sucesión de vectores x(k) que convergen a la solución x.
Un sistema de ecuaciones algebraicas lineales es un conjunto de ecuaciones
de la forma:

a11 x1 + a12 x2 + a13 x3 + ... + a1n xn = b1


a21 x1 + a22 x2 + a23 x3 + ... + a2n xn = b2
a31 x1 + a32 x2 + a33 x3 + ... + a3n xn = b3
. . ... .
. . ... .
. . ... .
an1 x1 + an2 x2 + an3 x3 + ... + ann xn = bn

Que se puede expresar como Ax = b


Donde ”A” es la matriz de coeficientes, x es el vector de incógnitas y b el
vector de términos independientes. La solución del sistema de ecuaciones
es un conjunto de n valores x1 , x2 , x3 , ..., xn que satisfacen simultáneamente
todas las ecuaciones.

1.2.1. DESCRIPCIÓN:
La base del método consiste en construir una sucesión convergente
definida iterativamente. El lı́mite de esta sucesión es precisamente la
solución del sistema. A efectos prácticos si el algoritmo se detiene después
de un número finito de pasos se llega a una aproximación al valor de x de la
solución del sistema.

2
La sucesión se construye descomponiendo la matriz del sistema A en la
forma siguiente:
A=D+R

donde D, es una matriz diagonal y R , es la suma de una matriz triangular


inferior L y una matriz triangular superior U , luego R = L + U . Partiendo
de Ax = b, podemos reescribir dicha ecuación como:

Dx + Rx = b

Luego:
x = D−1 (B − Rx)

2. Modificación del codigo jacobi


En el codigo se modifico la seccion que generaba una matriz arbitraria y
se le cambio por una matriz de covarianza de los datos de iris. Estos procesos
se muestran detalladamente en el siguiente codigo:
1
2 /* L -19 MCS 572 Wed 5 Oct 2016 : jacobi . c
3 * This program runs the Jacobi method on a test system A * x
= b,
4 * where A is diagonally dominant and the exact solution
consists
5 * of all ones . The dimension can be supplied at the
command line . */
6
7 # include < stdio .h >
8 # include < stdlib .h >
9 # include < math .h >
10
11
12 void test_system
13 ( int n , double ** A , double * b ) ;
14 /*
15 * Given n on entry ,
16 * On return is an n - by - n matrix A
17 * with n +1 on the diagonal and 1 elsewhere .
18 * The elements of the right hand side b
19 * all equal 2* n , so the exact solution x
20 * to A * x = b is a vector of ones . */

3
21
22 void ru n_jaco bi_met hod
23 ( int n , double ** A , double *b ,
24 double epsilon , int maxit ,
25 int * numit , double * x ) ;
26 /*
27 * Runs the Jacobi method for A * x = b .
28 *
29 * ON ENTRY :
30 * n the dimension of the system ;
31 * A an n - by - n matrix A [ i ][ i ] /= 0;
32 * b an n - dimensional vector ;
33 * epsilon accuracy requirement ;
34 * maxit maximal number of iterations ;
35 * x start vector for the iteration .
36 *
37 * ON RETURN :
38 * numit number of iterations used ;
39 * x approximate solution to A * x = b . */
40
41 int main ( int argc , char * argv [] )
42 {
43 int n = 150 , i ;
44 double * b ;
45 b = ( double *) calloc (n , sizeof ( double ) ) ;
46 double ** A ;
47 A = ( double **) calloc (n , sizeof ( double *) ) ;
48 for ( i =0; i < n ; i ++)
49 A [ i ] = ( double *) calloc (n , sizeof ( double ) ) ;
50 test_system (n ,A , b ) ;
51 double * x ;
52 x = ( double *) calloc (n , sizeof ( double ) ) ;
53 /* we start at an array of all zeroes */
54 for ( i =0; i < n ; i ++) x [ i ] = 0.0;
55 double eps = 1.0 e -4;
56 int maxit = 2* n * n ;
57 int cnt = 0;
58 run_ jacob i_meth od (n ,A ,b , eps , maxit ,& cnt , x ) ;
59 printf ( " computed %d iterations \ n " , cnt ) ;
60 double sum = 0.0;
61 for ( i =0; i < n ; i ++) /* compute the error */
62 {
63 double d = x [ i ] - 1.0;
64 sum += ( d >= 0.0) ? d : -d ;
65 }

4
66 printf ( " error : %.3 e \ n " , sum ) ;
67 return 0;
68 }
69
70 void test_system ( int n , double ** A , double * b )
71 {
72 int i ,j , k ;
73 // comando que lee los datos de iris
74 FILE * fp = fopen ( " iris_3 . data " , " r " ) ;
75
76 double sum0 = 0.0;
77 double sum1 = 0.0;
78 double sum2 = 0.0;
79 double sum3 = 0.0;
80
81 int aux ;
82
83 double mat [ n ][4];
84
85 for ( i =0; i < n ; i ++) {
86 // recoger valores
87 fscanf ( fp , " %lf %lf %lf %lf %d " , & mat [ i
][0] , & mat [ i ][1] , & mat [ i ][2] , & mat [ i
][3] , & aux ) ;
88
89 // acumular las sumas de una columna
90 sum0 += mat [ i ][0];
91 sum1 += mat [ i ][1];
92 sum2 += mat [ i ][2];
93 sum3 += mat [ i ][3];
94 }
95
96 // promedio
97 double prom0 = sum0 / n ;
98 double prom1 = sum1 / n ;
99 double prom2 = sum2 / n ;
100 double prom3 = sum3 / n ;
101
102 // restar el promedio
103 for ( i =0; i < n ; i ++) {
104 mat [ i ][0] -= prom0 ;
105 mat [ i ][1] -= prom1 ;
106 mat [ i ][2] -= prom2 ;
107 mat [ i ][3] -= prom3 ;
108 }

5
109
110 // crear la matriz transpuesta
111 double matTrans [4][ n ];
112 for ( i =0; i < n ; i ++) {
113 matTrans [0][ i ] = mat [ i ][0];
114 matTrans [1][ i ] = mat [ i ][1];
115 matTrans [2][ i ] = mat [ i ][2];
116 matTrans [3][ i ] = mat [ i ][3];
117 }
118
119 // multiplicar normal por la transpuesta
120 double matAnswer [150][150];
121 for ( i =0; i < n ; i ++) {
122 for ( j =0; j < n ; j ++) {
123 double suma = 0.0;
124 for ( k =0; k <4; k ++) {
125 suma += mat [ i ][ k ]* matTrans [
k ][ j ];
126 }
127 matAnswer [ i ][ j ] = suma ;
128 }
129 }
130
131 // multiplicar todo por 1/ n = 1/150
132 for ( i =0; i <150; i ++) {
133 for ( j =0; j <150; j ++) {
134 matAnswer [ i ][ j ] /= 1.0* n ;
135 }
136 }
137
138
139
140
141 fclose ( fp ) ;
142
143 for ( i =0; i < n ; i ++)
144 {
145 b [ i ] = 0.0;
146 for ( j =0; j < n ; j ++)
147 A [ i ][ j ] = 1.0;
148 A [ i ][ i ] = matAnswer [ i ][ j ];
149 }
150 }
151

6
152 void ru n_jaco bi_met hod ( int n , double ** A , double *b ,
double epsilon , int maxit , int * numit , double * x )
153 {
154 double * dx ,* y ;
155 dx = ( double *) calloc (n , sizeof ( double ) ) ;
156 y = ( double *) calloc (n , sizeof ( double ) ) ;
157 int i ,j , k ;
158
159 for ( k =0; k < maxit ; k ++)
160 {
161 double sum = 0.0;
162 for ( i =0; i < n ; i ++)
163 {
164 dx [ i ] = b [ i ];
165 for ( j =0; j < n ; j ++)
166 dx [ i ] -= A [ i ][ j ]* x [ j ];
167 dx [ i ] /= A [ i ][ i ];
168 y [ i ] += dx [ i ];
169 sum += ( ( dx [ i ] >= 0.0) ? dx [ i ] : - dx [ i ]) ;
170 }
171 for ( i =0; i < n ; i ++) x [ i ] = y [ i ];
172 printf ( " %4d : %.3 e \ n " ,k , sum ) ;
173 if ( sum <= epsilon ) break ;
174 }
175 * numit = k +1;
176 free ( dx ) ; free ( y ) ;
177 }

7
3. Análisis de resultados

Figura 1: Compilacion del codigo Modificado

3.0.1. Interpretacion de Resultados


NaN = not a number : El lenguaje de programacion c no trabaja con
imaginarios, los errores semanticos en lenguaje c no son considerados
como numeros; entonces se denotara como ”nan”.

8
Utilizando los comandos de octave se calculo los autovalores de la matriz
de covarianza.
1 roots ( poly ( load ( ’ psm . dat ’) ) )

Figura 2: Autovalores de la matriz de covarianza

siendo ”psm.dat”la matriz de covarianza de 150x150

como se puede visualizar en la imagen las raices pertenecen al campo


de los imaginarios o complejos, lo cual valida los resultos obtenidos en
el programa c ”nan”.

9
4. METODO DE LA POTENCIA SIMPLE
Es un metodo numerico iterativo que se encarga de calcular el autovalor
de mayor valor (autovalor dominate).
1 /* potencia simple */
2
3 # include < stdio .h >
4 # include < stdlib .h >
5 # include < math .h >
6
7 double max ( double a , double b ) {
8 return (a > b ) ? a : b ;
9 }
10
11 int main () {
12 int n = 150;
13 int i ,j , k ;
14
15 FILE * fp = fopen ( " iris_3 . data " , " r " ) ;
16
17 double sum0 = 0.0;
18 double sum1 = 0.0;
19 double sum2 = 0.0;
20 double sum3 = 0.0;
21
22 int aux ;
23
24 double mat [ n ][4];
25
26 for ( i =0; i < n ; i ++) {
27 // recoger valores
28 fscanf ( fp , " %lf %lf %lf %lf %d " , & mat [ i
][0] , & mat [ i ][1] , & mat [ i ][2] , & mat [ i
][3] , & aux ) ;
29
30 // acumular las sumas de una columna
31 sum0 += mat [ i ][0];
32 sum1 += mat [ i ][1];
33 sum2 += mat [ i ][2];
34 sum3 += mat [ i ][3];
35 }
36
37 // promedio
38 double prom0 = sum0 / n ;

10
39 double prom1 = sum1 / n ;
40 double prom2 = sum2 / n ;
41 double prom3 = sum3 / n ;
42
43 // restar el promedio
44 for ( i =0; i < n ; i ++) {
45 mat [ i ][0] -= prom0 ;
46 mat [ i ][1] -= prom1 ;
47 mat [ i ][2] -= prom2 ;
48 mat [ i ][3] -= prom3 ;
49 }
50
51 // crear la matriz transpuesta
52 double matTrans [4][ n ];
53 for ( i =0; i < n ; i ++) {
54 matTrans [0][ i ] = mat [ i ][0];
55 matTrans [1][ i ] = mat [ i ][1];
56 matTrans [2][ i ] = mat [ i ][2];
57 matTrans [3][ i ] = mat [ i ][3];
58 }
59
60 // multiplicar normal por la transpuesta
61 double matAnswer [ n ][ n ];
62 for ( i =0; i < n ; i ++) {
63 for ( j =0; j < n ; j ++) {
64 double suma = 0.0;
65 for ( k =0; k <4; k ++) {
66 suma += mat [ i ][ k ]* matTrans [
k ][ j ];
67 }
68 matAnswer [ i ][ j ] = suma ;
69 }
70 }
71
72 // multiplicar todo por 1/ n = 1/150 para finalmente
73 // optener la matriz de covarianzas
74 for ( i =0; i < n ; i ++) {
75 for ( j =0; j < n ; j ++) {
76 matAnswer [ i ][ j ] /= 1.0* n ;
77 }
78 }
79
80 // metodo de potencia simple
81
82 double z [ n ][1];

11
83 for ( i =0; i < n ; i ++) {
84 z [ i ][0] = 1.0;
85 }
86
87 double w [ n ][1];
88 for ( i =0; i < n ; i ++) {
89 w [ i ][0] = 0.0;
90 }
91
92 // norma de z - w
93 double sum = 0.0;
94 for ( i =0; i < n ; i ++) {
95 sum += pow ( z [ i ][0] - w [ i ][0] , 2) ;
96 }
97 double norma = sqrt ( sum ) ;
98
99
100 while ( norma > pow (10 , -14) ) {
101 // w = z
102 for ( i =0; i < n ; i ++) {
103 w [ i ][0] = z [ i ][0];
104 }
105
106 // z = A * w
107 double maxValue = 0;
108 for ( i =0; i < n ; i ++) {
109 for ( j =0; j <1; j ++) {
110 z [ i ][ j ] = 0.0;
111 for ( k =0; k < n ; k ++) {
112 z [ i ][ j ] +=
matAnswer [ i ][ k
]* w [ k ][ j ];
113 }
114 maxValue = max ( maxValue ,
fabs ( z [ i ][ j ]) ) ;
115 }
116 }
117
118 // comprobacion
119
120 for ( i =0; i < n ; i ++) {
121 if ( fabs ( z [ i ][0]) == maxValue ) {
122 break ;
123 }
124 }

12
125
126
127 // z = z / z [ end ]
128 for ( i =0; i < n ; i ++) {
129 z [ i ][0] /= z [n -1][0];
130 }
131
132 // hallar nueva norma
133 sum = 0.0;
134 for ( i =0; i < n ; i ++) {
135 sum += pow ( z [ i ][0] - w [ i ][0] , 2) ;
136 }
137 norma = sqrt ( sum ) ;
138 }
139
140 // autovalor = ( z ’* A * z ) /( z ’* z )
141
142 // zt = z ’
143 double zt [1][ n ];
144 for ( i =0; i < n ; i ++) {
145 zt [0][ i ] = z [ i ][0];
146 }
147
148 // ztA = z ’* A
149 double ztA [1][ n ];
150 for ( i =0; i <1; i ++) {
151 for ( j =0; j < n ; j ++) {
152 ztA [ i ][ j ] = 0.0;
153 for ( k =0; k < n ; k ++) {
154 ztA [ i ][ j ] += zt [ i ][ k ]*
matAnswer [ k ][ j ];
155 }
156 }
157 }
158
159 // ztAz = z ’* A * z
160 double ztAz = 0.0;
161 for ( i =0; i < n ; i ++) {
162 ztAz += ztA [0][ i ]* z [ i ][0];
163 }
164
165 // ztz = z ’* z
166 double ztz = 0.0;
167 for ( i =0; i < n ; i ++) {
168 ztz += z [ i ][0]* z [ i ][0];

13
169 }
170
171 // calculo del autovalor
172 double autovalor = 1.0* ztAz / ztz ;
173
174 printf ( " Autovalor dominante = %.2 lf \ n " , autovalor ) ;
175
176 fclose ( fp ) ;
177 return 0;
178 }

Figura 3: Autovalor dominante

14
5. bibliografı́a
https://es.wikipedia.org/wiki/M%C3%A9todo_iterativo

http://test.cua.uam.mx/MN/Methods/EcLineales/Jacobi/
Jacobi.php

https://es.wikipedia.org/wiki/M%C3%A9todo_de_Jacobi

15

También podría gustarte