Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "highs"
version = "1.12.0"
version = "2.0.0"
authors = ["Ophir LOJKINE", "rust-or"]
edition = "2021"
description = "Safe rust bindings for the HiGHS linear programming solver. See http://highs.dev."
Expand All @@ -9,5 +9,5 @@ repository = "https://github.com/rust-or/highs"
keywords = ["linear-programming", "optimization", "math", "solver"]

[dependencies]
highs-sys = "1.11.0"
highs-sys = "1.12.0"
log = "0.4.27"
29 changes: 19 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ use highs_sys::*;

pub use matrix_col::{ColMatrix, Row};
pub use matrix_row::{Col, RowMatrix};
pub use status::{HighsModelStatus, HighsStatus};
pub use status::{HighsModelStatus, HighsSolutionStatus, HighsStatus};

use crate::options::HighsOptionValue;

Expand Down Expand Up @@ -261,12 +261,12 @@ pub enum Sense {

impl Model {
/// Return pointer to underlying HiGHS model
pub fn as_ptr(&self) -> *const c_void{
pub fn as_ptr(&self) -> *const c_void {
self.highs.ptr()
}

/// Return mutable pointer to underlying HiGHS model
pub fn as_mut_ptr(&mut self) -> *mut c_void{
pub fn as_mut_ptr(&mut self) -> *mut c_void {
self.highs.mut_ptr()
}

Expand Down Expand Up @@ -452,10 +452,7 @@ impl Model {
bound_value(bounds.start_bound()).unwrap_or(f64::NEG_INFINITY),
bound_value(bounds.end_bound()).unwrap_or(f64::INFINITY),
rows.len().try_into().unwrap(),
rows.into_iter()
.map(|r| r.0)
.collect::<Vec<_>>()
.as_ptr(),
rows.into_iter().map(|r| r.0).collect::<Vec<_>>().as_ptr(),
factors.as_ptr()
))
}?;
Expand Down Expand Up @@ -602,12 +599,12 @@ impl HighsPtr {

impl SolvedModel {
/// Return pointer to underlying HiGHS model
pub fn as_ptr(&self) -> *const c_void{
pub fn as_ptr(&self) -> *const c_void {
self.highs.ptr()
}

/// Return mutable pointer to underlying HiGHS model
pub fn as_mut_ptr(&mut self) -> *mut c_void{
pub fn as_mut_ptr(&mut self) -> *mut c_void {
self.highs.mut_ptr()
}

Expand All @@ -618,7 +615,7 @@ impl SolvedModel {
unsafe { highs_sys::Highs_getObjectiveValue(self.as_ptr()) }
}

/// The status of the solution. Should be Optimal if everything went well.
/// The model status of the solution. Should be Optimal if everything went well.
pub fn status(&self) -> HighsModelStatus {
let model_status = unsafe { Highs_getModelStatus(self.highs.unsafe_mut_ptr()) };
HighsModelStatus::try_from(model_status).unwrap()
Expand All @@ -636,6 +633,18 @@ impl SolvedModel {
.unwrap()
}

/// The primal solution status, reflecting if a solution was found or not.
pub fn primal_solution_status(&self) -> HighsSolutionStatus {
let name = CString::new("primal_solution_status").unwrap();
let solution_status: &mut HighsInt = &mut -1;
let status = unsafe {
Highs_getIntInfoValue(self.highs.unsafe_mut_ptr(), name.as_ptr(), solution_status)
};
try_handle_status(status, "Highs_getIntInfoValue")
.map(|_| HighsSolutionStatus::try_from(*solution_status).unwrap())
.unwrap()
}

/// Get the solution to the problem
pub fn get_solution(&self) -> Solution {
let cols = self.num_cols();
Expand Down
39 changes: 36 additions & 3 deletions src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use highs_sys::*;

/// The kinds of results of an optimization
#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Ord, Eq)]
#[non_exhaustive]
pub enum HighsModelStatus {
/// not initialized
NotSet = MODEL_STATUS_NOTSET as isize,
Expand Down Expand Up @@ -39,12 +40,18 @@ pub enum HighsModelStatus {
ObjectiveBound = MODEL_STATUS_OBJECTIVE_BOUND as isize,
/// objective target
ObjectiveTarget = MODEL_STATUS_OBJECTIVE_TARGET as isize,
/// reached limit
/// reached time limit
ReachedTimeLimit = MODEL_STATUS_REACHED_TIME_LIMIT as isize,
/// reached limit
/// reached iteration limit
ReachedIterationLimit = MODEL_STATUS_REACHED_ITERATION_LIMIT as isize,
/// Unknown model status
Unknown = MODEL_STATUS_UNKNOWN as isize,
/// reached solution limit
ReachedSolutionLimit = MODEL_STATUS_REACHED_SOLUTION_LIMIT as isize,
/// interrupted
ReachedInterrupt = MODEL_STATUS_REACHED_INTERRUPT as isize,
/// reached memory limit
ReachedMemoryLimit = MODEL_STATUS_REACHED_MEMORY_LIMIT as isize,
Comment thread
TeXitoi marked this conversation as resolved.
}

/// This error should never happen: an unexpected status was returned
Expand All @@ -67,7 +74,6 @@ impl TryFrom<c_int> for HighsModelStatus {
type Error = InvalidStatus;

fn try_from(value: c_int) -> Result<Self, Self::Error> {
use highs_sys::*;
match value {
MODEL_STATUS_NOTSET => Ok(Self::NotSet),
MODEL_STATUS_LOAD_ERROR => Ok(Self::LoadError),
Expand All @@ -85,6 +91,9 @@ impl TryFrom<c_int> for HighsModelStatus {
MODEL_STATUS_REACHED_TIME_LIMIT => Ok(Self::ReachedTimeLimit),
MODEL_STATUS_REACHED_ITERATION_LIMIT => Ok(Self::ReachedIterationLimit),
MODEL_STATUS_UNKNOWN => Ok(Self::Unknown),
MODEL_STATUS_REACHED_SOLUTION_LIMIT => Ok(Self::ReachedSolutionLimit),
MODEL_STATUS_REACHED_INTERRUPT => Ok(Self::ReachedInterrupt),
MODEL_STATUS_REACHED_MEMORY_LIMIT => Ok(Self::ReachedMemoryLimit),
n => Err(InvalidStatus(n)),
}
}
Expand Down Expand Up @@ -119,3 +128,27 @@ impl TryFrom<c_int> for HighsStatus {
}
}
}

/// The status of a solution
#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Ord, Eq)]
pub enum HighsSolutionStatus {
/// No solution found
None = SOLUTION_STATUS_NONE as isize,
/// No solution exists
Infeasible = SOLUTION_STATUS_INFEASIBLE as isize,
/// A feasible solution was found
Feasible = SOLUTION_STATUS_FEASIBLE as isize,
}

impl TryFrom<c_int> for HighsSolutionStatus {
type Error = InvalidStatus;

fn try_from(value: c_int) -> Result<Self, Self::Error> {
match value {
SOLUTION_STATUS_NONE => Ok(Self::None),
SOLUTION_STATUS_INFEASIBLE => Ok(Self::Infeasible),
SOLUTION_STATUS_FEASIBLE => Ok(Self::Feasible),
n => Err(InvalidStatus(n)),
}
}
}