-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(hugr-passes): Add force_order
pass.
#1285
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1285 +/- ##
==========================================
+ Coverage 87.04% 87.17% +0.12%
==========================================
Files 103 104 +1
Lines 19243 19421 +178
Branches 17073 17251 +178
==========================================
+ Hits 16750 16930 +180
+ Misses 1716 1712 -4
- Partials 777 779 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💥 Nice.
There may just be some problem with newly discovered nodes having higher rank than existing ones.
There's also a solution that doesn't require computing dominators.
After popping from tovisit
, if there's other nodes left in in tovisit
keep the popped node around and add an order edge from it to the next visited node.
That would ensure that there's a unique topological order.
hugr-passes/src/force_order.rs
Outdated
/// All dataflow parents which are transitive children of `root`, including | ||
/// `root` itself, will be ordered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be better to talk about the dataflow regions being ordered, rather than parent nodes.
hugr-passes/src/force_order.rs
Outdated
// we can only add an order edge if the two ops support it | ||
let (n1_ot, n2_ot) = (hugr.get_optype(n1), hugr.get_optype(n2)); | ||
let expected_edge_kind = Some(hugr_core::types::EdgeKind::StateOrder); | ||
if n1_ot.other_port_kind(Direction::Outgoing) != expected_edge_kind | ||
|| n2_ot.other_port_kind(Direction::Incoming) != expected_edge_kind | ||
{ | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to delay the edge then.
If n1_ot
supports state order edges, keep it around until we find a target node which also supports them and add the edge.
I think there are no node types that support state order edges in only one direction? Though it may be incorrect to assume that...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I can assert for the weird case you describe.
}) | ||
.collect_vec(); | ||
|
||
self.extend(new_nodes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no guarantee that the new nodes have a lower rank than the existing ones in self.tovisit
.
We should use an ordered BTreeSet
instead, so they can be added to the right position.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right this is much better. I think I prefer BinaryHeap
here, since we don't need lookup. Do you have a test case in mind that would tickle this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just [0, 1, 2, 3]
in your example :)
#[test]
fn test_force_order_3() {
let (mut hugr, [v0, v1, v2, v3]) = test_hugr();
let rank_map = [(v0, 0), (v1, 1), (v2, 2), (v3, 3)].into_iter().collect();
let topo_sort = force_order_test_impl(&mut hugr, rank_map);
assert_eq!(vec![v0, v1, v2, v3], topo_sort);
}
It'd be nice to do some benchmarks at some point, but we're lacking test hugrs to benchmark on :/ |
Co-authored-by: Agustín Borgna <[email protected]>
Btw, a more flexible API could be to offer a key: impl Fn(Node) -> (impl Ord) which is just a generalization of |
@aborgna-q I've made most of the algorithmic changes you suggested. I do not like the idea of mutating the hugr from within Instead, I have observed that all DataflowChild ops have state order edges. See what you think. I've not edited docs yet, will ask for re-review when I'm done. |
Note I've added the passes to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Just some minor code suggestions
Co-authored-by: Agustín Borgna <[email protected]>
Co-authored-by: Agustín Borgna <[email protected]>
## 🤖 New release * `hugr`: 0.6.1 -> 0.7.0 * `hugr-core`: 0.3.1 -> 0.4.0 * `hugr-passes`: 0.3.0 -> 0.4.0 * `hugr-cli`: 0.1.2 -> 0.1.3 <details><summary><i><b>Changelog</b></i></summary><p> ## `hugr` <blockquote> ## 0.7.0 (2024-07-10) ### Bug Fixes - Bring back input_extensions serialized field in rust NodeSer ([#1275](#1275)) - [**breaking**] `ops::Module` now empty struct rather than unit struct ([#1271](#1271)) ### Features - Add `force_order` pass. ([#1285](#1285)) - [**breaking**] `MakeOpDef` has new `extension` method. ([#1266](#1266)) ### Refactor - [**breaking**] Remove `Value::Tuple` ([#1255](#1255)) - [**breaking**] Rename `HugrView` function type methods + simplify behaviour ([#1265](#1265)) ### Styling - Change "serialise" etc to "serialize" etc. ([#1251](#1251)) ### Testing - Add a test for [#1257](#1257) ([#1260](#1260)) </blockquote> ## `hugr-core` <blockquote> ## 0.4.0 (2024-07-10) ### Bug Fixes - Bring back input_extensions serialized field in rust NodeSer ([#1275](#1275)) - [**breaking**] `ops::Module` now empty struct rather than unit struct ([#1271](#1271)) ### Features - [**breaking**] `MakeOpDef` has new `extension` method. ([#1266](#1266)) ### Refactor - [**breaking**] Remove `Value::Tuple` ([#1255](#1255)) - [**breaking**] Rename `HugrView` function type methods + simplify behaviour ([#1265](#1265)) ### Styling - Change "serialise" etc to "serialize" etc. ([#1251](#1251)) ### Testing - Add a test for [#1257](#1257) ([#1260](#1260)) </blockquote> ## `hugr-passes` <blockquote> ## 0.4.0 (2024-07-10) ### Features - Add `force_order` pass. ([#1285](#1285)) ### Refactor - [**breaking**] Remove `Value::Tuple` ([#1255](#1255)) </blockquote> ## `hugr-cli` <blockquote> ## 0.1.3 (2024-07-10) ### Styling - Change "serialise" etc to "serialize" etc. ([#1251](#1251)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/MarcoIeni/release-plz/).
closes #1282