use crate::error::{QuantumError, QuantumResult};
use crate::gates::controlled::apply_cnot;
use crate::gates::hadamard::gate_h;
use crate::gates::parametric::gate_ry;
use crate::statevec::apply_1q::{apply_1q_controlled, apply_1q_inplace};
use crate::statevec::state::StateVector;
pub fn prepare_ghz(n_qubits: usize) -> QuantumResult<StateVector> {
if n_qubits == 0 || n_qubits > 30 {
return Err(QuantumError::InvalidQubitCount { n: n_qubits });
}
let mut sv = StateVector::new_zero_state(n_qubits)?;
apply_1q_inplace(&mut sv, 0, &gate_h())?;
for q in 1..n_qubits {
apply_cnot(&mut sv, q - 1, q)?;
}
Ok(sv)
}
pub fn prepare_w(n_qubits: usize) -> QuantumResult<StateVector> {
if n_qubits == 0 || n_qubits > 30 {
return Err(QuantumError::InvalidQubitCount { n: n_qubits });
}
let mut sv = StateVector::new_zero_state(n_qubits)?;
if n_qubits == 1 {
apply_1q_inplace(&mut sv, 0, &crate::gates::pauli::gate_x())?;
return Ok(sv);
}
apply_1q_inplace(&mut sv, 0, &crate::gates::pauli::gate_x())?;
for k in 0..n_qubits - 1 {
let remaining = (n_qubits - k) as f32;
let theta = 2.0 * (1.0 / remaining).sqrt().acos();
apply_1q_controlled(&mut sv, k, k + 1, &gate_ry(theta))?;
apply_cnot(&mut sv, k + 1, k)?;
}
Ok(sv)
}
pub fn bit_flip_encode(state: &mut StateVector) -> QuantumResult<()> {
if state.n_qubits != 3 {
return Err(QuantumError::InvalidQubitCount { n: state.n_qubits });
}
apply_cnot(state, 0, 1)?;
apply_cnot(state, 0, 2)?;
Ok(())
}
fn bit_flip_syndrome(state: &StateVector) -> (bool, bool) {
let mut p_s0 = [0.0f32; 2];
let mut p_s1 = [0.0f32; 2];
for (idx, amp) in state.amps.iter().enumerate() {
let pr = amp.norm_sqr();
if pr == 0.0 {
continue;
}
let b0 = idx & 1;
let b1 = (idx >> 1) & 1;
let b2 = (idx >> 2) & 1;
p_s0[b0 ^ b1] += pr;
p_s1[b1 ^ b2] += pr;
}
(p_s0[1] > p_s0[0], p_s1[1] > p_s1[0])
}
pub fn bit_flip_correct(state: &mut StateVector) -> QuantumResult<Option<usize>> {
if state.n_qubits != 3 {
return Err(QuantumError::InvalidQubitCount { n: state.n_qubits });
}
let (s0, s1) = bit_flip_syndrome(state);
let correct_qubit = match (s0, s1) {
(false, false) => None,
(true, false) => Some(0),
(true, true) => Some(1),
(false, true) => Some(2),
};
if let Some(q) = correct_qubit {
apply_1q_inplace(state, q, &crate::gates::pauli::gate_x())?;
}
Ok(correct_qubit)
}
pub fn phase_flip_encode(state: &mut StateVector) -> QuantumResult<()> {
bit_flip_encode(state)?;
for q in 0..3 {
apply_1q_inplace(state, q, &gate_h())?;
}
Ok(())
}
pub fn phase_flip_correct(state: &mut StateVector) -> QuantumResult<Option<usize>> {
if state.n_qubits != 3 {
return Err(QuantumError::InvalidQubitCount { n: state.n_qubits });
}
for q in 0..3 {
apply_1q_inplace(state, q, &gate_h())?;
}
let corrected = bit_flip_correct(state)?;
for q in 0..3 {
apply_1q_inplace(state, q, &gate_h())?;
}
Ok(corrected)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::gates::pauli::{gate_x, gate_z};
const INV_SQRT2: f32 = std::f32::consts::FRAC_1_SQRT_2;
#[test]
fn ghz_two_qubit_is_bell() {
let sv = prepare_ghz(2).expect("valid 2-qubit GHZ state");
assert!((sv.amps[0].re - INV_SQRT2).abs() < 1e-5);
assert!((sv.amps[3].re - INV_SQRT2).abs() < 1e-5);
assert!(sv.amps[1].norm() < 1e-5);
assert!(sv.amps[2].norm() < 1e-5);
}
#[test]
fn ghz_three_qubit_amplitudes() {
let sv = prepare_ghz(3).expect("valid 3-qubit GHZ state");
assert!((sv.amps[0].re - INV_SQRT2).abs() < 1e-5, "|000>");
assert!((sv.amps[7].re - INV_SQRT2).abs() < 1e-5, "|111>");
for i in 1..7 {
assert!(sv.amps[i].norm() < 1e-5, "amp[{i}]={:?}", sv.amps[i]);
}
}
#[test]
fn ghz_norm_preserved() {
for n in 1..=5 {
let sv = prepare_ghz(n).expect("valid n-qubit GHZ state");
assert!((sv.norm_sq() - 1.0).abs() < 1e-4, "n={n}");
}
}
#[test]
fn ghz_invalid_qubit_count() {
assert!(prepare_ghz(0).is_err());
assert!(prepare_ghz(31).is_err());
}
#[test]
fn w_state_single_excitation_amplitudes() {
let sv = prepare_w(3).expect("valid 3-qubit W state");
let amp = (1.0f32 / 3.0).sqrt();
for &i in &[1usize, 2, 4] {
assert!(
(sv.amps[i].norm() - amp).abs() < 1e-4,
"amp[{i}]={:?}",
sv.amps[i]
);
}
for &i in &[0usize, 3, 5, 6, 7] {
assert!(sv.amps[i].norm() < 1e-4, "amp[{i}]={:?}", sv.amps[i]);
}
}
#[test]
fn w_state_norm_is_one() {
for n in 1..=5 {
let sv = prepare_w(n).expect("valid n-qubit W state");
assert!((sv.norm_sq() - 1.0).abs() < 1e-4, "n={n}");
}
}
#[test]
fn w_state_exactly_one_excitation() {
let sv = prepare_w(4).expect("valid 4-qubit W state");
for (idx, amp) in sv.amps.iter().enumerate() {
if amp.norm() > 1e-4 {
assert_eq!(idx.count_ones(), 1, "idx={idx:b} has weight ≠ 1");
}
}
}
#[test]
fn w_state_uniform_marginals() {
let n = 4;
let sv = prepare_w(n).expect("valid 4-qubit W state");
for q in 0..n {
let p1 = sv
.measure_prob(q, true)
.expect("valid qubit index for probability measurement");
assert!((p1 - 1.0 / n as f32).abs() < 1e-4, "q={q} p1={p1}");
}
}
#[test]
fn bit_flip_encode_logical_one() {
let mut sv = StateVector::new_zero_state(3).expect("valid 3-qubit zero state");
apply_1q_inplace(&mut sv, 0, &gate_x()).expect("X gate on qubit 0 succeeds");
bit_flip_encode(&mut sv).expect("bit-flip encoding succeeds on 3-qubit state");
assert!((sv.amps[7].norm() - 1.0).abs() < 1e-5, "expected |111>");
}
#[test]
fn bit_flip_corrects_single_error_on_each_qubit() {
for err_q in 0..3 {
let mut sv = StateVector::new_zero_state(3).expect("valid 3-qubit zero state");
apply_1q_inplace(&mut sv, 0, &gate_x()).expect("X gate on qubit 0 succeeds");
bit_flip_encode(&mut sv).expect("bit-flip encoding succeeds on 3-qubit state");
apply_1q_inplace(&mut sv, err_q, &gate_x())
.expect("X error injection on target qubit succeeds");
let corrected = bit_flip_correct(&mut sv).expect("bit-flip correction succeeds");
assert_eq!(corrected, Some(err_q), "error on {err_q}");
assert!((sv.amps[7].norm() - 1.0).abs() < 1e-5, "err_q={err_q}");
}
}
#[test]
fn bit_flip_no_error_detected() {
let mut sv = StateVector::new_zero_state(3).expect("valid 3-qubit zero state");
bit_flip_encode(&mut sv).expect("bit-flip encoding of |000> succeeds"); let corrected =
bit_flip_correct(&mut sv).expect("bit-flip correction on clean state succeeds");
assert_eq!(corrected, None);
assert!((sv.amps[0].norm() - 1.0).abs() < 1e-5);
}
#[test]
fn bit_flip_preserves_superposition_after_correction() {
let mut sv = StateVector::new_zero_state(3).expect("valid 3-qubit zero state");
apply_1q_inplace(&mut sv, 0, &gate_h()).expect("Hadamard gate on qubit 0 succeeds");
bit_flip_encode(&mut sv).expect("bit-flip encoding of superposition succeeds");
let before0 = sv.amps[0];
let before7 = sv.amps[7];
apply_1q_inplace(&mut sv, 1, &gate_x()).expect("X error injection on qubit 1 succeeds");
let corrected =
bit_flip_correct(&mut sv).expect("bit-flip correction restores superposition");
assert_eq!(corrected, Some(1));
assert!((sv.amps[0] - before0).norm() < 1e-5);
assert!((sv.amps[7] - before7).norm() < 1e-5);
}
#[test]
fn bit_flip_wrong_qubit_count_errors() {
let mut sv = StateVector::new_zero_state(2).expect("valid 2-qubit zero state");
assert!(bit_flip_encode(&mut sv).is_err());
assert!(bit_flip_correct(&mut sv).is_err());
}
#[test]
fn phase_flip_corrects_single_z_error() {
for err_q in 0..3 {
let mut sv = StateVector::new_zero_state(3).expect("valid 3-qubit zero state");
apply_1q_inplace(&mut sv, 0, &gate_x()).expect("X gate on qubit 0 succeeds");
phase_flip_encode(&mut sv).expect("phase-flip encoding succeeds on 3-qubit state");
let encoded = sv.clone();
apply_1q_inplace(&mut sv, err_q, &gate_z())
.expect("Z error injection on target qubit succeeds");
let corrected = phase_flip_correct(&mut sv).expect("phase-flip correction succeeds");
assert_eq!(corrected, Some(err_q), "z-error on {err_q}");
for i in 0..8 {
assert!(
(sv.amps[i] - encoded.amps[i]).norm() < 1e-4,
"err_q={err_q} amp[{i}]"
);
}
}
}
#[test]
fn phase_flip_no_error_detected() {
let mut sv = StateVector::new_zero_state(3).expect("valid 3-qubit zero state");
phase_flip_encode(&mut sv).expect("phase-flip encoding succeeds");
let corrected =
phase_flip_correct(&mut sv).expect("phase-flip correction on clean state succeeds");
assert_eq!(corrected, None);
}
}