problemreductions/rules/
ksatisfiability_kclique.rs1use crate::models::formula::KSatisfiability;
16use crate::models::graph::KClique;
17use crate::reduction;
18use crate::rules::traits::{ReduceTo, ReductionResult};
19use crate::topology::SimpleGraph;
20use crate::variant::K3;
21
22#[derive(Debug, Clone)]
24pub struct Reduction3SATToKClique {
25 target: KClique<SimpleGraph>,
26 source_clauses: Vec<Vec<i32>>,
28 source_num_vars: usize,
29}
30
31impl ReductionResult for Reduction3SATToKClique {
32 type Source = KSatisfiability<K3>;
33 type Target = KClique<SimpleGraph>;
34
35 fn target_problem(&self) -> &Self::Target {
36 &self.target
37 }
38
39 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
40 let n = self.source_num_vars;
41 let mut assignment = vec![0usize; n];
43 let mut set = vec![false; n];
45
46 for (v, &val) in target_solution.iter().enumerate() {
47 if val != 1 {
48 continue;
49 }
50 let j = v / 3;
52 let p = v % 3;
53 let lit = self.source_clauses[j][p];
54 let var_idx = (lit.unsigned_abs() as usize) - 1; if !set[var_idx] {
56 assignment[var_idx] = if lit > 0 { 1 } else { 0 };
57 set[var_idx] = true;
58 }
59 }
60 assignment
61 }
62}
63
64fn literals_contradict(lit1: i32, lit2: i32) -> bool {
66 lit1 == -lit2
67}
68
69#[reduction(
70 overhead = {
71 num_vertices = "3 * num_clauses",
72 num_edges = "9 * num_clauses * (num_clauses - 1) / 2",
73 k = "num_clauses",
74 }
75)]
76impl ReduceTo<KClique<SimpleGraph>> for KSatisfiability<K3> {
77 type Result = Reduction3SATToKClique;
78
79 fn reduce_to(&self) -> Self::Result {
80 let m = self.num_clauses();
81 let num_verts = 3 * m;
82
83 let clause_lits: Vec<Vec<i32>> =
85 self.clauses().iter().map(|c| c.literals.clone()).collect();
86
87 let mut edges = Vec::new();
90 for j1 in 0..m {
91 for j2 in (j1 + 1)..m {
92 for p1 in 0..3 {
93 for p2 in 0..3 {
94 let lit1 = clause_lits[j1][p1];
95 let lit2 = clause_lits[j2][p2];
96 if !literals_contradict(lit1, lit2) {
97 let v1 = 3 * j1 + p1;
98 let v2 = 3 * j2 + p2;
99 edges.push((v1, v2));
100 }
101 }
102 }
103 }
104 }
105
106 let graph = SimpleGraph::new(num_verts, edges);
107 let target = KClique::new(graph, m);
108
109 Reduction3SATToKClique {
110 target,
111 source_clauses: clause_lits,
112 source_num_vars: self.num_vars(),
113 }
114 }
115}
116
117#[cfg(feature = "example-db")]
118pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
119 use crate::export::SolutionPair;
120 use crate::models::formula::CNFClause;
121
122 vec![crate::example_db::specs::RuleExampleSpec {
123 id: "ksatisfiability_to_kclique",
124 build: || {
125 let source = KSatisfiability::<K3>::new(
127 3,
128 vec![
129 CNFClause::new(vec![1, 2, 3]),
130 CNFClause::new(vec![-1, -2, 3]),
131 ],
132 );
133 crate::example_db::specs::rule_example_with_witness::<_, KClique<SimpleGraph>>(
138 source,
139 SolutionPair {
140 source_config: vec![0, 0, 1],
141 target_config: vec![0, 0, 1, 1, 0, 0],
142 },
143 )
144 },
145 }]
146}
147
148#[cfg(test)]
149#[path = "../unit_tests/rules/ksatisfiability_kclique.rs"]
150mod tests;