LBFGS++ Documentation

repository·master·Indexed 20 days ago

https://github.com/yixuan/lbfgspp

A header-only C++ library providing implementations of the L-BFGS algorithm for unconstrained minimization and the L-BFGS-B algorithm for box-constrained optimization problems. It relies on the Eigen library for linear algebra and supports custom line search algorithms.

Tokens
1.3K
Snippets
4
Records
4
Agent score
21%

What's inside LBFGS++

  1. Integrate LBFGS++ with Bazel

    master

    LBFGS++ can be integrated into Bazel projects using Bzlmod.

    1. Add the dependency to your MODULE.bazel file:
    bazel_dep(name = "lbfgspp", version = "4.0.0")
    git_override(
        module_name = "lbfgspp",
        commit = "c524a407fb85b74807f53de5a3ca2ddbcc164e54",
        remote = "https://github.com/yixuan/LBFGSpp.git",
    )
    1. Add @lbfgspp to the deps of your cc_library, cc_binary, or cc_test target in your BUILD.bazel file. Bazel will automatically resolve the transitive dependency on @eigen.
    # BUILD.bazel
    
    cc_library(
        name = "my_lib",
        srcs = ["my_lib.cc"],
        hdrs = ["my_lib.h"],
        deps = ["@lbfgspp"],
    )
  2. How to use LBFGS++ for unconstrained minimization

    master

    To use LBFGS++ for unconstrained optimization, you must define a functor (a class or struct) that represents your multivariate function. This functor must implement an operator() that takes a position vector x and a gradient vector grad, returning the objective function value as a double and populating grad with the evaluated gradient at x.

    Steps to minimize:

    1. Define your function functor.
    2. Configure parameters using LBFGSParam<T> (e.g., epsilon, max_iterations).
    3. Instantiate LBFGSSolver<T> with your parameters.
    4. Provide an initial guess vector x.
    5. Call solver.minimize(fun, x, fx), where x is overwritten with the optimal point and fx stores the minimum value.
    #include <Eigen/Core>
    #include <iostream>
    #include <LBFGS.h>
    
    using Eigen::VectorXd;
    using namespace LBFGSpp;
    
    class Rosenbrock
    {
    private:
        int n;
    public:
        Rosenbrock(int n_) : n(n_) {}
        double operator()(const VectorXd& x, VectorXd& grad)
        {
            double fx = 0.0;
            for(int i = 0; i < n; i += 2)
            {
                double t1 = 1.0 - x[i];
                double t2 = 10 * (x[i + 1] - x[i] * x[i]);
                grad[i + 1] = 20 * t2;
                grad[i]     = -2.0 * (x[i] * grad[i + 1] + t1);
                fx += t1 * t1 + t2 * t2;
            }
            return fx;
        }
    };
    
    int main()
    {
        const int n = 10;
        LBFGSParam<double> param;
        param.epsilon = 1e-6;
        param.max_iterations = 100;
    
        LBFGSSolver<double> solver(param);
        Rosenbrock fun(n);
    
        VectorXd x = VectorXd::Zero(n);
        double fx;
        int niter = solver.minimize(fun, x, fx);
    
        return 0;
    }
  3. How to use LBFGSBSolver for box-constrained problems

    master

    If your optimization problem has simple bounds (lower and upper limits for each variable), use the LBFGSBSolver class.

    Key differences from the unconstrained solver:

    1. Include <LBFGSB.h> instead of <LBFGS.h>.
    2. Use LBFGSBParam<T> for configuration.
    3. Instantiate LBFGSBSolver<T>.
    4. Provide lower bounds (lb) and upper bounds (ub) as Eigen::VectorXd to the minimize method.

    You can represent infinite bounds by using std::numeric_limits<double>::infinity() for the corresponding index in the bounds vectors.

    #include <Eigen/Core>
    #include <iostream>
    #include <LBFGSB.h>
    
    using Eigen::VectorXd;
    using namespace LBFGSpp;
    
    // ... (Functor definition) ...
    
    int main()
    {
        const int n = 10;
        LBFGSBParam<double> param;
        param.epsilon = 1e-6;
        param.max_iterations = 100;
    
        LBFGSBSolver<double> solver(param);
        Rosenbrock fun(n);
    
        VectorXd lb = VectorXd::Constant(n, 2.0);
        VectorXd ub = VectorXd::Constant(n, 4.0);
        VectorXd x = VectorXd::Constant(n, 3.0);
    
        double fx;
        int niter = solver.minimize(fun, x, fx, lb, ub);
    
        return 0;
    }
  4. Use a custom line search algorithm in LBFGSSolver

    master

    You can change the line search algorithm used by LBFGSSolver by providing a second template parameter. For example, to use the LineSearchBracketing algorithm, instantiate the solver as LBFGSSolver<double, LineSearchBracketing>.

    LBFGSSolver<double, LineSearchBracketing> solver(param);