problemreductions/rules/
setsplitting_ilp.rs1use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP};
13use crate::models::set::SetSplitting;
14use crate::reduction;
15use crate::rules::traits::{ReduceTo, ReductionResult};
16
17#[derive(Debug, Clone)]
19pub struct ReductionSetSplittingToILP {
20 target: ILP<bool>,
21}
22
23impl ReductionResult for ReductionSetSplittingToILP {
24 type Source = SetSplitting;
25 type Target = ILP<bool>;
26
27 fn target_problem(&self) -> &ILP<bool> {
28 &self.target
29 }
30
31 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
32 target_solution.to_vec()
33 }
34}
35
36#[reduction(
37 overhead = {
38 num_vars = "universe_size",
39 num_constraints = "2 * num_subsets",
40 }
41)]
42impl ReduceTo<ILP<bool>> for SetSplitting {
43 type Result = ReductionSetSplittingToILP;
44
45 fn reduce_to(&self) -> Self::Result {
46 let num_vars = self.universe_size();
47 let mut constraints = Vec::new();
48
49 for subset in self.subsets() {
50 let k = subset.len();
51 let terms: Vec<(usize, f64)> = subset.iter().map(|&e| (e, 1.0)).collect();
52
53 constraints.push(LinearConstraint::ge(terms.clone(), 1.0));
55
56 constraints.push(LinearConstraint::le(terms, (k - 1) as f64));
58 }
59
60 let target = ILP::new(num_vars, constraints, vec![], ObjectiveSense::Minimize);
61 ReductionSetSplittingToILP { target }
62 }
63}
64
65#[cfg(feature = "example-db")]
66pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
67 vec![crate::example_db::specs::RuleExampleSpec {
68 id: "setsplitting_to_ilp",
69 build: || {
70 let source = SetSplitting::new(
71 6,
72 vec![vec![0, 1, 2], vec![2, 3, 4], vec![0, 4, 5], vec![1, 3, 5]],
73 );
74 crate::example_db::specs::rule_example_via_ilp::<_, bool>(source)
75 },
76 }]
77}
78
79#[cfg(test)]
80#[path = "../unit_tests/rules/setsplitting_ilp.rs"]
81mod tests;