1use ndarray::{Array1, Array2};
15use num_complex::Complex64;
16use std::f64::consts::PI;
17
18pub struct QuantumPhaseEstimation {
22 precision_bits: usize,
24 unitary: Array2<Complex64>,
26 target_qubits: usize,
28}
29
30impl QuantumPhaseEstimation {
31 pub fn new(precision_bits: usize, unitary: Array2<Complex64>) -> Self {
33 let target_qubits = (unitary.shape()[0] as f64).log2() as usize;
34
35 Self {
36 precision_bits,
37 unitary,
38 target_qubits,
39 }
40 }
41
42 fn apply_controlled_u_power(&self, state: &mut [Complex64], control: usize, k: usize) {
44 let power = 1 << k;
45 let n = self.target_qubits;
46 let dim = 1 << n;
47
48 let mut u_power = Array2::eye(dim);
50 let mut temp = self.unitary.clone();
51 let mut p = power;
52
53 while p > 0 {
54 if p & 1 == 1 {
55 u_power = u_power.dot(&temp);
56 }
57 temp = temp.dot(&temp);
58 p >>= 1;
59 }
60
61 let total_qubits = self.precision_bits + self.target_qubits;
63 let state_dim = 1 << total_qubits;
64
65 for basis in 0..state_dim {
66 if (basis >> (total_qubits - control - 1)) & 1 == 1 {
68 let _target_basis = basis & ((1 << n) - 1);
70
71 let mut new_amplitudes = vec![Complex64::new(0.0, 0.0); dim];
73 for (i, amp) in new_amplitudes.iter_mut().enumerate() {
74 let state_idx = (basis & !((1 << n) - 1)) | i;
75 *amp = state[state_idx];
76 }
77
78 let result = u_power.dot(&Array1::from(new_amplitudes));
79
80 for i in 0..dim {
81 let state_idx = (basis & !((1 << n) - 1)) | i;
82 state[state_idx] = result[i];
83 }
84 }
85 }
86 }
87
88 fn apply_inverse_qft(&self, state: &mut [Complex64]) {
90 let n = self.precision_bits;
91 let total_qubits = n + self.target_qubits;
92
93 for j in (0..n).rev() {
95 self.apply_hadamard(state, j, total_qubits);
97
98 for k in (0..j).rev() {
100 let angle = -PI / (1 << (j - k)) as f64;
101 self.apply_controlled_phase(state, k, j, angle, total_qubits);
102 }
103 }
104
105 for i in 0..n / 2 {
107 self.swap_qubits(state, i, n - 1 - i, total_qubits);
108 }
109 }
110
111 fn apply_hadamard(&self, state: &mut [Complex64], qubit: usize, total_qubits: usize) {
113 let h = 1.0 / std::f64::consts::SQRT_2;
114 let dim = 1 << total_qubits;
115
116 for i in 0..dim {
117 if (i >> (total_qubits - qubit - 1)) & 1 == 0 {
118 let j = i | (1 << (total_qubits - qubit - 1));
119 let a = state[i];
120 let b = state[j];
121 state[i] = h * (a + b);
122 state[j] = h * (a - b);
123 }
124 }
125 }
126
127 fn apply_controlled_phase(
129 &self,
130 state: &mut [Complex64],
131 control: usize,
132 target: usize,
133 angle: f64,
134 total_qubits: usize,
135 ) {
136 let phase = Complex64::new(angle.cos(), angle.sin());
137
138 for (i, amp) in state.iter_mut().enumerate() {
139 let control_bit = (i >> (total_qubits - control - 1)) & 1;
140 let target_bit = (i >> (total_qubits - target - 1)) & 1;
141
142 if control_bit == 1 && target_bit == 1 {
143 *amp *= phase;
144 }
145 }
146 }
147
148 fn swap_qubits(&self, state: &mut [Complex64], q1: usize, q2: usize, total_qubits: usize) {
150 let dim = 1 << total_qubits;
151
152 for i in 0..dim {
153 let bit1 = (i >> (total_qubits - q1 - 1)) & 1;
154 let bit2 = (i >> (total_qubits - q2 - 1)) & 1;
155
156 if bit1 != bit2 {
157 let j = i ^ (1 << (total_qubits - q1 - 1)) ^ (1 << (total_qubits - q2 - 1));
158 if i < j {
159 state.swap(i, j);
160 }
161 }
162 }
163 }
164
165 pub fn estimate_phase(&self, eigenstate: Vec<Complex64>) -> f64 {
167 let total_qubits = self.precision_bits + self.target_qubits;
168 let state_dim = 1 << total_qubits;
169 let mut state = vec![Complex64::new(0.0, 0.0); state_dim];
170
171 for i in 0..(1 << self.target_qubits) {
173 if i < eigenstate.len() {
174 state[i] = eigenstate[i];
175 }
176 }
177
178 for j in 0..self.precision_bits {
180 self.apply_hadamard(&mut state, j, total_qubits);
181 }
182
183 for j in 0..self.precision_bits {
185 self.apply_controlled_u_power(&mut state, j, self.precision_bits - j - 1);
186 }
187
188 self.apply_inverse_qft(&mut state);
190
191 let mut max_prob = 0.0;
193 let mut measured_value = 0;
194
195 for (i, amp) in state.iter().enumerate() {
196 let precision_bits_value = i >> self.target_qubits;
197 let prob = amp.norm_sqr();
198
199 if prob > max_prob {
200 max_prob = prob;
201 measured_value = precision_bits_value;
202 }
203 }
204
205 measured_value as f64 / (1 << self.precision_bits) as f64
207 }
208}
209
210pub struct QuantumCounting {
214 pub n_items: usize,
216 pub precision_bits: usize,
218 pub oracle: Box<dyn Fn(usize) -> bool>,
220}
221
222impl QuantumCounting {
223 pub fn new(n_items: usize, precision_bits: usize, oracle: Box<dyn Fn(usize) -> bool>) -> Self {
225 Self {
226 n_items,
227 precision_bits,
228 oracle,
229 }
230 }
231
232 fn build_grover_operator(&self) -> Array2<Complex64> {
234 let n = self.n_items;
235 let mut grover = Array2::zeros((n, n));
236
237 for i in 0..n {
239 if (self.oracle)(i) {
240 grover[[i, i]] = Complex64::new(-1.0, 0.0);
241 } else {
242 grover[[i, i]] = Complex64::new(1.0, 0.0);
243 }
244 }
245
246 let s_amplitude = 1.0 / (n as f64).sqrt();
248 let diffusion =
249 Array2::from_elem((n, n), Complex64::new(2.0 * s_amplitude * s_amplitude, 0.0))
250 - Array2::<Complex64>::eye(n);
251
252 -diffusion.dot(&grover)
254 }
255
256 pub fn count(&self) -> f64 {
258 let grover = self.build_grover_operator();
260
261 let qpe = QuantumPhaseEstimation::new(self.precision_bits, grover);
263
264 let n = self.n_items;
266 let amplitude = Complex64::new(1.0 / (n as f64).sqrt(), 0.0);
267 let eigenstate = vec![amplitude; n];
268
269 let phase = qpe.estimate_phase(eigenstate);
271
272 let theta = phase * PI;
275 let sin_theta = theta.sin();
276 sin_theta * sin_theta * n as f64
277 }
278}
279
280pub struct QuantumAmplitudeEstimation {
284 pub state_prep: Array2<Complex64>,
286 pub oracle: Array2<Complex64>,
288 pub precision_bits: usize,
290}
291
292impl QuantumAmplitudeEstimation {
293 pub fn new(
295 state_prep: Array2<Complex64>,
296 oracle: Array2<Complex64>,
297 precision_bits: usize,
298 ) -> Self {
299 Self {
300 state_prep,
301 oracle,
302 precision_bits,
303 }
304 }
305
306 fn build_q_operator(&self) -> Array2<Complex64> {
308 let n = self.state_prep.shape()[0];
309 let identity = Array2::<Complex64>::eye(n);
310
311 let reflection_good = &identity - &self.oracle * 2.0;
313
314 let zero_state = Array1::zeros(n);
316 let mut zero_state_vec = zero_state.to_vec();
317 zero_state_vec[0] = Complex64::new(1.0, 0.0);
318
319 let initial = self.state_prep.dot(&Array1::from(zero_state_vec));
320 let mut reflection_initial = Array2::zeros((n, n));
321
322 for i in 0..n {
323 for j in 0..n {
324 reflection_initial[[i, j]] = 2.0 * initial[i] * initial[j].conj();
325 }
326 }
327 reflection_initial -= &identity;
328
329 -reflection_initial.dot(&reflection_good)
331 }
332
333 pub fn estimate(&self) -> f64 {
335 let q_operator = self.build_q_operator();
337
338 let qpe = QuantumPhaseEstimation::new(self.precision_bits, q_operator);
340
341 let n = self.state_prep.shape()[0];
343 let mut zero_state = vec![Complex64::new(0.0, 0.0); n];
344 zero_state[0] = Complex64::new(1.0, 0.0);
345 let initial_state = self.state_prep.dot(&Array1::from(zero_state));
346
347 let phase = qpe.estimate_phase(initial_state.to_vec());
349
350 let theta = phase * PI;
353 theta.sin().abs()
354 }
355}
356
357pub fn quantum_counting_example() {
359 println!("Quantum Counting Example");
360 println!("=======================");
361
362 let oracle = Box::new(|x: usize| x % 3 == 0 && x > 0);
364
365 let counter = QuantumCounting::new(16, 4, oracle);
366 let count = counter.count();
367
368 println!("Counting numbers divisible by 3 in range 1-15:");
369 println!("Estimated count: {:.1}", count);
370 println!("Actual count: 5 (3, 6, 9, 12, 15)");
371 println!("Error: {:.1}", (count - 5.0).abs());
372}
373
374pub fn amplitude_estimation_example() {
376 println!("\nAmplitude Estimation Example");
377 println!("============================");
378
379 let n = 8;
381 let state_prep = Array2::from_elem((n, n), Complex64::new(1.0 / (n as f64).sqrt(), 0.0));
382
383 let mut oracle = Array2::zeros((n, n));
385 oracle[[2, 2]] = Complex64::new(1.0, 0.0);
386 oracle[[5, 5]] = Complex64::new(1.0, 0.0);
387
388 let qae = QuantumAmplitudeEstimation::new(state_prep, oracle, 4);
389 let amplitude = qae.estimate();
390
391 println!("Estimating amplitude of marked states (2 and 5) in uniform superposition:");
392 println!("Estimated amplitude: {:.3}", amplitude);
393 println!("Actual amplitude: {:.3}", (2.0 / n as f64).sqrt());
394 println!("Error: {:.3}", (amplitude - (2.0 / n as f64).sqrt()).abs());
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test]
402 fn test_phase_estimation_basic() {
403 let phase = PI / 4.0;
406 let u = Array2::from_shape_vec(
407 (2, 2),
408 vec![
409 Complex64::new(1.0, 0.0),
410 Complex64::new(0.0, 0.0),
411 Complex64::new(0.0, 0.0),
412 Complex64::new(phase.cos(), phase.sin()),
413 ],
414 )
415 .unwrap();
416
417 let qpe = QuantumPhaseEstimation::new(4, u);
418
419 let eigenstate = vec![Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0)];
421 let estimated = qpe.estimate_phase(eigenstate);
422
423 assert!((0.0..=1.0).contains(&estimated));
425 }
426
427 #[test]
428 fn test_quantum_counting_simple() {
429 let oracle = Box::new(|x: usize| x == 2);
432 let counter = QuantumCounting::new(4, 4, oracle);
433 let count = counter.count();
434
435 assert!(count >= 0.0);
437 }
438}