def test_quadratic_constraints(self): num_constraints = 100000 x = dimod.Binary('x') y = dimod.Binary('y') cqm = dimod.ConstrainedQuadraticModel() for _ in range(num_constraints): cqm.add_constraint(x*y == 1) sampler.sample_cqm(cqm).resolve() # smoke test
def test_sample_CONSTRAINED_MIXED(self): # Using various Vartypes, including the `add_discrete` method cqm = dimod.ConstrainedQuadraticModel() x = {(u, v): dimod.Binary((u, v)) for u, v in product(['u1', 'u2'], range(3))} cqm.add_discrete([('u1', v) for v in range(3)], label='u1') cqm.add_discrete([('u2', v) for v in range(3)], label='u2') y, z = dimod.Spin('y'), dimod.Integer('z', lower_bound=1, upper_bound=3) obj1 = x[('u1', 0)] * y - x[('u2', 1)] * y obj2 = x[('u1', 0)] * z + 2 * x[('u1', 2)] * x[('u2', 2)] cqm.set_objective(obj1 + obj2) cqm.add_constraint(z == 2) response = dimod.ExactCQMSolver().sample_cqm(cqm) # every possible combination should be present, respecting the discrete constraints self.assertEqual(len(response), 54) self.assertEqual(response.record.sample.shape, (54, len(cqm.variables))) # only 18 samples should be feasible feasible_responses = response.filter(lambda d: d.is_feasible) self.assertEqual(len(feasible_responses), 18) dimod.testing.assert_sampleset_energies_cqm(response, cqm)
def test_qm(self): x = dimod.Binary('x') s = dimod.Spin('s') i = dimod.Integer('i') self.assertTrue((x + s + i).is_almost_equal(1.001 * (x + s + i), places=2)) self.assertFalse((x + s + i).is_almost_equal(1.1 * (x + s + i), places=2))
def test_sample_CONSTRAINED_BINARY(self): # using Binary variables, with equality constraint: cqm = dimod.ConstrainedQuadraticModel() x, y, z = dimod.Binary('x'), dimod.Binary('y'), dimod.Binary('z') cqm.set_objective(x * y + 2 * y * z) cqm.add_constraint(x * y == 1) response = dimod.ExactCQMSolver().sample_cqm(cqm) # every possible combination should be present self.assertEqual(len(response), 8) self.assertEqual(response.record.sample.shape, (8, len(cqm.variables))) # only two samples should be feasible feasible_responses = response.filter(lambda d: d.is_feasible) self.assertEqual(len(feasible_responses), 2) dimod.testing.assert_sampleset_energies_cqm(response, cqm)
def test_qm_Ge_constraint(self): i = dimod.Integer('i', upper_bound=7) j = dimod.Integer('j', upper_bound=9) x = dimod.Binary('x') cqm = CQM() cqm.add_constraint(i + j + x >= 5) bqm, inverter = dimod.cqm_to_bqm(cqm, lagrange_multiplier=1) for bin_sample in dimod.ExactSolver().sample(bqm).lowest().samples(): int_sample = inverter(bin_sample) self.assertGreaterEqual(int_sample['i'] + int_sample['j'] + int_sample['x'], 5)
def test_qm_objective_only(self): i = dimod.Integer('i', upper_bound=7) j = dimod.Integer('j', upper_bound=9) x = dimod.Binary('x') qm = i*j + 5*j*x + 8*i + 3*x + 5 cqm = CQM.from_qm(qm) bqm, inverter = dimod.cqm_to_bqm(cqm) sampleset = dimod.ExactSolver().sample(bqm) for bin_sample, energy in sampleset.data(['sample', 'energy']): int_sample = inverter(bin_sample) self.assertEqual(qm.energy(int_sample), energy)
def test_serializable(self): i = dimod.Integer('i', upper_bound=7) j = dimod.Integer('j', upper_bound=9) x = dimod.Binary('x') cqm = CQM() cqm.add_constraint(i + j + x >= 5) bqm, inverter = dimod.cqm_to_bqm(cqm, lagrange_multiplier=1) newinverter = dimod.constrained.CQMToBQMInverter.from_dict( json.loads(json.dumps(inverter.to_dict()))) for bin_sample in dimod.ExactSolver().sample(bqm).lowest().samples(): int_sample = newinverter(bin_sample) self.assertGreaterEqual(int_sample['i'] + int_sample['j'] + int_sample['x'], 5)
def graph_partition_cqm(G, num_partitions): """Find a constrained quadratic model for the graph's partitions. Defines an CQM with ground states corresponding to a balanced k-partition of G and uses the sampler to sample from it. A k-partition is a collection of k subsets of the vertices of G such that each vertex is in exactly one subset, and the number of edges between vertices in different subsets is as small as possible. If G is a weighted graph, the sum of weights over those edges are minimized. Parameters ---------- G : NetworkX graph The graph to partition. num_partitions : int The number of subsets in the desired partition. Returns ------- cqm : :class:`dimod.ConstrainedQuadraticModel` A constrained quadratic model with ground states corresponding to a partition problem. The nodes of `G` are discrete logical variables of the CQM, where the cases are the different partitions the node can be assigned to. The objective is given as the number of edges connecting nodes in different partitions. """ partition_size = G.number_of_nodes() / num_partitions partitions = range(num_partitions) cqm = dimod.ConstrainedQuadraticModel() # Variables will be added using the discrete method in CQM x = {vk: dimod.Binary(vk) for vk in itertools.product(G.nodes, partitions)} for v in G.nodes: cqm.add_discrete(((v, k) for k in partitions), label=v) if not math.isclose(partition_size, int(partition_size)): # if number of nodes don't divide into num_partitions, # accept partitions of size ceil() or floor() floor, ceil = int(partition_size), int(partition_size + 1) for k in partitions: cqm.add_constraint(dimod.quicksum( (x[u, k] for u in G.nodes)) >= floor, label='equal_partition_low_%s' % k) cqm.add_constraint(dimod.quicksum( (x[u, k] for u in G.nodes)) <= ceil, label='equal_partition_high_%s' % k) else: # each partition must have partition_size elements for k in partitions: cqm.add_constraint(dimod.quicksum( (x[u, k] for u in G.nodes)) == int(partition_size), label='equal_partition_%s' % k) cuts = 0 for (u, v, d) in G.edges(data=True): for k in partitions: w = d.get('weight', 1) cuts += w * x[u, k] * x[v, k] if cuts: cqm.set_objective(-cuts) return cqm