problemreductions/rules/
ksatisfiability_kernel.rs1use crate::models::formula::KSatisfiability;
7use crate::models::graph::Kernel;
8use crate::reduction;
9use crate::rules::traits::{ReduceTo, ReductionResult};
10use crate::topology::DirectedGraph;
11use crate::variant::K3;
12
13#[derive(Debug, Clone)]
15pub struct Reduction3SatToKernel {
16 target: Kernel,
17 source_num_vars: usize,
18}
19
20impl ReductionResult for Reduction3SatToKernel {
21 type Source = KSatisfiability<K3>;
22 type Target = Kernel;
23
24 fn target_problem(&self) -> &Self::Target {
25 &self.target
26 }
27
28 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
29 (0..self.source_num_vars)
30 .map(|i| usize::from(target_solution.get(2 * i).copied().unwrap_or(0) == 1))
31 .collect()
32 }
33}
34
35fn literal_vertex(literal: i32) -> usize {
36 let variable = literal.unsigned_abs() as usize - 1;
37 if literal > 0 {
38 2 * variable
39 } else {
40 2 * variable + 1
41 }
42}
43
44#[reduction(
45 overhead = {
46 num_vertices = "2 * num_vars + 3 * num_clauses",
47 num_arcs = "2 * num_vars + 6 * num_clauses",
48 }
49)]
50impl ReduceTo<Kernel> for KSatisfiability<K3> {
51 type Result = Reduction3SatToKernel;
52
53 fn reduce_to(&self) -> Self::Result {
54 let num_vars = self.num_vars();
55 let num_clauses = self.num_clauses();
56 let mut arcs = Vec::with_capacity(2 * num_vars + 6 * num_clauses);
57
58 for variable in 0..num_vars {
59 let positive = 2 * variable;
60 let negative = positive + 1;
61 arcs.push((positive, negative));
62 arcs.push((negative, positive));
63 }
64
65 for (clause_index, clause) in self.clauses().iter().enumerate() {
66 let clause_base = 2 * num_vars + 3 * clause_index;
67 arcs.push((clause_base, clause_base + 1));
68 arcs.push((clause_base + 1, clause_base + 2));
69 arcs.push((clause_base + 2, clause_base));
70
71 for (literal_index, &literal) in clause.literals.iter().enumerate() {
72 arcs.push((clause_base + literal_index, literal_vertex(literal)));
73 }
74 }
75
76 Reduction3SatToKernel {
77 target: Kernel::new(DirectedGraph::new(2 * num_vars + 3 * num_clauses, arcs)),
78 source_num_vars: num_vars,
79 }
80 }
81}
82
83#[cfg(feature = "example-db")]
84pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
85 use crate::export::SolutionPair;
86 use crate::models::formula::CNFClause;
87
88 vec![crate::example_db::specs::RuleExampleSpec {
89 id: "ksatisfiability_to_kernel",
90 build: || {
91 crate::example_db::specs::rule_example_with_witness::<_, Kernel>(
92 KSatisfiability::<K3>::new(
93 3,
94 vec![
95 CNFClause::new(vec![1, 2, 3]),
96 CNFClause::new(vec![-1, -2, 3]),
97 ],
98 ),
99 SolutionPair {
100 source_config: vec![1, 1, 1],
101 target_config: vec![1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0],
102 },
103 )
104 },
105 }]
106}
107#[cfg(test)]
108#[path = "../unit_tests/rules/ksatisfiability_kernel.rs"]
109mod tests;