use pyo3::prelude::*;
use qoqo_macros::noise_model_wrapper;
use roqoqo::noise_models::{
NoiseModel, SingleQubitOverrotationDescription, SingleQubitOverrotationOnGate,
};
#[cfg(feature = "json_schema")]
use roqoqo::{operations::SupportedVersion, ROQOQO_VERSION};
#[pyclass(frozen, name = "SingleQubitOverrotationDescription")]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct SingleQubitOverrotationDescriptionWrapper {
internal: SingleQubitOverrotationDescription,
}
#[pymethods]
impl SingleQubitOverrotationDescriptionWrapper {
#[new]
pub fn new(
gate: &str,
theta_mean: f64,
theta_std: f64,
) -> SingleQubitOverrotationDescriptionWrapper {
SingleQubitOverrotationDescriptionWrapper {
internal: SingleQubitOverrotationDescription::new(gate, theta_mean, theta_std),
}
}
pub fn __copy__(&self) -> Self {
self.clone()
}
pub fn __deepcopy__(&self, _memodict: &Bound<PyAny>) -> Self {
self.clone()
}
pub fn to_bincode(&self) -> PyResult<Py<pyo3::types::PyByteArray>> {
let noise_descp = self.internal.clone();
let serialized = bincode::serde::encode_to_vec(&noise_descp, bincode::config::legacy())
.map_err(|_| {
pyo3::exceptions::PyValueError::new_err(
"Cannot serialize Noise-Overrotation description to bytes",
)
})?;
let b: Py<pyo3::types::PyByteArray> =
Python::with_gil(|py| -> Py<pyo3::types::PyByteArray> {
pyo3::types::PyByteArray::new(py, &serialized[..]).into()
});
Ok(b)
}
pub fn to_json(&self) -> PyResult<String> {
let noise_descp = self.internal.clone();
let serialized = serde_json::to_string(&noise_descp).map_err(|_| {
pyo3::exceptions::PyValueError::new_err(
"Cannot serialize single qubit overrotation description to json.",
)
})?;
Ok(serialized)
}
#[staticmethod]
#[pyo3(text_signature = "(input)")]
pub fn from_bincode(
input: &Bound<PyAny>,
) -> PyResult<SingleQubitOverrotationDescriptionWrapper> {
let bytes = input.extract::<Vec<u8>>().map_err(|_| {
pyo3::exceptions::PyTypeError::new_err("Input cannot be converted to byte array")
})?;
let noise_description: SingleQubitOverrotationDescription =
bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy())
.map_err(|_| {
pyo3::exceptions::PyValueError::new_err(
"Input cannot be deserialized to overrotation description.",
)
})?
.0;
Ok(SingleQubitOverrotationDescriptionWrapper {
internal: noise_description,
})
}
#[staticmethod]
#[pyo3(text_signature = "(input)")]
pub fn from_json(input: &str) -> PyResult<SingleQubitOverrotationDescriptionWrapper> {
let noise_description: SingleQubitOverrotationDescription = serde_json::from_str(input)
.map_err(|_| {
pyo3::exceptions::PyValueError::new_err(
"Input cannot be deserialized to overrotation description.",
)
})?;
Ok(SingleQubitOverrotationDescriptionWrapper {
internal: noise_description,
})
}
fn __richcmp__(
&self,
other: &Bound<PyAny>,
op: pyo3::class::basic::CompareOp,
) -> PyResult<bool> {
let other = SingleQubitOverrotationDescriptionWrapper::from_pyany(other);
match op {
pyo3::class::basic::CompareOp::Eq => match other {
Ok(osystem) => Ok(self.internal.clone() == osystem),
_ => Ok(false),
},
pyo3::class::basic::CompareOp::Ne => match other {
Ok(osystem) => Ok(self.internal.clone() != osystem),
_ => Ok(true),
},
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented",
)),
}
}
#[cfg(feature = "json_schema")]
pub fn min_supported_version(&self) -> String {
let min_version: (u32, u32, u32) =
SingleQubitOverrotationDescription::minimum_supported_roqoqo_version(
&self.internal.clone(),
);
format!("{}.{}.{}", min_version.0, min_version.1, min_version.2)
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn current_version() -> String {
ROQOQO_VERSION.to_string()
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn json_schema() -> String {
let schema = schemars::schema_for!(SingleQubitOverrotationDescription);
serde_json::to_string_pretty(&schema).expect("Unexpected failure to serialize schema")
}
fn __repr__(&self) -> String {
format!("{:?}", self.internal)
}
}
impl SingleQubitOverrotationDescriptionWrapper {
pub fn from_pyany(input: &Bound<PyAny>) -> PyResult<SingleQubitOverrotationDescription> {
if let Ok(try_downcast) = input.extract::<SingleQubitOverrotationDescriptionWrapper>() {
Ok(try_downcast.internal)
} else {
let get_bytes = input.call_method0("to_bincode")?;
let bytes = get_bytes.extract::<Vec<u8>>()?;
bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy())
.map_err(|err| {
pyo3::exceptions::PyValueError::new_err(format!(
"Cannot treat input as Overrotation Description: {err}"
))
})
.map(|(deserialized, _)| deserialized)
}
}
}
#[pyclass(frozen, name = "SingleQubitOverrotationOnGate")]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct SingleQubitOverrotationOnGateWrapper {
internal: SingleQubitOverrotationOnGate,
}
#[noise_model_wrapper]
impl SingleQubitOverrotationOnGateWrapper {
#[new]
pub fn new() -> SingleQubitOverrotationOnGateWrapper {
SingleQubitOverrotationOnGateWrapper {
internal: SingleQubitOverrotationOnGate::new(),
}
}
pub fn set_single_qubit_overrotation(
&self,
gate: &str,
qubit: usize,
noise_description: &Bound<PyAny>,
) -> PyResult<Self> {
let noise_description =
SingleQubitOverrotationDescriptionWrapper::from_pyany(noise_description)?;
Ok(Self {
internal: self.internal.clone().set_single_qubit_overrotation(
gate,
qubit,
noise_description,
),
})
}
pub fn get_single_qubit_overrotation(
&self,
gate: &str,
qubit: usize,
) -> Option<SingleQubitOverrotationDescriptionWrapper> {
self.internal
.get_single_qubit_overrotation(gate, qubit)
.map(|noise_descp| SingleQubitOverrotationDescriptionWrapper {
internal: noise_descp.clone(),
})
}
pub fn set_two_qubit_overrotation(
&self,
gate: &str,
control: usize,
target: usize,
noise_operator: (Py<PyAny>, Py<PyAny>),
) -> PyResult<Self> {
Python::with_gil(|py| -> PyResult<Self> {
let noise1 =
SingleQubitOverrotationDescriptionWrapper::from_pyany(noise_operator.0.bind(py))?;
let noise2 =
SingleQubitOverrotationDescriptionWrapper::from_pyany(noise_operator.1.bind(py))?;
Ok(Self {
internal: self.internal.clone().set_two_qubit_overrotation(
gate,
control,
target,
(noise1, noise2),
),
})
})
}
pub fn get_two_qubit_overrotation(
&self,
gate: &str,
control: usize,
target: usize,
) -> Option<(
SingleQubitOverrotationDescriptionWrapper,
SingleQubitOverrotationDescriptionWrapper,
)> {
self.internal
.get_two_qubit_overrotation(gate, control, target)
.map(|noise| {
(
SingleQubitOverrotationDescriptionWrapper {
internal: noise.0.clone(),
},
SingleQubitOverrotationDescriptionWrapper {
internal: noise.1.clone(),
},
)
})
}
#[staticmethod]
#[pyo3(text_signature = "(input)")]
pub fn from_bincode(input: &Bound<PyAny>) -> PyResult<SingleQubitOverrotationOnGateWrapper> {
let bytes = input.extract::<Vec<u8>>().map_err(|_| {
pyo3::exceptions::PyTypeError::new_err("Input cannot be converted to byte array")
})?;
let noise_model: NoiseModel =
bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy())
.map_err(|_| {
pyo3::exceptions::PyValueError::new_err(
"Input cannot be deserialized to Noise-Model.",
)
})?
.0;
match noise_model {
NoiseModel::SingleQubitOverrotationOnGate(internal) => {
Ok(SingleQubitOverrotationOnGateWrapper { internal })
}
_ => Err(pyo3::exceptions::PyValueError::new_err(
"Input cannot be deserialized to selected Noise-Model.",
)),
}
}
#[staticmethod]
#[pyo3(text_signature = "(input)")]
pub fn from_json(input: &str) -> PyResult<SingleQubitOverrotationOnGateWrapper> {
let noise_model: NoiseModel = serde_json::from_str(input).map_err(|_| {
pyo3::exceptions::PyValueError::new_err("Input cannot be deserialized to Noise-Model.")
})?;
match noise_model {
NoiseModel::SingleQubitOverrotationOnGate(internal) => {
Ok(SingleQubitOverrotationOnGateWrapper { internal })
}
_ => Err(pyo3::exceptions::PyValueError::new_err(
"Input cannot be deserialized to selected Noise-Model.",
)),
}
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn json_schema() -> String {
let schema = schemars::schema_for!(SingleQubitOverrotationOnGate);
serde_json::to_string_pretty(&schema).expect("Unexpected failure to serialize schema")
}
}