use crate::{convert_into_circuit, CircuitWrapper};
use ndarray::Array1;
use num_complex::Complex64;
use numpy::{PyArray1, PyArray2, PyReadonlyArray1, PyReadonlyArray2, ToPyArray};
use pyo3::exceptions::{PyRuntimeError, PyTypeError};
use pyo3::prelude::*;
use pyo3::types::PyByteArray;
use pyo3::types::PySet;
use qoqo_calculator::CalculatorFloat;
use qoqo_calculator_pyo3::{convert_into_calculator_float, CalculatorFloatWrapper};
use qoqo_macros::*;
use roqoqo::operations::*;
use roqoqo::Circuit;
use std::collections::HashMap;
#[wrap(Operate, OperatePragma)]
#[derive(Eq)]
struct PragmaSetNumberOfMeasurements {
number_measurements: usize,
readout: String,
}
#[wrap(Operate, OperatePragma)]
pub struct PragmaLoop {
repetitions: CalculatorFloat,
circuit: Circuit,
}
#[pymodule]
fn pragma_set_statevector(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_class::<PragmaSetStateVectorWrapper>()?;
Ok(())
}
#[pyclass(name = "PragmaSetStateVector", module = "qoqo.operations")]
#[derive(Clone, Debug, PartialEq)]
pub struct PragmaSetStateVectorWrapper {
pub internal: PragmaSetStateVector,
}
insert_pyany_to_operation!(
"PragmaSetStateVector" =>{
let array = op.call_method0("statevector").expect("error extracting");
let statevec_casted: PyReadonlyArray1<Complex64> = array.extract().unwrap();
let statevec_array: Array1<Complex64> = statevec_casted.to_owned_array();
Ok(PragmaSetStateVector::new(statevec_array).into())
}
);
insert_operation_to_pyobject!(
Operation::PragmaSetStateVector(internal) => {
{
let pyref: Py<PragmaSetStateVectorWrapper> =
Py::new(py, PragmaSetStateVectorWrapper { internal }).unwrap();
let pyobject: PyObject = pyref.to_object(py);
Ok(pyobject)
}
}
);
#[pymethods]
impl PragmaSetStateVectorWrapper {
#[new]
fn new(statevector: Py<PyAny>) -> PyResult<Self> {
let try_cast: PyResult<Array1<Complex64>> =
Python::with_gil(|py| -> PyResult<Array1<Complex64>> {
let extracted: PyReadonlyArray1<Complex64> = statevector.as_ref(py).extract()?;
let statevec: Array1<Complex64> = extracted.to_owned_array();
Ok(statevec)
});
let try_cast = try_cast.or_else(|_| {
Python::with_gil(|py| -> PyResult<Array1<Complex64>> {
let extracted: PyReadonlyArray1<f64> = statevector.as_ref(py).extract()?;
let statevec: Array1<f64> = extracted.to_owned_array();
let statevec: Array1<Complex64> = statevec
.into_iter()
.map(|f| Complex64::new(f, 0.0))
.collect();
Ok(statevec)
})
});
let try_cast = try_cast.or_else(|_| {
Python::with_gil(|py| -> PyResult<Array1<Complex64>> {
let extracted: PyReadonlyArray1<isize> = statevector.as_ref(py).extract()?;
let statevec: Array1<isize> = extracted.to_owned_array();
let statevec: Array1<Complex64> = statevec
.into_iter()
.map(|f| Complex64::new(f as f64, 0.0))
.collect();
Ok(statevec)
})
});
match try_cast {
Ok(array) => Ok(Self {
internal: PragmaSetStateVector::new(array),
}),
Err(_) => {
let statevec_casted: Vec<Complex64> =
Python::with_gil(|py| -> PyResult<Vec<Complex64>> {
Vec::extract(statevector.as_ref(py))
})?;
let statevec_array: Array1<Complex64> = Array1::from(statevec_casted);
Ok(Self {
internal: PragmaSetStateVector::new(statevec_array),
})
}
}
}
fn statevector(&self) -> Py<PyArray1<Complex64>> {
Python::with_gil(|py| -> Py<PyArray1<Complex64>> {
self.internal.statevector().to_pyarray(py).to_owned()
})
}
fn involved_qubits(&self) -> PyObject {
let pyobject: PyObject =
Python::with_gil(|py| -> PyObject { PySet::new(py, &["All"]).unwrap().to_object(py) });
pyobject
}
fn tags(&self) -> Vec<String> {
self.internal.tags().iter().map(|s| s.to_string()).collect()
}
fn hqslang(&self) -> &'static str {
self.internal.hqslang()
}
fn is_parametrized(&self) -> bool {
self.internal.is_parametrized()
}
fn substitute_parameters(
&self,
substitution_parameters: std::collections::HashMap<&str, f64>,
) -> PyResult<Self> {
let mut calculator = qoqo_calculator::Calculator::new();
for (key, val) in substitution_parameters.iter() {
calculator.set_variable(key, *val);
}
Ok(Self {
internal: self
.internal
.substitute_parameters(&calculator)
.map_err(|x| {
pyo3::exceptions::PyRuntimeError::new_err(format!(
"Parameter Substitution failed: {:?}",
x
))
})?,
})
}
fn remap_qubits(&self, mapping: std::collections::HashMap<usize, usize>) -> PyResult<Self> {
let new_internal = self
.internal
.remap_qubits(&mapping)
.map_err(|_| pyo3::exceptions::PyRuntimeError::new_err("Qubit remapping failed: "))?;
Ok(Self {
internal: new_internal,
})
}
fn __copy__(&self) -> PragmaSetStateVectorWrapper {
self.clone()
}
fn __deepcopy__(&self, _memodict: Py<PyAny>) -> PragmaSetStateVectorWrapper {
self.clone()
}
fn __format__(&self, _format_spec: &str) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __repr__(&self) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __richcmp__(&self, other: Py<PyAny>, op: pyo3::class::basic::CompareOp) -> PyResult<bool> {
let other: Operation = Python::with_gil(|py| -> PyResult<Operation> {
let other_ref = other.as_ref(py);
crate::operations::convert_pyany_to_operation(other_ref).map_err(|_| {
pyo3::exceptions::PyTypeError::new_err(
"Right hand side cannot be converted to Operation",
)
})
})?;
match op {
pyo3::class::basic::CompareOp::Eq => {
Ok(Operation::from(self.internal.clone()) == other)
}
pyo3::class::basic::CompareOp::Ne => {
Ok(Operation::from(self.internal.clone()) != other)
}
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented.",
)),
}
}
}
#[pymodule]
fn pragma_set_density_matrix(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_class::<PragmaSetDensityMatrixWrapper>()?;
Ok(())
}
#[pyclass(name = "PragmaSetDensityMatrix", module = "qoqo.operations")]
#[derive(Clone, Debug, PartialEq)]
pub struct PragmaSetDensityMatrixWrapper {
pub internal: PragmaSetDensityMatrix,
}
insert_pyany_to_operation!(
"PragmaSetDensityMatrix" =>{
let density_matrix = op.call_method0("density_matrix")
.map_err(|_| QoqoError::ConversionError)?;
let density_matrix_op = density_matrix.cast_as::<PyArray2<Complex64>>().unwrap();
let densmat_array = density_matrix_op.readonly().as_array().to_owned();
Ok(PragmaSetDensityMatrix::new(densmat_array).into())
}
);
insert_operation_to_pyobject!(
Operation::PragmaSetDensityMatrix(internal) => {
{
let pyref: Py<PragmaSetDensityMatrixWrapper> =
Py::new(py, PragmaSetDensityMatrixWrapper { internal }).unwrap();
let pyobject: PyObject = pyref.to_object(py);
Ok(pyobject)
}
}
);
#[pymethods]
impl PragmaSetDensityMatrixWrapper {
#[new]
fn new(density_matrix: PyReadonlyArray2<Complex64>) -> PyResult<Self> {
let density_matrix_for_initialisation = density_matrix.as_array().to_owned();
Ok(Self {
internal: PragmaSetDensityMatrix::new(density_matrix_for_initialisation),
})
}
fn density_matrix(&self) -> Py<PyArray2<Complex64>> {
Python::with_gil(|py| -> Py<PyArray2<Complex64>> {
self.internal.density_matrix().to_pyarray(py).to_owned()
})
}
fn involved_qubits(&self) -> PyObject {
let pyobject: PyObject =
Python::with_gil(|py| -> PyObject { PySet::new(py, &["All"]).unwrap().to_object(py) });
pyobject
}
fn tags(&self) -> Vec<String> {
self.internal.tags().iter().map(|s| s.to_string()).collect()
}
fn hqslang(&self) -> &'static str {
self.internal.hqslang()
}
fn is_parametrized(&self) -> bool {
self.internal.is_parametrized()
}
fn substitute_parameters(
&self,
substitution_parameters: std::collections::HashMap<&str, f64>,
) -> PyResult<Self> {
let mut calculator = qoqo_calculator::Calculator::new();
for (key, val) in substitution_parameters.iter() {
calculator.set_variable(key, *val);
}
Ok(Self {
internal: self
.internal
.substitute_parameters(&calculator)
.map_err(|x| {
pyo3::exceptions::PyRuntimeError::new_err(format!(
"Parameter Substitution failed: {:?}",
x
))
})?,
})
}
fn remap_qubits(&self, mapping: std::collections::HashMap<usize, usize>) -> PyResult<Self> {
let new_internal = self
.internal
.remap_qubits(&mapping)
.map_err(|_| pyo3::exceptions::PyRuntimeError::new_err("Qubit remapping failed: "))?;
Ok(Self {
internal: new_internal,
})
}
fn __copy__(&self) -> PragmaSetDensityMatrixWrapper {
self.clone()
}
fn __deepcopy__(&self, _memodict: Py<PyAny>) -> PragmaSetDensityMatrixWrapper {
self.clone()
}
fn __format__(&self, _format_spec: &str) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __repr__(&self) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __richcmp__(&self, other: Py<PyAny>, op: pyo3::class::basic::CompareOp) -> PyResult<bool> {
let other: Operation = Python::with_gil(|py| -> PyResult<Operation> {
let other_ref = other.as_ref(py);
crate::operations::convert_pyany_to_operation(other_ref).map_err(|_| {
pyo3::exceptions::PyTypeError::new_err(
"Right hand side cannot be converted to Operation",
)
})
})?;
match op {
pyo3::class::basic::CompareOp::Eq => {
Ok(Operation::from(self.internal.clone()) == other)
}
pyo3::class::basic::CompareOp::Ne => {
Ok(Operation::from(self.internal.clone()) != other)
}
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented.",
)),
}
}
}
#[wrap(Operate, OperatePragma)]
#[derive(Eq)]
struct PragmaRepeatGate {
repetition_coefficient: usize,
}
#[wrap(Operate, OperatePragma, OperateMultiQubit)]
struct PragmaOverrotation {
gate_hqslang: String,
qubits: Vec<usize>,
amplitude: f64,
variance: f64,
}
#[wrap(Operate, OperatePragma)]
struct PragmaBoostNoise {
noise_coefficient: CalculatorFloat,
}
#[wrap(Operate, OperateMultiQubit, OperatePragma)]
struct PragmaStopParallelBlock {
qubits: Vec<usize>,
execution_time: CalculatorFloat,
}
#[wrap(Operate)]
struct PragmaGlobalPhase {
phase: CalculatorFloat,
}
#[wrap(Operate, OperateMultiQubit, OperatePragma)]
pub struct PragmaSleep {
qubits: Vec<usize>,
sleep_time: CalculatorFloat,
}
#[wrap(Operate, OperateSingleQubit, OperatePragma)]
#[derive(Eq)]
pub struct PragmaActiveReset {
qubit: usize,
}
#[wrap(Operate, OperateMultiQubit, OperatePragma)]
#[derive(Eq)]
pub struct PragmaStartDecompositionBlock {
qubits: Vec<usize>,
reordering_dictionary: HashMap<usize, usize>,
}
#[wrap(Operate, OperateMultiQubit, OperatePragma)]
#[derive(Eq)]
pub struct PragmaStopDecompositionBlock {
qubits: Vec<usize>,
}
#[wrap(
Operate,
OperateSingleQubit,
OperatePragma,
OperatePragmaNoise,
OperatePragmaNoiseProba
)]
pub struct PragmaDamping {
qubit: usize,
gate_time: CalculatorFloat,
rate: CalculatorFloat,
}
#[wrap(
Operate,
OperateSingleQubit,
OperatePragma,
OperatePragmaNoise,
OperatePragmaNoiseProba
)]
pub struct PragmaDepolarising {
qubit: usize,
gate_time: CalculatorFloat,
rate: CalculatorFloat,
}
#[wrap(
Operate,
OperateSingleQubit,
OperatePragma,
OperatePragmaNoise,
OperatePragmaNoiseProba
)]
pub struct PragmaDephasing {
qubit: usize,
gate_time: CalculatorFloat,
rate: CalculatorFloat,
}
#[wrap(
Operate,
OperateSingleQubit,
OperatePragma,
OperatePragmaNoise,
OperatePragmaNoiseProba
)]
pub struct PragmaRandomNoise {
qubit: usize,
gate_time: CalculatorFloat,
depolarising_rate: CalculatorFloat,
dephasing_rate: CalculatorFloat,
}
#[pymodule]
fn pragma_general_noise(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_class::<PragmaGeneralNoiseWrapper>()?;
Ok(())
}
#[pyclass(name = "PragmaGeneralNoise", module = "qoqo.operations")]
#[derive(Clone, Debug, PartialEq)]
pub struct PragmaGeneralNoiseWrapper {
pub internal: PragmaGeneralNoise,
}
insert_pyany_to_operation!(
"PragmaGeneralNoise" =>{
let qbt = op.call_method0("qubit")
.map_err(|_| QoqoError::ConversionError)?;
let qubit: usize = qbt.extract()
.map_err(|_| QoqoError::ConversionError)?;
let gatetm = op.call_method0("gate_time")
.map_err(|_| QoqoError::ConversionError)?;
let gate_time: CalculatorFloat = convert_into_calculator_float(gatetm).map_err(|_| {
QoqoError::ConversionError
})?;
let array = op.call_method0("rates")
.map_err(|_| QoqoError::ConversionError)?;
let rates_array = array.cast_as::<PyArray2<f64>>().unwrap();
let rates = rates_array.readonly().as_array().to_owned();
Ok(PragmaGeneralNoise::new(qubit, gate_time, rates).into())
}
);
insert_operation_to_pyobject!(
Operation::PragmaGeneralNoise(internal) => {
{
let pyref: Py<PragmaGeneralNoiseWrapper> =
Py::new(py, PragmaGeneralNoiseWrapper { internal }).unwrap();
let pyobject: PyObject = pyref.to_object(py);
Ok(pyobject)
}
}
);
#[pymethods]
impl PragmaGeneralNoiseWrapper {
#[new]
fn new(qubit: usize, gate_time: Py<PyAny>, rates: PyReadonlyArray2<f64>) -> PyResult<Self> {
let rates_array = rates.as_array().to_owned();
let gate_time_cf = Python::with_gil(|py| -> PyResult<CalculatorFloat> {
convert_into_calculator_float(gate_time.as_ref(py)).map_err(|_| {
pyo3::exceptions::PyTypeError::new_err(
"Argument gate time cannot be converted to CalculatorFloat",
)
})
})?;
Ok(Self {
internal: PragmaGeneralNoise::new(qubit, gate_time_cf, rates_array),
})
}
fn qubit(&self) -> usize {
*self.internal.qubit()
}
fn gate_time(&self) -> CalculatorFloatWrapper {
CalculatorFloatWrapper {
internal: self.internal.gate_time().clone(),
}
}
fn rates(&self) -> Py<PyArray2<f64>> {
Python::with_gil(|py| -> Py<PyArray2<f64>> {
self.internal.rates().to_pyarray(py).to_owned()
})
}
fn superoperator(&self) -> PyResult<Py<PyArray2<f64>>> {
Python::with_gil(|py| -> PyResult<Py<PyArray2<f64>>> {
match self.internal.superoperator() {
Ok(x) => Ok(x.to_pyarray(py).to_owned()),
Err(err) => Err(PyRuntimeError::new_err(format!("{:?}", err))),
}
})
}
fn involved_qubits(&self) -> PyObject {
let pyobject: PyObject = Python::with_gil(|py| -> PyObject {
PySet::new(py, &[*self.internal.qubit()])
.unwrap()
.to_object(py)
});
pyobject
}
fn tags(&self) -> Vec<String> {
self.internal.tags().iter().map(|s| s.to_string()).collect()
}
fn hqslang(&self) -> &'static str {
self.internal.hqslang()
}
fn is_parametrized(&self) -> bool {
self.internal.is_parametrized()
}
fn substitute_parameters(
&self,
substitution_parameters: std::collections::HashMap<&str, f64>,
) -> PyResult<Self> {
let mut calculator = qoqo_calculator::Calculator::new();
for (key, val) in substitution_parameters.iter() {
calculator.set_variable(key, *val);
}
Ok(Self {
internal: self
.internal
.substitute_parameters(&calculator)
.map_err(|x| {
pyo3::exceptions::PyRuntimeError::new_err(format!(
"Parameter Substitution failed: {:?}",
x
))
})?,
})
}
fn remap_qubits(&self, mapping: std::collections::HashMap<usize, usize>) -> PyResult<Self> {
let new_internal = self
.internal
.remap_qubits(&mapping)
.map_err(|_| pyo3::exceptions::PyRuntimeError::new_err("Qubit remapping failed: "))?;
Ok(Self {
internal: new_internal,
})
}
fn __copy__(&self) -> PragmaGeneralNoiseWrapper {
self.clone()
}
fn __deepcopy__(&self, _memodict: Py<PyAny>) -> PragmaGeneralNoiseWrapper {
self.clone()
}
fn __format__(&self, _format_spec: &str) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __repr__(&self) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __richcmp__(&self, other: Py<PyAny>, op: pyo3::class::basic::CompareOp) -> PyResult<bool> {
let other: Operation = Python::with_gil(|py| -> PyResult<Operation> {
let other_ref = other.as_ref(py);
crate::operations::convert_pyany_to_operation(other_ref).map_err(|_| {
pyo3::exceptions::PyTypeError::new_err(
"Right hand side cannot be converted to Operation",
)
})
})?;
match op {
pyo3::class::basic::CompareOp::Eq => {
Ok(Operation::from(self.internal.clone()) == other)
}
pyo3::class::basic::CompareOp::Ne => {
Ok(Operation::from(self.internal.clone()) != other)
}
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented.",
)),
}
}
}
#[wrap(Operate, OperatePragma)]
pub struct PragmaConditional {
condition_register: String,
condition_index: usize,
circuit: Circuit,
}
#[pyclass(name = "PragmaChangeDevice", module = "qoqo.operations")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PragmaChangeDeviceWrapper {
pub internal: PragmaChangeDevice,
}
insert_pyany_to_operation!(
"PragmaChangeDevice" =>{
let wt = op.call_method0( "wrapped_tags").map_err(|_|QoqoError::ConversionError)?;
let wrapped_tags: Vec<String> = wt.extract()
.map_err(|_| QoqoError::ConversionError)?;
let wh = op.call_method0( "wrapped_hqslang").map_err(|_|QoqoError::ConversionError)?;
let wrapped_hqslang: String = wh.extract()
.map_err(|_|QoqoError::ConversionError)?;
let wo = op.call_method0( "wrapped_operation").map_err(|_|QoqoError::ConversionError)?;
let wrapped_operation: Vec<u8> = wo.extract()
.map_err(|_|QoqoError::ConversionError)?;
Ok( PragmaChangeDevice{wrapped_tags, wrapped_hqslang, wrapped_operation}.into())
}
);
insert_operation_to_pyobject!(
Operation::PragmaChangeDevice(internal) => {
{
let pyref: Py<PragmaChangeDeviceWrapper> =
Py::new(py, PragmaChangeDeviceWrapper { internal }).unwrap();
let pyobject: PyObject = pyref.to_object(py);
Ok(pyobject)
}
}
);
#[pymethods]
impl PragmaChangeDeviceWrapper {
#[new]
fn new() -> PyResult<Self> {
Err(PyTypeError::new_err("A PragmaChangeDevice wrapper Pragma cannot be created directly, use a .to_pragma_change_device() from the wrapped PRAGMA instead"))
}
fn wrapped_tags(&self) -> Vec<String> {
self.internal
.wrapped_tags
.iter()
.map(|s| s.to_string())
.collect()
}
fn wrapped_hqslang(&self) -> String {
self.internal.wrapped_hqslang.to_string()
}
fn wrapped_operation(&self) -> PyResult<Py<PyByteArray>> {
let serialized: Vec<u8> = self.internal.wrapped_operation.clone();
let b: Py<PyByteArray> = Python::with_gil(|py| -> Py<PyByteArray> {
PyByteArray::new(py, &serialized[..]).into()
});
Ok(b)
}
fn involved_qubits(&self) -> PyObject {
let pyobject: PyObject =
Python::with_gil(|py| -> PyObject { PySet::new(py, &["All"]).unwrap().to_object(py) });
pyobject
}
fn tags(&self) -> Vec<String> {
self.internal.tags().iter().map(|s| s.to_string()).collect()
}
fn hqslang(&self) -> &'static str {
self.internal.hqslang()
}
fn is_parametrized(&self) -> bool {
self.internal.is_parametrized()
}
fn substitute_parameters(
&self,
substitution_parameters: std::collections::HashMap<&str, f64>,
) -> PyResult<Self> {
let mut calculator = qoqo_calculator::Calculator::new();
for (key, val) in substitution_parameters.iter() {
calculator.set_variable(key, *val);
}
Ok(Self {
internal: self
.internal
.substitute_parameters(&calculator)
.map_err(|x| {
pyo3::exceptions::PyRuntimeError::new_err(format!(
"Parameter Substitution failed: {:?}",
x
))
})?,
})
}
fn remap_qubits(&self, mapping: std::collections::HashMap<usize, usize>) -> PyResult<Self> {
let new_internal = self
.internal
.remap_qubits(&mapping)
.map_err(|_| pyo3::exceptions::PyRuntimeError::new_err("Qubit remapping failed: "))?;
Ok(Self {
internal: new_internal,
})
}
fn __copy__(&self) -> PragmaChangeDeviceWrapper {
self.clone()
}
fn __deepcopy__(&self, _memodict: Py<PyAny>) -> PragmaChangeDeviceWrapper {
self.clone()
}
fn __format__(&self, _format_spec: &str) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __repr__(&self) -> PyResult<String> {
Ok(format!("{:?}", self.internal))
}
fn __richcmp__(&self, other: Py<PyAny>, op: pyo3::class::basic::CompareOp) -> PyResult<bool> {
let other: Operation = Python::with_gil(|py| -> PyResult<Operation> {
let other_ref = other.as_ref(py);
crate::operations::convert_pyany_to_operation(other_ref).map_err(|_| {
pyo3::exceptions::PyTypeError::new_err(
"Right hand side cannot be converted to Operation",
)
})
})?;
match op {
pyo3::class::basic::CompareOp::Eq => {
Ok(Operation::from(self.internal.clone()) == other)
}
pyo3::class::basic::CompareOp::Ne => {
Ok(Operation::from(self.internal.clone()) != other)
}
_ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
"Other comparison not implemented.",
)),
}
}
}
#[cfg(test)]
mod tests {
use crate::operations::*;
use bincode::serialize;
use roqoqo::operations::*;
use std::collections::HashSet;
#[test]
fn test_pyo3_involved_qubits_all_change_device() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let input_definition: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(input_definition).unwrap();
let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
let involved_op: HashSet<&str> = HashSet::extract(to_involved.as_ref(py)).unwrap();
let mut involved_param: HashSet<&str> = HashSet::new();
involved_param.insert("All");
assert_eq!(involved_op, involved_param);
assert!(PragmaChangeDeviceWrapper::new().is_err());
})
}
#[test]
fn test_pyo3_format_repr_change_device() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
let format_repr = format!("PragmaChangeDevice {{ wrapped_tags: {:?}, wrapped_hqslang: {:?}, wrapped_operation: {:?} }}", wrapped.tags(), wrapped.hqslang(), serialize(&wrapped).unwrap());
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(input_measurement).unwrap();
let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
let to_repr = operation.call_method0(py, "__repr__").unwrap();
let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
assert_eq!(format_op, format_repr);
assert_eq!(repr_op, format_repr);
})
}
#[test]
fn test_pyo3_copy_deepcopy_change_device() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(input_measurement).unwrap();
let copy_op = operation.call_method0(py, "__copy__").unwrap();
let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
let copy_deepcopy_param = operation;
let comparison_copy = bool::extract(
copy_op
.as_ref(py)
.call_method1("__eq__", (copy_deepcopy_param.clone(),))
.unwrap(),
)
.unwrap();
assert!(comparison_copy);
let comparison_deepcopy = bool::extract(
deepcopy_op
.as_ref(py)
.call_method1("__eq__", (copy_deepcopy_param,))
.unwrap(),
)
.unwrap();
assert!(comparison_deepcopy);
})
}
#[test]
fn test_pyo3_tags_simple_change_device() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(input_measurement).unwrap();
let to_tag = operation.call_method0(py, "tags").unwrap();
let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
let tags_param: &[&str] = &["Operation", "PragmaOperation", "PragmaChangeDevice"];
assert_eq!(tags_op, tags_param);
})
}
#[test]
fn test_pyo3_hqslang_change_device() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(input_measurement).unwrap();
let hqslang_op: String =
String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
assert_eq!(hqslang_op, "PragmaChangeDevice".to_string());
})
}
#[test]
fn test_pyo3_is_parametrized_change_device() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(input_measurement).unwrap();
assert!(!bool::extract(
operation
.call_method0(py, "is_parametrized")
.unwrap()
.as_ref(py)
)
.unwrap());
})
}
#[test]
fn test_pyo3_substitute_parameters() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let first_op: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
let second_op: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(first_op).unwrap();
let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
substitution_dict.insert("test", 1.0);
let substitute_op = operation
.call_method1(py, "substitute_parameters", (substitution_dict,))
.unwrap();
let substitute_param = convert_operation_to_pyobject(second_op).unwrap();
let comparison = bool::extract(
substitute_op
.as_ref(py)
.call_method1("__eq__", (substitute_param,))
.unwrap(),
)
.unwrap();
assert!(comparison);
})
}
#[test]
fn test_pyo3_remap_qubits() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let first_op: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
let second_op: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(first_op).unwrap();
let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
qubit_mapping.insert(0, 0);
let remapped_op = operation
.call_method1(py, "remap_qubits", (qubit_mapping,))
.unwrap();
let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
let comparison = bool::extract(
remapped_op
.call_method1(py, "__eq__", (comparison_op,))
.unwrap()
.as_ref(py),
)
.unwrap();
assert!(comparison);
})
}
#[test]
fn test_pyo3_remap_qubits_error() {
let wrapped: Operation = PragmaActiveReset::new(0).into();
let first_op: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation = convert_operation_to_pyobject(first_op).unwrap();
let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
qubit_mapping.insert(0, 2);
let remapped_op = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
assert!(remapped_op.is_err());
})
}
#[test]
fn test_pyo3_richcmp_change_device() {
let wrapped_1: Operation = PragmaActiveReset::new(0).into();
let definition_1: Operation = PragmaChangeDevice::new(&wrapped_1).unwrap().into();
let wrapped_2: Operation = PragmaActiveReset::new(1).into();
let definition_2: Operation = PragmaChangeDevice::new(&wrapped_2).unwrap().into();
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
let comparison = bool::extract(
operation_one
.as_ref(py)
.call_method1("__eq__", (operation_two.clone(),))
.unwrap(),
)
.unwrap();
assert!(!comparison);
let comparison = bool::extract(
operation_one
.as_ref(py)
.call_method1("__ne__", (operation_two.clone(),))
.unwrap(),
)
.unwrap();
assert!(comparison);
let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
assert!(comparison.is_err());
let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
assert!(comparison.is_err());
})
}
}