Skip to content

Commit

Permalink
remove LayoutTransformation call
Browse files Browse the repository at this point in the history
  • Loading branch information
ewinston committed Oct 5, 2022
1 parent 64e078d commit 8f583c9
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 26 deletions.
3 changes: 0 additions & 3 deletions qiskit/transpiler/passes/routing/layout_transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,5 @@ def run(self, dag):
perm_circ = self.token_swapper.permutation_circuit(permutation, self.trials)

qubits = [dag.qubits[i[0]] for i in sorted(perm_circ.inputmap.items(), key=lambda x: x[0])]
self.property_set["perm_circ"] = perm_circ
self.property_set["perm_qubits"] = qubits

dag.compose(perm_circ.circuit, qubits=qubits, inplace=self.inplace)
return dag
66 changes: 43 additions & 23 deletions qiskit/transpiler/passes/routing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from qiskit.transpiler.layout import Layout
from qiskit.dagcircuit import DAGCircuit
from qiskit.circuit import QuantumRegister
from qiskit.transpiler import CouplingMap
from qiskit.transpiler.exceptions import TranspilerError


def route_cf_multiblock(tpass, cf_opnode, current_layout, qregs, root_dag, seed=None):
Expand All @@ -38,7 +40,6 @@ def route_cf_multiblock(tpass, cf_opnode, current_layout, qregs, root_dag, seed=
list(Qubit): list of idle qubits in controlflow layer.
"""
# pylint: disable=cyclic-import
from qiskit.transpiler.passes.routing.layout_transformation import LayoutTransformation
from qiskit.converters import dag_to_circuit, circuit_to_dag

if current_layout is None:
Expand Down Expand Up @@ -67,18 +68,13 @@ def route_cf_multiblock(tpass, cf_opnode, current_layout, qregs, root_dag, seed=
if i == deepest_index:
block_circuits[i] = dag_to_circuit(updated_dag_block)
else:
layout_xform = LayoutTransformation(
coupling, block_layouts[i], block_layouts[deepest_index], seed=seed, inplace=False
swap_circuit, swap_qubits = _get_swap_map_dag(
root_dag, coupling, block_layouts[i], block_layouts[deepest_index], seed=seed
)
layout_xform.run(updated_dag_block)
physical_swap_dag = layout_xform.property_set["perm_circ"].circuit
if physical_swap_dag.depth():
if swap_circuit.depth():
virtual_swap_dag = updated_dag_block.copy_empty_like()
order = [
p2v[virtual_swap_dag.qubits.index(qubit)]
for qubit in layout_xform.property_set["perm_qubits"]
]
virtual_swap_dag.compose(physical_swap_dag, qubits=order)
order = [p2v[virtual_swap_dag.qubits.index(qubit)] for qubit in swap_qubits]
virtual_swap_dag.compose(swap_circuit, qubits=order)
updated_dag_block.compose(virtual_swap_dag)
idle_qubits &= set(updated_dag_block.idle_wires())
# contract idle bits from full width post routing
Expand All @@ -100,7 +96,7 @@ def route_cf_multiblock(tpass, cf_opnode, current_layout, qregs, root_dag, seed=


def route_cf_looping(tpass, cf_opnode, current_layout, root_dag, seed=None):
"""For looping this pass adds a swap layer using LayoutTransformation
"""For looping this pass adds a swap layer using ApproximateTokenSwapper
to the end of the loop body to bring the layout back to the
starting layout. This prevents reapplying layout changing
swaps for every iteration of the loop.
Expand All @@ -119,7 +115,6 @@ def route_cf_looping(tpass, cf_opnode, current_layout, root_dag, seed=None):
list(Qubit): list of idle qubits in controlflow layer.
"""
# pylint: disable=cyclic-import
from qiskit.transpiler.passes.routing.layout_transformation import LayoutTransformation
from qiskit.converters import dag_to_circuit, circuit_to_dag

cf_op = cf_opnode.op # control flow operation
Expand All @@ -133,19 +128,15 @@ def route_cf_looping(tpass, cf_opnode, current_layout, root_dag, seed=None):
full_dag_block.compose(dag_block, qubits=order)
updated_dag_block = tpass.run(full_dag_block)
updated_layout = tpass.property_set["final_layout"].copy()
layout_xform = LayoutTransformation(
coupling, updated_layout, start_layout, seed=seed, inplace=False
swap_circuit, swap_qubits = _get_swap_map_dag(
root_dag, coupling, updated_layout, start_layout, seed=seed
)
layout_xform.run(updated_dag_block)
physical_swap_dag = layout_xform.property_set["perm_circ"].circuit
if physical_swap_dag.depth():

if swap_circuit.depth():
p2v = current_layout.get_physical_bits()
virtual_swap_dag = updated_dag_block.copy_empty_like()
order = [
p2v[virtual_swap_dag.qubits.index(qubit)]
for qubit in layout_xform.property_set["perm_qubits"]
]
virtual_swap_dag.compose(physical_swap_dag, qubits=order)
order = [p2v[virtual_swap_dag.qubits.index(qubit)] for qubit in swap_qubits]
virtual_swap_dag.compose(swap_circuit, qubits=order)
updated_dag_block.compose(virtual_swap_dag)
# contract from full width post routing
idle_qubits = set(root_dag.qubits) & set(updated_dag_block.idle_wires())
Expand Down Expand Up @@ -178,3 +169,32 @@ def combine_permutations(*permutations):
for this_order in permutations[1:]:
order = [order[i] for i in this_order]
return order


def _get_swap_map_dag(dag, coupling_map, from_layout, to_layout, seed, trials=4):
"""Gets the circuit of swaps to go from from_layout to to_layout."""
from qiskit.transpiler.passes.routing.algorithms import ApproximateTokenSwapper

if len(dag.qregs) != 1 or dag.qregs.get("q", None) is None:
raise TranspilerError("layout transformation runs on physical circuits only")

if len(dag.qubits) > len(coupling_map.physical_qubits):
raise TranspilerError("The layout does not match the amount of qubits in the DAG")

if coupling_map:
graph = coupling_map.graph.to_undirected()
else:
coupling_map = CouplingMap.from_full(len(to_layout))
graph = coupling_map.graph.to_undirected()

token_swapper = ApproximateTokenSwapper(graph, seed)
# Find the permutation between the initial physical qubits and final physical qubits.
permutation = {
pqubit: to_layout.get_virtual_bits()[vqubit]
for vqubit, pqubit in from_layout.get_virtual_bits().items()
}
permutation_circ = token_swapper.permutation_circuit(permutation, trials)
permutation_qubits = [
dag.qubits[i[0]] for i in sorted(permutation_circ.inputmap.items(), key=lambda x: x[0])
]
return permutation_circ.circuit, permutation_qubits

0 comments on commit 8f583c9

Please sign in to comment.