problemreductions/rules/
qubo_ilp.rs1use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP, QUBO};
18use crate::reduction;
19use crate::rules::traits::{ReduceTo, ReductionResult};
20
21#[derive(Debug, Clone)]
23pub struct ReductionQUBOToILP {
24 target: ILP<bool>,
25 num_original: usize,
26}
27
28impl ReductionResult for ReductionQUBOToILP {
29 type Source = QUBO<f64>;
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> {
37 target_solution[..self.num_original].to_vec()
38 }
39}
40
41#[reduction(
42 overhead = {
43 num_vars = "num_vars^2",
44 num_constraints = "num_vars^2",
45 }
46)]
47impl ReduceTo<ILP<bool>> for QUBO<f64> {
48 type Result = ReductionQUBOToILP;
49
50 fn reduce_to(&self) -> Self::Result {
51 let n = self.num_vars();
52 let matrix = self.matrix();
53
54 let mut off_diag: Vec<(usize, usize, f64)> = Vec::new();
56 for (i, row) in matrix.iter().enumerate() {
57 for (j, &q_ij) in row.iter().enumerate().skip(i + 1) {
58 if q_ij != 0.0 {
59 off_diag.push((i, j, q_ij));
60 }
61 }
62 }
63
64 let m = off_diag.len();
65 let total_vars = n + m;
66
67 let mut objective: Vec<(usize, f64)> = Vec::new();
69 for (i, row) in matrix.iter().enumerate() {
70 let q_ii = row[i];
71 if q_ii != 0.0 {
72 objective.push((i, q_ii));
73 }
74 }
75 for (k, &(_, _, q_ij)) in off_diag.iter().enumerate() {
76 objective.push((n + k, q_ij));
77 }
78
79 let mut constraints = Vec::with_capacity(3 * m);
81 for (k, &(i, j, _)) in off_diag.iter().enumerate() {
82 let y_k = n + k;
83 constraints.push(LinearConstraint::le(vec![(y_k, 1.0), (i, -1.0)], 0.0));
85 constraints.push(LinearConstraint::le(vec![(y_k, 1.0), (j, -1.0)], 0.0));
87 constraints.push(LinearConstraint::ge(
89 vec![(y_k, 1.0), (i, -1.0), (j, -1.0)],
90 -1.0,
91 ));
92 }
93
94 let target = ILP::new(total_vars, constraints, objective, ObjectiveSense::Minimize);
95 ReductionQUBOToILP {
96 target,
97 num_original: n,
98 }
99 }
100}
101
102#[cfg(test)]
103#[path = "../unit_tests/rules/qubo_ilp.rs"]
104mod tests;