problemreductions/rules/
minimumvertexcover_minimumweightandorgraph.rs1use crate::models::graph::MinimumVertexCover;
4use crate::models::misc::MinimumWeightAndOrGraph;
5use crate::reduction;
6use crate::rules::traits::{ReduceTo, ReductionResult};
7use crate::topology::Graph;
8use crate::topology::SimpleGraph;
9
10#[derive(Debug, Clone)]
12pub struct ReductionVCToAndOrGraph {
13 target: MinimumWeightAndOrGraph,
14 sink_arc_start: usize,
15 num_source_vertices: usize,
16}
17
18impl ReductionResult for ReductionVCToAndOrGraph {
19 type Source = MinimumVertexCover<SimpleGraph, i32>;
20 type Target = MinimumWeightAndOrGraph;
21
22 fn target_problem(&self) -> &Self::Target {
23 &self.target
24 }
25
26 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
27 (0..self.num_source_vertices)
28 .map(|j| usize::from(target_solution.get(self.sink_arc_start + j) == Some(&1)))
29 .collect()
30 }
31}
32
33#[reduction(
34 overhead = {
35 num_vertices = "1 + num_edges + 2 * num_vertices",
36 num_arcs = "3 * num_edges + num_vertices",
37 }
38)]
39impl ReduceTo<MinimumWeightAndOrGraph> for MinimumVertexCover<SimpleGraph, i32> {
40 type Result = ReductionVCToAndOrGraph;
41
42 fn reduce_to(&self) -> Self::Result {
43 let n = self.graph().num_vertices();
44 let edges = self.graph().edges();
45 let m = edges.len();
46
47 let num_target_vertices = 1 + m + (2 * n);
48 let mut gate_types = vec![None; num_target_vertices];
49 gate_types[0] = Some(true);
50 for gate in gate_types.iter_mut().skip(1).take(m + n) {
51 *gate = Some(false);
52 }
53
54 let edge_vertex = |i: usize| 1 + i;
55 let cover_vertex = |j: usize| 1 + m + j;
56 let sink_vertex = |j: usize| 1 + m + n + j;
57
58 let mut arcs = Vec::with_capacity((3 * m) + n);
59 let mut arc_weights = Vec::with_capacity((3 * m) + n);
60
61 for i in 0..m {
62 arcs.push((0, edge_vertex(i)));
63 arc_weights.push(1);
64 }
65
66 for (i, &(u, v)) in edges.iter().enumerate() {
67 arcs.push((edge_vertex(i), cover_vertex(u)));
68 arc_weights.push(1);
69 arcs.push((edge_vertex(i), cover_vertex(v)));
70 arc_weights.push(1);
71 }
72
73 let sink_arc_start = arcs.len();
74 for (j, &weight) in self.weights().iter().enumerate() {
75 arcs.push((cover_vertex(j), sink_vertex(j)));
76 arc_weights.push(weight);
77 }
78
79 let target =
80 MinimumWeightAndOrGraph::new(num_target_vertices, arcs, 0, gate_types, arc_weights);
81
82 ReductionVCToAndOrGraph {
83 target,
84 sink_arc_start,
85 num_source_vertices: n,
86 }
87 }
88}
89
90#[cfg(any(test, feature = "example-db"))]
91fn issue_example_source() -> MinimumVertexCover<SimpleGraph, i32> {
92 MinimumVertexCover::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i32; 3])
93}
94
95#[cfg(feature = "example-db")]
96pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
97 use crate::export::SolutionPair;
98
99 vec![crate::example_db::specs::RuleExampleSpec {
100 id: "minimumvertexcover_to_minimumweightandorgraph",
101 build: || {
102 crate::example_db::specs::rule_example_with_witness::<_, MinimumWeightAndOrGraph>(
103 issue_example_source(),
104 SolutionPair {
105 source_config: vec![0, 1, 0],
106 target_config: vec![1, 1, 0, 1, 1, 0, 0, 1, 0],
107 },
108 )
109 },
110 }]
111}
112
113#[cfg(test)]
114#[path = "../unit_tests/rules/minimumvertexcover_minimumweightandorgraph.rs"]
115mod tests;