use super::*;
use crate::KrausChannel;
use crate::photonic::{factories::ResourceFactory, optics::OpticalBellInstrument};
use serde::Serialize;
#[derive(Clone, Debug, Serialize)]
pub struct ResourceFactoryModel {
calibration: String,
factory: ResourceFactory,
noise: Option<KrausChannel>,
}
impl ResourceFactoryModel {
pub fn new(
calibration: String,
factory: ResourceFactory,
noise: Option<KrausChannel>,
) -> Result<Self> {
if calibration.is_empty() || calibration.len() > 4096 {
return Err(Error::InvalidValue(
"invalid resource calibration identity".into(),
));
}
Ok(Self {
calibration,
factory,
noise,
})
}
pub fn factory(&self) -> &ResourceFactory {
&self.factory
}
pub fn calibration(&self) -> &str {
&self.calibration
}
pub fn noise(&self) -> Option<&KrausChannel> {
self.noise.as_ref()
}
fn validate(&self, k: usize) -> Result<()> {
if self.factory.photons_per_attempt() < 2 * k {
return Err(Error::InvalidValue(
"resource factory photon cost is below supplied resource size".into(),
));
}
if self
.noise
.as_ref()
.is_some_and(|c| c.operators()[0].dimension() != 3usize.pow((2 * k) as u32))
{
return Err(Error::Shape(
"resource noise must act on all measured/output dual-rail sites".into(),
));
}
Ok(())
}
}
#[derive(Clone, Debug, Serialize)]
pub struct PhysicalCalibration {
local: ResourceFactoryModel,
entangling: ResourceFactoryModel,
analyzer: OpticalBellInstrument,
max_kraus_terms: usize,
}
impl PhysicalCalibration {
pub fn new(
local: ResourceFactoryModel,
entangling: ResourceFactoryModel,
analyzer: OpticalBellInstrument,
max_kraus_terms: usize,
) -> Result<Self> {
local.validate(1)?;
entangling.validate(2)?;
if max_kraus_terms == 0 || max_kraus_terms > 1_000_000 {
return Err(Error::InvalidValue(
"invalid calibrated Kraus work budget".into(),
));
}
Ok(Self {
local,
entangling,
analyzer,
max_kraus_terms,
})
}
pub fn analyzer(&self) -> &OpticalBellInstrument {
&self.analyzer
}
pub fn resource(&self, arity: usize) -> Result<&ResourceFactoryModel> {
match arity {
1 => Ok(&self.local),
2 => Ok(&self.entangling),
_ => Err(Error::Unsupported(
"calibrated resources support one or two logical sites".into(),
)),
}
}
pub(super) fn max_terms(&self) -> usize {
self.max_kraus_terms
}
}