Non-linear Least Squares with Ceres Solver and external Fortran function

117 views
Skip to first unread message

Heinz Alfons

unread,
Sep 23, 2022, 5:08:50 AM9/23/22
to Ceres Solver
Hi,
I'm new to C++ and trying to use Google's Ceres solver for solving a Non-linear Least Squares problem. I'm using an external fortran function that returns 10 values which I want to use as my loss values of the least squares problem. As I understand I need to somehow wrap each value in a residual block, however then in each block the Fortran function has to be recomputed. Is there a better way to do it? Maybe with some small example code? I've already been able to minimize the loss of the function using LBFGS as follows:
void minimizer() {
    struct Approx {
      bool operator()(const double* parameters, double* cost) const {
        cost[0] = fortran_minimizer_sum(parameters, additional_params);
        return true;
      }

      static ceres::FirstOrderFunction* Create() {
        constexpr int kNumParameters = 12;
        return new ceres::NumericDiffFirstOrderFunction<Approx,
                                                        ceres::CENTRAL,
                                                        kNumParameters>(new Approx);
      }
    };
   
    ceres::GradientProblemSolver::Options options;

    ceres::GradientProblemSolver::Summary summary;
    ceres::GradientProblem problem(Approx::Create());

    ceres::Solve(options, problem, parameters, &summary);
}

Now, how can I use the Trust Region solver of Ceres to to the same with a slightly different fortran function "fortran_minimizer" that doesn't only have one single cost/loss value but multiple loss values that I want to use as input to a Non-linear Least Squares solver?

Thank you
Heinz

Heinz Alfons

unread,
Sep 23, 2022, 5:12:17 AM9/23/22
to Ceres Solver
Sorry, the way I wrote it may be a bit confusing, the "fortran_minimizer" function I want to use returns 10 loss values that I want to use as my least squares. I wrote the helper function fortran_minimizer_sum that just computes the squared sum of these values in order to use it in the operator function.

Dmitriy Korchemkin

unread,
Sep 23, 2022, 5:58:19 AM9/23/22
to ceres-...@googlegroups.com
Heinz,

If you want to continue using numeric differentiation - you can use ceres::NumericDiffCostFunction . http://ceres-solver.org/nnls_modeling.html#_CPPv4N5ceres23NumericDiffCostFunctionE
Example in the documentation works with a single residual, but there are a number of examples for larger residual blocks in ceres/internal/numeric_diff_cost_function_test.cc ( + internal/ceres/numeric_diff_test_utils.h, internal/ceres/numeric_diff_test_utils.cc).

--
You received this message because you are subscribed to the Google Groups "Ceres Solver" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceres-solver...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/dad2f8e6-219d-4205-88f7-2d33282cfef2n%40googlegroups.com.


--
Dmitriy A Korchemkin

Heinz Alfons

unread,
Sep 23, 2022, 8:15:32 AM9/23/22
to Ceres Solver
I want to use the Levenberg-Marquardt method, is that possible with ceres::NumericDiffCostFunction?

Dmitriy Korchemkin

unread,
Sep 23, 2022, 9:10:49 AM9/23/22
to ceres-...@googlegroups.com
Yes, you can use NumericDiffCostFunction with Levenberg-Marquardt optimizer; you can find a complete minimal example (from cost functor class to invocation of solver) in examples/examples/helloworld_numeric_diff.cc .

You'll need to change the number of residuals and parameters in template arguments according to your optimization problem. If dimensionality of residuals / parameters is unknown at compile time, there is a DynamicNumericDiffCostFunction class.



--
Dmitriy A Korchemkin
Reply all
Reply to author
Forward
0 new messages