def test_vartype(self): poly = {(0, 1, 2): 10, (0, 1): 5} # make sure (0, 1) is most common self.assertEqual(dimod.make_quadratic(poly, 1.0, 'SPIN'), dimod.make_quadratic(poly, 1.0, dimod.SPIN)) self.assertEqual(dimod.make_quadratic(poly, 1.0, 'BINARY'), dimod.make_quadratic(poly, 1.0, dimod.BINARY))
def test_quad_to_linear(self): J = {(0, 1): -1, (0, 1, 2): 1, (0, 1, 3): 1} h = {} off = .5 poly = J.copy() poly.update({(v, ): bias for v, bias in h.items()}) poly[()] = off bqm = make_quadratic(J, 10.0, bqm=dimod.BinaryQuadraticModel.from_ising( h, {}, off)) variables = set(h).union(*J) aux_variables = tuple(set(bqm.linear) - variables) variables = tuple(variables) self.assertTrue(aux_variables) for config in itertools.product((-1, 1), repeat=len(variables)): sample = dict(zip(variables, config)) energy = poly_energy(sample, poly) reduced_energies = [] for aux_config in itertools.product((-1, 1), repeat=len(aux_variables)): aux_sample = dict(zip(aux_variables, aux_config)) aux_sample.update(sample) reduced_energies.append(bqm.energy(aux_sample)) self.assertAlmostEqual(energy, min(reduced_energies))
def test_several_terms(self): poly = {(0, 1, 2): -1, (1, 2, 3): 1, (0, 2, 3): .5, (0,): .4, (): .5} bqm = make_quadratic(poly, 5.0, bqm=dimod.BinaryQuadraticModel.empty(dimod.SPIN)) variables = set().union(*poly) aux_variables = tuple(set(bqm.linear) - variables) variables = tuple(variables) self.assertTrue(aux_variables) for config in itertools.product((-1, 1), repeat=len(variables)): sample = dict(zip(variables, config)) energy = poly_energy(sample, poly) reduced_energies = [] for aux_config in itertools.product((-1, 1), repeat=len(aux_variables)): aux_sample = dict(zip(aux_variables, aux_config)) aux_sample.update(sample) reduced_energies.append(bqm.energy(aux_sample)) self.assertAlmostEqual(energy, min(reduced_energies))
def test_linear_and_offset(self): poly = {(0,): .5, tuple(): 1.3} bqm = dimod.make_quadratic(poly, 10.0, dimod.BINARY) self.assertEqual(bqm, dimod.BinaryQuadraticModel({0: .5}, {}, 1.3, dimod.BINARY))
def test_bug(self): # from a bug report # https://support.dwavesys.com/hc/en-us/community/posts/360035719954-dimod-make-quadratic-returns-error H = {(0, 1, 0, 1): -4.61898, (0, 1, 1, 0): 4.61898, (0, 2, 0, 2): -5.18353, (0, 2, 2, 0): 5.18353, (1, 0, 0, 1): 4.61898, (1, 0, 1, 0): -4.61898, (1, 2, 2, 1): 4.97017, (2, 0, 0, 2): 5.18353, (2, 0, 2, 0): -5.18353, (2, 1, 1, 2): 4.97017, } bqm = make_quadratic(H, 1, 'BINARY') self.assertEqual(set(bqm), {0, 1, 2}) # should be no aux variables
def test_no_higher_order(self): poly = {(0, 1): -1, (1, 2): 1} bqm = make_quadratic(poly, 1.0, dimod.SPIN) variables = set().union(*poly) aux_variables = tuple(set(bqm.linear) - variables) variables = tuple(variables) for config in itertools.product((-1, 1), repeat=len(variables)): sample = dict(zip(variables, config)) energy = poly_energy(sample, poly) reduced_energies = [] for aux_config in itertools.product((-1, 1), repeat=len(aux_variables)): aux_sample = dict(zip(aux_variables, aux_config)) aux_sample.update(sample) reduced_energies.append(bqm.energy(aux_sample)) self.assertAlmostEqual(energy, min(reduced_energies))
def test_binary_polynomial(self): HUBO = {(0, 1, 2): .5, (0, 1): 1.3, (2, 4, 1): -1, (3, 2): -1} bqm = dimod.make_quadratic(HUBO, 1000.0, dimod.BINARY) variables = set().union(*HUBO) aux_variables = tuple(set(bqm.linear) - variables) variables = tuple(variables) self.assertTrue(aux_variables) for config in itertools.product((0, 1), repeat=len(variables)): sample = dict(zip(variables, config)) energy = poly_energy(sample, {}, HUBO, offset=0.0) reduced_energies = [] for aux_config in itertools.product((0, 1), repeat=len(aux_variables)): aux_sample = dict(zip(aux_variables, aux_config)) aux_sample.update(sample) reduced_energies.append(bqm.energy(aux_sample)) self.assertAlmostEqual(energy, min(reduced_energies))
def test_several_terms(self): h = {0: .4, 1: 0, 2: 0, 3: 0} J = {(0, 1, 2): -1, (1, 2, 3): 1, (0, 2, 3): .5} off = .5 bqm = dimod.make_quadratic(J, 5.0, bqm=dimod.BinaryQuadraticModel.from_ising(h, {}, off)) variables = set(h).union(*J) aux_variables = tuple(set(bqm.linear) - variables) variables = tuple(variables) self.assertTrue(aux_variables) for config in itertools.product((-1, 1), repeat=len(variables)): sample = dict(zip(variables, config)) energy = poly_energy(sample, h, J, offset=off) reduced_energies = [] for aux_config in itertools.product((-1, 1), repeat=len(aux_variables)): aux_sample = dict(zip(aux_variables, aux_config)) aux_sample.update(sample) reduced_energies.append(bqm.energy(aux_sample)) self.assertAlmostEqual(energy, min(reduced_energies))
def test_simple(self): h = {0: 0, 1: 0, 2: 0} J = {(0, 1, 2): -1} off = 0 bqm = dimod.make_quadratic(J, 5.0, dimod.SPIN) variables = set(h).union(*J) aux_variables = tuple(set(bqm.linear) - variables) variables = tuple(variables) self.assertTrue(aux_variables) for config in itertools.product((-1, 1), repeat=len(variables)): sample = dict(zip(variables, config)) energy = poly_energy(sample, h, J, offset=off) reduced_energies = [] for aux_config in itertools.product((-1, 1), repeat=len(aux_variables)): aux_sample = dict(zip(aux_variables, aux_config)) aux_sample.update(sample) reduced_energies.append(bqm.energy(aux_sample)) self.assertAlmostEqual(energy, min(reduced_energies))
def test_empty(self): bqm = make_quadratic({}, 1.0, dimod.SPIN) self.assertEqual(bqm, dimod.BinaryQuadraticModel.empty(dimod.SPIN))
def compile(self, strength=5.0): """Returns the compiled :class:`Model`. This method reduces the degree of the expression if the degree is higher than 2, and convert it into :class:`.Model` which has information about QUBO. Args: strength (float): The strength of the reduction constraint. Insufficient strength can result in the binary quadratic model not having the same minimizations as the polynomial. Returns: :class:`Model`: The model compiled from the :class:`.Express`. Examples: In this example, there is a higher order term :math:`abcd`. It is decomposed as [[``a*d``, ``c``], ``b``] hierarchically and converted into QUBO. By calling :func:`to_qubo()` of the :obj:`model`, we get the resulting QUBO. >>> from pyqubo import Binary >>> a, b, c, d = Binary("a"), Binary("b"), Binary("c"), Binary("d") >>> model = (a*b*c + a*b*d).compile() >>> pprint(model.to_qubo()) # doctest: +SKIP ({('a', 'a'): 0.0, ('a', 'a*b'): -10.0, ('a', 'b'): 5.0, ('a*b', 'a*b'): 15.0, ('a*b', 'b'): -10.0, ('a*b', 'c'): 1.0, ('a*b', 'd'): 1.0, ('b', 'b'): 0.0, ('c', 'c'): 0, ('d', 'd'): 0}, 0.0) """ def compile_param_if_express(val): if isinstance(val, Express): return val._compile_param() else: return val # Constraint for AND(multiplier, multiplicand) = product def binary_product(multiplier, multiplicand, product, weight): return { BinaryProd({product}): 3.0 * weight, BinaryProd({multiplicand, product}): -2.0 * weight, BinaryProd({multiplier, product}): -2.0 * weight, BinaryProd({multiplier, multiplicand}): weight } # When the label contains PROD_SYM, elements of products should be sorted # such that the resulting label is uniquely determined. def normalize_label(label): s = Express.PROD_SYM if s in label: return s.join(sorted(label.split(s))) else: return label # Expand the expression to polynomial expanded, constraints, penalties = Express._expand(self) expanded = Express._merge_term(expanded, penalties) # Make polynomials quadratic offset = 0.0 pubo = {} for term_key, value in expanded.items(): if term_key.is_constant(): offset = value else: pubo[tuple(term_key.keys)] = value bqm = dimod.make_quadratic(pubo, strength, dimod.BINARY) bqm_qubo, bqm_offset = bqm.to_qubo() # Extracts product constrains product_consts = {} for (a, b), v in bqm.info['reduction'].items(): prod = normalize_label(v['product']) a = normalize_label(a) b = normalize_label(b) product_consts["AND({},{})={}".format(a, b, prod)]\ = binary_product(a, b, prod, strength) # Normalize labels and compile values of the QUBO compiled_qubo = {} for (label1, label2), value in bqm_qubo.items(): norm_label1 = normalize_label(label1) norm_label2 = normalize_label(label2) # Sort the tuple of labels such that the created key is uniquely determined. if norm_label2 > norm_label1: label_key = (norm_label1, norm_label2) else: label_key = (norm_label2, norm_label1) # Compile values of the QUBO compiled_qubo[label_key] = compile_param_if_express(value) compiled_qubo = CompiledQubo( compiled_qubo, compile_param_if_express(offset + bqm_offset)) # compile values of constraint compiled_constraints = {} for label, constraint in Express._merge_dict(constraints, product_consts).items(): compiled_constraints[label] =\ CompiledConstraint({prod: compile_param_if_express(value) for prod, value in constraint.items()}) # Merge structures uniq_variables = Express._unique_vars(self) structure = reduce(Express._merge_dict, [var.structure for var in uniq_variables]) return Model(compiled_qubo, structure, compiled_constraints)
def get_dic_from_matrix(matrix): d = {} for i in product(*[range(s) for s in matrix.shape]): if matrix[i]: d[i] = matrix[i] return d set_up_linear_members() set_up_quadratic_members() set_up_cubic_memebers() # print(get_dic_from_matrix(I)) poly = { **get_dic_from_matrix(I), **get_dic_from_matrix(J), **get_dic_from_matrix(H) } # used to make cubic-quadratic conversion strength = 5 bqm = dimod.make_quadratic(poly, strength, dimod.BINARY) print(bqm.num_variables) sampler = neal.SimulatedAnnealingSampler() result = sampler.sample(bqm, num_reads=20) # sampler = LeapHybridSampler() # sampleset = sampler.sample(bqm)
def get_results(self): strength = 5 bqm = dimod.make_quadratic(self.poly, strength, dimod.BINARY) sampler = neal.SimulatedAnnealingSampler() result = sampler.sample(bqm, num_reads=200) return result.lowest().first.sample