Skip to content

Commit c2c5752

Browse files
aborgna-qdoug-q
andauthored
feat: Add SiblingSubgraph::from_node (#1655)
Complementary improvement to #1654. Creating a k-node subgraph in an n-node graph should ideally be `O(k)`. However, due to CQCL/portgraph#155 this ends up being `O(n)`. For `k=1`, this results in a linear cost overhead. This PR adds a special case (written by @doug-q) that completely skips the unnecessary checks. ``` group before from_node ----- ------ --------- multinode_subgraph/10 1.01 17.7±0.26µs ? ?/sec 1.00 17.5±0.23µs ? ?/sec multinode_subgraph/100 1.00 169.1±11.34µs ? ?/sec 1.00 168.8±4.37µs ? ?/sec multinode_subgraph/1000 1.01 2.3±0.46ms ? ?/sec 1.00 2.3±0.34ms ? ?/sec singleton_subgraph/10 12.26 3.0±0.06µs ? ?/sec 1.00 245.6±21.24ns ? ?/sec singleton_subgraph/100 20.01 4.7±0.06µs ? ?/sec 1.00 234.4±6.50ns ? ?/sec singleton_subgraph/1000 93.34 22.0±0.25µs ? ?/sec 1.00 235.6±4.93ns ? ?/sec ``` --------- Co-authored-by: Douglas Wilson <[email protected]>
1 parent e63878f commit c2c5752

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

hugr-core/src/hugr/views/sibling_subgraph.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ impl SiblingSubgraph {
211211
/// The subgraph signature will be given by the types of the incoming and
212212
/// outgoing edges ordered by the node order in `nodes` and within each node
213213
/// by the port order.
214-
214+
///
215215
/// The in- and out-arity of the signature will match the
216216
/// number of incoming and outgoing edges respectively. In particular, the
217217
/// assumption is made that no two incoming edges have the same source
@@ -238,6 +238,14 @@ impl SiblingSubgraph {
238238
checker: &impl ConvexChecker,
239239
) -> Result<Self, InvalidSubgraph> {
240240
let nodes = nodes.into();
241+
242+
// If there's one or less nodes, we don't need to check convexity.
243+
match nodes.as_slice() {
244+
[] => return Err(InvalidSubgraph::EmptySubgraph),
245+
[node] => return Ok(Self::from_node(*node, hugr)),
246+
_ => {}
247+
};
248+
241249
let nodes_set = nodes.iter().copied().collect::<HashSet<_>>();
242250
let incoming_edges = nodes
243251
.iter()
@@ -265,6 +273,31 @@ impl SiblingSubgraph {
265273
Self::try_new_with_checker(inputs, outputs, hugr, checker)
266274
}
267275

276+
/// Create a subgraph containing a single node.
277+
///
278+
/// The subgraph signature will be given by signature of the node.
279+
pub fn from_node(node: Node, hugr: &impl HugrView) -> Self {
280+
// TODO once https://github.com/CQCL/portgraph/issues/155
281+
// is fixed we can just call try_from_nodes here.
282+
// Until then, doing this saves a lot of work.
283+
let nodes = vec![node];
284+
let inputs = hugr
285+
.node_inputs(node)
286+
.filter(|&p| hugr.is_linked(node, p))
287+
.map(|p| vec![(node, p)])
288+
.collect_vec();
289+
let outputs = hugr
290+
.node_outputs(node)
291+
.filter_map(|p| hugr.is_linked(node, p).then_some((node, p)))
292+
.collect_vec();
293+
294+
Self {
295+
nodes,
296+
inputs,
297+
outputs,
298+
}
299+
}
300+
268301
/// An iterator over the nodes in the subgraph.
269302
pub fn nodes(&self) -> &[Node] {
270303
&self.nodes

0 commit comments

Comments
 (0)