problemreductions/models/specialized/
factoring.rs1use crate::graph_types::SimpleGraph;
7use crate::traits::Problem;
8use crate::types::{EnergyMode, ProblemSize, SolutionSize};
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct Factoring {
36 m: usize,
38 n: usize,
40 target: u64,
42}
43
44impl Factoring {
45 pub fn new(m: usize, n: usize, target: u64) -> Self {
52 Self { m, n, target }
53 }
54
55 pub fn m(&self) -> usize {
57 self.m
58 }
59
60 pub fn n(&self) -> usize {
62 self.n
63 }
64
65 pub fn target(&self) -> u64 {
67 self.target
68 }
69
70 pub fn read_factors(&self, config: &[usize]) -> (u64, u64) {
75 let a = bits_to_int(&config[..self.m]);
76 let b = bits_to_int(&config[self.m..self.m + self.n]);
77 (a, b)
78 }
79
80 pub fn is_valid_factorization(&self, config: &[usize]) -> bool {
82 let (a, b) = self.read_factors(config);
83 a * b == self.target
84 }
85}
86
87fn bits_to_int(bits: &[usize]) -> u64 {
89 bits.iter().enumerate().map(|(i, &b)| (b as u64) << i).sum()
90}
91
92#[allow(dead_code)]
94fn int_to_bits(n: u64, num_bits: usize) -> Vec<usize> {
95 (0..num_bits).map(|i| ((n >> i) & 1) as usize).collect()
96}
97
98impl Problem for Factoring {
99 const NAME: &'static str = "Factoring";
100 type GraphType = SimpleGraph;
101 type Weight = i32;
102 type Size = i32;
103
104 fn num_variables(&self) -> usize {
105 self.m + self.n
106 }
107
108 fn num_flavors(&self) -> usize {
109 2 }
111
112 fn problem_size(&self) -> ProblemSize {
113 ProblemSize::new(vec![
114 ("num_bits_first", self.m),
115 ("num_bits_second", self.n),
116 ("target", self.target as usize),
117 ])
118 }
119
120 fn energy_mode(&self) -> EnergyMode {
121 EnergyMode::SmallerSizeIsBetter }
123
124 fn solution_size(&self, config: &[usize]) -> SolutionSize<Self::Size> {
125 let (a, b) = self.read_factors(config);
126 let product = a * b;
127
128 let distance = if product > self.target {
130 (product - self.target) as i32
131 } else {
132 (self.target - product) as i32
133 };
134
135 let is_valid = product == self.target;
136 SolutionSize::new(distance, is_valid)
137 }
138}
139
140pub fn is_factoring(target: u64, a: u64, b: u64) -> bool {
142 a * b == target
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use crate::solvers::{BruteForce, Solver};
149
150 #[test]
151 fn test_factoring_creation() {
152 let problem = Factoring::new(3, 3, 15);
153 assert_eq!(problem.m(), 3);
154 assert_eq!(problem.n(), 3);
155 assert_eq!(problem.target(), 15);
156 assert_eq!(problem.num_variables(), 6);
157 assert_eq!(problem.num_flavors(), 2);
158 }
159
160 #[test]
161 fn test_bits_to_int() {
162 assert_eq!(bits_to_int(&[0, 0, 0]), 0);
163 assert_eq!(bits_to_int(&[1, 0, 0]), 1);
164 assert_eq!(bits_to_int(&[0, 1, 0]), 2);
165 assert_eq!(bits_to_int(&[1, 1, 0]), 3);
166 assert_eq!(bits_to_int(&[0, 0, 1]), 4);
167 assert_eq!(bits_to_int(&[1, 1, 1]), 7);
168 }
169
170 #[test]
171 fn test_int_to_bits() {
172 assert_eq!(int_to_bits(0, 3), vec![0, 0, 0]);
173 assert_eq!(int_to_bits(1, 3), vec![1, 0, 0]);
174 assert_eq!(int_to_bits(2, 3), vec![0, 1, 0]);
175 assert_eq!(int_to_bits(3, 3), vec![1, 1, 0]);
176 assert_eq!(int_to_bits(7, 3), vec![1, 1, 1]);
177 }
178
179 #[test]
180 fn test_read_factors() {
181 let problem = Factoring::new(2, 2, 6);
182 let (a, b) = problem.read_factors(&[0, 1, 1, 1]);
185 assert_eq!(a, 2);
186 assert_eq!(b, 3);
187 }
188
189 #[test]
190 fn test_solution_size_valid() {
191 let problem = Factoring::new(2, 2, 6);
192 let sol = problem.solution_size(&[0, 1, 1, 1]);
194 assert!(sol.is_valid);
195 assert_eq!(sol.size, 0); let sol = problem.solution_size(&[1, 1, 0, 1]);
199 assert!(sol.is_valid);
200 assert_eq!(sol.size, 0);
201 }
202
203 #[test]
204 fn test_solution_size_invalid() {
205 let problem = Factoring::new(2, 2, 6);
206 let sol = problem.solution_size(&[0, 1, 0, 1]);
208 assert!(!sol.is_valid);
209 assert_eq!(sol.size, 2); let sol = problem.solution_size(&[1, 0, 1, 0]);
213 assert!(!sol.is_valid);
214 assert_eq!(sol.size, 5); }
216
217 #[test]
218 fn test_brute_force_factor_6() {
219 let problem = Factoring::new(2, 2, 6);
220 let solver = BruteForce::new();
221
222 let solutions = solver.find_best(&problem);
223 assert!(!solutions.is_empty());
225 for sol in &solutions {
226 let (a, b) = problem.read_factors(sol);
227 assert_eq!(a * b, 6);
228 }
229 }
230
231 #[test]
232 fn test_brute_force_factor_15() {
233 let problem = Factoring::new(3, 3, 15);
234 let solver = BruteForce::new();
235
236 let solutions = solver.find_best(&problem);
237 for sol in &solutions {
239 let (a, b) = problem.read_factors(sol);
240 assert_eq!(a * b, 15);
241 }
242 }
243
244 #[test]
245 fn test_brute_force_prime() {
246 let problem = Factoring::new(3, 3, 7);
248 let solver = BruteForce::new();
249
250 let solutions = solver.find_best(&problem);
251 let factor_pairs: Vec<_> = solutions.iter().map(|s| problem.read_factors(s)).collect();
252
253 assert!(factor_pairs.contains(&(1, 7)) || factor_pairs.contains(&(7, 1)));
255 }
256
257 #[test]
258 fn test_is_factoring_function() {
259 assert!(is_factoring(6, 2, 3));
260 assert!(is_factoring(6, 3, 2));
261 assert!(is_factoring(15, 3, 5));
262 assert!(!is_factoring(6, 2, 2));
263 }
264
265 #[test]
266 fn test_energy_mode() {
267 let problem = Factoring::new(2, 2, 6);
268 assert!(problem.energy_mode().is_minimization());
269 }
270
271 #[test]
272 fn test_problem_size() {
273 let problem = Factoring::new(3, 4, 12);
274 let size = problem.problem_size();
275 assert_eq!(size.get("num_bits_first"), Some(3));
276 assert_eq!(size.get("num_bits_second"), Some(4));
277 assert_eq!(size.get("target"), Some(12));
278 }
279
280 #[test]
281 fn test_is_valid_factorization() {
282 let problem = Factoring::new(2, 2, 6);
283 assert!(problem.is_valid_factorization(&[0, 1, 1, 1])); assert!(!problem.is_valid_factorization(&[0, 1, 0, 1])); }
286
287 #[test]
288 fn test_factor_one() {
289 let problem = Factoring::new(2, 2, 1);
291 let solver = BruteForce::new();
292
293 let solutions = solver.find_best(&problem);
294 for sol in &solutions {
295 let (a, b) = problem.read_factors(sol);
296 assert_eq!(a * b, 1);
297 }
298 }
299}