-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix potential infinite loop in SabreSwap (#7970)
* Fix potential infinite loop in SabreSwap This adds a "release valve" mechanism to `SabreSwap`, so that it will always eventually make forwards progress and terminate the run. Before this commit, it was possible for certain pathological circuits (see `looping_circuit` in `test/python/transpiler/test_sabre_swap.py` for an example) to get stuck in a stable local minimum of the 'lookahead' or 'decay' heuristics (no matter the weightings). The release mechanism is done with very small per-loop overhead for the vastly more common good paths; we simply count how many iterations we have been through since we made progress, and the minimum weight in the coupling map to be overcome to make progress again. Once the number of iterations without progress exceeds some value, we backtrack (inefficiently, because this is the bad path) to the last time we made progress, and forcibly insert swaps to bring the nearest gate together. We then continue like normal. There are also a few minor optimisations in this commit that prevent recalculating sets that we already know; `extended_set` is fixed by knowledge of the `front_layer` if the DAG isn't (meaningfully) changed, so there's no need to recalculate it on each loop. * Reduce depth of greedy swap insertion * Add link in release note Co-authored-by: Matthew Treinish <mtreinish@kortar.org> * Remove extra keyword argument in SabreSwap constructor The `max_iterations_without_progress` value was originally exposed to users via the constructor. It was added because I thought I'd need a way to force the backtracking algorithm to occur to test the behaviour. When I wrote the tests, I ended up using Aer to find the keys, which is sufficiently fast that we can verify validity using the regular infinite loop circuit, and the argument is unnecessary. It was highly unlikely to actually be useful in real applications, so it does not need to be added. * Remove useless return from _add_greedy_swaps Co-authored-by: Matthew Treinish <mtreinish@kortar.org> (cherry picked from commit f414273)
- Loading branch information
1 parent
a93b089
commit 70c826c
Showing
3 changed files
with
238 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
fixes: | ||
- | | ||
The :class:`.SabreSwap` transpiler pass, and by extension | ||
:class:`.SabreLayout` and :func:`.transpile` at ``optimization_level=3``, | ||
now has an escape mechanism to guarantee that it can never get stuck in an | ||
infinite loop. Certain inputs previously could, with a great amount of bad | ||
luck, get stuck in a stable local minimum of the search space and the pass | ||
would never make further progress. It will now force a series of swaps that | ||
allow the routing to continue if it detects it has not made progress | ||
recently. Fixed `#7707 <https://github.com/Qiskit/qiskit-terra/issues/7707>`__. |
Oops, something went wrong.