use crate::ffi;
use scip_sys::SCIP_Status;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Status {
Unknown,
UserInterrupt,
NodeLimit,
TotalNodeLimit,
StallNodeLimit,
TimeLimit,
MemoryLimit,
GapLimit,
PrimalLimit,
DualLimit,
SolutionLimit,
BestSolutionLimit,
RestartLimit,
Optimal,
Infeasible,
Unbounded,
Inforunbd,
Terminate,
}
impl From<SCIP_Status> for Status {
fn from(val: SCIP_Status) -> Self {
match val {
ffi::SCIP_Status_SCIP_STATUS_UNKNOWN => Status::Unknown,
ffi::SCIP_Status_SCIP_STATUS_USERINTERRUPT => Status::UserInterrupt,
ffi::SCIP_Status_SCIP_STATUS_NODELIMIT => Status::NodeLimit,
ffi::SCIP_Status_SCIP_STATUS_TOTALNODELIMIT => Status::TotalNodeLimit,
ffi::SCIP_Status_SCIP_STATUS_STALLNODELIMIT => Status::StallNodeLimit,
ffi::SCIP_Status_SCIP_STATUS_TIMELIMIT => Status::TimeLimit,
ffi::SCIP_Status_SCIP_STATUS_MEMLIMIT => Status::MemoryLimit,
ffi::SCIP_Status_SCIP_STATUS_GAPLIMIT => Status::GapLimit,
ffi::SCIP_Status_SCIP_STATUS_PRIMALLIMIT => Status::PrimalLimit,
ffi::SCIP_Status_SCIP_STATUS_DUALLIMIT => Status::DualLimit,
ffi::SCIP_Status_SCIP_STATUS_SOLLIMIT => Status::SolutionLimit,
ffi::SCIP_Status_SCIP_STATUS_BESTSOLLIMIT => Status::BestSolutionLimit,
ffi::SCIP_Status_SCIP_STATUS_RESTARTLIMIT => Status::RestartLimit,
ffi::SCIP_Status_SCIP_STATUS_OPTIMAL => Status::Optimal,
ffi::SCIP_Status_SCIP_STATUS_INFEASIBLE => Status::Infeasible,
ffi::SCIP_Status_SCIP_STATUS_UNBOUNDED => Status::Unbounded,
ffi::SCIP_Status_SCIP_STATUS_INFORUNBD => Status::Inforunbd,
ffi::SCIP_Status_SCIP_STATUS_TERMINATE => Status::Terminate,
_ => panic!("Unknown SCIP status {val:?}"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Model;
#[test]
fn time_limit() {
let model = Model::new()
.hide_output()
.set_real_param("limits/time", 0.)
.unwrap()
.include_default_plugins()
.read_prob("data/test/simple.lp")
.unwrap()
.solve();
assert_eq!(model.status(), Status::TimeLimit);
}
#[test]
fn memory_limit() {
let model = Model::new()
.hide_output()
.set_real_param("limits/memory", 0.)
.unwrap()
.include_default_plugins()
.read_prob("data/test/gen-ip054.mps")
.unwrap()
.solve();
assert_eq!(model.status(), Status::MemoryLimit);
}
#[test]
fn gap_limit() {
let model = Model::new()
.hide_output()
.set_real_param("limits/gap", 100000.)
.unwrap()
.include_default_plugins()
.read_prob("data/test/gen-ip054.mps")
.unwrap()
.solve();
assert_eq!(model.status(), Status::GapLimit);
}
#[test]
fn solution_limit() {
let model = Model::new()
.hide_output()
.set_int_param("limits/solutions", 0)
.unwrap()
.include_default_plugins()
.read_prob("data/test/simple.lp")
.unwrap()
.solve();
assert_eq!(model.status(), Status::SolutionLimit);
}
#[test]
fn total_node_limit() {
let model = Model::new()
.hide_output()
.set_longint_param("limits/totalnodes", 0)
.unwrap()
.include_default_plugins()
.read_prob("data/test/simple.lp")
.unwrap()
.solve();
assert_eq!(model.status(), Status::TotalNodeLimit);
}
#[test]
fn stall_node_limit() {
let model = Model::new()
.hide_output()
.set_longint_param("limits/stallnodes", 0)
.unwrap()
.include_default_plugins()
.read_prob("data/test/simple.lp")
.unwrap()
.solve();
assert_eq!(model.status(), Status::StallNodeLimit);
}
#[test]
fn best_solution_limit() {
let model = Model::new()
.hide_output()
.set_int_param("limits/bestsol", 0)
.unwrap()
.include_default_plugins()
.read_prob("data/test/simple.lp")
.unwrap()
.solve();
assert_eq!(model.status(), Status::BestSolutionLimit);
}
#[test]
fn primal_limit() {
let mut model = Model::new()
.hide_output()
.include_default_plugins()
.read_prob("data/test/gen-ip054.mps")
.unwrap();
model = model.set_int_param("presolving/maxrounds", 0).unwrap();
model = model.set_real_param("limits/primal", 100000.).unwrap();
let model = model.solve();
assert_eq!(model.status(), Status::PrimalLimit);
}
#[test]
fn dual_limit() {
let mut model = Model::new()
.hide_output()
.include_default_plugins()
.read_prob("data/test/gen-ip054.mps")
.unwrap();
model = model.set_int_param("presolving/maxrounds", 0).unwrap();
model = model.set_real_param("limits/dual", -100000.).unwrap();
let model = model.solve();
assert_eq!(model.status(), Status::DualLimit);
}
#[test]
fn unknown() {
assert_eq!(Model::new().status(), Status::Unknown);
}
}