1use crate::error::{CoreError, CoreResult};
11use std::f64::consts::PI;
12use std::time::{Duration, Instant};
13
14#[cfg(feature = "parallel")]
15use crate::parallel_ops::*;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum QuantumStrategy {
20 QuantumAnnealing,
22 QuantumEvolutionary,
24 QuantumParticleSwarm,
26 QuantumDifferentialEvolution,
28 AdiabaticQuantum,
30 QAOA,
32}
33
34#[derive(Debug, Clone)]
36pub struct QuantumState {
37 pub amplitudes: Vec<f64>,
39 pub phases: Vec<f64>,
41 pub entanglementmatrix: Vec<Vec<f64>>,
43 pub measurement_probs: Vec<f64>,
45}
46
47impl QuantumState {
48 pub fn dimensions(dimensions: usize) -> Self {
50 let amplitude = 1.0 / (dimensions as f64).sqrt();
51 Self {
52 amplitudes: vec![amplitude; dimensions],
53 phases: vec![0.0; dimensions],
54 entanglementmatrix: vec![vec![0.0; dimensions]; dimensions],
55 measurement_probs: vec![1.0 / dimensions as f64; dimensions],
56 }
57 }
58
59 pub fn new_uniform(nqubits: usize) -> Self {
60 let size = 1 << nqubits;
61 let amplitude = 1.0 / (size as f64).sqrt();
62 let amplitudes = vec![amplitude; size];
63
64 Self {
65 amplitudes,
66 phases: vec![0.0; size],
67 entanglementmatrix: vec![vec![0.0; size]; size],
68 measurement_probs: vec![1.0 / size as f64; size],
69 }
70 }
71
72 pub fn from_amplitudes(amplitudes: Vec<f64>) -> CoreResult<Self> {
74 let norm_squared: f64 = amplitudes.iter().map(|a| a * a).sum();
75 if (norm_squared - 1.0).abs() > 1e-10 {
76 return Err(CoreError::ValidationError(crate::error::ErrorContext::new(
77 "Quantum state amplitudes must be normalized".to_string(),
78 )));
79 }
80
81 let dimensions = amplitudes.len();
82 Ok(Self {
83 amplitudes,
84 phases: vec![0.0; dimensions],
85 entanglementmatrix: vec![vec![0.0; dimensions]; dimensions],
86 measurement_probs: vec![1.0 / dimensions as f64; dimensions],
87 })
88 }
89}
90
91impl QuantumState {
92 pub fn apply_rotation(&mut self, angle: f64, axis: usize) {
94 if axis < self.amplitudes.len() {
95 let cos_half = (angle / 2.0).cos();
96 let sin_half = (angle / 2.0).sin();
97
98 let old_amp = self.amplitudes[axis];
99 let old_phase = self.phases[axis];
100
101 self.amplitudes[axis] = cos_half * old_amp;
102 self.phases[axis] = old_phase + sin_half;
103 }
104 }
105
106 pub fn apply_hadamard(&mut self, qubit: usize) {
108 if qubit < self.amplitudes.len() {
109 let sqrt_2_inv = 1.0 / 2.0_f64.sqrt();
110 self.amplitudes[qubit] *= sqrt_2_inv;
111
112 if qubit + 1 < self.amplitudes.len() {
114 self.amplitudes[qubit + 1] = self.amplitudes[qubit];
115 self.phases[qubit + 1] = self.phases[qubit] + PI;
116 }
117 }
118 }
119
120 pub fn measure(&mut self) -> usize {
122 let total_prob: f64 = self.amplitudes.iter().map(|a| a * a).sum();
124
125 for i in 0..self.measurement_probs.len() {
126 self.measurement_probs[i] = (self.amplitudes[i] * self.amplitudes[i]) / total_prob;
127 }
128
129 let rand_val: f64 = self.pseudo_random();
131 let mut cumulative_prob = 0.0;
132
133 for (i, &prob) in self.measurement_probs.iter().enumerate() {
134 cumulative_prob += prob;
135 if rand_val <= cumulative_prob {
136 self.amplitudes.fill(0.0);
138 self.amplitudes[i] = 1.0;
139 self.phases.fill(0.0);
140 return i;
141 }
142 }
143
144 self.amplitudes.len() - 1
146 }
147
148 fn pseudo_random(&self) -> f64 {
150 use std::collections::hash_map::DefaultHasher;
151 use std::hash::{Hash, Hasher};
152
153 let mut hasher = DefaultHasher::new();
154 for amp in &self.amplitudes {
155 amp.to_bits().hash(&mut hasher);
156 }
157
158 let hash_val = hasher.finish();
159 (hash_val % 10000) as f64 / 10000.0
160 }
161
162 pub fn entangle(&mut self, qubit1: usize, qubit2: usize, strength: f64) {
164 if qubit1 < self.entanglementmatrix.len() && qubit2 < self.entanglementmatrix[0].len() {
165 self.entanglementmatrix[qubit1][qubit2] = strength;
166 self.entanglementmatrix[qubit2][qubit1] = strength;
167 }
168 }
169
170 pub fn entropy(&self) -> f64 {
172 let total_prob: f64 = self.amplitudes.iter().map(|a| a * a).sum();
173 let mut entropy = 0.0;
174
175 for amp in &self.amplitudes {
176 let prob = (amp * amp) / total_prob;
177 if prob > 0.0 {
178 entropy -= prob * prob.ln();
179 }
180 }
181
182 entropy
183 }
184}
185
186pub struct QuantumOptimizer {
188 pub state: QuantumState,
190 strategy: QuantumStrategy,
192 pub dimensions: usize,
194 population_size: usize,
196 generation: usize,
198 best_solution: Vec<f64>,
200 best_fitness: f64,
202 convergence_history: Vec<f64>,
204 quantum_params: QuantumParameters,
206}
207
208#[derive(Debug, Clone)]
210pub struct QuantumParameters {
211 pub temperature: f64,
213 pub cooling_rate: f64,
215 pub min_temperature: f64,
217 pub tunneling_rate: f64,
219 pub coherence_time: Duration,
221 pub measurement_interval: usize,
223}
224
225impl Default for QuantumParameters {
226 fn default() -> Self {
227 Self {
228 temperature: 100.0,
229 cooling_rate: 0.95,
230 min_temperature: 0.01,
231 tunneling_rate: 0.1,
232 coherence_time: Duration::from_millis(100),
233 measurement_interval: 10,
234 }
235 }
236}
237
238impl QuantumOptimizer {
239 pub fn new(
241 dimensions: usize,
242 strategy: QuantumStrategy,
243 population_size: Option<usize>,
244 ) -> CoreResult<Self> {
245 if dimensions == 0 {
246 return Err(CoreError::ValidationError(crate::error::ErrorContext::new(
247 "Optimization dimensions must be > 0".to_string(),
248 )));
249 }
250
251 let pop_size = population_size.unwrap_or(50.max(dimensions * 2));
252 let state = QuantumState::new_uniform(dimensions);
253
254 Ok(Self {
255 state,
256 strategy,
257 dimensions,
258 population_size: pop_size,
259 generation: 0,
260 best_solution: vec![0.0; dimensions],
261 best_fitness: f64::INFINITY,
262 convergence_history: Vec::new(),
263 quantum_params: QuantumParameters::default(),
264 })
265 }
266
267 pub fn optimize<F>(
269 &mut self,
270 objective_fn: F,
271 bounds: &[(f64, f64)],
272 max_iterations: usize,
273 ) -> CoreResult<OptimizationResult>
274 where
275 F: Fn(&[f64]) -> f64 + Send + Sync,
276 {
277 if bounds.len() != self.dimensions {
278 return Err(CoreError::ValidationError(crate::error::ErrorContext::new(
279 "Bounds length must match optimization dimensions".to_string(),
280 )));
281 }
282
283 let start_time = Instant::now();
284
285 match self.strategy {
286 QuantumStrategy::QuantumAnnealing => {
287 self.quantum_annealing(&objective_fn, bounds, max_iterations)?
288 }
289 QuantumStrategy::QuantumEvolutionary => {
290 self.quantum_evolutionary(&objective_fn, bounds, max_iterations)?
291 }
292 QuantumStrategy::QuantumParticleSwarm => {
293 self.quantum_particle_swarm(&objective_fn, bounds, max_iterations)?
294 }
295 QuantumStrategy::QuantumDifferentialEvolution => {
296 self.quantum_differential_evolution(&objective_fn, bounds, max_iterations)?
297 }
298 QuantumStrategy::AdiabaticQuantum => {
299 self.adiabatic_quantum(&objective_fn, bounds, max_iterations)?
300 }
301 QuantumStrategy::QAOA => {
302 self.qaoa_optimization(&objective_fn, bounds, max_iterations)?
303 }
304 }
305
306 Ok(OptimizationResult {
307 best_solution: self.best_solution.clone(),
308 best_fitness: self.best_fitness,
309 iterations_performed: self.generation,
310 convergence_history: self.convergence_history.clone(),
311 execution_time: start_time.elapsed(),
312 strategy_used: self.strategy,
313 quantum_state_entropy: self.state.entropy(),
314 })
315 }
316
317 fn quantum_annealing<F>(
319 &mut self,
320 objective_fn: &F,
321 bounds: &[(f64, f64)],
322 max_iterations: usize,
323 ) -> CoreResult<()>
324 where
325 F: Fn(&[f64]) -> f64 + Send + Sync,
326 {
327 let mut current_solution = self.initialize_solution(bounds);
328 let mut currentfitness = objective_fn(¤t_solution);
329
330 if currentfitness < self.best_fitness {
331 self.best_fitness = currentfitness;
332 self.best_solution = current_solution.clone();
333 }
334
335 for iteration in 0..max_iterations {
336 self.generation = iteration;
337
338 self.update_quantum_state_from_solution(¤t_solution, bounds);
340
341 if self.should_tunnel() {
343 current_solution = self.quantum_tunnel(¤t_solution, bounds);
344 } else {
345 current_solution = self.anneal_move(¤t_solution, bounds);
347 }
348
349 let new_fitness = objective_fn(¤t_solution);
350
351 if self.accept_solution(currentfitness, new_fitness, iteration, max_iterations) {
353 currentfitness = new_fitness;
354
355 if new_fitness < self.best_fitness {
356 self.best_fitness = new_fitness;
357 self.best_solution = current_solution.clone();
358 }
359 }
360
361 self.convergence_history.push(self.best_fitness);
362
363 self.quantum_params.temperature *= self.quantum_params.cooling_rate;
365 self.quantum_params.temperature = self
366 .quantum_params
367 .temperature
368 .max(self.quantum_params.min_temperature);
369
370 if iteration % self.quantum_params.measurement_interval == 0 {
372 let _ = self.state.measure();
373 }
374 }
375
376 Ok(())
377 }
378
379 fn quantum_evolutionary<F>(
381 &mut self,
382 objective_fn: &F,
383 bounds: &[(f64, f64)],
384 max_iterations: usize,
385 ) -> CoreResult<()>
386 where
387 F: Fn(&[f64]) -> f64 + Send + Sync,
388 {
389 let mut population = self.initialize_quantum_population(bounds);
391 #[allow(unused_assignments)]
392 let mut fitnessvalues = vec![0.0; self.population_size];
393
394 for iteration in 0..max_iterations {
395 self.generation = iteration;
396
397 #[cfg(feature = "parallel")]
399 {
400 fitnessvalues = population
401 .par_iter()
402 .map(|individual| objective_fn(individual))
403 .collect();
404 }
405
406 #[cfg(not(feature = "parallel"))]
407 {
408 fitnessvalues = population
409 .iter()
410 .map(|individual| objective_fn(individual))
411 .collect();
412 }
413
414 if let Some((best_idx, &best_fitness)) = fitnessvalues
416 .iter()
417 .enumerate()
418 .min_by(|a, b| a.1.partial_cmp(b.1).unwrap())
419 {
420 if best_fitness < self.best_fitness {
421 self.best_fitness = best_fitness;
422 self.best_solution = population[best_idx].clone();
423 }
424 }
425
426 self.convergence_history.push(self.best_fitness);
427
428 population = self.quantum_reproduction(&population, &fitnessvalues, bounds);
430
431 self.apply_quantum_mutations(&mut population, bounds, iteration, max_iterations);
433 }
434
435 Ok(())
436 }
437
438 fn quantum_particle_swarm<F>(
440 &mut self,
441 objective_fn: &F,
442 bounds: &[(f64, f64)],
443 max_iterations: usize,
444 ) -> CoreResult<()>
445 where
446 F: Fn(&[f64]) -> f64 + Send + Sync,
447 {
448 let mut particles = self.initialize_quantum_population(bounds);
450 let mut velocities = vec![vec![0.0; self.dimensions]; self.population_size];
451 let mut personal_best = particles.clone();
452 let mut personal_best_fitness = vec![f64::INFINITY; self.population_size];
453
454 for iteration in 0..max_iterations {
455 self.generation = iteration;
456
457 for (i, particle) in particles.iter().enumerate() {
459 let fitness = objective_fn(particle);
460
461 if fitness < personal_best_fitness[i] {
462 personal_best_fitness[i] = fitness;
463 personal_best[i] = particle.clone();
464 }
465
466 if fitness < self.best_fitness {
467 self.best_fitness = fitness;
468 self.best_solution = particle.clone();
469 }
470 }
471
472 self.convergence_history.push(self.best_fitness);
473
474 let best_solution = self.best_solution.clone();
476 for i in 0..self.population_size {
477 self.update_velocity(
478 &mut velocities[i],
479 &particles[i],
480 &personal_best[i],
481 &best_solution,
482 iteration,
483 max_iterations,
484 );
485
486 for (d, bound) in bounds.iter().enumerate().take(self.dimensions) {
488 particles[i][d] += velocities[i][d];
489
490 let quantum_effect = self.calculate_quantum_interference(i, d);
492 particles[i][d] += quantum_effect;
493
494 particles[i][d] = particles[i][d].clamp(bound.0, bound.1);
496 }
497 }
498
499 self.update_swarm_quantum_state(&particles);
501 }
502
503 Ok(())
504 }
505
506 fn quantum_differential_evolution<F>(
508 &mut self,
509 objective_fn: &F,
510 bounds: &[(f64, f64)],
511 max_iterations: usize,
512 ) -> CoreResult<()>
513 where
514 F: Fn(&[f64]) -> f64 + Send + Sync,
515 {
516 let mut population = self.initialize_quantum_population(bounds);
517 let f_factor = 0.5; let _cr_factor = 0.9; for iteration in 0..max_iterations {
521 self.generation = iteration;
522
523 let mut new_population = population.clone();
524
525 for i in 0..self.population_size {
526 let mut indices = (0..self.population_size)
528 .filter(|&x| x != i)
529 .collect::<Vec<_>>();
530 indices.sort_by(|_a, _b| {
531 if self.state.pseudo_random() > 0.5 {
532 std::cmp::Ordering::Greater
533 } else {
534 std::cmp::Ordering::Less
535 }
536 });
537
538 if indices.len() >= 3 {
539 let a = indices[0];
540 let b = indices[1];
541 let c = indices[2];
542
543 let mut mutant = vec![0.0; self.dimensions];
545 for d in 0..self.dimensions {
546 mutant[d] =
547 population[a][d] + f_factor * (population[b][d] - population[c][d]);
548
549 let quantum_fluctuation =
551 self.calculate_quantum_fluctuation(d, iteration, max_iterations);
552 mutant[d] += quantum_fluctuation;
553
554 mutant[d] = mutant[d].clamp(bounds[d].0, bounds[d].1);
555 }
556
557 let mut trial = population[0].clone();
559 let random_index = (self.state.pseudo_random() * self.dimensions as f64)
560 as usize
561 % self.dimensions;
562
563 for d in 0..self.dimensions {
564 let quantum_cr = self.calculate_quantum_crossover_probability(d, iteration);
565 if self.state.pseudo_random() < quantum_cr || d == random_index {
566 trial[d] = mutant[d];
567 }
568 }
569
570 let trial_fitness = objective_fn(&trial);
572 let currentfitness = objective_fn(&population[0]);
573
574 if trial_fitness <= currentfitness {
575 new_population[0] = trial.clone();
576
577 if trial_fitness < self.best_fitness {
578 self.best_fitness = trial_fitness;
579 self.best_solution = trial;
580 }
581 }
582 }
583 }
584
585 population = new_population;
586 self.convergence_history.push(self.best_fitness);
587 }
588
589 Ok(())
590 }
591
592 fn adiabatic_quantum<F>(
594 &mut self,
595 objective_fn: &F,
596 bounds: &[(f64, f64)],
597 max_iterations: usize,
598 ) -> CoreResult<()>
599 where
600 F: Fn(&[f64]) -> f64 + Send + Sync,
601 {
602 self.state = QuantumState::new_uniform(self.dimensions);
604
605 for i in 0..self.dimensions.min(self.state.amplitudes.len()) {
607 self.state.apply_hadamard(i);
608 }
609
610 for iteration in 0..max_iterations {
611 self.generation = iteration;
612
613 let s = iteration as f64 / max_iterations as f64;
615
616 let h_initial_weight = 1.0 - s;
618 let h_problem_weight = s;
619
620 let solution = self.extract_solution_from_quantum_state(bounds);
622 let fitness = objective_fn(&solution);
623
624 if fitness < self.best_fitness {
625 self.best_fitness = fitness;
626 self.best_solution = solution.clone();
627 }
628
629 self.evolve_adiabatic_hamiltonian(h_initial_weight, h_problem_weight, fitness, bounds);
631
632 self.convergence_history.push(self.best_fitness);
633
634 if iteration % 10 == 0 {
636 for i in 0..self.dimensions.min(self.state.amplitudes.len()) {
637 let angle = 0.1 * self.state.pseudo_random();
638 self.state.apply_rotation(angle, i);
639 }
640 }
641 }
642
643 Ok(())
644 }
645
646 fn qaoa_optimization<F>(
648 &mut self,
649 objective_fn: &F,
650 bounds: &[(f64, f64)],
651 max_iterations: usize,
652 ) -> CoreResult<()>
653 where
654 F: Fn(&[f64]) -> f64 + Send + Sync,
655 {
656 let p_layers = 3; let mut gamma_params = vec![0.5; p_layers]; let mut beta_params = vec![0.5; p_layers]; for iteration in 0..max_iterations {
661 self.generation = iteration;
662
663 self.state = QuantumState::new_uniform(self.dimensions);
665
666 for layer in 0..p_layers {
668 self.apply_problem_hamiltonian(gamma_params[layer], objective_fn, bounds);
670
671 self.apply_mixer_hamiltonian(beta_params[layer]);
673 }
674
675 let measurement = self.state.measure();
677 let solution = self.decode_measurement_to_solution(measurement, bounds);
678 let fitness = objective_fn(&solution);
679
680 if fitness < self.best_fitness {
681 self.best_fitness = fitness;
682 self.best_solution = solution;
683 }
684
685 self.convergence_history.push(self.best_fitness);
686
687 if iteration % 10 == 0 {
689 self.update_qaoa_params(&mut gamma_params, &mut beta_params, iteration);
690 }
691 }
692
693 Ok(())
694 }
695
696 fn initialize_solution(&self, bounds: &[(f64, f64)]) -> Vec<f64> {
699 (0..self.dimensions)
700 .map(|i| {
701 let range = bounds[i].1 - bounds[i].0;
702 bounds[i].0 + range * self.state.pseudo_random()
703 })
704 .collect()
705 }
706
707 fn initialize_quantum_population(&self, bounds: &[(f64, f64)]) -> Vec<Vec<f64>> {
708 (0..self.population_size)
709 .map(|_| self.initialize_solution(bounds))
710 .collect()
711 }
712
713 fn should_tunnel(&self) -> bool {
714 self.state.pseudo_random() < self.quantum_params.tunneling_rate
715 }
716
717 fn quantum_tunnel(&self, current: &[f64], bounds: &[(f64, f64)]) -> Vec<f64> {
718 let mut new_solution = current.to_vec();
719
720 for i in 0..self.dimensions {
722 if self.state.pseudo_random() < 0.3 {
723 let range = bounds[i].1 - bounds[i].0;
724 let tunnel_distance = range * 0.1 * self.state.pseudo_random();
725
726 if self.state.pseudo_random() < 0.5 {
727 new_solution[0] += tunnel_distance;
728 } else {
729 new_solution[0] -= tunnel_distance;
730 }
731
732 new_solution[i] = new_solution[i].clamp(bounds[i].0, bounds[i].1);
733 }
734 }
735
736 new_solution
737 }
738
739 fn anneal_move(&self, current: &[f64], bounds: &[(f64, f64)]) -> Vec<f64> {
740 let mut new_solution = current.to_vec();
741
742 for i in 0..self.dimensions {
743 if self.state.pseudo_random() < 0.5 {
744 let range = bounds[i].1 - bounds[i].0;
745 let step_size = range * 0.01 * self.quantum_params.temperature;
746
747 new_solution[i] += step_size * (self.state.pseudo_random() - 0.5);
748 new_solution[i] = new_solution[i].clamp(bounds[i].0, bounds[i].1);
749 }
750 }
751
752 new_solution
753 }
754
755 #[allow(dead_code)]
756 fn accept_move(&mut self, new_fitness: f64, currentfitness: f64) -> bool {
757 if new_fitness <= currentfitness {
758 return true;
759 }
760
761 let delta = new_fitness - currentfitness;
763 let quantum_factor = 1.0 + 0.1 * self.state.entropy();
764 let probability = (-delta / (self.quantum_params.temperature * quantum_factor)).exp();
765
766 self.state.pseudo_random() < probability
767 }
768
769 fn update_quantum_state_from_solution(&mut self, solution: &[f64], bounds: &[(f64, f64)]) {
770 for (i, &value) in solution.iter().enumerate() {
772 if i < self.state.amplitudes.len() {
773 let normalized = (value - bounds[i].0) / (bounds[i].1 - bounds[i].0);
774 self.state.amplitudes[i] = normalized.sqrt();
775 }
776 }
777
778 let norm: f64 = self
780 .state
781 .amplitudes
782 .iter()
783 .map(|a| a * a)
784 .sum::<f64>()
785 .sqrt();
786 if norm > 0.0 {
787 for amp in &mut self.state.amplitudes {
788 *amp /= norm;
789 }
790 }
791 }
792
793 #[allow(dead_code)]
794 fn evolve_population(
795 &mut self,
796 fitnessvalues: &[f64],
797 population: &[Vec<f64>],
798 bounds: &[(f64, f64)],
799 ) -> Vec<Vec<f64>> {
800 let mut new_population = Vec::with_capacity(self.population_size);
801
802 for _ in 0..self.population_size {
804 let parent1_idx = self.quantum_selection(fitnessvalues);
805 let parent2_idx = self.quantum_selection(fitnessvalues);
806
807 let offspring =
808 self.quantum_crossover(&population[parent1_idx], &population[parent2_idx], bounds);
809 new_population.push(offspring);
810 }
811
812 new_population
813 }
814
815 fn quantum_selection(&self, fitnessvalues: &[f64]) -> usize {
816 let max_fitness = fitnessvalues
818 .iter()
819 .cloned()
820 .fold(f64::NEG_INFINITY, f64::max);
821 let adjusted_fitness: Vec<f64> = fitnessvalues
822 .iter()
823 .map(|&f| max_fitness - f + 1.0)
824 .collect();
825
826 let total_fitness: f64 = adjusted_fitness.iter().sum();
827 let mut cumulative_prob = 0.0;
828 let rand_val = self.state.pseudo_random();
829
830 for (i, &fitness) in adjusted_fitness.iter().enumerate() {
831 cumulative_prob += fitness / total_fitness;
832 if rand_val <= cumulative_prob {
833 return i;
834 }
835 }
836
837 fitnessvalues.len() - 1
838 }
839
840 fn quantum_crossover(
841 &self,
842 parent1: &[f64],
843 parent2: &[f64],
844 bounds: &[(f64, f64)],
845 ) -> Vec<f64> {
846 let mut offspring = vec![0.0; self.dimensions];
847
848 for i in 0..self.dimensions {
849 let alpha = self.state.pseudo_random();
851 let quantum_interference = (2.0 * PI * alpha).sin() * 0.1;
852
853 offspring[i] = alpha * parent1[i] + (1.0 - alpha) * parent2[i] + quantum_interference;
854 offspring[i] = offspring[i].clamp(bounds[i].0, bounds[i].1);
855 }
856
857 offspring
858 }
859
860 fn apply_quantum_mutations(
861 &self,
862 population: &mut [Vec<f64>],
863 bounds: &[(f64, f64)],
864 iteration: usize,
865 max_iterations: usize,
866 ) {
867 let mutation_rate = 0.1 * (1.0 - iteration as f64 / max_iterations as f64);
868
869 for individual in population.iter_mut() {
870 for i in 0..self.dimensions {
871 if self.state.pseudo_random() < mutation_rate {
872 let range = bounds[i].1 - bounds[i].0;
873 let quantum_step = range * 0.05 * self.state.pseudo_random();
874
875 if self.state.pseudo_random() < 0.5 {
876 individual[i] += quantum_step;
877 } else {
878 individual[i] -= quantum_step;
879 }
880
881 individual[i] = individual[i].clamp(bounds[i].0, bounds[i].1);
882 }
883 }
884 }
885 }
886
887 fn update_velocity(
888 &mut self,
889 velocity: &mut [f64],
890 position: &[f64],
891 personal_best: &[f64],
892 global_best: &[f64],
893 iteration: usize,
894 max_iterations: usize,
895 ) {
896 let w = 0.9 - 0.5 * iteration as f64 / max_iterations as f64; let c1 = 2.0; let c2 = 2.0; for i in 0..self.dimensions {
901 let r1 = self.state.pseudo_random();
902 let r2 = self.state.pseudo_random();
903
904 let quantum_phase = self.state.phases.get(i).unwrap_or(&0.0);
906 let quantum_factor = 1.0 + 0.1 * quantum_phase.cos();
907
908 velocity[i] = w * velocity[i] * quantum_factor
909 + c1 * r1 * (personal_best[i] - position[i])
910 + c2 * r2 * (global_best[i] - position[i]);
911
912 velocity[i] = velocity[i].clamp(-1.0, 1.0);
914 }
915 }
916
917 fn calculate_quantum_interference(&self, particle: usize, dimension: usize) -> f64 {
918 if particle < self.state.amplitudes.len() && dimension < self.state.phases.len() {
919 let amplitude = self.state.amplitudes[particle];
920 let phase = self.state.phases[dimension];
921 amplitude * phase.sin() * 0.01
922 } else {
923 0.0
924 }
925 }
926
927 fn update_swarm_quantum_state(&mut self, particles: &[Vec<f64>]) {
928 if !particles.is_empty() && !particles[0].is_empty() {
930 for i in 0..self.dimensions.min(self.state.amplitudes.len()) {
931 let values: Vec<f64> = particles
932 .iter()
933 .map(|p| p.get(i).copied().unwrap_or(0.0))
934 .collect();
935 let mean = values.iter().sum::<f64>() / values.len() as f64;
936 let variance =
937 values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
938
939 self.state.amplitudes[0] = (1.0 / (1.0 + variance)).sqrt();
941 }
942 }
943 }
944
945 fn calculate_quantum_perturbation(
946 &mut self,
947 dimension: usize,
948 iteration: usize,
949 max_iterations: usize,
950 ) -> f64 {
951 let progress = iteration as f64 / max_iterations as f64;
952 let amplitude = if dimension < self.state.amplitudes.len() {
953 self.state.amplitudes[dimension]
954 } else {
955 1.0
956 };
957
958 amplitude * (1.0 - progress) * 0.01 * (self.state.pseudo_random() - 0.5)
959 }
960
961 fn calculate_crossover_rate(&self, dimension: usize) -> f64 {
962 let base_cr = 0.9;
963 let quantum_modulation = if dimension < self.state.amplitudes.len() {
964 self.state.amplitudes[dimension] * 0.1
965 } else {
966 0.0
967 };
968
969 (base_cr + quantum_modulation).clamp(0.0, 1.0)
970 }
971
972 fn extract_solution_from_quantum_state(&self, bounds: &[(f64, f64)]) -> Vec<f64> {
973 (0..self.dimensions)
974 .map(|i| {
975 let prob = if i < self.state.amplitudes.len() {
976 self.state.amplitudes[i] * self.state.amplitudes[i]
977 } else {
978 0.5
979 };
980 bounds[i].0 + prob * (bounds[i].1 - bounds[i].0)
981 })
982 .collect()
983 }
984
985 fn apply_adiabatic_evolution(
986 &mut self,
987 solution: &[f64],
988 fitness: f64,
989 h_problem: f64,
990 h_initial: f64,
991 ) {
992 #[allow(clippy::needless_range_loop)]
994 for i in 0..self.dimensions.min(self.state.amplitudes.len()) {
995 let energy_contribution = fitness * solution.get(i).copied().unwrap_or(0.0) * h_problem;
996 let mixing_contribution = h_initial;
997
998 let total_energy = energy_contribution + mixing_contribution;
999 let rotation_angle = -total_energy * 0.01; self.state.apply_rotation(rotation_angle, i);
1002 }
1003 }
1004
1005 fn apply_problem_hamiltonian<F>(&mut self, gamma: f64, objectivefn: &F, bounds: &[(f64, f64)])
1006 where
1007 F: Fn(&[f64]) -> f64 + Send + Sync,
1008 {
1009 let solution = self.extract_solution_from_quantum_state(bounds);
1010 let fitness = objectivefn(&solution);
1011
1012 #[allow(clippy::needless_range_loop)]
1013 for i in 0..self.dimensions.min(self.state.amplitudes.len()) {
1014 let rotation_angle = gamma * fitness * solution.get(i).copied().unwrap_or(0.0) * 0.001;
1015 self.state.apply_rotation(rotation_angle, i);
1016 }
1017 }
1018
1019 fn apply_mixer_hamiltonian(&mut self, beta: f64) {
1020 for i in 0..self.dimensions.min(self.state.amplitudes.len()) {
1021 let rotation_angle = beta;
1022 self.state.apply_rotation(rotation_angle, i);
1023 }
1024 }
1025
1026 fn decode_measurement_to_solution(
1027 &self,
1028 measurement: usize,
1029 bounds: &[(f64, f64)],
1030 ) -> Vec<f64> {
1031 (0..self.dimensions)
1032 .map(|i| {
1033 let normalized_value = ((measurement + i) % (1 << 10)) as f64 / (1 << 10) as f64;
1034 bounds[i].0 + normalized_value * (bounds[i].1 - bounds[i].0)
1035 })
1036 .collect()
1037 }
1038
1039 fn update_qaoa_params(
1040 &mut self,
1041 gamma_params: &mut [f64],
1042 beta_params: &mut [f64],
1043 iteration: usize,
1044 ) {
1045 let step_size = 0.01 * (1.0 - iteration as f64 / 1000.0);
1046
1047 for i in 0..gamma_params.len() {
1048 gamma_params[i] += step_size * (self.state.pseudo_random() - 0.5);
1049 gamma_params[i] = gamma_params[i].clamp(0.0, PI);
1050
1051 beta_params[i] += step_size * (self.state.pseudo_random() - 0.5);
1052 beta_params[i] = beta_params[i].clamp(0.0, PI);
1053 }
1054 }
1055
1056 pub fn get_measurement_probabilities(&self) -> &[f64] {
1058 &self.state.measurement_probs
1059 }
1060
1061 pub fn get_quantum_entropy(&self) -> f64 {
1063 self.state.entropy()
1064 }
1065
1066 fn accept_solution(
1068 &self,
1069 currentfitness: f64,
1070 new_fitness: f64,
1071 iteration: usize,
1072 max_iterations: usize,
1073 ) -> bool {
1074 if new_fitness < currentfitness {
1075 return true;
1076 }
1077
1078 let temperature = 1.0 - (iteration as f64 / max_iterations as f64);
1080 let delta_fitness = new_fitness - currentfitness;
1081 let quantum_probability = (-delta_fitness / temperature).exp();
1082
1083 use rand::Rng;
1084 let mut rng = rand::rng();
1085 rng.random::<f64>() < quantum_probability
1086 }
1087
1088 fn quantum_reproduction(
1090 &mut self,
1091 parents: &[Vec<f64>],
1092 _fitnessvalues: &[f64],
1093 _bounds: &[(f64, f64)],
1094 ) -> Vec<Vec<f64>> {
1095 if parents.is_empty() {
1096 return vec![vec![0.0; self.dimensions]; self.population_size];
1097 }
1098
1099 let mut offspring = Vec::with_capacity(self.population_size);
1100
1101 for _ in 0..self.population_size {
1102 let mut child = vec![0.0; self.dimensions];
1104 for i in 0..self.dimensions {
1105 let mut sum = 0.0;
1106 for parent in parents {
1107 if i < parent.len() {
1108 sum += parent[i];
1109 }
1110 }
1111 child[i] = sum / parents.len() as f64;
1112
1113 child[i] += self.calculate_quantum_fluctuation(i, 0, 100);
1115 }
1116 offspring.push(child);
1117 }
1118
1119 offspring
1120 }
1121
1122 fn calculate_quantum_fluctuation(
1124 &mut self,
1125 dimension: usize,
1126 _iteration: usize,
1127 _max_iterations: usize,
1128 ) -> f64 {
1129 if dimension < self.state.amplitudes.len() {
1131 let amplitude = self.state.amplitudes[dimension];
1132 amplitude.abs() * 0.1 } else {
1134 0.0
1135 }
1136 }
1137
1138 fn calculate_quantum_crossover_probability(&self, dimension: usize, iteration: usize) -> f64 {
1140 let base_probability = 0.8;
1142 let quantum_modulation = (iteration as f64 * 0.1).sin() * 0.1;
1143 (base_probability + quantum_modulation).clamp(0.1, 0.9)
1144 }
1145
1146 fn evolve_adiabatic_hamiltonian(
1148 &mut self,
1149 _h_initial_weight: f64,
1150 _h_problem_weight: f64,
1151 _fitness: f64,
1152 _bounds: &[(f64, f64)],
1153 ) {
1154 for i in 0..self.state.amplitudes.len().min(self.dimensions) {
1156 let evolution_factor = (_h_problem_weight * 0.1).sin();
1157 self.state.amplitudes[i] *= evolution_factor.abs();
1158 }
1159 }
1160}
1161
1162#[derive(Debug, Clone)]
1164pub struct OptimizationResult {
1165 pub best_solution: Vec<f64>,
1167 pub best_fitness: f64,
1169 pub iterations_performed: usize,
1171 pub convergence_history: Vec<f64>,
1173 pub execution_time: Duration,
1175 pub strategy_used: QuantumStrategy,
1177 pub quantum_state_entropy: f64,
1179}
1180
1181impl OptimizationResult {
1182 pub fn has_converged(&self, tolerance: f64) -> bool {
1184 if self.convergence_history.len() < 10 {
1185 return false;
1186 }
1187
1188 let last_10: Vec<f64> = self
1189 .convergence_history
1190 .iter()
1191 .rev()
1192 .take(10)
1193 .cloned()
1194 .collect();
1195 let variance = {
1196 let mean = last_10.iter().sum::<f64>() / last_10.len() as f64;
1197 last_10.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / last_10.len() as f64
1198 };
1199
1200 variance < tolerance
1201 }
1202
1203 pub fn convergence_rate(&self) -> f64 {
1205 if self.convergence_history.len() < 2 {
1206 return 0.0;
1207 }
1208
1209 let initial = self.convergence_history[0];
1210 let final_val = self.best_fitness;
1211
1212 if initial == final_val {
1213 1.0
1214 } else {
1215 (initial - final_val) / initial
1216 }
1217 }
1218}
1219
1220#[cfg(test)]
1221mod tests {
1222 use super::*;
1223
1224 #[test]
1225 fn test_quantum_state_creation() {
1226 let state = QuantumState::dimensions(4);
1227 assert_eq!(state.amplitudes.len(), 4);
1228 assert_eq!(state.phases.len(), 4);
1229
1230 let norm_squared: f64 = state.amplitudes.iter().map(|a| a * a).sum();
1232 assert!((norm_squared - 1.0).abs() < 1e-10);
1233 }
1234
1235 #[test]
1236 fn test_quantum_measurement() {
1237 let mut state = QuantumState::dimensions(4);
1238 let measurement = state.measure();
1239 assert!(measurement < 4);
1240
1241 let non_zero_count = state.amplitudes.iter().filter(|&&a| a > 0.0).count();
1243 assert_eq!(non_zero_count, 1);
1244 }
1245
1246 #[test]
1247 fn test_quantum_optimizer_creation() {
1248 let optimizer = QuantumOptimizer::new(5, QuantumStrategy::QuantumAnnealing, Some(20));
1249 assert!(optimizer.is_ok());
1250
1251 let opt = optimizer.unwrap();
1252 assert_eq!(opt.dimensions, 5);
1253 assert_eq!(opt.population_size, 20);
1254 assert_eq!(opt.strategy, QuantumStrategy::QuantumAnnealing);
1255 }
1256
1257 #[test]
1258 fn test_quantum_optimization_simple() {
1259 let mut optimizer =
1260 QuantumOptimizer::new(2, QuantumStrategy::QuantumAnnealing, Some(10)).unwrap();
1261
1262 let objective = |x: &[f64]| x.iter().map(|xi| xi * xi).sum();
1264 let bounds = vec![(-5.0, 5.0), (-5.0, 5.0)];
1265
1266 let result = optimizer.optimize(objective, &bounds, 50).unwrap();
1267
1268 assert!(result.best_fitness >= 0.0);
1269 assert_eq!(result.best_solution.len(), 2);
1270 assert!(result.iterations_performed > 0);
1271 assert!(!result.convergence_history.is_empty());
1272 }
1273
1274 #[test]
1275 fn test_quantum_annealing_optimization() {
1276 let mut optimizer =
1277 QuantumOptimizer::new(1, QuantumStrategy::QuantumAnnealing, None).unwrap();
1278
1279 let objective = |x: &[f64]| (x[0] - 2.0).powi(2);
1281 let bounds = vec![(-5.0, 5.0)]; let result = optimizer.optimize(objective, &bounds, 300).unwrap(); assert!(result.best_fitness >= 0.0); assert!(result.best_fitness < 25.0); assert!((result.best_solution[0] - 2.0).abs() < 5.0); assert!(result.iterations_performed > 0);
1290 assert!(!result.convergence_history.is_empty());
1291 }
1292
1293 #[test]
1294 fn test_quantum_evolutionary_optimization() {
1295 let mut optimizer =
1296 QuantumOptimizer::new(2, QuantumStrategy::QuantumEvolutionary, Some(20)).unwrap();
1297
1298 let objective = |x: &[f64]| {
1300 let a = 1.0;
1301 let b = 100.0;
1302 (a - x[0]).powi(2) + b * (x[1] - x[0].powi(2)).powi(2)
1303 };
1304 let bounds = vec![(-5.0, 5.0), (-5.0, 5.0)];
1305
1306 let result = optimizer.optimize(objective, &bounds, 100).unwrap();
1307
1308 assert!(result.best_fitness.is_finite());
1311 assert!(result.iterations_performed > 0);
1312 assert!(!result.convergence_history.is_empty());
1313 assert_eq!(result.strategy_used, QuantumStrategy::QuantumEvolutionary);
1314 }
1315
1316 #[test]
1317 fn test_optimization_result_convergence() {
1318 let convergence_history = vec![
1322 10.0, 5.0, 0.505, 0.504, 0.503, 0.502, 0.501, 0.5008, 0.5006, 0.5004, 0.5002,
1324 0.5001, ];
1326 let result = OptimizationResult {
1327 best_solution: vec![1.0, 1.0],
1328 best_fitness: 0.5001,
1329 iterations_performed: 12,
1330 convergence_history,
1331 execution_time: Duration::from_millis(100),
1332 strategy_used: QuantumStrategy::QuantumAnnealing,
1333 quantum_state_entropy: 0.5,
1334 };
1335
1336 assert!(result.has_converged(0.01));
1337 assert!(result.convergence_rate() > 0.9);
1338 }
1339
1340 #[test]
1341 fn test_quantum_state_operations() {
1342 let mut state = QuantumState::new_uniform(2);
1343
1344 state.apply_hadamard(0);
1346
1347 state.apply_rotation(PI / 4.0, 0);
1349
1350 state.entangle(0, 1, 0.5);
1352 assert_eq!(state.entanglementmatrix[0][1], 0.5);
1353 assert_eq!(state.entanglementmatrix[1][0], 0.5);
1354
1355 let entropy = state.entropy();
1357 assert!(entropy >= 0.0);
1358 }
1359
1360 #[test]
1361 fn test_quantum_parameters() {
1362 let params = QuantumParameters::default();
1363 assert!(params.temperature > 0.0);
1364 assert!(params.cooling_rate > 0.0 && params.cooling_rate < 1.0);
1365 assert!(params.min_temperature > 0.0);
1366 assert!(params.tunneling_rate >= 0.0 && params.tunneling_rate <= 1.0);
1367 }
1368
1369 #[test]
1370 fn test_all_quantum_strategies() {
1371 let strategies = vec![
1372 QuantumStrategy::QuantumAnnealing,
1373 QuantumStrategy::QuantumEvolutionary,
1374 QuantumStrategy::QuantumParticleSwarm,
1375 QuantumStrategy::QuantumDifferentialEvolution,
1376 QuantumStrategy::AdiabaticQuantum,
1377 QuantumStrategy::QAOA,
1378 ];
1379
1380 for strategy in strategies {
1381 let optimizer = QuantumOptimizer::new(2, strategy, Some(10));
1382 assert!(
1383 optimizer.is_ok(),
1384 "Failed to create optimizer for strategy {strategy:?}"
1385 );
1386 }
1387 }
1388
1389 #[test]
1390 #[cfg(feature = "parallel")]
1391 fn test_parallel_evaluation() {
1392 let mut optimizer =
1393 QuantumOptimizer::new(3, QuantumStrategy::QuantumEvolutionary, Some(20)).unwrap();
1394
1395 let objective = |x: &[f64]| {
1397 std::thread::sleep(Duration::from_millis(1));
1399 x.iter().map(|xi| xi * xi).sum::<f64>()
1400 };
1401
1402 let bounds = vec![(-2.0, 2.0), (-2.0, 2.0), (-2.0, 2.0)];
1403
1404 let start = Instant::now();
1405 let result = optimizer.optimize(objective, &bounds, 20).unwrap();
1406 let elapsed = start.elapsed();
1407
1408 assert!(elapsed < Duration::from_secs(5));
1410 assert!(result.best_fitness >= 0.0);
1411 }
1412}