def _layout_from_raw(initial_layout, circuit): if initial_layout is None or isinstance(initial_layout, Layout): return initial_layout elif isinstancelist(initial_layout): if all(isinstanceint(elem) for elem in initial_layout): initial_layout = Layout.from_intlist(initial_layout, *circuit.qregs) elif all(elem is None or isinstance(elem, Qubit) for elem in initial_layout): initial_layout = Layout.from_qubit_list(initial_layout) elif isinstance(initial_layout, dict): initial_layout = Layout(initial_layout) else: raise TranspilerError("The initial_layout parameter could not be parsed") return initial_layout
def _compose_non_swap_nodes(self, accumulator: DAGCircuit, layout: Layout, new_dag: DAGCircuit) -> DAGCircuit: """Add all the non-swap strategy nodes that we have accumulated up to now. This method also resets the node accumulator to an empty dag. Args: layout: The current layout that keeps track of the swaps. new_dag: The new dag that we are building up. accumulator: A DAG to keep track of nodes that do not decompose using swap strategies. Returns: A new accumulator with the same registers as ``new_dag``. """ # Add all the non-swap strategy nodes that we have accumulated up to now. order = layout.reorder_bits(new_dag.qubits) order_bits = [None] * len(layout) for idx, val in enumerate(order): order_bits[val] = idx new_dag.compose(accumulator, qubits=order_bits) # Re-initialize the node accumulator return new_dag.copy_empty_like()
def test_all_single_qubit(self): """Test all trivial layers.""" coupling = CouplingMap([[0, 1], [1, 2], [1, 3]]) qr = QuantumRegister(2, 'q') ar = QuantumRegister(2, 'a') cr = ClassicalRegister(4, 'c') circ = QuantumCircuit(qr, ar, cr) circ.h(qr) circ.h(ar) circ.s(qr) circ.s(ar) circ.t(qr) circ.t(ar) circ.measure(qr[0], cr[0]) # intentional duplicate circ.measure(qr[0], cr[0]) circ.measure(qr[1], cr[1]) circ.measure(ar[0], cr[2]) circ.measure(ar[1], cr[3]) dag = circuit_to_dag(circ) layout = Layout({qr[0]: 0, qr[1]: 1, ar[0]: 2, ar[1]: 3}) pass_ = StochasticSwap(coupling, layout, 20, 13) after = pass_.run(dag) self.assertEqual(dag, after)
def test_multiple_registers_with_layout_adjust(self): """ Test two registers + measurements using a layout. The mapper will adjust the initial layout so that all of the gates can be done without swaps. """ coupling = CouplingMap([[0, 1], [1, 2]]) qr_q = QuantumRegister(2, 'q') qr_a = QuantumRegister(1, 'a') cr_c = ClassicalRegister(3, 'c') circ = QuantumCircuit(qr_q, qr_a, cr_c) circ.cx(qr_q[0], qr_a[0]) circ.cx(qr_q[1], qr_a[0]) circ.measure(qr_q[0], cr_c[0]) circ.measure(qr_q[1], cr_c[1]) circ.measure(qr_a[0], cr_c[2]) dag = circuit_to_dag(circ) layout = Layout({qr_q[0]: 0, qr_q[1]: 1, qr_a[0]: 2}) pass_ = StochasticSwap(coupling, layout, 20, 13) after = pass_.run(dag) self.assertEqual(dag, after)
def test_multi_alap(): qr0 = QuantumRegister(2) qr1 = QuantumRegister(2) qc = QuantumCircuit(qr0, qr1) qc.cx(qr0[0], qr0[1]) qc.cx(qr1[0], qr1[1]) qc.cx(qr1[1], qr1[0]) qc.cx(qr1[0], qr1[1]) qc.measure_all() layout = Layout({ qr0[0]: 0, qr0[1]: 1, qr1[0]: 2, qr1[1]: 3, }) durations = InstructionDurations([('cx', None, 1000), ('measure', None, 1000)]) transpiled_qc = transpile(qc, initial_layout=layout) dag = circuit_to_dag(transpiled_qc) malap_dag = MultiALAPSchedule(durations).run(dag, time_unit="dt") print(dag_to_circuit(malap_dag)) assert (malap_dag.duration == 4000)
def test_move_measurements(self): """Measurements applied AFTER swap mapping. """ backend = FakeRueschlikon() cmap = backend.configuration().coupling_map circ = QuantumCircuit.from_qasm_file( self._get_resource_path('move_measurements.qasm', Path.QASMS)) lay = Layout({ ('qa', 0): ('q', 0), ('qa', 1): ('q', 1), ('qb', 0): ('q', 15), ('qb', 1): ('q', 2), ('qb', 2): ('q', 14), ('qN', 0): ('q', 3), ('qN', 1): ('q', 13), ('qN', 2): ('q', 4), ('qc', 0): ('q', 12), ('qNt', 0): ('q', 5), ('qNt', 1): ('q', 11), ('qt', 0): ('q', 6) }) out = transpile(circ, initial_layout=lay, coupling_map=cmap) out_dag = circuit_to_dag(out) meas_nodes = out_dag.named_nodes('measure') for meas_node in meas_nodes: is_last_measure = all([ after_measure.type == 'out' for after_measure in out_dag.quantum_successors(meas_node) ]) self.assertTrue(is_last_measure)
def run(self, dag): """ If `dag` is mapped and the direction is correct the property `is_direction_mapped` is set to True (or to False otherwise). Args: dag (DAGCircuit): DAG to check. """ if self.layout is None: if self.property_set["layout"]: self.layout = self.property_set["layout"] else: self.layout = Layout.generate_trivial_layout( *dag.qregs.values()) self.property_set['is_direction_mapped'] = True edges = self.coupling_map.get_edges() for gate in dag.twoQ_gates(): physical_q0 = self.layout[gate.qargs[0]] physical_q1 = self.layout[gate.qargs[1]] if isinstance(gate.op, (CXBase, CnotGate)) and (physical_q0, physical_q1) not in edges: self.property_set['is_direction_mapped'] = False return
def test_already_mapped_1(self): """Circuit not remapped if matches topology. See: https://github.com/Qiskit/qiskit-terra/issues/342 """ backend = FakeRueschlikon() coupling_map = backend.configuration().coupling_map basis_gates = backend.configuration().basis_gates qr = QuantumRegister(16, 'qr') cr = ClassicalRegister(16, 'cr') qc = QuantumCircuit(qr, cr) qc.cx(qr[3], qr[14]) qc.cx(qr[5], qr[4]) qc.h(qr[9]) qc.cx(qr[9], qr[8]) qc.x(qr[11]) qc.cx(qr[3], qr[4]) qc.cx(qr[12], qr[11]) qc.cx(qr[13], qr[4]) qc.measure(qr, cr) new_qc = transpile(qc, coupling_map=coupling_map, basis_gates=basis_gates, initial_layout=Layout.generate_trivial_layout(qr)) cx_qubits = [ qargs for (gate, qargs, _) in new_qc.data if gate.name == "cx" ] cx_qubits_physical = [[ctrl.index, tgt.index] for [ctrl, tgt] in cx_qubits] self.assertEqual(sorted(cx_qubits_physical), [[3, 4], [3, 14], [5, 4], [9, 8], [12, 11], [13, 4]])
def test_3q_circuit_5q_coupling(self): """Allocates 2 ancillas for a 3q circuit in a 5q coupling map 0 -> q0 q0 -> 0 1 -> q1 q1 -> 1 => 2 -> q2 q2 -> 2 3 -> ancilla0 4 -> ancilla1 """ qr = QuantumRegister(3, 'q') circ = QuantumCircuit(qr) dag = circuit_to_dag(circ) initial_layout = Layout() initial_layout[0] = qr[0] initial_layout[1] = qr[1] initial_layout[2] = qr[2] pass_ = FullAncillaAllocation(self.cmap5) pass_.property_set['layout'] = initial_layout pass_.run(dag) after_layout = pass_.property_set['layout'] ancilla = QuantumRegister(2, 'ancilla') self.assertEqual(after_layout[0], qr[0]) self.assertEqual(after_layout[1], qr[1]) self.assertEqual(after_layout[2], qr[2]) self.assertEqual(after_layout[3], ancilla[0]) self.assertEqual(after_layout[4], ancilla[1])
def test_3q_with_holes_5q_coupling(self): """Allocates 3 ancillas for a 2q circuit on a 5q coupling, with holes 0 -> q0 q0 -> 0 1 -> ancilla0 q1 -> 2 => 2 -> q2 3 -> ancilla1 4 -> ancilla2 """ qr = QuantumRegister(2, 'q') circ = QuantumCircuit(qr) dag = circuit_to_dag(circ) initial_layout = Layout() initial_layout[0] = qr[0] initial_layout[2] = qr[1] pass_ = FullAncillaAllocation(self.cmap5) pass_.property_set['layout'] = initial_layout pass_.run(dag) after_layout = pass_.property_set['layout'] ancilla = QuantumRegister(3, 'ancilla') self.assertEqual(after_layout[0], qr[0]) self.assertEqual(after_layout[1], ancilla[0]) self.assertEqual(after_layout[2], qr[1]) self.assertEqual(after_layout[3], ancilla[1]) self.assertEqual(after_layout[4], ancilla[2])
def test_only_output_cx_and_swaps_in_coupling_map(self): """Test that output DAG contains only 2q gates from the the coupling map.""" coupling = CouplingMap([[0, 1], [1, 2], [2, 3]]) qr = QuantumRegister(4, 'q') cr = ClassicalRegister(4, 'c') circuit = QuantumCircuit(qr, cr) circuit.h(qr[0]) circuit.cx(qr[0], qr[1]) circuit.cx(qr[0], qr[2]) circuit.cx(qr[0], qr[3]) circuit.measure(qr, cr) dag = circuit_to_dag(circuit) layout = Layout({qr[0]: 0, qr[1]: 1, qr[2]: 2, qr[3]: 3}) pass_ = StochasticSwap(coupling, layout, 20, 5) after = pass_.run(dag) valid_couplings = [ set([layout[a], layout[b]]) for (a, b) in coupling.get_edges() ] for _2q_gate in after.twoQ_gates(): self.assertIn(set(_2q_gate.qargs), valid_couplings)
def test_initial_layout_in_different_qregs(self): """ Using an initial_layout, and with several qregs 0:q1_0:--(+)-- | 1:q0_0:---|--- | 2:q2_0:---.--- CouplingMap map: [0]--[1]--[2] 0:q1_0:--X------- | 1:q0_0:--X---.--- | 2:q2_0:-----(+)-- """ coupling = CouplingMap([[0, 1], [1, 2]]) qr0 = QuantumRegister(1, 'q0') qr1 = QuantumRegister(1, 'q1') qr2 = QuantumRegister(1, 'q2') circuit = QuantumCircuit(qr0, qr1, qr2) circuit.cx(qr1[0], qr2[0]) dag = circuit_to_dag(circuit) layout = Layout({qr1[0]: 0, qr0[0]: 1, qr2[0]: 2}) expected = QuantumCircuit(qr0, qr1, qr2) expected.swap(qr1[0], qr0[0]) expected.cx(qr0[0], qr2[0]) pass_ = BasicSwap(coupling, initial_layout=layout) after = pass_.run(dag) self.assertEqual(circuit_to_dag(expected), after)
def test_initial_layout(self): """ Using an initial_layout 0:q1:--(+)-- | 1:q0:---|--- | 2:q2:---.--- CouplingMap map: [0]--[1]--[2] 0:q1:--X------- | 1:q0:--X---.--- | 2:q2:-----(+)-- """ coupling = CouplingMap([[0, 1], [1, 2]]) qr = QuantumRegister(3, 'q') circuit = QuantumCircuit(qr) circuit.cx(qr[1], qr[2]) dag = circuit_to_dag(circuit) layout = Layout({qr[1]: 0, qr[0]: 1, qr[2]: 2}) expected = QuantumCircuit(qr) expected.swap(qr[1], qr[0]) expected.cx(qr[0], qr[2]) pass_ = BasicSwap(coupling, initial_layout=layout) after = pass_.run(dag) self.assertEqual(circuit_to_dag(expected), after)
def test_3q_out_of_order_5q_coupling(self): """Allocates 2 ancillas a 3q circuit on a 5q coupling map, out of order 0 <- q0 q0 -> 0 1 <- ancilla0 q1 -> 3 => 2 <- q2 q2 -> 2 3 <- q1 4 <- ancilla1 """ qr = QuantumRegister(3, 'q') circ = QuantumCircuit(qr) dag = circuit_to_dag(circ) initial_layout = Layout() initial_layout[0] = qr[0] initial_layout[3] = qr[1] initial_layout[2] = qr[2] pass_ = FullAncillaAllocation(self.cmap5) pass_.property_set['layout'] = initial_layout pass_.run(dag) after_layout = pass_.property_set['layout'] ancilla = QuantumRegister(2, 'ancilla') self.assertEqual(after_layout[0], qr[0]) self.assertEqual(after_layout[1], ancilla[0]) self.assertEqual(after_layout[2], qr[2]) self.assertEqual(after_layout[3], qr[1]) self.assertEqual(after_layout[4], ancilla[1])
def test_with_extension(self): """There are 2 virtual qubit to extend.""" ancilla = QuantumRegister(2, 'ancilla') layout = Layout({0: self.qr3[0], 1: ancilla[0], 2: self.qr3[1], 3: ancilla[1], 4: self.qr3[2]}) layout.add_register(ancilla) pass_ = EnlargeWithAncilla() pass_.property_set['layout'] = layout after = pass_.run(self.dag) qregs = list(after.qregs.values()) self.assertEqual(2, len(qregs)) self.assertEqual(self.qr3, qregs[0]) self.assertEqual(ancilla, qregs[1])
def test_final_measurement_barrier_for_devices(self, mock_pass): """Verify BarrierBeforeFinalMeasurements pass is called in default pipeline for devices.""" circ = QuantumCircuit.from_qasm_file(self._get_resource_path('example.qasm', Path.QASMS)) layout = Layout.generate_trivial_layout(*circ.qregs) transpile(circ, coupling_map=FakeRueschlikon().configuration().coupling_map, initial_layout=layout) self.assertTrue(mock_pass.called)
def create_passmanager(self, coupling_map, initial_layout=None): """Returns a PassManager using self.pass_class(coupling_map, initial_layout)""" passmanager = PassManager() if initial_layout: passmanager.append(SetLayout(Layout(initial_layout))) # pylint: disable=not-callable passmanager.append(self.pass_class(CouplingMap(coupling_map), **self.additional_args)) return passmanager
def _remap_circuit_faulty_backend(circuit, num_qubits, backend_prop, faulty_qubits_map): faulty_qubits = backend_prop.faulty_qubits() if backend_prop else [] disconnected_qubits = { k for k, v in faulty_qubits_map.items() if v is None }.difference(faulty_qubits) faulty_qubits_map_reverse = {v: k for k, v in faulty_qubits_map.items()} if faulty_qubits: faulty_qreg = circuit._create_qreg(len(faulty_qubits), 'faulty') else: faulty_qreg = [] if disconnected_qubits: disconnected_qreg = circuit._create_qreg(len(disconnected_qubits), 'disconnected') else: disconnected_qreg = [] new_layout = Layout() faulty_qubit = 0 disconnected_qubit = 0 for real_qubit in range(num_qubits): if faulty_qubits_map[real_qubit] is not None: new_layout[real_qubit] = circuit._layout[ faulty_qubits_map[real_qubit]] else: if real_qubit in faulty_qubits: new_layout[real_qubit] = faulty_qreg[faulty_qubit] faulty_qubit += 1 else: new_layout[real_qubit] = disconnected_qreg[disconnected_qubit] disconnected_qubit += 1 physical_layout_dict = {} for qubit in circuit.qubits: physical_layout_dict[qubit] = faulty_qubits_map_reverse[qubit.index] for qubit in faulty_qreg[:] + disconnected_qreg[:]: physical_layout_dict[qubit] = new_layout[qubit] dag_circuit = circuit_to_dag(circuit) apply_layout_pass = ApplyLayout() apply_layout_pass.property_set['layout'] = Layout(physical_layout_dict) circuit = dag_to_circuit(apply_layout_pass.run(dag_circuit)) circuit._layout = new_layout return circuit
def _remap_layout_faulty_backend(layout, faulty_qubits_map): if layout is None: return layout new_layout = Layout() for virtual, physical in layout.get_virtual_bits().items(): if faulty_qubits_map[physical] is None: raise TranspilerError("The initial_layout parameter refers to faulty" " or disconnected qubits") new_layout[virtual] = faulty_qubits_map[physical] return new_layout
def test_full_connected_coupling_map(self): """Test if the permutation {0->3,1->0,2->1,3->2} in a fully connected map.""" v = QuantumRegister(4, "v") # virtual qubits from_layout = Layout({v[0]: 0, v[1]: 1, v[2]: 2, v[3]: 3}) to_layout = Layout({v[0]: 3, v[1]: 0, v[2]: 1, v[3]: 2}) ltpass = LayoutTransformation(coupling_map=None, from_layout=from_layout, to_layout=to_layout, seed=42) qc = QuantumCircuit(4) # input (empty) physical circuit dag = circuit_to_dag(qc) output_dag = ltpass.run(dag) expected = QuantumCircuit(4) expected.swap(1, 0) expected.swap(2, 1) expected.swap(3, 2) self.assertEqual(circuit_to_dag(expected), output_dag)
def test_three_qubit(self): """Test if the permutation {0->2,1->0,2->1} is implemented correctly.""" v = QuantumRegister(3, "v") # virtual qubits coupling = CouplingMap([[0, 1], [1, 2]]) from_layout = Layout({v[0]: 0, v[1]: 1, v[2]: 2}) to_layout = Layout({v[0]: 2, v[1]: 0, v[2]: 1}) ltpass = LayoutTransformation(coupling_map=coupling, from_layout=from_layout, to_layout=to_layout, seed=42) qc = QuantumCircuit(3) dag = circuit_to_dag(qc) output_dag = ltpass.run(dag) expected = QuantumCircuit(3) expected.swap(1, 0) expected.swap(1, 2) self.assertEqual(circuit_to_dag(expected), output_dag)
def test_no_extension(self): """There are no virtual qubits to extend.""" layout = Layout({self.qr3[0]: 0, self.qr3[1]: 1, self.qr3[2]: 2}) pass_ = EnlargeWithAncilla(layout) after = pass_.run(self.dag) qregs = list(after.qregs.values()) self.assertEqual(1, len(qregs)) self.assertEqual(self.qr3, qregs[0])
def run(self, quantum_circuit): dag_circuit = circuit_to_dag(quantum_circuit) init_time = time.time() self.parameters["TIME_START"] = init_time initial_mapping = [] if self.parameters["initial_map"] == K7MInitialMapping.RANDOM: # Only the first positions which correspond to the circuit qubits initial_mapping = numpy.random.permutation( self.parameters["nisq_qubits"]) initial_mapping = initial_mapping[:dag_circuit.num_qubits()] elif self.parameters["initial_map"] == K7MInitialMapping.LINEAR: initial_mapping = list(range(dag_circuit.num_qubits())) elif self.parameters["initial_map"] == K7MInitialMapping.HEURISTIC: initial_mapping = cuthill_order(dag_circuit, self.coupling_obj, self.parameters) init_time = time.time() - init_time if initial_mapping is None: return None, init_time, None # print(initial_mapping) # # return quantum_circuit print(" .......") original_pm = PassManager() optimal_layout = Layout() for c_idx, p_idx in enumerate(initial_mapping): optimal_layout.add(quantum_circuit.qregs[0][c_idx], p_idx) original_pm.append([ SetLayout(optimal_layout), ApplyLayout(), StochasticSwap(self.coupling_obj.coupling, seed=0), Decompose(gate=qiskit.extensions.SwapGate) ]) return original_pm.run(quantum_circuit), init_time, initial_mapping
def run(self, dag): """ Flips the cx nodes to match the directed coupling map. Args: dag (DAGCircuit): DAG to map. Returns: DAGCircuit: The rearranged dag for the coupling map Raises: TranspilerError: If the circuit cannot be mapped just by flipping the cx nodes. """ new_dag = DAGCircuit() if self.layout is None: # LegacySwap renames the register in the DAG and does not match the property set self.layout = Layout.generate_trivial_layout(*dag.qregs.values()) for layer in dag.serial_layers(): subdag = layer['graph'] for cnot_node in subdag.named_nodes('cx', 'CX'): control = cnot_node.qargs[0] target = cnot_node.qargs[1] physical_q0 = self.layout[control] physical_q1 = self.layout[target] if self.coupling_map.distance(physical_q0, physical_q1) != 1: raise TranspilerError( 'The circuit requires a connection between physical ' 'qubits %s and %s' % (physical_q0, physical_q1)) if (physical_q0, physical_q1) not in self.coupling_map.get_edges(): # A flip needs to be done # Create the involved registers if control[0] not in subdag.qregs.values(): subdag.add_qreg(control[0]) if target[0] not in subdag.qregs.values(): subdag.add_qreg(target[0]) # Add H gates around subdag.apply_operation_back(HGate(), [target], []) subdag.apply_operation_back(HGate(), [control], []) subdag.apply_operation_front(HGate(), [target], []) subdag.apply_operation_front(HGate(), [control], []) # Flips the CX cnot_node.qargs[0], cnot_node.qargs[1] = target, control new_dag.extend_back(subdag) return new_dag
def test_default_pass_manager_two(self): """Test default_pass_manager.run(circuitS). circuit1 and circuit2: qr0:-[H]--.------------ -> 1 | qr1:-----(+)--.-------- -> 2 | qr2:---------(+)--.---- -> 3 | qr3:-------------(+)--- -> 5 device: 0 - 1 - 2 - 3 - 4 - 5 - 6 | | | | | | 13 - 12 - 11 - 10 - 9 - 8 - 7 """ qr = QuantumRegister(4, "qr") circuit1 = QuantumCircuit(qr) circuit1.h(qr[0]) circuit1.cx(qr[0], qr[1]) circuit1.cx(qr[1], qr[2]) circuit1.cx(qr[2], qr[3]) circuit2 = QuantumCircuit(qr) circuit2.cx(qr[1], qr[2]) circuit2.cx(qr[0], qr[1]) circuit2.cx(qr[2], qr[3]) coupling_map = FakeMelbourne().configuration().coupling_map basis_gates = FakeMelbourne().configuration().basis_gates initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]] pass_manager = level_1_pass_manager( PassManagerConfig( basis_gates=basis_gates, coupling_map=CouplingMap(coupling_map), initial_layout=Layout.from_qubit_list(initial_layout), seed_transpiler=42, )) new_circuits = pass_manager.run([circuit1, circuit2]) for new_circuit in new_circuits: bit_indices = { bit: idx for idx, bit in enumerate(new_circuit.qregs[0]) } for gate, qargs, _ in new_circuit.data: if isinstance(gate, CXGate): self.assertIn([bit_indices[x] for x in qargs], coupling_map)
def test_empty_score(self): """Test error rate is 0 for empty circuit.""" bit_map = {} reverse_bit_map = {} im_graph = retworkx.PyDiGraph() backend = FakeYorktownV2() vf2_pass = VF2PostLayout(target=backend.target) layout = Layout() score = vf2_pass._score_layout(layout, bit_map, reverse_bit_map, im_graph) self.assertEqual(0, score)
def setUp(self): coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]] coupling_map = CouplingMap(couplinglist=coupling) qr = QuantumRegister(7, 'q') layout = Layout({qr[i]: i for i in range(coupling_map.size())}) self.config = TranspileConfig(optimization_level=1, basis_gates=['u1', 'u3', 'u2', 'cx'], initial_layout=layout, coupling_map=coupling_map, seed_transpiler=987, backend_properties=None)
def test_four_qubit(self): """Test if the permutation {0->3,1->0,2->1,3->2} is implemented correctly.""" v = QuantumRegister(4, "v") # virtual qubits coupling = CouplingMap([[0, 1], [1, 2], [2, 3]]) from_layout = Layout({v[0]: 0, v[1]: 1, v[2]: 2, v[3]: 3}) to_layout = Layout({v[0]: 3, v[1]: 0, v[2]: 1, v[3]: 2}) ltpass = LayoutTransformation(coupling_map=coupling, from_layout=from_layout, to_layout=to_layout, seed=42) qc = QuantumCircuit(4) # input (empty) physical circuit dag = circuit_to_dag(qc) output_dag = ltpass.run(dag) expected = QuantumCircuit(4) expected.swap(1, 0) expected.swap(1, 2) expected.swap(2, 3) self.assertEqual(circuit_to_dag(expected), output_dag)
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: TranspilerError: if the coupling map or the layout are not compatible with the DAG """ coupling_map = self._coupling_map ordered_virtual_gates = list(dag.serial_layers()) if self.initial_layout is None: if self.property_set["layout"]: self.initial_layout = self.property_set["layout"] else: self.initial_layout = Layout.generate_trivial_layout( *dag.qregs.values()) if len(dag.qubits()) != len(self.initial_layout): raise TranspilerError( 'The layout does not match the amount of qubits in the DAG') if len(self._coupling_map.physical_qubits) != len(self.initial_layout): raise TranspilerError( "Mappers require to have the layout to be the same size as the coupling map" ) mapped_gates = [] layout = self.initial_layout.copy() 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 node in mapped_gates: mapped_dag.apply_operation_back(op=node.op, qargs=node.qargs, cargs=node.cargs) return mapped_dag
def test_three_qubit(self): """Test if the permutation {0->2,1->0,2->1} is implemented correctly.""" np.random.seed(0) v = QuantumRegister(3, 'v') # virtual qubits coupling = CouplingMap([[0, 1], [1, 2]]) from_layout = Layout({v[0]: 0, v[1]: 1, v[2]: 2}) to_layout = Layout({v[0]: 2, v[1]: 0, v[2]: 1}) ltpass = LayoutTransformation(coupling_map=coupling, from_layout=from_layout, to_layout=to_layout) qc = QuantumCircuit(3) # input (empty) physical circuit dag = circuit_to_dag(qc) q = dag.qubits() output_dag = ltpass.run(dag) # output_dag.draw() # Check that only two swaps were performed self.assertCountEqual(["swap"] * 2, [op.name for op in output_dag.topological_op_nodes()]) # And check that the swaps were first performed on {q0,q1} then on {q1,q2}. self.assertEqual([frozenset([q[0], q[1]]), frozenset([q[1], q[2]])], [frozenset(op.qargs) for op in output_dag.topological_op_nodes()])