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 crate::operations;
14 : use crate::prelude::*;
15 : use crate::Circuit;
16 : use crate::RoqoqoError;
17 : use ndarray::Array2;
18 : use num_complex::Complex64;
19 : use qoqo_calculator::CalculatorFloat;
20 : #[cfg(feature = "overrotate")]
21 : use rand_distr::{Distribution, Normal};
22 : #[cfg(feature = "serialize")]
23 : use serde::{Deserialize, Serialize};
24 :
25 : /// The Molmer-Sorensen gate between multiple qubits.
26 : ///
27 : #[allow(clippy::upper_case_acronyms)]
28 : #[derive(
29 1 : Debug,
30 7 : Clone,
31 9 : PartialEq,
32 1 : roqoqo_derive::InvolveQubits,
33 35 : roqoqo_derive::Operate,
34 6 : roqoqo_derive::Substitute,
35 2 : roqoqo_derive::OperateMultiQubit,
36 24 : roqoqo_derive::Rotate,
37 : )]
38 : #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
39 : pub struct MultiQubitMS {
40 : /// The qubits involved in the multi qubit Molmer-Sorensen gate.
41 : qubits: Vec<usize>,
42 : /// The angle of the multi qubit Molmer-Sorensen gate.
43 : theta: CalculatorFloat,
44 : }
45 :
46 : #[allow(non_upper_case_globals)]
47 : const TAGS_MultiQubitMS: &[&str; 4] = &[
48 : "Operation",
49 : "GateOperation",
50 : "MultiQubitGateOperation",
51 : "MultiQubitMS",
52 : ];
53 :
54 : impl OperateGate for MultiQubitMS {
55 2 : fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
56 2 : let dim = 2_usize.pow(self.qubits.len() as u32);
57 2 : let mut array: Array2<Complex64> = Array2::zeros((dim, dim));
58 2 : let cos: Complex64 = Complex64::new((self.theta.float()? / 2.0).cos(), 0.0);
59 2 : let sin: Complex64 = Complex64::new(0.0, -(self.theta.float()? / 2.0).sin());
60 12 : for i in 0..dim {
61 12 : array[(i, i)] = cos;
62 12 : array[(i, dim - i - 1)] = sin;
63 12 : }
64 2 : Ok(array)
65 2 : }
66 : }
67 :
68 : impl OperateMultiQubitGate for MultiQubitMS {
69 : // Todo fill out circuit
70 2 : fn circuit(&self) -> Circuit {
71 2 : let dim = self.qubits.len();
72 2 : let mut circuit = Circuit::new();
73 5 : for q in self.qubits.iter() {
74 5 : circuit += operations::Hadamard::new(*q);
75 5 : }
76 3 : for q in self.qubits[1..].iter() {
77 3 : circuit += operations::CNOT::new(*q - 1, *q);
78 3 : }
79 2 : circuit += operations::RotateZ::new(dim - 1, self.theta.clone() / 2);
80 3 : for q in self.qubits[1..].iter() {
81 3 : circuit += operations::CNOT::new(dim - *q - 1, dim - *q);
82 3 : }
83 5 : for q in self.qubits.iter() {
84 5 : circuit += operations::Hadamard::new(*q);
85 5 : }
86 2 : circuit
87 2 : }
88 : }
|