https://github.com/colinfang/lbfgsb_cpp
A thin wrapper around the original Fortran L-BFGS-B routine v3.0
https://github.com/colinfang/lbfgsb_cpp
Last synced: 6 months ago
JSON representation
A thin wrapper around the original Fortran L-BFGS-B routine v3.0
- Host: GitHub
- URL: https://github.com/colinfang/lbfgsb_cpp
- Owner: colinfang
- Created: 2019-02-06T18:58:42.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2022-06-17T21:09:29.000Z (over 3 years ago)
- Last Synced: 2025-02-10T12:42:56.961Z (11 months ago)
- Language: Fortran
- Homepage:
- Size: 46.9 KB
- Stars: 2
- Watchers: 2
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# L-BFGS-B C++ Wrapper
## Overview
This is a thin wrapper around the original [Fortran
L-BFGS-B routine v3.0](http://users.iems.northwestern.edu/~nocedal/lbfgsb.html)
- Lightweight & flexible abstraction.
- Provided interface follows SciPy convention.
- Require C++11.
## Install Using CMake
```bash
mkdir build
cd build
cmake ..
make install
```
- `-DCMAKE_INSTALL_PREFIX=/path/to/folder` - Install to `/path/to/folder` instead of `/usr/local`.
- `-DCMAKE_BUILD_TYPE=Release` - Fully optimized build.
- `-DBUILD_SHARED_LIBS=ON` - Build a shared library instead (default is static with `-fPIC`).
- `-DBUILD_EXAMPLE=ON` - Build example.
- The underlying fortran subroutine is compiled with `-frecursive` to ensure thread-safety.
## Quick Start
```c++
#include
using namespace lbfgsb;
double get_objective(const std::array& x, std::array& grad) {
grad[0] = 2 * (x[0] - 0.5);
grad[1] = 2 * (x[1] - 1);
return std::pow(x[0] - 0.5, 2) + std::pow(x[1] - 1, 2);
}
int main() {
const std::array lb{-2, -2};
const std::array ub{2, 2};
// 0 if unbounded,
// 1 if only a lower bound,
// 2 if both lower and upper bounds,
// 3 if only an upper bound.
const std::array bound_type{2, 2};
Optimizer optimizer{lb.size()};
// Can adjust many optimization configs.
// E.g. `iprint`, `factr`, `pgtol`, `max_iter`, `max_fun`, `time_limit_sec`
optimizer.iprint = 1;
std::array x0{2, 3};
auto result = optimizer.minimize(
get_objective, x0, lb.data(), ub.data(), bound_type.data()
);
result.print();
// (0.5, 1) => 0
std::cout << "x0: (" << x0[0] << ", " << x0[1] << ")" << std::endl;
return 0;
}
```
## API
- `minimize(F& func, T& x0, const double* lb, const double* ub, const int* bound_type)`
- `x0` will be updated with the optimal parameters.
- `func(const T& x0, T& grad) -> double fval`
- Aim to optimize the return value.
- `grad` is required to be updated on each call.
- Requirement from `T`
- `T grad(x0)` must be able to initialize `grad`.
- `T.data()` must return a pointer to the data.
- So `std::array` & `std::vector` both work.
## Differences with SciPy
- All defaults are from SciPy except for `max_iter`.
- Unlike SciPy, `max_iter` is defined by the fortran subroutine, not the number of times the subroutine is called.
- The subroutine may be called multiple times for line searches in one iteration.
- `OptimizeResult.warn_flag` returns 3 for `ABNORMAL_TERMINATION_IN_LNSRCH` instead of 2.
- The Fortran subroutine SciPy uses has an additional parameter `maxls`.
## References
- Julia
-
- Rust
-
-
- C++
-
- SciPy
-