use crate::operations::single_qubit_gate_operations::*;
use crate::prelude::*;
use crate::Circuit;
use crate::RoqoqoError;
use ndarray::{array, Array2};
use num_complex::Complex64;
use qoqo_calculator::{CalculatorComplex, CalculatorFloat};
#[cfg(feature = "overrotate")]
use rand_distr::{Distribution, Normal};
use std::convert::TryFrom;
use std::f64::consts::PI;
use super::SupportedVersion;
#[derive(Debug, Clone, PartialEq)]
pub struct KakDecomposition {
pub global_phase: CalculatorFloat,
pub k_vector: [CalculatorFloat; 3],
pub circuit_before: Option<Circuit>,
pub circuit_after: Option<Circuit>,
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct CNOT {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_CNOT: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"CNOT",
];
impl OperateGate for CNOT {
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(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(1.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 OperateTwoQubitGate for CNOT {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateX::new(self.target, CalculatorFloat::FRAC_PI_2);
let mut circuit_a = Circuit::new();
circuit_a += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
KakDecomposition {
global_phase: CalculatorFloat::FRAC_PI_4,
k_vector: [
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct SWAP {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_SWAP: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"SWAP",
];
impl OperateGate for SWAP {
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(1.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(1.0, 0.0)
],
])
}
}
impl OperateTwoQubitGate for SWAP {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::from(-PI / 4.0),
k_vector: [
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::FRAC_PI_4,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ISwap {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_ISwap: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"ISwap",
];
impl OperateGate for ISwap {
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, 1.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 1.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 OperateTwoQubitGate for ISwap {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::ZERO,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct FSwap {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_FSwap: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"FSwap",
];
impl OperateGate for FSwap {
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(1.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(-1.0, 0.0)
],
])
}
}
impl OperateTwoQubitGate for FSwap {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
circuit_b += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2 * (-1.0));
KakDecomposition {
global_phase: CalculatorFloat::FRAC_PI_2 * (-1.0),
k_vector: [
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::ZERO,
],
circuit_before: Some(circuit_b),
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct SqrtISwap {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_SqrtISwap: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"SqrtISwap",
];
impl OperateGate for SqrtISwap {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let f: f64 = 1.0 / ((2.0_f64).sqrt());
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(f, 0.0),
Complex64::new(0.0, f),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, f),
Complex64::new(f, 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 OperateTwoQubitGate for SqrtISwap {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
CalculatorFloat::from(PI / 8.0),
CalculatorFloat::from(PI / 8.0),
CalculatorFloat::ZERO,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct InvSqrtISwap {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_InvSqrtISwap: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"InvSqrtISwap",
];
impl OperateGate for InvSqrtISwap {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let f: f64 = 1.0 / ((2.0_f64).sqrt());
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(f, 0.0),
Complex64::new(0.0, -f),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -f),
Complex64::new(f, 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 OperateTwoQubitGate for InvSqrtISwap {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
CalculatorFloat::from(-PI / 8.0),
CalculatorFloat::from(-PI / 8.0),
CalculatorFloat::ZERO,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct XY {
control: usize,
target: usize,
theta: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_XY: &[&str; 5] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Rotation",
"XY",
];
impl OperateGate for XY {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).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(c, 0.0),
Complex64::new(0.0, s),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, s),
Complex64::new(c, 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 OperateTwoQubitGate for XY {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
self.theta.clone() / 4.0,
self.theta.clone() / 4.0,
CalculatorFloat::ZERO,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledPhaseShift {
control: usize,
target: usize,
theta: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_ControlledPhaseShift: &[&str; 5] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Rotation",
"ControlledPhaseShift",
];
impl OperateGate for ControlledPhaseShift {
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(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(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(c, s)
],
])
}
}
impl OperateTwoQubitGate for ControlledPhaseShift {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, self.theta.clone() / 2.0);
circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
KakDecomposition {
global_phase: self.theta.clone() / 4.0,
k_vector: [
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
self.theta.clone() / 4.0,
],
circuit_before: Some(circuit_b),
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledPauliY {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_ControlledPauliY: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"ControlledPauliY",
];
impl OperateGate for ControlledPauliY {
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(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, -1.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 1.0),
Complex64::new(0.0, 0.0)
],
])
}
}
impl OperateTwoQubitGate for ControlledPauliY {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateY::new(self.target, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateX::new(self.target, CalculatorFloat::FRAC_PI_2);
let mut circuit_a = Circuit::new();
circuit_a += RotateX::new(self.target, CalculatorFloat::FRAC_PI_2 * (-1.0));
KakDecomposition {
global_phase: CalculatorFloat::FRAC_PI_4,
k_vector: [
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
CalculatorFloat::FRAC_PI_4,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledPauliZ {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_ControlledPauliZ: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"ControlledPauliZ",
];
impl OperateGate for ControlledPauliZ {
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(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(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(-1.0, 0.0)
],
])
}
}
impl OperateTwoQubitGate for ControlledPauliZ {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2);
KakDecomposition {
global_phase: CalculatorFloat::FRAC_PI_4,
k_vector: [
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
CalculatorFloat::FRAC_PI_4,
],
circuit_before: Some(circuit_b),
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
Eq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct MolmerSorensenXX {
control: usize,
target: usize,
}
#[allow(non_upper_case_globals)]
const TAGS_MolmerSorensenXX: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"MolmerSorensenXX",
];
impl OperateGate for MolmerSorensenXX {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let f: f64 = 1.0 / ((2.0_f64).sqrt());
Ok(array![
[
Complex64::new(f, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -f)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(f, 0.0),
Complex64::new(0.0, -f),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -f),
Complex64::new(f, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, -f),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(f, 0.0)
],
])
}
}
impl OperateTwoQubitGate for MolmerSorensenXX {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
CalculatorFloat::from(-PI / 4.0),
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct VariableMSXX {
control: usize,
target: usize,
theta: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_VariableMSXX: &[&str; 5] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Rotation",
"VariableMSXX",
];
impl OperateGate for VariableMSXX {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
Ok(array![
[
Complex64::new(c, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -s)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(c, 0.0),
Complex64::new(0.0, -s),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -s),
Complex64::new(c, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, -s),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(c, 0.0)
],
])
}
}
impl OperateTwoQubitGate for VariableMSXX {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
self.theta.clone() * (-1.0 / 2.0),
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct GivensRotation {
control: usize,
target: usize,
theta: CalculatorFloat,
phi: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_GivensRotation: &[&str; 5] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Rotation",
"GivensRotation",
];
impl OperateGate for GivensRotation {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let ct: f64 = (f64::try_from(self.theta.clone())?).cos();
let st: f64 = (f64::try_from(self.theta.clone())?).sin();
let cp: f64 = (f64::try_from(self.phi.clone())?).cos();
let sp: f64 = (f64::try_from(self.phi.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(ct * cp, ct * sp),
Complex64::new(st, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(-st * cp, -st * sp),
Complex64::new(ct, 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(cp, sp)
],
])
}
}
impl OperateTwoQubitGate for GivensRotation {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.target, self.phi.clone() + (PI / 2.0));
let mut circuit_a = Circuit::new();
circuit_a += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2 * (-1.0));
KakDecomposition {
global_phase: self.phi.clone() / 2.0,
k_vector: [
self.theta.clone() / 2.0,
self.theta.clone() / 2.0,
CalculatorFloat::ZERO,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct GivensRotationLittleEndian {
control: usize,
target: usize,
theta: CalculatorFloat,
phi: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_GivensRotationLittleEndian: &[&str; 5] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Rotation",
"GivensRotationLittleEndian",
];
impl OperateGate for GivensRotationLittleEndian {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let ct: f64 = (f64::try_from(self.theta.clone())?).cos();
let st: f64 = (f64::try_from(self.theta.clone())?).sin();
let cp: f64 = (f64::try_from(self.phi.clone())?).cos();
let sp: f64 = (f64::try_from(self.phi.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(ct, 0.0),
Complex64::new(st, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(-st * cp, -st * sp),
Complex64::new(ct * cp, ct * sp),
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(cp, sp)
],
])
}
}
impl OperateTwoQubitGate for GivensRotationLittleEndian {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
let mut circuit_a = Circuit::new();
circuit_a += RotateZ::new(self.control, self.phi.clone() + (PI / 2.0));
KakDecomposition {
global_phase: self.phi.clone() / 2.0,
k_vector: [
self.theta.clone() / 2.0,
self.theta.clone() / 2.0,
CalculatorFloat::ZERO,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct Qsim {
control: usize,
target: usize,
x: CalculatorFloat,
y: CalculatorFloat,
z: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_Qsim: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Qsim",
];
impl OperateGate for Qsim {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let x: f64 = f64::try_from(self.x.clone())?;
let y: f64 = f64::try_from(self.y.clone())?;
let z: f64 = f64::try_from(self.z.clone())?;
let cm: f64 = (x - y).cos();
let cp: f64 = (x + y).cos();
let sm: f64 = (x - y).sin();
let sp: f64 = (x + y).sin();
let cz: f64 = z.cos();
let sz: f64 = z.sin();
Ok(array![
[
Complex64::new(cm * cz, -cm * sz),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(-sm * sz, -sm * cz)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(sp * sz, -sp * cz),
Complex64::new(cp * cz, cp * sz),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(cp * cz, cp * sz),
Complex64::new(sp * sz, -sp * cz),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(-sm * sz, -sm * cz),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cm * cz, -cm * sz)
],
])
}
}
impl OperateTwoQubitGate for Qsim {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::from(-PI / 4.0),
k_vector: [
self.x.clone() * (-1.0) + PI / 4.0,
self.y.clone() * (-1.0) + PI / 4.0,
self.z.clone() * (-1.0) + PI / 4.0,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct Fsim {
control: usize,
target: usize,
t: CalculatorFloat,
u: CalculatorFloat,
delta: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_Fsim: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Fsim",
];
impl OperateGate for Fsim {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let t: f64 = f64::try_from(self.t.clone())?;
let u: f64 = f64::try_from(self.u.clone())?;
let d: f64 = f64::try_from(self.delta.clone())?;
Ok(array![
[
Complex64::new(d.cos(), 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, d.sin())
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -t.sin()),
Complex64::new(t.cos(), 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(t.cos(), 0.0),
Complex64::new(0.0, -t.sin()),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(-d.sin() * u.sin(), -d.sin() * u.cos()),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(-d.cos() * u.cos(), d.cos() * u.sin())
],
])
}
}
impl OperateTwoQubitGate for Fsim {
fn kak_decomposition(&self) -> KakDecomposition {
let theta = self.u.clone() / (-2.0) - PI / 2.0;
let mut circuit_a = Circuit::new();
circuit_a += RotateZ::new(self.control, theta.clone());
circuit_a += RotateZ::new(self.target, theta);
KakDecomposition {
global_phase: self.u.clone() / (-4.0) - PI / 2.0,
k_vector: [
(self.t.clone() / (-2.0) + self.delta.clone() / 2.0 + PI / 4.0),
(self.t.clone() / (-2.0) - self.delta.clone() / 2.0 + PI / 4.0),
self.u.clone() / (-4.0),
],
circuit_before: None,
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct SpinInteraction {
control: usize,
target: usize,
x: CalculatorFloat,
y: CalculatorFloat,
z: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_SpinInteraction: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"SpinInteraction",
];
impl OperateGate for SpinInteraction {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let x: f64 = f64::try_from(self.x.clone())?;
let y: f64 = f64::try_from(self.y.clone())?;
let z: f64 = f64::try_from(self.z.clone())?;
let cm: f64 = (x - y).cos();
let cp: f64 = (x + y).cos();
let sm: f64 = (x - y).sin();
let sp: f64 = (x + y).sin();
let cz: f64 = z.cos();
let sz: f64 = z.sin();
Ok(array![
[
Complex64::new(cm * cz, -cm * sz),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(-sm * sz, -sm * cz)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(cp * cz, cp * sz),
Complex64::new(sp * sz, -sp * cz),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(sp * sz, -sp * cz),
Complex64::new(cp * cz, cp * sz),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(-sm * sz, -sm * cz),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cm * cz, -cm * sz)
],
])
}
}
impl OperateTwoQubitGate for SpinInteraction {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
self.x.clone() * (-1.0),
self.y.clone() * (-1.0),
self.z.clone() * (-1.0),
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct Bogoliubov {
control: usize,
target: usize,
delta_real: CalculatorFloat,
delta_imag: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_Bogoliubov: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Bogoliubov",
];
impl OperateGate for Bogoliubov {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let dr: f64 = f64::try_from(self.delta_real.clone())?;
let di: f64 = f64::try_from(self.delta_imag.clone())?;
let delta: Complex64 = Complex64::new(dr, di);
let da: f64 = delta.norm(); let dp: f64 = delta.arg(); Ok(array![
[
Complex64::new(da.cos(), 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(-da.sin() * dp.sin(), da.sin() * dp.cos())
],
[
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(1.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(da.sin() * dp.sin(), da.sin() * dp.cos()),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(da.cos(), 0.0)
],
])
}
}
impl OperateTwoQubitGate for Bogoliubov {
fn kak_decomposition(&self) -> KakDecomposition {
let dr = self.delta_real.clone();
let di = self.delta_imag.clone();
let delta: CalculatorComplex = CalculatorComplex::new(dr, di);
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.target, delta.arg());
let mut circuit_a = Circuit::new();
circuit_a += RotateZ::new(self.target, delta.arg() * (-1.0));
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
delta.norm() / (2.0),
delta.norm() / (-2.0),
CalculatorFloat::ZERO,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct PMInteraction {
control: usize,
target: usize,
t: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_PMInteraction: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"PMInteraction",
];
impl OperateGate for PMInteraction {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let c: f64 = (f64::try_from(self.t.clone())?).cos();
let s: f64 = (f64::try_from(self.t.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(c, 0.0),
Complex64::new(0.0, -s),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -s),
Complex64::new(c, 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 OperateTwoQubitGate for PMInteraction {
fn kak_decomposition(&self) -> KakDecomposition {
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
self.t.clone() / (-2.0),
self.t.clone() / (-2.0),
CalculatorFloat::ZERO,
],
circuit_before: None,
circuit_after: None,
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ComplexPMInteraction {
control: usize,
target: usize,
t_real: CalculatorFloat,
t_imag: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_ComplexPMInteraction: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"ComplexPMInteraction",
];
impl OperateGate for ComplexPMInteraction {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let tr: f64 = f64::try_from(self.t_real.clone())?;
let ti: f64 = f64::try_from(self.t_imag.clone())?;
let t: Complex64 = Complex64::new(tr, ti);
let tn: f64 = t.norm(); let ta: f64 = t.arg(); 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(tn.cos(), 0.0),
Complex64::new(-tn.sin() * ta.sin(), -tn.sin() * ta.cos()),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(tn.sin() * ta.sin(), -tn.sin() * ta.cos()),
Complex64::new(tn.cos(), 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 OperateTwoQubitGate for ComplexPMInteraction {
fn kak_decomposition(&self) -> KakDecomposition {
let tr = self.t_real.clone();
let ti = self.t_imag.clone();
let t: CalculatorComplex = CalculatorComplex::new(tr, ti);
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.target, t.arg());
let mut circuit_a = Circuit::new();
circuit_a += RotateZ::new(self.target, t.arg() * (-1.0));
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [t.norm() / (-2.0), t.norm() / (-2.0), CalculatorFloat::ZERO],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::SupportedVersion,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct PhaseShiftedControlledZ {
control: usize,
target: usize,
phi: CalculatorFloat,
}
#[allow(non_upper_case_globals)]
const TAGS_PhaseShiftedControlledZ: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"PhaseShiftedControlledZ",
];
impl OperateGate for PhaseShiftedControlledZ {
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 + PI).cos();
let sin2: f64 = (2.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(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(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(cos2, sin2)
],
])
}
}
impl OperateTwoQubitGate for PhaseShiftedControlledZ {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2);
let mut circuit_a = Circuit::new();
circuit_a += RotateZ::new(self.control, self.phi.clone());
circuit_a += RotateZ::new(self.target, self.phi.clone());
let g: CalculatorFloat = CalculatorFloat::FRAC_PI_4 + self.phi.clone();
KakDecomposition {
global_phase: g,
k_vector: [
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
CalculatorFloat::FRAC_PI_4,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct PhaseShiftedControlledPhase {
control: usize,
target: usize,
theta: CalculatorFloat,
phi: CalculatorFloat,
}
impl SupportedVersion for PhaseShiftedControlledPhase {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 2, 0)
}
}
impl super::ImplementedIn1point2 for PhaseShiftedControlledPhase {}
#[allow(non_upper_case_globals)]
const TAGS_PhaseShiftedControlledPhase: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"PhaseShiftedControlledPhase",
];
impl OperateGate for PhaseShiftedControlledPhase {
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 + theta).cos();
let sin2: f64 = (2.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(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(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(cos2, sin2)
],
])
}
}
impl OperateTwoQubitGate for PhaseShiftedControlledPhase {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.control, self.theta.clone() / 2.0);
circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
let mut circuit_a = Circuit::new();
circuit_a += RotateZ::new(self.control, self.phi.clone());
circuit_a += RotateZ::new(self.target, self.phi.clone());
let g: CalculatorFloat = self.theta.clone() / 4.0 + self.phi.clone();
KakDecomposition {
global_phase: g,
k_vector: [
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
self.theta.clone() / 4.0,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledRotateX {
control: usize,
target: usize,
theta: CalculatorFloat,
}
impl SupportedVersion for ControlledRotateX {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 3, 0)
}
}
impl super::ImplementedIn1point3 for ControlledRotateX {}
#[allow(non_upper_case_globals)]
const TAGS_ControlledRotateX: &[&str; 5] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Rotation",
"ControlledRotateX",
];
impl OperateGate for ControlledRotateX {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).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(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(c, 0.0),
Complex64::new(0.0, -s)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -s),
Complex64::new(c, 0.0)
]
])
}
}
impl OperateTwoQubitGate for ControlledRotateX {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += Hadamard::new(self.target);
circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
let mut circuit_a = Circuit::new();
circuit_a += Hadamard::new(self.target);
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
self.theta.clone() / 4.0,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
roqoqo_derive::Rotate,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ControlledRotateXY {
control: usize,
target: usize,
theta: CalculatorFloat,
phi: CalculatorFloat,
}
impl SupportedVersion for ControlledRotateXY {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 3, 0)
}
}
impl super::ImplementedIn1point3 for ControlledRotateXY {}
#[allow(non_upper_case_globals)]
const TAGS_ControlledRotateXY: &[&str; 5] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"Rotation",
"ControlledRotateXY",
];
impl OperateGate for ControlledRotateXY {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
let vx: f64 = (f64::try_from(self.phi.clone())?).cos();
let vy: f64 = (f64::try_from(self.phi.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(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(c, 0.0),
Complex64::new(-s * vy, -s * vx)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(s * vy, -s * vx),
Complex64::new(c, 0.0)
]
])
}
}
impl OperateTwoQubitGate for ControlledRotateXY {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += RotateZ::new(self.target, -self.phi.clone());
circuit_b += Hadamard::new(self.target);
circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
let mut circuit_a = Circuit::new();
circuit_a += Hadamard::new(self.target);
circuit_a += RotateZ::new(self.target, self.phi.clone());
KakDecomposition {
global_phase: CalculatorFloat::ZERO,
k_vector: [
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
self.theta.clone() / 4.0,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Clone,
PartialEq,
roqoqo_derive::InvolveQubits,
roqoqo_derive::Operate,
roqoqo_derive::Substitute,
roqoqo_derive::OperateTwoQubit,
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct EchoCrossResonance {
control: usize,
target: usize,
}
impl SupportedVersion for EchoCrossResonance {
fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
(1, 8, 0)
}
}
impl super::ImplementedIn1point8 for EchoCrossResonance {}
#[allow(non_upper_case_globals)]
const TAGS_EchoCrossResonance: &[&str; 4] = &[
"Operation",
"GateOperation",
"TwoQubitGateOperation",
"EchoCrossResonance",
];
impl OperateGate for EchoCrossResonance {
fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
let matrix: Array2<Complex64> = array![
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 1.0)
],
[
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 1.0),
Complex64::new(1.0, 0.0)
],
[
Complex64::new(1.0, 0.0),
Complex64::new(0.0, -1.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
],
[
Complex64::new(0.0, -1.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0)
]
];
Ok(matrix / 2.0_f64.sqrt())
}
}
impl OperateTwoQubitGate for EchoCrossResonance {
fn kak_decomposition(&self) -> KakDecomposition {
let mut circuit_b = Circuit::new();
circuit_b += SGate::new(self.control);
circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2);
circuit_b += RotateX::new(self.target, CalculatorFloat::PI);
let mut circuit_a = Circuit::new();
circuit_a += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
circuit_a += PauliX::new(self.control);
KakDecomposition {
global_phase: CalculatorFloat::FRAC_PI_4,
k_vector: [
CalculatorFloat::FRAC_PI_4,
CalculatorFloat::ZERO,
CalculatorFloat::ZERO,
],
circuit_before: Some(circuit_b),
circuit_after: Some(circuit_a),
}
}
}