problemreductions/rules/
maxcut_minimumcutintoboundedsets.rs1use crate::models::graph::{MaxCut, MinimumCutIntoBoundedSets};
11use crate::reduction;
12use crate::rules::traits::{ReduceTo, ReductionResult};
13use crate::topology::{Graph, SimpleGraph};
14
15#[derive(Debug, Clone)]
17pub struct ReductionMaxCutToMinCutBounded {
18 target: MinimumCutIntoBoundedSets<SimpleGraph, i32>,
19 original_n: usize,
21}
22
23impl ReductionResult for ReductionMaxCutToMinCutBounded {
24 type Source = MaxCut<SimpleGraph, i32>;
25 type Target = MinimumCutIntoBoundedSets<SimpleGraph, i32>;
26
27 fn target_problem(&self) -> &Self::Target {
28 &self.target
29 }
30
31 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
34 target_solution[..self.original_n].to_vec()
35 }
36}
37
38#[reduction(
39 overhead = {
40 num_vertices = "2 * num_vertices + 2",
41 num_edges = "(num_vertices + 1) * (2 * num_vertices + 1)",
42 }
43)]
44impl ReduceTo<MinimumCutIntoBoundedSets<SimpleGraph, i32>> for MaxCut<SimpleGraph, i32> {
45 type Result = ReductionMaxCutToMinCutBounded;
46
47 fn reduce_to(&self) -> Self::Result {
48 let n = self.graph().num_vertices();
49
50 let n_prime = n + (n % 2); let big_n = 2 * n_prime;
54
55 let w_max = self.edge_weights().iter().copied().max().unwrap_or(0) + 1;
57
58 let orig_edges = self.graph().edges();
60 let mut edge_weight_map: std::collections::HashMap<(usize, usize), i32> =
61 std::collections::HashMap::new();
62 for (idx, &(u, v)) in orig_edges.iter().enumerate() {
63 let w = *self.edge_weight_by_index(idx).unwrap();
64 let (a, b) = if u < v { (u, v) } else { (v, u) };
65 edge_weight_map.insert((a, b), w);
66 }
67
68 let mut edges = Vec::new();
70 let mut weights = Vec::new();
71 for i in 0..big_n {
72 for j in (i + 1)..big_n {
73 edges.push((i, j));
74 if let Some(&w) = edge_weight_map.get(&(i, j)) {
75 weights.push(w_max - w);
76 } else {
77 weights.push(w_max);
78 }
79 }
80 }
81
82 let source_vertex = n_prime;
84 let sink_vertex = n_prime + 1;
85 let size_bound = n_prime;
86
87 let target = MinimumCutIntoBoundedSets::new(
88 SimpleGraph::new(big_n, edges),
89 weights,
90 source_vertex,
91 sink_vertex,
92 size_bound,
93 );
94
95 ReductionMaxCutToMinCutBounded {
96 target,
97 original_n: n,
98 }
99 }
100}
101
102#[cfg(feature = "example-db")]
103pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
104 use crate::export::SolutionPair;
105 use crate::solvers::BruteForce;
106
107 vec![crate::example_db::specs::RuleExampleSpec {
108 id: "maxcut_to_minimumcutintoboundedsets",
109 build: || {
110 let source = MaxCut::new(
112 SimpleGraph::new(3, vec![(0, 1), (1, 2), (0, 2)]),
113 vec![1i32, 1, 1],
114 );
115 let reduction =
116 ReduceTo::<MinimumCutIntoBoundedSets<SimpleGraph, i32>>::reduce_to(&source);
117
118 let solver = BruteForce::new();
120 let source_witness = solver.find_witness(&source).unwrap();
121 let target_witness = solver.find_witness(reduction.target_problem()).unwrap();
122
123 crate::example_db::specs::assemble_rule_example(
124 &source,
125 reduction.target_problem(),
126 vec![SolutionPair {
127 source_config: source_witness,
128 target_config: target_witness,
129 }],
130 )
131 },
132 }]
133}
134
135#[cfg(test)]
136#[path = "../unit_tests/rules/maxcut_minimumcutintoboundedsets.rs"]
137mod tests;