Overview
ucminfcpp is an R package that provides unconstrained
nonlinear optimization through a modern C++17
reimplementation of the classic Fortran-based ucminf algorithm.
It is a drop-in replacement for
ucminf::ucminf().
The package was primarily developed to power the nicher and xsdmMle
packages, where fast and reliable unconstrained optimization is central
to fitting ecological niche models and maximum-likelihood
estimators.
Optimization Showcases
1. Rosenbrock’s Banana Function
The Banana Function is a classic benchmark for optimization
algorithms. Its global minimum is at (1, 1).
Verifying Consistency with ucminf
ucminfcpp is designed to be numerically equivalent to
ucminf. The following code confirms the roots match for the
Banana Function.
starting_point <- c(-1.2, 1)
result_cpp <- ucminfcpp::ucminf(starting_point, banana)
result_fortran <- ucminf::ucminf(starting_point, banana)
cat("ucminfcpp result:\n"); print(result_cpp$par)
#> ucminfcpp result:
#> [1] 0.9996971 0.9993937
cat("ucminf result:\n"); print(result_fortran$par)
#> ucminf result:
#> [1] 0.9996971 0.9993937
identical_result <- all.equal(result_cpp$par, result_fortran$par)
cat("Are the results the same?", identical_result, "\n")
#> Are the results the same? TRUEPerformance Benchmarks
Even when calling pure R objective functions (which cross the
interpreter boundary on every evaluation), ucminfcpp
typically outperforms the Fortran-based ucminf due to
reduced C/Fortran call overhead in its C++ core.
library(microbenchmark)
benchmark_results <- microbenchmark(
ucminfcpp = ucminfcpp::ucminf(c(-1.2, 1), banana),
ucminf = ucminf::ucminf(c(-1.2, 1), banana),
times = 100L
)
print(benchmark_results)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> ucminfcpp 91.961 93.790 98.26517 95.9840 98.5135 166.621 100
#> ucminf 122.959 125.329 131.13844 128.0685 130.5130 217.977 100The benchmark shows the median execution time for each implementation
across 100 runs. ucminfcpp achieves comparable or better
performance while maintaining full numerical equivalence.
For even greater speed, implement the objective function in C++ and
call it via ucminfcpp::minimize_direct<F>() to
eliminate all interpreter overhead.