Skip to content

Commit b81ed94

Browse files
committed
feat: PersistentHugr Walker API
1 parent 1ab5ea7 commit b81ed94

File tree

7 files changed

+1492
-51
lines changed

7 files changed

+1492
-51
lines changed

hugr-core/src/hugr/patch/port_types.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use derive_more::From;
88

99
/// A port in either the host or replacement graph.
1010
///
11-
/// This is used to represent boundary edges that will be added between the host and
12-
/// replacement graphs when applying a rewrite.
11+
/// This is used to represent boundary edges that will be added between the host
12+
/// and replacement graphs when applying a rewrite.
1313
#[derive(Debug, Clone, Copy)]
1414
pub enum BoundaryPort<HostNode, P> {
1515
/// A port in the host graph.
@@ -19,7 +19,7 @@ pub enum BoundaryPort<HostNode, P> {
1919
}
2020

2121
/// A port in the host graph.
22-
#[derive(Debug, Clone, Copy, From)]
22+
#[derive(Debug, Clone, Copy, PartialEq, Eq, From)]
2323
pub struct HostPort<N, P>(pub N, pub P);
2424

2525
/// A port in the replacement graph.
@@ -28,7 +28,8 @@ pub struct ReplacementPort<P>(pub Node, pub P);
2828

2929
impl<HostNode: Copy, P> BoundaryPort<HostNode, P> {
3030
/// Maps a boundary port according to the insertion mapping.
31-
/// Host ports are unchanged, while Replacement ports are mapped according to the index_map.
31+
/// Host ports are unchanged, while Replacement ports are mapped according
32+
/// to the index_map.
3233
pub fn map_replacement(self, index_map: &HashMap<Node, HostNode>) -> (HostNode, P) {
3334
match self {
3435
BoundaryPort::Host(node, port) => (node, port),

hugr-core/src/hugr/patch/simple_replace.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::hugr::hugrmut::InsertionResult;
77
use crate::hugr::views::SiblingSubgraph;
88
use crate::hugr::{HugrMut, HugrView};
99
use crate::ops::{OpTag, OpTrait, OpType};
10-
use crate::{Hugr, IncomingPort, Node, OutgoingPort, Port};
10+
use crate::{Direction, Hugr, IncomingPort, Node, OutgoingPort, Port};
1111

1212
use derive_more::derive::From;
1313
use itertools::{Either, Itertools};
@@ -93,6 +93,22 @@ impl<N: HugrNode> OutputBoundaryMap<N> {
9393
.into_iter()
9494
}
9595

96+
/// The keys of the map.
97+
///
98+
/// These will be either outgoing or incoming ports, depending on the
99+
/// variant of `self`.
100+
pub fn keys(&self) -> impl Iterator<Item = (N, Port)> + '_ {
101+
match self {
102+
OutputBoundaryMap::ByIncoming(map) => {
103+
Either::Left(map.keys().map(|&(node, port)| (node, port.into())))
104+
}
105+
OutputBoundaryMap::ByOutgoing(map) => {
106+
Either::Right(map.keys().map(|&(node, port)| (node, port.into())))
107+
}
108+
}
109+
.into_iter()
110+
}
111+
96112
/// Iterate over the boundary map with keys resolved as incoming ports.
97113
///
98114
/// By providing the host HUGR `host`, all ports in the keys are resolved
@@ -308,6 +324,14 @@ impl<HostNode: HugrNode> SimpleReplacement<HostNode> {
308324
)
309325
}
310326

327+
/// Get the direction of the ports in the outgoing boundary.
328+
pub fn outgoing_boundary_type(&self) -> Direction {
329+
match &self.nu_out {
330+
OutputBoundaryMap::ByIncoming(_) => Direction::Incoming,
331+
OutputBoundaryMap::ByOutgoing(_) => Direction::Outgoing,
332+
}
333+
}
334+
311335
/// Get all edges that the replacement would add between ports in `host`.
312336
///
313337
/// These correspond to direct edges between the input and output nodes
@@ -364,6 +388,44 @@ impl<HostNode: HugrNode> SimpleReplacement<HostNode> {
364388
.map(|rep_out_port| ReplacementPort(rep_output, rep_out_port))
365389
}
366390

391+
/// Get the incoming ports connected to the input node of `self.replacement`
392+
/// that corresponds to the given host input port.
393+
///
394+
/// This is the inverse of [`Self::map_replacement_input`]. Beware that it
395+
/// is slightly inefficient as it iterates over all host input ports to find
396+
/// matching `replacement` ports.
397+
///
398+
/// This panics if self.replacement is not a DFG.
399+
pub fn map_host_input(
400+
&self,
401+
port: impl Into<HostPort<HostNode, IncomingPort>>,
402+
) -> impl Iterator<Item = ReplacementPort<IncomingPort>> + '_ {
403+
let host_port = port.into();
404+
let all_repl_node_port = self.nu_inp.keys().copied();
405+
all_repl_node_port
406+
.map_into()
407+
.filter(move |&repl_port| self.map_replacement_input(repl_port) == Some(host_port))
408+
}
409+
410+
/// Get the incoming ports in `subgraph` that corresponds to the given
411+
/// replacement output port.
412+
///
413+
/// This is the inverse of [`Self::map_host_output`]. Beware that it is
414+
/// slightly inefficient as it iterates over all replacement output ports
415+
/// to find matching `subgraph` ports.
416+
///
417+
/// This panics if self.replacement is not a DFG.
418+
pub fn map_replacement_output(
419+
&self,
420+
port: impl Into<ReplacementPort<IncomingPort>>,
421+
) -> impl Iterator<Item = HostPort<HostNode, Port>> + '_ {
422+
let repl_port = port.into();
423+
let all_host_node_port = self.nu_out.keys();
424+
all_host_node_port
425+
.map_into()
426+
.filter(move |&host_port| self.map_host_output(host_port) == Some(repl_port))
427+
}
428+
367429
/// Get the incoming port in `subgraph` that corresponds to the given
368430
/// replacement input port.
369431
///

0 commit comments

Comments
 (0)