| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Esse capítulo descreve funções para o cálculo de suavisação de splines base (B-splines). Um spline suavisada difere de um spline interpolada na curva resultante onde não é requerido que a mesma passe através de cada ponto de dados. Veja Veja seção Interpolação, para informação sobre interpolação de splines.
O arquivo de cabeçalho ‘gsl_bspline.h’ contém os protótipos para as funções bspline e declarações relacionadas.
| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
B-splines são comumente usadas como funções base para ajustar curvas
planas para grandes conjuntos de dados. Para fazer isso, o eixo das abscissas é
quebrado em algum número de intervalos, onde as extremidades
de cada intervalo são chamadas pontos de parada. Esses pontos de parada
são então convertidos para nós impondo-se várias condições de
continuidade e suavisação em cada interface. Dado um não decrescente
vetor de nós
t = {t_0, t_1, …, t_{n+k-1}},
as n splines base de ordem k são definidas por
|
|
Se definirmos nós apropriados sobre um intervalo [a,b] então
as funções B-spline base formam um completo conjunto sobre aquele intervalo.
Todavia podemos expandir uma função de suavisação como
|
| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O cálculo de funções B-spline requerem um pré-alocado
espaço de trabalho do tipo gsl_bspline_workspace. Se derivadas
de B-spline forem também requeridas, um adicional
é necessário gsl_bspline_deriv_workspace.
Essa função aloca um espaço de trabalho para calcular B-splines de ordem k. O número de pontos de parada é dado por nbreak. Isso conduz a n = nbreak + k - 2 funções base. B-splines cúbicas são especificadas por k = 4. O tamanho do espaço de trabalho é O(5k + nbreak).
Essa função libera a memória associada ao espaço de trabalho w.
Essa função aloca um espaço de trabalho para calcular as derivadas de uma função B-spline base de ordem k. O tamanho do espaço de trabalho é O(2k^2).
Essa função libera a memória associada ao espaço de trabalho de derivadas w.
| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Essa função calcula os nós associados aos dados pontos de parada
e armazena-os internamente em w->knots.
Essa função assume pontos de parada uniformemente espaçados no intervalo [a,b]
e constrói o correspondente vetor de nós usando o préviamente
especificado parâmetro nbreak. Os nós são armazenados em
w->knots.
| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Essa função avalia todas funções B-spline base na posição
x e armazena-as no vetor B, de forma que o i-ésimo elemento
é B_i(x). O vetor B deve ser de comprimento
n = nbreak + k - 2. Esse valor pode também ser obtido chamando
gsl_bspline_ncoeffs.
Calculando todas as funções de base uma única vez é mais eficiente que
calculá-las individualmente, devido à natureza de definir
relações de recorrência.
Essa função avalia todos potencialmente não nulas funções B-spline base na posição x e armazena-as em um vetor Bk, de forma que o i-ésimo elemento seja B_(istart+i)(x). O último elemento de Bk é B_(iend)(x). O vetor Bk deve ser de comprimento k. Por meio do retorno de somente funções de base não nulas, essa função permite que quantidades envolvendo combinações lineares de B_i(x) sejam calculadas sem termos desnecessários (tal combinação linear ocorre, por exemplo, quando avalia-se uma função interpolada).
Essa função retorna o número de coeficientes de B-spline dado por n = nbreak + k - 2.
| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Essa função avalia todas as derivadas de funções B-spline base de ordem
0 até a ordem nderiv (inclusive) na posição x
e armazena-as na matriz dB. O (i,j)-ésimo elemento de dB
é d^jB_i(x)/dx^j. A matriz dB deve ser
de tamanho n = nbreak + k - 2 por nderiv + 1.
O valor n pode também ser obtida
chamando gsl_bspline_ncoeffs. Note que funções de avaliações
são incluídas como a derivada de zero-ésima ordem em dB.
calculando todas as derivadas de função base de uma vez é mais eficiente
que calculá-las individualmente, devido à natureza da definição da
relação de recorrência.
Essa função avalia todas as potencialmente não nulas derivadas de funções B-spline base de ordem 0 até a ordem nderiv (inclusive) na posição x e armazena-as na matriz dB. O (i,j)-ésimo elemento de dB é d^j/dx^j B_(istart+i)(x). A última linha de dB contém d^j/dx^j B_(iend)(x). A matriz dB deve ser de tamanho k o qual deve ser pelo menos nderiv + 1. Note que avaliações de função são incluídas como derivadas de zero-ésima ordem em dB. Por meio do retorno somente as funções base não nulas, essa função permite que quantidades envolvendo combinações lineares dos B_i(x) com suas derivadas sejam calculadas sem termos desnecessários.
| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
As abscissas de Greville são definidas para serem a localização média de k-1
nós consecutivos no vetor de nós para cada função spline base de ordem
k. Com o primeiro e últimos nós no vetor de nós no
gsl_bspline_workspace excluídos, existem gsl_bspline_ncoeffs abscissas de Greville
para qualquer dado B-spline base. Esses valores são muitas vezes usados em aplicações de
colocação de B-spline e pode também serem chamados pontos de Marsden-Schoenberg.
Retorna a localização da i-ésima abscissa de Greville para a dada B-spline base. Para o pior caso sendo k=1, a implementação escolhe retornar o ponto médio entre dois pontos de parada.
| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O seguinte programa calcula um ajuste linear por mínimos quadrados para dados usando funções de B-splines base cúbicas com pontos de parada uniforme. Os dados são gerados a partir da curva y(x) = \cos{(x)} \exp{(-x/10)} sobre o intervalo [0, 15] com ruído de Gauss adicionado.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gsl/gsl_bspline.h>
#include <gsl/gsl_multifit.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_statistics.h>
/* number of data points to fit */
#define N 200
/* number of fit coefficients */
#define NCOEFFS 12
/* nbreak = ncoeffs + 2 - k = ncoeffs - 2 since k = 4 */
#define NBREAK (NCOEFFS - 2)
int
main (void)
{
const size_t n = N;
const size_t ncoeffs = NCOEFFS;
const size_t nbreak = NBREAK;
size_t i, j;
gsl_bspline_workspace *bw;
gsl_vector *B;
double dy;
gsl_rng *r;
gsl_vector *c, *w;
gsl_vector *x, *y;
gsl_matrix *X, *cov;
gsl_multifit_linear_workspace *mw;
double chisq, Rsq, dof, tss;
gsl_rng_env_setup();
r = gsl_rng_alloc(gsl_rng_default);
/* allocate a cubic bspline workspace (k = 4) */
bw = gsl_bspline_alloc(4, nbreak);
B = gsl_vector_alloc(ncoeffs);
x = gsl_vector_alloc(n);
y = gsl_vector_alloc(n);
X = gsl_matrix_alloc(n, ncoeffs);
c = gsl_vector_alloc(ncoeffs);
w = gsl_vector_alloc(n);
cov = gsl_matrix_alloc(ncoeffs, ncoeffs);
mw = gsl_multifit_linear_alloc(n, ncoeffs);
printf("#m=0,S=0\n");
/* this is the data to be fitted */
for (i = 0; i < n; ++i)
{
double sigma;
double xi = (15.0 / (N - 1)) * i;
double yi = cos(xi) * exp(-0.1 * xi);
sigma = 0.1 * yi;
dy = gsl_ran_gaussian(r, sigma);
yi += dy;
gsl_vector_set(x, i, xi);
gsl_vector_set(y, i, yi);
gsl_vector_set(w, i, 1.0 / (sigma * sigma));
printf("%f %f\n", xi, yi);
}
/* use uniform breakpoints on [0, 15] */
gsl_bspline_knots_uniform(0.0, 15.0, bw);
/* construct the fit matrix X */
for (i = 0; i < n; ++i)
{
double xi = gsl_vector_get(x, i);
/* compute B_j(xi) for all j */
gsl_bspline_eval(xi, B, bw);
/* fill in row i of X */
for (j = 0; j < ncoeffs; ++j)
{
double Bj = gsl_vector_get(B, j);
gsl_matrix_set(X, i, j, Bj);
}
}
/* do the fit */
gsl_multifit_wlinear(X, w, y, c, cov, &chisq, mw);
dof = n - ncoeffs;
tss = gsl_stats_wtss(w->data, 1, y->data, 1, y->size);
Rsq = 1.0 - chisq / tss;
fprintf(stderr, "chisq/dof = %e, Rsq = %f\n",
chisq / dof, Rsq);
/* output the smoothed curve */
{
double xi, yi, yerr;
printf("#m=1,S=0\n");
for (xi = 0.0; xi < 15.0; xi += 0.1)
{
gsl_bspline_eval(xi, B, bw);
gsl_multifit_linear_est(B, c, cov, &yi, &yerr);
printf("%f %f\n", xi, yi);
}
}
gsl_rng_free(r);
gsl_bspline_free(bw);
gsl_vector_free(B);
gsl_vector_free(x);
gsl_vector_free(y);
gsl_matrix_free(X);
gsl_vector_free(c);
gsl_vector_free(w);
gsl_matrix_free(cov);
gsl_multifit_linear_free(mw);
return 0;
} /* main() */
A saída pode ser mostrada com o GNU graph.
$ ./a.out > bspline.dat chisq/dof = 1.118217e+00, Rsq = 0.989771 $ graph -T ps -X x -Y y -x 0 15 -y -1 1.3 < bspline.dat > bspline.ps

| [ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Informação adicional sobre os algoritmos descritos nessa seção pode ser encontrado no seguinte livro,
Informação adicional sobre as abscissas de Greville e colocação de B-spline pode ser encontrado no seguinte artigo,
Uma grande coleção de rotinas B-spline está disponivel na biblioteca PPPACK disponível em http://www.netlib.org/pppack, que é também parte de SLATEC.
| [ << ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Esse documento foi gerado em 23 de Julho de 2013 usando texi2html 5.0.