-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Convert Sabre's lookahead
to layer-based tracking
#14911
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
Open
jakelishman
wants to merge
6
commits into
Qiskit:main
Choose a base branch
from
jakelishman:sabre/layers/3
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains hidden or 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 allows `NLayout` to be indexed by `VirtualQubit` and `PhysicalQubit`, which is a shorter way of writing `VirtualQubit::to_phys` and `PhysicalQubit::to_virt`.
This commit separates out the three logical components of the Sabre routing tracking into three separate structs, where each struct groups objects that have the same mutation tendency. The previous Sabre state stored its problem description, internal tracking, and output tracking altogether in the same flat structure. Those three components have different tendencies to mutate: the problem description never mutates, the internal tracking frequently does, and the output tracking only occasionally does and has a lifetime validity tied to that of the problem description. Putting them together made it impossible to call methods that mutated the state while passing an object that borrowed from the problem description, such as when recursing into control-flow operations, because the borrow checker could not validate it. This applied interface pressure to inline more into the same method, which made code-reuse of separate concerns harder.
Sabre uses several objects that are logically maps from an index-like newtype (like `NodeIndex` or `PhysicalQubit`) to some value, and are implemented as fixed-slice `Vec`s for lookup efficiency. The newtype provides type safety while it's in use, but we have to cast it away to index, which makes it easy to index slices with the wrong object. This introduces a `VecMap` object, which provides a (minimal) slice-like interface, but indexes using the relevant newtype. The current implementation of Sabre does not use this _too_ much, but a refactoring of the layer structures will have them store one slice indexed by `PhysicalQubit` and one by `VirtualQubit`, which are trivially easy to get switched (a frequent mistake that is the base reason those new types were introduced in the first place).
The previous Sabre extended set was just the "next N" 2q gates topologically on from the front layer, where Qiskit reliably used `N = 20` ever since its introduction. For small-width circuits (as were common when the original Sabre paper was written, and when it was first implemented in Qiskit), this could mean the extended set was reliably several layers deep. This could also be the case for star-like circuits. For the wider circuits in use now, at the 100q order of magnitude, the 20-gate limit reliably means that denser circuits cannot have their entire next layer considered by the lookahead set. This commit modifies the lookahead heuristic to be based specifically on layers. This regularises much of the structure of the heuristic with respect to circuit and target topology; we reliably "look ahead" by the same "distance" as far as routing is concerned. It comes with the additional benefits: - we can use the same `Layer` structure for both the front layer and the lookahead layers, which reduces the amount of scoring code - the lookahead score of a swap can now affect at most two gates per layer, just like the front-layer scoring, and we can do this statically without loops - we no longer risk "biasing" the lookahead heuristic in either case of long chains of dependent gates (e.g. a gate that has 10 predecessors weights the score the same as a gate with only 1) or wide circuits (some qubits have their next layer counted in the score, but others don't because the extended set reached capacity). - applying a swap to the lookahead now has a time complexity that is constant per layer, regardless of the number of gates stored in it, whereas previously it was proportional to the number of gates stored (and the implementation in the parent of this commit is proportional to the number of qubits in the circuit). This change alone is mostly a set up, which enables further computational complexity improvements by modifying the lookahead layers in place after a gate routes, rather than rebuilding them from scratch, and subsequently only updating _swap scores_ based on routing changes, rather than recalculating all from scratch.
One or more of the following people are relevant to this code:
|
This was referenced Aug 14, 2025
Pull Request Test Coverage Report for Build 16969144205Details
💛 - Coveralls |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The previous Sabre extended set was just the "next N" 2q gates topologically on from the front layer, where Qiskit reliably used
N = 20
ever since its introduction. For small-width circuits (as were common when the original Sabre paper was written, and when it was first implemented in Qiskit), this could mean the extended set was reliably several layers deep. This could also be the case for star-like circuits. For the wider circuits in use now, at the 100q order of magnitude, the 20-gate limit reliably means that denser circuits cannot have their entire next layer considered by the lookahead set.This commit modifies the lookahead heuristic to be based specifically on layers. This regularises much of the structure of the heuristic with respect to circuit and target topology; we reliably "look ahead" by the same "distance" as far as routing is concerned. It comes with the additional benefits:
we can use the same
Layer
structure for both the front layer and the lookahead layers, which reduces the amount of scoring codethe lookahead score of a swap can now affect at most two gates per layer, just like the front-layer scoring, and we can do this statically without loops
we no longer risk "biasing" the lookahead heuristic in either case of long chains of dependent gates (e.g. a gate that has 10 predecessors weights the score the same as a gate with only 1) or wide circuits (some qubits have their next layer counted in the score, but others don't because the extended set reached capacity).
applying a swap to the lookahead now has a time complexity that is constant per layer, regardless of the number of gates stored in it, whereas previously it was proportional to the number of gates stored (and the implementation in the parent of this commit is proportional to the number of qubits in the circuit).
This change alone is mostly a set up, which enables further computational complexity improvements by modifying the lookahead layers in place after a gate routes, rather than rebuilding them from scratch, and subsequently only updating swap scores based on routing changes, rather than recalculating all from scratch.