problemreductions/rules/
minimumvertexcover_longestcommonsubsequence.rs1use crate::models::graph::MinimumVertexCover;
4use crate::models::misc::LongestCommonSubsequence;
5use crate::reduction;
6use crate::rules::traits::{ReduceTo, ReductionResult};
7use crate::topology::{Graph, SimpleGraph};
8use crate::types::One;
9
10#[derive(Debug, Clone)]
11pub struct ReductionVCToLCS {
12 target: LongestCommonSubsequence,
13 num_vertices: usize,
14}
15
16impl ReductionResult for ReductionVCToLCS {
17 type Source = MinimumVertexCover<SimpleGraph, One>;
18 type Target = LongestCommonSubsequence;
19
20 fn target_problem(&self) -> &Self::Target {
21 &self.target
22 }
23
24 fn extract_solution(
25 &self,
26 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
27 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
28 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
29
30 Ok({
31 let mut cover = vec![true; self.num_vertices];
32 for &symbol in target_solution {
33 let Some(symbol) = symbol else { break };
34 cover[symbol] = false;
35 }
36 cover
37 })
38 }
39}
40
41#[reduction(
42 transform = {
43 exact {
44 alphabet_size = "num_vertices",
45 num_strings = "num_edges + 1",
46 max_length = "num_vertices",
47 total_length = "num_vertices + 2 * num_edges * num_vertices - 2 * num_edges",
48 sum_triangular_lengths = "num_vertices * (num_vertices + 1) / 2 + num_edges * (2 * num_vertices - 2) * (2 * num_vertices - 1) / 2",
49 },
50 upper_bound {
51 num_transitions = "num_vertices",
52 },
53 },
54 unavailable = {
55 cross_frequency_product = "each symbol occurs once in the base string and at most twice in each of num_edges edge strings; the source-only bound num_vertices * 2^num_edges needs a variable exponent, unsupported by the exact evaluator; endpoint incidences determine the exact product",
56 }
57)]
58impl ReduceTo<LongestCommonSubsequence> for MinimumVertexCover<SimpleGraph, One> {
59 type Result = ReductionVCToLCS;
60
61 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
62 let num_vertices = self.graph().num_vertices();
63 let mut strings = Vec::with_capacity(self.graph().num_edges() + 1);
64 strings.push((0..num_vertices).collect());
65
66 for (left, right) in self.graph().edges() {
67 let (u, v) = if left < right {
70 (left, right)
71 } else {
72 (right, left)
73 };
74 let mut edge_string = string_without_vertex(num_vertices, u);
75 edge_string.extend(string_without_vertex(num_vertices, v));
76 strings.push(edge_string);
77 }
78
79 let target = LongestCommonSubsequence::new(num_vertices, strings);
80 Ok(ReductionVCToLCS {
81 target,
82 num_vertices,
83 })
84 }
85}
86
87fn string_without_vertex(num_vertices: usize, omitted: usize) -> Vec<usize> {
88 (0..num_vertices)
89 .filter(|&vertex| vertex != omitted)
90 .collect()
91}
92
93#[cfg(feature = "example-db")]
94pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
95 use crate::export::SolutionPair;
96
97 vec![crate::example_db::specs::RuleExampleSpec {
98 id: "minimumvertexcover_to_longestcommonsubsequence",
99 build: || {
100 let source = MinimumVertexCover::new(
101 SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)]),
102 vec![One; 4],
103 );
104 crate::example_db::specs::rule_example_with_witness::<_, LongestCommonSubsequence>(
105 source,
106 SolutionPair {
107 source_config: serde_json::json!(vec![false, true, true, false]),
108 target_config: serde_json::json!(vec![Some(0), Some(3), None, None]),
109 },
110 )
111 },
112 }]
113}
114
115#[cfg(test)]
116#[path = "../unit_tests/rules/minimumvertexcover_longestcommonsubsequence.rs"]
117mod tests;