use super::SupportedVersion;
use std::collections::HashMap;
#[cfg(feature = "serialize")]
use struqture::spins::PlusMinusLindbladNoiseOperator;
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", serde(from = "DecoherenceOnGateModelSerialize"))]
#[cfg_attr(feature = "serialize", serde(into = "DecoherenceOnGateModelSerialize"))]
pub struct DecoherenceOnGateModel {
single_qubit_gate_errors:
HashMap<(String, usize), struqture::spins::PlusMinusLindbladNoiseOperator>,
two_qubit_gate_errors:
HashMap<(String, (usize, usize)), struqture::spins::PlusMinusLindbladNoiseOperator>,
three_qubit_gate_errors:
HashMap<(String, (usize, usize, usize)), struqture::spins::PlusMinusLindbladNoiseOperator>,
multi_qubit_gate_errors:
HashMap<(String, Vec<usize>), struqture::spins::PlusMinusLindbladNoiseOperator>,
}
#[cfg(feature = "json_schema")]
impl schemars::JsonSchema for DecoherenceOnGateModel {
fn schema_name() -> std::borrow::Cow<'static, str> {
"DecoherenceOnGateModel".into()
}
fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
<DecoherenceOnGateModelSerialize>::json_schema(generator)
}
}
#[cfg(feature = "serialize")]
type SingleQGateIndex = (String, usize);
#[cfg(feature = "serialize")]
type SingleQubitErrors = Vec<(
SingleQGateIndex,
struqture_1::spins::PlusMinusLindbladNoiseOperator,
)>;
#[cfg(feature = "serialize")]
type TwoQubitGateIndex = (String, (usize, usize));
#[cfg(feature = "serialize")]
type TwoQubitErrors = Vec<(
TwoQubitGateIndex,
struqture_1::spins::PlusMinusLindbladNoiseOperator,
)>;
#[cfg(feature = "serialize")]
type ThreeQubitGateIndex = (String, (usize, usize, usize));
#[cfg(feature = "serialize")]
type ThreeQubitErrors = Vec<(
ThreeQubitGateIndex,
struqture_1::spins::PlusMinusLindbladNoiseOperator,
)>;
#[cfg(feature = "serialize")]
type MultiQubitGateIndex = (String, Vec<usize>);
#[cfg(feature = "serialize")]
type MultiQubitErrors = Vec<(
MultiQubitGateIndex,
struqture_1::spins::PlusMinusLindbladNoiseOperator,
)>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "json_schema",
derive(schemars::JsonSchema),
schemars(deny_unknown_fields)
)]
#[cfg(feature = "serialize")]
struct DecoherenceOnGateModelSerialize {
single_qubit_gate_errors: SingleQubitErrors,
two_qubit_gate_errors: TwoQubitErrors,
three_qubit_gate_errors: ThreeQubitErrors,
multi_qubit_gate_errors: MultiQubitErrors,
}
#[cfg(feature = "serialize")]
impl From<DecoherenceOnGateModel> for DecoherenceOnGateModelSerialize {
fn from(value: DecoherenceOnGateModel) -> Self {
let single_qubit_gate_errors: SingleQubitErrors =
value.single_qubit_gate_errors.into_iter().map(|(key, value)|(key, value.to_struqture_1().expect("Failed to convert PlusMinusLindbladNoiseOperator to struqture 1.x for serialization."))).collect();
let two_qubit_gate_errors: TwoQubitErrors =
value.two_qubit_gate_errors.into_iter().map(|(key, value)|(key, value.to_struqture_1().expect("Failed to convert PlusMinusLindbladNoiseOperator to struqture 1.x for serialization."))).collect();
let three_qubit_gate_errors: ThreeQubitErrors =
value.three_qubit_gate_errors.into_iter().map(|(key, value)|(key, value.to_struqture_1().expect("Failed to convert PlusMinusLindbladNoiseOperator to struqture 1.x for serialization."))).collect();
let multi_qubit_gate_errors: MultiQubitErrors =
value.multi_qubit_gate_errors.into_iter().map(|(key, value)|(key, value.to_struqture_1().expect("Failed to convert PlusMinusLindbladNoiseOperator to struqture 1.x for serialization."))).collect();
DecoherenceOnGateModelSerialize {
single_qubit_gate_errors,
two_qubit_gate_errors,
three_qubit_gate_errors,
multi_qubit_gate_errors,
}
}
}
#[cfg(feature = "serialize")]
impl From<DecoherenceOnGateModelSerialize> for DecoherenceOnGateModel {
fn from(value: DecoherenceOnGateModelSerialize) -> Self {
let single_qubit_gate_errors: HashMap<
(String, usize),
struqture::spins::PlusMinusLindbladNoiseOperator,
> = value.single_qubit_gate_errors.into_iter().map(|(key, value)|(key, PlusMinusLindbladNoiseOperator::from_struqture_1(&value).expect("Failed to convert PlusMinusLindbladNoiseOperator from struqture 1.x for serialization."))).collect();
let two_qubit_gate_errors: HashMap<
(String, (usize, usize)),
struqture::spins::PlusMinusLindbladNoiseOperator,
> = value.two_qubit_gate_errors.into_iter().map(|(key, value)|(key, PlusMinusLindbladNoiseOperator::from_struqture_1(&value).expect("Failed to convert PlusMinusLindbladNoiseOperator from struqture 1.x for serialization."))).collect();
let three_qubit_gate_errors: HashMap<
(String, (usize, usize, usize)),
struqture::spins::PlusMinusLindbladNoiseOperator,
> = value.three_qubit_gate_errors.into_iter().map(|(key, value)|(key, PlusMinusLindbladNoiseOperator::from_struqture_1(&value).expect("Failed to convert PlusMinusLindbladNoiseOperator from struqture 1.x for serialization."))).collect();
let multi_qubit_gate_errors: HashMap<
(String, Vec<usize>),
struqture::spins::PlusMinusLindbladNoiseOperator,
> = value.multi_qubit_gate_errors.into_iter().map(|(key, value)|(key, PlusMinusLindbladNoiseOperator::from_struqture_1(&value).expect("Failed to convert PlusMinusLindbladNoiseOperator from struqture 1.x for serialization."))).collect();
DecoherenceOnGateModel {
single_qubit_gate_errors,
two_qubit_gate_errors,
three_qubit_gate_errors,
multi_qubit_gate_errors,
}
}
}
impl SupportedVersion for DecoherenceOnGateModel {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 6, 0)
}
}
impl DecoherenceOnGateModel {
pub fn new() -> Self {
Self {
single_qubit_gate_errors: HashMap::new(),
two_qubit_gate_errors: HashMap::new(),
three_qubit_gate_errors: HashMap::new(),
multi_qubit_gate_errors: HashMap::new(),
}
}
pub fn set_single_qubit_gate_error(
mut self,
gate: &str,
qubit: usize,
noise_operator: struqture::spins::PlusMinusLindbladNoiseOperator,
) -> Self {
self.single_qubit_gate_errors
.insert((gate.to_string(), qubit), noise_operator);
self
}
pub fn get_single_qubit_gate_error(
&self,
gate: &str,
qubit: usize,
) -> Option<&struqture::spins::PlusMinusLindbladNoiseOperator> {
self.single_qubit_gate_errors
.get(&(gate.to_string(), qubit))
}
pub fn set_two_qubit_gate_error(
mut self,
gate: &str,
control: usize,
target: usize,
noise_operator: struqture::spins::PlusMinusLindbladNoiseOperator,
) -> Self {
self.two_qubit_gate_errors
.insert((gate.to_string(), (control, target)), noise_operator);
self
}
pub fn get_two_qubit_gate_error(
&self,
gate: &str,
control: usize,
target: usize,
) -> Option<&struqture::spins::PlusMinusLindbladNoiseOperator> {
self.two_qubit_gate_errors
.get(&(gate.to_string(), (control, target)))
}
pub fn set_three_qubit_gate_error(
mut self,
gate: &str,
control0: usize,
control1: usize,
target: usize,
noise_operator: struqture::spins::PlusMinusLindbladNoiseOperator,
) -> Self {
self.three_qubit_gate_errors.insert(
(gate.to_string(), (control0, control1, target)),
noise_operator,
);
self
}
pub fn get_three_qubit_gate_error(
&self,
gate: &str,
control0: usize,
control1: usize,
target: usize,
) -> Option<&struqture::spins::PlusMinusLindbladNoiseOperator> {
self.three_qubit_gate_errors
.get(&(gate.to_string(), (control0, control1, target)))
}
pub fn set_multi_qubit_gate_error(
mut self,
gate: &str,
qubits: Vec<usize>,
noise_operator: struqture::spins::PlusMinusLindbladNoiseOperator,
) -> Self {
self.multi_qubit_gate_errors
.insert((gate.to_string(), qubits), noise_operator);
self
}
pub fn get_multi_qubit_gate_error(
&self,
gate: &str,
qubits: Vec<usize>,
) -> Option<&struqture::spins::PlusMinusLindbladNoiseOperator> {
self.multi_qubit_gate_errors
.get(&(gate.to_string(), qubits))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "json_schema")]
use jsonschema::Validator;
use struqture::spins::PlusMinusLindbladNoiseOperator;
#[test]
fn test_decoherence_on_gate_model_single() {
let mut noise_model = DecoherenceOnGateModel::new();
noise_model = noise_model.set_single_qubit_gate_error(
"RotateX",
0,
PlusMinusLindbladNoiseOperator::new(),
);
assert_eq!(
noise_model.get_single_qubit_gate_error("RotateX", 0),
Some(&PlusMinusLindbladNoiseOperator::new())
);
}
#[test]
fn test_decoherence_on_gate_model_two() {
let mut noise_model = DecoherenceOnGateModel::new();
noise_model = noise_model.set_two_qubit_gate_error(
"CNOT",
0,
1,
PlusMinusLindbladNoiseOperator::new(),
);
assert_eq!(
noise_model.get_two_qubit_gate_error("CNOT", 0, 1),
Some(&PlusMinusLindbladNoiseOperator::new())
);
}
#[test]
fn test_decoherence_on_gate_model_three() {
let mut noise_model = DecoherenceOnGateModel::new();
noise_model = noise_model.set_three_qubit_gate_error(
"ControlledControlledPauliZ",
0,
1,
2,
PlusMinusLindbladNoiseOperator::new(),
);
assert_eq!(
noise_model.get_three_qubit_gate_error("ControlledControlledPauliZ", 0, 1, 2),
Some(&PlusMinusLindbladNoiseOperator::new())
);
}
#[test]
fn test_decoherence_on_gate_model_mulit() {
let mut noise_model = DecoherenceOnGateModel::new();
noise_model = noise_model.set_multi_qubit_gate_error(
"MultiQubitMS",
vec![0, 1, 2, 3],
PlusMinusLindbladNoiseOperator::new(),
);
assert_eq!(
noise_model.get_multi_qubit_gate_error("MultiQubitMS", vec![0, 1, 2, 3]),
Some(&PlusMinusLindbladNoiseOperator::new())
);
}
#[cfg(feature = "serialize")]
#[test]
fn test_json_serialization() {
let mut noise_model = DecoherenceOnGateModel::new();
noise_model = noise_model.set_single_qubit_gate_error(
"RotateX",
0,
PlusMinusLindbladNoiseOperator::new(),
);
let json_str = serde_json::to_string(&noise_model).unwrap();
let deserialized_noise_model: DecoherenceOnGateModel =
serde_json::from_str(&json_str).unwrap();
assert_eq!(noise_model, deserialized_noise_model);
}
#[cfg(feature = "json_schema")]
#[test]
fn test_json_schema_feature() {
let mut model = DecoherenceOnGateModel::new();
model =
model.set_single_qubit_gate_error("RotateX", 0, PlusMinusLindbladNoiseOperator::new());
let schema = schemars::schema_for!(DecoherenceOnGateModel);
let schema_checker =
Validator::new(&serde_json::to_value(&schema).unwrap()).expect("schema is valid");
let value = serde_json::to_value(model).unwrap();
let val = match value {
serde_json::Value::Object(ob) => ob,
_ => panic!(),
};
let value: serde_json::Value = serde_json::to_value(val).unwrap();
let validation = schema_checker.validate(&value);
assert!(validation.is_ok());
}
}