problemreductions/rules/
maximumsetpacking_qubo.rs1use crate::models::algebraic::QUBO;
15use crate::models::set::MaximumSetPacking;
16use crate::reduction;
17use crate::rules::traits::{ReduceTo, ReductionResult};
18
19#[derive(Debug, Clone)]
21pub struct ReductionSPToQUBO {
22 target: QUBO<f64>,
23}
24
25impl ReductionResult for ReductionSPToQUBO {
26 type Source = MaximumSetPacking<f64>;
27 type Target = QUBO<f64>;
28
29 fn target_problem(&self) -> &Self::Target {
30 &self.target
31 }
32
33 fn extract_solution(
34 &self,
35 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
36 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
37 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
38
39 Ok(target_solution.to_vec())
40 }
41}
42
43#[reduction(
44 transform = exact {
45 num_vars = "num_sets",
46 }
47)]
48impl ReduceTo<QUBO<f64>> for MaximumSetPacking<f64> {
49 type Result = ReductionSPToQUBO;
50
51 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
52 let n = self.num_sets();
53 let weights = self.weights_ref();
54 let max_weight = weights.iter().copied().fold(1.0_f64, f64::max);
57 let penalty = 2.0 * max_weight;
58 if !penalty.is_finite() {
59 return Err(crate::rules::ReductionError::non_finite_result::<
60 MaximumSetPacking<f64>,
61 QUBO<f64>,
62 >("computing the set-packing conflict penalty"));
63 }
64
65 let mut matrix = vec![vec![0.0; n]; n];
66
67 for i in 0..n {
69 matrix[i][i] = -weights[i];
70 }
71
72 for (i, j) in self.overlapping_pairs() {
74 let (a, b) = if i < j { (i, j) } else { (j, i) };
75 matrix[a][b] += penalty;
76 }
77
78 Ok(ReductionSPToQUBO {
79 target: QUBO::from_matrix(matrix).map_err(|message| {
80 crate::rules::ReductionError::construction::<MaximumSetPacking<f64>, QUBO<f64>>(
81 message,
82 )
83 })?,
84 })
85 }
86}
87
88#[cfg(feature = "example-db")]
89pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
90 use crate::export::SolutionPair;
91 use crate::models::set::MaximumSetPacking;
92
93 vec![crate::example_db::specs::RuleExampleSpec {
94 id: "maximumsetpacking_to_qubo",
95 build: || {
96 let source = MaximumSetPacking::<f64>::new(vec![
97 vec![0, 1, 2],
98 vec![2, 3, 4],
99 vec![4, 5, 6],
100 vec![6, 7, 0],
101 vec![1, 3, 5],
102 vec![0, 4, 7],
103 ]);
104 crate::example_db::specs::rule_example_with_witness::<_, QUBO<f64>>(
105 source,
106 SolutionPair {
107 source_config: serde_json::json!(vec![false, false, false, true, true, false]),
108 target_config: serde_json::json!(vec![false, false, false, true, true, false]),
109 },
110 )
111 },
112 }]
113}
114
115#[cfg(test)]
116#[path = "../unit_tests/rules/maximumsetpacking_qubo.rs"]
117mod tests;