LCOV - code coverage report
Current view: top level - src/measurements - cheated_basis_rotation_measurement.rs (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 59 60 98.3 %
Date: 2021-11-09 13:25:48 Functions: 8 8 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 super::*;
      14             : use ndarray::Array1;
      15             : #[cfg(feature = "serialize")]
      16             : use serde::{Deserialize, Serialize};
      17             : 
      18             : /// Collected information for executing a cheated basis rotation measurement.
      19           2 : #[derive(Debug, PartialEq, Clone)]
      20             : #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
      21             : pub struct CheatedBasisRotation {
      22             :     /// Constant Circuit that is executed before each Circuit in circuits.
      23             :     pub constant_circuit: Option<Circuit>,
      24             :     /// Collection of quantum circuits for the separate basis rotations.
      25             :     pub circuits: Vec<Circuit>,
      26             :     /// Additional input information required for measurement.
      27             :     pub input: CheatedBasisRotationInput,
      28             : }
      29             : 
      30             : impl Measure for CheatedBasisRotation {
      31             :     /// Returns the constant Circuit that is executed before each Circuit in circuits.
      32             :     ///
      33             :     /// # Returns
      34             :     ///
      35             :     /// * `&Option<Circuit` - The constant Circuit (None if not defined).
      36           3 :     fn constant_circuit(&self) -> &Option<Circuit> {
      37           3 :         &self.constant_circuit
      38           3 :     }
      39             : 
      40             :     /// Returns iterator over circuits for measurement.
      41             :     ///
      42             :     /// # Returns
      43             :     ///
      44             :     /// * `Box<dyn Iterator<Item = &'a Circuit> + 'a>` - The quantum circuits.
      45           3 :     fn circuits<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Circuit> + 'a> {
      46           3 :         Box::new(self.circuits.iter())
      47           3 :     }
      48             : 
      49             :     /// Returns clone of Measurement with symbolic parameters replaced.
      50             :     ///
      51             :     /// # Arguments
      52             :     ///
      53             :     /// * `substituted_parameters` - The HashMap containing the substitutions to use in the Circuit.
      54             :     ///
      55             :     /// # Returns
      56             :     ///
      57             :     /// * `Ok(Self)` -  The Circuits with the parameters substituted.
      58             :     /// * `Err(RoqoqoError)` - The subsitution failed.
      59           3 :     fn substitute_parameters(
      60           3 :         &self,
      61           3 :         substituted_parameters: HashMap<String, f64>,
      62           3 :     ) -> Result<Self, RoqoqoError> {
      63           3 :         let mut calculator = qoqo_calculator::Calculator::new();
      64           9 :         for (name, val) in substituted_parameters.iter() {
      65           6 :             calculator.set_variable(name, *val)
      66             :         }
      67           3 :         let new_constant_circuit = match &self.constant_circuit {
      68           0 :             None => None,
      69           3 :             Some(c) => Some(c.substitute_parameters(&mut calculator)?),
      70             :         };
      71           2 :         let mut new_circuits = Vec::new();
      72           2 :         for circ in self.circuits.iter() {
      73           2 :             let mut calculator = qoqo_calculator::Calculator::new();
      74           6 :             for (name, val) in substituted_parameters.iter() {
      75           4 :                 calculator.set_variable(name, *val)
      76             :             }
      77           2 :             new_circuits.push(circ.substitute_parameters(&mut calculator)?)
      78             :         }
      79           2 :         Ok(Self {
      80           2 :             constant_circuit: new_constant_circuit,
      81           2 :             circuits: new_circuits,
      82           2 :             input: self.input.clone(),
      83           2 :         })
      84           3 :     }
      85             : }
      86             : 
      87             : impl MeasureExpectationValues for CheatedBasisRotation {
      88             :     /// Executes the cheated basis rotation measurement
      89             :     ///
      90             :     /// # Arguments
      91             :     ///
      92             :     /// * `bit_registers` - The classical bit registers as a HashMap with the register name as key
      93             :     /// * `float_registers` - The classical float registers as a HashMap with the register name as key
      94             :     /// * `complex_registers` - The classical complex registers as a HashMap with the register name as key
      95             :     ///
      96             :     /// # Returns
      97             :     ///
      98             :     /// * `Ok(Some(HashMap<String, f64>))` - The measurement has been evaluated successfully. The HashMap contains the measured expectation values
      99             :     /// * `Ok(None)` - The measurement did not fail but is incomplete. A new round of measurements is needed
     100             :     /// * `Err(RoqoqoError)` - Calculator parsing error.
     101             :     ///
     102             :     #[allow(unused_variables)]
     103           3 :     fn evaluate(
     104           3 :         &self,
     105           3 :         bit_registers: HashMap<String, BitOutputRegister>,
     106           3 :         float_registers: HashMap<String, FloatOutputRegister>,
     107           3 :         complex_registers: HashMap<String, ComplexOutputRegister>,
     108           3 :     ) -> Result<Option<HashMap<String, f64>>, RoqoqoError> {
     109           3 :         let mut pauli_products: Array1<f64> = Array1::zeros(self.input.pauli_product_keys.len());
     110           9 :         for (register_name, register) in float_registers.iter() {
     111           6 :             if let Some(index) = self.input.pauli_product_keys.get(register_name) {
     112           6 :                 pauli_products[*index] = register[0][0];
     113           6 :             }
     114             :         }
     115             :         // Evaluating expectation values
     116           3 :         let mut results: HashMap<String, f64> = HashMap::new();
     117             : 
     118           6 :         for (name, evaluation) in self.input.measured_exp_vals.iter() {
     119             :             results.insert(
     120           3 :                 name.clone(),
     121           3 :                 match evaluation {
     122           2 :                     PauliProductsToExpVal::Linear(hm) => {
     123           2 :                         let mut value: f64 = 0.0;
     124           6 :                         for (index, coefficient) in hm {
     125           4 :                             value += pauli_products[*index] * coefficient;
     126           4 :                         }
     127           2 :                         value
     128             :                     }
     129           1 :                     PauliProductsToExpVal::Symbolic(x) => {
     130           1 :                         let mut calculator = qoqo_calculator::Calculator::new();
     131           3 :                         for (ind, p) in pauli_products.iter().enumerate() {
     132           3 :                             dbg!(ind);
     133           3 :                             dbg!(p);
     134           3 :                             calculator.set_variable(format!("pauli_product_{}", ind).as_str(), *p);
     135           3 :                         }
     136           1 :                         calculator.parse_get(x.clone())?
     137             :                     }
     138             :                 },
     139             :             );
     140             :         }
     141             : 
     142           3 :         Ok(Some(results))
     143           3 :     }
     144             : }

Generated by: LCOV version 1.13