Beispiel #1
0
    def run(self, dag):
        """Run the SabreLayout pass on `dag`.

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

        Raises:
            TranspilerError: if dag wider than self.coupling_map
        """
        if len(dag.qubits) > self.coupling_map.size():
            raise TranspilerError("More virtual qubits exist than physical.")

        # Choose a random initial_layout.
        if self.seed is None:
            self.seed = np.random.randint(0, np.iinfo(np.int32).max)
        rng = np.random.default_rng(self.seed)

        physical_qubits = rng.choice(self.coupling_map.size(),
                                     len(dag.qubits),
                                     replace=False)
        physical_qubits = rng.permutation(physical_qubits)
        initial_layout = Layout(
            {q: dag.qubits[i]
             for i, q in enumerate(physical_qubits)})

        if self.routing_pass is None:
            self.routing_pass = SabreSwap(self.coupling_map,
                                          "decay",
                                          seed=self.seed,
                                          fake_run=True)
        else:
            self.routing_pass.fake_run = True

        # Do forward-backward iterations.
        circ = dag_to_circuit(dag)
        rev_circ = circ.reverse_ops()
        for _ in range(self.max_iterations):
            for _ in ("forward", "backward"):
                pm = self._layout_and_route_passmanager(initial_layout)
                new_circ = pm.run(circ)

                # Update initial layout and reverse the unmapped circuit.
                pass_final_layout = pm.property_set["final_layout"]
                final_layout = self._compose_layouts(
                    initial_layout,
                    pass_final_layout,
                    new_circ.qregs  # pylint: disable=no-member
                )
                initial_layout = final_layout
                circ, rev_circ = rev_circ, circ

            # Diagnostics
            logger.info("new initial layout")
            logger.info(initial_layout)

        for qreg in dag.qregs.values():
            initial_layout.add_register(qreg)

        self.property_set["layout"] = initial_layout
        self.routing_pass.fake_run = False
Beispiel #2
0
    def test_layout_add_register(self):
        """add_register() method"""
        layout = Layout()
        layout.add_register(QuantumRegister(2, 'q0'))
        layout.add_register(QuantumRegister(1, 'qr1'))

        self.assertEqual(layout[(QuantumRegister(2, 'q0'), 0)], 0)
        self.assertEqual(layout[(QuantumRegister(2, 'q0'), 1)], 1)
        self.assertEqual(layout[(QuantumRegister(1, 'qr1'), 0)], 2)
Beispiel #3
0
    def run(self, dag):
        """Run the SabreLayout pass on `dag`.

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

        Raises:
            TranspilerError: if dag wider than self.coupling_map
        """
        if len(dag.qubits) > self.coupling_map.size():
            raise TranspilerError('More virtual qubits exist than physical.')

        # Choose a random initial_layout.
        if self.seed is None:
            self.seed = np.random.randint(0, np.iinfo(np.int32).max)
        rng = np.random.default_rng(self.seed)

        physical_qubits = rng.choice(self.coupling_map.size(),
                                     len(dag.qubits),
                                     replace=False)
        physical_qubits = rng.permutation(physical_qubits)
        initial_layout = Layout(
            {q: dag.qubits[i]
             for i, q in enumerate(physical_qubits)})

        if self.routing_pass is None:
            self.routing_pass = SabreSwap(self.coupling_map,
                                          'decay',
                                          seed=self.seed)

        # Do forward-backward iterations.
        circ = dag_to_circuit(dag)
        for i in range(self.max_iterations):
            for _ in ('forward', 'backward'):
                pm = self._layout_and_route_passmanager(initial_layout)
                new_circ = pm.run(circ)

                # Update initial layout and reverse the unmapped circuit.
                pass_final_layout = pm.property_set['final_layout']
                final_layout = self._compose_layouts(initial_layout,
                                                     pass_final_layout,
                                                     new_circ.qregs)  # pylint: disable=no-member
                initial_layout = final_layout
                circ = circ.reverse_ops()

            # Diagnostics
            logger.info('After round %d, num_swaps: %d', i + 1,
                        new_circ.count_ops().get('swap', 0))  # pylint: disable=no-member

            logger.info('new initial layout')
            logger.info(initial_layout)

        for qreg in dag.qregs.values():
            initial_layout.add_register(qreg)

        self.property_set['layout'] = initial_layout
Beispiel #4
0
    def test_layout_add_register(self):
        """add_register() method"""
        layout = Layout()
        qr0 = QuantumRegister(2, 'q0')
        qr1 = QuantumRegister(1, 'qr1')
        layout.add_register(qr0)
        layout.add_register(qr1)

        self.assertEqual(layout[qr0[0]], 0)
        self.assertEqual(layout[qr0[1]], 1)
        self.assertEqual(layout[qr1[0]], 2)
    def test_layout_add_register(self):
        """add_register() method"""
        layout = Layout()
        qr0 = QuantumRegister(2, "q0")
        qr1 = QuantumRegister(1, "qr1")
        layout.add_register(qr0)
        layout.add_register(qr1)

        self.assertEqual(layout[qr0[0]], 0)
        self.assertEqual(layout[qr0[1]], 1)
        self.assertEqual(layout[qr1[0]], 2)
        self.assertIn(qr0, layout.get_registers())
        self.assertIn(qr1, layout.get_registers())
Beispiel #6
0
    def get_layout(self, t: int) -> Layout:
        """Get layout at time-step t.

        Args:
            t: Time-step

        Returns:
            Layout
        """
        dic = {}
        for q in range(self.num_vqubits):
            for i in range(self.num_pqubits):
                if self.solution.get_value(f"w_{t}_{q}_{i}") > 0.5:
                    dic[self._index_to_virtual[q]] = self.global_qubit[i]
        layout = Layout(dic)
        for reg in self._dag.qregs.values():
            layout.add_register(reg)
        return layout
    def run(self, dag):
        """Run the DenseLayout pass on `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
        """
        if self.coupling_map is None:
            raise TranspilerError(
                "A coupling_map or target with constrained qargs is necessary to run the pass."
            )
        num_dag_qubits = len(dag.qubits)
        if num_dag_qubits > self.coupling_map.size():
            raise TranspilerError("Number of qubits greater than device.")
        num_cx = 0
        num_meas = 0

        if self.target is not None:
            num_cx = 1
            num_meas = 1
        else:
            # Get avg number of cx and meas per qubit
            ops = dag.count_ops()
            if "cx" in ops.keys():
                num_cx = ops["cx"]
            if "measure" in ops.keys():
                num_meas = ops["measure"]

        best_sub = self._best_subset(num_dag_qubits, num_meas, num_cx)
        layout = Layout()
        map_iter = 0
        for qreg in dag.qregs.values():
            for i in range(qreg.size):
                layout[qreg[i]] = int(best_sub[map_iter])
                map_iter += 1
            layout.add_register(qreg)
        self.property_set["layout"] = layout
Beispiel #8
0
    def run(self, dag):
        """Run the DenseLayout pass on `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.")

        # Get avg number of cx and meas per qubit
        ops = dag.count_ops()
        if "cx" in ops.keys():
            self.num_cx = ops["cx"]
        if "measure" in ops.keys():
            self.num_meas = ops["measure"]

        # Compute the sparse cx_err matrix and meas array
        device_qubits = self.coupling_map.size()
        if self.backend_prop:
            rows = []
            cols = []
            cx_err = []

            for edge in self.coupling_map.get_edges():
                for gate in self.backend_prop.gates:
                    if gate.qubits == edge:
                        rows.append(edge[0])
                        cols.append(edge[1])
                        cx_err.append(gate.parameters[0].value)
                        break
                else:
                    continue

            self.cx_mat = sp.coo_matrix(
                (cx_err, (rows, cols)), shape=(device_qubits, device_qubits)
            ).tocsr()

            # Set measurement array
            meas_err = []
            for qubit_data in self.backend_prop.qubits:
                for item in qubit_data:
                    if item.name == "readout_error":
                        meas_err.append(item.value)
                        break
                else:
                    continue
            self.meas_arr = np.asarray(meas_err)

        best_sub = self._best_subset(num_dag_qubits)
        layout = Layout()
        map_iter = 0
        for qreg in dag.qregs.values():
            for i in range(qreg.size):
                layout[qreg[i]] = int(best_sub[map_iter])
                map_iter += 1
            layout.add_register(qreg)
        self.property_set["layout"] = layout
Beispiel #9
0
    def run(self, dag):
        """Run the ApplyLayout pass on `dag`.

        Args:
            dag (DAGCircuit): DAG to map.

        Returns:
            DAGCircuit: A mapped DAG (with physical qubits).

        Raises:
            TranspilerError: if no layout is found in `property_set` or no full physical qubits.
        """
        layout = self.property_set["layout"]
        if not layout:
            raise TranspilerError(
                "No 'layout' is found in property_set. Please run a Layout pass in advance."
            )
        if len(layout) != (1 + max(layout.get_physical_bits())):
            raise TranspilerError("The 'layout' must be full (with ancilla).")

        post_layout = self.property_set["post_layout"]

        q = QuantumRegister(len(layout), "q")

        new_dag = DAGCircuit()
        new_dag.add_qreg(q)
        new_dag.metadata = dag.metadata
        new_dag.add_clbits(dag.clbits)
        for creg in dag.cregs.values():
            new_dag.add_creg(creg)
        if post_layout is None:
            for qreg in dag.qregs.values():
                self.property_set["layout"].add_register(qreg)
            virtual_phsyical_map = layout.get_virtual_bits()
            for node in dag.topological_op_nodes():
                qargs = [q[virtual_phsyical_map[qarg]] for qarg in node.qargs]
                new_dag.apply_operation_back(node.op, qargs, node.cargs)
        else:
            # First build a new layout object going from:
            # old virtual -> old phsyical -> new virtual -> new physical
            # to:
            # old virtual -> new physical
            full_layout = Layout()
            old_phys_to_virtual = layout.get_physical_bits()
            new_virtual_to_physical = post_layout.get_virtual_bits()
            qubit_index_map = {
                bit: index
                for index, bit in enumerate(dag.qubits)
            }
            for new_virt, new_phys in new_virtual_to_physical.items():
                old_phys = qubit_index_map[new_virt]
                old_virt = old_phys_to_virtual[old_phys]
                full_layout.add(old_virt, new_phys)
            for reg in layout.get_registers():
                full_layout.add_register(reg)
            # Apply new layout to the circuit
            for node in dag.topological_op_nodes():
                qargs = [
                    q[new_virtual_to_physical[qarg]] for qarg in node.qargs
                ]
                new_dag.apply_operation_back(node.op, qargs, node.cargs)
            self.property_set["layout"] = full_layout
        new_dag._global_phase = dag._global_phase

        return new_dag
Beispiel #10
0
    def run(self, dag):
        """Run the NoiseAdaptiveLayout pass on `dag`."""
        self.swap_graph = rx.PyDiGraph()
        self.cx_reliability = {}
        self.readout_reliability = {}
        self.available_hw_qubits = []
        self.gate_list = []
        self.gate_reliability = {}
        self.swap_reliabs = {}
        self.prog_graph = rx.PyGraph()
        self.prog_neighbors = {}
        self.qarg_to_id = {}
        self.pending_program_edges = []
        self.prog2hw = {}

        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.')

        # sort by weight, then edge name for determinism (since networkx on python 3.5 returns
        # different order of edges)
        self.pending_program_edges = sorted(self.prog_graph.weighted_edge_list(),
                                            key=lambda x: [x[2], -x[0], -x[1]],
                                            reverse=True)

        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()
                if best_hw_edge is None:
                    raise TranspilerError("CNOT({}, {}) could not be placed "
                                          "in selected device.".format(edge[0], edge[1]))
                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])
                if best_hw_qubit is None:
                    raise TranspilerError(
                        "CNOT({}, {}) could not be placed in selected device. "
                        "No qubit near qr[{}] available".format(edge[0], edge[1], 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])
                if best_hw_qubit is None:
                    raise TranspilerError(
                        "CNOT({}, {}) could not be placed in selected device. "
                        "No qubit near qr[{}] available".format(edge[0], edge[1], 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] = hwid
        for qreg in dag.qregs.values():
            layout.add_register(qreg)
        self.property_set['layout'] = layout