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 forced_cover: Vec<bool>,
16}
17
18impl ReductionResult for ReductionVCToAndOrGraph {
19 type Source = MinimumVertexCover<SimpleGraph, i64>;
20 type Target = MinimumWeightAndOrGraph;
21
22 fn target_problem(&self) -> &Self::Target {
23 &self.target
24 }
25
26 fn extract_solution(
27 &self,
28 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
29 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
30 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
31
32 Ok({
33 self.forced_cover
34 .iter()
35 .enumerate()
36 .map(|(j, &forced)| forced || target_solution[self.sink_arc_start + j])
37 .collect()
38 })
39 }
40}
41
42#[reduction(
43 transform = upper_bound {
44 num_vertices = "1 + num_edges + 2 * num_vertices",
45 num_arcs = "3 * num_edges + num_vertices",
46 }
47)]
48impl ReduceTo<MinimumWeightAndOrGraph> for MinimumVertexCover<SimpleGraph, i64> {
49 type Result = ReductionVCToAndOrGraph;
50
51 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
52 let n = self.graph().num_vertices();
53 let forced_cover: Vec<_> = self.weights().iter().map(|&w| w < 0).collect();
55 let edges: Vec<_> = self
56 .graph()
57 .edges()
58 .into_iter()
59 .filter(|&(u, v)| !forced_cover[u] && !forced_cover[v])
60 .collect();
61 let m = edges.len();
62
63 let num_target_vertices = 1 + m + (2 * n);
64 let mut gate_types = vec![None; num_target_vertices];
65 gate_types[0] = Some(true);
66 for gate in gate_types.iter_mut().skip(1).take(m + n) {
67 *gate = Some(false);
68 }
69
70 let edge_vertex = |i: usize| 1 + i;
71 let cover_vertex = |j: usize| 1 + m + j;
72 let sink_vertex = |j: usize| 1 + m + n + j;
73
74 let mut arcs = Vec::with_capacity((3 * m) + n);
75 let mut arc_weights = Vec::with_capacity((3 * m) + n);
76
77 for i in 0..m {
78 arcs.push((0, edge_vertex(i)));
79 arc_weights.push(1);
80 }
81
82 for (i, &(u, v)) in edges.iter().enumerate() {
83 arcs.push((edge_vertex(i), cover_vertex(u)));
84 arc_weights.push(1);
85 arcs.push((edge_vertex(i), cover_vertex(v)));
86 arc_weights.push(1);
87 }
88
89 let sink_arc_start = arcs.len();
90 for (j, &weight) in self.weights().iter().enumerate() {
91 arcs.push((cover_vertex(j), sink_vertex(j)));
92 arc_weights.push(weight.max(0));
93 }
94
95 let target =
96 MinimumWeightAndOrGraph::new(num_target_vertices, arcs, 0, gate_types, arc_weights);
97
98 Ok(ReductionVCToAndOrGraph {
99 target,
100 sink_arc_start,
101 forced_cover,
102 })
103 }
104}
105
106#[cfg(any(test, feature = "example-db"))]
107fn issue_example_source() -> MinimumVertexCover<SimpleGraph, i64> {
108 MinimumVertexCover::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3])
109}
110
111#[cfg(feature = "example-db")]
112pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
113 use crate::export::SolutionPair;
114
115 vec![crate::example_db::specs::RuleExampleSpec {
116 id: "minimumvertexcover_to_minimumweightandorgraph",
117 build: || {
118 crate::example_db::specs::rule_example_with_witness::<_, MinimumWeightAndOrGraph>(
119 issue_example_source(),
120 SolutionPair {
121 source_config: serde_json::json!(vec![false, true, false]),
122 target_config: serde_json::json!(vec![
123 true, true, false, true, true, false, false, true, false
124 ]),
125 },
126 )
127 },
128 }]
129}
130
131#[cfg(test)]
132#[path = "../unit_tests/rules/minimumvertexcover_minimumweightandorgraph.rs"]
133mod tests;