def run(self, dag): """Run one pass of the lookahead mapper on the provided DAG. Args: dag (DAGCircuit): the directed acyclic graph to be mapped Returns: DAGCircuit: A dag mapped to be compatible with the coupling_map in the property_set. Raises: MapperError: If the provided DAG has more qubits than are available in the coupling map. """ # Preserve fix for https://github.com/Qiskit/qiskit-terra/issues/674 removed_measures = remove_last_measurements(dag) coupling_map = self._coupling_map ordered_virtual_gates = list(dag.serial_layers()) if len(dag.get_qubits()) > len(coupling_map.physical_qubits): raise MapperError( 'DAG contains more qubits than are present in the coupling map.' ) dag_qubits = dag.get_qubits() coupling_qubits = coupling_map.physical_qubits starting_layout = [ dag_qubits[i] if i < len(dag_qubits) else None for i in range(len(coupling_qubits)) ] mapped_gates = [] layout = Layout(starting_layout) gates_remaining = ordered_virtual_gates.copy() while gates_remaining: best_step = _search_forward_n_swaps(layout, gates_remaining, coupling_map) layout = best_step['layout'] gates_mapped = best_step['gates_mapped'] gates_remaining = best_step['gates_remaining'] mapped_gates.extend(gates_mapped) # Preserve input DAG's name, regs, wire_map, etc. but replace the graph. mapped_dag = _copy_circuit_metadata(dag, coupling_map) for gate in mapped_gates: mapped_dag.apply_operation_back(**gate) return_last_measurements(mapped_dag, removed_measures, layout) return mapped_dag
def transpile(dag, basis_gates='u1,u2,u3,cx,id', coupling_map=None, initial_layout=None, get_layout=False, format='dag', seed=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 (str): a comma separated string for the target basis gates 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) } get_layout (bool): flag for returning the final layout after mapping format (str): The target format of the compilation: {'dag', 'json', 'qasm'} seed (int): random seed 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 DAGCircuit, dict: transformed dag along with the final layout on backend qubits Raises: TranspilerError: if the format is not valid. """ # TODO: `basis_gates` will be removed after we have the unroller pass. # TODO: `coupling_map`, `initial_layout`, `get_layout`, `seed` removed after mapper pass. # TODO: move this to the mapper pass num_qubits = sum(dag.qregs.values()) if num_qubits == 1 or coupling_map == "all-to-all": coupling_map = None final_layout = None 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 basis = basis_gates.split(',') if basis_gates else [] dag_unroller = DagUnroller(dag, DAGBackend(basis)) dag = dag_unroller.expand_gates() # if a coupling map is given compile to the map if coupling_map: logger.info("pre-mapping properties: %s", dag.property_summary()) # Insert swap gates coupling = Coupling(coupling_list2dict(coupling_map)) removed_meas = remove_last_measurements(dag) logger.info("measurements moved: %s", removed_meas) logger.info("initial layout: %s", initial_layout) dag, final_layout, last_layout = swap_mapper(dag, coupling, initial_layout, trials=20, seed=seed) logger.info("final layout: %s", final_layout) # Expand swaps dag_unroller = DagUnroller(dag, DAGBackend(basis)) dag = dag_unroller.expand_gates() # Change cx directions dag = direction_mapper(dag, coupling) # Simplify cx gates cx_cancellation(dag) # Simplify single qubit gates dag = optimize_1q_gates(dag) return_last_measurements(dag, removed_meas, last_layout) logger.info("post-mapping properties: %s", dag.property_summary()) # choose output format # TODO: do we need all of these formats, or just the dag? if format == 'dag': compiled_circuit = dag elif format == 'json': # FIXME: JsonBackend is wrongly taking an ordered dict as basis, not list dag_unroller = DagUnroller(dag, JsonBackend(dag.basis)) compiled_circuit = dag_unroller.execute() elif format == 'qasm': compiled_circuit = dag.qasm() else: raise TranspilerError('unrecognized circuit format') if get_layout: return compiled_circuit, final_layout return compiled_circuit
def transpile_dag(dag, basis_gates='u1,u2,u3,cx,id', coupling_map=None, initial_layout=None, get_layout=False, format='dag', 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 (str): a comma separated string for the target basis gates 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) } get_layout (bool): flag for returning the final layout after mapping format (str): DEPRECATED The target format of the compilation: {'dag', 'json', 'qasm'} 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 DAGCircuit, dict: transformed dag along with the final layout on backend qubits """ # TODO: `basis_gates` will be removed after we have the unroller pass. # TODO: `coupling_map`, `initial_layout`, `get_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 final_layout = None 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 basis = basis_gates.split(',') if basis_gates else [] dag = Unroller(basis).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 = Coupling(couplinglist=coupling_map) removed_meas = remove_last_measurements(dag) logger.info("measurements moved: %s", removed_meas) logger.info("initial layout: %s", initial_layout) dag, final_layout, last_layout = swap_mapper(dag, coupling, initial_layout, trials=20, seed=seed_mapper) logger.info("final layout: %s", final_layout) # Expand swaps dag = Unroller(basis).run(dag) # Change cx directions dag = direction_mapper(dag, coupling) # Simplify cx gates cx_cancellation(dag) # Simplify single qubit gates dag = optimize_1q_gates(dag) return_last_measurements(dag, removed_meas, last_layout) logger.info("post-mapping properties: %s", dag.properties()) if format != 'dag': warnings.warn( "transpiler no longer supports different formats. " "only dag to dag transformations are supported.", DeprecationWarning) if get_layout: return dag, final_layout return dag