EFOPT is an efficient sequential convex programming solver for nonlinear optimization problems with constraints. It implements the EFOPT algorithm with trust region methods and penalty functions for handling constraints. For more technical details, please refer to our paper on IEEE T-RO: Autonomous tail-sitter flights in unknown environments. If you use EFOPT in your research, please cite our work:
@article{lu2025autonomous,
title={Autonomous tail-sitter flights in unknown environments},
author={Lu, Guozheng and Ren, Yunfan and Zhu, Fangcheng and Li, Haotian and Xue, Ruize and Cai, Yixi and Lyu, Ximin and Zhang, Fu},
journal={IEEE Transactions on Robotics},
volume={41},
pages={1098--1117},
year={2025},
publisher={IEEE}
}
- ✅ Split code structure: Separated header and implementation files (no longer header-only)
- ✅ JSON parameter support: Load/save optimization parameters from JSON files
- ✅ Improved API: Better error handling and validation
- ✅ Result serialization: Convert optimization results to JSON format
- ✅ Static library: Compiles to static library for easy linking
- Trust region subproblem solved using Steihaug-CG method
- BFGS Hessian approximation for second-order optimization
- Penalty function approach for handling both equality and inequality constraints
- Two-stage convergence thresholds for improved efficiency
- Convexification step to ensure positive definite Hessian
- Eigen3 based for efficient linear algebra operations
- nlohmann/json for parameter serialization
EFOPT implements the algorithm described in the pseudocode with the following key steps:
- Outer penalty loop: Increases penalty coefficient for constraints until they are satisfied
- Inner convexification loop: Builds local convex approximation of the problem
- Trust Region Subproblem (TRS): Solved using Steihaug-CG algorithm
- Hessian update: Uses BFGS quasi-Newton update to improve second-order information
- Trust region adjustment: Expands or shrinks trust region based on model quality
- Threshold switching: Switches to finer convergence thresholds once constraints are satisfied
- C++17 compatible compiler
- Eigen3 (version 3.3 or higher)
- CMake (version 3.14 or higher)
- nlohmann/json (version 3.11 or higher, automatically downloaded if not found)
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make installAdd to your CMakeLists.txt:
find_package(efopt REQUIRED)
target_link_libraries(your_target PRIVATE efopt::efopt)#include <efopt/efopt.hpp>
// Define your problem
struct MyProblem {
void evaluate(const Eigen::VectorXd& x, double& objective, double& constraint_violation,
Eigen::VectorXd& grad_objective, Eigen::VectorXd& grad_constraint) {
// Implement your objective function and constraints here
objective = x(0)*x(0) + x(1)*x(1); // Example: min x² + y²
// Example constraint: x + y = 1
double c = x(0) + x(1) - 1;
constraint_violation = c*c;
grad_objective(0) = 2*x(0);
grad_objective(1) = 2*x(1);
grad_constraint(0) = 2*c*1;
grad_constraint(1) = 2*c*1;
}
static void evaluate_wrapper(void* instance, const Eigen::VectorXd& x, double& f, double& c,
Eigen::VectorXd& grad_f, Eigen::VectorXd& grad_c) {
static_cast<MyProblem*>(instance)->evaluate(x, f, c, grad_f, grad_c);
}
};
int main() {
MyProblem problem;
// Initial guess
Eigen::VectorXd x0(2);
x0 << 0.0, 0.0;
// Use default parameters
efopt::Parameters params;
params.verbose = true;
// Solve
efopt::Result result = efopt::optimize(x0, MyProblem::evaluate_wrapper, &problem, params);
// Use result
std::cout << "Optimal x: " << result.x.transpose() << std::endl;
std::cout << "Objective: " << result.objective << std::endl;
// Convert result to JSON
std::cout << "Result JSON: " << result.to_json().dump(4) << std::endl;
return 0;
}// Load from JSON object
efopt::json params_json = {
{"verbose", true},
{"max_penalty_iterations", 10},
{"xtol_fine", 1e-5}
};
efopt::Parameters params = efopt::Parameters::from_json(params_json);
// Or load from JSON file
efopt::Parameters params = efopt::Parameters::from_json_file("config.json");{
"verbose": true,
"penalty_init": 1000.0,
"penalty_scale": 10.0,
"max_penalty_iterations": 8,
"max_convexify_iterations": 40,
"extra_iterations": 10,
"trust_region_init": 1.0,
"trust_region_expand": 2.0,
"trust_region_shrink": 0.75,
"model_quality_low": 0.25,
"model_quality_high": 0.75,
"xtol_coarse": 0.01,
"ftol_coarse": 0.01,
"ctol_coarse": 0.01,
"xtol_fine": 0.0001,
"ftol_fine": 0.0001,
"ctol_fine": 0.0001,
"trs_params": {
"max_iterations": 128,
"tolerance": 1e-8
}
}| Parameter | Description | Default |
|---|---|---|
verbose |
Print optimization progress | false |
penalty_init |
Initial penalty coefficient | 1e3 |
penalty_scale |
Penalty scaling factor | 10.0 |
max_penalty_iterations |
Maximum penalty loop iterations | 8 |
max_convexify_iterations |
Maximum inner loop iterations | 40 |
trust_region_init |
Initial trust region radius | 1.0 |
trust_region_expand |
Trust region expansion factor | 2.0 |
trust_region_shrink |
Trust region shrinkage factor | 0.75 |
model_quality_low |
Threshold for shrinking trust region | 0.25 |
model_quality_high |
Threshold for expanding trust region | 0.75 |
xtol_coarse, ftol_coarse, ctol_coarse |
First-stage thresholds | 1e-2 |
xtol_fine, ftol_fine, ctol_fine |
Second-stage thresholds | 1e-4 |
| Code | Description |
|---|---|
| 1 | Success |
| 2 | Converged due to x tolerance |
| 3 | Converged due to function tolerance |
| 4 | Converged due to constraint tolerance |
| Negative values | Errors |
cd build
./test_efoptThe test suite includes:
- JSON parameter loading test
- Rosenbrock function with equality constraint test
- Nonconvex function with inequality constraint test
MIT License