problemreductions/rules/
naesatisfiability_maxcut.rs1use crate::models::formula::NAESatisfiability;
14use crate::models::graph::MaxCut;
15use crate::reduction;
16use crate::rules::traits::{ReduceTo, ReductionResult};
17use crate::topology::SimpleGraph;
18
19#[derive(Debug, Clone)]
21pub struct ReductionNAESATToMaxCut {
22 target: MaxCut<SimpleGraph, i32>,
23 source_num_vars: usize,
24}
25
26impl ReductionResult for ReductionNAESATToMaxCut {
27 type Source = NAESatisfiability;
28 type Target = MaxCut<SimpleGraph, i32>;
29
30 fn target_problem(&self) -> &Self::Target {
31 &self.target
32 }
33
34 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
40 (0..self.source_num_vars)
41 .map(|i| target_solution[2 * i])
42 .collect()
43 }
44}
45
46fn literal_vertex(lit: i32) -> usize {
51 let var_idx = lit.unsigned_abs() as usize - 1;
52 if lit > 0 {
53 2 * var_idx
54 } else {
55 2 * var_idx + 1
56 }
57}
58
59#[reduction(
60 overhead = {
61 num_vertices = "2 * num_vars",
62 num_edges = "num_vars + num_literal_pairs",
63 }
64)]
65impl ReduceTo<MaxCut<SimpleGraph, i32>> for NAESatisfiability {
66 type Result = ReductionNAESATToMaxCut;
67
68 fn reduce_to(&self) -> Self::Result {
69 let n = self.num_vars();
70 let m = self.num_clauses();
71 let total_vertices = 2 * n;
72 let big_m = (m + 1) as i32;
73
74 let mut edges: Vec<(usize, usize)> = Vec::new();
75 let mut weights: Vec<i32> = Vec::new();
76
77 for i in 0..n {
79 edges.push((2 * i, 2 * i + 1));
80 weights.push(big_m);
81 }
82
83 for clause in self.clauses() {
86 let lits = &clause.literals;
87 for a in 0..lits.len() {
88 for b in (a + 1)..lits.len() {
89 edges.push((literal_vertex(lits[a]), literal_vertex(lits[b])));
90 weights.push(1);
91 }
92 }
93 }
94
95 let graph = SimpleGraph::new(total_vertices, edges);
96 let target = MaxCut::new(graph, weights);
97
98 ReductionNAESATToMaxCut {
99 target,
100 source_num_vars: n,
101 }
102 }
103}
104
105#[cfg(feature = "example-db")]
106pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
107 use crate::export::SolutionPair;
108 use crate::models::formula::CNFClause;
109
110 vec![crate::example_db::specs::RuleExampleSpec {
111 id: "naesatisfiability_to_maxcut",
112 build: || {
113 let source = NAESatisfiability::new(
118 3,
119 vec![
120 CNFClause::new(vec![1, 2, -3]),
121 CNFClause::new(vec![-1, 3, 2]),
122 ],
123 );
124 crate::example_db::specs::rule_example_with_witness::<_, MaxCut<SimpleGraph, i32>>(
125 source,
126 SolutionPair {
127 source_config: vec![1, 0, 1],
129 target_config: vec![1, 0, 0, 1, 1, 0],
135 },
136 )
137 },
138 }]
139}
140
141#[cfg(test)]
142#[path = "../unit_tests/rules/naesatisfiability_maxcut.rs"]
143mod tests;