use crate::error::QuantRS2Result;
use crate::qubit::QubitId;
use scirs2_core::Complex64;
use std::any::Any;
use std::f64::consts::PI;
use std::fmt::Debug;
macro_rules! impl_clone_gate {
() => {
fn clone_gate(&self) -> Box<dyn GateOp> {
Box::new(self.clone())
}
};
}
pub trait GateOp: Debug + Send + Sync {
fn name(&self) -> &'static str;
fn qubits(&self) -> Vec<QubitId>;
fn num_qubits(&self) -> usize {
self.qubits().len()
}
fn is_parameterized(&self) -> bool {
false
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>>;
fn as_any(&self) -> &dyn Any;
fn clone_gate(&self) -> Box<dyn GateOp>;
}
impl Clone for Box<dyn GateOp> {
fn clone(&self) -> Self {
self.clone_gate()
}
}
pub mod single {
use super::*;
use super::*;
#[derive(Debug, Clone, Copy)]
pub struct Hadamard {
pub target: QubitId,
}
impl GateOp for Hadamard {
fn name(&self) -> &'static str {
"H"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
Ok(vec![
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(-sqrt2_inv, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct PauliX {
pub target: QubitId,
}
impl GateOp for PauliX {
fn name(&self) -> &'static str {
"X"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct PauliY {
pub target: QubitId,
}
impl GateOp for PauliY {
fn name(&self) -> &'static str {
"Y"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -1.0),
Complex64::new(0.0, 1.0),
Complex64::new(0.0, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct PauliZ {
pub target: QubitId,
}
impl GateOp for PauliZ {
fn name(&self) -> &'static str {
"Z"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(-1.0, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RotationX {
pub target: QubitId,
pub theta: f64,
}
impl GateOp for RotationX {
fn name(&self) -> &'static str {
"RX"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
Ok(vec![
Complex64::new(cos, 0.0),
Complex64::new(0.0, -sin),
Complex64::new(0.0, -sin),
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RotationY {
pub target: QubitId,
pub theta: f64,
}
impl GateOp for RotationY {
fn name(&self) -> &'static str {
"RY"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
Ok(vec![
Complex64::new(cos, 0.0),
Complex64::new(-sin, 0.0),
Complex64::new(sin, 0.0),
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RotationZ {
pub target: QubitId,
pub theta: f64,
}
impl GateOp for RotationZ {
fn name(&self) -> &'static str {
"RZ"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
Ok(vec![
phase_conj,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
phase,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct Phase {
pub target: QubitId,
}
impl GateOp for Phase {
fn name(&self) -> &'static str {
"S"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 1.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct T {
pub target: QubitId,
}
impl GateOp for T {
fn name(&self) -> &'static str {
"T"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let phase = Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin());
Ok(vec![
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
phase,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct TDagger {
pub target: QubitId,
}
impl GateOp for TDagger {
fn name(&self) -> &'static str {
"T†"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let phase = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
Ok(vec![
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
phase,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct PhaseDagger {
pub target: QubitId,
}
impl GateOp for PhaseDagger {
fn name(&self) -> &'static str {
"S†"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -1.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct SqrtX {
pub target: QubitId,
}
impl GateOp for SqrtX {
fn name(&self) -> &'static str {
"√X"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let half_plus_i_half = Complex64::new(0.5, 0.5);
let half_minus_i_half = Complex64::new(0.5, -0.5);
Ok(vec![
half_plus_i_half,
half_minus_i_half,
half_minus_i_half,
half_plus_i_half,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct SqrtXDagger {
pub target: QubitId,
}
impl GateOp for SqrtXDagger {
fn name(&self) -> &'static str {
"√X†"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let half_minus_i_half = Complex64::new(0.5, -0.5);
let half_plus_i_half = Complex64::new(0.5, 0.5);
Ok(vec![
half_minus_i_half,
half_plus_i_half,
half_plus_i_half,
half_minus_i_half,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct UGate {
pub target: QubitId,
pub theta: f64,
pub phi: f64,
pub lambda: f64,
}
impl GateOp for UGate {
fn name(&self) -> &'static str {
"U"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
let exp_i_phi = Complex64::new(0.0, self.phi).exp();
let exp_i_phi_lambda = Complex64::new(0.0, self.phi + self.lambda).exp();
Ok(vec![
Complex64::new(cos, 0.0),
-exp_i_lambda * sin,
exp_i_phi * sin,
exp_i_phi_lambda * cos,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct PGate {
pub target: QubitId,
pub lambda: f64,
}
impl GateOp for PGate {
fn name(&self) -> &'static str {
"P"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
Ok(vec![
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
exp_i_lambda,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct Identity {
pub target: QubitId,
}
impl GateOp for Identity {
fn name(&self) -> &'static str {
"I"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
Complex64::new(1.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(1.0, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
}
pub mod multi {
use super::*;
#[derive(Debug, Clone, Copy)]
pub struct CNOT {
pub control: QubitId,
pub target: QubitId,
}
impl GateOp for CNOT {
fn name(&self) -> &'static str {
"CNOT"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
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),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CZ {
pub control: QubitId,
pub target: QubitId,
}
impl GateOp for CZ {
fn name(&self) -> &'static str {
"CZ"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
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),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct SWAP {
pub qubit1: QubitId,
pub qubit2: QubitId,
}
impl GateOp for SWAP {
fn name(&self) -> &'static str {
"SWAP"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
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),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CY {
pub control: QubitId,
pub target: QubitId,
}
impl GateOp for CY {
fn name(&self) -> &'static str {
"CY"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
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),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CH {
pub control: QubitId,
pub target: QubitId,
}
impl GateOp for CH {
fn name(&self) -> &'static str {
"CH"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
Ok(vec![
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(sqrt2_inv, 0.0),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(-sqrt2_inv, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CS {
pub control: QubitId,
pub target: QubitId,
}
impl GateOp for CS {
fn name(&self) -> &'static str {
"CS"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
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(0.0, 1.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct Toffoli {
pub control1: QubitId,
pub control2: QubitId,
pub target: QubitId,
}
impl GateOp for Toffoli {
fn name(&self) -> &'static str {
"Toffoli"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control1, self.control2, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Err(crate::error::QuantRS2Error::UnsupportedOperation(
"Direct matrix representation of Toffoli gate not supported. \
Use gate decomposition."
.into(),
))
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct Fredkin {
pub control: QubitId,
pub target1: QubitId,
pub target2: QubitId,
}
impl GateOp for Fredkin {
fn name(&self) -> &'static str {
"Fredkin"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target1, self.target2]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Err(crate::error::QuantRS2Error::UnsupportedOperation(
"Direct matrix representation of Fredkin gate not supported. \
Use gate decomposition."
.into(),
))
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CRX {
pub control: QubitId,
pub target: QubitId,
pub theta: f64,
}
impl GateOp for CRX {
fn name(&self) -> &'static str {
"CRX"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
Ok(vec![
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(cos, 0.0),
Complex64::new(0.0, -sin),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -sin),
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CRY {
pub control: QubitId,
pub target: QubitId,
pub theta: f64,
}
impl GateOp for CRY {
fn name(&self) -> &'static str {
"CRY"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
Ok(vec![
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(cos, 0.0),
Complex64::new(-sin, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(sin, 0.0),
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CRZ {
pub control: QubitId,
pub target: QubitId,
pub theta: f64,
}
impl GateOp for CRZ {
fn name(&self) -> &'static str {
"CRZ"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
Ok(vec![
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),
phase_conj,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
phase,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct ISwap {
pub qubit1: QubitId,
pub qubit2: QubitId,
}
impl GateOp for ISwap {
fn name(&self) -> &'static str {
"iSWAP"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
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),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct ECR {
pub control: QubitId,
pub target: QubitId,
}
impl GateOp for ECR {
fn name(&self) -> &'static str {
"ECR"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
Ok(vec![
Complex64::new(0.0, 0.0),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, sqrt2_inv),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, -sqrt2_inv),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, sqrt2_inv),
Complex64::new(0.0, 0.0),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(0.0, -sqrt2_inv),
Complex64::new(0.0, 0.0),
Complex64::new(sqrt2_inv, 0.0),
Complex64::new(0.0, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RXX {
pub qubit1: QubitId,
pub qubit2: QubitId,
pub theta: f64,
}
impl GateOp for RXX {
fn name(&self) -> &'static str {
"RXX"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
let mi_sin = Complex64::new(0.0, -sin);
Ok(vec![
Complex64::new(cos, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
mi_sin,
Complex64::new(0.0, 0.0),
Complex64::new(cos, 0.0),
mi_sin,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
mi_sin,
Complex64::new(cos, 0.0),
Complex64::new(0.0, 0.0),
mi_sin,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RYY {
pub qubit1: QubitId,
pub qubit2: QubitId,
pub theta: f64,
}
impl GateOp for RYY {
fn name(&self) -> &'static str {
"RYY"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
let i_sin = Complex64::new(0.0, sin);
let mi_sin = Complex64::new(0.0, -sin);
Ok(vec![
Complex64::new(cos, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
i_sin,
Complex64::new(0.0, 0.0),
Complex64::new(cos, 0.0),
mi_sin,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
mi_sin,
Complex64::new(cos, 0.0),
Complex64::new(0.0, 0.0),
i_sin,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RZZ {
pub qubit1: QubitId,
pub qubit2: QubitId,
pub theta: f64,
}
impl GateOp for RZZ {
fn name(&self) -> &'static str {
"RZZ"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let phase_neg = Complex64::new(0.0, -self.theta / 2.0).exp();
let phase_pos = Complex64::new(0.0, self.theta / 2.0).exp();
Ok(vec![
phase_neg,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
phase_pos,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
phase_pos,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
phase_neg,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RZX {
pub control: QubitId,
pub target: QubitId,
pub theta: f64,
}
impl GateOp for RZX {
fn name(&self) -> &'static str {
"RZX"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
let mi_sin = Complex64::new(0.0, -sin);
let i_sin = Complex64::new(0.0, sin);
Ok(vec![
Complex64::new(cos, 0.0),
mi_sin,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
mi_sin,
Complex64::new(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(cos, 0.0),
i_sin,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
i_sin,
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct DCX {
pub qubit1: QubitId,
pub qubit2: QubitId,
}
impl GateOp for DCX {
fn name(&self) -> &'static str {
"DCX"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
Ok(vec![
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(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),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct XXPlusYY {
pub qubit1: QubitId,
pub qubit2: QubitId,
pub theta: f64,
pub beta: f64,
}
impl GateOp for XXPlusYY {
fn name(&self) -> &'static str {
"XXPlusYY"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
let exp_i_beta = Complex64::new(0.0, self.beta).exp();
let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
Ok(vec![
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, 0.0),
mi_sin_neg,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
mi_sin_pos,
Complex64::new(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),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct XXMinusYY {
pub qubit1: QubitId,
pub qubit2: QubitId,
pub theta: f64,
pub beta: f64,
}
impl GateOp for XXMinusYY {
fn name(&self) -> &'static str {
"XXMinusYY"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.qubit1, self.qubit2]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
let exp_i_beta = Complex64::new(0.0, self.beta).exp();
let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
Ok(vec![
Complex64::new(cos, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
mi_sin_pos,
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),
mi_sin_neg,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct CSX {
pub control: QubitId,
pub target: QubitId,
}
impl GateOp for CSX {
fn name(&self) -> &'static str {
"CSX"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.control, self.target]
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let half_plus_i_half = Complex64::new(0.5, 0.5);
let half_minus_i_half = Complex64::new(0.5, -0.5);
Ok(vec![
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),
half_plus_i_half,
half_minus_i_half,
Complex64::new(0.0, 0.0),
Complex64::new(0.0, 0.0),
half_minus_i_half,
half_plus_i_half,
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
}
pub mod global {
use super::*;
#[derive(Debug, Clone, Copy)]
pub struct GlobalPhase {
pub phase: f64,
}
impl GateOp for GlobalPhase {
fn name(&self) -> &'static str {
"GlobalPhase"
}
fn qubits(&self) -> Vec<QubitId> {
vec![]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let phase = Complex64::new(0.0, self.phase).exp();
Ok(vec![phase])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
#[derive(Debug, Clone, Copy)]
pub struct RGate {
pub target: QubitId,
pub theta: f64,
pub phi: f64,
}
impl GateOp for RGate {
fn name(&self) -> &'static str {
"R"
}
fn qubits(&self) -> Vec<QubitId> {
vec![self.target]
}
fn is_parameterized(&self) -> bool {
true
}
fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
let cos = (self.theta / 2.0).cos();
let sin = (self.theta / 2.0).sin();
let exp_neg_i_phi = Complex64::new(0.0, -self.phi).exp();
let exp_i_phi = Complex64::new(0.0, self.phi).exp();
Ok(vec![
Complex64::new(cos, 0.0),
Complex64::new(0.0, -sin) * exp_neg_i_phi,
Complex64::new(0.0, -sin) * exp_i_phi,
Complex64::new(cos, 0.0),
])
}
fn as_any(&self) -> &dyn Any {
self
}
impl_clone_gate!();
}
}