def test_change_vartype_copy(self): bqm = dimod.BinaryQuadraticModel({'a': .1}, {('a', 'b'): -1}, 0.0, dimod.SPIN) samples = [{'a': -1, 'b': +1}, {'a': +1, 'b': -1}, {'a': +1, 'b': +1}, {'a': -1, 'b': -1}] energies = [bqm.energy(sample) for sample in samples] response = dimod.Response.from_dicts(samples, {'energy': energies}) for sample, energy in response.data(['sample', 'energy']): self.assertAlmostEqual(bqm.energy(sample), energy) response_copy = response.change_vartype(dimod.SPIN, inplace=False) # should do nothing self.assertIsNot(response, response_copy) for sample, energy in response_copy.data(['sample', 'energy']): self.assertAlmostEqual(bqm.energy(sample), energy)
def test_tobqm(self): x = PBP(1, -1.) + PBP(2, -1.) + PBP(1, 8.) * PBP(2) + PBP( 3, -1.) + PBP(1, 8.) * PBP(3) + PBP(2, 8.) * PBP(3) + PBP( 4, 6.) + PBP(1, -6.) * PBP(4) + PBP(2, -6.) * PBP(4) + PBP( 3, -6.) * PBP(4) lin = {4: 6.0, 1: -1.0, 2: -1.0, 3: -1.0} quad = { (1, 4): -6.0, (2, 4): -6.0, (3, 4): -6.0, (1, 2): 8.0, (1, 3): 8.0, (2, 3): 8.0 } y = dimod.BinaryQuadraticModel(lin, quad, 0, dimod.BINARY) assert x.toBQM() == y
def test_auto_embedding_failure(self): counter = MockDWaveSamplerCounter() q = QPUSubproblemAutoEmbeddingSampler(qpu_sampler=counter) target_structure = q.sampler.target_structure num_vars = len( target_structure.nodelist ) + 1 # source graph will be too large for the target and ensure an embedding failure bqm = dimod.BinaryQuadraticModel(num_vars, 'SPIN') init = State.from_subsample(random_sample(bqm), bqm) retries = 3 with self.assertRaises(ValueError): result = q.run(init, num_retries=retries).result() self.assertEqual(retries + 1, counter.count)
def test_embed_bqm_identity(self): bqm = dimod.BinaryQuadraticModel({'a': -1}, { (0, 1): .5, (1, 'a'): -1. }, 1.0, dimod.BINARY) embedding = {v: {v} for v in bqm.linear} # identity embedding target_adj = nx.Graph() target_adj.add_nodes_from(bqm.linear) target_adj.add_edges_from(bqm.quadratic) embedded_bqm = dwave.embedding.embed_bqm(bqm, embedding, target_adj) self.assertEqual(bqm, embedded_bqm)
def test_pfs_traverse_connected_too_small(self): eid = EnergyImpactDecomposer(size=None, traversal='pfs') bqm = dimod.BinaryQuadraticModel({}, { 'ab': 1, 'bc': 1, 'cd': 1, 'da': 1 }, 0.0, dimod.SPIN) priority = collections.OrderedDict(zip('bdac', itertools.count(0, -1))) var = eid.traverse(bqm=bqm, sample=None, ordered_priority=priority, visited=set(), size=5) # start from 'b', try to pick more then there is (get complete graph back) self.assertEqual(var, set('abcd'))
def test_pfs_traverse_connected(self): eid = EnergyImpactDecomposer(size=None, traversal='pfs') bqm = dimod.BinaryQuadraticModel({}, { 'ab': 1, 'bc': 1, 'cd': 1, 'da': 1 }, 0.0, dimod.SPIN) priority = collections.OrderedDict(zip('bdac', itertools.count(0, -1))) var = eid.traverse(bqm=bqm, sample=None, ordered_priority=priority, visited=set(), size=3) # start from 'b', pick 2 connected variables, traversed in order of best energy (priority) self.assertEqual(var, set('bad'))
def test_all_three(self): builtin = [0, 'a', [0, 'a']] num_variables = 100 num_samples = 100 samples = 2*np.triu(np.ones((num_samples, num_variables)), -4) - 1 bqm = dimod.BinaryQuadraticModel.from_ising({v: .1*v for v in range(num_variables)}, {}) sampleset = dimod.SampleSet.from_samples_bqm(samples, bqm) linear = {'a': -1, 4: 1, ('a', "complex key"): 3} quadratic = {('a', 'c'): 3, ('b', 'c'): -3., ('a', 3): -1} bqm = dimod.BinaryQuadraticModel(linear, quadratic, 3, dimod.SPIN) obj = [builtin, sampleset, bqm] new = json.loads(json.dumps(obj, cls=DimodEncoder), cls=DimodDecoder) self.assertEqual(obj, new)
def to_bqm(self, sign=-1.0): # Signs for BQM are opposite from our (sawatabi's) definition. # - BQM: H = sum( J_{ij} * x_i * x_j ) + sum( h_{i} * x_i ) # - Sawatabi: H = - sum( J_{ij} * x_i * x_j ) - sum( h_{i} * x_i ) linear, quadratic = {}, {} for k, v in self._raw_interactions[constants.INTERACTION_LINEAR].items(): linear[k] = sign * v for k, v in self._raw_interactions[constants.INTERACTION_QUADRATIC].items(): quadratic[k] = sign * v if self.get_mtype() == constants.MODEL_ISING: vartype = dimod.SPIN elif self.get_mtype() == constants.MODEL_QUBO: vartype = dimod.BINARY bqm = dimod.BinaryQuadraticModel(linear, quadratic, self._offset, vartype) return bqm
def test_sample_bqm(self, mock_client): mock_client.from_config.side_effect = MockClient bqm = dimod.BinaryQuadraticModel({'a': -1, 'b': 1, 'c': 1}, {'ab': -0.8, 'ac': -0.7, 'bc': -1}, 0, dimod.SPIN) sampler = LeapHybridSampler() response = sampler.sample(bqm) rows, cols = response.record.sample.shape self.assertEqual(cols, 3) self.assertFalse(np.any(response.record.sample == 0)) self.assertIs(response.vartype, dimod.SPIN) self.assertIn('num_occurrences', response.record.dtype.fields)
def generate_bqm(self): "Generate a BinaryQuadraticModel version of the Problem." # Create an Ising-model BQM. bqm = dimod.BinaryQuadraticModel(self.weights, self.strengths, 0, dimod.SPIN) # Pin all variables the user asked to pin. bool2spin = {False: -1, True: +1} pins = {q: bool2spin[b] for q, b in self.pinned} for q in pins: # Ensure that every pinned variable exists. Otherwise, # fix_variables will throw a KeyError. bqm.add_variable(q, 0) bqm.fix_variables(pins) # Store the BQM. self.bqm = bqm
class TestHybridRunnable(unittest.TestCase): bqm = dimod.BinaryQuadraticModel({}, {'ab': 1, 'bc': 1, 'ca': -1}, 0, dimod.SPIN) init_state = State.from_sample(min_sample(bqm), bqm) def test_generic(self): runnable = HybridRunnable(TabuSampler(), fields=('problem', 'samples')) response = runnable.run(self.init_state) self.assertIsInstance(response, concurrent.futures.Future) self.assertEqual(response.result().samples.record[0].energy, -3.0) def test_validation(self): with self.assertRaises(TypeError): HybridRunnable(1, 'ab') with self.assertRaises(ValueError): HybridRunnable(TabuSampler(), None) with self.assertRaises(ValueError): HybridRunnable(TabuSampler(), ('a')) self.assertIsInstance(HybridRunnable(TabuSampler(), 'ab'), HybridRunnable) self.assertIsInstance(HybridRunnable(TabuSampler(), ('a', 'b')), HybridRunnable) self.assertIsInstance(HybridRunnable(TabuSampler(), ['a', 'b']), HybridRunnable) def test_problem_sampler_runnable(self): runnable = HybridProblemRunnable(TabuSampler()) response = runnable.run(self.init_state) self.assertIsInstance(response, concurrent.futures.Future) self.assertEqual(response.result().samples.record[0].energy, -3.0) def test_subproblem_sampler_runnable(self): runnable = HybridSubproblemRunnable(TabuSampler()) state = self.init_state.updated(subproblem=self.bqm) response = runnable.run(state) self.assertIsInstance(response, concurrent.futures.Future) self.assertEqual(response.result().subsamples.record[0].energy, -3.0) def test_runnable_composition(self): runnable = IdentityDecomposer() | HybridSubproblemRunnable(TabuSampler()) | IdentityComposer() response = runnable.run(self.init_state) self.assertIsInstance(response, concurrent.futures.Future) self.assertEqual(response.result().samples.record[0].energy, -3.0)
def test_partial_relabel_copy(self): linear = {v: .1 * v for v in range(-5, 5)} quadratic = {(u, v): .1 * u * v for u, v in itertools.combinations(linear, 2)} offset = 1.2 vartype = dimod.SPIN model = dimod.BinaryQuadraticModel(linear, quadratic, offset, vartype) mapping = {0: 'a', 1: 'b'} # partial mapping newmodel = model.relabel_variables(mapping, inplace=False) newlinear = linear.copy() newlinear['a'] = newlinear[0] newlinear['b'] = newlinear[1] del newlinear[0] del newlinear[1] self.assertEqual(newlinear, newmodel.linear)
def bqm_from_serializable(serializable: Dict[str, Any]) -> dimod.BinaryQuadraticModel: """Create a binary quadratic model from serializable dictionary. Args: serializable: dictionary representing BQM. The expected format of this dictionary as the same as the output format of `bqm_to_serializable`. Returns: Binary quadratic model converted from the input dictionary. """ return dimod.BinaryQuadraticModel( {i: coef for i, coef in serializable["linear"]}, {(i, j): coef for i, j, coef in serializable["quadratic"]}, serializable["offset"], vartype=serializable["vartype"], )
def test_pfs_on_impactful_far_subproblem(self): # problem graph has two components, each one is 4-node cycle graph # variable flip energy gains order variables: a, h..b edges = {'ab': 1, 'bc': 1, 'cd': 1, 'da': 1, 'ef': 1, 'fg': 1, 'gh': 1, 'he': 1, 'de': 0} biases = dict(zip(string.ascii_letters, range(8))) biases['a'] += 10 bqm = dimod.BinaryQuadraticModel(biases, edges, 0.0, 'SPIN') sample = {i: -1 for i in bqm.variables} state = State.from_sample(sample, bqm) eid = EnergyImpactDecomposer(size=5, traversal='pfs') result = eid.run(state).result() # move towards second cluster and pick the highest energy variables from there self.assertEqual(set(result.subproblem.variables), set('adehg'))
def test_pfs_traverse_connected_some_visited(self): eid = EnergyImpactDecomposer(size=None, traversal='pfs') bqm = dimod.BinaryQuadraticModel({}, { 'ab': 1, 'bc': 1, 'cd': 1, 'da': 1, 'bd': 1 }, 0.0, dimod.SPIN) priority = collections.OrderedDict(zip('bdac', itertools.count(0, -1))) var = eid.traverse(bqm=bqm, sample=None, ordered_priority=priority, visited=set('b'), size=3) # start with 'b' visited, so use 'd' as root and pick 2 more neighbors self.assertEqual(var, set('dac'))
def test_insert_retrieve(self): dbfile = self.database linear = {'1': 0.0, '0': -0.5, '3': 1.0, '2': -0.5} quadratic = { ('0', '3'): -1.0, ('1', '2'): 1.0, ('0', '2'): 0.5, ('1', '3'): 1.0 } offset = 0.0 model = dimod.BinaryQuadraticModel(linear, quadratic, offset, vartype=dimod.SPIN) graph = nx.Graph() graph.add_edges_from(quadratic) decision_variables = ('0', '2', '3') feasible_configurations = ((-1, -1, -1), (-1, 1, -1), (1, -1, -1), (1, 1, 1)) spec = pm.Specification(graph, decision_variables, feasible_configurations, dimod.SPIN) classical_gap = 2 ground = -2.5 pmodel = pm.PenaltyModel.from_specification(spec, model, classical_gap, ground) pmc.cache_penalty_model(pmodel, database=dbfile) # print(spec.feasible_configurations) # print(spec.decision_variables) # get it back ret_pmodel = pmc.get_penalty_model(spec, database=dbfile) # now get back one with a different decision_variables spec2 = pm.Specification(graph, ('3', '0', '2'), feasible_configurations, dimod.SPIN) try: ret_pmodel = pmc.get_penalty_model(spec2, database=dbfile) self.assertNotEqual(ret_pmodel, pmodel) except: pass
def test_arbitrary_labels_on_k44(self): dbfile = self.database graph = nx.Graph() for i in range(3): for j in range(3, 6): graph.add_edge(i, j) decision_variables = (0, 5) feasible_configurations = ((0, 0), (1, 1)) # equality spec = pm.Specification(graph, decision_variables, feasible_configurations, vartype=dimod.BINARY) linear = {v: 0 for v in graph} quadratic = {edge: 0 for edge in graph.edges} if decision_variables in quadratic: quadratic[decision_variables] = -1 else: u, v = decision_variables assert (v, u) in quadratic quadratic[(v, u)] = -1 model = dimod.BinaryQuadraticModel(linear, quadratic, 0.0, vartype=dimod.SPIN) pmodel = pm.PenaltyModel.from_specification(spec, model, 2, -1) # now cache the pmodel to make sure there is something to find for thingy in itertools.permutations(range(6)): mapping = dict(enumerate(thingy)) pmodel = pmodel.relabel_variables(mapping, inplace=False) pmc.cache_penalty_model(pmodel, database=dbfile) # now relabel some variables mapping = {1: '1', 2: '2', 3: '3', 4: '4'} new_spec = spec.relabel_variables(mapping, inplace=True) # retrieve from the new_spec # now try to retrieve it retreived_pmodel = pmc.get_penalty_model(new_spec, database=dbfile)
class TestRandomSubproblemDecomposer(unittest.TestCase): bqm = dimod.BinaryQuadraticModel({}, {'ab': 1, 'bc': 1}, 0, dimod.SPIN) state = State.from_sample(min_sample(bqm), bqm) def test_simple(self): runnable = RandomSubproblemDecomposer(size=1) state = self.state for _ in range(10): state = runnable.next(state) self.assertEqual(len(state.subproblem.variables), 1) self.assertIn(next(iter(state.subproblem.variables)), self.bqm.variables) def test_look_and_feel(self): self.assertEqual(repr(RandomSubproblemDecomposer(7)), 'RandomSubproblemDecomposer(size=7)') def test_validation(self): with self.assertRaises(ValueError): RandomSubproblemDecomposer(len(self.bqm)+1).run(self.state).result()
def test_order_preservation_doubled(self): bqm = dimod.BinaryQuadraticModel({}, {'ab': 1, 'bc': -1}, 0, dimod.SPIN) ss1 = dimod.SampleSet.from_samples_bqm(([[1, 1, 0], [1, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 0], [1, 0, 0], [0, 0, 0]], 'abc'), bqm) target = dimod.SampleSet.from_samples_bqm(([[1, 1, 0], [1, 0, 0], [0, 0, 0]], 'abc'), bqm, num_occurrences=[2, 2, 3]) self.assertEqual(target, ss1.aggregate())
def test_interruptable_tabu(self): bqm = dimod.BinaryQuadraticModel({}, { 'ab': 1, 'bc': -1, 'ca': 1 }, 0, 'SPIN') workflow = InterruptableTabuSampler() init = State(problem=bqm) future = workflow.run(init) while len(workflow.runnable.timers.get('dispatch.next', ())) < 1: time.sleep(0) workflow.stop() self.assertEqual(future.result().samples.first.energy, -3) self.assertGreater(len(workflow.timers['dispatch.next']), 0)
def test_from_subsamples(self): s1 = [0, 1] s2 = {0: 1, 1: 0} bqm = dimod.BinaryQuadraticModel({0: 1, 1: 2}, {}, 0.0, 'BINARY') self.assertEqual( State.from_subsample(s1, bqm).subsamples.first.energy, 2.0) self.assertEqual( State.from_subsample(s2, bqm).subsamples.first.energy, 1.0) self.assertEqual(State.from_subsample(s2, bqm, beta=0.5).beta, 0.5) self.assertEqual( State.from_subsamples([s1, s1], bqm).subsamples.first.energy, 2.0) self.assertEqual( State.from_subsamples([s2, s2], bqm).subsamples.first.energy, 1.0) self.assertEqual( State.from_subsamples([s2, s2], bqm, beta=0.5).beta, 0.5) self.assertEqual( State.from_subsamples([sample_as_dict(s1), s2], bqm).subsamples.first.energy, 1.0)
def test_relabel_with_overlap(self): linear = {v: .1 * v for v in range(-5, 4)} quadratic = {(u, v): .1 * u * v for u, v in itertools.combinations(linear, 2)} offset = 1.2 vartype = dimod.SPIN model = dimod.BinaryQuadraticModel(linear, quadratic, offset, vartype) partial_overlap_mapping = {v: -v for v in linear} # has variables mapped to other old labels # construct a test model by using copy testmodel = model.relabel_variables(partial_overlap_mapping, inplace=False) # now apply in place model.relabel_variables(partial_overlap_mapping, inplace=True) # should have stayed the same self.assertEqual(testmodel, model) self.assertEqual(testmodel.adj, model.adj)
def test_all_three_functional(self): builtin = [0, 'a', [0, 'a']] num_variables = 100 num_samples = 100 samples = 2*np.triu(np.ones((num_samples, num_variables)), -4) - 1 bqm = dimod.BinaryQuadraticModel.from_ising({v: .1*v for v in range(num_variables)}, {}) sampleset = dimod.SampleSet.from_samples_bqm(samples, bqm) linear = {'a': -1, 4: 1, ('a', "complex key"): 3} quadratic = {('a', 'c'): 3, ('b', 'c'): -3., ('a', 3): -1} bqm = dimod.BinaryQuadraticModel(linear, quadratic, 3, dimod.SPIN) obj = [builtin, sampleset, bqm] # no encoder, uses ._asdict new = simplejson.loads(simplejson.dumps(obj), object_hook=dimod_object_hook) self.assertEqual(obj, new)
def test_qubo_conversion_with_binary_fractions(): qubo = dimod.BinaryQuadraticModel( { 0: 1, 1: 2, 2: 3 }, { (1, 2): 0.5, (1, 0): -0.25, (0, 2): 2.125 }, -1, vartype=dimod.BINARY, ) ising = convert_qubo_to_openfermion_ising(qubo) new_qubo = convert_openfermion_ising_to_qubo(ising) assert qubo == new_qubo
def test_vartype_is_stored(self, vartype, expected_output_vartype): bqm = dimod.BinaryQuadraticModel( { 0: 0.5, 2: -2.0, 3: 3 }, { (2, 1): 0.5, (1, 0): 0.4, (0, 3): -0.1 }, vartype=vartype, ) serializable = bqm_to_serializable(bqm) assert serializable["vartype"] == expected_output_vartype
def test_to_networkx_graph(self): graph = nx.barbell_graph(7, 6) # build a BQM model = dimod.BinaryQuadraticModel({v: -.1 for v in graph}, {edge: -.4 for edge in graph.edges}, 1.3, vartype=dimod.SPIN) # get the graph BQM = dimod.to_networkx_graph(model) self.assertEqual(set(graph), set(BQM)) for u, v in graph.edges: self.assertIn(u, BQM[v]) for v, bias in model.linear.items(): self.assertEqual(bias, BQM.nodes[v]['bias'])
def test_rolling_subproblem_larger_than_rolling_history(self): """In case rolling history too small, just one problem is unrolled.""" # 10 variables, 0 to 9 when ordered by energy increase on flip bqm = dimod.BinaryQuadraticModel({i: i for i in range(10)}, {}, 0.0, 'SPIN') sample = {i: 1 for i in range(10)} # exactly 1 five-variable problems should be produced state = State.from_sample(sample, bqm) eid = EnergyImpactDecomposer(size=5, rolling=True, rolling_history=0.3, silent_rewind=False) states = list(iter(partial(eid.next, state=state), None)) self.assertEqual(len(states), 1) self.assertEqual(len(states[0].subproblem), 5) self.assertEqual(list(dict(states[0].subproblem.linear).values()), list(range(0, 5))) # works even for subproblems as large as the input problem eid = EnergyImpactDecomposer(size=len(bqm), rolling=True, rolling_history=0.3, silent_rewind=False) states = list(iter(partial(eid.next, state=state), None)) self.assertEqual(len(states), 1) self.assertEqual(len(states[0].subproblem), 10) self.assertEqual(list(dict(states[0].subproblem.linear).values()), list(range(0, 10))) # but adapt to problem size if subproblem larger than problem eid = EnergyImpactDecomposer(size=11, rolling=True, rolling_history=0.3, silent_rewind=False) states = list(iter(partial(eid.next, state=state), None)) self.assertEqual(len(states), 1) self.assertEqual(len(states[0].subproblem), 10) self.assertEqual(list(dict(states[0].subproblem.linear).values()), list(range(0, 10)))
def test_offset_is_stored(self, offset): bqm = dimod.BinaryQuadraticModel( { 0: 0.5, 2: -2.0, 3: 3 }, { (2, 1): 0.5, (1, 0): 0.4, (0, 3): -0.1 }, offset, vartype=dimod.BINARY, ) serializable = bqm_to_serializable(bqm) assert serializable["offset"] == offset
def test_all_linear_coefficients_are_stored(self): bqm = dimod.BinaryQuadraticModel( { 0: 1, 1: 2, 2: 3 }, { (1, 2): 0.5, (1, 0): 0.7, (0, 2): 0.9 }, -10, vartype=dimod.BINARY, ) serializable = bqm_to_serializable(bqm) assert set(serializable["linear"]) == {(0, 1), (1, 2), (2, 3)}
def test_pfs_traverse_disconnected_some_visited(self): eid = EnergyImpactDecomposer(size=None, traversal='pfs') bqm = dimod.BinaryQuadraticModel({}, { 'ab': 1, 'bc': 1, 'cd': 1, 'da': 1, 'ef': 1, 'fg': 1 }, 0.0, dimod.SPIN) priority = collections.OrderedDict( zip('abcdefg', itertools.count(0, -1))) var = eid.traverse(bqm=bqm, sample=None, ordered_priority=priority, visited=set('abc'), size=3) # pick 'd' from first graph component, and 'ef' from the second self.assertEqual(var, set('def'))