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(transform = {
44 exact {
45 num_vars = "num_sets",
46 },
47 upper_bound {
48 num_quadratic_terms = "num_sets * (num_sets - 1) / 2",
49 },
50})]
51impl ReduceTo<QUBO<f64>> for MaximumSetPacking<f64> {
52 type Result = ReductionSPToQUBO;
53
54 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
55 let n = self.num_sets();
56 let weights = self.weights_ref();
57 let max_weight = weights.iter().copied().fold(1.0_f64, f64::max);
60 let penalty = 2.0 * max_weight;
61 if !penalty.is_finite() {
62 return Err(crate::rules::ReductionError::non_finite_result::<
63 MaximumSetPacking<f64>,
64 QUBO<f64>,
65 >("computing the set-packing conflict penalty"));
66 }
67
68 let mut matrix = vec![vec![0.0; n]; n];
69
70 for i in 0..n {
72 matrix[i][i] = -weights[i];
73 }
74
75 for (i, j) in self.overlapping_pairs() {
77 let (a, b) = if i < j { (i, j) } else { (j, i) };
78 matrix[a][b] += penalty;
79 }
80
81 Ok(ReductionSPToQUBO {
82 target: QUBO::from_matrix(matrix).map_err(|message| {
83 crate::rules::ReductionError::construction::<MaximumSetPacking<f64>, QUBO<f64>>(
84 message,
85 )
86 })?,
87 })
88 }
89}
90
91#[cfg(feature = "example-db")]
92pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
93 use crate::export::SolutionPair;
94 use crate::models::set::MaximumSetPacking;
95
96 vec![crate::example_db::specs::RuleExampleSpec {
97 id: "maximumsetpacking_to_qubo",
98 build: || {
99 let source = MaximumSetPacking::<f64>::new(vec![
100 vec![0, 1, 2],
101 vec![2, 3, 4],
102 vec![4, 5, 6],
103 vec![6, 7, 0],
104 vec![1, 3, 5],
105 vec![0, 4, 7],
106 ]);
107 crate::example_db::specs::rule_example_with_witness::<_, QUBO<f64>>(
108 source,
109 SolutionPair {
110 source_config: serde_json::json!(vec![false, false, false, true, true, false]),
111 target_config: serde_json::json!(vec![false, false, false, true, true, false]),
112 },
113 )
114 },
115 }]
116}
117
118#[cfg(test)]
119#[path = "../unit_tests/rules/maximumsetpacking_qubo.rs"]
120mod tests;