qilisdk.digital.circuit_transpiler_passes.sabre_swap_pass

Classes

SabreSwapPass

SABRE routing (SWAP insertion) for 1Q/2Q circuits on an undirected coupling graph.

Module Contents

class SabreSwapPass(topology: qilisdk.digital.types.Topology, *, initial_layout: list[int] | None = None, seed: int | None = None, lookahead_size: int = 10, beta: float = 0.8, decay_delta: float = 0.001, decay_lambda: float = 0.99, max_swaps_factor: float = 64.0, max_attempts: int = 10)[source]

Bases: qilisdk.digital.circuit_transpiler_passes.circuit_transpiler_pass.CircuitTranspilerPass

SABRE routing (SWAP insertion) for 1Q/2Q circuits on an undirected coupling graph.

Inputs

topologyTopology

Coupling map provided either as an edge list or as an undirected PyGraph whose node indices are physical qubits.

initial_layoutlist[int] | None

Logical -> physical mapping to start from (e.g., from SabreLayoutPass.last_layout). If None, uses the lowest-indexed physical qubits provided by the coupling graph.

Heuristic (SABRE-style)

When a 2Q gate’s mapped endpoints are non-adjacent, choose one SWAP on an edge touching the mapped endpoints of the current front-set gates that minimizes:

cost = sum_{g in F} distance_matrix(p_u, p_v) * (1 + decay[p_u] + decay[p_v])
  • beta * sum_{g in E} distance_matrix(p_u, p_v)

where F is the per-qubit first unscheduled 2Q gate and E is a small look-ahead set. A light decay penalty discourages thrashing.

Behavior

  • Returns a new Circuit with 1Q gates mapped and SWAPs inserted before each non-adjacent 2Q gate so that every emitted 2Q gate acts on an edge of topology.

  • Preserves the original gate order (no reordering/commutation across the list).

Notes

  • Supports 1Q and 2Q gates (CNOT, CZ, SWAP, generic Controlled with one control). Multi-qubit (>2) non-SWAP gates should be decomposed before routing.

Configure SABRE swap routing behavior.

param topology:

Coupling map as an edge list or PyGraph.

type topology:

Topology

param initial_layout:

Optional initial logical-to-physical mapping; uses identity-style mapping when omitted.

type initial_layout:

list[int] | None

param seed:

Base seed for stochastic swap scoring and retry attempts.

type seed:

int | None

param lookahead_size:

Number of future two-qubit gates used in the extended SABRE cost.

type lookahead_size:

int

param beta:

Weight balancing extended-set cost against immediate front-set cost.

type beta:

float

param decay_delta:

Penalty increment added to swapped physical qubits.

type decay_delta:

float

param decay_lambda:

Per-iteration multiplier that relaxes accumulated decay penalties.

type decay_lambda:

float

param max_swaps_factor:

Per-gate swap budget factor derived from current endpoint distance.

type max_swaps_factor:

float

param max_attempts:

Maximum number of independent routing attempts with varied seeds.

type max_attempts:

int

topology: rustworkx.PyGraph[int, None][source]
initial_layout = None[source]
seed = None[source]
lookahead_size = 10[source]
beta[source]
decay_delta[source]
decay_lambda[source]
max_swaps_factor[source]
max_attempts = 10[source]
last_swap_count: int | None = None[source]
last_final_layout: list[int] | None = None[source]
run(circuit: qilisdk.digital.Circuit) qilisdk.digital.Circuit[source]

Route a circuit onto the coupling graph using SABRE swap insertion.

The pass retries with different seeds when an attempt exceeds swap budget and stores diagnostics in context.

Parameters:

circuit (Circuit) – Logical circuit to route.

Returns:

Routed circuit with gates mapped to physical qubits and inserted SWAPs.

Return type:

Circuit

Raises:

RuntimeError – If all attempts fail due to exhausted swap budgets.