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(
397            candidate_vectors.len()
398                / std::thread::available_parallelism()
399                    .map(|n| n.get())
400                    .unwrap_or(1),
401            1,
402        );
403
404        let results: Result<Vec<Vec<QuantumSearchResult>>> = candidate_vectors
405            .par_chunks(chunk_size)
406            .map(|chunk| -> Result<Vec<QuantumSearchResult>> {
407                let mut chunk_results = Vec::new();
408                let mut quantum_state = QuantumState::new(self.config.superposition_states);
409                quantum_state.apply_superposition(&self.config);
410                quantum_state.create_entanglement(&self.config);
411
412                for (candidate_id, candidate_vector) in chunk {
413                    let candidate_f32 = candidate_vector.as_f32();
414
415                    // Classical similarity computation with SIMD optimization
416                    let classical_similarity =
417                        self.compute_cosine_similarity(&query_f32, &candidate_f32);
418
419                    // Apply quantum interference
420                    quantum_state.apply_interference(classical_similarity);
421
422                    // Quantum tunneling if enabled
423                    let tunneling_advantage = if self.config.enable_tunneling {
424                        let barrier_height =
425                            vec![1.0 - classical_similarity; self.config.superposition_states];
426                        match quantum_state.enhanced_quantum_tunneling(&barrier_height) {
427                            Ok(tunneling_states) => {
428                                if tunneling_states.is_empty() {
429                                    0.0
430                                } else {
431                                    tunneling_states.len() as f32
432                                        / self.config.superposition_states as f32
433                                }
434                            }
435                            Err(_) => 0.0,
436                        }
437                    } else {
438                        0.0
439                    };
440
441                    // Measure quantum state
442                    let measured_states = quantum_state.measure(&self.config);
443
444                    // Compute quantum-enhanced metrics
445                    let quantum_probability = quantum_state.probabilities.iter().sum::<f32>()
446                        / quantum_state.probabilities.len() as f32;
447                    let entanglement_score = self.compute_entanglement_score(&quantum_state);
448                    let interference_pattern = self.compute_interference_pattern(&quantum_state);
449                    let quantum_confidence =
450                        self.compute_quantum_confidence(&quantum_state, &measured_states);
451
452                    // Enhanced quantum similarity score with better weighting
453                    let quantum_enhancement = quantum_probability * 0.3
454                        + entanglement_score * 0.1
455                        + tunneling_advantage * 0.2;
456                    let quantum_similarity = classical_similarity * (1.0 + quantum_enhancement);
457
458                    chunk_results.push(QuantumSearchResult {
459                        vector_id: candidate_id.clone(),
460                        similarity: quantum_similarity,
461                        quantum_probability,
462                        entanglement_score,
463                        interference_pattern,
464                        tunneling_advantage,
465                        quantum_confidence,
466                    });
467                }
468
469                Ok(chunk_results)
470            })
471            .collect();
472
473        let mut all_results: Vec<QuantumSearchResult> = results?.into_iter().flatten().collect();
474
475        // Sort by quantum-enhanced similarity
476        all_results.sort_by(|a, b| {
477            b.similarity
478                .partial_cmp(&a.similarity)
479                .unwrap_or(std::cmp::Ordering::Equal)
480        });
481        all_results.truncate(k);
482
483        // Store search result in history
484        {
485            let mut history = self
486                .search_history
487                .write()
488                .expect("search_history lock should not be poisoned");
489            history.extend(all_results.clone());
490        }
491
492        info!(
493            "Parallel quantum similarity search completed with {} results",
494            all_results.len()
495        );
496        Ok(all_results)
497    }
498
499    /// Perform quantum amplitude amplification for targeted search
500    pub fn quantum_amplitude_amplification(
501        &self,
502        target_similarity: f32,
503        quantum_state: &mut QuantumState,
504        iterations: usize,
505    ) -> Result<()> {
506        for iteration in 0..iterations {
507            // Oracle operation: mark target states
508            for (i, &prob) in quantum_state.probabilities.iter().enumerate() {
509                if prob >= target_similarity {
510                    quantum_state.amplitudes[i] *= -1.0; // Phase flip
511                }
512            }
513
514            // Diffusion operation: inversion about average
515            let average_amplitude: f32 = quantum_state.amplitudes.iter().sum::<f32>()
516                / quantum_state.amplitudes.len() as f32;
517
518            for amplitude in &mut quantum_state.amplitudes {
519                *amplitude = 2.0 * average_amplitude - *amplitude;
520            }
521
522            quantum_state.normalize();
523
524            debug!(
525                "Amplitude amplification iteration {} completed",
526                iteration + 1
527            );
528        }
529
530        Ok(())
531    }
532
533    /// Quantum annealing for optimization landscape exploration
534    pub fn quantum_annealing_optimization(
535        &self,
536        cost_function: impl Fn(&[f32]) -> f32,
537        initial_state: &[f32],
538        temperature_schedule: &[f32],
539    ) -> Result<Vec<f32>> {
540        let mut current_state = initial_state.to_vec();
541        let mut best_state = current_state.clone();
542        let mut best_cost = cost_function(&current_state);
543
544        for &temperature in temperature_schedule {
545            // Quantum fluctuations
546            for item in &mut current_state {
547                let quantum_fluctuation = self.generate_quantum_fluctuation(temperature);
548                *item += quantum_fluctuation;
549            }
550
551            let current_cost = cost_function(&current_state);
552
553            // Quantum acceptance probability
554            let accept_prob = if current_cost < best_cost {
555                1.0
556            } else {
557                (-(current_cost - best_cost) / temperature).exp()
558            };
559
560            if self.generate_random() < accept_prob {
561                best_state = current_state.clone();
562                best_cost = current_cost;
563            }
564
565            debug!(
566                "Quantum annealing: temperature={}, cost={}",
567                temperature, current_cost
568            );
569        }
570
571        Ok(best_state)
572    }
573
574    /// Get quantum search statistics
575    pub fn get_quantum_statistics(&self) -> QuantumSearchStatistics {
576        let history = self
577            .search_history
578            .read()
579            .expect("search_history lock should not be poisoned");
580
581        let total_searches = history.len();
582        let avg_quantum_probability = if total_searches > 0 {
583            history.iter().map(|r| r.quantum_probability).sum::<f32>() / total_searches as f32
584        } else {
585            0.0
586        };
587
588        let avg_entanglement_score = if total_searches > 0 {
589            history.iter().map(|r| r.entanglement_score).sum::<f32>() / total_searches as f32
590        } else {
591            0.0
592        };
593
594        let avg_quantum_confidence = if total_searches > 0 {
595            history.iter().map(|r| r.quantum_confidence).sum::<f32>() / total_searches as f32
596        } else {
597            0.0
598        };
599
600        QuantumSearchStatistics {
601            total_searches,
602            avg_quantum_probability,
603            avg_entanglement_score,
604            avg_quantum_confidence,
605            superposition_states: self.config.superposition_states,
606            entanglement_strength: self.config.entanglement_strength,
607        }
608    }
609
610    // Helper methods
611
612    fn generate_query_id(&self, vector: &Vector) -> String {
613        use std::collections::hash_map::DefaultHasher;
614        use std::hash::{Hash, Hasher};
615
616        let mut hasher = DefaultHasher::new();
617        for value in vector.as_f32() {
618            value.to_bits().hash(&mut hasher);
619        }
620        format!("quantum_query_{:x}", hasher.finish())
621    }
622
623    fn compute_cosine_similarity(&self, a: &[f32], b: &[f32]) -> f32 {
624        if a.len() != b.len() {
625            return 0.0;
626        }
627
628        // Use SIMD optimization via oxirs-core for better performance
629        // Note: SimdOps provides cosine_distance, so we convert to similarity
630        let cosine_distance = f32::cosine_distance(a, b);
631        1.0 - cosine_distance
632    }
633
634    fn compute_entanglement_score(&self, quantum_state: &QuantumState) -> f32 {
635        let mut entanglement_score = 0.0;
636        let num_states = quantum_state.entanglement_matrix.len();
637
638        for i in 0..num_states {
639            for j in (i + 1)..num_states {
640                entanglement_score += quantum_state.entanglement_matrix[i][j].abs();
641            }
642        }
643
644        entanglement_score / (num_states * (num_states - 1) / 2) as f32
645    }
646
647    fn compute_interference_pattern(&self, quantum_state: &QuantumState) -> f32 {
648        let mut interference = 0.0;
649
650        for i in 0..quantum_state.amplitudes.len() {
651            let amplitude = quantum_state.amplitudes[i];
652            let phase = quantum_state.phases[i];
653            interference += amplitude * phase.cos();
654        }
655
656        interference / quantum_state.amplitudes.len() as f32
657    }
658
659    fn compute_quantum_confidence(
660        &self,
661        quantum_state: &QuantumState,
662        measured_states: &[usize],
663    ) -> f32 {
664        if measured_states.is_empty() {
665            return 0.0;
666        }
667
668        let measured_probability: f32 = measured_states
669            .iter()
670            .map(|&i| quantum_state.probabilities[i])
671            .sum();
672
673        // Confidence based on measurement certainty
674        let max_probability = quantum_state
675            .probabilities
676            .iter()
677            .max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
678            .unwrap_or(&0.0);
679
680        (measured_probability * max_probability).sqrt()
681    }
682
683    fn generate_quantum_fluctuation(&self, temperature: f32) -> f32 {
684        // Simulate quantum fluctuation using thermal noise with proper Gaussian distribution
685        let mut rng = self.rng.write().expect("rng lock should not be poisoned");
686
687        // Use proper normal distribution for quantum fluctuations
688        let normal = Normal::new(0.0, temperature.sqrt()).unwrap_or_else(|_| {
689            Normal::new(0.0, 1.0).expect("fallback normal distribution parameters are valid")
690        });
691        normal.sample(&mut *rng)
692    }
693
694    #[allow(deprecated)]
695    fn generate_random(&self) -> f32 {
696        // Use proper random number generator
697        let mut rng = self.rng.write().expect("rng lock should not be poisoned");
698        rng.random_range(0.0..1.0)
699    }
700}
701
702/// Statistics for quantum search operations
703#[derive(Debug, Clone, Serialize, Deserialize)]
704pub struct QuantumSearchStatistics {
705    pub total_searches: usize,
706    pub avg_quantum_probability: f32,
707    pub avg_entanglement_score: f32,
708    pub avg_quantum_confidence: f32,
709    pub superposition_states: usize,
710    pub entanglement_strength: f32,
711}
712
713#[cfg(test)]
714mod tests {
715    use super::*;
716
717    #[test]
718    fn test_quantum_state_creation() {
719        let quantum_state = QuantumState::new(8);
720        assert_eq!(quantum_state.amplitudes.len(), 8);
721        assert_eq!(quantum_state.phases.len(), 8);
722        assert_eq!(quantum_state.entanglement_matrix.len(), 8);
723        assert_eq!(quantum_state.probabilities.len(), 8);
724    }
725
726    #[test]
727    fn test_quantum_superposition() {
728        let mut quantum_state = QuantumState::new(4);
729        let config = QuantumSearchConfig::default();
730
731        quantum_state.apply_superposition(&config);
732
733        // Check that amplitudes are normalized
734        let norm: f32 = quantum_state.amplitudes.iter().map(|a| a.powi(2)).sum();
735        assert!((norm - 1.0).abs() < 1e-6);
736    }
737
738    #[test]
739    fn test_quantum_entanglement() {
740        let mut quantum_state = QuantumState::new(4);
741        let config = QuantumSearchConfig::default();
742
743        quantum_state.create_entanglement(&config);
744
745        // Check that entanglement matrix is symmetric
746        for i in 0..4 {
747            for j in 0..4 {
748                assert_eq!(
749                    quantum_state.entanglement_matrix[i][j],
750                    quantum_state.entanglement_matrix[j][i]
751                );
752            }
753        }
754    }
755
756    #[tokio::test]
757    async fn test_quantum_vector_search() -> Result<()> {
758        let quantum_search = QuantumVectorSearch::with_seed(QuantumSearchConfig::default(), 42);
759
760        let query_vector = Vector::new(vec![1.0, 0.0, 0.0]);
761        let candidates = vec![
762            ("vec1".to_string(), Vector::new(vec![0.9, 0.1, 0.0])),
763            ("vec2".to_string(), Vector::new(vec![0.0, 1.0, 0.0])),
764            ("vec3".to_string(), Vector::new(vec![0.8, 0.0, 0.6])),
765        ];
766
767        let results = quantum_search
768            .quantum_similarity_search(&query_vector, &candidates, 2)
769            .await?;
770
771        assert_eq!(results.len(), 2);
772        assert!(results[0].similarity >= results[1].similarity);
773        assert!(results[0].quantum_confidence >= 0.0);
774        assert!(results[0].quantum_confidence <= 1.0);
775        Ok(())
776    }
777
778    #[tokio::test]
779    async fn test_parallel_quantum_vector_search() -> Result<()> {
780        let quantum_search = QuantumVectorSearch::with_seed(QuantumSearchConfig::default(), 42);
781
782        let query_vector = Vector::new(vec![1.0, 0.0, 0.0]);
783        let candidates = vec![
784            ("vec1".to_string(), Vector::new(vec![0.9, 0.1, 0.0])),
785            ("vec2".to_string(), Vector::new(vec![0.0, 1.0, 0.0])),
786            ("vec3".to_string(), Vector::new(vec![0.8, 0.0, 0.6])),
787            ("vec4".to_string(), Vector::new(vec![0.7, 0.7, 0.0])),
788            ("vec5".to_string(), Vector::new(vec![0.5, 0.5, 0.7])),
789        ];
790
791        let results = quantum_search
792            .parallel_quantum_similarity_search(&query_vector, &candidates, 3)
793            .await?;
794
795        assert_eq!(results.len(), 3);
796        assert!(results[0].similarity >= results[1].similarity);
797        assert!(results[1].similarity >= results[2].similarity);
798        assert!(results[0].quantum_confidence >= 0.0);
799        assert!(results[0].quantum_confidence <= 1.0);
800        Ok(())
801    }
802
803    #[test]
804    fn test_quantum_amplitude_amplification() {
805        let quantum_search = QuantumVectorSearch::with_default_config();
806        let mut quantum_state = QuantumState::new(8);
807
808        let result = quantum_search.quantum_amplitude_amplification(0.5, &mut quantum_state, 3);
809        assert!(result.is_ok());
810
811        // Check that amplitudes are still normalized
812        let norm: f32 = quantum_state.amplitudes.iter().map(|a| a.powi(2)).sum();
813        assert!((norm - 1.0).abs() < 1e-6);
814    }
815
816    #[test]
817    fn test_quantum_annealing() -> Result<()> {
818        let quantum_search = QuantumVectorSearch::with_default_config();
819
820        // Simple quadratic cost function
821        let cost_fn = |state: &[f32]| -> f32 { state.iter().map(|x| (x - 0.5).powi(2)).sum() };
822
823        let initial_state = vec![0.0, 1.0, 0.2];
824        let temperature_schedule = vec![1.0, 0.5, 0.1];
825
826        let result = quantum_search.quantum_annealing_optimization(
827            cost_fn,
828            &initial_state,
829            &temperature_schedule,
830        );
831        assert!(result.is_ok());
832
833        let optimized_state = result?;
834        assert_eq!(optimized_state.len(), initial_state.len());
835        Ok(())
836    }
837
838    #[test]
839    fn test_quantum_tunneling() {
840        let mut quantum_state = QuantumState::new(8);
841        let tunneling_states = quantum_state.quantum_tunneling(0.8);
842
843        // Should return some states that can tunnel
844        assert!(tunneling_states.len() <= 8);
845
846        // Check all returned states are valid indices
847        for state in tunneling_states {
848            assert!(state < 8);
849        }
850    }
851
852    #[test]
853    fn test_quantum_measurement() {
854        let mut quantum_state = QuantumState::new(4);
855        let config = QuantumSearchConfig::default();
856
857        // Set up some probability distribution
858        quantum_state.amplitudes = vec![0.6, 0.4, 0.3, 0.5];
859        quantum_state.normalize();
860
861        let measured_states = quantum_state.measure(&config);
862
863        // Should return states above threshold
864        assert!(!measured_states.is_empty());
865        for state in measured_states {
866            assert!(state < 4);
867        }
868    }
869
870    #[test]
871    fn test_enhanced_quantum_tunneling() -> Result<()> {
872        let mut quantum_state = QuantumState::new(8);
873
874        // Set up initial state
875        quantum_state.amplitudes = vec![0.3, 0.4, 0.2, 0.5, 0.1, 0.6, 0.3, 0.4];
876        quantum_state.normalize();
877
878        // Create barrier profile (higher values = stronger barriers)
879        let barrier_profile = vec![0.9, 0.1, 0.8, 0.2, 0.7, 0.3, 0.6, 0.4];
880
881        let tunneling_result = quantum_state.enhanced_quantum_tunneling(&barrier_profile);
882        assert!(tunneling_result.is_ok());
883
884        let tunneling_states = tunneling_result?;
885
886        // Should return some states that can tunnel (those with lower barriers)
887        assert!(!tunneling_states.is_empty());
888
889        // Check all returned states are valid indices
890        for state in tunneling_states {
891            assert!(state < 8);
892        }
893        Ok(())
894    }
895
896    #[test]
897    fn test_quantum_statistics() {
898        let quantum_search = QuantumVectorSearch::with_default_config();
899        let stats = quantum_search.get_quantum_statistics();
900
901        assert_eq!(stats.total_searches, 0);
902        assert_eq!(stats.superposition_states, 64);
903        assert_eq!(stats.entanglement_strength, 0.7);
904    }
905}