use crate::circuit::standard_gate_ops;
use crate::states::{ProductState, Qubit, SuperPosition};
#[derive(Clone, PartialEq, Debug)]
pub enum Gate<'a> {
Id,
H,
X,
Y,
Z,
S,
Sdag,
T,
Tdag,
Rx(f64),
Ry(f64),
Rz(f64),
X90,
Y90,
MX90,
MY90,
Phase(f64),
CR(f64, usize),
CRk(i32, usize),
CZ(usize),
CY(usize),
CNot(usize),
Swap(usize),
Toffoli(usize, usize),
Custom(
fn(ProductState) -> Option<SuperPosition>,
&'a [usize],
String,
),
}
impl<'a> Gate<'a> {
pub(super) fn get_nodes(&self) -> Option<Vec<usize>> {
match self {
Gate::Id
| Gate::H
| Gate::S
| Gate::Sdag
| Gate::T
| Gate::Tdag
| Gate::X
| Gate::Y
| Gate::Z
| Gate::Rx(_)
| Gate::Ry(_)
| Gate::Rz(_)
| Gate::Phase(_)
| Gate::X90
| Gate::Y90
| Gate::MX90
| Gate::MY90 => None,
Gate::CNot(c)
| Gate::Swap(c)
| Gate::CZ(c)
| Gate::CY(c)
| Gate::CR(_, c)
| Gate::CRk(_, c) => Some(vec![*c]),
Gate::Toffoli(c1, c2) => Some(vec![*c1, *c2]),
Gate::Custom(_, nodes, _) => Some(nodes.to_vec()),
}
}
pub(crate) fn linker(&self) -> GateCategory {
match self {
Gate::Id => GateCategory::Identity,
Gate::H => GateCategory::Single(standard_gate_ops::hadamard),
Gate::S => GateCategory::Single(standard_gate_ops::phase),
Gate::Sdag => GateCategory::Single(standard_gate_ops::phasedag),
Gate::T => GateCategory::Single(standard_gate_ops::tgate),
Gate::Tdag => GateCategory::Single(standard_gate_ops::tgatedag),
Gate::X => GateCategory::Single(standard_gate_ops::pauli_x),
Gate::Y => GateCategory::Single(standard_gate_ops::pauli_y),
Gate::Z => GateCategory::Single(standard_gate_ops::pauli_z),
Gate::X90 => GateCategory::Single(standard_gate_ops::x90),
Gate::Y90 => GateCategory::Single(standard_gate_ops::y90),
Gate::MX90 => GateCategory::Single(standard_gate_ops::mx90),
Gate::MY90 => GateCategory::Single(standard_gate_ops::my90),
Gate::Rx(arg) => GateCategory::SingleArg(*arg, standard_gate_ops::rx),
Gate::Ry(arg) => GateCategory::SingleArg(*arg, standard_gate_ops::ry),
Gate::Rz(arg) => GateCategory::SingleArg(*arg, standard_gate_ops::rz),
Gate::Phase(arg) => GateCategory::SingleArg(*arg, standard_gate_ops::global_phase),
Gate::CNot(c) => GateCategory::Double(*c, standard_gate_ops::cnot),
Gate::Swap(c) => GateCategory::Double(*c, standard_gate_ops::swap),
Gate::CZ(c) => GateCategory::Double(*c, standard_gate_ops::cz),
Gate::CY(c) => GateCategory::Double(*c, standard_gate_ops::cy),
Gate::CR(arg, c) => GateCategory::DoubleArg(*arg, *c, standard_gate_ops::cr),
Gate::CRk(arg, c) => GateCategory::DoubleArgInt(*arg, *c, standard_gate_ops::crk),
Gate::Toffoli(c1, c2) => GateCategory::Triple(*c1, *c2, standard_gate_ops::toffoli),
Gate::Custom(func, controls, _) => GateCategory::Custom(*func, controls),
}
}
pub(crate) fn is_single_gate(&self) -> bool {
match self {
Gate::Id
| Gate::H
| Gate::S
| Gate::Sdag
| Gate::T
| Gate::Tdag
| Gate::X
| Gate::Y
| Gate::Z
| Gate::Rx(_)
| Gate::Ry(_)
| Gate::Rz(_)
| Gate::Phase(_)
| Gate::X90
| Gate::Y90
| Gate::MX90
| Gate::MY90 => true,
Gate::CNot(_)
| Gate::Swap(_)
| Gate::CZ(_)
| Gate::CY(_)
| Gate::CR(_, _)
| Gate::CRk(_, _)
| Gate::Toffoli(_, _)
| Gate::Custom(_, _, _) => false,
}
}
pub(crate) fn get_name(&self) -> String {
match self {
Gate::Id => "".to_string(),
Gate::X => "X".to_string(),
Gate::H => "H".to_string(),
Gate::S => "S".to_string(),
Gate::Sdag => "S*".to_string(),
Gate::T => "T".to_string(),
Gate::Tdag => "T*".to_string(),
Gate::Y => "Y".to_string(),
Gate::Z => "Z".to_string(),
Gate::Rx(_) => "Rx".to_string(),
Gate::Ry(_) => "Ry".to_string(),
Gate::Rz(_) => "Rz".to_string(),
Gate::Phase(_) => "P".to_string(),
Gate::X90 => "X90".to_string(),
Gate::Y90 => "Y90".to_string(),
Gate::MX90 => "X90*".to_string(),
Gate::MY90 => "Y90*".to_string(),
Gate::CR(_, _) => "CR".to_string(),
Gate::CRk(_, _) => "CRk".to_string(),
Gate::Swap(_) => "Sw".to_string(),
Gate::CZ(_) => "Z".to_string(),
Gate::CY(_) => "Y".to_string(),
Gate::CNot(_) => "X".to_string(),
Gate::Toffoli(_, _) => "X".to_string(),
Gate::Custom(_, _, name) => name.to_string(),
}
}
}
#[derive(PartialEq, Debug)]
pub(crate) enum GateCategory<'a> {
Identity,
Single(fn(Qubit) -> SuperPosition),
SingleArg(f64, fn(Qubit, f64) -> SuperPosition),
Double(usize, fn(Qubit, Qubit) -> SuperPosition),
DoubleArg(f64, usize, fn(Qubit, Qubit, f64) -> SuperPosition),
DoubleArgInt(i32, usize, fn(Qubit, Qubit, i32) -> SuperPosition),
Triple(usize, usize, fn(Qubit, Qubit, Qubit) -> SuperPosition),
Custom(fn(ProductState) -> Option<SuperPosition>, &'a [usize]),
}
#[derive(Debug)]
pub(crate) struct GateInfo<'a> {
pub cat_gate: GateCategory<'a>,
pub position: usize,
}