From c5c6b11324f1c15046035ab1b69f196d1c6aa919 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Thu, 7 Sep 2023 13:53:08 +0100 Subject: [PATCH] Track Sabre decay heuristic on physical qubits (#10756) The custom `decay` heuristic is supposed to penalise increases in depth in the output. The output space of qubits are the physical qubits, so the depth is defined in relation to those. Since its introduction in gh-4537, this heuristic has instead been tracking the depth on the virtual qubits, which due to the swaps is not necessarily related to the depth in the output. Notably, this commit actually makes the depth for routing large volumetric circuits slightly _worse_ on average (at least for heavy-hex topologies). This may be because the effect on the heuristic is overweighted, or that the depth tracking resets after each gate is routed (and occasionally in between) to be flat across all qubits, rather than reflecting the actual depth each qubit is subject to. --- crates/accelerate/src/sabre_swap/mod.rs | 7 ++++--- .../notes/sabre-decay-physical-ad2f470cd45d69f3.yaml | 6 ++++++ test/python/transpiler/test_sabre_layout.py | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/sabre-decay-physical-ad2f470cd45d69f3.yaml diff --git a/crates/accelerate/src/sabre_swap/mod.rs b/crates/accelerate/src/sabre_swap/mod.rs index 2a7c7317f650..6a1aa9b7bc4e 100644 --- a/crates/accelerate/src/sabre_swap/mod.rs +++ b/crates/accelerate/src/sabre_swap/mod.rs @@ -411,8 +411,8 @@ fn swap_map_trial( qubits_decay.fill(1.); num_search_steps = 0; } else { - qubits_decay[best_swap[0].index()] += DECAY_RATE; - qubits_decay[best_swap[1].index()] += DECAY_RATE; + qubits_decay[best_swap[0].to_phys(&layout).index()] += DECAY_RATE; + qubits_decay[best_swap[1].to_phys(&layout).index()] += DECAY_RATE; } } // If we exceeded the number of allowed attempts without successfully routing a node, we @@ -713,7 +713,8 @@ fn choose_best_swap( + EXTENDED_SET_WEIGHT * extended_set.score(swap, layout, dist) } Heuristic::Decay => { - qubits_decay[swap[0].index()].max(qubits_decay[swap[1].index()]) + qubits_decay[swap[0].to_phys(layout).index()] + .max(qubits_decay[swap[1].to_phys(layout).index()]) * (absolute_score + layer.score(swap, layout, dist) + EXTENDED_SET_WEIGHT * extended_set.score(swap, layout, dist)) diff --git a/releasenotes/notes/sabre-decay-physical-ad2f470cd45d69f3.yaml b/releasenotes/notes/sabre-decay-physical-ad2f470cd45d69f3.yaml new file mode 100644 index 000000000000..8d647d5b13d5 --- /dev/null +++ b/releasenotes/notes/sabre-decay-physical-ad2f470cd45d69f3.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + The ``"decay"`` heuristic of :class:`.SabreSwap` and :class:`.SabreLayout` now tracks the depth + correctly on physical qubits rather than mistakenly tracking the "depth" of swaps on virtual + qubits. diff --git a/test/python/transpiler/test_sabre_layout.py b/test/python/transpiler/test_sabre_layout.py index 2c41de46df04..ff9788521c16 100644 --- a/test/python/transpiler/test_sabre_layout.py +++ b/test/python/transpiler/test_sabre_layout.py @@ -60,7 +60,7 @@ def test_5q_circuit_20q_coupling(self): pass_.run(dag) layout = pass_.property_set["layout"] - self.assertEqual([layout[q] for q in circuit.qubits], [11, 10, 16, 5, 17]) + self.assertEqual([layout[q] for q in circuit.qubits], [16, 7, 11, 12, 13]) def test_6q_circuit_20q_coupling(self): """Test finds layout for 6q circuit on 20q device."""