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
usando a decomposição QR.
Exemplo 13.4.1. Implemente um código para resolver o sistema
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: ,,
,
.
Supondo que a reta tenha equação
,
temos
um sistema que pode ser resolvido pelo critério dos mínimos quadrados. Na
forma matricial, temos
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
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
possui a seguinte versão discreta
|
|
onde ,
,
.
#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));
}