def transpile_dag(dag, basis_gates=None, coupling_map=None, initial_layout=None, seed_mapper=None, pass_manager=None): """Transform a dag circuit into another dag circuit (transpile), through consecutive passes on the dag. Args: dag (DAGCircuit): dag circuit to transform via transpilation basis_gates (list[str]): list of basis gate names supported by the target. Default: ['u1','u2','u3','cx','id'] coupling_map (list): A graph of coupling:: [ [control0(int), target0(int)], [control1(int), target1(int)], ] eg. [[0, 2], [1, 2], [1, 3], [3, 4]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", start(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } seed_mapper (int): random seed_mapper for the swap mapper pass_manager (PassManager): pass manager instance for the transpilation process If None, a default set of passes are run. Otherwise, the passes defined in it will run. If contains no passes in it, no dag transformations occur. Returns: DAGCircuit: transformed dag """ # TODO: `basis_gates` will be removed after we have the unroller pass. # TODO: `coupling_map`, `initial_layout`, `seed_mapper` removed after mapper pass. # TODO: move this to the mapper pass num_qubits = sum([qreg.size for qreg in dag.qregs.values()]) if num_qubits == 1 or coupling_map == "all-to-all": coupling_map = None if basis_gates is None: basis_gates = ['u1', 'u2', 'u3', 'cx', 'id'] if isinstance(basis_gates, str): warnings.warn( "The parameter basis_gates is now a list of strings. " "For example, this basis ['u1','u2','u3','cx'] should be used " "instead of 'u1,u2,u3,cx'. The string format will be " "removed after 0.9", DeprecationWarning, 2) basis_gates = basis_gates.split(',') if pass_manager: # run the passes specified by the pass manager # TODO return the property set too. See #1086 dag = pass_manager.run_passes(dag) else: # default set of passes # TODO: move each step here to a pass, and use a default passmanager below name = dag.name dag = Unroller(basis_gates).run(dag) dag = BarrierBeforeFinalMeasurements().run(dag) # if a coupling map is given compile to the map if coupling_map: logger.info("pre-mapping properties: %s", dag.properties()) # Insert swap gates coupling = CouplingMap(coupling_map) logger.info("initial layout: %s", initial_layout) dag, final_layout = swap_mapper(dag, coupling, initial_layout, trials=20, seed=seed_mapper) logger.info("final layout: %s", final_layout) # Expand swaps dag = Decompose(SwapGate).run(dag) # Change cx directions dag = CXDirection(coupling).run(dag) # Simplify cx gates dag = CXCancellation().run(dag) # Unroll to the basis dag = Unroller(['u1', 'u2', 'u3', 'id', 'cx']).run(dag) # Simplify single qubit gates dag = Optimize1qGates().run(dag) logger.info("post-mapping properties: %s", dag.properties()) dag.name = name return dag
def transpile_dag(dag, basis_gates=None, coupling_map=None, initial_layout=None, seed_mapper=None, pass_manager=None): """Transform a dag circuit into another dag circuit (transpile), through consecutive passes on the dag. Args: dag (DAGCircuit): dag circuit to transform via transpilation basis_gates (list[str]): list of basis gate names supported by the target. Default: ['u1','u2','u3','cx','id'] coupling_map (list): A graph of coupling:: [ [control0(int), target0(int)], [control1(int), target1(int)], ] eg. [[0, 2], [1, 2], [1, 3], [3, 4]} initial_layout (Layout or None): A layout object seed_mapper (int): random seed_mapper for the swap mapper pass_manager (PassManager): pass manager instance for the transpilation process If None, a default set of passes are run. Otherwise, the passes defined in it will run. If contains no passes in it, no dag transformations occur. Returns: DAGCircuit: transformed dag """ # TODO: `basis_gates` will be removed after we have the unroller pass. # TODO: `coupling_map`, `initial_layout`, `seed_mapper` removed after mapper pass. # TODO: move this to the mapper pass num_qubits = sum([qreg.size for qreg in dag.qregs.values()]) if num_qubits == 1: coupling_map = None if basis_gates is None: basis_gates = ['u1', 'u2', 'u3', 'cx', 'id'] if isinstance(basis_gates, str): warnings.warn( "The parameter basis_gates is now a list of strings. " "For example, this basis ['u1','u2','u3','cx'] should be used " "instead of 'u1,u2,u3,cx'. The string format will be " "removed after 0.9", DeprecationWarning, 2) basis_gates = basis_gates.split(',') if initial_layout is None: initial_layout = Layout.generate_trivial_layout(*dag.qregs.values()) if pass_manager: # run the passes specified by the pass manager # TODO return the property set too. See #1086 dag = pass_manager.run_passes(dag) else: # default set of passes # TODO: move each step here to a pass, and use a default passmanager below name = dag.name dag = Unroller(basis_gates).run(dag) dag = BarrierBeforeFinalMeasurements().run(dag) # if a coupling map is given compile to the map if coupling_map: logger.info("pre-mapping properties: %s", dag.properties()) coupling = CouplingMap(coupling_map) # Extend and enlarge the the dag/layout with ancillas using the full coupling map logger.info("initial layout: %s", initial_layout) pass_ = ExtendLayout(coupling) pass_.property_set['layout'] = initial_layout pass_.run(dag) initial_layout = pass_.property_set['layout'] pass_ = EnlargeWithAncilla(initial_layout) dag = pass_.run(dag) initial_layout = pass_.property_set['layout'] logger.info("initial layout (ancilla extended): %s", initial_layout) # temporarily build old-style layout dict # (TODO: remove after transition to StochasticSwap pass) virtual_qubits = initial_layout.get_virtual_bits() initial_layout = {(v[0].name, v[1]): ('q', initial_layout[v]) for v in virtual_qubits} # Swap mapper dag, final_layout = swap_mapper(dag, coupling, initial_layout, trials=20, seed=seed_mapper) logger.info("final layout: %s", final_layout) # Expand swaps dag = Decompose(SwapGate).run(dag) # Change cx directions dag = CXDirection(coupling).run(dag) # Unroll to the basis dag = Unroller(['u1', 'u2', 'u3', 'id', 'cx']).run(dag) # Simplify single qubit gates and CXs pm_4_optimization = PassManager() pm_4_optimization.append( [Optimize1qGates(), CXCancellation(), DAGFixedPoint()], do_while=lambda property_set: not property_set[ 'dag_fixed_point']) dag = transpile_dag(dag, pass_manager=pm_4_optimization) dag.name = name return dag