problemreductions/rules/
spinglass_qubo.rs1use crate::models::algebraic::QUBO;
9use crate::models::graph::SpinGlass;
10use crate::reduction;
11use crate::rules::traits::{ReduceTo, ReductionResult};
12use crate::topology::SimpleGraph;
13
14#[derive(Debug, Clone)]
16pub struct ReductionQUBOToSG {
17 target: SpinGlass<SimpleGraph, f64>,
18}
19
20impl ReductionResult for ReductionQUBOToSG {
21 type Source = QUBO<f64>;
22 type Target = SpinGlass<SimpleGraph, f64>;
23
24 fn target_problem(&self) -> &Self::Target {
25 &self.target
26 }
27
28 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
30 target_solution.to_vec()
31 }
32}
33
34#[reduction(
35 overhead = {
36 num_spins = "num_vars",
37 }
38)]
39impl ReduceTo<SpinGlass<SimpleGraph, f64>> for QUBO<f64> {
40 type Result = ReductionQUBOToSG;
41
42 fn reduce_to(&self) -> Self::Result {
43 let n = self.num_vars();
44 let matrix = self.matrix();
45
46 let mut interactions = Vec::new();
58 let mut onsite = vec![0.0; n];
59
60 for i in 0..n {
61 for j in i..n {
62 let q = matrix[i][j];
63 if q.abs() < 1e-10 {
64 continue;
65 }
66
67 if i == j {
68 onsite[i] += q / 2.0;
70 } else {
71 let j_ij = q / 4.0;
74 if j_ij.abs() > 1e-10 {
75 interactions.push(((i, j), j_ij));
76 }
77 onsite[i] += q / 4.0;
79 onsite[j] += q / 4.0;
80 }
81 }
82 }
83
84 let target = SpinGlass::<SimpleGraph, f64>::new(n, interactions, onsite);
85
86 ReductionQUBOToSG { target }
87 }
88}
89
90#[derive(Debug, Clone)]
92pub struct ReductionSGToQUBO {
93 target: QUBO<f64>,
94}
95
96impl ReductionResult for ReductionSGToQUBO {
97 type Source = SpinGlass<SimpleGraph, f64>;
98 type Target = QUBO<f64>;
99
100 fn target_problem(&self) -> &Self::Target {
101 &self.target
102 }
103
104 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
105 target_solution.to_vec()
106 }
107}
108
109#[reduction(
110 overhead = {
111 num_vars = "num_spins",
112 }
113)]
114impl ReduceTo<QUBO<f64>> for SpinGlass<SimpleGraph, f64> {
115 type Result = ReductionSGToQUBO;
116
117 fn reduce_to(&self) -> Self::Result {
118 let n = self.num_spins();
119 let mut matrix = vec![vec![0.0; n]; n];
120
121 for ((i, j), j_val) in self.interactions() {
130 matrix[i][j] += 4.0 * j_val;
132 matrix[i][i] -= 2.0 * j_val;
134 matrix[j][j] -= 2.0 * j_val;
135 }
136
137 for (i, &h) in self.fields().iter().enumerate() {
139 matrix[i][i] += 2.0 * h;
141 }
142
143 let target = QUBO::from_matrix(matrix);
144
145 ReductionSGToQUBO { target }
146 }
147}
148
149#[cfg(test)]
150#[path = "../unit_tests/rules/spinglass_qubo.rs"]
151mod tests;