169 lines
9.1 KiB
Plaintext
169 lines
9.1 KiB
Plaintext
---
|
||
title: SabreSwap (v1.2)
|
||
description: API reference for qiskit.transpiler.passes.SabreSwap in qiskit v1.2
|
||
in_page_toc_min_heading_level: 1
|
||
python_api_type: class
|
||
python_api_name: qiskit.transpiler.passes.SabreSwap
|
||
---
|
||
|
||
# SabreSwap
|
||
|
||
<Class id="qiskit.transpiler.passes.SabreSwap" isDedicatedPage={true} github="https://github.com/Qiskit/qiskit/tree/stable/1.2/qiskit/transpiler/passes/routing/sabre_swap.py#L40-L277" signature="qiskit.transpiler.passes.SabreSwap(*args, **kwargs)" modifiers="class">
|
||
Bases: [`TransformationPass`](qiskit.transpiler.TransformationPass "qiskit.transpiler.basepasses.TransformationPass")
|
||
|
||
Map input circuit onto a backend topology via insertion of SWAPs.
|
||
|
||
Implementation of the SWAP-based heuristic search from the SABRE qubit mapping paper \[1] (Algorithm 1). The heuristic aims to minimize the number of lossy SWAPs inserted and the depth of the circuit.
|
||
|
||
This algorithm starts from an initial layout of virtual qubits onto physical qubits, and iterates over the circuit DAG until all gates are exhausted, inserting SWAPs along the way. It only considers 2-qubit gates as only those are germane for the mapping problem (it is assumed that 3+ qubit gates are already decomposed).
|
||
|
||
In each iteration, it will first check if there are any gates in the `front_layer` that can be directly applied. If so, it will apply them and remove them from `front_layer`, and replenish that layer with new gates if possible. Otherwise, it will try to search for SWAPs, insert the SWAPs, and update the mapping.
|
||
|
||
The search for SWAPs is restricted, in the sense that we only consider physical qubits in the neighborhood of those qubits involved in `front_layer`. These give rise to a `swap_candidate_list` which is scored according to some heuristic cost function. The best SWAP is implemented and `current_layout` updated.
|
||
|
||
This transpiler pass adds onto the SABRE algorithm in that it will run multiple trials of the algorithm with different seeds. The best output, determined by the trial with the least amount of SWAPed inserted, will be selected from the random trials.
|
||
|
||
**References:**
|
||
|
||
\[1] Li, Gushu, Yufei Ding, and Yuan Xie. “Tackling the qubit mapping problem for NISQ-era quantum devices.” ASPLOS 2019. [arXiv:1809.02573](https://arxiv.org/pdf/1809.02573.pdf)
|
||
|
||
SabreSwap initializer.
|
||
|
||
**Parameters**
|
||
|
||
* **coupling\_map** (*Union\[*[*CouplingMap*](qiskit.transpiler.CouplingMap "qiskit.transpiler.CouplingMap")*,* [*Target*](qiskit.transpiler.Target "qiskit.transpiler.Target")*]*) – CouplingMap of the target backend.
|
||
* **heuristic** ([*str*](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.13)")) – The type of heuristic to use when deciding best swap strategy (‘basic’ or ‘lookahead’ or ‘decay’).
|
||
* **seed** ([*int*](https://docs.python.org/3/library/functions.html#int "(in Python v3.13)")) – random seed used to tie-break among candidate swaps.
|
||
* **fake\_run** ([*bool*](https://docs.python.org/3/library/functions.html#bool "(in Python v3.13)")) – if true, it only pretend to do routing, i.e., no swap is effectively added.
|
||
* **trials** ([*int*](https://docs.python.org/3/library/functions.html#int "(in Python v3.13)")) – The number of seed trials to run sabre with. These will be run in parallel (unless the PassManager is already running in parallel). If not specified this defaults to the number of physical CPUs on the local system. For reproducible results it is recommended that you set this explicitly, as the output will be deterministic for a fixed number of trials.
|
||
|
||
**Raises**
|
||
|
||
[**TranspilerError**](transpiler#qiskit.transpiler.TranspilerError "qiskit.transpiler.TranspilerError") – If the specified heuristic is not valid.
|
||
|
||
Additional Information:
|
||
|
||
> The search space of possible SWAPs on physical qubits is explored by assigning a score to the layout that would result from each SWAP. The goodness of a layout is evaluated based on how viable it makes the remaining virtual gates that must be applied. A few heuristic cost functions are supported
|
||
>
|
||
> * ‘basic’:
|
||
>
|
||
> The sum of distances for corresponding physical qubits of interacting virtual qubits in the front\_layer.
|
||
>
|
||
> $$
|
||
> H_{basic} = \sum_{gate \in F} D[\pi(gate.q_1)][\pi(gate.q2)]
|
||
> $$
|
||
>
|
||
> * ‘lookahead’:
|
||
>
|
||
> This is the sum of two costs: first is the same as the basic cost. Second is the basic cost but now evaluated for the extended set as well (i.e. $|E|$ number of upcoming successors to gates in front\_layer F). This is weighted by some amount EXTENDED\_SET\_WEIGHT (W) to signify that upcoming gates are less important that the front\_layer.
|
||
>
|
||
> $$
|
||
> H_{decay}=\frac{1}{\left|{F}\right|}\sum_{gate \in F} D[\pi(gate.q_1)][\pi(gate.q2)]
|
||
> + W*\frac{1}{\left|{E}\right|} \sum_{gate \in E} D[\pi(gate.q_1)][\pi(gate.q2)]
|
||
> $$
|
||
>
|
||
> * ‘decay’:
|
||
>
|
||
> This is the same as ‘lookahead’, but the whole cost is multiplied by a decay factor. This increases the cost if the SWAP that generated the trial layout was recently used (i.e. it penalizes increase in depth).
|
||
>
|
||
> $$
|
||
> H_{decay} = max(decay(SWAP.q_1), decay(SWAP.q_2)) {
|
||
> \frac{1}{\left|{F}\right|} \sum_{gate \in F} D[\pi(gate.q_1)][\pi(gate.q2)]\\
|
||
> + W *\frac{1}{\left|{E}\right|} \sum_{gate \in E} D[\pi(gate.q_1)][\pi(gate.q2)]
|
||
> }
|
||
> $$
|
||
|
||
## Attributes
|
||
|
||
### is\_analysis\_pass
|
||
|
||
<Attribute id="qiskit.transpiler.passes.SabreSwap.is_analysis_pass">
|
||
Check if the pass is an analysis pass.
|
||
|
||
If the pass is an AnalysisPass, that means that the pass can analyze the DAG and write the results of that analysis in the property set. Modifications on the DAG are not allowed by this kind of pass.
|
||
</Attribute>
|
||
|
||
### is\_transformation\_pass
|
||
|
||
<Attribute id="qiskit.transpiler.passes.SabreSwap.is_transformation_pass">
|
||
Check if the pass is a transformation pass.
|
||
|
||
If the pass is a TransformationPass, that means that the pass can manipulate the DAG, but cannot modify the property set (but it can be read).
|
||
</Attribute>
|
||
|
||
## Methods
|
||
|
||
### execute
|
||
|
||
<Function id="qiskit.transpiler.passes.SabreSwap.execute" github="https://github.com/Qiskit/qiskit/tree/stable/1.2/qiskit/transpiler/basepasses.py#L189-L211" signature="execute(passmanager_ir, state, callback=None)">
|
||
Execute optimization task for input Qiskit IR.
|
||
|
||
**Parameters**
|
||
|
||
* **passmanager\_ir** ([*Any*](https://docs.python.org/3/library/typing.html#typing.Any "(in Python v3.13)")) – Qiskit IR to optimize.
|
||
* **state** ([*PassManagerState*](qiskit.passmanager.PassManagerState "qiskit.passmanager.compilation_status.PassManagerState")) – State associated with workflow execution by the pass manager itself.
|
||
* **callback** ([*Callable*](https://docs.python.org/3/library/collections.abc.html#collections.abc.Callable "(in Python v3.13)") *| None*) – A callback function which is caller per execution of optimization task.
|
||
|
||
**Returns**
|
||
|
||
Optimized Qiskit IR and state of the workflow.
|
||
|
||
**Return type**
|
||
|
||
[tuple](https://docs.python.org/3/library/stdtypes.html#tuple "(in Python v3.13)")\[[*Any*](https://docs.python.org/3/library/typing.html#typing.Any "(in Python v3.13)"), [qiskit.passmanager.compilation\_status.PassManagerState](qiskit.passmanager.PassManagerState "qiskit.passmanager.compilation_status.PassManagerState")]
|
||
</Function>
|
||
|
||
### name
|
||
|
||
<Function id="qiskit.transpiler.passes.SabreSwap.name" github="https://github.com/Qiskit/qiskit/tree/stable/1.2/qiskit/passmanager/base_tasks.py#L68-L70" signature="name()">
|
||
Name of the pass.
|
||
|
||
**Return type**
|
||
|
||
[str](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.13)")
|
||
</Function>
|
||
|
||
### run
|
||
|
||
<Function id="qiskit.transpiler.passes.SabreSwap.run" github="https://github.com/Qiskit/qiskit/tree/stable/1.2/qiskit/transpiler/passes/routing/sabre_swap.py#L175-L277" signature="run(dag)">
|
||
Run the SabreSwap pass on dag.
|
||
|
||
**Parameters**
|
||
|
||
**dag** ([*DAGCircuit*](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit")) – the directed acyclic graph to be mapped.
|
||
|
||
**Returns**
|
||
|
||
A dag mapped to be compatible with the coupling\_map.
|
||
|
||
**Return type**
|
||
|
||
[DAGCircuit](qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.DAGCircuit")
|
||
|
||
**Raises**
|
||
|
||
* [**TranspilerError**](transpiler#qiskit.transpiler.TranspilerError "qiskit.transpiler.TranspilerError") – if the coupling map or the layout are not
|
||
* **compatible with the DAG**\*\*, or \*\***if the coupling\_map=None** –
|
||
</Function>
|
||
|
||
### update\_status
|
||
|
||
<Function id="qiskit.transpiler.passes.SabreSwap.update_status" github="https://github.com/Qiskit/qiskit/tree/stable/1.2/qiskit/transpiler/basepasses.py#L213-L221" signature="update_status(state, run_state)">
|
||
Update workflow status.
|
||
|
||
**Parameters**
|
||
|
||
* **state** ([*PassManagerState*](qiskit.passmanager.PassManagerState "qiskit.passmanager.compilation_status.PassManagerState")) – Pass manager state to update.
|
||
* **run\_state** (*RunState*) – Completion status of current task.
|
||
|
||
**Returns**
|
||
|
||
Updated pass manager state.
|
||
|
||
**Return type**
|
||
|
||
[*PassManagerState*](qiskit.passmanager.PassManagerState "qiskit.passmanager.compilation_status.PassManagerState")
|
||
</Function>
|
||
</Class>
|
||
|