Skip to content

Commit

Permalink
fix: NonConvex error on SiblingSubgraph::from_nodes with multiports (#…
Browse files Browse the repository at this point in the history
…1295)

Fixes #1294
  • Loading branch information
aborgna-q authored Jul 11, 2024
1 parent a70ca87 commit 115a7d2
Showing 1 changed file with 40 additions and 7 deletions.
47 changes: 40 additions & 7 deletions hugr-core/src/hugr/views/sibling_subgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,8 @@ impl SiblingSubgraph {
.collect_vec();
let outputs = outgoing_edges
.filter(|&(n, p)| {
if !hugr.is_linked(n, p) {
return false;
}
// TODO: what if there are multiple outgoing edges?
// See https://github.com/CQCL/hugr/issues/518
let (in_n, _) = hugr.linked_ports(n, p).next().unwrap();
!nodes_set.contains(&in_n)
hugr.linked_ports(n, p)
.any(|(n1, _)| !nodes_set.contains(&n1))
})
.collect_vec();
Self::try_new_with_checker(inputs, outputs, hugr, checker)
Expand Down Expand Up @@ -792,6 +787,7 @@ mod tests {
Ok((hugr, func_id.node()))
}

/// A bool to bool hugr with three subsequent NOT gates.
fn build_3not_hugr() -> Result<(Hugr, Node), BuildError> {
let mut mod_builder = ModuleBuilder::new();
let func = mod_builder.declare("test", FunctionType::new_endo(type_row![BOOL_T]).into())?;
Expand All @@ -808,6 +804,26 @@ mod tests {
Ok((hugr, func_id.node()))
}

/// A bool to (bool, bool) with multiports.
fn build_multiport_hugr() -> Result<(Hugr, Node), BuildError> {
let mut mod_builder = ModuleBuilder::new();
let func = mod_builder.declare(
"test",
FunctionType::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]).into(),
)?;
let func_id = {
let mut dfg = mod_builder.define_declaration(&func)?;
let [b0] = dfg.input_wires_arr();
let [b1] = dfg.add_dataflow_op(NotOp, [b0])?.outputs_arr();
let [b2] = dfg.add_dataflow_op(NotOp, [b1])?.outputs_arr();
dfg.finish_with_outputs([b1, b2])?
};
let hugr = mod_builder
.finish_prelude_hugr()
.map_err(|e| -> BuildError { e.into() })?;
Ok((hugr, func_id.node()))
}

/// A HUGR with a copy
fn build_hugr_classical() -> Result<(Hugr, Node), BuildError> {
let mut mod_builder = ModuleBuilder::new();
Expand Down Expand Up @@ -979,6 +995,23 @@ mod tests {
);
}

/// A subgraphs mixed with multiports caused a NonConvex error.
/// https://github.com/CQCL/hugr/issues/1294
#[test]
fn convex_multiports() {
let (hugr, func_root) = build_multiport_hugr().unwrap();
let [inp, out] = hugr.get_io(func_root).unwrap();
let not1 = hugr.output_neighbours(inp).exactly_one().unwrap();
let not2 = hugr
.output_neighbours(not1)
.filter(|&n| n != out)
.exactly_one()
.unwrap();

let subgraph = SiblingSubgraph::try_from_nodes([not1, not2], &hugr).unwrap();
assert_eq!(subgraph.nodes(), [not1, not2]);
}

#[test]
fn invalid_boundary() {
let (hugr, func_root) = build_hugr().unwrap();
Expand Down

0 comments on commit 115a7d2

Please sign in to comment.