use num_complex::Complex64;
use pyo3::exceptions::{PyRuntimeError, PyTypeError, PyValueError};
use pyo3::prelude::*;
use pyo3::types::PyByteArray;
use roqoqo::measurements::{
CheatedInput, CheatedPauliZProductInput, PauliProductMask, PauliZProductInput,
};
#[cfg(feature = "json_schema")]
use roqoqo::{operations::SupportedVersion, ROQOQO_VERSION};
use std::collections::HashMap;
#[pyclass(
from_py_object,
name = "PauliZProductInput",
module = "qoqo.measurements"
)]
#[derive(Clone, Debug)]
pub struct PauliZProductInputWrapper {
pub internal: PauliZProductInput,
}
#[pymethods]
impl PauliZProductInputWrapper {
#[new]
pub fn new(number_qubits: usize, use_flipped_measurement: bool) -> Self {
Self {
internal: PauliZProductInput::new(number_qubits, use_flipped_measurement),
}
}
pub fn add_pauliz_product(
&mut self,
readout: String,
pauli_product_mask: PauliProductMask,
) -> PyResult<usize> {
self.internal
.add_pauliz_product(readout, pauli_product_mask)
.map_err(|_| PyRuntimeError::new_err("Failed to add pauli product"))
}
pub fn add_linear_exp_val(
&mut self,
name: String,
linear: HashMap<usize, f64>,
) -> PyResult<()> {
self.internal.add_linear_exp_val(name, linear).map_err(|x| {
PyRuntimeError::new_err(format!("Failed to add linear expectation value {x:?}"))
})
}
pub fn add_symbolic_exp_val(&mut self, name: String, symbolic: String) -> PyResult<()> {
self.internal
.add_symbolic_exp_val(name, symbolic.into())
.map_err(|x| {
PyRuntimeError::new_err(format!("Failed to add symbolic expectation value {x:?}"))
})
}
pub fn to_json(&self) -> PyResult<String> {
serde_json::to_string(&self.internal)
.map_err(|_| PyRuntimeError::new_err("Unexpected error serializing PauliZProductInput"))
}
#[staticmethod]
pub fn from_json(json_string: &str) -> PyResult<Self> {
Ok(Self {
internal: serde_json::from_str(json_string).map_err(|_| {
PyValueError::new_err("Cannot deserialize string to PauliZProductInput")
})?,
})
}
pub fn to_bincode(&self) -> PyResult<Py<PyByteArray>> {
let serialized = bincode::serde::encode_to_vec(&self.internal, bincode::config::legacy())
.map_err(|_| {
PyValueError::new_err("Cannot serialize PauliZProductInput to bytes")
})?;
let b: Py<PyByteArray> = Python::attach(|py| -> Py<PyByteArray> {
PyByteArray::new(py, &serialized[..]).into()
});
Ok(b)
}
#[staticmethod]
pub fn from_bincode(input: &Bound<PyAny>) -> PyResult<Self> {
let bytes = input
.extract::<Vec<u8>>()
.map_err(|_| PyTypeError::new_err("Input cannot be converted to byte array"))?;
Ok(Self {
internal: bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy())
.map_err(|_| {
PyValueError::new_err("Input cannot be deserialized to PauliZProductInput")
})?
.0,
})
}
pub fn __repr__(&self) -> String {
format!("{:?}", self.internal)
}
pub fn __copy__(&self) -> Self {
self.clone()
}
fn __richcmp__(
&self,
other: PauliZProductInputWrapper,
op: pyo3::class::basic::CompareOp,
) -> PyResult<bool> {
match op {
pyo3::class::basic::CompareOp::Eq => Ok(self.internal == other.internal),
pyo3::class::basic::CompareOp::Ne => Ok(self.internal != other.internal),
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented",
)),
}
}
pub fn __deepcopy__(&self, _memodict: &Bound<PyAny>) -> Self {
self.clone()
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn json_schema() -> String {
let schema = schemars::schema_for!(PauliZProductInput);
serde_json::to_string_pretty(&schema).expect("Unexpected failure to serialize schema")
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn current_version() -> String {
ROQOQO_VERSION.to_string()
}
#[cfg(feature = "json_schema")]
pub fn min_supported_version(&self) -> String {
let min_version: (u32, u32, u32) =
PauliZProductInput::minimum_supported_roqoqo_version(&self.internal);
format!("{}.{}.{}", min_version.0, min_version.1, min_version.2)
}
}
#[pyclass(
from_py_object,
name = "CheatedPauliZProductInput",
module = "qoqo.measurements"
)]
#[derive(Clone, Debug)]
pub struct CheatedPauliZProductInputWrapper {
pub internal: CheatedPauliZProductInput,
}
impl Default for CheatedPauliZProductInputWrapper {
fn default() -> Self {
Self::new()
}
}
#[pymethods]
impl CheatedPauliZProductInputWrapper {
#[new]
pub fn new() -> Self {
Self {
internal: CheatedPauliZProductInput::new(),
}
}
pub fn add_pauliz_product(&mut self, readout: String) -> usize {
self.internal.add_pauliz_product(readout)
}
pub fn add_linear_exp_val(
&mut self,
name: String,
linear: HashMap<usize, f64>,
) -> PyResult<()> {
self.internal.add_linear_exp_val(name, linear).map_err(|x| {
PyRuntimeError::new_err(format!("Failed to add linear expectation value {x:?}"))
})
}
pub fn add_symbolic_exp_val(&mut self, name: String, symbolic: String) -> PyResult<()> {
self.internal
.add_symbolic_exp_val(name, symbolic.into())
.map_err(|x| {
PyRuntimeError::new_err(format!("Failed to add symbolic expectation value {x:?}"))
})
}
pub fn to_json(&self) -> PyResult<String> {
serde_json::to_string(&self.internal)
.map_err(|_| PyRuntimeError::new_err("Unexpected error serializing PauliZProductInput"))
}
#[staticmethod]
pub fn from_json(json_string: &str) -> PyResult<Self> {
Ok(Self {
internal: serde_json::from_str(json_string).map_err(|_| {
PyValueError::new_err("Cannot deserialize string to PauliZProductInput")
})?,
})
}
pub fn to_bincode(&self) -> PyResult<Py<PyByteArray>> {
let serialized = bincode::serde::encode_to_vec(&self.internal, bincode::config::legacy())
.map_err(|_| {
PyValueError::new_err("Cannot serialize CheatedPauliZProductInput to bytes")
})?;
let b: Py<PyByteArray> = Python::attach(|py| -> Py<PyByteArray> {
PyByteArray::new(py, &serialized[..]).into()
});
Ok(b)
}
#[staticmethod]
pub fn from_bincode(input: &Bound<PyAny>) -> PyResult<Self> {
let bytes = input
.extract::<Vec<u8>>()
.map_err(|_| PyTypeError::new_err("Input cannot be converted to byte array"))?;
Ok(Self {
internal: bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy())
.map_err(|_| {
PyValueError::new_err(
"Input cannot be deserialized to CheatedPauliZProductInput",
)
})?
.0,
})
}
pub fn __repr__(&self) -> String {
format!("{:?}", self.internal)
}
pub fn __copy__(&self) -> Self {
self.clone()
}
pub fn __deepcopy__(&self, _memodict: &Bound<PyAny>) -> Self {
self.clone()
}
fn __richcmp__(
&self,
other: CheatedPauliZProductInputWrapper,
op: pyo3::class::basic::CompareOp,
) -> PyResult<bool> {
match op {
pyo3::class::basic::CompareOp::Eq => Ok(self.internal == other.internal),
pyo3::class::basic::CompareOp::Ne => Ok(self.internal != other.internal),
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented",
)),
}
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn json_schema() -> String {
let schema = schemars::schema_for!(CheatedPauliZProductInput);
serde_json::to_string_pretty(&schema).expect("Unexpected failure to serialize schema")
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn current_version() -> String {
ROQOQO_VERSION.to_string()
}
#[cfg(feature = "json_schema")]
pub fn min_supported_version(&self) -> String {
let min_version: (u32, u32, u32) =
CheatedPauliZProductInput::minimum_supported_roqoqo_version(&self.internal);
format!("{}.{}.{}", min_version.0, min_version.1, min_version.2)
}
}
#[pyclass(from_py_object, name = "CheatedInput", module = "qoqo.measurements")]
#[derive(Clone, Debug)]
pub struct CheatedInputWrapper {
pub internal: CheatedInput,
}
#[pymethods]
impl CheatedInputWrapper {
#[new]
pub fn new(number_qubits: usize) -> Self {
Self {
internal: CheatedInput::new(number_qubits),
}
}
pub fn add_operator_exp_val(
&mut self,
name: String,
operator: Vec<(usize, usize, Complex64)>,
readout: String,
) -> PyResult<()> {
self.internal
.add_operator_exp_val(name, operator, readout)
.map_err(|x| {
PyRuntimeError::new_err(format!(
"Failed to add operator based expectation value {x:?}"
))
})
}
pub fn to_json(&self) -> PyResult<String> {
serde_json::to_string(&self.internal)
.map_err(|_| PyRuntimeError::new_err("Unexpected error serializing PauliZProductInput"))
}
#[staticmethod]
pub fn from_json(json_string: &str) -> PyResult<Self> {
Ok(Self {
internal: serde_json::from_str(json_string).map_err(|_| {
PyValueError::new_err("Cannot deserialize string to PauliZProductInput")
})?,
})
}
pub fn to_bincode(&self) -> PyResult<Py<PyByteArray>> {
let serialized =
bincode::serde::encode_to_vec(&self.internal, bincode::config::legacy())
.map_err(|_| PyValueError::new_err("Cannot serialize CheatedInput to bytes"))?;
let b: Py<PyByteArray> = Python::attach(|py| -> Py<PyByteArray> {
PyByteArray::new(py, &serialized[..]).into()
});
Ok(b)
}
#[staticmethod]
pub fn from_bincode(input: &Bound<PyAny>) -> PyResult<Self> {
let bytes = input
.extract::<Vec<u8>>()
.map_err(|_| PyTypeError::new_err("Input cannot be converted to byte array"))?;
Ok(Self {
internal: bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy())
.map_err(|_| PyValueError::new_err("Input cannot be deserialized to CheatedInput"))?
.0,
})
}
pub fn __repr__(&self) -> String {
format!("{:?}", self.internal)
}
pub fn __copy__(&self) -> Self {
self.clone()
}
pub fn __deepcopy__(&self, _memodict: &Bound<PyAny>) -> Self {
self.clone()
}
fn __richcmp__(
&self,
other: CheatedInputWrapper,
op: pyo3::class::basic::CompareOp,
) -> PyResult<bool> {
match op {
pyo3::class::basic::CompareOp::Eq => Ok(self.internal == other.internal),
pyo3::class::basic::CompareOp::Ne => Ok(self.internal != other.internal),
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented",
)),
}
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn json_schema() -> String {
let schema = schemars::schema_for!(CheatedInput);
serde_json::to_string_pretty(&schema).expect("Unexpected failure to serialize schema")
}
#[cfg(feature = "json_schema")]
#[staticmethod]
pub fn current_version() -> String {
ROQOQO_VERSION.to_string()
}
#[cfg(feature = "json_schema")]
pub fn min_supported_version(&self) -> String {
let min_version: (u32, u32, u32) =
CheatedInput::minimum_supported_roqoqo_version(&self.internal);
format!("{}.{}.{}", min_version.0, min_version.1, min_version.2)
}
}
impl CheatedPauliZProductInputWrapper {
pub fn from_pyany(input: &Bound<PyAny>) -> PyResult<CheatedPauliZProductInput> {
if let Ok(try_downcast) = input.extract::<CheatedPauliZProductInputWrapper>() {
Ok(try_downcast.internal)
} else {
let get_bytes = input.call_method0("to_bincode").map_err(|_| {
PyTypeError::new_err("Python object cannot be converted to qoqo CheatedPauliZInput: Cast to binary representation failed".to_string())
})?;
let bytes = get_bytes.extract::<Vec<u8>>().map_err(|_| {
PyTypeError::new_err("Python object cannot be converted to qoqo CheatedPauliZInput: Cast to binary representation failed".to_string())
})?;
bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy()).map_err(|err| {
PyTypeError::new_err(format!(
"Python object cannot be converted to qoqo CheatedPauliZInput: Deserialization failed: {err}"
))
}).map(|(deserialized, _)| deserialized)
}
}
}
impl PauliZProductInputWrapper {
pub fn from_pyany(input: &Bound<PyAny>) -> PyResult<PauliZProductInput> {
if let Ok(try_downcast) = input.extract::<PauliZProductInputWrapper>() {
Ok(try_downcast.internal)
} else {
let get_bytes = input.call_method0("to_bincode").map_err(|_| {
PyTypeError::new_err("Python object cannot be converted to qoqo PauliZInput: Cast to binary representation failed".to_string())
})?;
let bytes = get_bytes.extract::<Vec<u8>>().map_err(|_| {
PyTypeError::new_err("Python object cannot be converted to qoqo PauliZInput: Cast to binary representation failed".to_string())
})?;
bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy()).map_err(|err| {
PyTypeError::new_err(format!(
"Python object cannot be converted to qoqo PauliZInput: Deserialization failed: {err}"
))
}).map(|(deserialized, _)| deserialized)
}
}
}
impl CheatedInputWrapper {
pub fn from_pyany(input: &Bound<PyAny>) -> PyResult<CheatedInput> {
if let Ok(try_downcast) = input.extract::<CheatedInputWrapper>() {
Ok(try_downcast.internal)
} else {
let get_bytes = input.call_method0("to_bincode").map_err(|_| {
PyTypeError::new_err("Python object cannot be converted to qoqo CheatedInput: Cast to binary representation failed".to_string())
})?;
let bytes = get_bytes.extract::<Vec<u8>>().map_err(|_| {
PyTypeError::new_err("Python object cannot be converted to qoqo CheatedInput: Cast to binary representation failed".to_string())
})?;
bincode::serde::decode_from_slice(&bytes[..], bincode::config::legacy()).map_err(|err| {
PyTypeError::new_err(format!(
"Python object cannot be converted to qoqo CheatedInput: Deserialization failed: {err}"
))
}).map(|(deserialized, _)| deserialized)
}
}
}