diff --git a/Cargo.toml b/Cargo.toml index 33ac588..0df007a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ coin_cbc = { version = "0.1", optional = true, default-features = false } minilp = { version = "0.2", optional = true } lpsolve = { version = "0.1", optional = true } highs = { version = "1.5.0", optional = true } -russcip = { version = "0.2.4", optional = true } +russcip = { version = "0.2.6", optional = true } lp-solvers = { version = "1.0.0", features = ["cplex"], optional = true } fnv = "1.0.5" diff --git a/src/cardinality_constraint_solver_trait.rs b/src/cardinality_constraint_solver_trait.rs new file mode 100644 index 0000000..3134d79 --- /dev/null +++ b/src/cardinality_constraint_solver_trait.rs @@ -0,0 +1,7 @@ +use crate::{Variable, constraint::ConstraintReference}; + +/// A trait for solvers that support cardinality constraints +pub trait CardinalityConstraintSolver { + /// Add cardinality constraint. Constrains the number of non-zero variables from `vars` to at most `rhs`. + fn add_cardinality_constraint(&mut self, vars: &[Variable], rhs: usize) -> ConstraintReference; +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index e83ee1c..cbd22ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,7 @@ //! pub use affine_expression_trait::IntoAffineExpression; +pub use cardinality_constraint_solver_trait::CardinalityConstraintSolver; pub use constraint::Constraint; pub use expression::Expression; #[cfg_attr(docsrs, doc(cfg(feature = "minilp")))] @@ -149,6 +150,7 @@ mod expression; #[macro_use] pub mod variable; mod affine_expression_trait; +mod cardinality_constraint_solver_trait; pub mod constraint; pub mod solvers; mod variables_macro; diff --git a/src/solvers/scip.rs b/src/solvers/scip.rs index 6a1122f..e556d09 100644 --- a/src/solvers/scip.rs +++ b/src/solvers/scip.rs @@ -15,6 +15,7 @@ use russcip::WithSolutions; use crate::variable::{UnsolvedProblem, VariableDefinition}; use crate::{ + CardinalityConstraintSolver, constraint::ConstraintReference, solvers::{ObjectiveDirection, ResolutionError, Solution, SolverModel}, }; @@ -81,9 +82,11 @@ impl SCIPProblem { pub fn as_inner_mut(&mut self) -> &mut Model { &mut self.model } +} +impl CardinalityConstraintSolver for SCIPProblem { /// Add cardinality constraint. Constrains the number of non-zero variables to at most `rhs`. - pub fn add_cardinality_constraint(&mut self, vars: &[Variable], rhs: usize) -> ConstraintReference { + fn add_cardinality_constraint(&mut self, vars: &[Variable], rhs: usize) -> ConstraintReference { let scip_vars = vars.iter() .map(|v| Rc::clone(&self.id_for_var[v])) .collect::>(); @@ -97,7 +100,6 @@ impl SCIPProblem { ConstraintReference { index } } - } impl SolverModel for SCIPProblem { @@ -175,7 +177,7 @@ impl Solution for SCIPSolved { #[cfg(test)] mod tests { - use crate::{constraint, variable, variables, Solution, SolverModel}; + use crate::{constraint, variable, variables, Solution, SolverModel, CardinalityConstraintSolver}; use super::scip;