#[cfg(feature = "portmatching")]
pub mod ecc_rewriter;
pub mod strategy;
pub mod trace;
use bytemuck::TransparentWrapper;
#[cfg(feature = "portmatching")]
pub use ecc_rewriter::ECCRewriter;
use derive_more::{From, Into};
use hugr::core::HugrNode;
use hugr::hugr::hugrmut::HugrMut;
use hugr::hugr::patch::simple_replace;
use hugr::hugr::views::sibling_subgraph::{InvalidReplacement, InvalidSubgraph};
use hugr::hugr::Patch;
use hugr::types::Signature;
use hugr::{
hugr::{views::SiblingSubgraph, SimpleReplacementError},
SimpleReplacement,
};
use hugr::{Hugr, HugrView, Node};
use crate::circuit::Circuit;
#[derive(Debug, Clone, From, Into)]
#[repr(transparent)]
pub struct Subcircuit<N = Node> {
pub(crate) subgraph: SiblingSubgraph<N>,
}
unsafe impl<N> TransparentWrapper<SiblingSubgraph<N>> for Subcircuit<N> {}
impl<N: HugrNode> Subcircuit<N> {
pub fn try_from_nodes(
nodes: impl Into<Vec<N>>,
circ: &Circuit<impl HugrView<Node = N>>,
) -> Result<Self, InvalidSubgraph<N>> {
let subgraph = SiblingSubgraph::try_from_nodes(nodes, circ.hugr())?;
Ok(Self { subgraph })
}
pub fn nodes(&self) -> &[N] {
self.subgraph.nodes()
}
pub fn node_count(&self) -> usize {
self.subgraph.node_count()
}
pub fn signature(&self, circ: &Circuit<impl HugrView<Node = N>>) -> Signature {
self.subgraph.signature(circ.hugr())
}
}
impl Subcircuit<Node> {
pub fn create_rewrite(
&self,
circuit: &Circuit<impl HugrView<Node = Node>>,
replacement: Circuit<impl HugrView<Node = Node>>,
) -> Result<CircuitRewrite, InvalidReplacement> {
let replacement = replacement
.extract_dfg()
.unwrap_or_else(|e| panic!("{}", e))
.into_hugr();
Ok(CircuitRewrite(
self.subgraph
.create_simple_replacement(circuit.hugr(), replacement)?,
))
}
}
#[derive(Debug, Clone, From, Into)]
pub struct CircuitRewrite<N = Node>(SimpleReplacement<N>);
impl CircuitRewrite {
pub fn try_new(
circuit_position: &Subcircuit,
circuit: &Circuit<impl HugrView<Node = Node>>,
replacement: Circuit<impl HugrView<Node = Node>>,
) -> Result<Self, InvalidReplacement> {
let replacement = replacement
.extract_dfg()
.unwrap_or_else(|e| panic!("{}", e))
.into_hugr();
circuit_position
.subgraph
.create_simple_replacement(circuit.hugr(), replacement)
.map(Self)
}
pub fn node_count_delta(&self) -> isize {
let new_count = self.replacement().num_operations() as isize;
let old_count = self.subcircuit().node_count() as isize;
new_count - old_count
}
pub fn subcircuit(&self) -> &Subcircuit {
Subcircuit::wrap_ref(self.0.subgraph())
}
pub fn replacement(&self) -> Circuit<&Hugr> {
self.0.replacement().into()
}
#[inline]
pub fn invalidation_set(&self) -> impl Iterator<Item = Node> + '_ {
self.0.invalidation_set()
}
#[inline]
pub fn apply(
self,
circ: &mut Circuit<impl HugrMut<Node = Node>>,
) -> Result<simple_replace::Outcome<Node>, SimpleReplacementError> {
circ.add_rewrite_trace(&self);
self.0.apply(circ.hugr_mut())
}
#[inline]
pub fn apply_notrace(
self,
circ: &mut Circuit<impl HugrMut<Node = Node>>,
) -> Result<simple_replace::Outcome<Node>, SimpleReplacementError> {
self.0.apply(circ.hugr_mut())
}
}
pub trait Rewriter {
fn get_rewrites(&self, circ: &Circuit<impl HugrView<Node = Node>>) -> Vec<CircuitRewrite>;
}