Skip to main content

oxirs_vec/
quantum_search.rs

1//! Quantum-inspired algorithms for vector search optimization.
2//!
3//! This module implements quantum computing principles to enhance vector search
4//! performance through quantum superposition, entanglement, and interference patterns.
5//! These algorithms provide novel optimization approaches that can outperform
6//! classical algorithms in specific scenarios, particularly for high-dimensional
7//! similarity search and complex optimization landscapes.
8
9use crate::random_utils::NormalSampler as Normal;
10use crate::Vector;
11use anyhow::{anyhow, Result};
12use oxirs_core::parallel::*;
13use oxirs_core::simd::SimdOps;
14use scirs2_core::random::{Random, Rng};
15use scirs2_core::rngs::StdRng;
16use serde::{Deserialize, Serialize};
17use std::collections::HashMap;
18use std::sync::{Arc, RwLock};
19use tracing::{debug, info, span, Level};
20
21/// Quantum-inspired search configuration
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct QuantumSearchConfig {
24    /// Number of quantum superposition states
25    pub superposition_states: usize,
26    /// Entanglement strength between vectors
27    pub entanglement_strength: f32,
28    /// Interference pattern amplification factor
29    pub interference_amplitude: f32,
30    /// Quantum measurement probability threshold
31    pub measurement_threshold: f32,
32    /// Maximum quantum search iterations
33    pub max_iterations: usize,
34    /// Enable quantum tunneling optimization
35    pub enable_tunneling: bool,
36    /// Quantum decoherence rate
37    pub decoherence_rate: f32,
38}
39
40impl Default for QuantumSearchConfig {
41    fn default() -> Self {
42        Self {
43            superposition_states: 64,
44            entanglement_strength: 0.7,
45            interference_amplitude: 1.2,
46            measurement_threshold: 0.1,
47            max_iterations: 100,
48            enable_tunneling: true,
49            decoherence_rate: 0.05,
50        }
51    }
52}
53
54/// Quantum state representation for vector search
55#[derive(Debug, Clone)]
56pub struct QuantumState {
57    /// Amplitude coefficients for superposition states
58    pub amplitudes: Vec<f32>,
59    /// Phase information for quantum interference
60    pub phases: Vec<f32>,
61    /// Entanglement matrix between states
62    pub entanglement_matrix: Vec<Vec<f32>>,
63    /// Probability distribution over states
64    pub probabilities: Vec<f32>,
65}
66
67impl QuantumState {
68    /// Create a new quantum state with given number of states
69    pub fn new(num_states: usize) -> Self {
70        let amplitudes = vec![1.0 / (num_states as f32).sqrt(); num_states];
71        let phases = vec![0.0; num_states];
72        let entanglement_matrix = vec![vec![0.0; num_states]; num_states];
73        let probabilities = vec![1.0 / num_states as f32; num_states];
74
75        Self {
76            amplitudes,
77            phases,
78            entanglement_matrix,
79            probabilities,
80        }
81    }
82
83    /// Apply quantum superposition to create multiple search paths
84    pub fn apply_superposition(&mut self, config: &QuantumSearchConfig) {
85        let num_states = self.amplitudes.len();
86
87        for i in 0..num_states {
88            // Apply Hadamard-like transformation for superposition
89            let angle = std::f32::consts::PI * i as f32 / num_states as f32;
90            self.amplitudes[i] = (angle.cos() * config.interference_amplitude).abs();
91            self.phases[i] = angle.sin() * config.interference_amplitude;
92        }
93
94        self.normalize();
95    }
96
97    /// Create entanglement between quantum states
98    pub fn create_entanglement(&mut self, config: &QuantumSearchConfig) {
99        let num_states = self.amplitudes.len();
100
101        for i in 0..num_states {
102            for j in (i + 1)..num_states {
103                // Create entanglement based on state similarity
104                let entanglement =
105                    config.entanglement_strength * (self.amplitudes[i] * self.amplitudes[j]).sqrt();
106
107                self.entanglement_matrix[i][j] = entanglement;
108                self.entanglement_matrix[j][i] = entanglement;
109            }
110        }
111    }
112
113    /// Apply quantum interference patterns
114    pub fn apply_interference(&mut self, target_similarity: f32) {
115        let num_states = self.amplitudes.len();
116
117        for i in 0..num_states {
118            // Constructive interference for high similarity states
119            if self.probabilities[i] > target_similarity {
120                self.amplitudes[i] *= 1.0 + target_similarity;
121                self.phases[i] += std::f32::consts::PI / 4.0;
122            } else {
123                // Destructive interference for low similarity states
124                self.amplitudes[i] *= 1.0 - target_similarity * 0.5;
125                self.phases[i] -= std::f32::consts::PI / 4.0;
126            }
127        }
128
129        self.normalize();
130    }
131
132    /// Simulate quantum tunneling for optimization landscape exploration
133    pub fn quantum_tunneling(&mut self, barrier_height: f32) -> Vec<usize> {
134        let mut tunneling_states = Vec::new();
135
136        for i in 0..self.amplitudes.len() {
137            // Quantum tunneling probability based on barrier height
138            let tunneling_prob = (-2.0 * barrier_height).exp();
139
140            if self.probabilities[i] * tunneling_prob > 0.1 {
141                tunneling_states.push(i);
142                // Boost amplitude for tunneling states
143                self.amplitudes[i] *= (1.0 + tunneling_prob).sqrt();
144            }
145        }
146
147        self.normalize();
148        tunneling_states
149    }
150
151    /// Measure quantum state and collapse to classical result
152    pub fn measure(&mut self, config: &QuantumSearchConfig) -> Vec<usize> {
153        self.update_probabilities();
154
155        let mut measured_states = Vec::new();
156
157        for (i, &prob) in self.probabilities.iter().enumerate() {
158            if prob > config.measurement_threshold {
159                measured_states.push(i);
160            }
161        }
162
163        // Apply decoherence
164        for amplitude in &mut self.amplitudes {
165            *amplitude *= 1.0 - config.decoherence_rate;
166        }
167
168        measured_states
169    }
170
171    /// Update probability distribution from amplitudes
172    fn update_probabilities(&mut self) {
173        for (i, prob) in self.probabilities.iter_mut().enumerate() {
174            *prob = self.amplitudes[i].powi(2);
175        }
176    }
177
178    /// Normalize quantum state with SIMD optimization
179    fn normalize(&mut self) {
180        // Use SIMD for computing norm
181        let norm = f32::norm(&self.amplitudes);
182
183        if norm > 0.0 {
184            // Scale vector to normalize (no SIMD scale available, use scalar)
185            for amplitude in &mut self.amplitudes {
186                *amplitude /= norm;
187            }
188        }
189
190        self.update_probabilities();
191    }
192
193    /// Enhanced quantum tunneling with better barrier modeling
194    pub fn enhanced_quantum_tunneling(&mut self, barrier_profile: &[f32]) -> Result<Vec<usize>> {
195        if barrier_profile.len() != self.amplitudes.len() {
196            return Err(anyhow!(
197                "Barrier profile length must match number of quantum states"
198            ));
199        }
200
201        let mut tunneling_states = Vec::new();
202
203        #[allow(clippy::needless_range_loop)]
204        for i in 0..self.amplitudes.len() {
205            let barrier_height = barrier_profile[i];
206
207            // More sophisticated tunneling probability calculation
208            let transmission_coefficient = if barrier_height > 0.0 {
209                let tunneling_width = 1.0; // Simplified barrier width
210                (-2.0 * (2.0 * barrier_height).sqrt() * tunneling_width).exp()
211            } else {
212                1.0 // No barrier
213            };
214
215            let tunneling_prob = self.probabilities[i] * transmission_coefficient;
216
217            if tunneling_prob > 0.05 {
218                tunneling_states.push(i);
219                // Enhance amplitude for successful tunneling
220                self.amplitudes[i] *= (1.0 + transmission_coefficient).sqrt();
221            }
222        }
223
224        self.normalize();
225        Ok(tunneling_states)
226    }
227}
228
229/// Quantum-inspired vector search algorithm
230#[derive(Debug)]
231pub struct QuantumVectorSearch {
232    config: QuantumSearchConfig,
233    quantum_states: Arc<RwLock<HashMap<String, QuantumState>>>,
234    search_history: Arc<RwLock<Vec<QuantumSearchResult>>>,
235    optimization_cache: Arc<RwLock<HashMap<String, f32>>>,
236    rng: Arc<RwLock<Random<StdRng>>>,
237}
238
239/// Result of quantum-inspired search with quantum metrics
240#[derive(Debug, Clone, Serialize, Deserialize)]
241pub struct QuantumSearchResult {
242    pub vector_id: String,
243    pub similarity: f32,
244    pub quantum_probability: f32,
245    pub entanglement_score: f32,
246    pub interference_pattern: f32,
247    pub tunneling_advantage: f32,
248    pub quantum_confidence: f32,
249}
250
251impl QuantumVectorSearch {
252    /// Create a new quantum vector search instance
253    pub fn new(config: QuantumSearchConfig) -> Self {
254        Self {
255            config,
256            quantum_states: Arc::new(RwLock::new(HashMap::new())),
257            search_history: Arc::new(RwLock::new(Vec::new())),
258            optimization_cache: Arc::new(RwLock::new(HashMap::new())),
259            rng: Arc::new(RwLock::new(Random::seed(42))),
260        }
261    }
262
263    /// Create with default configuration
264    pub fn with_default_config() -> Self {
265        Self::new(QuantumSearchConfig::default())
266    }
267
268    /// Create with seeded random number generator for reproducible results
269    pub fn with_seed(config: QuantumSearchConfig, seed: u64) -> Self {
270        Self {
271            config,
272            quantum_states: Arc::new(RwLock::new(HashMap::new())),
273            search_history: Arc::new(RwLock::new(Vec::new())),
274            optimization_cache: Arc::new(RwLock::new(HashMap::new())),
275            rng: Arc::new(RwLock::new(Random::seed(seed))),
276        }
277    }
278
279    /// Perform quantum-inspired similarity search
280    pub async fn quantum_similarity_search(
281        &self,
282        query_vector: &Vector,
283        candidate_vectors: &[(String, Vector)],
284        k: usize,
285    ) -> Result<Vec<QuantumSearchResult>> {
286        let span = span!(Level::DEBUG, "quantum_similarity_search");
287        let _enter = span.enter();
288
289        let query_id = self.generate_query_id(query_vector);
290
291        // Initialize quantum state for this search
292        let mut quantum_state = QuantumState::new(self.config.superposition_states);
293        quantum_state.apply_superposition(&self.config);
294        quantum_state.create_entanglement(&self.config);
295
296        let mut results = Vec::new();
297        let query_f32 = query_vector.as_f32();
298
299        // Quantum-enhanced similarity computation
300        for (candidate_id, candidate_vector) in candidate_vectors {
301            let candidate_f32 = candidate_vector.as_f32();
302
303            // Classical similarity computation
304            let classical_similarity = self.compute_cosine_similarity(&query_f32, &candidate_f32);
305
306            // Apply quantum interference based on similarity
307            quantum_state.apply_interference(classical_similarity);
308
309            // Quantum tunneling for exploration
310            let tunneling_states = if self.config.enable_tunneling {
311                quantum_state.quantum_tunneling(1.0 - classical_similarity)
312            } else {
313                Vec::new()
314            };
315
316            // Measure quantum state
317            let measured_states = quantum_state.measure(&self.config);
318
319            // Compute quantum-enhanced metrics
320            let quantum_probability = quantum_state.probabilities.iter().sum::<f32>()
321                / quantum_state.probabilities.len() as f32;
322            let entanglement_score = self.compute_entanglement_score(&quantum_state);
323            let interference_pattern = self.compute_interference_pattern(&quantum_state);
324            let tunneling_advantage = if tunneling_states.is_empty() {
325                0.0
326            } else {
327                tunneling_states.len() as f32 / self.config.superposition_states as f32
328            };
329
330            // Quantum-enhanced similarity score
331            let quantum_similarity = classical_similarity * (1.0 + quantum_probability * 0.3);
332            let quantum_confidence =
333                self.compute_quantum_confidence(&quantum_state, &measured_states);
334
335            results.push(QuantumSearchResult {
336                vector_id: candidate_id.clone(),
337                similarity: quantum_similarity,
338                quantum_probability,
339                entanglement_score,
340                interference_pattern,
341                tunneling_advantage,
342                quantum_confidence,
343            });
344        }
345
346        // Sort by quantum-enhanced similarity
347        results.sort_by(|a, b| {
348            b.similarity
349                .partial_cmp(&a.similarity)
350                .unwrap_or(std::cmp::Ordering::Equal)
351        });
352        results.truncate(k);
353
354        // Store quantum state for future use
355        {
356            let mut states = self
357                .quantum_states
358                .write()
359                .expect("quantum_states lock should not be poisoned");
360            states.insert(query_id, quantum_state);
361        }
362
363        // Store search result in history
364        {
365            let mut history = self
366                .search_history
367                .write()
368                .expect("search_history lock should not be poisoned");
369            history.extend(results.clone());
370        }
371
372        info!(
373            "Quantum similarity search completed with {} results",
374            results.len()
375        );
376        Ok(results)
377    }
378
379    /// Parallel quantum-inspired similarity search for improved performance
380    pub async fn parallel_quantum_similarity_search(
381        &self,
382        query_vector: &Vector,
383        candidate_vectors: &[(String, Vector)],
384        k: usize,
385    ) -> Result<Vec<QuantumSearchResult>> {
386        let span = span!(Level::DEBUG, "parallel_quantum_similarity_search");
387        let _enter = span.enter();
388
389        if candidate_vectors.is_empty() {
390            return Ok(Vec::new());
391        }
392
393        let _query_id = self.generate_query_id(query_vector);
394        let query_f32 = query_vector.as_f32();
395
396        // Use parallel processing for large datasets
397        let chunk_size = std::cmp::max(candidate_vectors.len() / num_cpus::get(), 1);
398
399        let results: Result<Vec<Vec<QuantumSearchResult>>> = candidate_vectors
400            .par_chunks(chunk_size)
401            .map(|chunk| -> Result<Vec<QuantumSearchResult>> {
402                let mut chunk_results = Vec::new();
403                let mut quantum_state = QuantumState::new(self.config.superposition_states);
404                quantum_state.apply_superposition(&self.config);
405                quantum_state.create_entanglement(&self.config);
406
407                for (candidate_id, candidate_vector) in chunk {
408                    let candidate_f32 = candidate_vector.as_f32();
409
410                    // Classical similarity computation with SIMD optimization
411                    let classical_similarity =
412                        self.compute_cosine_similarity(&query_f32, &candidate_f32);
413
414                    // Apply quantum interference
415                    quantum_state.apply_interference(classical_similarity);
416
417                    // Quantum tunneling if enabled
418                    let tunneling_advantage = if self.config.enable_tunneling {
419                        let barrier_height =
420                            vec![1.0 - classical_similarity; self.config.superposition_states];
421                        match quantum_state.enhanced_quantum_tunneling(&barrier_height) {
422                            Ok(tunneling_states) => {
423                                if tunneling_states.is_empty() {
424                                    0.0
425                                } else {
426                                    tunneling_states.len() as f32
427                                        / self.config.superposition_states as f32
428                                }
429                            }
430                            Err(_) => 0.0,
431                        }
432                    } else {
433                        0.0
434                    };
435
436                    // Measure quantum state
437                    let measured_states = quantum_state.measure(&self.config);
438
439                    // Compute quantum-enhanced metrics
440                    let quantum_probability = quantum_state.probabilities.iter().sum::<f32>()
441                        / quantum_state.probabilities.len() as f32;
442                    let entanglement_score = self.compute_entanglement_score(&quantum_state);
443                    let interference_pattern = self.compute_interference_pattern(&quantum_state);
444                    let quantum_confidence =
445                        self.compute_quantum_confidence(&quantum_state, &measured_states);
446
447                    // Enhanced quantum similarity score with better weighting
448                    let quantum_enhancement = quantum_probability * 0.3
449                        + entanglement_score * 0.1
450                        + tunneling_advantage * 0.2;
451                    let quantum_similarity = classical_similarity * (1.0 + quantum_enhancement);
452
453                    chunk_results.push(QuantumSearchResult {
454                        vector_id: candidate_id.clone(),
455                        similarity: quantum_similarity,
456                        quantum_probability,
457                        entanglement_score,
458                        interference_pattern,
459                        tunneling_advantage,
460                        quantum_confidence,
461                    });
462                }
463
464                Ok(chunk_results)
465            })
466            .collect();
467
468        let mut all_results: Vec<QuantumSearchResult> = results?.into_iter().flatten().collect();
469
470        // Sort by quantum-enhanced similarity
471        all_results.sort_by(|a, b| {
472            b.similarity
473                .partial_cmp(&a.similarity)
474                .unwrap_or(std::cmp::Ordering::Equal)
475        });
476        all_results.truncate(k);
477
478        // Store search result in history
479        {
480            let mut history = self
481                .search_history
482                .write()
483                .expect("search_history lock should not be poisoned");
484            history.extend(all_results.clone());
485        }
486
487        info!(
488            "Parallel quantum similarity search completed with {} results",
489            all_results.len()
490        );
491        Ok(all_results)
492    }
493
494    /// Perform quantum amplitude amplification for targeted search
495    pub fn quantum_amplitude_amplification(
496        &self,
497        target_similarity: f32,
498        quantum_state: &mut QuantumState,
499        iterations: usize,
500    ) -> Result<()> {
501        for iteration in 0..iterations {
502            // Oracle operation: mark target states
503            for (i, &prob) in quantum_state.probabilities.iter().enumerate() {
504                if prob >= target_similarity {
505                    quantum_state.amplitudes[i] *= -1.0; // Phase flip
506                }
507            }
508
509            // Diffusion operation: inversion about average
510            let average_amplitude: f32 = quantum_state.amplitudes.iter().sum::<f32>()
511                / quantum_state.amplitudes.len() as f32;
512
513            for amplitude in &mut quantum_state.amplitudes {
514                *amplitude = 2.0 * average_amplitude - *amplitude;
515            }
516
517            quantum_state.normalize();
518
519            debug!(
520                "Amplitude amplification iteration {} completed",
521                iteration + 1
522            );
523        }
524
525        Ok(())
526    }
527
528    /// Quantum annealing for optimization landscape exploration
529    pub fn quantum_annealing_optimization(
530        &self,
531        cost_function: impl Fn(&[f32]) -> f32,
532        initial_state: &[f32],
533        temperature_schedule: &[f32],
534    ) -> Result<Vec<f32>> {
535        let mut current_state = initial_state.to_vec();
536        let mut best_state = current_state.clone();
537        let mut best_cost = cost_function(&current_state);
538
539        for &temperature in temperature_schedule {
540            // Quantum fluctuations
541            for item in &mut current_state {
542                let quantum_fluctuation = self.generate_quantum_fluctuation(temperature);
543                *item += quantum_fluctuation;
544            }
545
546            let current_cost = cost_function(&current_state);
547
548            // Quantum acceptance probability
549            let accept_prob = if current_cost < best_cost {
550                1.0
551            } else {
552                (-(current_cost - best_cost) / temperature).exp()
553            };
554
555            if self.generate_random() < accept_prob {
556                best_state = current_state.clone();
557                best_cost = current_cost;
558            }
559
560            debug!(
561                "Quantum annealing: temperature={}, cost={}",
562                temperature, current_cost
563            );
564        }
565
566        Ok(best_state)
567    }
568
569    /// Get quantum search statistics
570    pub fn get_quantum_statistics(&self) -> QuantumSearchStatistics {
571        let history = self
572            .search_history
573            .read()
574            .expect("search_history lock should not be poisoned");
575
576        let total_searches = history.len();
577        let avg_quantum_probability = if total_searches > 0 {
578            history.iter().map(|r| r.quantum_probability).sum::<f32>() / total_searches as f32
579        } else {
580            0.0
581        };
582
583        let avg_entanglement_score = if total_searches > 0 {
584            history.iter().map(|r| r.entanglement_score).sum::<f32>() / total_searches as f32
585        } else {
586            0.0
587        };
588
589        let avg_quantum_confidence = if total_searches > 0 {
590            history.iter().map(|r| r.quantum_confidence).sum::<f32>() / total_searches as f32
591        } else {
592            0.0
593        };
594
595        QuantumSearchStatistics {
596            total_searches,
597            avg_quantum_probability,
598            avg_entanglement_score,
599            avg_quantum_confidence,
600            superposition_states: self.config.superposition_states,
601            entanglement_strength: self.config.entanglement_strength,
602        }
603    }
604
605    // Helper methods
606
607    fn generate_query_id(&self, vector: &Vector) -> String {
608        use std::collections::hash_map::DefaultHasher;
609        use std::hash::{Hash, Hasher};
610
611        let mut hasher = DefaultHasher::new();
612        for value in vector.as_f32() {
613            value.to_bits().hash(&mut hasher);
614        }
615        format!("quantum_query_{:x}", hasher.finish())
616    }
617
618    fn compute_cosine_similarity(&self, a: &[f32], b: &[f32]) -> f32 {
619        if a.len() != b.len() {
620            return 0.0;
621        }
622
623        // Use SIMD optimization via oxirs-core for better performance
624        // Note: SimdOps provides cosine_distance, so we convert to similarity
625        let cosine_distance = f32::cosine_distance(a, b);
626        1.0 - cosine_distance
627    }
628
629    fn compute_entanglement_score(&self, quantum_state: &QuantumState) -> f32 {
630        let mut entanglement_score = 0.0;
631        let num_states = quantum_state.entanglement_matrix.len();
632
633        for i in 0..num_states {
634            for j in (i + 1)..num_states {
635                entanglement_score += quantum_state.entanglement_matrix[i][j].abs();
636            }
637        }
638
639        entanglement_score / (num_states * (num_states - 1) / 2) as f32
640    }
641
642    fn compute_interference_pattern(&self, quantum_state: &QuantumState) -> f32 {
643        let mut interference = 0.0;
644
645        for i in 0..quantum_state.amplitudes.len() {
646            let amplitude = quantum_state.amplitudes[i];
647            let phase = quantum_state.phases[i];
648            interference += amplitude * phase.cos();
649        }
650
651        interference / quantum_state.amplitudes.len() as f32
652    }
653
654    fn compute_quantum_confidence(
655        &self,
656        quantum_state: &QuantumState,
657        measured_states: &[usize],
658    ) -> f32 {
659        if measured_states.is_empty() {
660            return 0.0;
661        }
662
663        let measured_probability: f32 = measured_states
664            .iter()
665            .map(|&i| quantum_state.probabilities[i])
666            .sum();
667
668        // Confidence based on measurement certainty
669        let max_probability = quantum_state
670            .probabilities
671            .iter()
672            .max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
673            .unwrap_or(&0.0);
674
675        (measured_probability * max_probability).sqrt()
676    }
677
678    fn generate_quantum_fluctuation(&self, temperature: f32) -> f32 {
679        // Simulate quantum fluctuation using thermal noise with proper Gaussian distribution
680        let mut rng = self.rng.write().expect("rng lock should not be poisoned");
681
682        // Use proper normal distribution for quantum fluctuations
683        let normal = Normal::new(0.0, temperature.sqrt()).unwrap_or_else(|_| {
684            Normal::new(0.0, 1.0).expect("fallback normal distribution parameters are valid")
685        });
686        normal.sample(&mut *rng)
687    }
688
689    #[allow(deprecated)]
690    fn generate_random(&self) -> f32 {
691        // Use proper random number generator
692        let mut rng = self.rng.write().expect("rng lock should not be poisoned");
693        rng.gen_range(0.0..1.0)
694    }
695}
696
697/// Statistics for quantum search operations
698#[derive(Debug, Clone, Serialize, Deserialize)]
699pub struct QuantumSearchStatistics {
700    pub total_searches: usize,
701    pub avg_quantum_probability: f32,
702    pub avg_entanglement_score: f32,
703    pub avg_quantum_confidence: f32,
704    pub superposition_states: usize,
705    pub entanglement_strength: f32,
706}
707
708#[cfg(test)]
709mod tests {
710    use super::*;
711
712    #[test]
713    fn test_quantum_state_creation() {
714        let quantum_state = QuantumState::new(8);
715        assert_eq!(quantum_state.amplitudes.len(), 8);
716        assert_eq!(quantum_state.phases.len(), 8);
717        assert_eq!(quantum_state.entanglement_matrix.len(), 8);
718        assert_eq!(quantum_state.probabilities.len(), 8);
719    }
720
721    #[test]
722    fn test_quantum_superposition() {
723        let mut quantum_state = QuantumState::new(4);
724        let config = QuantumSearchConfig::default();
725
726        quantum_state.apply_superposition(&config);
727
728        // Check that amplitudes are normalized
729        let norm: f32 = quantum_state.amplitudes.iter().map(|a| a.powi(2)).sum();
730        assert!((norm - 1.0).abs() < 1e-6);
731    }
732
733    #[test]
734    fn test_quantum_entanglement() {
735        let mut quantum_state = QuantumState::new(4);
736        let config = QuantumSearchConfig::default();
737
738        quantum_state.create_entanglement(&config);
739
740        // Check that entanglement matrix is symmetric
741        for i in 0..4 {
742            for j in 0..4 {
743                assert_eq!(
744                    quantum_state.entanglement_matrix[i][j],
745                    quantum_state.entanglement_matrix[j][i]
746                );
747            }
748        }
749    }
750
751    #[tokio::test]
752    async fn test_quantum_vector_search() {
753        let quantum_search = QuantumVectorSearch::with_seed(QuantumSearchConfig::default(), 42);
754
755        let query_vector = Vector::new(vec![1.0, 0.0, 0.0]);
756        let candidates = vec![
757            ("vec1".to_string(), Vector::new(vec![0.9, 0.1, 0.0])),
758            ("vec2".to_string(), Vector::new(vec![0.0, 1.0, 0.0])),
759            ("vec3".to_string(), Vector::new(vec![0.8, 0.0, 0.6])),
760        ];
761
762        let results = quantum_search
763            .quantum_similarity_search(&query_vector, &candidates, 2)
764            .await
765            .unwrap();
766
767        assert_eq!(results.len(), 2);
768        assert!(results[0].similarity >= results[1].similarity);
769        assert!(results[0].quantum_confidence >= 0.0);
770        assert!(results[0].quantum_confidence <= 1.0);
771    }
772
773    #[tokio::test]
774    async fn test_parallel_quantum_vector_search() {
775        let quantum_search = QuantumVectorSearch::with_seed(QuantumSearchConfig::default(), 42);
776
777        let query_vector = Vector::new(vec![1.0, 0.0, 0.0]);
778        let candidates = vec![
779            ("vec1".to_string(), Vector::new(vec![0.9, 0.1, 0.0])),
780            ("vec2".to_string(), Vector::new(vec![0.0, 1.0, 0.0])),
781            ("vec3".to_string(), Vector::new(vec![0.8, 0.0, 0.6])),
782            ("vec4".to_string(), Vector::new(vec![0.7, 0.7, 0.0])),
783            ("vec5".to_string(), Vector::new(vec![0.5, 0.5, 0.7])),
784        ];
785
786        let results = quantum_search
787            .parallel_quantum_similarity_search(&query_vector, &candidates, 3)
788            .await
789            .unwrap();
790
791        assert_eq!(results.len(), 3);
792        assert!(results[0].similarity >= results[1].similarity);
793        assert!(results[1].similarity >= results[2].similarity);
794        assert!(results[0].quantum_confidence >= 0.0);
795        assert!(results[0].quantum_confidence <= 1.0);
796    }
797
798    #[test]
799    fn test_quantum_amplitude_amplification() {
800        let quantum_search = QuantumVectorSearch::with_default_config();
801        let mut quantum_state = QuantumState::new(8);
802
803        let result = quantum_search.quantum_amplitude_amplification(0.5, &mut quantum_state, 3);
804        assert!(result.is_ok());
805
806        // Check that amplitudes are still normalized
807        let norm: f32 = quantum_state.amplitudes.iter().map(|a| a.powi(2)).sum();
808        assert!((norm - 1.0).abs() < 1e-6);
809    }
810
811    #[test]
812    fn test_quantum_annealing() {
813        let quantum_search = QuantumVectorSearch::with_default_config();
814
815        // Simple quadratic cost function
816        let cost_fn = |state: &[f32]| -> f32 { state.iter().map(|x| (x - 0.5).powi(2)).sum() };
817
818        let initial_state = vec![0.0, 1.0, 0.2];
819        let temperature_schedule = vec![1.0, 0.5, 0.1];
820
821        let result = quantum_search.quantum_annealing_optimization(
822            cost_fn,
823            &initial_state,
824            &temperature_schedule,
825        );
826        assert!(result.is_ok());
827
828        let optimized_state = result.unwrap();
829        assert_eq!(optimized_state.len(), initial_state.len());
830    }
831
832    #[test]
833    fn test_quantum_tunneling() {
834        let mut quantum_state = QuantumState::new(8);
835        let tunneling_states = quantum_state.quantum_tunneling(0.8);
836
837        // Should return some states that can tunnel
838        assert!(tunneling_states.len() <= 8);
839
840        // Check all returned states are valid indices
841        for state in tunneling_states {
842            assert!(state < 8);
843        }
844    }
845
846    #[test]
847    fn test_quantum_measurement() {
848        let mut quantum_state = QuantumState::new(4);
849        let config = QuantumSearchConfig::default();
850
851        // Set up some probability distribution
852        quantum_state.amplitudes = vec![0.6, 0.4, 0.3, 0.5];
853        quantum_state.normalize();
854
855        let measured_states = quantum_state.measure(&config);
856
857        // Should return states above threshold
858        assert!(!measured_states.is_empty());
859        for state in measured_states {
860            assert!(state < 4);
861        }
862    }
863
864    #[test]
865    fn test_enhanced_quantum_tunneling() {
866        let mut quantum_state = QuantumState::new(8);
867
868        // Set up initial state
869        quantum_state.amplitudes = vec![0.3, 0.4, 0.2, 0.5, 0.1, 0.6, 0.3, 0.4];
870        quantum_state.normalize();
871
872        // Create barrier profile (higher values = stronger barriers)
873        let barrier_profile = vec![0.9, 0.1, 0.8, 0.2, 0.7, 0.3, 0.6, 0.4];
874
875        let tunneling_result = quantum_state.enhanced_quantum_tunneling(&barrier_profile);
876        assert!(tunneling_result.is_ok());
877
878        let tunneling_states = tunneling_result.unwrap();
879
880        // Should return some states that can tunnel (those with lower barriers)
881        assert!(!tunneling_states.is_empty());
882
883        // Check all returned states are valid indices
884        for state in tunneling_states {
885            assert!(state < 8);
886        }
887    }
888
889    #[test]
890    fn test_quantum_statistics() {
891        let quantum_search = QuantumVectorSearch::with_default_config();
892        let stats = quantum_search.get_quantum_statistics();
893
894        assert_eq!(stats.total_searches, 0);
895        assert_eq!(stats.superposition_states, 64);
896        assert_eq!(stats.entanglement_strength, 0.7);
897    }
898}