я нашел хороший код для подбора полиномиальных наименьших квадратов на основе GSL.
Я использую его с 3 градусами: y = Cx² + Bx + A.
В моем приложении я знаю, что A должно быть нулем. Можно ли изменить алгоритм так, чтобы A всегда был нулевым?
bool polynomialfit(int obs, int degree,
double *dx, double *dy, double *store) /* n, p */
{
gsl_multifit_linear_workspace *ws;
gsl_matrix *cov, *X;
gsl_vector *y, *c;
double chisq;
int i, j;
X = gsl_matrix_alloc(obs, degree);
y = gsl_vector_alloc(obs);
c = gsl_vector_alloc(degree);
cov = gsl_matrix_alloc(degree, degree);
for(i=0; i < obs; i++) {
gsl_matrix_set(X, i, 0, 1.0);
for(j=0; j < degree; j++) {
gsl_matrix_set(X, i, j, pow(dx[i], j));
}
gsl_vector_set(y, i, dy[i]);
}
ws = gsl_multifit_linear_alloc(obs, degree);
gsl_multifit_linear(X, y, c, cov, &chisq, ws);
/* store result ... */
for(i=0; i < degree; i++)
{
store[i] = gsl_vector_get(c, i);
}
gsl_multifit_linear_free(ws);
gsl_matrix_free(X);
gsl_matrix_free(cov);
gsl_vector_free(y);
gsl_vector_free(c);
return true; /* we do not "analyse" the result (cov matrix mainly)
to know if the fit is "good" */
}
Вы можете заменить y на y ‘= y / x, а затем выполнить подгонку полинома 1. степени y’ = Cx + B?
(если точка x = 0 присутствует в вашем наборе данных, вы должны удалить ее, но эта точка не улучшает соответствие в случае, если вы хотите применить ограничение A = 0, вы все равно можете использовать его для повторного вычисления достоверности соответствия)
В размещенном вами коде есть этот цикл:
for(j=0; j < degree; j++) {
gsl_matrix_set(X, i, j, pow(dx[i], j));
}
и функция pow
вычисляет термины x ^ j, вы должны «игнорировать» термин где j==0
,
У меня нет доступа к GSL, и поэтому следующее не соответствует моей голове и не проверено:
bool polynomialfit(int obs, int polynom_degree,
double *dx, double *dy, double *store) /* n, p */
{
gsl_multifit_linear_workspace *ws;
gsl_matrix *cov, *X;
gsl_vector *y, *c;
double chisq;
int i, j;
int degree = polynom_degree - 1;
X = gsl_matrix_alloc(obs, degree);
y = gsl_vector_alloc(obs);
c = gsl_vector_alloc(degree);
cov = gsl_matrix_alloc(degree, degree);
for(i=0; i < obs; i++) {
gsl_matrix_set(X, i, 0, 1.0);
for(j=0; j < degree; j++) {
gsl_matrix_set(X, i, j, pow(dx[i], j+1));
}
gsl_vector_set(y, i, dy[i]);
}
ws = gsl_multifit_linear_alloc(obs, degree);
gsl_multifit_linear(X, y, c, cov, &chisq, ws);
/* store result ... */
for(i=0; i < degree; i++)
{
store[i] = gsl_vector_get(c, i);
}
gsl_multifit_linear_free(ws);
gsl_matrix_free(X);
gsl_matrix_free(cov);
gsl_vector_free(y);
gsl_vector_free(c);
return true; /* we do not "analyse" the result (cov matrix mainly)
to know if the fit is "good" */
}
Для того, чтобы соответствовать y=c*x*x+b*x
ты должен позвонить с polynom_degree
установлен в 3
,
Вы также можете взглянуть на теорию:
Вайштайн, Эрик У. «Фитинг наименьших квадратов — полином». От MathWorld—Веб-ресурс Wolfram. http://mathworld.wolfram.com/LeastSquaresFittingPolynomial.html