#![allow(dead_code)]
#![allow(non_camel_case_types)]
use std::os::raw::{c_double, c_void};
pub type int32_t = i32;
pub const CLP_STATUS_OPTIMAL: i32 = 0;
pub const CLP_STATUS_PRIMAL_INFEASIBLE: i32 = 1;
pub const CLP_STATUS_DUAL_INFEASIBLE: i32 = 2;
pub const CLP_STATUS_STOPPED: i32 = 3;
pub const CLP_STATUS_ERRORS: i32 = 4;
unsafe extern "C" {
pub fn cobre_clp_create() -> *mut c_void;
pub fn cobre_clp_destroy(model: *mut c_void);
pub fn cobre_clp_set_log_level(model: *mut c_void, value: int32_t);
pub fn cobre_clp_load_problem(
model: *mut c_void,
num_cols: int32_t,
num_rows: int32_t,
col_starts: *const int32_t,
row_indices: *const int32_t,
values: *const c_double,
col_lower: *const c_double,
col_upper: *const c_double,
objective: *const c_double,
row_lower: *const c_double,
row_upper: *const c_double,
);
pub fn cobre_clp_add_rows(
model: *mut c_void,
number: int32_t,
row_lower: *const c_double,
row_upper: *const c_double,
row_starts: *const int32_t,
columns: *const int32_t,
elements: *const c_double,
);
pub fn cobre_clp_chg_row_lower(model: *mut c_void, row_lower: *const c_double);
pub fn cobre_clp_chg_row_upper(model: *mut c_void, row_upper: *const c_double);
pub fn cobre_clp_chg_column_lower(model: *mut c_void, column_lower: *const c_double);
pub fn cobre_clp_chg_column_upper(model: *mut c_void, column_upper: *const c_double);
pub fn cobre_clp_dual(model: *mut c_void, if_values_pass: int32_t) -> int32_t;
pub fn cobre_clp_primal(model: *mut c_void, if_values_pass: int32_t) -> int32_t;
pub fn cobre_clp_objective_value(model: *const c_void) -> c_double;
pub fn cobre_clp_status(model: *const c_void) -> int32_t;
pub fn cobre_clp_number_iterations(model: *const c_void) -> int32_t;
pub fn cobre_clp_get_col_solution(model: *const c_void) -> *const c_double;
pub fn cobre_clp_get_row_price(model: *const c_void) -> *const c_double;
pub fn cobre_clp_get_reduced_cost(model: *const c_void) -> *const c_double;
pub fn cobre_clp_set_perturbation(model: *mut c_void, value: int32_t);
pub fn cobre_clp_scaling(model: *mut c_void, mode: int32_t);
pub fn cobre_clp_set_primal_tolerance(model: *mut c_void, value: c_double);
pub fn cobre_clp_set_dual_tolerance(model: *mut c_void, value: c_double);
pub fn cobre_clp_set_maximum_iterations(model: *mut c_void, value: int32_t);
pub fn cobre_clp_get_column_status(model: *const c_void, sequence: int32_t) -> int32_t;
pub fn cobre_clp_set_column_status(model: *mut c_void, sequence: int32_t, value: int32_t);
pub fn cobre_clp_get_row_status(model: *const c_void, sequence: int32_t) -> int32_t;
pub fn cobre_clp_set_row_status(model: *mut c_void, sequence: int32_t, value: int32_t);
pub fn cobre_clp_set_dual_row_steepest(model: *mut c_void, mode: int32_t);
pub fn cobre_clp_set_factorization_frequency(model: *mut c_void, value: int32_t);
pub fn cobre_clp_mark_hot_start(model: *mut c_void) -> *mut c_void;
pub fn cobre_clp_solve_from_hot_start(model: *mut c_void, save_stuff: *mut c_void) -> int32_t;
pub fn cobre_clp_unmark_hot_start(model: *mut c_void, save_stuff: *mut c_void);
pub fn cobre_clp_version_major() -> int32_t;
pub fn cobre_clp_version_minor() -> int32_t;
pub fn cobre_clp_version_release() -> int32_t;
}
#[cfg(test)]
mod tests {
use super::{
CLP_STATUS_OPTIMAL, cobre_clp_create, cobre_clp_destroy, cobre_clp_dual,
cobre_clp_load_problem, cobre_clp_objective_value, cobre_clp_set_log_level,
cobre_clp_status,
};
#[test]
fn test_clp_ffi_smoke_create_solve_destroy() {
let model = unsafe { cobre_clp_create() };
assert!(!model.is_null(), "cobre_clp_create() returned null");
unsafe { cobre_clp_set_log_level(model, 0) };
let col_starts: [i32; 2] = [0, 0];
let row_indices: [i32; 0] = [];
let values: [f64; 0] = [];
let col_lower: [f64; 1] = [0.0];
let col_upper: [f64; 1] = [10.0];
let objective: [f64; 1] = [1.0];
let row_lower: [f64; 0] = [];
let row_upper: [f64; 0] = [];
unsafe {
cobre_clp_load_problem(
model,
1, 0, col_starts.as_ptr(),
row_indices.as_ptr(),
values.as_ptr(),
col_lower.as_ptr(),
col_upper.as_ptr(),
objective.as_ptr(),
row_lower.as_ptr(),
row_upper.as_ptr(),
);
}
let solve_status = unsafe { cobre_clp_dual(model, 0) };
assert_eq!(
solve_status, CLP_STATUS_OPTIMAL,
"cobre_clp_dual() returned solve status {solve_status}"
);
let status = unsafe { cobre_clp_status(model) };
assert_eq!(
status, CLP_STATUS_OPTIMAL,
"expected Optimal status, got {status}"
);
let obj = unsafe { cobre_clp_objective_value(model) };
assert!(
(obj - 0.0_f64).abs() < 1e-10,
"objective value {obj} is not within 1e-10 of expected 0.0"
);
unsafe { cobre_clp_destroy(model) };
}
}