oxicuda_quantum/algorithm/
superdense.rs1use crate::error::QuantumResult;
24use crate::gates::controlled::apply_cnot;
25use crate::gates::hadamard::gate_h;
26use crate::gates::pauli::{gate_x, gate_z};
27use crate::statevec::apply_1q::apply_1q_inplace;
28use crate::statevec::state::StateVector;
29
30#[derive(Debug, Clone)]
32pub struct SuperdenseResult {
33 pub decoded: (bool, bool),
35 pub probability: f32,
37}
38
39pub fn superdense_decode(b0: bool, b1: bool) -> QuantumResult<SuperdenseResult> {
48 let mut sv = StateVector::new_zero_state(2)?;
50 apply_1q_inplace(&mut sv, 0, &gate_h())?;
51 apply_cnot(&mut sv, 0, 1)?;
52
53 if b1 {
56 apply_1q_inplace(&mut sv, 0, &gate_x())?;
57 }
58 if b0 {
59 apply_1q_inplace(&mut sv, 0, &gate_z())?;
60 }
61
62 apply_cnot(&mut sv, 0, 1)?;
64 apply_1q_inplace(&mut sv, 0, &gate_h())?;
65
66 let mut best_idx = 0usize;
68 let mut best = f32::NEG_INFINITY;
69 for (i, a) in sv.amps.iter().enumerate() {
70 let p = a.norm_sqr();
71 if p > best {
72 best = p;
73 best_idx = i;
74 }
75 }
76
77 let decoded_b0 = (best_idx & 1) != 0;
79 let decoded_b1 = (best_idx & 2) != 0;
80
81 Ok(SuperdenseResult {
82 decoded: (decoded_b0, decoded_b1),
83 probability: best,
84 })
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn decodes_zero_zero() {
93 let res = superdense_decode(false, false)
94 .expect("superdense decode of (false, false) should succeed");
95 assert_eq!(res.decoded, (false, false));
96 assert!(res.probability > 0.999, "p={}", res.probability);
97 }
98
99 #[test]
100 fn decodes_zero_one() {
101 let res = superdense_decode(false, true)
102 .expect("superdense decode of (false, true) should succeed");
103 assert_eq!(res.decoded, (false, true));
104 assert!(res.probability > 0.999, "p={}", res.probability);
105 }
106
107 #[test]
108 fn decodes_one_zero() {
109 let res = superdense_decode(true, false)
110 .expect("superdense decode of (true, false) should succeed");
111 assert_eq!(res.decoded, (true, false));
112 assert!(res.probability > 0.999, "p={}", res.probability);
113 }
114
115 #[test]
116 fn decodes_one_one() {
117 let res = superdense_decode(true, true)
118 .expect("superdense decode of (true, true) should succeed");
119 assert_eq!(res.decoded, (true, true));
120 assert!(res.probability > 0.999, "p={}", res.probability);
121 }
122
123 #[test]
124 fn all_messages_round_trip() {
125 for &(b0, b1) in &[(false, false), (false, true), (true, false), (true, true)] {
127 let res = superdense_decode(b0, b1)
128 .expect("superdense decode should succeed for all two-bit messages");
129 assert_eq!(res.decoded, (b0, b1), "failed for ({b0},{b1})");
130 assert!(res.probability > 0.999, "({b0},{b1}) p={}", res.probability);
131 }
132 }
133
134 #[test]
135 fn encodings_are_orthogonal() {
136 let mut seen = std::collections::HashSet::new();
138 for &(b0, b1) in &[(false, false), (false, true), (true, false), (true, true)] {
139 let res = superdense_decode(b0, b1)
140 .expect("superdense decode should succeed for orthogonality check");
141 let idx = usize::from(res.decoded.0) | (usize::from(res.decoded.1) << 1);
142 assert!(seen.insert(idx), "collision at message ({b0},{b1})");
143 }
144 assert_eq!(seen.len(), 4);
145 }
146
147 #[test]
148 fn probability_is_deterministic() {
149 let a = superdense_decode(true, false)
150 .expect("superdense decode (true, false) first call should succeed");
151 let b = superdense_decode(true, false)
152 .expect("superdense decode (true, false) second call should succeed");
153 assert_eq!(a.decoded, b.decoded);
154 assert!((a.probability - b.probability).abs() < 1e-7);
155 }
156
157 #[test]
158 fn probability_finite_and_in_range() {
159 let res = superdense_decode(true, true)
160 .expect("superdense decode of (true, true) should succeed");
161 assert!(res.probability.is_finite());
162 assert!((0.0..=1.0 + 1e-5).contains(&res.probability));
163 }
164
165 #[test]
166 fn decoded_state_is_normalized() {
167 let mut sv = StateVector::new_zero_state(2).expect("valid 2-qubit zero state");
169 apply_1q_inplace(&mut sv, 0, &gate_h()).expect("H gate on qubit 0 should succeed");
170 apply_cnot(&mut sv, 0, 1).expect("CNOT on qubits 0 to 1 should succeed");
171 apply_1q_inplace(&mut sv, 0, &gate_x()).expect("X gate on qubit 0 should succeed");
172 apply_1q_inplace(&mut sv, 0, &gate_z()).expect("Z gate on qubit 0 should succeed");
173 apply_cnot(&mut sv, 0, 1).expect("CNOT on qubits 0 to 1 (decode step) should succeed");
174 apply_1q_inplace(&mut sv, 0, &gate_h())
175 .expect("H gate on qubit 0 (decode step) should succeed");
176 assert!((sv.norm_sq() - 1.0).abs() < 1e-5, "norm={}", sv.norm_sq());
177 }
178}