use crate::{Error, Result};
use serde::{Deserialize, Serialize};
mod encoded;
pub mod fusion_surgery;
mod gf2;
mod magic;
mod memory;
mod network;
mod open;
mod optical_erasure;
mod planar;
mod planar_study;
mod relations;
mod six_ring;
mod study;
mod surgery;
pub mod threshold;
pub use encoded::{
EncodedFusion, EncodedFusionRecovery, ShorBlock, ShorEncodedResource, ShorOrientation,
};
pub use magic::{
MagicDistillation, MagicDistillationConfig, MagicDistillationCost, MagicInjection,
MagicInjectionBranch, MagicRecord, MagicState, ReedMuller15,
};
pub use memory::{MemoryBudgets, PhysicalMemoryStudy, PhysicalToricMemory, ToricFusionCode};
pub use network::{FourStarTorus, MatchingDecode, SyndromeGraph};
pub use open::{PatchBoundary, PatchShot, PhotonLossBurst, SixRingPatch};
pub use optical_erasure::{FusionErasureDistribution, OpticalFusionLoss};
pub use planar::{PlanarCode, PlanarCost, PlanarDecodeBudget, PlanarReadout, PlanarRecovery};
pub use planar_study::{PlanarMemoryNoise, PlanarMemoryStudy, run_planar_memory};
pub use relations::{MeasurementRelations, ParityInference, ParityRelation};
pub use six_ring::SixRingTorus;
pub use study::{
MemoryStudy, MemoryStudyTimings, NetworkNoise, WilsonInterval, run_four_star_memory,
run_four_star_memory_profiled,
};
pub use surgery::{
MergeBasis, PlanarSurgery, SurgeryAbort, SurgeryAttempt, SurgeryCheckRecord, SurgeryCnotRecord,
SurgeryDetectorLimits, SurgeryDetectorModel, SurgeryDistance, SurgeryFault, SurgeryLimits,
SurgeryMeasurement, SurgeryPhase, SurgeryRecord, SurgeryRecovery,
};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct CodeData {
version: u32,
variables: usize,
checks: Vec<Vec<bool>>,
logicals: Vec<Vec<bool>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(try_from = "CodeData", into = "CodeData")]
pub struct ParityCode(CodeData);
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ErasureDecode {
Decoded {
correction: Vec<bool>,
logical_flips: Vec<bool>,
},
Ambiguous {
logicals: Vec<usize>,
},
Inconsistent,
}
impl ParityCode {
pub fn new(variables: usize, checks: Vec<Vec<bool>>, logicals: Vec<Vec<bool>>) -> Result<Self> {
if variables == 0 || variables > 4096 {
return Err(Error::InvalidDimensions(
"parity-code width must be in 1..=4096".into(),
));
}
let rows = checks
.len()
.checked_add(logicals.len())
.ok_or(Error::Overflow)?;
let required = rows.checked_mul(variables).ok_or(Error::Overflow)?;
if required > 1 << 22 {
return Err(Error::ResourceLimit {
resource: "parity-code entries",
required,
limit: 1 << 22,
});
}
if checks
.iter()
.chain(&logicals)
.any(|row| row.len() != variables)
{
return Err(Error::Shape("parity-code row width".into()));
}
Ok(Self(CodeData {
version: 1,
variables,
checks,
logicals,
}))
}
pub fn repetition(distance: usize) -> Result<Self> {
if !(3..=4095).contains(&distance) || distance.is_multiple_of(2) {
return Err(Error::InvalidDimensions(
"repetition distance must be odd in 3..=4095".into(),
));
}
let required = distance.checked_mul(distance).ok_or(Error::Overflow)?;
if required > 1 << 22 {
return Err(Error::ResourceLimit {
resource: "parity-code entries",
required,
limit: 1 << 22,
});
}
let checks = (0..distance - 1)
.map(|i| {
let mut row = vec![false; distance];
row[i] = true;
row[i + 1] = true;
row
})
.collect();
let mut logical = vec![false; distance];
logical[0] = true;
Self::new(distance, checks, vec![logical])
}
pub fn variables(&self) -> usize {
self.0.variables
}
pub fn checks(&self) -> &[Vec<bool>] {
&self.0.checks
}
pub fn logicals(&self) -> &[Vec<bool>] {
&self.0.logicals
}
fn check_vector(&self, value: &[bool]) -> Result<()> {
if value.len() != self.variables() {
Err(Error::Shape("error/erasure vector width".into()))
} else {
Ok(())
}
}
pub fn syndrome(&self, errors: &[bool]) -> Result<Vec<bool>> {
self.check_vector(errors)?;
Ok(self.checks().iter().map(|r| dot(r, errors)).collect())
}
pub fn logical_flips(&self, errors: &[bool]) -> Result<Vec<bool>> {
self.check_vector(errors)?;
Ok(self.logicals().iter().map(|r| dot(r, errors)).collect())
}
pub fn decode_erasures(&self, syndrome: &[bool], erased: &[bool]) -> Result<ErasureDecode> {
self.check_vector(erased)?;
if syndrome.len() != self.checks().len() {
return Err(Error::Shape("syndrome width".into()));
}
let unknown: Vec<_> = erased
.iter()
.enumerate()
.filter_map(|(i, &e)| e.then_some(i))
.collect();
let n = unknown.len();
let matrix: Vec<Vec<bool>> = self
.checks()
.iter()
.map(|r| unknown.iter().map(|&q| r[q]).collect())
.collect();
let Some((solution, kernel)) = gf2::solve(&matrix, n, syndrome) else {
return Ok(ErasureDecode::Inconsistent);
};
let ambiguous: Vec<_> = self
.logicals()
.iter()
.enumerate()
.filter_map(|(l, logical)| {
kernel
.iter()
.any(|v| {
v.iter()
.zip(&unknown)
.fold(false, |s, (&b, &q)| s ^ (b && logical[q]))
})
.then_some(l)
})
.collect();
if !ambiguous.is_empty() {
return Ok(ErasureDecode::Ambiguous {
logicals: ambiguous,
});
}
let mut correction = vec![false; self.variables()];
for (&q, b) in unknown.iter().zip(solution) {
correction[q] = b;
}
let logical_flips = self.logical_flips(&correction)?;
Ok(ErasureDecode::Decoded {
correction,
logical_flips,
})
}
}
fn dot(a: &[bool], b: &[bool]) -> bool {
a.iter().zip(b).fold(false, |s, (&x, &y)| s ^ (x && y))
}
impl TryFrom<CodeData> for ParityCode {
type Error = Error;
fn try_from(data: CodeData) -> Result<Self> {
if data.version != 1 {
return Err(Error::Unsupported("unknown parity-code schema".into()));
}
Self::new(data.variables, data.checks, data.logicals)
}
}
impl From<ParityCode> for CodeData {
fn from(value: ParityCode) -> Self {
value.0
}
}