# lbfgsb.rs
## Overview
Initially started from a [c2rust](https://c2rust.com/manual/) port of [L-BFGS-B-C](https://github.com/stephenbeckr/L-BFGS-B-C), this project aims to provide a pure Rust implementation of the L-BFGS-B algorithm. Existing Rust crates are, for now, mostly wrappers around Fortran and C implementations. The purpose of this exercise is primarily educational but aims towards a modern take on this algorithm by removing Fortran or C specific idioms (such as goto and 1-based indexing).
This algorithm is widely used for solving bound-constrained optimization problems with memory efficiency in mind, notably by approximating the inverse Hessian matrix for second order evaluation of the objective function's curvature. Starting with an initial estimate of the optimal value that minimizes the objective function, this algorithm proceeds iteratively to refine it through differential calculus, while using limited computer memory.
Roughly, this algorithm minimizes a function f(x) where x is is bounded with a lower and upper boundary.
## Refactoring
### Transpiling
The ```compile_commands.json``` file has been automatically created using [bear](https://github.com/rizsotto/Bear). Original C sources can be transpiled using the following command:
```
c2rust transpile --emit-build-files --translate-const-macros --overwrite-existing --output-dir rust compile_commands.json
```
The unsafe code resulting from the previous command is available in the ```unsafe``` folder. A few modifications have been made in order to have all three drivers to run.
## Steps
Refactoring process started following these steps:
1. Changed transpiling types to more conveniant and concise Rust ones (using the ```safe.py``` script in the ```scripts``` folder)
2. Replacement of ```libc```reference functions in the ```unsafe```code (```fabs```, ```fmax```, ```printf```, etc...) with their Rust counterparts
3. Creation of safe Rust functions wrapped in their unsafe counterpart
4. Removal of goto logic inherited from Fortran/C with state machines if applicable
5. Incremental removal of the unsafe wrappers
Extensive use of LLM has been made to speed up the refactoring process.
### Logs
Output logs of the three drivers are available for C, unsafe and safe Rust implementations for benchmarking and non regression testing. They have been saved in the ```logs``` folder.
### Testing
Three drivers are originally provided in the Fortran and C sources, keeping the non-convex Rosenbrock function for performance testing of the algorithm. Starting from their output, the refactoring has been checked step by step by comparing the reference values. Unit tests have then been implemented for all three drivers and modules. The drivers can be run using the following command (change driver name accordingly):
```
RUST_LOG=debug cargo run --example driver3
```
## References
[Rust wrapper for L-BFGS-B-C](https://docs.rs/crate/lbfgsb/latest)
[L-BFGS-B-C](https://github.com/stephenbeckr/L-BFGS-B-C)
[A pure Matlab implementation of L-BFGS-B](https://github.com/bgranzow/L-BFGS-B)
[Modern Fortran Refactoring of L-BFGS-B Nonlinear Optimization Code ](https://github.com/jacobwilliams/lbfgsb)
[Fortran procedures from Jacob Williams website](https://jacobwilliams.github.io/lbfgsb/lists/procedures.html)