quantrs2_tytan/optimize/
mod.rs1use scirs2_core::ndarray::{Array, ArrayD, Ix2};
7use scirs2_core::random::prelude::*;
8use std::collections::HashMap;
9
10use crate::sampler::SampleResult;
11
12#[cfg(feature = "scirs")]
13use crate::scirs_stub;
14
15#[cfg(feature = "advanced_optimization")]
20pub fn optimize_qubo(
21 matrix: &Array<f64, Ix2>,
22 var_map: &HashMap<String, usize>,
23 initial_guess: Option<Vec<bool>>,
24 max_iterations: usize,
25) -> Vec<SampleResult> {
26 let enhanced_matrix = scirs_stub::enhance_qubo_matrix(matrix);
28 let samples = scirs_stub::parallel_sample_qubo(&enhanced_matrix, max_iterations);
29
30 let idx_to_var: HashMap<usize, String> = var_map
32 .iter()
33 .map(|(var, &idx)| (idx, var.clone()))
34 .collect();
35
36 let mut results: Vec<SampleResult> = samples
38 .into_iter()
39 .map(|(solution, energy)| {
40 let assignments: HashMap<String, bool> = solution
41 .iter()
42 .enumerate()
43 .filter_map(|(idx, &value)| {
44 idx_to_var
45 .get(&idx)
46 .map(|var_name| (var_name.clone(), value))
47 })
48 .collect();
49
50 SampleResult {
51 assignments,
52 energy,
53 occurrences: 1,
54 }
55 })
56 .collect();
57
58 results.sort_by(|a, b| {
60 a.energy
61 .partial_cmp(&b.energy)
62 .unwrap_or(std::cmp::Ordering::Equal)
63 });
64 results.truncate(10); results
67}
68
69#[cfg(not(feature = "advanced_optimization"))]
71pub fn optimize_qubo(
72 matrix: &Array<f64, Ix2>,
73 var_map: &HashMap<String, usize>,
74 initial_guess: Option<Vec<bool>>,
75 max_iterations: usize,
76) -> Vec<SampleResult> {
77 let n_vars = var_map.len();
79
80 let idx_to_var: HashMap<usize, String> = var_map
82 .iter()
83 .map(|(var, &idx)| (idx, var.clone()))
84 .collect();
85
86 let mut solution: Vec<bool> = if let Some(guess) = initial_guess {
88 guess
89 } else {
90 use scirs2_core::random::prelude::*;
91 let mut rng = thread_rng();
92 (0..n_vars).map(|_| rng.gen_bool(0.5)).collect()
93 };
94
95 let mut energy = calculate_energy(&solution, matrix);
97
98 let mut temperature = 10.0;
100 let cooling_rate = 0.99;
101
102 let mut rng = thread_rng();
104
105 for _ in 0..max_iterations {
106 let flip_idx = rng.gen_range(0..n_vars);
108 solution[flip_idx] = !solution[flip_idx];
109
110 let new_energy = calculate_energy(&solution, matrix);
112
113 let accept = if new_energy < energy {
115 true
116 } else {
117 let p = ((energy - new_energy) / temperature).exp();
118 rng.gen::<f64>() < p
119 };
120
121 if accept {
122 energy = new_energy;
123 } else {
124 solution[flip_idx] = !solution[flip_idx];
126 }
127
128 temperature *= cooling_rate;
130 }
131
132 let assignments: HashMap<String, bool> = solution
134 .iter()
135 .enumerate()
136 .filter_map(|(idx, &value)| {
137 idx_to_var
138 .get(&idx)
139 .map(|var_name| (var_name.clone(), value))
140 })
141 .collect();
142
143 let sample_result = SampleResult {
145 assignments,
146 energy,
147 occurrences: 1,
148 };
149
150 vec![sample_result]
151}
152
153pub fn calculate_energy(solution: &[bool], matrix: &Array<f64, Ix2>) -> f64 {
155 calculate_energy_standard(solution, matrix)
156}
157
158fn calculate_energy_standard(solution: &[bool], matrix: &Array<f64, Ix2>) -> f64 {
160 let n = solution.len();
161 let mut energy = 0.0;
162
163 for i in 0..n {
165 if solution[i] {
166 energy += matrix[[i, i]];
167 }
168 }
169
170 for i in 0..n {
172 if solution[i] {
173 for j in (i + 1)..n {
174 if solution[j] {
175 energy += matrix[[i, j]];
176 }
177 }
178 }
179 }
180
181 energy
182}
183
184#[cfg(feature = "scirs")]
186pub fn optimize_hobo(
187 tensor: &ArrayD<f64>,
188 var_map: &HashMap<String, usize>,
189 initial_guess: Option<Vec<bool>>,
190 max_iterations: usize,
191) -> Vec<SampleResult> {
192 let _enhanced = scirs_stub::optimize_hobo_tensor(tensor);
194
195 optimize_hobo_basic(tensor, var_map, initial_guess, max_iterations)
198}
199
200#[cfg(not(feature = "scirs"))]
202pub fn optimize_hobo(
203 tensor: &ArrayD<f64>,
204 var_map: &HashMap<String, usize>,
205 initial_guess: Option<Vec<bool>>,
206 max_iterations: usize,
207) -> Vec<SampleResult> {
208 optimize_hobo_basic(tensor, var_map, initial_guess, max_iterations)
209}
210
211fn optimize_hobo_basic(
213 _tensor: &ArrayD<f64>,
214 var_map: &HashMap<String, usize>,
215 _initial_guess: Option<Vec<bool>>,
216 _max_iterations: usize,
217) -> Vec<SampleResult> {
218 let assignments: HashMap<String, bool> =
223 var_map.keys().map(|name| (name.clone(), false)).collect();
224
225 vec![SampleResult {
226 assignments,
227 energy: 0.0,
228 occurrences: 1,
229 }]
230}