use serial_test::serial;
use numopt::model::*;
use numopt::solver::*;
#[test]
#[serial]
fn numopt_model_solve_milp_cbc_cmd() {
let x1 = VariableScalar::new_integer("x1");
let x2 = VariableScalar::new_integer("x2");
let x3 = VariableScalar::new_continuous("x3");
let x4 = VariableScalar::new_continuous("x4");
let f = -&x1 - &x2;
let c1 = (-2.*&x1+ 2.*&x2 + &x3).equal(1.);
let c2 = (-8.*&x1 + 10.*&x2 + &x4).equal(13.);
let c3 = &x4.geq(0.);
let c4 = &x3.leq(0.);
let mut m = Model::new();
m.set_objective(Objective::minimize(&f));
m.add_constraint(&c1);
m.add_constraint(&c2);
m.add_constraint(&c3);
m.add_constraint(&c4);
let mut s = SolverCbcCmd::new();
s.set_param("logLevel", SolverParam::IntParam(0)).unwrap();
m.solve(&s).unwrap();
assert_eq!(*m.solver_status().unwrap(), SolverStatus::Solved);
assert_eq!(*m.final_primals().get(&x1).unwrap(), 1.);
assert_eq!(*m.final_primals().get(&x2).unwrap(), 2.);
}
#[cfg(feature = "ipopt")]
#[test]
#[serial]
fn numopt_model_solve_nlp1_ipopt() {
use approx::assert_abs_diff_eq;
const N: usize = 100;
let x: Vec<Node>= (0..N).map(|i| VariableScalar::new_continuous(format!("x{}", i).as_ref()))
.collect();
let mut f = ConstantScalar::zero();
for i in 0..(N-1) {
f = f + 100.*(&x[i+1] - &x[i]*&x[i])*(&x[i+1] - &x[i]*&x[i]) + (1. - &x[i])*(1. - &x[i]);
}
let mut m = Model::new();
m.set_objective(Objective::minimize(&f));
let mut s = SolverIpopt::new();
s.set_param("print_level", SolverParam::IntParam(0)).unwrap();
s.set_param("sb", SolverParam::StrParam("yes".to_string())).unwrap();
m.solve(&s).unwrap();
assert_eq!(*m.solver_status().unwrap(), SolverStatus::Solved);
let final_primals = m.final_primals();
for xx in x.iter() {
assert_abs_diff_eq!(*final_primals.get(xx).unwrap(), 1., epsilon=1e-8);
}
}
#[cfg(feature = "ipopt")]
#[test]
#[serial]
fn numopt_model_solve_nlp2_ipopt() {
use num_traits::ToPrimitive;
use approx::assert_abs_diff_eq;
const N: usize = 100;
const ALPHA: f64 = 350.;
let h: f64 = 1./N.to_f64().unwrap();
let t: Vec<Node>= (0..N+1).map(|i| VariableScalar::new_continuous(format!("t{}", i).as_ref()))
.collect();
let x: Vec<Node>= (0..N+1).map(|i| VariableScalar::new_continuous(format!("x{}", i).as_ref()))
.collect();
let u: Vec<Node>= (0..N+1).map(|i| VariableScalar::new_continuous(format!("u{}", i).as_ref()))
.collect();
let mut f = ConstantScalar::zero();
for i in 0..N {
f = f + 0.5*h*(&u[i]*&u[i] + &u[i+1]*&u[i+1]) +
0.5*ALPHA*h*(t[i].cos() + t[i+1].cos());
}
let mut m = Model::new();
m.set_objective(Objective::minimize(&f));
for i in 0..N {
m.add_constraint(&(&x[i+1] - &x[i] - 0.5*h*(t[i+1].sin() + t[i].sin())).equal(0.));
m.add_constraint(&(&t[i+1] - &t[i] - 0.5*h*(&u[i+1] - &u[i])).equal(0.));
}
for i in 0..(N+1) {
m.add_constraint(&t[i].leq(1.));
m.add_constraint(&t[i].geq(-1.));
m.add_constraint(&x[i].leq(0.05));
m.add_constraint(&x[i].geq(-0.05));
}
let mut s = SolverIpopt::new();
s.set_param("print_level", SolverParam::IntParam(0)).unwrap();
s.set_param("sb", SolverParam::StrParam("yes".to_string())).unwrap();
m.solve(&s).unwrap();
assert_eq!(*m.solver_status().unwrap(), SolverStatus::Solved);
assert_abs_diff_eq!(f.evaluate(&m.final_primals()), 350., epsilon=1e-8);
}