예제 #1
0
 def time_list1000x1000(self):
     dimod.as_samples(self.list1000x1000)
예제 #2
0
 def time_dict1000x1000(self):
     dimod.as_samples(self.dict1000x1000)
예제 #3
0
 def time_empty(self):
     dimod.as_samples([])
예제 #4
0
 def time_empty_labelled(self):
     dimod.as_samples((self.empty, []))
예제 #5
0
 def time_100x100_labelled(self):
     dimod.as_samples((self.arr100x100, self.labels100))
예제 #6
0
    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)]])
예제 #7
0
    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)
예제 #8
0
 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, [])
예제 #9
0
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
예제 #10
0
 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'])
예제 #11
0
 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, [])
예제 #12
0
 def test_dict_with_inconsistent_labels(self):
     with self.assertRaises(ValueError):
         dimod.as_samples(({'a': -1}, 'b'))
예제 #13
0
 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)
예제 #14
0
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)
    }
예제 #15
0
 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, [])
예제 #16
0
    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)
예제 #17
0
 def test_iterator_labelled(self):
     with self.assertRaises(TypeError):
         dimod.as_samples(([-1] for _ in range(10)), 'a')
예제 #18
0
 def time_100x100(self):
     dimod.as_samples(self.arr100x100)
예제 #19
0
 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)
예제 #20
0
    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)