Ejemplo n.º 1
0
 def decode(self, code, syndrome, **kwargs):
     """See :meth:`qecsim.model.Decoder.decode`"""
     # prepare recovery
     recovery_pauli = code.new_pauli()
     # ask code for plaquette_indices
     plaquette_indices = code.syndrome_to_plaquette_indices(syndrome)
     # for each lattice
     for lattice in (code.PRIMAL_INDEX, code.DUAL_INDEX):
         # prepare lattice graph
         l_graph = gt.SimpleGraph()
         # select lattice plaquettes
         l_plaquette_indices = [(la, r, c) for la, r, c in plaquette_indices
                                if la == lattice]
         # add weighted edges to lattice graph
         for a_index, b_index in itertools.combinations(
                 l_plaquette_indices, 2):
             # add edge with taxi-cab distance between a and b
             l_graph.add_edge(a_index, b_index,
                              self.distance(code, a_index, b_index))
         # find MWPM edges {(a, b), (c, d), ...}
         l_mates = gt.mwpm(l_graph)
         # iterate edges
         for a_index, b_index in l_mates:
             # add path to recover
             recovery_pauli.path(a_index, b_index)
     # return recover as bsf
     return recovery_pauli.to_bsf()
 def _matching(cls, graph):
     """Matching (minimum weight perfect matching) over graph.
     :param graph: Graph of weighted edges between nodes, as {(a_node, b_node): weight, ...}.
     :type graph: dict of (object, object) edges to float weights.
     :return: Matches between nodes as (a_node, b_node).
     :rtype: set of (object, object)
     """
     return gt.mwpm(graph)  # option to switch to networkx or blossom5 here
Ejemplo n.º 3
0
    def _matching(cls, graphs):
        """Combined matching (minimum weight perfect matching) over given graphs.

        :param graphs: List of graphs of weighted edges between nodes, as {(a_node, b_node): weight, ...}.
        :type graphs: list of dict of (object, object) edges to float weights.
        :return: Matches between nodes as (a_node, b_node).
        :rtype: set of (object, object)
        """
        matches = set()
        for graph in graphs:
            matches.update(gt.mwpm(graph))  # option to switch to networkx or blossom5 here
            del graph  # release heavy object
        return matches
Ejemplo n.º 4
0
 def decode(self, code, syndrome, **kwargs):
     """See :meth:`qecsim.model.Decoder.decode`"""
     # prepare recovery
     recovery_pauli = code.new_pauli()
     # get syndrome indices
     syndrome_indices = code.syndrome_to_plaquette_indices(syndrome)
     # split indices into primal and dual
     primal_indices = [i for i in syndrome_indices if code.is_primal(i)]
     dual_indices = [i for i in syndrome_indices if code.is_dual(i)]
     # extra virual indices are deliberately well off-boundary to be separate from nearest virtual indices
     primal_extra_vindex = (-9, -10)
     dual_extra_vindex = (-10, -9)
     # for each type of indices and extra virtual index
     for indices, extra_vindex in (primal_indices, primal_extra_vindex), (dual_indices, dual_extra_vindex):
         # prepare graph
         graph = gt.SimpleGraph()
         # prepare virtual nodes
         vindices = set()
         # add weighted edges between nodes and virtual nodes
         for index in indices:
             vindex = code.virtual_plaquette_index(index)
             vindices.add(vindex)
             distance = self.distance(code, index, vindex)
             graph.add_edge(index, vindex, distance)
         # add extra virtual node if odd number of total nodes
         if (len(indices) + len(vindices)) % 2:
             vindices.add(extra_vindex)
         # add weighted edges to graph between all (non-virtual) nodes
         for a_index, b_index in itertools.combinations(indices, 2):
             distance = self.distance(code, a_index, b_index)
             graph.add_edge(a_index, b_index, distance)
         # add zero weight edges between all virtual nodes
         for a_index, b_index in itertools.combinations(vindices, 2):
             graph.add_edge(a_index, b_index, 0)
         # find MWPM edges {(a, b), (c, d), ...}
         mates = gt.mwpm(graph)
         # iterate edges
         for a_index, b_index in mates:
             # add path to recover
             recovery_pauli.path(a_index, b_index)
     # return recover as bsf
     return recovery_pauli.to_bsf()
Ejemplo n.º 5
0
        def mwpm(self,
                 matched_indices,
                 syndrome_indices,
                 factor=3,
                 initial=1,
                 box_shape='t',
                 distance_algorithm=4):
            """
            Minimum-weight perfect matching of syndrome indices over a background of matched dual syndrome indices.

            Notes:

            * The background is set according to :meth:`set_background`.
            * A graph of the unmatched foreground indices is created, with appropriate virtual indices, and with edge
              weights given by :meth:`distance`.
            * A standard minimum-weight perfect matching is found in the graph.

            :param matched_indices: Matched pairs of background syndrome indices (dual to foreground).
            :type matched_indices: frozenset of 2-tuples of 2-tuple of int
            :param syndrome_indices: Unmatched foreground syndrome indices.
            :type syndrome_indices: frozenset of 2-tuple of int
            :param factor: Multiplication factor. (default=3)
            :type factor: int or float
            :param initial: Initial edge weight. (default=1)
            :type initial: int or float
            :param box_shape: Shape of background boxes. (default='t', 't'=tight, 'r'=rounded, 'f'=fitted, 'l'=loose)
            :type box_shape: str
            :param distance_algorithm: Distance algorithm. (default=4, 1=v+h, 2=min(v+h,h+v), 4=min(v+h,h+v,v+h+v,h+v+h)
            :type distance_algorithm: int
            :return: Minimum-weight perfect matching of foreground syndrome indices.
            :rtype: frozenset of 2-tuples of 2-tuple of int
            """
            # set grid background
            self.set_background(matched_indices,
                                factor=factor,
                                initial=initial,
                                box_shape=box_shape)
            # prepare graph
            graph = gt.SimpleGraph()
            # create lists of nodes and corresponding vnodes
            # NOTE: encapsulate indices in node objects that implement object reference equality since we may pass
            # multiple virtual plaquettes with the same index for matching.
            nodes, vnodes = [], []
            for index in syndrome_indices:
                nodes.append(self._Node(index))
                vnodes.append(
                    self._Node(self._code.virtual_plaquette_index(index)))
            # add weighted edges to graph
            for a_node, b_node in itertools.chain(
                    itertools.combinations(nodes, 2),  # all nodes to all nodes
                    itertools.combinations(vnodes,
                                           2),  # all vnodes to all vnodes
                    zip(nodes, vnodes)):  # each node to corresponding vnode
                # find weighted taxi-cab distance between a and b
                distance = self.distance(a_node.index,
                                         b_node.index,
                                         algorithm=distance_algorithm)
                # add edge with weight=distance
                graph.add_edge(a_node, b_node, distance)
            # find MWPM edges {(a, b), (c, d), ...}
            mates = gt.mwpm(graph)
            # convert to frozenset of sorted tuples {(a_index, b_index), ...}, removing matches if both indices virtual
            matches = frozenset(
                tuple(sorted((a.index, b.index))) for a, b in mates
                if self._code.is_in_bounds(a.index)
                or self._code.is_in_bounds(b.index))
            return matches
Ejemplo n.º 6
0
def test_mwpm():
    graph = {('b', 'c'): 10, ('b', 'd'): 25, ('a', 'c'): 56, ('a', 'b'): 15, ('c', 'd'): 6}
    mates = gt.mwpm(graph)
    sorted_mates = {tuple(sorted(match)) for match in mates}
    expected = {('a', 'b'), ('c', 'd')}
    assert sorted_mates == expected