Skip to content

Blackbox NLP solver using IPOPT and automatic differentiation

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
license-apache
MIT
license-mit
Notifications You must be signed in to change notification settings

prehner/ipopt-ad

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

IPOPT-AD - Blackbox NLP solver using IPOPT and automatic differentiation

crate documentation

This crate provides a simple interface to the IPOPT nonlinear program (NLP) solver. By evaluating gradients and Hessians using automatic differentiation provided by the num-dual crate, it "converts" IPOPT into a blackbox solver without introducing numerical errors through forward differences that could diminish the robustness and accuracy. The only limitation is that the evaluation of the objective and constraints has to be implemented generically for values implementing the DualNum trait.

Example: problem 71 from the Hock-Schittkowsky test-suite

This example demonstrates how to solve the problem that is also used as example in the documentation of IPOPT. Because the objective value and constraints are simple functions of x, the SimpleADProblem interface can be used.

use ipopt_ad::{ADProblem, BasicADProblem, SimpleADProblem};
use ipopt_ad::ipopt::Ipopt;
use num_dual::DualNum;
use approx::assert_relative_eq;

struct HS071;

impl BasicADProblem<4> for HS071 {
    fn bounds(&self) -> ([f64; 4], [f64; 4]) {
        ([1.0; 4], [5.0; 4])
    }
    fn initial_point(&self) -> [f64; 4] {
        [1.0, 5.0, 5.0, 1.0]
    }
    fn constraint_bounds(&self) -> (Vec<f64>, Vec<f64>) {
        (vec![25.0, 40.0], vec![f64::INFINITY, 40.0])
    }
}

impl SimpleADProblem<4> for HS071 {
    fn objective<D: DualNum<f64> + Copy>(&self, x: [D; 4]) -> D {
        let [x1, x2, x3, x4] = x;
        x1 * x4 * (x1 + x2 + x3) + x3
    }
    fn constraint_values<D: DualNum<f64> + Copy>(&self, x: [D; 4]) -> Vec<D> {
        let [x1, x2, x3, x4] = x;
        vec![x1 * x2 * x3 * x4, x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4]
    }
}

let problem = ADProblem::new(HS071);
let mut ipopt = Ipopt::new(problem).unwrap();
ipopt.set_option("print_level", 0);
let res = ipopt.solve();
let x = res.solver_data.solution.primal_variables;
let x_lit = &[1f64, 4.74299963, 3.82114998, 1.37940829] as &[f64];
assert_relative_eq!(x, x_lit, max_relative = 1e-8);

For more complex NLPs, it can be advantageous to evaluate the objective function and constraints simultaneously, which is possible with the CachedADProblem interface. For the HS071 problem, this looks like this:

impl CachedADProblem<4> for HS071 {
    type Error = Infallible;
    fn evaluate<D: DualNum<f64> + Copy>(&self, x: [D; 4]) -> Result<(D, Vec<D>), Infallible> {
        let [x1, x2, x3, x4] = x;
        Ok((
            x1 * x4 * (x1 + x2 + x3) + x3,
            vec![x1 * x2 * x3 * x4, x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4],
        ))
    }
}

let problem = ADProblem::new_cached(HS071).unwrap();
let mut ipopt = Ipopt::new(problem).unwrap();
ipopt.set_option("print_level", 0);
let res = ipopt.solve();
let x = res.solver_data.solution.primal_variables;
let x_lit = &[1f64, 4.74299963, 3.82114998, 1.37940829] as &[f64];
assert_relative_eq!(x, x_lit, max_relative = 1e-8);

About

Blackbox NLP solver using IPOPT and automatic differentiation

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
license-apache
MIT
license-mit

Stars

Watchers

Forks

Packages

No packages published

Languages