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