1use std::f64::consts::PI;
2use super::schrodinger::Complex;
3use super::entanglement::QubitState;
4
5pub type Qubit = QubitState;
7
8#[derive(Clone, Debug)]
10pub struct QuantumRegister {
11 pub n_qubits: usize,
12 pub state: Vec<Complex>,
13}
14
15impl QuantumRegister {
16 pub fn new(n_qubits: usize) -> Self {
17 let size = 1 << n_qubits;
18 let mut state = vec![Complex::zero(); size];
19 state[0] = Complex::one(); Self { n_qubits, state }
21 }
22
23 pub fn from_state(n_qubits: usize, state: Vec<Complex>) -> Self {
24 Self { n_qubits, state }
25 }
26
27 pub fn size(&self) -> usize {
28 self.state.len()
29 }
30
31 pub fn norm_sq(&self) -> f64 {
32 self.state.iter().map(|c| c.norm_sq()).sum()
33 }
34
35 pub fn normalize(&mut self) {
36 let n = self.norm_sq().sqrt();
37 if n > 1e-30 {
38 for c in &mut self.state {
39 *c = *c / n;
40 }
41 }
42 }
43}
44
45#[derive(Clone, Debug)]
47pub struct QuantumGate {
48 pub matrix: Vec<Vec<Complex>>,
49 pub n_qubits: usize,
50 pub name: String,
51}
52
53impl QuantumGate {
54 pub fn new(matrix: Vec<Vec<Complex>>, n_qubits: usize, name: &str) -> Self {
55 Self { matrix, n_qubits, name: name.to_string() }
56 }
57
58 pub fn dim(&self) -> usize {
59 self.matrix.len()
60 }
61}
62
63pub fn hadamard() -> QuantumGate {
66 let s = 1.0 / 2.0_f64.sqrt();
67 QuantumGate::new(
68 vec![
69 vec![Complex::new(s, 0.0), Complex::new(s, 0.0)],
70 vec![Complex::new(s, 0.0), Complex::new(-s, 0.0)],
71 ],
72 1,
73 "H",
74 )
75}
76
77pub fn pauli_x() -> QuantumGate {
78 QuantumGate::new(
79 vec![
80 vec![Complex::zero(), Complex::one()],
81 vec![Complex::one(), Complex::zero()],
82 ],
83 1,
84 "X",
85 )
86}
87
88pub fn pauli_y() -> QuantumGate {
89 QuantumGate::new(
90 vec![
91 vec![Complex::zero(), Complex::new(0.0, -1.0)],
92 vec![Complex::new(0.0, 1.0), Complex::zero()],
93 ],
94 1,
95 "Y",
96 )
97}
98
99pub fn pauli_z() -> QuantumGate {
100 QuantumGate::new(
101 vec![
102 vec![Complex::one(), Complex::zero()],
103 vec![Complex::zero(), Complex::new(-1.0, 0.0)],
104 ],
105 1,
106 "Z",
107 )
108}
109
110pub fn phase(theta: f64) -> QuantumGate {
111 QuantumGate::new(
112 vec![
113 vec![Complex::one(), Complex::zero()],
114 vec![Complex::zero(), Complex::from_polar(1.0, theta)],
115 ],
116 1,
117 "P",
118 )
119}
120
121pub fn t_gate() -> QuantumGate {
122 phase(PI / 4.0)
123}
124
125pub fn cnot() -> QuantumGate {
126 QuantumGate::new(
127 vec![
128 vec![Complex::one(), Complex::zero(), Complex::zero(), Complex::zero()],
129 vec![Complex::zero(), Complex::one(), Complex::zero(), Complex::zero()],
130 vec![Complex::zero(), Complex::zero(), Complex::zero(), Complex::one()],
131 vec![Complex::zero(), Complex::zero(), Complex::one(), Complex::zero()],
132 ],
133 2,
134 "CNOT",
135 )
136}
137
138pub fn swap() -> QuantumGate {
139 QuantumGate::new(
140 vec![
141 vec![Complex::one(), Complex::zero(), Complex::zero(), Complex::zero()],
142 vec![Complex::zero(), Complex::zero(), Complex::one(), Complex::zero()],
143 vec![Complex::zero(), Complex::one(), Complex::zero(), Complex::zero()],
144 vec![Complex::zero(), Complex::zero(), Complex::zero(), Complex::one()],
145 ],
146 2,
147 "SWAP",
148 )
149}
150
151pub fn toffoli() -> QuantumGate {
152 let mut m = vec![vec![Complex::zero(); 8]; 8];
153 for i in 0..6 {
154 m[i][i] = Complex::one();
155 }
156 m[6][7] = Complex::one();
158 m[7][6] = Complex::one();
159 QuantumGate::new(m, 3, "Toffoli")
160}
161
162pub fn apply_gate(register: &QuantumRegister, gate: &QuantumGate, target_qubits: &[usize]) -> QuantumRegister {
164 let n = register.n_qubits;
165 let size = register.size();
166 let g_dim = gate.dim();
167
168 let mut new_state = vec![Complex::zero(); size];
169
170 for i in 0..size {
171 if register.state[i].norm_sq() < 1e-30 {
172 continue;
173 }
174
175 let target_val = extract_bits(i, target_qubits, n);
177
178 for out_val in 0..g_dim {
180 let coeff = gate.matrix[out_val][target_val];
181 if coeff.norm_sq() < 1e-30 {
182 continue;
183 }
184 let j = replace_bits(i, target_qubits, out_val, n);
186 new_state[j] += register.state[i] * coeff;
187 }
188 }
189
190 QuantumRegister::from_state(n, new_state)
191}
192
193fn extract_bits(state_idx: usize, positions: &[usize], n_qubits: usize) -> usize {
195 let mut val = 0;
196 for (k, &pos) in positions.iter().enumerate() {
197 let bit = (state_idx >> (n_qubits - 1 - pos)) & 1;
198 val |= bit << (positions.len() - 1 - k);
199 }
200 val
201}
202
203fn replace_bits(state_idx: usize, positions: &[usize], new_val: usize, n_qubits: usize) -> usize {
205 let mut result = state_idx;
206 for (k, &pos) in positions.iter().enumerate() {
207 let bit = (new_val >> (positions.len() - 1 - k)) & 1;
208 let mask = 1 << (n_qubits - 1 - pos);
209 if bit == 1 {
210 result |= mask;
211 } else {
212 result &= !mask;
213 }
214 }
215 result
216}
217
218pub fn measure_register(register: &QuantumRegister, rng_val: f64) -> (Vec<u8>, QuantumRegister) {
220 let n = register.n_qubits;
221 let size = register.size();
222 let mut cumulative = 0.0;
223 let mut outcome = 0;
224
225 for i in 0..size {
226 cumulative += register.state[i].norm_sq();
227 if rng_val < cumulative {
228 outcome = i;
229 break;
230 }
231 if i == size - 1 {
232 outcome = i;
233 }
234 }
235
236 let bits: Vec<u8> = (0..n)
237 .map(|bit| ((outcome >> (n - 1 - bit)) & 1) as u8)
238 .collect();
239
240 let mut new_state = vec![Complex::zero(); size];
241 new_state[outcome] = Complex::one();
242 let new_reg = QuantumRegister::from_state(n, new_state);
243
244 (bits, new_reg)
245}
246
247pub fn measure_qubit_in_register(
249 register: &QuantumRegister,
250 qubit_index: usize,
251 rng_val: f64,
252) -> (u8, QuantumRegister) {
253 let n = register.n_qubits;
254 let size = register.size();
255 let mask = 1 << (n - 1 - qubit_index);
256
257 let p0: f64 = (0..size)
259 .filter(|&i| (i & mask) == 0)
260 .map(|i| register.state[i].norm_sq())
261 .sum();
262
263 let outcome = if rng_val < p0 { 0u8 } else { 1u8 };
264
265 let mut new_state = vec![Complex::zero(); size];
267 let norm = if outcome == 0 { p0.sqrt() } else { (1.0 - p0).sqrt() };
268
269 for i in 0..size {
270 let bit = if (i & mask) == 0 { 0 } else { 1 };
271 if bit == outcome {
272 new_state[i] = register.state[i] / norm.max(1e-30);
273 }
274 }
275
276 (outcome, QuantumRegister::from_state(n, new_state))
277}
278
279#[derive(Clone, Debug)]
281pub struct QuantumCircuit {
282 pub gates: Vec<(QuantumGate, Vec<usize>)>,
283}
284
285impl QuantumCircuit {
286 pub fn new() -> Self {
287 Self { gates: Vec::new() }
288 }
289
290 pub fn add_gate(&mut self, gate: QuantumGate, targets: Vec<usize>) {
291 self.gates.push((gate, targets));
292 }
293}
294
295pub fn execute(circuit: &QuantumCircuit, register: &QuantumRegister) -> QuantumRegister {
297 let mut reg = register.clone();
298 for (gate, targets) in &circuit.gates {
299 reg = apply_gate(®, gate, targets);
300 }
301 reg
302}
303
304pub fn deutsch_jozsa(n_qubits: usize, oracle_fn: &dyn Fn(usize) -> u8) -> bool {
308 let n = n_qubits;
309 let total = n + 1; let size = 1 << total;
311
312 let mut reg = QuantumRegister::new(total);
314 reg.state[0] = Complex::zero();
316 reg.state[1] = Complex::one(); for i in 0..total {
320 reg = apply_gate(®, &hadamard(), &[i]);
321 }
322
323 let mut new_state = vec![Complex::zero(); size];
325 for i in 0..size {
326 let input = i >> 1; let output_bit = i & 1; let f_x = oracle_fn(input % (1 << n)) as usize;
329 let new_output = output_bit ^ f_x;
330 let j = (input << 1) | new_output;
331 new_state[j] += reg.state[i];
332 }
333 reg.state = new_state;
334
335 for i in 0..n {
337 reg = apply_gate(®, &hadamard(), &[i]);
338 }
339
340 let input_zero_prob: f64 = (0..size)
342 .filter(|&i| (i >> 1) == 0)
343 .map(|i| reg.state[i].norm_sq())
344 .sum();
345
346 input_zero_prob < 0.5
348}
349
350pub fn grover_search(oracle: &dyn Fn(usize) -> bool, n_qubits: usize, iterations: usize) -> usize {
354 let size = 1 << n_qubits;
355 let mut reg = QuantumRegister::new(n_qubits);
356
357 for i in 0..n_qubits {
359 reg = apply_gate(®, &hadamard(), &[i]);
360 }
361
362 for _ in 0..iterations {
363 for i in 0..size {
365 if oracle(i) {
366 reg.state[i] = -reg.state[i];
367 }
368 }
369
370 for q in 0..n_qubits {
373 reg = apply_gate(®, &hadamard(), &[q]);
374 }
375 for i in 1..size {
377 reg.state[i] = -reg.state[i];
378 }
379 for q in 0..n_qubits {
381 reg = apply_gate(®, &hadamard(), &[q]);
382 }
383 }
384
385 let mut max_prob = 0.0;
387 let mut max_idx = 0;
388 for i in 0..size {
389 let prob = reg.state[i].norm_sq();
390 if prob > max_prob {
391 max_prob = prob;
392 max_idx = i;
393 }
394 }
395 max_idx
396}
397
398pub fn qft(register: &QuantumRegister) -> QuantumRegister {
400 let n = register.n_qubits;
401 let mut reg = register.clone();
402
403 for i in 0..n {
404 reg = apply_gate(®, &hadamard(), &[i]);
406
407 for j in (i + 1)..n {
409 let k = j - i;
410 let theta = PI / (1 << k) as f64;
411 let cp = controlled_phase(theta);
413 reg = apply_gate(®, &cp, &[j, i]);
414 }
415 }
416
417 for i in 0..n / 2 {
419 reg = apply_gate(®, &swap(), &[i, n - 1 - i]);
420 }
421
422 reg
423}
424
425fn controlled_phase(theta: f64) -> QuantumGate {
426 QuantumGate::new(
427 vec![
428 vec![Complex::one(), Complex::zero(), Complex::zero(), Complex::zero()],
429 vec![Complex::zero(), Complex::one(), Complex::zero(), Complex::zero()],
430 vec![Complex::zero(), Complex::zero(), Complex::one(), Complex::zero()],
431 vec![Complex::zero(), Complex::zero(), Complex::zero(), Complex::from_polar(1.0, theta)],
432 ],
433 2,
434 "CP",
435 )
436}
437
438pub struct CircuitRenderer;
440
441impl CircuitRenderer {
442 pub fn render(circuit: &QuantumCircuit, n_qubits: usize) -> Vec<String> {
443 let mut lines: Vec<String> = (0..n_qubits)
444 .map(|i| format!("q{}: ", i))
445 .collect();
446
447 for (gate, targets) in &circuit.gates {
448 let max_target = targets.iter().copied().max().unwrap_or(0);
449 let min_target = targets.iter().copied().min().unwrap_or(0);
450
451 for q in 0..n_qubits {
453 if targets.contains(&q) {
454 if targets.len() == 1 {
455 lines[q].push_str(&format!("[{}]", gate.name));
456 } else if q == targets[0] {
457 lines[q].push_str(&format!("[{}]", gate.name));
458 } else {
459 lines[q].push_str(" * ");
460 }
461 } else if q > min_target && q < max_target {
462 lines[q].push_str(" | ");
463 } else {
464 lines[q].push_str("---");
465 }
466 }
467
468 for q in 0..n_qubits {
470 lines[q].push('-');
471 }
472 }
473
474 lines
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use super::*;
481
482 #[test]
483 fn test_hadamard_squared_is_identity() {
484 let mut reg = QuantumRegister::new(1);
485 reg = apply_gate(®, &hadamard(), &[0]);
486 reg = apply_gate(®, &hadamard(), &[0]);
487 assert!((reg.state[0].re - 1.0).abs() < 1e-10);
489 assert!(reg.state[1].norm() < 1e-10);
490 }
491
492 #[test]
493 fn test_hadamard_creates_superposition() {
494 let mut reg = QuantumRegister::new(1);
495 reg = apply_gate(®, &hadamard(), &[0]);
496 let s = 1.0 / 2.0_f64.sqrt();
497 assert!((reg.state[0].re - s).abs() < 1e-10);
498 assert!((reg.state[1].re - s).abs() < 1e-10);
499 }
500
501 #[test]
502 fn test_pauli_x_flips() {
503 let mut reg = QuantumRegister::new(1);
504 reg = apply_gate(®, &pauli_x(), &[0]);
505 assert!(reg.state[0].norm() < 1e-10);
506 assert!((reg.state[1].re - 1.0).abs() < 1e-10);
507 }
508
509 #[test]
510 fn test_cnot_entangles() {
511 let mut reg = QuantumRegister::new(2);
513 reg = apply_gate(®, &hadamard(), &[0]);
514 reg = apply_gate(®, &cnot(), &[0, 1]);
515
516 let s = 1.0 / 2.0_f64.sqrt();
517 assert!((reg.state[0].re - s).abs() < 1e-10, "|00>: {}", reg.state[0].re); assert!(reg.state[1].norm() < 1e-10); assert!(reg.state[2].norm() < 1e-10); assert!((reg.state[3].re - s).abs() < 1e-10, "|11>: {}", reg.state[3].re); }
522
523 #[test]
524 fn test_measure_register() {
525 let mut reg = QuantumRegister::new(2);
526 reg.state[0] = Complex::zero();
528 reg.state[1] = Complex::one();
529
530 let (bits, _) = measure_register(®, 0.5);
531 assert_eq!(bits, vec![0, 1]);
532 }
533
534 #[test]
535 fn test_measure_qubit() {
536 let mut reg = QuantumRegister::new(2);
537 reg = apply_gate(®, &hadamard(), &[0]);
538 let (outcome, new_reg) = measure_qubit_in_register(®, 0, 0.3);
541 let norm = new_reg.norm_sq();
542 assert!((norm - 1.0).abs() < 1e-6, "Post-measurement norm: {}", norm);
543 }
544
545 #[test]
546 fn test_swap_gate() {
547 let mut reg = QuantumRegister::new(2);
548 reg.state[0] = Complex::zero();
550 reg.state[1] = Complex::one();
551
552 reg = apply_gate(®, &swap(), &[0, 1]);
553 assert!(reg.state[1].norm() < 1e-10);
555 assert!((reg.state[2].re - 1.0).abs() < 1e-10);
556 }
557
558 #[test]
559 fn test_circuit_execution() {
560 let mut circuit = QuantumCircuit::new();
561 circuit.add_gate(hadamard(), vec![0]);
562 circuit.add_gate(cnot(), vec![0, 1]);
563
564 let reg = QuantumRegister::new(2);
565 let result = execute(&circuit, ®);
566
567 let s = 1.0 / 2.0_f64.sqrt();
568 assert!((result.state[0].re - s).abs() < 1e-10);
569 assert!((result.state[3].re - s).abs() < 1e-10);
570 }
571
572 #[test]
573 fn test_deutsch_jozsa_constant() {
574 let is_balanced = deutsch_jozsa(2, &|_x| 0);
576 assert!(!is_balanced, "Constant function should not be balanced");
577 }
578
579 #[test]
580 fn test_deutsch_jozsa_balanced() {
581 let is_balanced = deutsch_jozsa(2, &|x| (x & 1) as u8);
583 assert!(is_balanced, "Balanced function should be detected");
584 }
585
586 #[test]
587 fn test_grover_search() {
588 let target = 3;
590 let result = grover_search(&|x| x == target, 2, 1);
591 assert_eq!(result, target, "Grover should find target {}, got {}", target, result);
592 }
593
594 #[test]
595 fn test_grover_larger() {
596 let target = 5;
598 let n = 3;
599 let iterations = ((PI / 4.0) * (8.0_f64).sqrt()).floor() as usize;
600 let result = grover_search(&|x| x == target, n, iterations);
601 assert_eq!(result, target, "Grover should find {}, got {}", target, result);
602 }
603
604 #[test]
605 fn test_qft_basic() {
606 let reg = QuantumRegister::new(2);
608 let result = qft(®);
609 let expected = 0.5; for i in 0..4 {
611 assert!(
612 (result.state[i].norm_sq() - expected).abs() < 0.1,
613 "QFT |0>[{}] prob: {}",
614 i,
615 result.state[i].norm_sq()
616 );
617 }
618 }
619
620 #[test]
621 fn test_qft_preserves_norm() {
622 let mut reg = QuantumRegister::new(3);
623 reg = apply_gate(®, &hadamard(), &[0]);
624 reg = apply_gate(®, &pauli_x(), &[1]);
625 let norm_before = reg.norm_sq();
626 let result = qft(®);
627 let norm_after = result.norm_sq();
628 assert!((norm_after - norm_before).abs() < 0.1, "QFT norm: {} -> {}", norm_before, norm_after);
629 }
630
631 #[test]
632 fn test_toffoli() {
633 let mut reg = QuantumRegister::new(3);
635 reg.state[0] = Complex::zero();
637 reg.state[6] = Complex::one(); reg = apply_gate(®, &toffoli(), &[0, 1, 2]);
639 assert!((reg.state[7].re - 1.0).abs() < 1e-10);
641 }
642
643 #[test]
644 fn test_circuit_renderer() {
645 let mut circuit = QuantumCircuit::new();
646 circuit.add_gate(hadamard(), vec![0]);
647 circuit.add_gate(cnot(), vec![0, 1]);
648 let lines = CircuitRenderer::render(&circuit, 2);
649 assert_eq!(lines.len(), 2);
650 assert!(lines[0].contains("H"));
651 }
652
653 #[test]
654 fn test_phase_gate() {
655 let mut reg = QuantumRegister::new(1);
656 reg.state[0] = Complex::zero();
658 reg.state[1] = Complex::one();
659 reg = apply_gate(®, &phase(PI), &[0]);
660 assert!((reg.state[1].re - (-1.0)).abs() < 1e-10);
662 }
663}