problemreductions/rules/
binpacking_ilp.rs1use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP};
10use crate::models::misc::BinPacking;
11use crate::reduction;
12use crate::rules::traits::{ReduceTo, ReductionResult};
13
14#[derive(Debug, Clone)]
22pub struct ReductionBPToILP {
23 target: ILP<bool>,
24 n: usize,
26}
27
28impl ReductionResult for ReductionBPToILP {
29 type Source = BinPacking<i32>;
30 type Target = ILP<bool>;
31
32 fn target_problem(&self) -> &ILP<bool> {
33 &self.target
34 }
35
36 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
40 let n = self.n;
41 let mut assignment = vec![0usize; n];
42 for i in 0..n {
43 for j in 0..n {
44 if target_solution[i * n + j] == 1 {
45 assignment[i] = j;
46 break;
47 }
48 }
49 }
50 assignment
51 }
52}
53
54#[reduction(
55 overhead = {
56 num_vars = "num_items * num_items + num_items",
57 num_constraints = "2 * num_items",
58 }
59)]
60impl ReduceTo<ILP<bool>> for BinPacking<i32> {
61 type Result = ReductionBPToILP;
62
63 fn reduce_to(&self) -> Self::Result {
64 let n = self.num_items();
65 let num_vars = n * n + n;
66
67 let mut constraints = Vec::with_capacity(2 * n);
68
69 for i in 0..n {
71 let terms: Vec<(usize, f64)> = (0..n).map(|j| (i * n + j, 1.0)).collect();
72 constraints.push(LinearConstraint::eq(terms, 1.0));
73 }
74
75 let cap = *self.capacity() as f64;
78 for j in 0..n {
79 let mut terms: Vec<(usize, f64)> = self
80 .sizes()
81 .iter()
82 .enumerate()
83 .map(|(i, w)| (i * n + j, *w as f64))
84 .collect();
85 terms.push((n * n + j, -cap));
87 constraints.push(LinearConstraint::le(terms, 0.0));
88 }
89
90 let objective: Vec<(usize, f64)> = (0..n).map(|j| (n * n + j, 1.0)).collect();
92
93 let target = ILP::new(num_vars, constraints, objective, ObjectiveSense::Minimize);
94
95 ReductionBPToILP { target, n }
96 }
97}
98
99#[cfg(feature = "example-db")]
100pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
101 use crate::export::SolutionPair;
102
103 vec![crate::example_db::specs::RuleExampleSpec {
104 id: "binpacking_to_ilp",
105 build: || {
106 crate::example_db::specs::rule_example_with_witness::<_, ILP<bool>>(
107 BinPacking::new(vec![6, 5, 5, 4, 3], 10),
108 SolutionPair {
109 source_config: vec![2, 1, 0, 0, 2],
110 target_config: vec![
111 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0,
112 1, 1, 1, 0, 0,
113 ],
114 },
115 )
116 },
117 }]
118}
119
120#[cfg(test)]
121#[path = "../unit_tests/rules/binpacking_ilp.rs"]
122mod tests;