use super::CheatedInputWrapper;
use crate::CircuitWrapper;
use pyo3::exceptions::{PyRuntimeError, PyValueError};
use pyo3::prelude::*;
use pyo3::types::PyType;
use roqoqo::measurements::Cheated;
use roqoqo::prelude::*;
use roqoqo::registers::{BitOutputRegister, ComplexOutputRegister, FloatOutputRegister};
use roqoqo::Circuit;
use std::collections::HashMap;
#[pyclass(name = "Cheated", module = "qoqo.measurements")]
#[derive(Clone, Debug)]
pub struct CheatedWrapper {
pub internal: Cheated,
}
#[pymethods]
impl CheatedWrapper {
#[new]
pub fn new(
constant_circuit: Option<CircuitWrapper>,
circuits: Vec<CircuitWrapper>,
input: CheatedInputWrapper,
) -> Self {
let new_circuits: Vec<Circuit> = circuits.into_iter().map(|c| c.internal).collect();
let new_constant: Option<Circuit> = match constant_circuit {
None => None,
Some(c) => Some(c.internal),
};
Self {
internal: Cheated {
constant_circuit: new_constant,
circuits: new_circuits,
input: input.internal,
},
}
}
pub fn evaluate(
&mut self,
input_bit_registers: Py<PyAny>,
float_registers: HashMap<String, FloatOutputRegister>,
complex_registers: HashMap<String, ComplexOutputRegister>,
) -> PyResult<Option<HashMap<String, f64>>> {
let mut bit_registers: HashMap<String, BitOutputRegister> = HashMap::new();
let bit_registers_bool: PyResult<HashMap<String, Vec<Vec<bool>>>> =
Python::with_gil(|py| -> PyResult<HashMap<String, Vec<Vec<bool>>>> {
input_bit_registers
.as_ref(py)
.extract::<HashMap<String, BitOutputRegister>>()
});
if let Ok(try_downcast) = bit_registers_bool {
bit_registers = try_downcast
} else {
let tmp_bit_registers =
Python::with_gil(|py| -> PyResult<HashMap<String, Vec<Vec<usize>>>> {
input_bit_registers
.as_ref(py)
.extract::<HashMap<String, Vec<Vec<usize>>>>()
})?;
for (name, output_reg) in tmp_bit_registers {
let mut tmp_output_reg: Vec<Vec<bool>> = Vec::with_capacity(output_reg.len());
for reg in output_reg {
tmp_output_reg.push(reg.into_iter().map(|x| !matches!(x, 0)).collect());
}
bit_registers.insert(name, tmp_output_reg);
}
}
self.internal
.evaluate(bit_registers, float_registers, complex_registers)
.map_err(|x| {
PyRuntimeError::new_err(format!("Error evaluating cheated measurement {:?}", x))
})
}
pub fn circuits(&self) -> Vec<CircuitWrapper> {
self.internal
.circuits()
.map(|c| CircuitWrapper {
internal: c.clone(),
})
.collect()
}
pub fn constant_circuit(&self) -> Option<CircuitWrapper> {
self.internal
.constant_circuit()
.clone()
.map(|c| CircuitWrapper { internal: c })
}
pub fn substitute_parameters(
&self,
substituted_parameters: HashMap<String, f64>,
) -> PyResult<Self> {
Ok(Self {
internal: self
.internal
.substitute_parameters(substituted_parameters)
.map_err(|x| {
PyRuntimeError::new_err(format!(
"Error substituting symbolic parameters {:?}",
x
))
})?,
})
}
pub fn to_json(&self) -> PyResult<String> {
serde_json::to_string(&self.internal)
.map_err(|_| PyRuntimeError::new_err("Unexpected error serializing Cheated"))
}
#[allow(unused_variables)]
#[classmethod]
pub fn from_json(cls: &PyType, json_string: &str) -> PyResult<Self> {
Ok(Self {
internal: serde_json::from_str(json_string)
.map_err(|_| PyValueError::new_err("Cannot deserialize string to Cheated"))?,
})
}
}