problemreductions/rules/
ksatisfiability_decisionminimumvertexcover.rs1use crate::models::decision::Decision;
15use crate::models::formula::KSatisfiability;
16use crate::models::graph::MinimumVertexCover;
17use crate::reduction;
18use crate::rules::traits::{ReduceTo, ReductionResult};
19use crate::topology::SimpleGraph;
20use crate::types::One;
21use crate::variant::K3;
22
23#[derive(Debug, Clone)]
25pub struct Reduction3SATToDecisionMVC {
26 target: Decision<MinimumVertexCover<SimpleGraph, One>>,
27 source_num_vars: usize,
28}
29
30impl ReductionResult for Reduction3SATToDecisionMVC {
31 type Source = KSatisfiability<K3>;
32 type Target = Decision<MinimumVertexCover<SimpleGraph, One>>;
33
34 fn target_problem(&self) -> &Self::Target {
35 &self.target
36 }
37
38 fn extract_solution(
46 &self,
47 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
48 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
49 crate::rules::traits::validate_target_witness(
50 self.target_problem(),
51 target_solution,
52 |value| value.0,
53 "target witness does not certify a YES answer for the source",
54 )?;
55
56 Ok({
57 (0..self.source_num_vars)
58 .map(|i| {
59 target_solution[2 * i]
61 })
62 .collect()
63 })
64 }
65}
66
67#[crate::aggregate_reduction(identity)]
68impl crate::rules::AggregateReductionResult for Reduction3SATToDecisionMVC {}
69
70#[reduction(
71 transform = exact {
72 num_vertices = "2 * num_vars + 3 * num_clauses",
73 num_edges = "num_vars + 6 * num_clauses",
74 }
75)]
76impl ReduceTo<Decision<MinimumVertexCover<SimpleGraph, One>>> for KSatisfiability<K3> {
77 type Result = Reduction3SATToDecisionMVC;
78
79 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
80 let n = self.num_vars();
81 let m = self.num_clauses();
82 let total_vertices = 2 * n + 3 * m;
83 let mut edges: Vec<(usize, usize)> = Vec::with_capacity(n + 6 * m);
84
85 for i in 0..n {
88 edges.push((2 * i, 2 * i + 1));
89 }
90
91 for (j, clause) in self.clauses().iter().enumerate() {
94 let base = 2 * n + 3 * j;
95
96 edges.push((base, base + 1));
98 edges.push((base + 1, base + 2));
99 edges.push((base, base + 2));
100
101 for k in 0..3 {
103 if clause.literals.is_empty() {
104 edges.push((base + k, base + k));
107 continue;
108 }
109 let lit = clause.literals[k % clause.literals.len()];
111 let var_idx = lit.unsigned_abs() as usize - 1; let literal_vertex = if lit > 0 {
113 2 * var_idx } else {
115 2 * var_idx + 1 };
117 edges.push((base + k, literal_vertex));
118 }
119 }
120
121 let graph = SimpleGraph::new(total_vertices, edges);
122 let weights = vec![One; total_vertices];
123 let target = MinimumVertexCover::new(graph, weights);
124
125 Ok(Reduction3SATToDecisionMVC {
126 target: Decision::new(
127 target,
128 <Self as ReduceTo<Decision<MinimumVertexCover<SimpleGraph, One>>>>::exact_i64(
129 n + 2 * m,
130 "computing the cover bound",
131 )?,
132 ),
133 source_num_vars: n,
134 })
135 }
136}
137
138#[cfg(feature = "example-db")]
139pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
140 use crate::export::SolutionPair;
141 use crate::models::formula::CNFClause;
142
143 vec![crate::example_db::specs::RuleExampleSpec {
144 id: "ksatisfiability_to_decisionminimumvertexcover",
145 build: || {
146 let source = KSatisfiability::<K3>::new(
147 3,
148 vec![
149 CNFClause::new(vec![1, 2, 3]),
150 CNFClause::new(vec![-1, -2, 3]),
151 ],
152 );
153 crate::example_db::specs::rule_example_with_witness::<
154 _,
155 Decision<MinimumVertexCover<SimpleGraph, One>>,
156 >(
157 source,
158 SolutionPair {
159 source_config: serde_json::json!(vec![false, false, true]),
161 target_config: serde_json::json!(vec![
169 false, true, false, true, true, false, true, true, false, true, true, false
170 ]),
171 },
172 )
173 },
174 }]
175}
176
177#[cfg(test)]
178#[path = "../unit_tests/rules/ksatisfiability_decisionminimumvertexcover.rs"]
179mod tests;