Use o botão abaixo para reportar erros ou dar sugestões.

Computação Científica - Um Livro Colaborativo

13.4 GSL - álgebra linear


O gsl resolve problemas em álgebra linear por diversos métodos. Aqui nós vamos trabalhar apenas com a decomposição QR e sistemas tridiagonais. O pacote para álgebra linear é gsl_linalg.h.

  • int gsl_linalg_QR_decomp(gsl_matrix * A, gsl_vector * tau): calcula a decomposição QR da matriz A.
  • int gsl_linalg_QR_solve(const gsl_matrix * QR, const gsl_vector * tau, const gsl_vector * b, gsl_vector * x): resolve o Ax = b usando a decomposição QR.

Exemplo 13.4.1. Implemente um código para resolver o sistema 3x + y + z = 1 −x − 4y + 2z = 2 −2x + 2y + 5z = 3

usando decomposição QR da biblioteca gsl.

#include <stdio.h>  
#include <math.h>  
#include <gsl/gsl_vector.h>  
#include <gsl/gsl_matrix.h>  
#include <gsl/gsl_linalg.h>  
 
main (void)  
{  
  gsl_vector *tau=gsl_vector_alloc(3);  
  gsl_vector *b=gsl_vector_alloc(3);  
  gsl_vector *x=gsl_vector_alloc(3);  
  gsl_matrix *A=gsl_matrix_alloc(3,3);;  
  gsl_matrix_set(A,0,0,3);  
  gsl_matrix_set(A,0,1,1);  
  gsl_matrix_set(A,0,2,1);  
  gsl_matrix_set(A,1,0,-1);  
  gsl_matrix_set(A,1,1,-4);  
  gsl_matrix_set(A,1,2,2);  
  gsl_matrix_set(A,2,0,-2);  
  gsl_matrix_set(A,2,1,2);  
  gsl_matrix_set(A,2,2,5);  
  gsl_vector_set(b,0,1);  
  gsl_vector_set(b,1,2);  
  gsl_vector_set(b,2,3);  
  int i,j;  
  for (i=0;i<3;i++)  
  {  
    for (j=0;j<3;j++) printf("A[%d,%d] = %f ",i,j,gsl_matrix_get(A,i,j));  
  printf("\n");  
  }  
  for (i=0;i<3;i++) printf("b[%d] = %f\n",i,gsl_vector_get(b,i));  
  gsl_linalg_QR_decomp(A, tau);  
  gsl_linalg_QR_solve(A, tau,b,x);  
  for (i=0;i<3;i++) printf("solucao[%d] = %f\n",i,gsl_vector_get(x,i));  
}

O comando

  • int gsl_linalg_QR_lssolve(const gsl_matrix * QR, const gsl_vector * tau, const gsl_vector * b, gsl_vector * x, gsl_vector * residual) resolve sistema impossível (quando possui mais linhas independes que colunas) pelo critério de mínimos quadrados.

Exemplo 13.4.2. Implemente um código para calcular os coeficientes de uma reta que melhor se ajusta aos pontos: (0,1),(1,0.5), (2, − 0.2), (3, − 0.7).

Supondo que a reta tenha equação y = ax + b, temos b = 1 (13.1) a + b = 0.5 (13.2) 2a + b = −0.2 (13.3) 3a + b = −0.7 (13.4)

um sistema que pode ser resolvido pelo critério dos mínimos quadrados. Na forma matricial, temos 0 1 1 1 2 1 3 1 a b = 1 0.5 − 0.2 − 0.7 .

Vamos resolver usando a decomposição QR.

#include <stdio.h>  
#include <math.h>  
#include <gsl/gsl_vector.h>  
#include <gsl/gsl_matrix.h>  
#include <gsl/gsl_linalg.h>  
 
main (void)  
{  
  gsl_vector *tau=gsl_vector_alloc(2);  
  gsl_vector *b=gsl_vector_alloc(4);  
  gsl_vector *x=gsl_vector_alloc(2);  
  gsl_vector *residual=gsl_vector_alloc(4);  
  gsl_matrix *A=gsl_matrix_alloc(4,2);;  
  gsl_matrix_set(A,0,0,0);  
  gsl_matrix_set(A,0,1,1);  
  gsl_matrix_set(A,1,0,1);  
  gsl_matrix_set(A,1,1,1);  
  gsl_matrix_set(A,2,0,2);  
  gsl_matrix_set(A,2,1,1);  
  gsl_matrix_set(A,3,0,3);  
  gsl_matrix_set(A,3,1,1);  
  gsl_vector_set(b,0,1);  
  gsl_vector_set(b,1,0.5);  
  gsl_vector_set(b,2,-0.2);  
  gsl_vector_set(b,3,-0.7);  
 
  int i,j;  
  for (i=0;i<4;i++)  
  {  
    for (j=0;j<2;j++) printf("A[%d,%d] = %f ",i,j,gsl_matrix_get(A,i,j));  
  printf("\n");  
  }  
  for (i=0;i<4;i++) printf("b[%d] = %f\n",i,gsl_vector_get(b,i));  
  gsl_linalg_QR_decomp(A, tau);  
  gsl_linalg_QR_lssolve(A, tau,b,x,residual);  
  for (i=0;i<2;i++) printf("solucao[%d] = %f\n",i,gsl_vector_get(x,i));  
  for (i=0;i<4;i++) printf("residuo[%d] = %f\n",i,gsl_vector_get(residual,i));  
}

A função

  • int gsl_linalg_solve_tridiag(const gsl_vector * diag, const gsl_vector * e, const gsl_vector * f, const gsl_vector * b, gsl_vector * x) resolve o sistema tridiagonal d0 e0 0 0 ⋯ 0 f0 d1 e1 0 ⋯ 0 0 f1 d2 e2 ⋯ 0 ⋮ ⋮ ⋱ 0 ⋯ 0 fn−2 dn−1 en−1 0 ⋯ 0 0 fn−1 dn x1 x2 x3 ⋮ x n−1 xn = b1 b2 b3 ⋮ b n−1 bn .

Exemplo 13.4.3. Vamos resolver novamente o problema do exemplo 6.3.2 usando a rotina gsl para sistemas tridiagonais.

O PVC do problema − uxx + ux = 200e−(x−1)2,0 < x < 1. 15u(0) + u′(0) = 500 10u(1) + u′(1) = 1

possui a seguinte versão discreta

15 − 1 h 1 h 0 0 0 ⋯ 0 − 1 h2 − 1 2h 2 h2 − 1 h2 + 1 2h 0 0 ⋯ 0 0 − 1 h2 − 1 2h 2 h2 − 1 h2 + 1 2h 0 ⋯ 0 ⋮⋮⋮⋮⋱⋮ 0 ⋯ 0 0 − 1 h2 − 1 2h 2 h2 − 1 h2 + 1 2h 0 ⋯ 0 0 0 − 1 h 10 + 1 h u1 u2 u3 ⋮ u N−1 uN = 500 200e−(x2−1)2 200e−(x3−1)2 ⋮ 200e−(xN−1−1)2 1

onde xi = h(i − 1), i = 1,2,...,N, h = 1 N−1.

#include <stdio.h>  
#include <math.h>  
#include <gsl/gsl_vector.h>  
#include <gsl/gsl_matrix.h>  
#include <gsl/gsl_linalg.h>  
#define N 10  
 
main (void)  
{  
  gsl_vector *d=gsl_vector_alloc(N);  
  gsl_vector *f=gsl_vector_alloc(N-1);  
  gsl_vector *e=gsl_vector_alloc(N-1);  
  gsl_vector *sol=gsl_vector_alloc(N);  
  gsl_vector *b=gsl_vector_alloc(N);  
  double h=1./(N-1);  
  int i,j;  
  //malha  
  gsl_vector *x=gsl_vector_alloc(N);  
  for (i=0;i<N;i++) gsl_vector_set(x,i,i*h);  
  for (i=0;i<N;i++) printf("x[%d] = %f\n",i,gsl_vector_get(x,i));  
 
  //sistema  
  gsl_vector_set(d,0,15-1/h);  
  gsl_vector_set(e,0,1/h);  
  gsl_vector_set(b,0,500);  
  for (i=1;i<N-1;i++)  
  {  
    gsl_vector_set(d,i,2/(h*h));  
    gsl_vector_set(e,i,-1/(h*h)+1/(2*h));  
    gsl_vector_set(f,i-1,-1/(h*h)-1/(2*h));  
    gsl_vector_set(b,0,200*exp(-(gsl_vector_get(x,i)-1)*(gsl_vector_get(x,i)-1)));  
  }  
  gsl_vector_set(d,N-1,10+1/h);  
  gsl_vector_set(f,N-2,-1/h);  
  gsl_linalg_solve_tridiag(d,e,f,b,sol);  
  for (i=0;i<N;i++) printf("solucao[%d] = %f\n",i,gsl_vector_get(sol,i));  
}

Creative Commons License Este texto é disponibilizado nos termos da licença Creative Commons Atribuição-CompartilhaIgual 3.0 Não Adaptada (CC-BY-SA 3.0). Página gerada em 19/8/2020 às 17:33:17.

Informe erros ou edite você mesmo!