コード例 #1
0
    def run(self, dag):
        """
        Runs the BasicSwap pass on `dag`.
        Args:
            dag (DAGCircuit): DAG to map.

        Returns:
            DAGCircuit: A mapped DAG.
        """
        new_dag = DAGCircuit()

        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())

        current_layout = copy(self.initial_layout)

        for layer in dag.serial_layers():
            subdag = layer['graph']

            for gate in subdag.get_2q_nodes():
                physical_q0 = current_layout[gate['qargs'][0]]
                physical_q1 = current_layout[gate['qargs'][1]]
                if self.coupling_map.distance(physical_q0, physical_q1) != 1:
                    # Insert a new layer with the SWAP(s).
                    swap_layer = DAGCircuit()

                    path = self.coupling_map.shortest_undirected_path(physical_q0, physical_q1)
                    for swap in range(len(path) - 2):
                        connected_wire_1 = path[swap]
                        connected_wire_2 = path[swap + 1]

                        qubit_1 = current_layout[connected_wire_1]
                        qubit_2 = current_layout[connected_wire_2]

                        # create qregs
                        for qreg in current_layout.get_registers():
                            if qreg[0] not in swap_layer.qregs.values():
                                swap_layer.add_qreg(qreg[0])

                        # create the swap operation
                        swap_layer.add_basis_element('swap', 2, 0, 0)
                        swap_layer.apply_operation_back(self.swap_gate(qubit_1, qubit_2),
                                                        qargs=[qubit_1, qubit_2])

                    # layer insertion
                    edge_map = current_layout.combine_into_edge_map(self.initial_layout)
                    new_dag.compose_back(swap_layer, edge_map)

                    # update current_layout
                    for swap in range(len(path) - 2):
                        current_layout.swap(path[swap], path[swap + 1])

            edge_map = current_layout.combine_into_edge_map(self.initial_layout)
            new_dag.extend_back(subdag, edge_map)

        return new_dag
コード例 #2
0
ファイル: cx_direction.py プロジェクト: dolph/qiskit-terra
    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:
            if self.property_set["layout"]:
                self.layout = self.property_set["layout"]
            else:
                self.layout = Layout.generate_trivial_layout(
                    *dag.qregs.values())

        for layer in dag.serial_layers():
            subdag = layer['graph']

            for cnot_id in subdag.named_nodes('cx', 'CX'):
                cnot_node = subdag.node(cnot_id)
                control = cnot_node['op'].qargs[0]
                target = cnot_node['op'].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['op'].qargs[0], cnot_node['op'].qargs[
                        1] = target, control

            new_dag.extend_back(subdag)

        return new_dag
コード例 #3
0
    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:
            MapperError: If the circuit cannot be mapped just by flipping the
                         cx nodes.
        """
        new_dag = DAGCircuit()

        if self.layout is None:
            # create a one-to-one layout
            self.layout = Layout()
            wire_no = 0
            for qreg in dag.qregs.values():
                for index in range(qreg.size):
                    self.layout[(qreg, index)] = wire_no
                    wire_no += 1

        for layer in dag.serial_layers():
            subdag = layer['graph']

            for cnot in subdag.get_cnot_nodes():

                control = cnot['op'].qargs[0]
                target = cnot['op'].qargs[1]

                physical_q0 = self.layout[control]
                physical_q1 = self.layout[target]
                if self.coupling_map.distance(physical_q0, physical_q1) != 1:
                    raise MapperError('The circuit requires a connectiontion between the phsycial '
                                      '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.add_basis_element('h', 1, 0, 0)
                    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['op'].qargs[0], cnot['op'].qargs[1] = target, control

            new_dag.extend_back(subdag)

        return new_dag
コード例 #4
0
    def test_copy(self):
        """Test copy methods return equivalent layouts."""
        layout = Layout()
        layout.add((self.qr, 0))
        layout.add((self.qr, 1))

        layout_dict_copy = layout.copy()
        self.assertTrue(isinstance(layout_dict_copy, Layout))
        self.assertDictEqual(layout, layout_dict_copy)

        layout_copy_copy = copy.copy(layout)
        self.assertTrue(isinstance(layout_copy_copy, Layout))
        self.assertDictEqual(layout, layout_copy_copy)

        layout_copy_deepcopy = copy.deepcopy(layout)
        self.assertTrue(isinstance(layout_copy_deepcopy, Layout))
        self.assertDictEqual(layout, layout_copy_deepcopy)
コード例 #5
0
 def create_passmanager(self, coupling_map, initial_layout=None):
     """Returns a PassManager using self.pass_class(coupling_map, initial_layout)"""
     passmanager = PassManager(
         self.pass_class(CouplingMap(coupling_map),  # pylint: disable=not-callable
                         **self.additional_args))
     if initial_layout:
         passmanager.property_set['layout'] = Layout(initial_layout)
     return passmanager
コード例 #6
0
    def test_layout_combine(self):
        """combine_into_edge_map() method"""
        layout = Layout()
        layout.add((self.qr, 0))
        layout.add((self.qr, 1))
        another_layout = Layout()
        another_layout.add((self.qr, 1))
        another_layout.add((self.qr, 0))

        edge_map = layout.combine_into_edge_map(another_layout)
        self.assertDictEqual(edge_map, {
            (self.qr, 0): (self.qr, 1),
            (self.qr, 1): (self.qr, 0)
        })
コード例 #7
0
 def test_layout_idle_physical_bits(self):
     """Get physical_bits that are not mapped"""
     layout = Layout()
     layout.add((self.qr, 1), 2)
     layout.add(None, 4)
     layout.add(None, 6)
     self.assertEqual(layout.idle_physical_bits(), [4, 6])
コード例 #8
0
 def test_layout_swap(self):
     """swap() method"""
     layout = Layout()
     layout.add((self.qr, 0))
     layout.add((self.qr, 1))
     layout.swap(0, 1)
     self.assertDictEqual(layout.get_virtual_bits(), {(self.qr, 0): 1, (self.qr, 1): 0})
コード例 #9
0
    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
コード例 #10
0
    def test_layout_error_when_same_type(self):
        """Layout does not work when key and value are the same type"""
        layout = Layout()

        with self.assertRaises(LayoutError):
            layout[(self.qr, 0)] = (self.qr, 1)

        with self.assertRaises(LayoutError):
            layout[0] = 1
コード例 #11
0
    def test_layout_error_str_key(self):
        """Layout does not work with strings"""
        layout = Layout()

        with self.assertRaises(LayoutError):
            layout['a_string'] = 3

        with self.assertRaises(LayoutError):
            layout[2] = 'a_string'
コード例 #12
0
    def run(self, dag):
        """
        Pick a convenient layout depending on the best matching
        qubit connectivity, and set the property `layout`.

        Args:
            dag (DAGCircuit): DAG to find layout for.

        Raises:
            TranspilerError: if dag wider than self.coupling_map
        """
        num_dag_qubits = sum([qreg.size for qreg in dag.qregs.values()])
        if num_dag_qubits > self.coupling_map.size():
            raise TranspilerError('Number of qubits greater than device.')
        layout = Layout()
        for qreg in dag.qregs.values():
            layout.add_register(qreg)
        self.property_set['layout'] = layout
コード例 #13
0
    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
コード例 #14
0
    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])
コード例 #15
0
ファイル: test_layout.py プロジェクト: CQCL/qiskit-terra
    def test_layout_from_dict(self):
        """Constructor from a dict"""
        layout = Layout({(self.qr, 0): 0, (self.qr, 1): 1, (self.qr, 2): 2})

        self.assertEqual(layout[(self.qr, 0)], 0)
        self.assertEqual(layout[(self.qr, 1)], 1)
        self.assertEqual(layout[(self.qr, 2)], 2)
        self.assertEqual(layout[0], (self.qr, 0))
        self.assertEqual(layout[1], (self.qr, 1))
        self.assertEqual(layout[2], (self.qr, 2))
コード例 #16
0
    def test_no_extension(self):
        """There are no idle physical bits to extend."""
        layout = Layout([(self.qr3, 0), (self.qr3, 1), (self.qr3, 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])
コード例 #17
0
    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))
        dag_circuit = circuit_to_dag(circ)
        layout = Layout.generate_trivial_layout(*circ.qregs)
        transpile_dag(dag_circuit, coupling_map=FakeRueschlikon().configuration().coupling_map,
                      initial_layout=layout)

        self.assertTrue(mock_pass.called)
コード例 #18
0
    def test_default_layout(self):
        """Static method generate_trivial_layout creates a Layout"""
        qr0 = QuantumRegister(3, 'q0')
        qr1 = QuantumRegister(2, 'q1')
        layout = Layout.generate_trivial_layout(qr0, qr1)

        self.assertEqual(layout[(qr0, 0)], 0)
        self.assertEqual(layout[(qr0, 1)], 1)
        self.assertEqual(layout[(qr0, 2)], 2)
        self.assertEqual(layout[(qr1, 0)], 3)
        self.assertEqual(layout[(qr1, 1)], 4)
コード例 #19
0
    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
コード例 #20
0
    def test_with_extension(self):
        """There are 2 idle physical bits to extend."""
        layout = Layout([(self.qr3, 0),
                         None,
                         (self.qr3, 1),
                         None,
                         (self.qr3, 2)])

        pass_ = EnlargeWithAncilla(layout)
        after = pass_.run(self.dag)

        final_layout = {0: (QuantumRegister(3, 'qr'), 0), 1: (QuantumRegister(2, 'ancilla'), 0),
                        2: (QuantumRegister(3, 'qr'), 1), 3: (QuantumRegister(2, 'ancilla'), 1),
                        4: (QuantumRegister(3, 'qr'), 2)}

        qregs = list(after.qregs.values())
        self.assertEqual(2, len(qregs))
        self.assertEqual(self.qr3, qregs[0])
        self.assertEqual(QuantumRegister(2, name='ancilla'), qregs[1])
        self.assertEqual(final_layout, layout.get_physical_bits())
コード例 #21
0
    def test_set_virtual_without_physical(self):
        """When adding a virtual without care in which physical is going"""
        layout = Layout()
        layout.add((self.qr, 1), 2)
        layout.add((self.qr, 0))

        self.assertDictEqual(layout.get_virtual_bits(), {
            (self.qr, 0): 1,
            (self.qr, 1): 2
        })
コード例 #22
0
 def test_layout_swap_error(self):
     """swap() method error"""
     layout = Layout()
     layout.add((self.qr, 0))
     layout.add((self.qr, 1))
     with self.assertRaises(LayoutError):
         layout.swap(0, (self.qr, 0))
コード例 #23
0
class CheckMap(AnalysisPass):
    """
    Checks if a DAGCircuit is mapped to `coupling_map`.
    """
    def __init__(self, coupling_map, initial_layout=None):
        """
        Checks if a DAGCircuit is mapped to `coupling_map`.
        Args:
            coupling_map (Coupling): Directed graph represented a coupling map.
            initial_layout (Layout): The initial layout of the DAG to analyze.
        """
        super().__init__()
        self.layout = initial_layout
        self.coupling_map = coupling_map

    def run(self, dag):
        """
        If `dag` is mapped to coupling_map, the property `is_mapped` is
        set to True (or to False otherwise).
        Args:
            dag (DAGCircuit): DAG to map.
        """
        if self.layout is None:
            self.layout = Layout()
            for qreg in dag.qregs.values():
                self.layout.add_register(qreg)

        self.property_set['is_mapped'] = None
        for layer in dag.serial_layers():
            subdag = layer['graph']

            for a_cx in subdag.get_cnot_nodes():
                q = QuantumRegister(self.coupling_map.node_counter, 'q')
                physical_q0 = (q, self.layout[a_cx['op'].qargs[0]])
                physical_q1 = (q, self.layout[a_cx['op'].qargs[1]])
                if self.coupling_map.distance(physical_q0, physical_q1) != 1:
                    self.property_set['is_mapped'] = False
                    return
        self.property_set['is_mapped'] = True
コード例 #24
0
 def test_layout_len(self):
     """Length of the layout is the amount of physical bits"""
     layout = Layout()
     self.assertEqual(len(layout), 0)
     layout.add((self.qr, 0))
     self.assertEqual(len(layout), 1)
     layout.add((self.qr, 1), 3)
     self.assertEqual(len(layout), 4)
コード例 #25
0
    def run(self, dag):
        """
        Pick a layout by assigning n circuit qubits to device qubits 0, .., n-1.

        Args:
            dag (DAGCircuit): DAG to find layout for.

        Raises:
            TranspilerError: if dag wider than self.coupling_map
        """
        num_dag_qubits = sum([qreg.size for qreg in dag.qregs.values()])
        if num_dag_qubits > self.coupling_map.size():
            raise TranspilerError('Number of qubits greater than device.')
        self.property_set['layout'] = Layout.generate_trivial_layout(*dag.qregs.values())
コード例 #26
0
    def run(self, dag):
        """
        If `dag` is mapped to coupling_map, the property `is_mapped` is
        set to True (or to False otherwise).
        Args:
            dag (DAGCircuit): DAG to map.
        """
        if self.layout is None:
            self.layout = Layout()
            for qreg in dag.qregs.values():
                self.layout.add_register(qreg)

        self.property_set['is_mapped'] = None
        for layer in dag.serial_layers():
            subdag = layer['graph']

            for a_cx in subdag.get_cnot_nodes():
                physical_q0 = ('q', self.layout[a_cx['op'].qargs[0]])
                physical_q1 = ('q', self.layout[a_cx['op'].qargs[1]])
                if self.coupling_map.distance(physical_q0, physical_q1) != 1:
                    self.property_set['is_mapped'] = False
                    return
        self.property_set['is_mapped'] = True
コード例 #27
0
    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 provided DAG has more qubits than are
                available in the coupling map.
        """

        coupling_map = self._coupling_map
        ordered_virtual_gates = list(dag.serial_layers())

        if len(dag.get_qubits()) > len(coupling_map.physical_qubits):
            raise TranspilerError('DAG contains more qubits than are '
                                  'present in the coupling map.')

        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())

        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 gate in mapped_gates:
            mapped_dag.apply_operation_back(**gate)

        return mapped_dag
コード例 #28
0
    def test_name_collision(self):
        """Name collision during ancilla extension."""
        qr_ancilla = QuantumRegister(3, 'ancilla')
        circuit = QuantumCircuit(qr_ancilla)
        circuit.h(qr_ancilla)
        dag = circuit_to_dag(circuit)

        layout = Layout([(qr_ancilla, 0), None, (qr_ancilla, 1), None,
                         (qr_ancilla, 2)])

        pass_ = EnlargeWithAncilla(layout)
        after = pass_.run(dag)

        qregs = list(after.qregs.values())
        self.assertEqual(2, len(qregs))
        self.assertEqual(qr_ancilla, qregs[0])
        self.assertEqual(2, qregs[1].size)
        self.assertRegex(qregs[1].name, r'^ancilla\d+$')
コード例 #29
0
    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))

        dag_circuit = circuit_to_dag(circ)
        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_dag = transpile_dag(dag_circuit, initial_layout=lay, coupling_map=cmap)
        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)
コード例 #30
0
 def run(self, dag):
     """Main run method for the noise adaptive layout."""
     self._initialize_backend_prop()
     num_qubits = self._create_program_graph(dag)
     if num_qubits > len(self.swap_graph):
         raise TranspilerError('Number of qubits greater than device.')
     for end1, end2, _ in sorted(self.prog_graph.edges(data=True),
                                 key=lambda x: x[2]['weight'],
                                 reverse=True):
         self.pending_program_edges.append((end1, end2))
     while self.pending_program_edges:
         edge = self._select_next_edge()
         q1_mapped = edge[0] in self.prog2hw
         q2_mapped = edge[1] in self.prog2hw
         if (not q1_mapped) and (not q2_mapped):
             best_hw_edge = self._select_best_remaining_cx()
             self.prog2hw[edge[0]] = best_hw_edge[0]
             self.prog2hw[edge[1]] = best_hw_edge[1]
             self.available_hw_qubits.remove(best_hw_edge[0])
             self.available_hw_qubits.remove(best_hw_edge[1])
         elif not q1_mapped:
             best_hw_qubit = self._select_best_remaining_qubit(edge[0])
             self.prog2hw[edge[0]] = best_hw_qubit
             self.available_hw_qubits.remove(best_hw_qubit)
         else:
             best_hw_qubit = self._select_best_remaining_qubit(edge[1])
             self.prog2hw[edge[1]] = best_hw_qubit
             self.available_hw_qubits.remove(best_hw_qubit)
         new_edges = [
             x for x in self.pending_program_edges
             if not (x[0] in self.prog2hw and x[1] in self.prog2hw)
         ]
         self.pending_program_edges = new_edges
     for qid in self.qarg_to_id.values():
         if qid not in self.prog2hw:
             self.prog2hw[qid] = self.available_hw_qubits[0]
             self.available_hw_qubits.remove(self.prog2hw[qid])
     layout = Layout()
     for q in dag.qubits():
         pid = self._qarg_to_id(q)
         hwid = self.prog2hw[pid]
         layout[(q[0], q[1])] = hwid
     self.property_set['layout'] = layout