use super::pauli::{Pauli, PauliString};
use super::stabilizer::StabilizerCode;
use crate::error::{QuantRS2Error, QuantRS2Result};
use scirs2_core::Complex64;
#[derive(Debug, Clone)]
pub struct ConcatenatedCode {
pub inner_code: StabilizerCode,
pub outer_code: StabilizerCode,
}
impl ConcatenatedCode {
pub const fn new(inner_code: StabilizerCode, outer_code: StabilizerCode) -> Self {
Self {
inner_code,
outer_code,
}
}
pub const fn total_qubits(&self) -> usize {
self.inner_code.n * self.outer_code.n
}
pub const fn logical_qubits(&self) -> usize {
self.inner_code.k * self.outer_code.k
}
pub const fn distance(&self) -> usize {
self.inner_code.d * self.outer_code.d
}
pub fn encode(&self, logical_state: &[Complex64]) -> QuantRS2Result<Vec<Complex64>> {
if logical_state.len() != 1 << self.logical_qubits() {
return Err(QuantRS2Error::InvalidInput(
"Logical state dimension mismatch".to_string(),
));
}
let outer_encoded = self.encode_with_code(logical_state, &self.outer_code)?;
let mut final_encoded = vec![Complex64::new(0.0, 0.0); 1 << self.total_qubits()];
for (i, &litude) in outer_encoded.iter().enumerate() {
if amplitude.norm() > 1e-10 {
final_encoded[i * (1 << self.inner_code.n)] = amplitude;
}
}
Ok(final_encoded)
}
pub fn correct_error(
&self,
encoded_state: &[Complex64],
error: &PauliString,
) -> QuantRS2Result<Vec<Complex64>> {
if error.paulis.len() != self.total_qubits() {
return Err(QuantRS2Error::InvalidInput(
"Error must act on all physical qubits".to_string(),
));
}
let mut corrected = encoded_state.to_vec();
for (i, &pauli) in error.paulis.iter().enumerate() {
if pauli != Pauli::I && i < corrected.len() {
corrected[i] *= -1.0;
}
}
Ok(corrected)
}
fn encode_with_code(
&self,
state: &[Complex64],
code: &StabilizerCode,
) -> QuantRS2Result<Vec<Complex64>> {
let mut encoded = vec![Complex64::new(0.0, 0.0); 1 << code.n];
for (i, &litude) in state.iter().enumerate() {
if i < encoded.len() {
encoded[i * (1 << (code.n - code.k))] = amplitude;
}
}
Ok(encoded)
}
}