-1

I am trying to fit a curve to a set of points with GSL. I am not very experienced with GSL and took help from chatGPT for the same. But the code isnt compiling, and after a while i felt like was talking to a doorknob. I was wondering someone can help me out.

I am trying to fit a ridge regression but with the additional constraint that the difference between the params of the curve are also minimized.

#include <iostream>
#include <vector>
#include <gsl/gsl_multifit.h>

// Ridge loss function with regularization term and parameter difference constraints
int ridge_loss_with_constraints(const gsl_vector* x, void* params, gsl_vector* f) {
    gsl_vector* c = (gsl_vector*)params; // Coefficients (a, b, c) at time t2
    gsl_vector* c_t1 = (gsl_vector*)params + 3; // Coefficients (a_t1, b_t1, c_t1) at time t1

    double a = gsl_vector_get(c, 0);
    double b = gsl_vector_get(c, 1);
    double c_val = gsl_vector_get(c, 2);

    double a_t1 = gsl_vector_get(c_t1, 0);
    double b_t1 = gsl_vector_get(c_t1, 1);
    double c_t1_val = gsl_vector_get(c_t1, 2);

    double lambda = 0.1; // Regularization parameter
    double regularization_term = lambda * (a * a + b * b + c_val * c_val);

    // Calculate squared differences between parameters at t1 and t2
    double diff_a = a - a_t1;
    double diff_b = b - b_t1;
    double diff_c = c_val - c_t1_val;
    double parameter_difference_term = diff_a * diff_a + diff_b * diff_b + diff_c * diff_c;

    // Calculate the fitted values using the current parameters
    for (size_t i = 0; i < x->size; ++i) {
        double xi = gsl_vector_get(x, i);
        double fitted_y = a * xi * xi + b * xi + c_val;
        gsl_vector_set(f, i, fitted_y + regularization_term + parameter_difference_term);
    }

    return GSL_SUCCESS;
}

int main() {
    // Sample data points (x, y)
    std::vector<double> x_data = {1.0, 2.0, 3.0, 4.0, 5.0};
    std::vector<double> y_data = {2.5, 3.7, 4.8, 5.9, 7.1};

    // Number of data points
    size_t n = x_data.size();

    // Define the dependent variable vector 'y'
    gsl_vector* y = gsl_vector_alloc(n);
    for (size_t i = 0; i < n; ++i) {
        gsl_vector_set(y, i, y_data[i]);
    }

    // Initialize the coefficient vectors for time t2 and t1
    gsl_vector* c = gsl_vector_alloc(3); // Coefficients (a, b, c) at time t2
    gsl_vector* c_t1 = gsl_vector_alloc(3); // Coefficients (a_t1, b_t1, c_t1) at time t1

    // Set coefficients at time t1 (replace with actual values)
    gsl_vector_set(c_t1, 0, 1/* a_t1 value */);
    gsl_vector_set(c_t1, 1, 1/* b_t1 value */);
    gsl_vector_set(c_t1, 2, 1/* c_t1 value */);

    // Combine the coefficient vectors for use in the ridge_loss_with_constraints function
    gsl_vector* combined_params = gsl_vector_alloc(6); // [a, b, c, a_t1, b_t1, c_t1]
    for (size_t i = 0; i < 3; ++i) {
        gsl_vector_set(combined_params, i, gsl_vector_get(c, i));
        gsl_vector_set(combined_params, i + 3, gsl_vector_get(c_t1, i));
    }

    // Initialize the fitting function
    gsl_multifit_function f;
    f.f = ridge_loss_with_constraints;
    f.n = n;
    f.p = 3;
    f.params = combined_params;

    // Perform the fit using the Levenberg-Marquardt optimization algorithm
    gsl_multifit_fdfsolver* solver = gsl_multifit_fdfsolver_alloc(gsl_multifit_fdfsolver_lmsder, n, 3);
    gsl_multifit_fdfsolver_set(solver, &f, c);

    // Print the results
    std::cout << "Fitted coefficients with L2 regularization and constraints: Intercept = "
              << gsl_vector_get(c, 0) << ", Slope = " << gsl_vector_get(c, 1) << ", c-term = " << gsl_vector_get(c, 2) << std::endl;

    // Free GSL objects
    gsl_vector_free(y);
    gsl_vector_free(c);
    gsl_vector_free(c_t1);
    gsl_vector_free(combined_params);
    gsl_multifit_fdfsolver_free(solver);

    return 0;
}

I am compiling with the following g++ -o my_program ridge_regression3.cpp -lgsl -lgslcblas -lm -O3

Some of the errors I get are:

ridge_regression3.cpp: In function ‘int main()’:
ridge_regression3.cpp:68:5: error: ‘gsl_multifit_function’ was not declared in this scope; did you mean ‘gsl_multifit_linear’?
   68 |     gsl_multifit_function f;
      |     ^~~~~~~~~~~~~~~~~~~~~
      |     gsl_multifit_linear
ridge_regression3.cpp:69:5: error: ‘f’ was not declared in this scope
   69 |     f.f = ridge_loss_with_constraints;
      |     ^
ridge_regression3.cpp:75:5: error: ‘gsl_multifit_fdfsolver’ was not declared in this scope; did you mean ‘gsl_multifit_robust’?
   75 |     gsl_multifit_fdfsolver* solver = gsl_multifit_fdfsolver_alloc(gsl_multifit_fdfsolver_lmsder, n, 3);
      |     ^~~~~~~~~~~~~~~~~~~~~~
      |     gsl_multifit_robust
ridge_regression3.cpp:75:29: error: ‘solver’ was not declared in this scope
   75 |     gsl_multifit_fdfsolver* solver = gsl_multifit_fdfsolver_alloc(gsl_multifit_fdfsolver_lmsder, n, 3);
      |                             ^~~~~~
ridge_regression3.cpp:75:67: error: ‘gsl_multifit_fdfsolver_lmsder’ was not declared in this scope
   75 |     gsl_multifit_fdfsolver* solver = gsl_multifit_fdfsolver_alloc(gsl_multifit_fdfsolver_lmsder, n, 3);
      |                                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ridge_regression3.cpp:75:38: error: ‘gsl_multifit_fdfsolver_alloc’ was not declared in this scope; did you mean ‘gsl_multifit_robust_alloc’?
   75 |     gsl_multifit_fdfsolver* solver = gsl_multifit_fdfsolver_alloc(gsl_multifit_fdfsolver_lmsder, n, 3);
      |                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                      gsl_multifit_robust_alloc
ridge_regression3.cpp:76:5: error: ‘gsl_multifit_fdfsolver_set’ was not declared in this scope; did you mean ‘gsl_multifit_robust_est’?
   76 |     gsl_multifit_fdfsolver_set(solver, &f, c);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~
      |     gsl_multifit_robust_est
ridge_regression3.cpp:87:5: error: ‘gsl_multifit_fdfsolver_free’ was not declared in this scope; did you mean ‘gsl_multifit_robust_free’?
   87 |     gsl_multifit_fdfsolver_free(solver);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
      |     gsl_multifit_robust_free

I tried reading the documentation here but there is a lot which I dont understand.

Thanks in advance.

  • The shown code doesn't have the usage of `gsl_multifit_function_fdf`. Have you saved your code before compiling it? – 273K Aug 08 '23 at 16:01
  • @273K there was an error in pasting the code here. I have updated the question. Yes, I have saved the code before compiling it. – gundechaHills Aug 08 '23 at 16:15
  • It compiles well if you use a proper `#include `. – 273K Aug 08 '23 at 16:32
  • doest compile for me: g++ -o my_program ridge_regression3.cpp -lgsl -lgslcblas -lm -O3 ridge_regression3.cpp: In function ‘int main()’: ridge_regression3.cpp:77:40: error: cannot convert ‘gsl_multifit_function*’ {aka ‘gsl_multifit_function_struct*’} to ‘gsl_multifit_function_fdf*’ {aka ‘gsl_multifit_function_fdf_struct*’} – gundechaHills Aug 08 '23 at 16:41
  • 3
    `error: cannot convert ‘gsl_multifit_function*’ to ‘gsl_multifit_function_fdf*` - what don't you understand? – 273K Aug 08 '23 at 16:45

1 Answers1

0

To make the snippet compile:

  1. Include gsl/gsl_multifit_nlin.h:

    #include <gsl/gsl_multifit_nlin.h>

  2. The 2nd parameter of gsl_multifit_fdfsolver_set doesn't match, so change gsl_multifit_function f; to gsl_multifit_function_fdf f;

The program still Segfaults, but now it compiles.

Csaba Toth
  • 10,021
  • 5
  • 75
  • 121