use crate::constrained::*;
use crate::error::OptimizeError;
use scirs2_core::ndarray::array;
#[allow(dead_code)]
fn objective(x: &[f64]) -> f64 {
(x[0] - 1.0).powi(2) + (x[1] - 2.5).powi(2)
}
#[allow(dead_code)]
fn constraint(x: &[f64]) -> f64 {
3.0 - x[0] - x[1] }
#[test]
#[allow(dead_code)]
fn test_minimize_constrained_placeholder() {
let x0 = array![0.0, 0.0];
let constraints = vec![Constraint::new(constraint, Constraint::INEQUALITY)];
let options = Options {
maxiter: Some(1), ..Options::default()
};
let result = minimize_constrained(
objective,
&x0.view(),
&constraints,
Method::SLSQP,
Some(options),
)
.expect("Operation failed");
assert!(!result.success);
assert!(result.constr.is_some());
let constr = result.constr.expect("Operation failed");
assert_eq!(constr.len(), 1);
}
#[test]
#[allow(dead_code)]
fn test_minimize_slsqp() {
let x0 = array![0.0, 0.0];
let constraints = vec![Constraint::new(constraint, Constraint::INEQUALITY)];
let options = Options {
maxiter: Some(100),
gtol: Some(1e-6),
ftol: Some(1e-6),
ctol: Some(1e-6),
..Options::default()
};
let result = minimize_constrained(
objective,
&x0.view(),
&constraints,
Method::SLSQP,
Some(options),
)
.expect("Operation failed");
assert!(result.x[0] >= 0.0);
assert!(result.x[1] >= 0.0);
let initial_value = objective(&[0.0, 0.0]);
assert!(result.fun <= initial_value);
assert!(result.constr.is_some());
println!(
"SLSQP result: x = {:?}, f = {}, iterations = {}",
result.x, result.fun, result.nit
);
}
#[test]
#[allow(dead_code)]
fn test_minimize_trust_constr() {
let x0 = array![0.0, 0.0];
let constraints = vec![Constraint::new(constraint, Constraint::INEQUALITY)];
let options = Options {
maxiter: Some(500), gtol: Some(1e-6),
ftol: Some(1e-6),
ctol: Some(1e-6),
..Options::default()
};
let result = minimize_constrained(
objective,
&x0.view(),
&constraints,
Method::TrustConstr,
Some(options.clone()),
)
.expect("Operation failed");
assert!(result.x[0] >= 0.0);
assert!(result.x[1] >= 0.0);
let initial_value = objective(&[0.0, 0.0]);
assert!(result.fun <= initial_value);
assert!(result.constr.is_some());
println!(
"TrustConstr result: x = {:?}, f = {}, iterations = {}",
result.x, result.fun, result.nit
);
}
#[test]
#[allow(dead_code)]
fn test_constrained_rosenbrock() {
fn rosenbrock(x: &[f64]) -> f64 {
100.0 * (x[1] - x[0].powi(2)).powi(2) + (1.0 - x[0]).powi(2)
}
fn circle_constraint(x: &[f64]) -> f64 {
1.5 - (x[0].powi(2) + x[1].powi(2)) }
let x0 = array![0.0, 0.0];
let constraints = vec![Constraint::new(circle_constraint, Constraint::INEQUALITY)];
let options = Options {
maxiter: Some(1000), gtol: Some(1e-4), ftol: Some(1e-4),
ctol: Some(1e-4),
..Options::default()
};
let options_copy1 = options.clone();
let options_copy2 = options.clone();
let result_slsqp = minimize_constrained(
rosenbrock,
&x0.view(),
&constraints,
Method::SLSQP,
Some(options_copy1),
)
.expect("Operation failed");
let result_trust = minimize_constrained(
rosenbrock,
&x0.view(),
&constraints,
Method::TrustConstr,
Some(options_copy2),
)
.expect("Operation failed");
println!(
"SLSQP Rosenbrock result: x = {:?}, f = {}, iterations = {}",
result_slsqp.x, result_slsqp.fun, result_slsqp.nit
);
println!(
"TrustConstr Rosenbrock result: x = {:?}, f = {}, iterations = {}",
result_trust.x, result_trust.fun, result_trust.nit
);
let initial_value = rosenbrock(&[0.0, 0.0]);
assert!(result_slsqp.fun < initial_value);
assert!(result_trust.fun < initial_value);
let constr_slsqp = result_slsqp.constr.expect("Operation failed");
let constr_trust = result_trust.constr.expect("Operation failed");
assert!(constr_slsqp[0] >= -0.01); assert!(constr_trust[0] >= -0.01); }
#[test]
#[allow(dead_code)]
fn test_cobyla_not_implemented() {
let x0 = array![0.0, 0.0];
let constraints = vec![Constraint::new(constraint, Constraint::INEQUALITY)];
let result = minimize_constrained(objective, &x0.view(), &constraints, Method::COBYLA, None);
assert!(result.is_ok());
let opt_result = result.expect("Operation failed");
assert!(opt_result.success || opt_result.nit > 0); }