1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! Quantum teleportation.
//!
//! Teleportation moves an unknown qubit state from qubit 0 to qubit 2 using a
//! shared Bell pair (qubits 1 and 2) and two bits of classical communication.
//! The circuit contains mid-circuit measurements and classically-controlled
//! corrections ($X$ and $Z$), so it exercises the full instruction set.
use crateCircuit;
use crateComplex64;
/// Returns the core teleportation circuit: 3 qubits, 2 classical bits.
///
/// - Qubit 0: the message qubit (caller prepares this before running).
/// - Qubits 1, 2: Alice and Bob's halves of the Bell pair.
/// - Classical bit 0: outcome of measuring qubit 0.
/// - Classical bit 1: outcome of measuring qubit 1.
///
/// After the circuit runs, qubit 2 holds whatever state qubit 0 was in at the
/// start, regardless of measurement outcomes. Use [`teleport_state`] for the
/// common case of preparing and teleporting in one step.
///
/// ## Protocol
///
/// 1. Prepare Bell pair on (1, 2): H on 1 then CNOT(1,2).
/// 2. Bell measurement on (0, 1): CNOT(0,1), H on 0, then measure both.
/// 3. Feed-forward: X on qubit 2 if classical bit 1 is set; Z on qubit 2 if
/// classical bit 0 is set.
///
/// # Examples
///
/// ```
/// use everett::prelude::*;
/// use everett::algorithms::teleport;
///
/// // teleport the |+> state
/// let circuit = teleport::teleport_state(
/// Complex64::new(1.0 / 2f64.sqrt(), 0.0),
/// Complex64::new(1.0 / 2f64.sqrt(), 0.0),
/// );
/// let exec = StateVectorBackend::run(&circuit).unwrap();
/// // qubit 2 should now be |+>; applying H and checking |0> verifies it.
/// // (see integration tests for the full correctness check)
/// ```
/// Returns a 3-qubit circuit that first prepares qubit 0 in
/// $\alpha|0\rangle + \beta|1\rangle$ and then teleports it to qubit 2.
///
/// The message is prepared using a single custom gate built from the supplied
/// amplitudes. The caller is responsible for ensuring $|\alpha|^2 + |\beta|^2
/// \approx 1$.
///
/// # Examples
///
/// ```
/// use everett::prelude::*;
/// use everett::algorithms::teleport;
///
/// // teleport |1>
/// let circuit = teleport::teleport_state(Complex64::ZERO, Complex64::ONE);
/// let exec = StateVectorBackend::run(&circuit).unwrap();
/// // qubit 2 should be in state |1>, with Bloch vector (0, 0, -1).
/// let [x, y, z] = exec.state().bloch_vector(2);
/// assert!(x.abs() < 1e-10 && y.abs() < 1e-10);
/// assert!((z + 1.0).abs() < 1e-10);
/// ```