problemreductions/rules/
ksatisfiability_oneinthreesatisfiability.rs1use crate::models::formula::{CNFClause, KSatisfiability, OneInThreeSatisfiability};
4use crate::reduction;
5use crate::rules::traits::{ReduceTo, ReductionResult};
6use crate::variant::K3;
7
8#[derive(Debug, Clone)]
9pub struct Reduction3SATToOneInThreeSAT {
10 source_num_vars: usize,
11 target: OneInThreeSatisfiability,
12}
13
14impl ReductionResult for Reduction3SATToOneInThreeSAT {
15 type Source = KSatisfiability<K3>;
16 type Target = OneInThreeSatisfiability;
17
18 fn target_problem(&self) -> &Self::Target {
19 &self.target
20 }
21
22 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
23 target_solution[..self.source_num_vars].to_vec()
24 }
25}
26
27#[reduction(overhead = {
28 num_vars = "num_vars + 2 + 6 * num_clauses",
29 num_clauses = "1 + 5 * num_clauses",
30})]
31impl ReduceTo<OneInThreeSatisfiability> for KSatisfiability<K3> {
32 type Result = Reduction3SATToOneInThreeSAT;
33
34 fn reduce_to(&self) -> Self::Result {
35 let source_num_vars = self.num_vars();
36 let z_false = source_num_vars as i32 + 1;
37 let z_true = source_num_vars as i32 + 2;
38 let mut next_var = source_num_vars as i32 + 3;
39
40 let mut clauses = Vec::with_capacity(1 + 5 * self.num_clauses());
41 clauses.push(CNFClause::new(vec![z_false, z_false, z_true]));
42
43 for clause in self.clauses() {
44 let [l1, l2, l3] = clause.literals.as_slice() else {
45 unreachable!("K3 clauses must have exactly three literals");
46 };
47 let a = next_var;
48 let b = next_var + 1;
49 let c = next_var + 2;
50 let d = next_var + 3;
51 let e = next_var + 4;
52 let f = next_var + 5;
53 next_var += 6;
54
55 clauses.push(CNFClause::new(vec![*l1, a, d]));
56 clauses.push(CNFClause::new(vec![*l2, b, d]));
57 clauses.push(CNFClause::new(vec![a, b, e]));
58 clauses.push(CNFClause::new(vec![c, d, f]));
59 clauses.push(CNFClause::new(vec![*l3, c, z_false]));
60 }
61
62 let target = OneInThreeSatisfiability::new((next_var - 1) as usize, clauses);
63
64 Reduction3SATToOneInThreeSAT {
65 source_num_vars,
66 target,
67 }
68 }
69}
70
71#[cfg(feature = "example-db")]
72pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
73 use crate::export::SolutionPair;
74
75 vec![crate::example_db::specs::RuleExampleSpec {
76 id: "ksatisfiability_to_oneinthreesatisfiability",
77 build: || {
78 let source = KSatisfiability::<K3>::new(3, vec![CNFClause::new(vec![1, 2, 3])]);
79 crate::example_db::specs::rule_example_with_witness::<_, OneInThreeSatisfiability>(
80 source,
81 SolutionPair {
82 source_config: vec![0, 0, 1],
83 target_config: vec![0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0],
84 },
85 )
86 },
87 }]
88}
89
90#[cfg(test)]
91#[path = "../unit_tests/rules/ksatisfiability_oneinthreesatisfiability.rs"]
92mod tests;