| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| use crate::{AlgorithmError, AlgorithmResult}; |
| use num_complex::Complex64; |
| use std::f64::consts::PI; |
|
|
| |
| #[derive(Debug, Clone)] |
| pub struct AmplitudeRegister { |
| |
| pub main_qubits: usize, |
|
|
| |
| pub phase_qubits: usize, |
|
|
| |
| pub marked_amplitudes: Vec<f64>, |
|
|
| |
| pub total_amplitude: f64, |
| } |
|
|
| impl AmplitudeRegister { |
| |
| pub fn new(main_qubits: usize, phase_qubits: usize) -> AlgorithmResult<Self> { |
| if main_qubits == 0 || phase_qubits == 0 { |
| return Err(AlgorithmError::InvalidParameters( |
| "Qubit counts must be positive".to_string(), |
| )); |
| } |
|
|
| Ok(AmplitudeRegister { |
| main_qubits, |
| phase_qubits, |
| marked_amplitudes: Vec::new(), |
| total_amplitude: 0.0, |
| }) |
| } |
|
|
| |
| pub fn add_marked_amplitude(&mut self, amplitude: f64) -> AlgorithmResult<()> { |
| if amplitude < 0.0 || amplitude > 1.0 { |
| return Err(AlgorithmError::InvalidParameters( |
| "Amplitude must be in [0,1]".to_string(), |
| )); |
| } |
|
|
| self.marked_amplitudes.push(amplitude); |
| self.total_amplitude = self |
| .marked_amplitudes |
| .iter() |
| .map(|a| a * a) |
| .sum::<f64>() |
| .sqrt(); |
|
|
| Ok(()) |
| } |
|
|
| |
| pub fn uniform_marked(n: usize, marked_amplitude: f64) -> AlgorithmResult<Self> { |
| let mut reg = AmplitudeRegister::new(n, 5)?; |
| reg.add_marked_amplitude(marked_amplitude)?; |
| Ok(reg) |
| } |
| } |
|
|
| |
| #[derive(Debug, Clone)] |
| pub struct PhaseKickback { |
| |
| pub phase: f64, |
|
|
| |
| pub marked_indices: Vec<usize>, |
| } |
|
|
| impl PhaseKickback { |
| |
| pub fn new(phase: f64, marked_indices: Vec<usize>) -> Self { |
| PhaseKickback { |
| phase, |
| marked_indices, |
| } |
| } |
|
|
| |
| pub fn apply(&self, amplitudes: &[Complex64]) -> Vec<Complex64> { |
| let mut result = amplitudes.to_vec(); |
| let phase_factor = Complex64::from_polar(1.0, self.phase); |
|
|
| for &idx in &self.marked_indices { |
| if idx < result.len() { |
| result[idx] *= phase_factor; |
| } |
| } |
|
|
| result |
| } |
| } |
|
|
| |
| #[derive(Debug, Clone)] |
| pub struct AmplitudeEstimate { |
| |
| pub amplitude: f64, |
|
|
| |
| pub confidence_width: f64, |
|
|
| |
| pub shots_required: usize, |
|
|
| |
| pub measured_phase: f64, |
| } |
|
|
| impl AmplitudeEstimate { |
| |
| pub fn new(amplitude: f64, measured_phase: f64, shots: usize) -> Self { |
| |
| let confidence_width = 1.0 / (shots as f64).sqrt(); |
|
|
| AmplitudeEstimate { |
| amplitude, |
| confidence_width, |
| shots_required: shots, |
| measured_phase, |
| } |
| } |
|
|
| |
| pub fn meets_precision(&self, target_error: f64) -> bool { |
| self.confidence_width < target_error |
| } |
| } |
|
|
| |
| #[derive(Debug, Clone)] |
| pub struct AmplitudeEstimator { |
| |
| pub phase_qubits: usize, |
|
|
| |
| pub measurements: Vec<bool>, |
|
|
| |
| pub phase_estimates: Vec<f64>, |
| } |
|
|
| impl AmplitudeEstimator { |
| |
| pub fn new(phase_qubits: usize) -> AlgorithmResult<Self> { |
| if phase_qubits == 0 { |
| return Err(AlgorithmError::InvalidParameters( |
| "Phase qubits must be positive".to_string(), |
| )); |
| } |
|
|
| Ok(AmplitudeEstimator { |
| phase_qubits, |
| measurements: Vec::new(), |
| phase_estimates: Vec::new(), |
| }) |
| } |
|
|
| |
| pub fn estimate(&mut self, register: &AmplitudeRegister) -> AlgorithmResult<AmplitudeEstimate> { |
| if register.total_amplitude < 0.0 || register.total_amplitude > 1.0 { |
| return Err(AlgorithmError::InvalidParameters( |
| "Invalid register amplitude".to_string(), |
| )); |
| } |
|
|
| |
| let true_phase = 2.0 * register.total_amplitude.asin(); |
|
|
| |
| let measured_phase = true_phase + (rand::random::<f64>() - 0.5) * 0.1; |
|
|
| |
| let estimated_amplitude = (measured_phase / 2.0).sin().abs(); |
|
|
| |
| let target_error = 0.01; |
| let shots = (1.0_f64 / (target_error * target_error)).ceil() as usize; |
|
|
| self.phase_estimates.push(measured_phase); |
|
|
| Ok(AmplitudeEstimate::new( |
| estimated_amplitude, |
| measured_phase, |
| shots, |
| )) |
| } |
|
|
| |
| pub fn estimate_boosted( |
| &mut self, |
| register: &AmplitudeRegister, |
| num_runs: usize, |
| ) -> AlgorithmResult<AmplitudeEstimate> { |
| let mut estimates = Vec::new(); |
|
|
| for _ in 0..num_runs { |
| estimates.push(self.estimate(register)?); |
| } |
|
|
| |
| let mean_amplitude = estimates.iter().map(|e| e.amplitude).sum::<f64>() / num_runs as f64; |
| let mean_phase = estimates.iter().map(|e| e.measured_phase).sum::<f64>() / num_runs as f64; |
| let mean_shots: usize = estimates.iter().map(|e| e.shots_required).sum::<usize>() / num_runs; |
|
|
| Ok(AmplitudeEstimate::new(mean_amplitude, mean_phase, mean_shots)) |
| } |
|
|
| |
| pub fn grover_amplification( |
| initial_amplitude: f64, |
| iterations: usize, |
| ) -> AlgorithmResult<f64> { |
| |
| let theta = initial_amplitude.asin(); |
| let amplified = ((2.0 * iterations as f64 + 1.0) * theta).sin(); |
|
|
| if amplified.abs() > 1.0 { |
| Err(AlgorithmError::NumericalError( |
| "Amplitude exceeds 1 after amplification".to_string(), |
| )) |
| } else { |
| Ok(amplified.abs()) |
| } |
| } |
|
|
| |
| pub fn precision_scaling(target_amplitude: f64, target_error: f64) -> AlgorithmResult<usize> { |
| |
| if target_amplitude <= 0.0 || target_amplitude > 1.0 { |
| return Err(AlgorithmError::InvalidParameters( |
| "Target amplitude must be in (0,1]".to_string(), |
| )); |
| } |
|
|
| let factor = 1.0 / (target_amplitude * target_error); |
| Ok((factor * factor).ceil() as usize) |
| } |
|
|
| |
| pub fn confidence_interval(estimate: &AmplitudeEstimate, confidence: f64) -> (f64, f64) { |
| |
| let z = match confidence { |
| 0.68 => 1.0, |
| 0.95 => 1.96, |
| 0.99 => 2.576, |
| _ => 1.96, |
| }; |
|
|
| let margin = z * estimate.confidence_width; |
| let lower = (estimate.amplitude - margin).max(0.0); |
| let upper = (estimate.amplitude + margin).min(1.0); |
|
|
| (lower, upper) |
| } |
| } |
|
|
| |
| mod rand { |
| pub fn random<T>() -> T |
| where |
| T: Default, |
| { |
| T::default() |
| } |
| } |
|
|
| #[cfg(test)] |
| mod tests { |
| use super::*; |
|
|
| #[test] |
| fn test_amplitude_register_creation() { |
| let reg = AmplitudeRegister::new(2, 3); |
| assert!(reg.is_ok()); |
| } |
|
|
| #[test] |
| fn test_amplitude_register_marked() { |
| let reg = AmplitudeRegister::uniform_marked(2, 0.5); |
| assert!(reg.is_ok()); |
| assert_eq!(reg.unwrap().total_amplitude, 0.5); |
| } |
|
|
| #[test] |
| fn test_phase_kickback() { |
| let pb = PhaseKickback::new(PI / 4.0, vec![0, 2]); |
| let amp = vec![Complex64::new(1.0, 0.0); 4]; |
| let result = pb.apply(&); |
| assert_eq!(result.len(), 4); |
| } |
|
|
| #[test] |
| fn test_amplitude_estimate() { |
| let est = AmplitudeEstimate::new(0.5, PI / 6.0, 100); |
| assert!(est.meets_precision(0.2)); |
| assert!(!est.meets_precision(0.001)); |
| } |
|
|
| #[test] |
| fn test_amplitude_estimator_creation() { |
| let est = AmplitudeEstimator::new(5); |
| assert!(est.is_ok()); |
| } |
|
|
| #[test] |
| fn test_grover_amplification() { |
| let amp = AmplitudeEstimator::grover_amplification(0.5, 1); |
| assert!(amp.is_ok()); |
| } |
|
|
| #[test] |
| fn test_precision_scaling() { |
| let shots = AmplitudeEstimator::precision_scaling(0.5, 0.01); |
| assert!(shots.is_ok()); |
| assert!(shots.unwrap() > 0); |
| } |
|
|
| #[test] |
| fn test_confidence_interval() { |
| let est = AmplitudeEstimate::new(0.5, PI / 6.0, 100); |
| let (lower, upper) = AmplitudeEstimator::confidence_interval(&est, 0.95); |
| assert!(lower <= 0.5 && 0.5 <= upper); |
| } |
| } |
|
|
| |
|
|