def time_list1000x1000(self): dimod.as_samples(self.list1000x1000)
def time_dict1000x1000(self): dimod.as_samples(self.dict1000x1000)
def time_empty(self): dimod.as_samples([])
def time_empty_labelled(self): dimod.as_samples((self.empty, []))
def time_100x100_labelled(self): dimod.as_samples((self.arr100x100, self.labels100))
def test_list_discrete(self): arr, labels = dimod.as_samples([int(1 << 8)]) self.assertEqual(arr.dtype, np.int16) np.testing.assert_array_equal(arr, [[int(1 << 8)]])
def sample(self, bqm, anneal_schedules=None, **parameters): """Sample the binary quadratic model using reverse annealing along a given set of anneal schedules. Args: bqm (:obj:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. anneal_schedules (list of lists): Anneal schedules in order of submission. Each schedule is formatted as a list of [time, s] pairs initial_state (dict, optional): the state to reverse anneal from. If not provided, it will be randomly generated **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :obj:`dimod.SampleSet` that has initial_state and schedule_index fields. Examples: This example runs 100 reverse anneals each for three schedules on a problem constructed by setting random :math:`\pm 1` values on a clique (complete graph) of 15 nodes, minor-embedded on a D-Wave system using the :class:`.DWaveCliqueSampler` sampler. >>> import dimod >>> from dwave.system import DWaveCliqueSampler, ReverseAdvanceComposite ... >>> sampler = DWaveCliqueSampler() # doctest: +SKIP >>> sampler_reverse = ReverseAdvanceComposite(sampler) # doctest: +SKIP >>> schedule = [[[0.0, 1.0], [t, 0.5], [20, 1.0]] for t in (5, 10, 15)] ... >>> bqm = dimod.generators.ran_r(1, 15) >>> init_samples = {i: -1 for i in range(15)} >>> sampleset = sampler_reverse.sample(bqm, ... anneal_schedules=schedule, ... initial_state=init_samples, ... num_reads=100, ... reinitialize_state=True) # doctest: +SKIP """ child = self.child if anneal_schedules is None: return child.sample(bqm, **parameters) vartype_values = list(bqm.vartype.value) if 'initial_state' not in parameters: initial_state = dict( zip(list(bqm.variables), np.random.choice(vartype_values, len(bqm)))) else: initial_state = parameters.pop('initial_state') if not isinstance(initial_state, abc.Mapping): raise TypeError( "initial state provided must be a dict, but received {}". format(initial_state)) if 'reinitialize_state' not in parameters: parameters['reinitialize_state'] = True if "answer_mode" in child.parameters: parameters['answer_mode'] = 'histogram' vectors = {} for schedule_idx, anneal_schedule in enumerate(anneal_schedules): sampleset = child.sample(bqm, anneal_schedule=anneal_schedule, initial_state=initial_state, **parameters) # update vectors initial_state, _ = dimod.as_samples(initial_state) vectors = _update_data_vector( vectors, sampleset, { 'initial_state': [initial_state[0]] * len(sampleset.record.energy), 'schedule_index': [schedule_idx] * len(sampleset.record.energy) }) if schedule_idx + 1 == len(anneal_schedules): # no need to create the next initial state - last iteration break # prepare the initial state for the next iteration if parameters['reinitialize_state']: # if reinitialize is on, choose the lowest energy, most probable state for next iteration ground_state_energy = sampleset.first.energy lowest_energy_samples = sampleset.record[ sampleset.record.energy == ground_state_energy] lowest_energy_samples.sort(order='num_occurrences') initial_state = dict( zip(sampleset.variables, lowest_energy_samples[-1].sample)) else: # if not reinitialized, take the last state as the next initial state initial_state = dict( zip(sampleset.variables, sampleset.record.sample[-1])) samples = vectors.pop('sample') return dimod.SampleSet.from_samples( (samples, bqm.variables), bqm.vartype, info={'anneal_schedules': anneal_schedules}, **vectors)
def test_empty_list(self): # no samples, no labels arr, labels = dimod.as_samples([]) np.testing.assert_array_equal(arr, np.zeros((0, 0))) self.assertEqual(labels, [])
def majority_vote(samples, chains): """Unembed samples using the most common value for broken chains. Args: samples (samples_like): A collection of samples. `samples_like` is an extension of NumPy's array_like. See :func:`dimod.as_samples`. chains (list[array_like]): List of chains, where each chain is an array_like collection of the variables in the same order as their represention in the given samples. Returns: tuple: A 2-tuple containing: :obj:`numpy.ndarray`: Unembedded samples as an nS-by-nC array of dtype 'int8', where nC is the number of chains and nS the number of samples. Broken chains are resolved by setting the sample value to that of most the chain's elements or, for chains without a majority, an arbitrary value. :obj:`numpy.ndarray`: Indicies of the samples. Equivalent to :code:`np.arange(nS)` because all samples are kept and none added. Examples: This example unembeds samples from a target graph that chains nodes 0 and 1 to represent one source node and nodes 2, 3, and 4 to represent another. Both samples have one broken chain, with different majority values. >>> import dimod >>> import numpy as np ... >>> chains = [(0, 1), (2, 3, 4)] >>> samples = np.array([[1, 1, 0, 0, 1], [1, 1, 1, 0, 1]], dtype=np.int8) >>> unembedded, idx = dwave.embedding.majority_vote(samples, chains) >>> print(unembedded) [[1 0] [1 1]] >>> print(idx) [0 1] """ samples, labels = dimod.as_samples(samples) if labels != range(len(labels)): relabel = {v: idx for idx, v in enumerate(labels)} chains = [[relabel[v] for v in chain] for chain in chains] else: chains = list(map(list, chains)) # because we use them for indexing num_samples, num_variables = samples.shape num_chains = len(chains) unembedded = np.empty((num_samples, num_chains), dtype='int8', order='F') # determine if spin or binary. If samples are all 1, then either method works, so we use spin # because it is faster if samples.all(): # spin-valued for cidx, chain in enumerate(chains): # we just need the sign for spin. We don't use np.sign because in that can return 0 # and fixing the 0s is slow. unembedded[:, cidx] = 2 * (samples[:, chain].sum(axis=1) >= 0) - 1 else: # binary-valued for cidx, chain in enumerate(chains): mid = len(chain) / 2 unembedded[:, cidx] = (samples[:, chain].sum(axis=1) >= mid) return unembedded, np.arange( num_samples) # we keep all of the samples in this case
def test_dict_with_labels(self): arr, labels = dimod.as_samples(({'a': -1}, 'a')) np.testing.assert_array_equal(arr, [[-1]]) self.assertEqual(labels, ['a'])
def test_empty_dict(self): # one sample, no labels arr, labels = dimod.as_samples({}) np.testing.assert_array_equal(arr, np.zeros((1, 0))) self.assertEqual(labels, [])
def test_dict_with_inconsistent_labels(self): with self.assertRaises(ValueError): dimod.as_samples(({'a': -1}, 'b'))
def test_ndarray_labelled(self): arr, labels = dimod.as_samples((np.ones(5, dtype=np.int32), 'abcde')) np.testing.assert_array_equal(arr, np.ones((1, 5))) self.assertEqual(labels, ['a', 'b', 'c', 'd', 'e']) self.assertEqual(arr.dtype, np.int32)
def chain_break_frequency(samples_like, embedding): """Determine the frequency of chain breaks in the given samples. Args: samples_like (samples_like/:obj:`dimod.SampleSet`): A collection of raw samples. 'samples_like' is an extension of NumPy's array_like. See :func:`dimod.as_samples`. embedding (dict): Mapping from source graph to target graph as a dict of form {s: {t, ...}, ...}, where s is a source-model variable and t is a target-model variable. Returns: dict: Frequency of chain breaks as a dict in the form {s: f, ...}, where s is a variable in the source graph, and frequency, a float, is the fraction of broken chains. Examples: This example embeds a single source node, 'a', as a chain of two target nodes (0, 1) and uses :func:`.chain_break_frequency` to show that out of two synthetic samples, one ([-1, +1]) represents a broken chain. >>> import dimod >>> import numpy as np >>> samples = np.array([[-1, +1], [+1, +1]]) >>> embedding = {'a': {0, 1}} >>> print(dimod.chain_break_frequency(samples, embedding)['a']) 0.5 This example embeds a single source node (0) as a chain of two target nodes (a, b) and uses :func:`.chain_break_frequency` to show that out of two samples in a dimod response, one ({'a': 1, 'b': 0}) represents a broken chain. >>> import dimod ... >>> response = dimod.SampleSet.from_samples([{'a': 1, 'b': 0}, {'a': 0, 'b': 0}], ... {'energy': [1, 0]}, {}, dimod.BINARY) >>> embedding = {0: {'a', 'b'}} >>> print(dimod.chain_break_frequency(response, embedding)[0]) 0.5 """ if isinstance(samples_like, dimod.SampleSet): labels = samples_like.variables samples = samples_like.record.sample num_occurrences = samples_like.record.num_occurrences else: samples, labels = dimod.as_samples(samples_like) num_occurrences = np.ones(samples.shape[0]) if not all(v == idx for idx, v in enumerate(labels)): labels_to_idx = {v: idx for idx, v in enumerate(labels)} embedding = { v: {labels_to_idx[u] for u in chain} for v, chain in embedding.items() } if not embedding: return {} variables, chains = zip(*embedding.items()) broken = broken_chains(samples, chains) return { v: float(np.average(broken[:, cidx], weights=num_occurrences)) for cidx, v in enumerate(variables) }
def test_empty_ndarray(self): arr, labels = dimod.as_samples(np.ones(0)) np.testing.assert_array_equal(arr, np.zeros((0, 0))) self.assertEqual(labels, [])
def __call__(self, samples, chains): """ Args: samples (samples_like): A collection of samples. `samples_like` is an extension of NumPy's array_like. See :func:`dimod.as_samples`. chains (list[array_like]): List of chains, where each chain is an array_like collection of the variables in the same order as their represention in the given samples. Returns: tuple: A 2-tuple containing: :obj:`numpy.ndarray`: Unembedded samples as an nS-by-nC array of dtype 'int8', where nC is the number of chains and nS the number of samples. Broken chains are resolved by greedy energy descent. :obj:`numpy.ndarray`: Indicies of the samples. Equivalent to :code:`np.arange(nS)` because all samples are kept and none added. """ samples, labels = dimod.as_samples(samples) if labels != range(len(labels)): relabel = {v: idx for idx, v in enumerate(labels)} chains = [[relabel[v] for v in chain] for chain in chains] else: chains = list(map(list, chains)) # because we use them for indexing chain_to_var = self.chain_to_var variables = [ chain_to_var[frozenset(labels[c] for c in chain)] for chain in chains ] # we want the bqm by index bqm = self.bqm.relabel_variables( {v: idx for idx, v in enumerate(variables)}, inplace=False) num_chains = len(chains) if bqm.vartype is dimod.SPIN: ZERO = -1 else: ZERO = 0 def _minenergy(arr): unbroken_arr = np.zeros((num_chains, ), dtype=np.int8) broken = [] for cidx, chain in enumerate(chains): eq1 = (arr[chain] == 1) if not np.bitwise_xor(eq1.all(), eq1.any()): # not broken unbroken_arr[cidx] = arr[chain][0] else: broken.append(cidx) energies = [] for cidx in broken: en = bqm.linear[cidx] + sum( unbroken_arr[idx] * bqm.adj[cidx][idx] for idx in bqm.adj[cidx]) energies.append([-abs(en), en, cidx]) heapify(energies) while energies: _, e, i = heappop(energies) unbroken_arr[i] = val = ZERO if e > 0 else 1 for energy_triple in energies: k = energy_triple[2] if k in bqm.adj[i]: energy_triple[1] += val * bqm.adj[i][k] energy_triple[0] = -abs(energy_triple[1]) heapify(energies) return unbroken_arr num_samples, num_variables = samples.shape return np.apply_along_axis(_minenergy, 1, samples), np.arange(num_samples)
def test_iterator_labelled(self): with self.assertRaises(TypeError): dimod.as_samples(([-1] for _ in range(10)), 'a')
def time_100x100(self): dimod.as_samples(self.arr100x100)
def test_ndarray(self): arr, labels = dimod.as_samples(np.ones(5, dtype=np.int32)) np.testing.assert_array_equal(arr, np.ones((1, 5))) self.assertEqual(labels, list(range(5))) self.assertEqual(arr.dtype, np.int32)
def sample(self, bqm, **parameters): """Sample the binary quadratic model using reverse annealing from multiple initial states. Args: bqm (:obj:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :obj:`dimod.SampleSet` that has initial_state field. Examples: This example runs 100 reverse anneals each from two initial states on a problem constructed by setting random :math:`\pm 1` values on a clique (complete graph) of 15 nodes, minor-embedded on a D-Wave system using the :class:`.DWaveCliqueSampler` sampler. >>> import dimod >>> from dwave.system import DWaveCliqueSampler, ReverseBatchStatesComposite ... >>> sampler = DWaveCliqueSampler() # doctest: +SKIP >>> sampler_reverse = ReverseBatchStatesComposite(sampler) # doctest: +SKIP >>> schedule = [[0.0, 1.0], [10.0, 0.5], [20, 1.0]] ... >>> bqm = dimod.generators.ran_r(1, 15) >>> init_samples = [{i: -1 for i in range(15)}, {i: 1 for i in range(15)}] >>> sampleset = sampler_reverse.sample(bqm, ... anneal_schedule=schedule, ... initial_states=init_samples, ... num_reads=100, ... reinitialize_state=True) # doctest: +SKIP """ child = self.child if 'initial_states' not in parameters: return child.sample(bqm, **parameters) initial_states = parameters.pop('initial_states') # there is gonna be way too much data generated - better to histogram them if possible if "answer_mode" in child.parameters: parameters['answer_mode'] = 'histogram' # prepare data fields for the new sampleset object vectors = {} for initial_state in initial_states: if not isinstance(initial_state, dict): initial_state = dict(zip(bqm.variables, initial_state)) sampleset = child.sample(bqm, initial_state=initial_state, **parameters) initial_state_, _ = dimod.as_samples(initial_state) vectors = _update_data_vector( vectors, sampleset, { 'initial_state': [initial_state_[0]] * len(sampleset.record.energy) }) samples = vectors.pop('sample') return dimod.SampleSet.from_samples((samples, bqm.variables), bqm.vartype, info={}, **vectors)