use super::SupportedVersion;
#[cfg(feature = "serialize")]
use crate::RoqoqoError;
use struqture::{
spins::PlusMinusLindbladNoiseOperator, spins::PlusMinusProduct, OperateOnDensityMatrix,
};
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
serde(try_from = "DecoherenceOnIdleModelSerialize")
)]
#[cfg_attr(feature = "serialize", serde(into = "DecoherenceOnIdleModelSerialize"))]
pub struct DecoherenceOnIdleModel {
pub lindblad_noise: PlusMinusLindbladNoiseOperator,
}
#[cfg(feature = "json_schema")]
impl schemars::JsonSchema for DecoherenceOnIdleModel {
fn schema_name() -> std::borrow::Cow<'static, str> {
"DecoherenceOnIdleModel".into()
}
fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
<DecoherenceOnIdleModelSerialize>::json_schema(generator)
}
}
#[cfg(feature = "serialize")]
#[derive(Clone, PartialEq, Debug, Default)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", serde(rename = "DecoherenceOnIdleModel"))]
#[cfg_attr(
feature = "json_schema",
derive(schemars::JsonSchema),
schemars(deny_unknown_fields)
)]
struct DecoherenceOnIdleModelSerialize {
lindblad_noise: struqture_1::spins::PlusMinusLindbladNoiseOperator,
}
#[cfg(feature = "serialize")]
impl TryFrom<DecoherenceOnIdleModelSerialize> for DecoherenceOnIdleModel {
type Error = RoqoqoError;
fn try_from(value: DecoherenceOnIdleModelSerialize) -> Result<Self, Self::Error> {
Ok(DecoherenceOnIdleModel {
lindblad_noise: PlusMinusLindbladNoiseOperator::from_struqture_1(&value.lindblad_noise).expect("Failed to convert PlusMinusLindbladNoiseOperator from struqture 1.x for serialization."),
})
}
}
#[cfg(feature = "serialize")]
impl From<DecoherenceOnIdleModel> for DecoherenceOnIdleModelSerialize {
fn from(value: DecoherenceOnIdleModel) -> Self {
let lindblad_noise = value.lindblad_noise.to_struqture_1().expect(
"Failed to convert PlusMinusLindbladNoiseOperator to struqture 1.x for serialization.",
);
Self { lindblad_noise }
}
}
impl SupportedVersion for DecoherenceOnIdleModel {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 11, 0)
}
}
impl DecoherenceOnIdleModel {
pub fn new() -> Self {
Self {
lindblad_noise: PlusMinusLindbladNoiseOperator::default(),
}
}
pub fn add_damping_rate(mut self, qubits: &[usize], rate: f64) -> Self {
for qubit in qubits {
self.lindblad_noise
.add_operator_product(
(
PlusMinusProduct::new().plus(*qubit),
PlusMinusProduct::new().plus(*qubit),
),
rate.into(),
)
.expect("Internal struqture bug.");
}
self
}
pub fn add_excitation_rate(mut self, qubits: &[usize], rate: f64) -> Self {
for qubit in qubits {
self.lindblad_noise
.add_operator_product(
(
PlusMinusProduct::new().minus(*qubit),
PlusMinusProduct::new().minus(*qubit),
),
rate.into(),
)
.expect("Internal struqture bug.");
}
self
}
pub fn add_dephasing_rate(mut self, qubits: &[usize], rate: f64) -> Self {
for qubit in qubits {
self.lindblad_noise
.add_operator_product(
(
PlusMinusProduct::new().z(*qubit),
PlusMinusProduct::new().z(*qubit),
),
(0.5 * rate).into(),
)
.expect("Internal struqture bug.");
}
self
}
pub fn add_depolarising_rate(mut self, qubits: &[usize], rate: f64) -> Self {
for qubit in qubits {
self.lindblad_noise
.add_operator_product(
(
PlusMinusProduct::new().plus(*qubit),
PlusMinusProduct::new().plus(*qubit),
),
(rate / 2.0).into(),
)
.expect("Internal struqture bug.");
self.lindblad_noise
.add_operator_product(
(
PlusMinusProduct::new().minus(*qubit),
PlusMinusProduct::new().minus(*qubit),
),
(rate / 2.0).into(),
)
.expect("Internal struqture bug.");
self.lindblad_noise
.add_operator_product(
(
PlusMinusProduct::new().z(*qubit),
PlusMinusProduct::new().z(*qubit),
),
(rate / 4.0).into(),
)
.expect("Internal struqture bug.");
}
self
}
}
impl From<PlusMinusLindbladNoiseOperator> for DecoherenceOnIdleModel {
fn from(value: PlusMinusLindbladNoiseOperator) -> Self {
Self {
lindblad_noise: value,
}
}
}
impl From<DecoherenceOnIdleModel> for PlusMinusLindbladNoiseOperator {
fn from(value: DecoherenceOnIdleModel) -> Self {
value.lindblad_noise
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "json_schema")]
use jsonschema::Validator;
#[test]
fn test_decoherence_on_idle_model_new() {
let model = DecoherenceOnIdleModel::new();
assert_eq!(model.lindblad_noise, PlusMinusLindbladNoiseOperator::new());
}
#[test]
fn test_decoherence_on_idle_model_add_damping() {
let model = DecoherenceOnIdleModel::new();
let model = model.add_damping_rate(&[0], 0.9);
let mut lindblad_operator = PlusMinusLindbladNoiseOperator::new();
lindblad_operator
.add_operator_product(
(
PlusMinusProduct::new().plus(0),
PlusMinusProduct::new().plus(0),
),
0.9.into(),
)
.unwrap();
assert_eq!(model.lindblad_noise, lindblad_operator);
}
#[test]
fn test_decoherence_on_idle_model_add_depolarising() {
let model = DecoherenceOnIdleModel::new();
let model = model.add_depolarising_rate(&[0], 1.8);
let mut lindblad_operator = PlusMinusLindbladNoiseOperator::new();
lindblad_operator
.add_operator_product(
(
PlusMinusProduct::new().plus(0),
PlusMinusProduct::new().plus(0),
),
0.9.into(),
)
.unwrap();
lindblad_operator
.add_operator_product(
(
PlusMinusProduct::new().minus(0),
PlusMinusProduct::new().minus(0),
),
0.9.into(),
)
.unwrap();
lindblad_operator
.add_operator_product(
(PlusMinusProduct::new().z(0), PlusMinusProduct::new().z(0)),
0.45.into(),
)
.unwrap();
assert_eq!(model.lindblad_noise, lindblad_operator);
}
#[test]
fn test_decoherence_on_idle_model_add_excitation_rate() {
let mut model = DecoherenceOnIdleModel::new();
model = model.add_excitation_rate(&[0, 1], 0.9);
let mut lindblad_operator = PlusMinusLindbladNoiseOperator::new();
lindblad_operator
.add_operator_product(
(
PlusMinusProduct::new().minus(0),
PlusMinusProduct::new().minus(0),
),
0.9.into(),
)
.unwrap();
lindblad_operator
.add_operator_product(
(
PlusMinusProduct::new().minus(1),
PlusMinusProduct::new().minus(1),
),
0.9.into(),
)
.unwrap();
assert_eq!(model.lindblad_noise, lindblad_operator);
}
#[test]
fn test_decoherence_on_idle_model_add_dephasing_rate() {
let mut model = DecoherenceOnIdleModel::new();
model = model.add_dephasing_rate(&[0, 1], 0.9);
let mut lindblad_operator = PlusMinusLindbladNoiseOperator::new();
lindblad_operator
.add_operator_product(
(PlusMinusProduct::new().z(0), PlusMinusProduct::new().z(0)),
0.45.into(),
)
.unwrap();
lindblad_operator
.add_operator_product(
(PlusMinusProduct::new().z(1), PlusMinusProduct::new().z(1)),
0.45.into(),
)
.unwrap();
assert_eq!(model.lindblad_noise, lindblad_operator);
}
#[test]
fn test_from_decoherence_on_idle_model_to_plus_minus_lindblad_noise_operator() {
let mut lindblad_noise = PlusMinusLindbladNoiseOperator::new();
lindblad_noise
.add_operator_product(
(PlusMinusProduct::new().z(0), PlusMinusProduct::new().z(0)),
0.9.into(),
)
.unwrap();
lindblad_noise
.add_operator_product(
(PlusMinusProduct::new().z(1), PlusMinusProduct::new().z(1)),
0.9.into(),
)
.unwrap();
let model = DecoherenceOnIdleModel { lindblad_noise };
let converted_model: PlusMinusLindbladNoiseOperator = model.clone().into();
assert_eq!(model.lindblad_noise, converted_model);
}
#[test]
fn test_from_plus_minus_lindblad_noise_operator_to_decoherence_on_idle_model() {
let mut lindblad_noise = PlusMinusLindbladNoiseOperator::new();
lindblad_noise
.add_operator_product(
(PlusMinusProduct::new().z(0), PlusMinusProduct::new().z(0)),
0.9.into(),
)
.unwrap();
lindblad_noise
.add_operator_product(
(PlusMinusProduct::new().z(1), PlusMinusProduct::new().z(1)),
0.9.into(),
)
.unwrap();
let converted_model: DecoherenceOnIdleModel = lindblad_noise.clone().into();
assert_eq!(DecoherenceOnIdleModel { lindblad_noise }, converted_model);
}
#[cfg(feature = "json_schema")]
#[test]
fn test_json_schema_feature() {
let mut model = DecoherenceOnIdleModel::new();
model = model.add_dephasing_rate(&[0, 1], 0.9);
let schema = schemars::schema_for!(DecoherenceOnIdleModel);
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());
}
}