#![allow(dead_code)]
#![allow(non_camel_case_types)]
use std::os::raw::{c_char, c_double, c_int, c_void};
pub type int32_t = i32;
pub const HIGHS_STATUS_ERROR: i32 = -1;
pub const HIGHS_STATUS_OK: i32 = 0;
pub const HIGHS_STATUS_WARNING: i32 = 1;
pub const HIGHS_MODEL_STATUS_SOLVE_ERROR: i32 = 4;
pub const HIGHS_MODEL_STATUS_OPTIMAL: i32 = 7;
pub const HIGHS_MODEL_STATUS_INFEASIBLE: i32 = 8;
pub const HIGHS_MODEL_STATUS_UNBOUNDED_OR_INFEASIBLE: i32 = 9;
pub const HIGHS_MODEL_STATUS_UNBOUNDED: i32 = 10;
pub const HIGHS_MODEL_STATUS_TIME_LIMIT: i32 = 13;
pub const HIGHS_MODEL_STATUS_ITERATION_LIMIT: i32 = 14;
pub const HIGHS_MODEL_STATUS_UNKNOWN: i32 = 15;
pub const HIGHS_BASIS_STATUS_LOWER: i32 = 0;
pub const HIGHS_BASIS_STATUS_BASIC: i32 = 1;
pub const HIGHS_BASIS_STATUS_UPPER: i32 = 2;
pub const HIGHS_BASIS_STATUS_ZERO: i32 = 3;
pub const HIGHS_BASIS_STATUS_NONBASIC: i32 = 4;
pub const HIGHS_MATRIX_FORMAT_COLWISE: i32 = 1;
pub const HIGHS_MATRIX_FORMAT_ROWWISE: i32 = 2;
pub const HIGHS_OBJ_SENSE_MINIMIZE: i32 = 1;
unsafe extern "C" {
pub fn cobre_highs_create() -> *mut c_void;
pub fn cobre_highs_destroy(highs: *mut c_void);
pub fn cobre_highs_pass_lp(
highs: *mut c_void,
num_col: int32_t,
num_row: int32_t,
num_nz: int32_t,
a_format: int32_t,
sense: int32_t,
offset: c_double,
col_cost: *const c_double,
col_lower: *const c_double,
col_upper: *const c_double,
row_lower: *const c_double,
row_upper: *const c_double,
a_start: *const int32_t,
a_index: *const int32_t,
a_value: *const c_double,
) -> c_int;
pub fn cobre_highs_add_rows(
highs: *mut c_void,
num_new_row: int32_t,
lower: *const c_double,
upper: *const c_double,
num_new_nz: int32_t,
starts: *const int32_t,
index: *const int32_t,
value: *const c_double,
) -> c_int;
pub fn cobre_highs_change_rows_bounds_by_set(
highs: *mut c_void,
num_set_entries: int32_t,
set: *const int32_t,
lower: *const c_double,
upper: *const c_double,
) -> c_int;
pub fn cobre_highs_change_cols_bounds_by_set(
highs: *mut c_void,
num_set_entries: int32_t,
set: *const int32_t,
lower: *const c_double,
upper: *const c_double,
) -> c_int;
pub fn cobre_highs_run(highs: *mut c_void) -> c_int;
pub fn cobre_highs_get_solution(
highs: *const c_void,
col_value: *mut c_double,
col_dual: *mut c_double,
row_value: *mut c_double,
row_dual: *mut c_double,
) -> c_int;
pub fn cobre_highs_get_objective_value(highs: *const c_void) -> c_double;
pub fn cobre_highs_get_model_status(highs: *const c_void) -> c_int;
pub fn cobre_highs_get_simplex_iteration_count(highs: *const c_void) -> c_int;
pub fn cobre_highs_set_basis_non_alien(
highs: *mut c_void,
col_status: *const int32_t,
row_status: *const int32_t,
) -> c_int;
pub fn cobre_highs_get_basis(
highs: *const c_void,
col_status: *mut int32_t,
row_status: *mut int32_t,
) -> c_int;
pub fn cobre_highs_clear_solver(highs: *mut c_void) -> c_int;
pub fn cobre_highs_set_string_option(
highs: *mut c_void,
option: *const c_char,
value: *const c_char,
) -> c_int;
pub fn cobre_highs_set_bool_option(
highs: *mut c_void,
option: *const c_char,
value: int32_t,
) -> c_int;
pub fn cobre_highs_set_int_option(
highs: *mut c_void,
option: *const c_char,
value: int32_t,
) -> c_int;
pub fn cobre_highs_set_double_option(
highs: *mut c_void,
option: *const c_char,
value: c_double,
) -> c_int;
pub fn cobre_highs_get_int_option(
highs: *const c_void,
option: *const c_char,
value: *mut c_int,
) -> c_int;
pub fn cobre_highs_get_double_option(
highs: *const c_void,
option: *const c_char,
value: *mut c_double,
) -> c_int;
pub fn cobre_highs_get_dual_ray(
highs: *const c_void,
has_dual_ray: *mut int32_t,
dual_ray_value: *mut c_double,
) -> c_int;
pub fn cobre_highs_get_primal_ray(
highs: *const c_void,
has_primal_ray: *mut int32_t,
primal_ray_value: *mut c_double,
) -> c_int;
pub fn cobre_highs_get_num_col(highs: *const c_void) -> c_int;
pub fn cobre_highs_get_num_row(highs: *const c_void) -> c_int;
pub fn cobre_highs_version_major() -> c_int;
pub fn cobre_highs_version_minor() -> c_int;
pub fn cobre_highs_version_patch() -> c_int;
}
#[cfg(all(test, feature = "highs"))]
mod tests {
use super::*;
#[test]
fn test_ffi_smoke_create_solve_destroy() {
let highs = unsafe { cobre_highs_create() };
assert!(!highs.is_null(), "cobre_highs_create() returned null");
let status = unsafe { cobre_highs_set_bool_option(highs, c"output_flag".as_ptr(), 0) };
assert_eq!(
status, HIGHS_STATUS_OK,
"cobre_highs_set_bool_option(output_flag) returned status {status}"
);
let col_cost: [f64; 1] = [1.0];
let col_lower: [f64; 1] = [0.0];
let col_upper: [f64; 1] = [10.0];
let a_start: [i32; 2] = [0, 0];
let status = unsafe {
cobre_highs_pass_lp(
highs,
1, 0, 0, HIGHS_MATRIX_FORMAT_COLWISE,
HIGHS_OBJ_SENSE_MINIMIZE,
0.0, col_cost.as_ptr(),
col_lower.as_ptr(),
col_upper.as_ptr(),
std::ptr::null(), std::ptr::null(), a_start.as_ptr(),
std::ptr::null(), std::ptr::null(), )
};
assert_eq!(
status, HIGHS_STATUS_OK,
"cobre_highs_pass_lp() returned status {status}"
);
let status = unsafe { cobre_highs_run(highs) };
assert_eq!(
status, HIGHS_STATUS_OK,
"cobre_highs_run() returned status {status}"
);
let model_status = unsafe { cobre_highs_get_model_status(highs) };
assert_eq!(
model_status, HIGHS_MODEL_STATUS_OPTIMAL,
"expected Optimal model status, got {model_status}"
);
let obj = unsafe { cobre_highs_get_objective_value(highs) };
assert!(
(obj - 0.0_f64).abs() < 1e-10,
"objective value {obj} is not within 1e-10 of expected 0.0"
);
unsafe { cobre_highs_destroy(highs) };
}
}