Skip to content
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

Merged
merged 8 commits into from
Jul 10, 2024
Merged

feat(hugr-passes): Add force_order pass. #1285

merged 8 commits into from
Jul 10, 2024

Conversation

doug-q
Copy link
Collaborator

@doug-q doug-q commented Jul 9, 2024

closes #1282

@doug-q doug-q requested a review from a team as a code owner July 9, 2024 13:28
@doug-q doug-q requested a review from aborgna-q July 9, 2024 13:28
Copy link

codecov bot commented Jul 9, 2024

Codecov Report

Attention: Patch coverage is 97.19101% with 5 lines in your changes missing coverage. Please review.

Project coverage is 87.17%. Comparing base (9b04097) to head (41296c0).
Report is 3 commits behind head on main.

Files Patch % Lines
hugr-passes/src/force_order.rs 97.19% 3 Missing and 2 partials ⚠️
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     
Flag Coverage Δ
rust 86.64% <97.19%> (+0.15%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@aborgna-q aborgna-q left a 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.

Comment on lines 25 to 26
/// All dataflow parents which are transitive children of `root`, including
/// `root` itself, will be ordered.
Copy link
Collaborator

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.

Comment on lines 61 to 68
// 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;
}
Copy link
Collaborator

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...

Copy link
Collaborator Author

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.

hugr-passes/src/force_order.rs Outdated Show resolved Hide resolved
})
.collect_vec();

self.extend(new_nodes);
Copy link
Collaborator

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.

Copy link
Collaborator Author

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?

Copy link
Collaborator

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);
}

@aborgna-q
Copy link
Collaborator

aborgna-q commented Jul 9, 2024

It'd be nice to do some benchmarks at some point, but we're lacking test hugrs to benchmark on :/

@aborgna-q
Copy link
Collaborator

Btw, a more flexible API could be to offer a force_order_by_key where instead of a rank you take a

key: impl Fn(Node) -> (impl Ord)

which is just a generalization of rank.

@doug-q
Copy link
Collaborator Author

doug-q commented Jul 10, 2024

@aborgna-q I've made most of the algorithmic changes you suggested. I do not like the idea of mutating the hugr from within visit, this seems dangerous and unnecessary. Note that the iteration order is deterministic because each node has a unique sort position to_visit.

Instead, I have observed that all DataflowChild ops have state order edges. See what you think.
EDIT: note that ScopedDefns are DataflowChild. Somewhat surprisingly, they also allow order edges.

I've not edited docs yet, will ask for re-review when I'm done.

@doug-q
Copy link
Collaborator Author

doug-q commented Jul 10, 2024

Note I've added the passes to lib.rs, lmk if you don't like it.

@doug-q doug-q requested a review from aborgna-q July 10, 2024 06:43
Copy link
Collaborator

@aborgna-q aborgna-q left a 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

hugr-passes/src/force_order.rs Outdated Show resolved Hide resolved
hugr-passes/src/force_order.rs Outdated Show resolved Hide resolved
hugr-passes/src/force_order.rs Outdated Show resolved Hide resolved
@doug-q doug-q added this pull request to the merge queue Jul 10, 2024
Merged via the queue into main with commit 9fe73ed Jul 10, 2024
20 checks passed
@doug-q doug-q deleted the doug/force-order branch July 10, 2024 12:10
@hugrbot hugrbot mentioned this pull request Jul 10, 2024
github-merge-queue bot pushed a commit that referenced this pull request Jul 10, 2024
## 🤖 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/).
@hugrbot hugrbot mentioned this pull request Jul 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a "sink" pass
2 participants