-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Fix an edge case in Sabre's release valve #13114
Conversation
If a Sabre trial does not find a set of Swaps to route nodes, the "release valve" adds Swaps to route the two-qubit gate in between the the closest two qubits. In rare cases, this leads to _more_ than one gate being routable, which was not handled correctly previously. Co-authored-by: Jake Lishman <[email protected]>
One or more of the following people are relevant to this code:
|
@@ -573,14 +600,16 @@ pub fn swap_map_trial( | |||
} | |||
if routable_nodes.is_empty() { |
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.
I can't comment above this line, but is there any reason we shouldn't use a SmallVec
for routable_nodes
itself?
And, should we increase the capacity of the pre-allocation to 3
now on line 573?
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 shouldn't necessarily, because the release valve should only be taken rarely, and we don't want to overallocate the happy path, and we should still only be routing two nodes in the new case.
Co-authored-by: Kevin Hartman <[email protected]>
Co-authored-by: Kevin Hartman <[email protected]>
…rra into fix-sabre-releasevalve
Pull Request Test Coverage Report for Build 10795320615Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
With #13119 merged, CI should pass now I think 🙂 |
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.
This LGTM, I have a small inline nit comment on code style but it's not significant or a blocker. I'm running the 1000q QV reproducer I put in the original issue to confirm it's fixed once I confirm it's fixed I'll add this to the merge queue.
.filter_map(|&swap_qubit| self.front_layer.qubits()[swap_qubit.index()]) | ||
// remove the closest_node, which we know we already routed | ||
.filter(|(node_index, _other_qubit)| *node_index != closest_node) | ||
.map(|(_node_index, other_qubit)| other_qubit); |
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.
Couldn't this just be a single filter map. Something like:
.filter_map(|&swap_qubit| self.front_layer.qubits()[swap_qubit.index()]) | |
// remove the closest_node, which we know we already routed | |
.filter(|(node_index, _other_qubit)| *node_index != closest_node) | |
.map(|(_node_index, other_qubit)| other_qubit); | |
.filter_map(|&swap_qubit| { | |
self.front_layer.qubits()[swap_qubit.index()]).map(|(node_index, other_qubit)| { | |
// remove the closest_node, which we know we already routed | |
if node_index != closest_node { | |
Some(other_qubit) | |
} else { | |
None | |
} | |
}) | |
}); |
Or even:
.filter_map(|&swap_qubit| self.front_layer.qubits()[swap_qubit.index()]) | |
// remove the closest_node, which we know we already routed | |
.filter(|(node_index, _other_qubit)| *node_index != closest_node) | |
.map(|(_node_index, other_qubit)| other_qubit); | |
.filter_map(|&swap_qubit| self.front_layer.qubits()[swap_qubit.index()]) | |
// remove the closest_node, which we know we already routed | |
.filter_map(|(node_index, other_qubit)| if *node_index != closest_node { | |
Some(other_qubit) | |
} else { | |
None | |
}) |
Not that this makes a big difference. I'm surprised clippy isn't complaining about the filter followed by a map though.
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.
if you're really going hard on fancy methods, you can even do (*node_index != closest_node).then_some(other_qubit)
haha.
The 1000 qubit QV circuit reproducer from #13081 works with this applied so I'm good to merge this. |
* Fix edge case in Sabre release valve If a Sabre trial does not find a set of Swaps to route nodes, the "release valve" adds Swaps to route the two-qubit gate in between the the closest two qubits. In rare cases, this leads to _more_ than one gate being routable, which was not handled correctly previously. Co-authored-by: Jake Lishman <[email protected]> * add reno and test * Use sensible syntax Co-authored-by: Kevin Hartman <[email protected]> * Use sensible grammar Co-authored-by: Kevin Hartman <[email protected]> * clippy * Check if the new test breaks CI * Revert "Check if the new test breaks CI" This reverts commit 01bcdc7. --------- Co-authored-by: Jake Lishman <[email protected]> Co-authored-by: Kevin Hartman <[email protected]> (cherry picked from commit f2ca920)
* Fix edge case in Sabre release valve If a Sabre trial does not find a set of Swaps to route nodes, the "release valve" adds Swaps to route the two-qubit gate in between the the closest two qubits. In rare cases, this leads to _more_ than one gate being routable, which was not handled correctly previously. Co-authored-by: Jake Lishman <[email protected]> * add reno and test * Use sensible syntax Co-authored-by: Kevin Hartman <[email protected]> * Use sensible grammar Co-authored-by: Kevin Hartman <[email protected]> * clippy * Check if the new test breaks CI * Revert "Check if the new test breaks CI" This reverts commit 01bcdc7. --------- Co-authored-by: Jake Lishman <[email protected]> Co-authored-by: Kevin Hartman <[email protected]> (cherry picked from commit f2ca920) Co-authored-by: Julien Gacon <[email protected]>
Summary
Fixes #13081.
Details and comments
If a Sabre trial does not find a set of Swaps to route nodes, the "release valve" adds Swaps to route the two-qubit gate in between the the closest two qubits. In rare cases, this leads to more than one gate being routable, which was not handled correctly previously.
As I understand it this should only ever occur if the release-valve adds a single swap and we have a scenario like
If more than one swap gate is applied it should not be possible that two gates are routable, so the code now only checks for a second routable gate if we insert a single swap. If someone can find a counterexample we can change the code to check for any routable gate after the release valve 🙂