use ipopt_bindgen::*;
unsafe extern "C" fn objective_callback(
n: ipindex,
x: *mut ipnumber,
_new_x: bool,
obj_value: *mut ipnumber,
_user_data: UserDataPtr,
) -> bool {
let x_slice = std::slice::from_raw_parts(x, n as usize);
*obj_value = x_slice[0] * x_slice[3] * (x_slice[0] + x_slice[1] + x_slice[2]) + x_slice[2];
true
}
unsafe extern "C" fn constraints_callback(
n: ipindex,
x: *mut ipnumber,
_new_x: bool,
m: ipindex,
g: *mut ipnumber,
_user_data: UserDataPtr,
) -> bool {
let x_slice = std::slice::from_raw_parts(x, n as usize);
let g_slice = std::slice::from_raw_parts_mut(g, m as usize);
g_slice[0] = x_slice[0] * x_slice[1] * x_slice[2] * x_slice[3];
g_slice[1] = x_slice[0] * x_slice[0]
+ x_slice[1] * x_slice[1]
+ x_slice[2] * x_slice[2]
+ x_slice[3] * x_slice[3];
true
}
unsafe extern "C" fn gradient_callback(
n: ipindex,
x: *mut ipnumber,
_new_x: bool,
grad_f: *mut ipnumber,
_user_data: UserDataPtr,
) -> bool {
let x_slice = std::slice::from_raw_parts(x, n as usize);
let grad_slice = std::slice::from_raw_parts_mut(grad_f, n as usize);
grad_slice[0] = x_slice[0] * x_slice[3] + x_slice[3] * (x_slice[0] + x_slice[1] + x_slice[2]);
grad_slice[1] = x_slice[0] * x_slice[3];
grad_slice[2] = x_slice[0] * x_slice[3] + 1.0;
grad_slice[3] = x_slice[0] * (x_slice[0] + x_slice[1] + x_slice[2]);
true
}
unsafe extern "C" fn jacobian_callback(
n: ipindex,
x: *mut ipnumber,
_new_x: bool,
_m: ipindex,
nele_jac: ipindex,
i_row: *mut ipindex,
j_col: *mut ipindex,
values: *mut ipnumber,
_user_data: UserDataPtr,
) -> bool {
if x.is_null() {
let i_row = std::slice::from_raw_parts_mut(i_row, nele_jac as usize);
let j_col = std::slice::from_raw_parts_mut(j_col, nele_jac as usize);
i_row[0] = 0;
j_col[0] = 0;
i_row[1] = 0;
j_col[1] = 1;
i_row[2] = 0;
j_col[2] = 2;
i_row[3] = 0;
j_col[3] = 3;
i_row[4] = 1;
j_col[4] = 0;
i_row[5] = 1;
j_col[5] = 1;
i_row[6] = 1;
j_col[6] = 2;
i_row[7] = 1;
j_col[7] = 3;
} else {
let x_slice = std::slice::from_raw_parts(x, n as usize);
let values = std::slice::from_raw_parts_mut(values, nele_jac as usize);
values[0] = x_slice[1] * x_slice[2] * x_slice[3]; values[1] = x_slice[0] * x_slice[2] * x_slice[3]; values[2] = x_slice[0] * x_slice[1] * x_slice[3]; values[3] = x_slice[0] * x_slice[1] * x_slice[2];
values[4] = 2.0 * x_slice[0]; values[5] = 2.0 * x_slice[1]; values[6] = 2.0 * x_slice[2]; values[7] = 2.0 * x_slice[3]; }
true
}
unsafe extern "C" fn hessian_callback(
n: ipindex,
x: *mut ipnumber,
_new_x: bool,
obj_factor: ipnumber,
m: ipindex,
lambda: *mut ipnumber,
_new_lambda: bool,
nele_hess: ipindex,
i_row: *mut ipindex,
j_col: *mut ipindex,
values: *mut ipnumber,
_user_data: UserDataPtr,
) -> bool {
if x.is_null() {
let i_row_slice = std::slice::from_raw_parts_mut(i_row, nele_hess as usize);
let j_col_slice = std::slice::from_raw_parts_mut(j_col, nele_hess as usize);
let mut idx: ipindex = 0;
for row in 0..n {
for col in 0..=row {
i_row_slice[idx as usize] = row;
j_col_slice[idx as usize] = col;
idx += 1;
}
}
} else {
let x_slice = std::slice::from_raw_parts(x, n as usize);
let lambda_slice = std::slice::from_raw_parts(lambda, m as usize);
let hessian = std::slice::from_raw_parts_mut(values, nele_hess as usize);
hessian[0] = obj_factor * (2.0 * x_slice[3]);
hessian[1] = obj_factor * (x_slice[3]); hessian[2] = 0.;
hessian[3] = obj_factor * (x_slice[3]); hessian[4] = 0.; hessian[5] = 0.;
hessian[6] = obj_factor * (2.0 * x_slice[0] + x_slice[1] + x_slice[2]); hessian[7] = obj_factor * (x_slice[0]); hessian[8] = obj_factor * (x_slice[0]); hessian[9] = 0.;
hessian[1] += lambda_slice[0] * (x_slice[2] * x_slice[3]); hessian[3] += lambda_slice[0] * (x_slice[1] * x_slice[3]); hessian[4] += lambda_slice[0] * (x_slice[0] * x_slice[3]); hessian[6] += lambda_slice[0] * (x_slice[1] * x_slice[2]); hessian[7] += lambda_slice[0] * (x_slice[0] * x_slice[2]); hessian[8] += lambda_slice[0] * (x_slice[0] * x_slice[1]);
hessian[0] += lambda_slice[1] * 2.0; hessian[2] += lambda_slice[1] * 2.0; hessian[5] += lambda_slice[1] * 2.0; hessian[9] += lambda_slice[1] * 2.0; }
true
}
fn main() {
let n = 4;
let m = 2;
let mut x_l = vec![1.0, 1.0, 1.0, 1.0];
let mut x_u = vec![5.0, 5.0, 5.0, 5.0];
let mut g_l = vec![25.0, 40.0];
let mut g_u = vec![2.0e19, 40.0];
let nnz_jacobian = 8;
let nnz_hessian = 10;
const C_STYLE_INDEXING: i32 = 0;
let objective: Eval_F_CB = Some(objective_callback);
let constraints: Eval_G_CB = Some(constraints_callback);
let gradients: Eval_Grad_F_CB = Some(gradient_callback);
let jacobian: Eval_Jac_G_CB = Some(jacobian_callback);
let hessian: Eval_H_CB = Some(hessian_callback);
let cstr = |s: &str| std::ffi::CString::new(s).unwrap().into_raw();
unsafe {
let problem = crate::CreateIpoptProblem(
n,
x_l.as_mut_ptr(),
x_u.as_mut_ptr(),
m,
g_l.as_mut_ptr(),
g_u.as_mut_ptr(),
nnz_jacobian,
nnz_hessian,
C_STYLE_INDEXING,
objective,
constraints,
gradients,
jacobian,
hessian,
);
AddIpoptNumOption(problem, cstr("tol"), 3.82e-6);
AddIpoptStrOption(problem, cstr("mu_strategy"), cstr("adaptive"));
AddIpoptStrOption(problem, cstr("output_file"), cstr("ipopt.out"));
let mut variables = vec![1.0, 5.0, 5.0, 1.0];
let mut constraint_multipliers = vec![0.0, 0.0];
let mut lower_bound_multipliers = vec![0.0, 0.0, 0.0, 0.0];
let mut upper_bound_multipliers = vec![0.0, 0.0, 0.0, 0.0];
let mut objective_value: f64 = 0.0;
let _status = IpoptSolve(
problem,
variables.as_mut_ptr(),
std::ptr::null_mut(),
std::ptr::addr_of_mut!(objective_value),
constraint_multipliers.as_mut_ptr(),
lower_bound_multipliers.as_mut_ptr(),
upper_bound_multipliers.as_mut_ptr(),
std::ptr::null_mut(),
);
}
}