use super::DeviceGateState;
use crate::circuit::StandardGate;
use smallvec::{SmallVec, smallvec};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum DirectionTemplate {
Cx,
Rzx,
Symmetric(StandardGate),
}
impl DirectionTemplate {
pub(super) fn stable_name(self) -> String {
match self {
Self::Cx => "direction_reverse_CX".to_string(),
Self::Rzx => "direction_reverse_RZX".to_string(),
Self::Symmetric(gate) => format!("direction_reverse_{}", gate.name()),
}
}
pub(super) fn child_states(self, parent: &DeviceGateState) -> Vec<DeviceGateState> {
debug_assert_eq!(parent.ordered_qargs.len(), 2);
let q0 = parent.ordered_qargs[0];
let q1 = parent.ordered_qargs[1];
match self {
Self::Cx | Self::Rzx => vec![
DeviceGateState::standard(StandardGate::H, smallvec![q0]),
DeviceGateState::standard(StandardGate::H, smallvec![q1]),
DeviceGateState {
instruction: parent.instruction.clone(),
ordered_qargs: smallvec![q1, q0],
},
DeviceGateState::standard(StandardGate::H, smallvec![q0]),
DeviceGateState::standard(StandardGate::H, smallvec![q1]),
],
Self::Symmetric(_) => vec![DeviceGateState {
instruction: parent.instruction.clone(),
ordered_qargs: smallvec![q1, q0],
}],
}
}
}
pub(super) fn candidates(state: &DeviceGateState) -> SmallVec<[DirectionTemplate; 1]> {
if state.ordered_qargs.len() != 2 {
return SmallVec::new();
}
let template = match state.instruction {
crate::compile::knowledge::KnowledgeInstructionKey::Standard(StandardGate::CX) => {
DirectionTemplate::Cx
}
crate::compile::knowledge::KnowledgeInstructionKey::Standard(StandardGate::RZX) => {
DirectionTemplate::Rzx
}
crate::compile::knowledge::KnowledgeInstructionKey::Standard(gate)
if gate.is_invariant_under_operand_swap() =>
{
DirectionTemplate::Symmetric(gate)
}
_ => return SmallVec::new(),
};
smallvec![template]
}