void ConjugateGradient( int n, double** A, double* b, double* x) { int i, j, k, stop; double aux1 = 0, aux2 = 0, aux3 = 0; double *vaux = (double*)malloc(n*sizeof(double)); double *d0 = (double*)malloc(n*sizeof(double)), *r0 = (double*)malloc(n*sizeof(double)); double a0,b0; mat_multv(n,n, A, x, vaux); for(i = 0; i < n; i++) { d0[i] = b[i] - vaux[i]; r0[i] = b[i] - vaux[i]; } do { stop = 0; aux1 = 0;aux2 = 0;aux3=0; mat_multv(n,n,A, d0, vaux); for(j = 0; j < n; j++) { aux2 +=d0[j]*vaux[j]; aux1 += r0[j]*r0[j]; } a0 = aux1/aux2; for(j = 0; j < n; j++) { x[j] = x[j] + a0*d0[j]; r0[j] = r0[j] - a0*vaux[j]; aux3 += r0[j]*r0[j]; } b0 = aux3/aux1; for(j = 0; j < n; j++) d0[j] = r0[j] +b0*d0[j]; for (j = 0; j < n; j++) { if ( (r0[j]<0.02) && (r0[j]>-0.02) ) stop++; } }while(stop != n); free(r0); free(d0); free(vaux); }
int ConjugateGradient(int n, Matriz ***A, double* b, double *x, double tol){ double * Rk, *Rk1, *Dk, *temp; double Alfa, Beta; int i; Rk = (double*) calloc(n+IDX,sizeof(double)); Rk1 = (double*) calloc(n+IDX,sizeof(double)); Dk = (double*) calloc(n+IDX,sizeof(double)); temp = (double*) calloc(n+IDX,sizeof(double)); // D0 = R0= b - Ax; mat_multv(n,A,x,temp); mat_sumV(n, -1, b, temp,Rk); copiaV(n,Dk,Rk); // For K= 0...n-1 for (i = IDX; i < n+IDX; ++i){ // if (Rk = 0) stop if(mat_modulo(n, Rk) < 0.5*pow(10,-tol)) break; // Alfa = RkT*Rk / DkT * A *Dk mat_multv(n,A,Dk,temp); Alfa = mat_escalar_vu(n,Rk,Rk)/ mat_escalar_vu(n,temp,Dk); // Xk1 = Xk + Alfa*Dk mat_sumV(n,Alfa,x,Dk,x); //Rk1 = Rk - Alfa * A* Dk ;; Obs: temp já contém A*Dk mat_sumV(n, -1*Alfa,Rk,temp,Rk1); //Beta = Rk1T * Rk1 / RkT * Rk Beta = mat_escalar_vu(n,Rk1,Rk1) / mat_escalar_vu(n,Rk,Rk); //Dk1 = Rk1 + Beta*Dk mat_sumV(n,Beta,Rk1,Dk,Dk); //Atualiza o Rk copiaV(n,Rk,Rk1); } free(Rk); free(Rk1); free(Dk); free(temp); return i-IDX; }
void test_mat_multv() { double a[6] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0}; double** A = mat_from_vector(a, 2, 3); double v[3] = {10.0, 20.0, 30.0}; double w[2]; mat_multv(2, 3, A, v, w); assert(w[0] == 140.0); assert(w[1] == 320.0); }
int main (void) { double** A = mat_cria(3,3); double** B = mat_cria(3,2); double** C = mat_cria(3,3); double** D = mat_cria(3,2); double** E = mat_cria(2,5); double x[5]; double v[3]; double w[3]; double XE[2]; // Vetor v v[0] = 0; v[1] = 1; v[2] = 2; // vetor x x[0] = 1; x[1] = 2; x[2] = 3; x[3] = 4; x[4] = 5; // Matriz A A[0][0] = 1; A[0][1] = 2; A[0][2] = 3; A[1][0] = 4; A[1][1] = 5; A[1][2] = 6; A[2][0] = 7; A[2][1] = 8; A[2][2] = 9; // Matriz B B[0][0] = 0; B[0][1] = 1; B[1][0] = 0; B[1][1] = 1; B[2][0] = 0; B[2][1] = 1; //Matriz E E[0][0] = 1; E[0][1] = 2; E[0][2] = 3; E[0][3] = 4; E[0][4] = 5; E[1][0] = 1; E[1][1] = 2; E[1][2] = 3; E[1][3] = 4; E[1][4] = 5; // Imprime a matriz printf(" Matriz A \n"); printm(3,3,A); mat_transposta(3,3, A, C); printf("\n\n Matriz Transposta C \n"); printm(3,3,C); printf("\n\n Vetor resultante da multiplicacao Matriz A x Vetor V \n"); mat_multv(3,3, A, v, w); printf("%g\n%g\n%g\n", w[0], w[1], w[2]); mat_multm(3,3,2, A, B, D); printf(" Matriz resultante da multiplicacao Matriz A x Matriz B \n"); printm(3,2,D); printf("\n\n Vetor resultante da multiplicacao vetor x * matriz E \n"); mat_multv(2,5, E, x, XE); printf("%g\n%g\n\n", XE[0], XE[1]); mat_libera(3, A); mat_libera(3, B); mat_libera(3, C); mat_libera(3, D); return 0; }
int main(){ double *x,*b, *bbarra; int n =100, i, tol =5; Matriz*** A, ***M, ***N; for(n=100; n<=10000;n=n*10){ A = mat_esparsa(n); x = (double*) calloc(n+IDX,sizeof(double)); b = (double*) calloc(n+IDX,sizeof(double)); bbarra = (double*) calloc(n+IDX,sizeof(double)); //Vetor solução for(int i =IDX; i< n+IDX; i++) x[i]=1; // Calculo do vetor b correto obtido atraves de Ax = b mat_multv(n,A,x,b); /*****SEM PRECOND*****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de Sem PreCond , n= %d \n",n ); i = ConjugateGradient(n, A, b, x,tol); printf("\n\ti = %d \t\n",i ); /******Jacobi*********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; // Matriz pre condicionador de Jacobi M = JacobiPC(A, n); //Minv Ax = Minv b/ N = mat_cria(n,n); mat_multm(n,M,A,N); mat_multv(n, M, b, bbarra); printf("\n\tMetodo gradiente Conjugado com pre condicionador de Jacobi , n= %d \n",n ); // Metodo gradiente Conjugado com pre condicionador de Jacobi , n= 1000 i = ConjugateGradient(n, N, bbarra, x,tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); mat_libera(n,N); /******Gaus Seidel****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de GaussSeidel , n= %d \n",n ); M = pre_cond(A,n,1); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); /***** SSOR *********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de SSOR , n= %d \n",n ); M = pre_cond(A,n,1.5); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); //=======Fim do Loop======// free(x); free(b); free(bbarra); mat_libera(n,A); } for(n=100; n<=10000;n=n*10){ A = mat_esparsa_extend(n); x = (double*) calloc(n+IDX,sizeof(double)); b = (double*) calloc(n+IDX,sizeof(double)); bbarra = (double*) calloc(n+IDX,sizeof(double)); //Vetor solução for(int i =IDX; i< n+IDX; i++) x[i]=1; // Calculo do vetor b correto obtido atraves de Ax = b mat_multv(n,A,x,b); /*****SEM PRECOND*****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de Sem PreCond , n= %d \n",n ); i = ConjugateGradient(n, A, b, x,tol); printf("\n\ti = %d \t\n",i ); /******Jacobi*********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; // Matriz pre condicionador de Jacobi M = JacobiPC(A, n); //Minv Ax = Minv b/ N = mat_cria(n,n); mat_multm(n,M,A,N); mat_multv(n, M, b, bbarra); printf("\n\tMetodo gradiente Conjugado com pre condicionador de Jacobi , n= %d \n",n ); // Metodo gradiente Conjugado com pre condicionador de Jacobi , n= 1000 i = ConjugateGradient(n, N, bbarra, x,tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); mat_libera(n,N); /******Gaus Seidel****/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de GaussSeidel , n= %d \n",n ); M = pre_cond(A,n,1); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); /***** SSOR *********/ //Redefinição de x[] para estimativa inicial vetor nulo for(int i =IDX; i< n+IDX; i++) x[i]=0; printf("\n\tMetodo gradiente Conjugado com pre condicionador de SSOR , n= %d \n",n ); M = pre_cond(A,n,1.5); i = ConjugateGradientPC(n, A, M, b, x, tol); printf("\n\ti = %d \t\n",i ); mat_libera(n,M); //=======Fim do Loop======// free(x); free(b); free(bbarra); mat_libera(n,A); } }
int ConjugateGradientPC(int n, Matriz ***A,Matriz ***M, double *b, double *x, double tol){ double * Rk, *Rk1, *Dk, *temp, *w; double Alfa, Beta,y; int i; Rk = (double*) calloc(n+IDX,sizeof(double)); Rk1 = (double*) calloc(n+IDX,sizeof(double)); Dk = (double*) calloc(n+IDX,sizeof(double)); temp = (double*) calloc(n+IDX,sizeof(double)); w = (double*) calloc(n+IDX,sizeof(double)); //R0= b - Ax; mat_multv(n,A,x,temp); mat_sumV(n, -1, b, temp,Rk); //D0 = M_inv * R0 ou M*D0 = R0 ConjugateGradient(n,M,Rk,Dk,tol+1); ///Para a 1a vez o y eh diferente, muda o calculo de alpha y = mat_escalar_vu(n,Rk,Dk); // For K= 0...n-1 for (i = IDX; i < n+IDX; ++i){ // puts("A1"); // if (Rk = 0) stop if(mat_modulo(n, Rk) < 0.5*pow(10,-tol)) break; // puts("A2"); // Alfa = RkT*(Dk ou W) / DkT * A *Dk mat_multv(n,A,Dk,temp); Alfa = y/ mat_escalar_vu(n,temp,Dk); // Xk1 = Xk + Alfa*Dk mat_sumV(n,Alfa,x,Dk,x); //Rk1 = Rk - Alfa * A* Dk ;; Obs: temp já contém A*Dk mat_sumV(n, -1*Alfa,Rk,temp,Rk1); ////w = M_inv * R0 ou M*w = R0 ConjugateGradient(n,M,Rk,w,tol+1); /// y = mat_escalar_vu(n,Rk1,w); //Beta = Rk1T * w / RkT * Rk Beta = y / mat_escalar_vu(n,Rk,Rk); //Dk1 = w + Beta*Dk mat_sumV(n,Beta,w,Dk,Dk); //Atualiza o Rk copiaV(n,Rk,Rk1); } free(Rk); free(Rk1); free(Dk); free(temp); free(w); return i-IDX; }