Example #1
0
    def test_as_spin(self):
        # add_sample with no energy specified, but Q given

        Q = {(0, 0): -1, (0, 1): 1, (1, 1): -1}

        sample0 = {0: 0, 1: 1}
        sample1 = {0: 1, 1: 1}
        sample2 = {0: 0, 1: 0}

        h, J, offset = qubo_to_ising(Q)

        response = self.response_factory()
        response.add_samples_from([sample0, sample1, sample2], [
            qubo_energy(Q, sample0),
            qubo_energy(Q, sample1),
            qubo_energy(Q, sample2)
        ])

        response.add_sample(sample0, qubo_energy(Q, sample0))

        spin_response = response.as_spin(-1 * offset)

        for sample, energy in spin_response.items():
            self.assertEqual(ising_energy(h, J, sample), energy)

        spin_response = response.as_spin(-1 * offset, data_copy=True)
        data_ids = {id(data) for __, data in response.samples(data=True)}
        for __, data in spin_response.samples(data=True):
            self.assertNotIn(id(data), data_ids)
Example #2
0
    def test_path3_weighted(self):
        G = nx.path_graph(3)
        G.nodes[1]['weight'] = 2.1

        Q = indep.maximum_weighted_independent_set_qubo(G, weight='weight')

        self.assertLess(dimod.qubo_energy({0: 0, 1: 1, 2: 0}, Q),
                        dimod.qubo_energy({0: 1, 1: 0, 2: 1}, Q))
Example #3
0
    def test_all_samples(self):
        """Check that every sample is included and has the correct energy."""

        n = 4

        # create a qubo
        Q = {(v, v): (v % 3) for v in range(n)}
        Q[(0, n - 1)] = 1.3
        Q[(3, n - 2)] = -.26666666

        response = self.sampler.sample_qubo(Q)

        # print(response)

        self.assertEqual(len(response), 2**n,
                         "incorrect number of samples returned")

        sample_tuples = set()
        for sample in response.samples():
            stpl = tuple(sample[v] for v in range(n))
            sample_tuples.add(stpl)

        for tpl in itertools.product((0, 1), repeat=n):
            self.assertIn(tpl, sample_tuples)

        # let's also double check the energy
        for sample, energy in response.data(['sample', 'energy']):
            self.assertAlmostEqual(energy, dimod.qubo_energy(sample, Q))
Example #4
0
 def sample_qubo(self, Q, **kwargs):
     for key in kwargs:
         if key not in self.properties['parameters']:
             raise ValueError
     result = {
         'num_variables': 2048,
         'format': 'qp',
         'num_occurrences': [1],
         'active_variables': list(range(2048)),
         'solutions': [[random.choice((0, 1)) for __ in range(2048)]],
         'timing': {
             'total_real_time': 11511,
             'anneal_time_per_run': 20,
             'post_processing_overhead_time': 2042,
             'qpu_sampling_time': 164,
             'readout_time_per_run': 123,
             'qpu_delay_time_per_sample': 21,
             'qpu_anneal_time_per_sample': 20,
             'total_post_processing_time': 2042,
             'qpu_programming_time': 8740,
             'run_time_chip': 164,
             'qpu_access_time': 11511,
             'qpu_readout_time_per_sample': 123
         },
         'occurrences': [1]
     }
     result['samples'] = result['solutions']
     result['energies'] = [
         dimod.qubo_energy(sample, Q) for sample in result['samples']
     ]
     future = Future()
     future.set_result(result)
     return future
Example #5
0
    def test_all_samples(self):
        """Check that every sample is included and that they all have the correct energy."""

        n = 10

        # create a qubo
        Q = {(v, v): (v % 3) for v in range(n)}
        Q[(0, n - 1)] = 1.3
        Q[(3, n - 2)] = -.26666666

        response = self.sampler.sample_qubo(Q)

        self.assertEqual(len(response), 2**n,
                         "incorrect number of samples returned")

        sample_tuples = set()
        for sample in response.samples():
            stpl = tuple(sample[v] for v in range(n))
            sample_tuples.add(stpl)

        for tpl in itertools.product((0, 1), repeat=n):
            self.assertIn(tpl, sample_tuples)

        # let's also double check the enegy
        for sample, energy in response.items():
            self.assertTrue(abs(energy - qubo_energy(Q, sample)) < .000001)
Example #6
0
    def test_as_binary(self):

        h = {0: 0, 1: 0}
        J = {(0, 1): 1}

        sample0 = {0: -1, 1: 1}
        sample1 = {0: 1, 1: -1}
        sample2 = {0: 1, 1: 1}

        Q, offset = ising_to_qubo(h, J)

        response = self.response_factory()
        response.add_samples_from([sample0, sample1, sample2], [
            ising_energy(h, J, sample0),
            ising_energy(h, J, sample1),
            ising_energy(h, J, sample2)
        ])

        bin_response = response.as_binary(-1 * offset)
        for sample, energy in bin_response.items():
            self.assertEqual(qubo_energy(Q, sample), energy)

        bin_response = response.as_binary(-1 * offset, data_copy=True)
        data_ids = {id(data) for __, data in response.samples(data=True)}
        for __, data in bin_response.samples(data=True):
            self.assertNotIn(id(data), data_ids)
Example #7
0
    def test_basic(self):

        sampler = self.sampler

        h = {0: -.5, 1: 0, 2: 1, 3: -.5}
        J = {(0, 2): -1, (1, 2): -1, (0, 3): .5, (1, 3): -1}

        response0 = sampler.sample_ising(h, J, num_samples=10)

        for sample, energy in response0.items():
            self.assertEqual(ising_energy(h, J, sample), energy)

        # make sure we actully got back 100 samples
        self.assertEqual(len(response0), 10)

        response2 = sampler.sample_structured_ising(h, J, num_samples=10)
        self.assertEqual(len(response2), 10)

        for sample, energy in response2.items():
            self.assertEqual(ising_energy(h, J, sample), energy)

        Q = {(0, 0): 0, (1, 1): 0, (0, 1): -1}

        response4 = sampler.sample_qubo(Q, num_samples=10)
        self.assertEqual(len(response4), 10)

        for sample, energy in response4.items():
            self.assertEqual(qubo_energy(Q, sample), energy)

        response6 = sampler.sample_structured_qubo(Q, num_samples=10)
        self.assertEqual(len(response6), 10)
Example #8
0
def test_sample_qubo(self, sampler, Q):
    sampleset = sampler.sample_qubo(Q)

    self.assertEqual(set(sampleset.variables), set().union(*Q))
    self.assertIs(sampleset.vartype, dimod.BINARY)

    for sample, en in sampleset.data(['sample', 'energy']):
        self.assertAlmostEqual(dimod.qubo_energy(sample, Q), en)
    def check_binary_response(self, response, Q):
        variables = set().union(*Q)

        for sample, energy in response.items():
            for v in variables:
                self.assertIn(v, sample)
            self.assertLessEqual(abs(dimod.qubo_energy(Q, sample) - energy),
                                 10**-5)
Example #10
0
    def test_typical(self):
        # AND gate
        h = {0: -.5, 1: 0, 2: 1, 3: -.5}
        J = {(0, 2): -1, (1, 2): -1, (0, 3): .5, (1, 3): -1}
        Q, __ = ising_to_qubo(h, J)

        en0 = min(qubo_energy({
            0: 0,
            1: 0,
            2: 0,
            3: 0
        }, Q), qubo_energy({
            0: 0,
            1: 0,
            2: 0,
            3: 1
        }, Q))
        en1 = min(qubo_energy({
            0: 1,
            1: 0,
            2: 0,
            3: 0
        }, Q), qubo_energy({
            0: 1,
            1: 0,
            2: 0,
            3: 1
        }, Q))
        en2 = min(qubo_energy({
            0: 0,
            1: 1,
            2: 0,
            3: 0
        }, Q), qubo_energy({
            0: 0,
            1: 1,
            2: 0,
            3: 1
        }, Q))
        en3 = min(qubo_energy({
            0: 1,
            1: 1,
            2: 1,
            3: 0
        }, Q), qubo_energy({
            0: 1,
            1: 1,
            2: 1,
            3: 1
        }, Q))

        self.assertEqual(en0, en1)
        self.assertEqual(en0, en2)
        self.assertEqual(en0, en3)
Example #11
0
    def add_sample(self, sample, energy=None, data={}, Q=None):
        """Loads a sample and associated energy into the response.

        Args:
            sample (dict): A sample as would be returned by a discrete
                model solver. Should be a dict of the form
                {var: value, ...}. The values should be spin-valued, that is
                -1 or 1.
            energy (float/int, optional): The energy associated with the
                given sample.
            data (dict, optional): A dict containing any additional
                data about the sample. Default empty.
            Q (dict): Defines a Quadratic Unconstrained Binary
                Optimization problem that can be used to calculate the energy
                associated with `sample`.

        Notes:
            Solutions are stored in order of energy, lowest first.

        Raises:
            TypeError: If `sample` is not a dict.
            TypeError: If `energy` is not an int or float.
            TypeError: If `data` is not a dict.
            ValueError: If any of the values in `sample` are not -1
            or 1.
            TypeError: If energy is not provided, Q must be.

        Examples:
            >>> sample = {0: 1, 1: 0, 2: 0}
            >>> energy = -1
            >>> response = BinaryResponse()
            >>> response.add_sample(sample, energy)
            >>> list(response.samples())
            [{0: 1, 1: 0, 2: 0}]
            >>> response.add_sample(sample, Q={(0, 0): -1, (1, 1): 0, (2, 2): 0})
            >>> list(response.items())
            [({0: 1, 1: 0, 2: 0}, -1), ({0: 1, 1: 0, 2: 0}, -1)]
            >>> response.add_sample(sample, data={'n': 10},
                                    Q={(0, 0): -1, (1, 1): 0, (2, 2): 0})

        """
        # check that the sample is sp]n-valued
        if any(val not in (0, 1) for val in itervalues(sample)):
            raise ValueError(
                'given sample is not binary. Values should be 0 or 1')

        # if energy is not provided, but Q is, then we can calculate
        # the energy for the sample.
        if energy is None:
            if Q is None:
                raise TypeError("most provide 'energy' or 'Q'")
            energy = qubo_energy(Q, sample)

        TemplateResponse.add_sample(self, sample, energy, data)
Example #12
0
    def test_energy(self):
        h = {v: v for v in range(0, 100, 2)}
        h.update({v: -(1 / v) for v in range(1, 100, 2)})
        J = {(u, v): 2 * (u / 3) + v ** .5 for (u, v) in itertools.combinations(range(100), 2)}

        spin_sample = {v: 1 if v % 2 else -1 for v in h}
        bin_sample = {v: 1 if v % 2 else 0 for v in h}

        Q, off = ising_to_qubo(h, J)

        ising_en = ising_energy(spin_sample, h, J)
        qubo_en = qubo_energy(bin_sample, Q)

        self.assertAlmostEqual(ising_en, qubo_en + off)
Example #13
0
    def test_spin_transform_composition_basic(self):
        sampler = self.sampler

        # let's get a problem that we know the answer to
        h = {v: .1 for v in range(10)}
        J = {(u, v): -1. for (u, v) in itertools.combinations(h, 2)}

        response = sampler.sample_ising(h, J, orig_h=h)

        # lowest energy sample should be all -1
        sample = next(iter(response))
        self.assertTrue(all(s == -1 for s in sample.values()))

        # also energy should still be preserved
        for sample, energy in response.items():
            self.assertLessEqual(
                abs(dimod.ising_energy(h, J, sample) - energy), 10**-5)

        for __, data in response.samples(data=True):
            self.assertIn('spin_reversal_variables', data)

        Q, __ = dimod.ising_to_qubo(h, J)

        response = sampler.sample_qubo(Q)

        # lowest energy sample should be all 0
        sample = next(iter(response))
        self.assertTrue(all(s == 0 for s in sample.values()))

        # also energy should still be preserved
        for sample, energy in response.items():
            self.assertLessEqual(abs(dimod.qubo_energy(Q, sample) - energy),
                                 10**-5)

        for __, data in response.samples(data=True):
            self.assertIn('spin_reversal_variables', data)

        response = sampler.sample_ising(h, J, orig_h=h)

        # lowest energy sample should be all -1
        sample = next(iter(response))
        self.assertTrue(all(s == -1 for s in sample.values()))

        # also energy should still be preserved
        for sample, energy in response.items():
            self.assertLessEqual(
                abs(dimod.ising_energy(h, J, sample) - energy), 10**-5)

        for __, data in response.samples(data=True):
            self.assertIn('spin_reversal_variables', data)
Example #14
0
    def test__vertex_one_color_qubo(self):
        G = dnx.chimera_graph(2, 2, 4)
        counter = itertools.count()
        x_vars = {v: {0: next(counter), 1: next(counter)} for v in G}

        # get the QUBO
        Q = _vertex_one_color_qubo(x_vars)

        # assign each variable a single color
        sample = {}
        for v in G:
            sample[x_vars[v][0]] = 1
            sample[x_vars[v][1]] = 0

        self.assertEqual(qubo_energy(sample, Q), -1 * len(G))
Example #15
0
    def test_energy(self):
        h = {v: v for v in range(0, 100, 2)}
        h.update({v: -(1 / v) for v in range(1, 100, 2)})
        J = {(u, v): 2 * (u / 3) + v**.5
             for (u, v) in itertools.combinations(range(100), 2)}

        spin_sample = {v: 1 if v % 2 else -1 for v in h}
        bin_sample = {v: 1 if v % 2 else 0 for v in h}

        Q, off = ising_to_qubo(h, J)

        ising_en = ising_energy(h, J, spin_sample)
        qubo_en = qubo_energy(Q, bin_sample)

        self.assertLessEqual(abs(-ising_en + qubo_en + off), 10**-5)
Example #16
0
    def test_sample_qubo(self):
        Q = {(0, 0): 0.0, (1, 1): 0.0, (2, 2): 0.0}
        Q.update({(0, 1): -1.0, (1, 2): 1.0, (0, 2): 1.0})

        response = dimod.ExactPolySolver().sample_hubo(Q)

        # every possible conbination should be present
        self.assertEqual(len(response), 2**3)
        self.assertEqual(response.record.sample.shape, (2**3, 3))

        # confirm vartype
        self.assertIs(response.vartype, dimod.BINARY)

        # check their energies
        for sample, energy in response.data(['sample', 'energy']):
            self.assertAlmostEqual(energy, dimod.qubo_energy(sample, Q))
    def test_sample_qubo(self):
        sampler = EmbeddingComposite(MockDWaveSampler())

        Q = {(0, 0): .1, (0, 4): -.8, (4, 4): 1}

        response = sampler.sample_qubo(Q)

        # nothing failed and we got at least one response back
        self.assertGreaterEqual(len(response), 1)

        for sample in response.samples():
            for u, v in Q:
                self.assertIn(v, sample)
                self.assertIn(u, sample)

        for sample, energy in response.data(['sample', 'energy']):
            self.assertAlmostEqual(dimod.qubo_energy(sample, Q), energy)
Example #18
0
    def test_as_binary(self):

        h = {0: 0, 1: 0}
        J = {(0, 1): 1}

        sample0 = {0: -1, 1: 1}
        sample1 = {0: 1, 1: -1}
        sample2 = {0: 1, 1: 1}

        Q, offset = ising_to_qubo(h, J)

        response = self.response_factory()
        response.add_samples_from([sample0, sample1, sample2], h=h, J=J)

        bin_response = response.as_binary(-1 * offset)
        for sample, energy in bin_response.items():
            self.assertEqual(qubo_energy(Q, sample), energy)
Example #19
0
    def test_sample_qubo(self):
        sampler = TilingComposite(MockDWaveSampler(), 2, 2)

        Q = {(u, v): random.uniform(-1, 1) for u, v in sampler.structure.edgelist}
        Q.update({(node, node): random.uniform(-1, 1) for node in sampler.structure.nodelist})

        response = sampler.sample_qubo(Q)

        # nothing failed and we got at least one response back per tile
        self.assertGreaterEqual(len(response), len(sampler.embeddings))

        for sample in response.samples():
            for u, v in Q:
                self.assertIn(v, sample)
                self.assertIn(u, sample)

        for sample, energy in response.data(['sample', 'energy']):
            self.assertAlmostEqual(dimod.qubo_energy(sample, Q), energy)
Example #20
0
    def test_start_from_spin(self):
        Q = {(0, 0): 4, (0, 3): 5, (0, 5): 4, (1, 1): 5, (1, 6): 1, (1, 7): -2,
             (1, 9): -3, (3, 0): -2, (3, 1): 2, (4, 5): 4, (4, 8): 2, (4, 9): -1,
             (5, 1): 2, (5, 6): -5, (5, 8): -4, (6, 0): 1, (6, 5): 2, (6, 6): -4,
             (6, 7): -2, (7, 0): -2, (7, 5): -3, (7, 6): -5, (7, 7): -3, (7, 8): 1,
             (8, 0): 2, (8, 5): 1, (9, 7): -3}
        qoff = 1.3

        h, J, ioff = qubo_to_ising(Q, qoff)

        bin_sample = {}
        ising_sample = {}
        for v in h:
            bin_sample[v] = 0
            ising_sample[v] = -1

        self.assertAlmostEqual(ising_energy(ising_sample, h, J, ioff),
                               qubo_energy(bin_sample, Q, qoff))
Example #21
0
    def test_start_from_binary(self):
        h = {i: v for i, v in enumerate([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4])}
        j = {(0, 5): 2, (0, 8): 4, (1, 4): -5, (1, 7): 1, (2, 0): 5,
             (2, 1): 4, (3, 0): -1, (3, 6): -3, (3, 8): 3, (4, 0): 2, (4, 7): 3,
             (4, 9): 3, (5, 1): 3, (6, 5): -4, (6, 7): -4, (7, 1): -4,
             (7, 8): 3, (8, 2): -4, (8, 3): -3, (8, 6): -5, (8, 7): -4, (9, 0): 4,
             (9, 1): -1, (9, 4): -5, (9, 7): 3}
        ioff = 1.7

        q, qoff = ising_to_qubo(h, j, ioff)

        bin_sample = {}
        ising_sample = {}
        for v in h:
            bin_sample[v] = 1
            ising_sample[v] = 1

        self.assertAlmostEqual(ising_energy(ising_sample, h, j, ioff),
                               qubo_energy(bin_sample, q, qoff))
Example #22
0
    def test_dimod_basic_qubo(self):
        n_variables = 50

        # all 0s
        Q = {(v, v): 1 for v in range(n_variables)}
        response = qbs.QBSolv().sample_qubo(Q, seed=10)
        sample = next(iter(response))
        for v in sample:
            self.assertEqual(sample[v], 0)

        # all 1s
        Q = {(u, v): -1 for u, v in itertools.combinations(range(n_variables), 2)}
        response = qbs.QBSolv().sample_qubo(Q, seed=167)
        sample = next(iter(response))
        for v in sample:
            self.assertEqual(sample[v], 1)

        for sample, energy in response.data(['sample', 'energy']):
            self.assertEqual(dimod.qubo_energy(sample, Q), energy)
Example #23
0
    def test_as_binary(self):

        h = {0: 0, 1: 0}
        J = {(0, 1): 1}

        sample0 = {0: -1, 1: 1}
        sample1 = {0: 1, 1: -1}
        sample2 = {0: 1, 1: 1}

        Q, offset = dimod.ising_to_qubo(h, J)

        response = self.response_factory()
        response.add_samples_from([sample0, sample1, sample2], h=h, J=J)

        bin_response = response.as_binary(-1 * offset)
        for sample, energy in bin_response.data(keys=['sample', 'energy']):
            self.assertEqual(dimod.qubo_energy(sample, Q), energy)

        bin_response = response.as_binary(-1 * offset)
        data_ids = {id(data) for __, data in response.samples(data=True)}
        for __, data in bin_response.samples(data=True):
            self.assertNotIn(id(data), data_ids)
    def test_basic(self):

        sampler = self.sampler

        h = {0: -.5, 1: 0, 2: 1, 3: -.5}
        J = {(0, 2): -1, (1, 2): -1, (0, 3): .5, (1, 3): -1}

        response0 = sampler.sample_ising(h, J, num_reads=10)

        for sample, energy in response0.data(['sample', 'energy']):
            self.assertEqual(dimod.ising_energy(sample, h, J), energy)

        # make sure we actully got back 100 samples
        self.assertEqual(len(response0), 10)

        Q = {(0, 0): 0, (1, 1): 0, (0, 1): -1}

        response4 = sampler.sample_qubo(Q, num_reads=10)
        self.assertEqual(len(response4), 10)

        for sample, energy in response4.data(['sample', 'energy']):
            self.assertEqual(dimod.qubo_energy(sample, Q), energy)
Example #25
0
    def test_as_spin_array(self):
        response = self.response_factory()

        # set up a BQM and some samples
        Q = {(0, 0): -1, (0, 1): 1, (1, 1): -1}
        h, J, offset = dimod.qubo_to_ising(Q)

        samples = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 0], [1, 1, 1]], dtype=int)
        energies = np.array([dimod.qubo_energy(row, Q) for row in samples])
        response.add_samples_from_array(samples, energies)

        # cast to spin
        spin_response = response.as_spin(-offset)

        # check that the energies are correcct
        for sample, energy in spin_response.items():
            self.assertEqual(dimod.ising_energy(sample, h, J), energy)

        # make a new spin response
        spin_response = response.as_spin(offset)
        data_ids = {id(data) for __, data in response.samples(data=True)}
        for __, data in spin_response.samples(data=True):
            self.assertNotIn(id(data), data_ids)
Example #26
0
    def test__vertex_different_colors_qubo(self):
        # Chimera tile (can be 2-colored)
        G = dnx.chimera_graph(1, 1, 4)
        counter = itertools.count()
        x_vars = {v: {0: next(counter), 1: next(counter)} for v in G}

        # get the QUBO
        Q = _vertex_different_colors_qubo(G, x_vars)

        # this thing should have energy 0 when each node is a different color
        bicolor = {v: 0 for v in range(4)}
        bicolor.update({v: 1 for v in range(4, 8)})

        # make the sample from the bicolor
        sample = {}
        for v in G:
            if bicolor[v] == 0:
                sample[x_vars[v][0]] = 1
                sample[x_vars[v][1]] = 0
            else:
                sample[x_vars[v][0]] = 0
                sample[x_vars[v][1]] = 1

        self.assertEqual(qubo_energy(sample, Q), 0)
Example #27
0
 def test_trivial(self):
     en = qubo_energy({}, {})
     self.assertEqual(en, 0)
Example #28
0
    def test__maximal_matching_qubo(self):

        G = nx.complete_graph(5)
        B = 1  # magnitude arg for _maximal_matching_qubo

        edge_mapping = {edge: idx for idx, edge in enumerate(G.edges())}
        edge_mapping.update({(e1, e0): idx
                             for (e0, e1), idx in edge_mapping.items()})
        inv_edge_mapping = {idx: edge for edge, idx in edge_mapping.items()}

        Q = _maximal_matching_qubo(G, edge_mapping, magnitude=B)

        # now for each combination of edges, we check that if the combination
        # is a maximal matching, it has energy magnitude * |edges|
        ground_energy = -1. * B * len(G.edges())
        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

            if dnx.is_maximal_matching(G, potential_matching):
                self.assertEqual(qubo_energy(Q, sample), ground_energy)
            elif not dnx.is_matching(potential_matching):
                # for now we don't care about these, they should be covered by the _matching_qubo
                # part of the QUBO function
                pass
            else:
                en = qubo_energy(Q, sample)

                gap = en - ground_energy
                if gap < infeasible_gap:
                    infeasible_gap = gap

        self.assertLessEqual(B, infeasible_gap)

        #
        # Another graph, Chimera tile this time
        #

        G = dnx.chimera_graph(1, 2, 2)
        B = 1  # magnitude arg for _maximal_matching_qubo

        edge_mapping = {edge: idx for idx, edge in enumerate(G.edges())}
        edge_mapping.update({(e1, e0): idx
                             for (e0, e1), idx in edge_mapping.items()})
        inv_edge_mapping = {idx: edge for edge, idx in edge_mapping.items()}

        Q = _maximal_matching_qubo(G, edge_mapping, magnitude=B)

        # now for each combination of edges, we check that if the combination
        # is a maximal matching, it has energy magnitude * |edges|
        ground_energy = -1. * B * len(G.edges())
        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

            if dnx.is_maximal_matching(G, potential_matching):
                # print potential_matching, qubo_energy(Q, sample)
                self.assertLess(abs(qubo_energy(Q, sample) - ground_energy),
                                10**-8)
            elif not dnx.is_matching(potential_matching):
                # for now we don't care about these, they should be covered by the _matching_qubo
                # part of the QUBO function
                pass
            else:
                en = qubo_energy(Q, sample)

                gap = en - ground_energy
                if gap < infeasible_gap:
                    infeasible_gap = gap

        self.assertLessEqual(B - infeasible_gap, 10**-8)
Example #29
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))
Example #30
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)