Ejemplo n.º 1
0
    def test_min_maximal_matching_bug1(self):
        G = nx.Graph()
        G.add_nodes_from(range(7))
        G.add_edges_from([(0, 2), (0, 3), (0, 5), (0, 6), (1, 5), (2, 3),
                          (2, 4), (2, 5), (3, 4), (4, 6), (5, 6)])

        delta = max(G.degree(node) for node in G)  # maximum degree
        A = 1  # magnitude arg for _matching_qubo
        B = .75 * A / (delta - 2.)  # magnitude arg for _maximal_matching_qubo
        C = .5 * B

        edge_mapping = _edge_mapping(G)
        inv_edge_mapping = {idx: edge for edge, idx in edge_mapping.items()}

        Qmm = _maximal_matching_qubo(G, edge_mapping, magnitude=B)
        Qm = _matching_qubo(G, edge_mapping, magnitude=A)
        Qmmm = {(v, v): C for v in edge_mapping.values()}
        Q = Qmm.copy()
        for edge, bias in Qm.items():
            Q[edge] += bias
        for edge, bias in Qmmm.items():
            Q[edge] += bias

        # now for each combination of edges, we check that if the combination
        # is a maximal matching, and if so that is has ground energy, else
        # there is an infeasible gap
        ground_energy = -1. * B * len(G.edges())  # from maximal matching
        infeasible_gap = float('inf')
        for edge_vars in powerset(set(edge_mapping.values())):

            # get the matching from the variables
            potential_matching = {inv_edge_mapping[v] for v in edge_vars}

            # get the sample from the edge_vars
            sample = {v: 0 for v in edge_mapping.values()}
            for v in edge_vars:
                sample[v] = 1

            en_matching = qubo_energy(Qm, sample)
            en_maximal = qubo_energy(Qmm, sample)
            en_minimal = qubo_energy(Qmmm, sample)

            en = qubo_energy(Q, sample)

            self.assertLess(abs(en_matching + en_maximal + en_minimal - en),
                            10**-8)

            if dnx.is_maximal_matching(G, potential_matching):
                # if the sample is a maximal matching, then let's check each qubo
                # and combined together
                self.assertEqual(en_matching, 0.0)  # matching
                self.assertLess(abs(en_maximal - ground_energy), 10**-8)

            elif dnx.is_matching(potential_matching):
                # in this case we expect the energy contribution of Qm to be 0
                self.assertEqual(en_matching, 0.0)  # matching

                # but there should be a gap to Qmm, because the matching is not maximal
                self.assertGreater(en_maximal, ground_energy)

                gap = en_matching + en_maximal + en_minimal - ground_energy
                if gap < infeasible_gap:
                    infeasible_gap = gap
            else:
                # ok, these are not even matching
                self.assertGreater(en_matching,
                                   0)  # so matching energy should be > 0

                self.assertGreater(gap, 0)

                gap = en_matching + en_maximal + en_minimal - ground_energy
                if gap < infeasible_gap:
                    infeasible_gap = gap

        self.assertGreater(infeasible_gap, 0)

        # finally let's test it using the function
        matching = dnx.min_maximal_matching(G, ExactSolver())
        self.assertTrue(dnx.is_maximal_matching(G, matching))
Ejemplo n.º 2
0
    def test_maximal_matching_combined_qubo_bug1(self):

        # a graph that was not working
        G = nx.Graph()
        G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7])
        G.add_edges_from([(0, 1), (0, 3), (1, 3), (1, 4), (1, 6), (1, 7),
                          (2, 3), (2, 5), (2, 7), (3, 5), (3, 6), (4, 5),
                          (4, 6), (4, 7), (5, 7)])
        delta = max(G.degree(node) for node in G)  # maximum degree
        A = 1  # magnitude arg for _matching_qubo
        B = .95 * A / (delta - 2.)  # magnitude arg for _maximal_matching_qubo

        edge_mapping = _edge_mapping(G)
        inv_edge_mapping = {idx: edge for edge, idx in edge_mapping.items()}

        Qmm = _maximal_matching_qubo(G, edge_mapping,
                                     magnitude=B)  # Q is a defaultdict
        Qm = _matching_qubo(G, edge_mapping, magnitude=A)
        Q = Qmm.copy()
        for edge, bias in Qm.items():
            Q[edge] += bias
        Q = dict(
            Q
        )  # we are not necessarily sure that the given sampler can handle a defaultdict
        Qmm = dict(Qmm)

        # now for each combination of edges, we check that if the combination
        # is a maximal matching, and if so that is has ground energy, else
        # there is an infeasible gap
        ground_energy = -1. * B * len(G.edges())  # from maximal matching
        infeasible_gap = float('inf')
        for edge_vars in powerset(set(edge_mapping.values())):

            # get the matching from the variables
            potential_matching = {inv_edge_mapping[v] for v in edge_vars}

            # get the sample from the edge_vars
            sample = {v: 0 for v in edge_mapping.values()}
            for v in edge_vars:
                sample[v] = 1

            en_matching = qubo_energy(Qm, sample)
            en_maximal = qubo_energy(Qmm, sample)
            en = qubo_energy(Q, sample)

            self.assertLess(abs(en_matching + en_maximal - en), 10**-8)

            if dnx.is_maximal_matching(G, potential_matching):
                # if the sample is a maximal matching, then let's check each qubo
                # and combined together
                self.assertEqual(en_matching, 0.0)  # matching
                self.assertLess(abs(en_maximal - ground_energy), 10**-8)

            elif dnx.is_matching(potential_matching):
                # in this case we expect the energy contribution of Qm to be 0
                self.assertEqual(en_matching, 0.0)  # matching

                # but there should be a gap to Qmm, because the matching is not maximal
                self.assertGreater(en_maximal, ground_energy)

                gap = en_matching + en_maximal - ground_energy
                if gap < infeasible_gap:
                    infeasible_gap = gap
            else:
                # ok, these are not even matching
                self.assertGreater(en_matching,
                                   0)  # so matching energy should be > 0

                self.assertGreater(gap, 0)

                gap = en_matching + en_maximal - ground_energy
                if gap < infeasible_gap:
                    infeasible_gap = gap

        self.assertGreater(infeasible_gap, 0)