use super::{ControlledPhaseShift, Hadamard, PhaseShiftedControlledPhase, CNOT};
use super::{RotateZ, TGate};
use crate::prelude::*;
use crate::Circuit;
use ndarray::{array, Array2};
use num_complex::Complex64;
use qoqo_calculator::CalculatorFloat;
#[cfg(feature = "overrotate")]
use rand_distr::{Distribution, Normal};
use std::f64::consts::PI;
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateThreeQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledControlledPauliZ {
control_0: usize,
control_1: usize,
target: usize,
}
impl super::ImplementedIn1point3 for ControlledControlledPauliZ {}
impl SupportedVersion for ControlledControlledPauliZ {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 3, 0)
}
}
#[allow(non_upper_case_globals)]
const TAGS_ControlledControlledPauliZ: &[&str; 4] = &[
"Operation",
"GateOperation",
"ThreeQubitGateOperation",
"ControlledControlledPauliZ",
];
impl OperateGate for ControlledControlledPauliZ {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
Ok(array![
[
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(-1.0, 0.0)
],
])
}
}
impl OperateThreeQubitGate for ControlledControlledPauliZ {
fn circuit(&self) -> Circuit {
let mut circuit = Circuit::new();
circuit +=
ControlledPhaseShift::new(self.control_1, self.target, CalculatorFloat::FRAC_PI_2);
circuit += CNOT::new(self.control_0, self.control_1);
circuit +=
ControlledPhaseShift::new(self.control_1, self.target, -CalculatorFloat::FRAC_PI_2);
circuit += CNOT::new(self.control_0, self.control_1);
circuit +=
ControlledPhaseShift::new(self.control_0, self.target, CalculatorFloat::FRAC_PI_2);
circuit
}
}
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateThreeQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledControlledPhaseShift {
control_0: usize,
control_1: usize,
target: usize,
theta: CalculatorFloat,
}
impl super::ImplementedIn1point3 for ControlledControlledPhaseShift {}
impl SupportedVersion for ControlledControlledPhaseShift {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 3, 0)
}
}
#[allow(non_upper_case_globals)]
const TAGS_ControlledControlledPhaseShift: &[&str; 5] = &[
"Operation",
"GateOperation",
"ThreeQubitGateOperation",
"Rotation",
"ControlledControlledPhaseShift",
];
impl OperateGate for ControlledControlledPhaseShift {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let c: f64 = (f64::try_from(self.theta.clone())?).cos();
let s: f64 = (f64::try_from(self.theta.clone())?).sin();
Ok(array![
[
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(c, s)
],
])
}
}
impl OperateThreeQubitGate for ControlledControlledPhaseShift {
fn circuit(&self) -> Circuit {
let mut circuit = Circuit::new();
circuit += ControlledPhaseShift::new(self.control_1, self.target, self.theta.clone() / 2.0);
circuit += CNOT::new(self.control_0, self.control_1);
circuit +=
ControlledPhaseShift::new(self.control_1, self.target, -self.theta.clone() / 2.0);
circuit += CNOT::new(self.control_0, self.control_1);
circuit += ControlledPhaseShift::new(self.control_0, self.target, self.theta.clone() / 2.0);
circuit
}
}
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateThreeQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct Toffoli {
control_0: usize,
control_1: usize,
target: usize,
}
impl super::ImplementedIn1point3 for Toffoli {}
impl SupportedVersion for Toffoli {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 3, 0)
}
}
#[allow(non_upper_case_globals)]
const TAGS_Toffoli: &[&str; 4] = &[
"Operation",
"GateOperation",
"ThreeQubitGateOperation",
"Toffoli",
];
impl OperateGate for Toffoli {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
Ok(array![
[
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0)
],
])
}
}
impl OperateThreeQubitGate for Toffoli {
fn circuit(&self) -> Circuit {
let mut circuit = Circuit::new();
circuit += Hadamard::new(self.target);
circuit += CNOT::new(self.control_1, self.target);
circuit += RotateZ::new(self.target, -CalculatorFloat::FRAC_PI_4);
circuit += CNOT::new(self.control_0, self.target);
circuit += TGate::new(self.target);
circuit += CNOT::new(self.control_1, self.target);
circuit += RotateZ::new(self.target, -CalculatorFloat::FRAC_PI_4);
circuit += CNOT::new(self.control_0, self.target);
circuit += TGate::new(self.control_1);
circuit += TGate::new(self.target);
circuit += Hadamard::new(self.target);
circuit += CNOT::new(self.control_0, self.control_1);
circuit += TGate::new(self.control_0);
circuit += RotateZ::new(self.control_1, -CalculatorFloat::FRAC_PI_4);
circuit += CNOT::new(self.control_0, self.control_1);
circuit
}
}
#[derive(Debug, Clone, PartialEq, Eq, roqoqo_derive::Operate)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledSWAP {
control: usize,
target_0: usize,
target_1: usize,
}
impl super::ImplementedIn1point16 for ControlledSWAP {}
impl SupportedVersion for ControlledSWAP {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 16, 0)
}
}
#[allow(non_upper_case_globals)]
const TAGS_ControlledSWAP: &[&str; 4] = &[
"Operation",
"GateOperation",
"ThreeQubitGateOperation",
"ControlledSWAP",
];
impl OperateGate for ControlledSWAP {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
Ok(array![
[
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0)
],
])
}
}
impl OperateThreeQubitGate for ControlledSWAP {
fn circuit(&self) -> Circuit {
let mut circuit = Circuit::new();
circuit += CNOT::new(self.target_1, self.target_0);
circuit += Hadamard::new(self.target_1);
circuit += CNOT::new(self.target_0, self.target_1);
circuit += RotateZ::new(self.target_1, -CalculatorFloat::FRAC_PI_4);
circuit += CNOT::new(self.control, self.target_1);
circuit += TGate::new(self.target_1);
circuit += CNOT::new(self.target_0, self.target_1);
circuit += RotateZ::new(self.target_1, -CalculatorFloat::FRAC_PI_4);
circuit += CNOT::new(self.control, self.target_1);
circuit += TGate::new(self.target_0);
circuit += TGate::new(self.target_1);
circuit += Hadamard::new(self.target_1);
circuit += CNOT::new(self.control, self.target_0);
circuit += TGate::new(self.control);
circuit += RotateZ::new(self.target_0, -CalculatorFloat::FRAC_PI_4);
circuit += CNOT::new(self.control, self.target_0);
circuit += CNOT::new(self.target_1, self.target_0);
circuit
}
}
impl OperateThreeQubit for ControlledSWAP {
fn target(&self) -> &usize {
&self.target_1
}
fn control_0(&self) -> &usize {
&self.control
}
fn control_1(&self) -> &usize {
&self.target_0
}
}
impl Substitute for ControlledSWAP {
fn substitute_parameters(
&self,
_calculator: &qoqo_calculator::Calculator,
) -> Result<Self, RoqoqoError> {
Ok(Self::new(self.control, self.target_0, self.target_1))
}
fn remap_qubits(
&self,
mapping: &std::collections::HashMap<usize, usize>,
) -> Result<Self, RoqoqoError> {
crate::operations::check_valid_mapping(mapping)?;
Ok(Self::new(
*mapping.get(&self.control).unwrap_or(&self.control),
*mapping.get(&self.target_0).unwrap_or(&self.target_0),
*mapping.get(&self.target_1).unwrap_or(&self.target_1),
))
}
}
impl InvolveQubits for ControlledSWAP {
fn involved_qubits(&self) -> InvolvedQubits {
let mut new_hash_set: std::collections::HashSet<usize> = std::collections::HashSet::new();
new_hash_set.insert(self.control);
new_hash_set.insert(self.target_0);
new_hash_set.insert(self.target_1);
InvolvedQubits::Set(new_hash_set)
}
}
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateThreeQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct PhaseShiftedControlledControlledZ {
control_0: usize,
control_1: usize,
target: usize,
phi: CalculatorFloat,
}
impl super::ImplementedIn1point16 for PhaseShiftedControlledControlledZ {}
impl SupportedVersion for PhaseShiftedControlledControlledZ {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 16, 0)
}
}
#[allow(non_upper_case_globals)]
const TAGS_PhaseShiftedControlledControlledZ: &[&str; 4] = &[
"Operation",
"GateOperation",
"ThreeQubitGateOperation",
"PhaseShiftedControlledControlledZ",
];
impl OperateGate for PhaseShiftedControlledControlledZ {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let phi: f64 = f64::try_from(self.phi.clone())?;
let cos: f64 = phi.cos();
let sin: f64 = phi.sin();
let cos2: f64 = (2.0 * phi).cos();
let sin2: f64 = (2.0 * phi).sin();
let cos3: f64 = (3.0 * phi + PI).cos();
let sin3: f64 = (3.0 * phi + PI).sin();
Ok(array![
[
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(cos, sin),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos, sin),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos2, sin2),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos, sin),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos2, sin2),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos2, sin2),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos3, sin3)
],
])
}
}
impl OperateThreeQubitGate for PhaseShiftedControlledControlledZ {
fn circuit(&self) -> Circuit {
let mut circuit = Circuit::new();
circuit += PhaseShiftedControlledPhase::new(
self.control_1,
self.target,
CalculatorFloat::FRAC_PI_2,
self.phi.clone(),
);
circuit += CNOT::new(self.control_0, self.control_1);
circuit += PhaseShiftedControlledPhase::new(
self.control_1,
self.target,
-CalculatorFloat::FRAC_PI_2,
self.phi.clone(),
);
circuit += CNOT::new(self.control_0, self.control_1);
circuit += PhaseShiftedControlledPhase::new(
self.control_0,
self.target,
CalculatorFloat::FRAC_PI_2,
self.phi.clone(),
);
circuit
}
}
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateThreeQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct PhaseShiftedControlledControlledPhase {
control_0: usize,
control_1: usize,
target: usize,
theta: CalculatorFloat,
phi: CalculatorFloat,
}
impl super::ImplementedIn1point16 for PhaseShiftedControlledControlledPhase {}
impl SupportedVersion for PhaseShiftedControlledControlledPhase {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 16, 0)
}
}
#[allow(non_upper_case_globals)]
const TAGS_PhaseShiftedControlledControlledPhase: &[&str; 4] = &[
"Operation",
"GateOperation",
"ThreeQubitGateOperation",
"PhaseShiftedControlledControlledPhase",
];
impl OperateGate for PhaseShiftedControlledControlledPhase {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let phi: f64 = f64::try_from(self.phi.clone())?;
let theta: f64 = f64::try_from(self.theta.clone())?;
let cos: f64 = phi.cos();
let sin: f64 = phi.sin();
let cos2: f64 = (2.0 * phi).cos();
let sin2: f64 = (2.0 * phi).sin();
let cos3: f64 = (3.0 * phi + theta).cos();
let sin3: f64 = (3.0 * phi + theta).sin();
Ok(array![
[
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(cos, sin),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos, sin),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos2, sin2),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos, sin),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos2, sin2),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos2, sin2),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos3, sin3)
],
])
}
}
impl OperateThreeQubitGate for PhaseShiftedControlledControlledPhase {
fn circuit(&self) -> Circuit {
let mut circuit = Circuit::new();
circuit += PhaseShiftedControlledPhase::new(
self.control_1,
self.target,
self.theta.clone() / 2,
self.phi.clone(),
);
circuit += CNOT::new(self.control_0, self.control_1);
circuit += PhaseShiftedControlledPhase::new(
self.control_1,
self.target,
-self.theta.clone() / 2,
self.phi.clone(),
);
circuit += CNOT::new(self.control_0, self.control_1);
circuit += PhaseShiftedControlledPhase::new(
self.control_0,
self.target,
self.theta.clone() / 2,
self.phi.clone(),
);
circuit
}
}