use std::collections::HashMap;
#[cfg(feature = "async")]
use crate::backends::AsyncEvaluatingBackend;
use crate::backends::{EvaluatingBackend, RegisterResult};
use crate::measurements;
use crate::measurements::Measure;
use crate::RoqoqoBackendError;
use std::fmt::{Display, Formatter};
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum QuantumProgram {
PauliZProduct {
measurement: measurements::PauliZProduct,
input_parameter_names: Vec<String>,
},
CheatedPauliZProduct {
measurement: measurements::CheatedPauliZProduct,
input_parameter_names: Vec<String>,
},
Cheated {
measurement: measurements::Cheated,
input_parameter_names: Vec<String>,
},
ClassicalRegister {
measurement: measurements::ClassicalRegister,
input_parameter_names: Vec<String>,
},
}
impl QuantumProgram {
pub fn run<T>(
&self,
backend: T,
parameters: &[f64],
) -> Result<Option<HashMap<String, f64>>, RoqoqoBackendError>
where
T: EvaluatingBackend,
{
match self{
QuantumProgram::PauliZProduct{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.run_measurement(&substituted_measurement)
}
QuantumProgram::CheatedPauliZProduct{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.run_measurement(&substituted_measurement)
}
QuantumProgram::Cheated{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.run_measurement(&substituted_measurement)
}
_ => Err(RoqoqoBackendError::GenericError{msg: "A quantum programm returning classical registeres cannot be executed by `run` use `run_registers` instead".to_string()})
}
}
pub fn run_registers<T>(&self, backend: T, parameters: &[f64]) -> RegisterResult
where
T: EvaluatingBackend,
{
match self{
QuantumProgram::ClassicalRegister{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.run_measurement_registers(&substituted_measurement)
}
_ => Err(RoqoqoBackendError::GenericError{msg: "A quantum programm returning expectation values cannot be executed by `run_registers` use `run` instead".to_string()})
}
}
#[cfg(feature = "async")]
pub async fn async_run<T>(
&self,
backend: T,
parameters: &[f64],
) -> Result<Option<HashMap<String, f64>>, RoqoqoBackendError>
where
T: AsyncEvaluatingBackend,
T: Sync,
{
match self{
QuantumProgram::PauliZProduct{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.async_run_measurement(&substituted_measurement).await
}
QuantumProgram::CheatedPauliZProduct{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.async_run_measurement(&substituted_measurement).await
}
QuantumProgram::Cheated{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.async_run_measurement(&substituted_measurement).await
}
_ => Err(RoqoqoBackendError::GenericError{msg: "A quantum programm returning classical registeres cannot be executed by `run` use `run_registers` instead".to_string()})
}
}
#[cfg(feature = "async")]
pub async fn async_run_registers<T>(&self, backend: T, parameters: &[f64]) -> RegisterResult
where
T: AsyncEvaluatingBackend,
T: Sync,
{
match self{
QuantumProgram::ClassicalRegister{measurement, input_parameter_names } => {
if parameters.len() != input_parameter_names.len() { return Err(RoqoqoBackendError::GenericError{msg: format!("Wrong number of parameters {} parameters expected {} parameters given", input_parameter_names.len(), parameters.len())})};
let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
let substituted_measurement = measurement.substitute_parameters(
substituted_parameters
)?;
backend.async_run_measurement_registers(&substituted_measurement).await
}
_ => Err(RoqoqoBackendError::GenericError{msg: "A quantum programm returning expectation values cannot be executed by `run_registers` use `run` instead".to_string()})
}
}
}
impl Display for QuantumProgram {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut s: String = String::new();
match self {
QuantumProgram::PauliZProduct { .. } => {
s.push_str("QuantumProgram::PauliZProduct");
}
QuantumProgram::CheatedPauliZProduct { .. } => {
s.push_str("QuantumProgram::CheatedPauliZProduct");
}
QuantumProgram::Cheated { .. } => {
s.push_str("QuantumProgram::Cheated");
}
QuantumProgram::ClassicalRegister { .. } => {
s.push_str("QuantumProgram::ClassicalRegister");
}
}
write!(f, "{}", s)
}
}
impl crate::operations::SupportedVersion for QuantumProgram {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
match self {
QuantumProgram::PauliZProduct { measurement, .. } => {
measurement.minimum_supported_roqoqo_version()
}
QuantumProgram::CheatedPauliZProduct { measurement, .. } => {
measurement.minimum_supported_roqoqo_version()
}
QuantumProgram::Cheated { measurement, .. } => {
measurement.minimum_supported_roqoqo_version()
}
QuantumProgram::ClassicalRegister { measurement, .. } => {
measurement.minimum_supported_roqoqo_version()
}
}
}
}