problemreductions/rules/
satisfiability_naesatisfiability.rs1use crate::models::formula::{CNFClause, NAESatisfiability, Satisfiability};
11use crate::reduction;
12use crate::rules::traits::{ReduceTo, ReductionResult};
13
14#[derive(Debug, Clone)]
16pub struct ReductionSATToNAESAT {
17 source_num_vars: usize,
19 target: NAESatisfiability,
21}
22
23impl ReductionResult for ReductionSATToNAESAT {
24 type Source = Satisfiability;
25 type Target = NAESatisfiability;
26
27 fn target_problem(&self) -> &Self::Target {
28 &self.target
29 }
30
31 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
32 let n = self.source_num_vars;
33 if target_solution.len() <= n {
34 return vec![0; n];
35 }
36 let sentinel_value = target_solution[n];
38 if sentinel_value == 0 {
39 target_solution[..n].to_vec()
41 } else {
42 target_solution[..n].iter().map(|&v| 1 - v).collect()
44 }
45 }
46}
47
48#[reduction(overhead = {
49 num_vars = "num_vars + 1",
50 num_clauses = "num_clauses",
51 num_literals = "num_literals + num_clauses",
52})]
53impl ReduceTo<NAESatisfiability> for Satisfiability {
54 type Result = ReductionSATToNAESAT;
55
56 fn reduce_to(&self) -> Self::Result {
57 let n = self.num_vars();
58 let sentinel_lit = (n + 1) as i32;
60
61 let nae_clauses: Vec<CNFClause> = self
62 .clauses()
63 .iter()
64 .map(|clause| {
65 if clause.literals.is_empty() {
66 CNFClause::new(vec![sentinel_lit, sentinel_lit])
69 } else {
70 let mut lits = clause.literals.clone();
71 lits.push(sentinel_lit);
72 CNFClause::new(lits)
73 }
74 })
75 .collect();
76
77 let target = NAESatisfiability::new(n + 1, nae_clauses);
78
79 ReductionSATToNAESAT {
80 source_num_vars: n,
81 target,
82 }
83 }
84}
85
86#[cfg(feature = "example-db")]
87pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
88 use crate::export::SolutionPair;
89
90 vec![crate::example_db::specs::RuleExampleSpec {
91 id: "satisfiability_to_naesatisfiability",
92 build: || {
93 let source = Satisfiability::new(
94 3,
95 vec![
96 CNFClause::new(vec![1, 2]),
97 CNFClause::new(vec![-1, 3]),
98 CNFClause::new(vec![-2, -3]),
99 ],
100 );
101 crate::example_db::specs::rule_example_with_witness::<_, NAESatisfiability>(
102 source,
103 SolutionPair {
104 source_config: vec![0, 1, 0],
105 target_config: vec![0, 1, 0, 0],
106 },
107 )
108 },
109 }]
110}
111
112#[cfg(test)]
113#[path = "../unit_tests/rules/satisfiability_naesatisfiability.rs"]
114mod tests;