LCOV - code coverage report
Current view: top level - src - quantum_program.rs (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 46 46 100.0 %
Date: 2021-11-09 13:25:48 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright © 2021 HQS Quantum Simulations GmbH. All Rights Reserved.
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
       4             : // in compliance with the License. You may obtain a copy of the License at
       5             : //
       6             : //     http://www.apache.org/licenses/LICENSE-2.0
       7             : //
       8             : // Unless required by applicable law or agreed to in writing, software distributed under the
       9             : // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
      10             : // express or implied. See the License for the specific language governing permissions and
      11             : // limitations under the License.
      12             : 
      13             : use std::collections::HashMap;
      14             : 
      15             : use crate::backends::{EvaluatingBackend, RegisterResult};
      16             : use crate::measurements;
      17             : use crate::measurements::Measure;
      18             : use crate::RoqoqoBackendError;
      19             : use std::fmt::{Display, Formatter};
      20             : /// Represents a quantum program evaluating measurements based on a one or more free float parameters.
      21             : ///
      22             : /// The main use of QuantumProgram is to contain a Measurements implementing [crate::measurements::Measure]
      23             : /// that measures expectation values or output registers of [crate::Circuit] quantum circuits that contain
      24             : /// symbolic parameters. Circuit with symbolic parameters can not be simulated or executed on real hardware.
      25             : /// The symbolic parameters need to be replaced with real floating point numbers first.
      26             : /// A QuantumProgram contains a list of the free parameters (`input_parameter_names`) and can automatically
      27             : /// replace the parameters with its `run` methods and return the result.
      28             : ///
      29             : /// The QuantumProgram should correspond as closely as possible to a normal mulit-parameter function
      30             : /// in classical computing that can be called with a set of parameters and returns a result.
      31             : /// It is the intended way to interface between normal program code and roqoqo based quantum programs.
      32             : ///
      33             : #[derive(Debug, PartialEq, Clone)]
      34             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
      35             : pub enum QuantumProgram {
      36             :     /// Variant for basis rotation measurement based quantum programs
      37             :     BasisRotation {
      38             :         /// The measurement that is performed
      39             :         measurement: measurements::BasisRotation,
      40             :         /// List of free input parameters that can be set when the QuantumProgram is executed
      41             :         input_parameter_names: Vec<String>,
      42             :     },
      43             :     /// Variant for cheated basis rotation measurement based quantum programs
      44             :     CheatedBasisRotation {
      45             :         /// The measurement that is performed
      46             :         measurement: measurements::CheatedBasisRotation,
      47             :         /// List of free input parameters that can be set when the QuantumProgram is executed
      48             :         input_parameter_names: Vec<String>,
      49             :     },
      50             :     /// Variant for statevector/density matrix based measurements
      51             :     Cheated {
      52             :         /// The measurement that is performed
      53             :         measurement: measurements::Cheated,
      54             :         /// List of free input parameters that can be set when the QuantumProgram is executed
      55             :         input_parameter_names: Vec<String>,
      56             :     },
      57             :     /// Variant quantum programs returning full classical registers
      58             :     ClassicalRegister {
      59             :         /// The measurement that is performed
      60             :         measurement: measurements::ClassicalRegister,
      61             :         /// List of free input parameters that can be set when the QuantumProgram is executed
      62             :         input_parameter_names: Vec<String>,
      63             :     },
      64             : }
      65             : 
      66             : impl QuantumProgram {
      67             :     /// Runs the QuantumProgram and returns expectation values.
      68             :     ///
      69             :     /// Runs the quantum programm for a given set of parameters passed in the same order as the parameters
      70             :     /// listed in `input_parameter_names` and returns expectation values.
      71             :     ///
      72             :     /// Arguments:
      73             :     ///
      74             :     /// * `backend` - The backend the program is executed on.
      75             :     /// * `parameters` - List of float ([f64]) parameters of the function call in order of `input_parameter_names`
      76          10 :     pub fn run<T>(
      77          10 :         &self,
      78          10 :         backend: T,
      79          10 :         parameters: &[f64],
      80          10 :     ) -> Result<Option<HashMap<String, f64>>, RoqoqoBackendError>
      81          10 :     where
      82          10 :         T: EvaluatingBackend,
      83          10 :     {
      84          10 :         match self{
      85           3 :             QuantumProgram::BasisRotation{measurement, input_parameter_names } => {
      86           3 :                 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())})};
      87           2 :                 let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
      88           1 :                 let substituted_measurement = measurement.substitute_parameters(
      89           1 :                     substituted_parameters
      90           1 :                 )?;
      91           1 :                 backend.run_measurement(&substituted_measurement)
      92             :             }
      93           3 :             QuantumProgram::CheatedBasisRotation{measurement, input_parameter_names } => {
      94           3 :                 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())})};
      95           2 :                 let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
      96           1 :                 let substituted_measurement = measurement.substitute_parameters(
      97           1 :                     substituted_parameters
      98           1 :                 )?;
      99           1 :                 backend.run_measurement(&substituted_measurement)
     100             :             }
     101           3 :             QuantumProgram::Cheated{measurement, input_parameter_names } => {
     102           3 :                 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())})};
     103           2 :                 let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
     104           1 :                 let substituted_measurement = measurement.substitute_parameters(
     105           1 :                     substituted_parameters
     106           1 :                 )?;
     107           1 :                 backend.run_measurement(&substituted_measurement)
     108             :             }
     109           1 :             _ => Err(RoqoqoBackendError::GenericError{msg: "A quantum programm returning classical registeres cannot be executed by `run` use `run_registers` instead".to_string()})
     110             :         }
     111          10 :     }
     112             : 
     113             :     /// Runs the QuantumProgram and returns the classical registers of the quantum program.
     114             :     ///
     115             :     /// Runs the quantum programm for a given set of parameters passed in the same order as the parameters
     116             :     /// listed in `input_parameter_names` and returns the classical register output.  
     117             :     /// The classical registers usually contain a record of measurement values for the repeated execution
     118             :     /// of a [crate::Circuit] quantum circuit for real quantum hardware
     119             :     /// or the readout of the statevector or the density matrix for simulators.
     120             :     ///
     121             :     /// Arguments:
     122             :     ///
     123             :     /// * `backend` - The backend the program is executed on.
     124             :     /// * `parameters` - List of float ([f64]) parameters of the function call in order of `input_parameter_names`
     125           6 :     pub fn run_registers<T>(&self, backend: T, parameters: &[f64]) -> RegisterResult
     126           6 :     where
     127           6 :         T: EvaluatingBackend,
     128           6 :     {
     129           6 :         match self{
     130           3 :             QuantumProgram::ClassicalRegister{measurement, input_parameter_names } => {
     131           3 :                 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())})};
     132           2 :                 let substituted_parameters: HashMap<String, f64> = input_parameter_names.iter().zip(parameters.iter()).map(|(key, value)| (key.clone(), *value)).collect();
     133           1 :                 let substituted_measurement = measurement.substitute_parameters(
     134           1 :                     substituted_parameters
     135           1 :                 )?;
     136           1 :                 backend.run_measurement_registers(&substituted_measurement)
     137             :             }
     138           3 :             _ => Err(RoqoqoBackendError::GenericError{msg: "A quantum programm returning expectation values cannot be executed by `run_registers` use `run` instead".to_string()})
     139             :         }
     140           6 :     }
     141             : }
     142             : 
     143             : /// Implements the Display trait for QuantumProgram.
     144             : impl Display for QuantumProgram {
     145             :     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
     146             :         let mut s: String = String::new();
     147             : 
     148             :         match self {
     149             :             QuantumProgram::BasisRotation { .. } => {
     150             :                 s.push_str(&"QuantumProgram::BasisRotation".to_string());
     151             :             }
     152             :             QuantumProgram::CheatedBasisRotation { .. } => {
     153             :                 s.push_str(&"QuantumProgram::CheatedBasisRotation".to_string());
     154             :             }
     155             :             QuantumProgram::Cheated { .. } => {
     156             :                 s.push_str(&"QuantumProgram::Cheated".to_string());
     157             :             }
     158             :             QuantumProgram::ClassicalRegister { .. } => {
     159             :                 s.push_str(&"QuantumProgram::ClassicalRegister".to_string());
     160             :             }
     161             :         }
     162             : 
     163             :         write!(f, "{}", s)
     164             :     }
     165             : }

Generated by: LCOV version 1.13