示例#1
0
    def add_physical_qubit(self, physical_qubit):
        """Add a physical qubit to the coupling graph as a node.

        physical_qubit (int): An integer representing a physical qubit.

        Raises:
            CouplingError: if trying to add duplicate qubit
        """
        if not isinstance(physical_qubit, int):
            raise CouplingError("Physical qubits should be integers.")
        if physical_qubit in self.physical_qubits:
            raise CouplingError(
                "The physical qubit %s is already in the coupling graph" % physical_qubit)
        self.graph.add_node(physical_qubit)
        self._dist_matrix = None  # invalidate
        self._qubit_list = None  # invalidate
示例#2
0
    def _compute_distance_matrix(self):
        """Compute the full distance matrix on pairs of nodes.

        The distance map self._dist_matrix is computed from the graph using
        all_pairs_shortest_path_length.
        """
        if not self.is_connected():
            raise CouplingError("coupling graph not connected")
        self._dist_matrix = rx.digraph_distance_matrix(self.graph, as_undirected=True)
示例#3
0
    def distance(self, physical_qubit1, physical_qubit2):
        """Returns the undirected distance between physical_qubit1 and physical_qubit2.

        Args:
            physical_qubit1 (int): A physical qubit
            physical_qubit2 (int): Another physical qubit

        Returns:
            int: The undirected distance

        Raises:
            CouplingError: if the qubits do not exist in the CouplingMap
        """
        if physical_qubit1 >= self.size():
            raise CouplingError("%s not in coupling graph" % physical_qubit1)
        if physical_qubit2 >= self.size():
            raise CouplingError("%s not in coupling graph" % physical_qubit2)
        self.compute_distance_matrix()
        return int(self._dist_matrix[physical_qubit1, physical_qubit2])
示例#4
0
    def distance(self, physical_qubit1, physical_qubit2):
        """Returns the undirected distance between physical_qubit1 and physical_qubit2.

        Args:
            physical_qubit1 (int): A physical qubit
            physical_qubit2 (int): Another physical qubit

        Returns:
            int: The undirected distance

        Raises:
            CouplingError: if the qubits do not exist in the CouplingMap
        """
        if physical_qubit1 not in self.physical_qubits:
            raise CouplingError("%s not in coupling graph" % (physical_qubit1,))
        if physical_qubit2 not in self.physical_qubits:
            raise CouplingError("%s not in coupling graph" % (physical_qubit2,))
        if self._dist_matrix is None:
            self._compute_distance_matrix()
        return self._dist_matrix[physical_qubit1, physical_qubit2]
示例#5
0
    def compute_distance_matrix(self):
        """Compute the full distance matrix on pairs of nodes.

        The distance map self._dist_matrix is computed from the graph using
        all_pairs_shortest_path_length. This is normally handled internally
        by the :attr:`~qiskit.transpiler.CouplingMap.distance_matrix`
        attribute or the :meth:`~qiskit.transpiler.CouplingMap.distance` method
        but can be called if you're accessing the distance matrix outside of
        those or want to pre-generate it.
        """
        if self._dist_matrix is None:
            if not self.is_connected():
                raise CouplingError("coupling graph not connected")
            self._dist_matrix = rx.digraph_distance_matrix(self.graph,
                                                           as_undirected=True)
示例#6
0
    def _compute_distance_matrix(self):
        """Compute the full distance matrix on pairs of nodes.

        The distance map self._dist_matrix is computed from the graph using
        all_pairs_shortest_path_length.
        """
        if not self.is_connected():
            raise CouplingError("coupling graph not connected")
        lengths = nx.all_pairs_shortest_path_length(self.graph.to_undirected(as_view=True))
        lengths = dict(lengths)
        size = len(lengths)
        cmap = np.zeros((size, size))
        for idx in range(size):
            cmap[idx, np.fromiter(lengths[idx].keys(), dtype=int)] = np.fromiter(
                lengths[idx].values(), dtype=int)
        self._dist_matrix = cmap
示例#7
0
 def shortest_undirected_path(self, physical_qubit1, physical_qubit2):
     """Returns the shortest undirected path between physical_qubit1 and physical_qubit2.
     Args:
         physical_qubit1 (int): A physical qubit
         physical_qubit2 (int): Another physical qubit
     Returns:
         List: The shortest undirected path
     Raises:
         CouplingError: When there is no path between physical_qubit1, physical_qubit2.
     """
     try:
         return nx.shortest_path(self.graph.to_undirected(as_view=True), source=physical_qubit1,
                                 target=physical_qubit2)
     except nx.exception.NetworkXNoPath:
         raise CouplingError(
             "Nodes %s and %s are not connected" % (str(physical_qubit1), str(physical_qubit2)))
    def shortest_undirected_path(self, physical_qubit1, physical_qubit2):
        """Returns the shortest undirected path between physical_qubit1 and physical_qubit2.

        Args:
            physical_qubit1 (int): A physical qubit
            physical_qubit2 (int): Another physical qubit
        Returns:
            List: The shortest undirected path
        Raises:
            CouplingError: When there is no path between physical_qubit1, physical_qubit2.
        """
        paths = rx.digraph_dijkstra_shortest_paths(self.graph,
                                                   source=physical_qubit1,
                                                   target=physical_qubit2,
                                                   as_undirected=True)
        if not paths:
            raise CouplingError("Nodes %s and %s are not connected" %
                                (str(physical_qubit1), str(physical_qubit2)))
        return paths[physical_qubit2]
示例#9
0
    def reduce(self, mapping):
        """Returns a reduced coupling map that
        corresponds to the subgraph of qubits
        selected in the mapping.

        Args:
            mapping (list): A mapping of reduced qubits to device
                            qubits.

        Returns:
            CouplingMap: A reduced coupling_map for the selected qubits.

        Raises:
            CouplingError: Reduced coupling map must be connected.
        """
        from scipy.sparse import coo_matrix, csgraph

        reduced_qubits = len(mapping)
        inv_map = [None] * (max(mapping) + 1)
        for idx, val in enumerate(mapping):
            inv_map[val] = idx

        reduced_cmap = []

        for edge in self.get_edges():
            if edge[0] in mapping and edge[1] in mapping:
                reduced_cmap.append([inv_map[edge[0]], inv_map[edge[1]]])

        # Verify coupling_map is connected
        rows = np.array([edge[0] for edge in reduced_cmap], dtype=int)
        cols = np.array([edge[1] for edge in reduced_cmap], dtype=int)
        data = np.ones_like(rows)

        mat = coo_matrix((data, (rows, cols)),
                         shape=(reduced_qubits, reduced_qubits)).tocsr()

        if csgraph.connected_components(mat)[0] != 1:
            raise CouplingError("coupling_map must be connected.")

        return CouplingMap(reduced_cmap)