Exemple #1
0
    def sample(self,
               bqm,
               chain_strength=None,
               chain_break_method=None,
               chain_break_fraction=True,
               embedding_parameters=None,
               return_embedding=None,
               warnings=None,
               **parameters):
        """Sample from the provided binary quadratic model.

        Args:
            bqm (:obj:`dimod.BinaryQuadraticModel`):
                Binary quadratic model to be sampled from.

            chain_strength (float/mapping/callable, optional):
                Magnitude of the quadratic bias (in SPIN-space) applied between
                variables to create chains. The energy penalty of chain breaks
                is 2 * `chain_strength`.  If a mapping is passed, a
                chain-specific strength is applied.  If a callable is passed, it
                will be called on `chain_strength(bqm, embedding)` and should
                return a float or mapping, to be interpreted as above. By default,
                `chain_strength` is calculated with 
                :func:`~dwave.embedding.chain_strength.uniform_torque_compensation`.

            chain_break_method (function/list, optional):
                Method or methods used to resolve chain breaks. If multiple
                methods are given, the results are concatenated and a new field
                called "chain_break_method" specifying the index of the method
                is appended to the sample set.
                See :func:`~dwave.embedding.unembed_sampleset` and
                :mod:`dwave.embedding.chain_breaks`.

            chain_break_fraction (bool, optional, default=True):
                Add a `chain_break_fraction` field to the unembedded response with
                the fraction of chains broken before unembedding.

            embedding_parameters (dict, optional):
                If provided, parameters are passed to the embedding method as
                keyword arguments. Overrides any `embedding_parameters` passed
                to the constructor.

            return_embedding (bool, optional):
                If True, the embedding, chain strength, chain break method and
                embedding parameters are added to :attr:`dimod.SampleSet.info`
                of the returned sample set. The default behaviour is defined
                by :attr:`return_embedding_default`, which itself defaults to
                False.

            warnings (:class:`~dwave.system.warnings.WarningAction`, optional):
                Defines what warning action to take, if any. See
                :mod:`~dwave.system.warnings`. The default behaviour is defined
                by :attr:`warnings_default`, which itself defaults to
                :class:`~dwave.system.warnings.IGNORE`

            **parameters:
                Parameters for the sampling method, specified by the child
                sampler.

        Returns:
            :obj:`dimod.SampleSet`

        Examples:
            See the example in :class:`EmbeddingComposite`.

        """
        if return_embedding is None:
            return_embedding = self.return_embedding_default

        # solve the problem on the child system
        child = self.child

        # apply the embedding to the given problem to map it to the child sampler
        __, target_edgelist, target_adjacency = self.target_structure

        # add self-loops to edgelist to handle singleton variables
        source_edgelist = list(bqm.quadratic) + [(v, v) for v in bqm.linear]

        # get the embedding
        if embedding_parameters is None:
            embedding_parameters = self.embedding_parameters
        else:
            # we want the parameters provided to the constructor, updated with
            # the ones provided to the sample method. To avoid the extra copy
            # we do an update, avoiding the keys that would overwrite the
            # sample-level embedding parameters
            embedding_parameters.update(
                (key, val) for key, val in self.embedding_parameters
                if key not in embedding_parameters)

        embedding = self.find_embedding(source_edgelist, target_edgelist,
                                        **embedding_parameters)

        if bqm and not embedding:
            raise ValueError("no embedding found")

        if not hasattr(embedding, 'embed_bqm'):
            embedding = EmbeddedStructure(target_edgelist, embedding)

        bqm_embedded = embedding.embed_bqm(bqm,
                                           chain_strength=chain_strength,
                                           smear_vartype=dimod.SPIN)

        if warnings is None:
            warnings = self.warnings_default
        elif 'warnings' in child.parameters:
            parameters.update(warnings=warnings)

        warninghandler = WarningHandler(warnings)

        warninghandler.chain_strength(bqm, embedding.chain_strength, embedding)
        warninghandler.chain_length(embedding)

        if 'initial_state' in parameters:
            # if initial_state was provided in terms of the source BQM, we want
            # to modify it to now provide the initial state for the target BQM.
            # we do this by spreading the initial state values over the
            # chains
            state = parameters['initial_state']
            parameters['initial_state'] = {
                u: state[v]
                for v, chain in embedding.items() for u in chain
            }

        if self.scale_aware and 'ignored_interactions' in child.parameters:

            ignored = []
            for chain in embedding.values():
                # just use 0 as a null value because we don't actually need
                # the biases, just the interactions
                ignored.extend(chain_to_quadratic(chain, target_adjacency, 0))

            parameters['ignored_interactions'] = ignored

        response = child.sample(bqm_embedded, **parameters)

        def async_unembed(response):
            # unembed the sampleset aysnchronously.

            warninghandler.chain_break(response, embedding)

            sampleset = unembed_sampleset(
                response,
                embedding,
                source_bqm=bqm,
                chain_break_method=chain_break_method,
                chain_break_fraction=chain_break_fraction,
                return_embedding=return_embedding)

            if return_embedding:
                sampleset.info['embedding_context'].update(
                    embedding_parameters=embedding_parameters,
                    chain_strength=embedding.chain_strength)

            if chain_break_fraction and len(sampleset):
                warninghandler.issue(
                    "All samples have broken chains",
                    func=lambda:
                    (sampleset.record.chain_break_fraction.all(), None))

            if warninghandler.action is WarningAction.SAVE:
                # we're done with the warning handler so we can just pass the list
                # off, if later we want to pass in a handler or similar we should
                # do a copy
                sampleset.info.setdefault('warnings',
                                          []).extend(warninghandler.saved)

            return sampleset

        return dimod.SampleSet.from_future(response, async_unembed)
Exemple #2
0
    def sample(self, bqm, warnings=None, **kwargs):
        """Sample from the specified binary quadratic model.

        Args:
            bqm (:class:`~dimod.BinaryQuadraticModel`):
                The binary quadratic model. Must match :attr:`.nodelist` and
                :attr:`.edgelist`.

            warnings (:class:`~dwave.system.warnings.WarningAction`, optional):
                Defines what warning action to take, if any. See
                :ref:`warnings_system`. The default behaviour is to
                ignore warnings.

            **kwargs:
                Optional keyword arguments for the sampling method, specified per solver in
                :attr:`.parameters`. D-Wave System Documentation's
                `solver guide <https://docs.dwavesys.com/docs/latest/doc_solver_ref.html>`_
                describes the parameters and properties supported on the D-Wave system.

        Returns:
            :class:`~dimod.SampleSet`: Sample set constructed from a (non-blocking)
            :class:`~concurrent.futures.Future`-like object.
            In it this sampler also provides timing information in the `info`
            field as described in the D-Wave System Documentation's
            :ref:`sysdocs_gettingstarted:qpu_sapi_qpu_timing`.

        Examples:
            This example submits a two-variable Ising problem mapped directly to two
            adjacent qubits on a D-Wave system. ``qubit_a`` is the first qubit in
            the QPU's indexed list of qubits and ``qubit_b`` is one of the qubits
            coupled to it. Given sufficient reads (here 100), the quantum
            computer should return the best solution, :math:`{1, -1}` on ``qubit_a`` and
            ``qubit_b``, respectively, as its first sample (samples are ordered from
            lowest energy).

            >>> from dwave.system import DWaveSampler
            ...
            >>> sampler = DWaveSampler()
            ...
            >>> qubit_a = sampler.nodelist[0]
            >>> qubit_b = next(iter(sampler.adjacency[qubit_a]))
            >>> sampleset = sampler.sample_ising({qubit_a: -1, qubit_b: 1},
            ...                                  {},
            ...                                  num_reads=100)
            >>> sampleset.first.sample[qubit_a] == 1 and sampleset.first.sample[qubit_b] == -1
            True

        See `Ocean Glossary <https://docs.ocean.dwavesys.com/en/stable/concepts/index.html>`_
        for explanations of technical terms in descriptions of Ocean tools.

        """

        solver = self.solver

        try:
            future = solver.sample_bqm(bqm, **kwargs)
        except ProblemStructureError as exc:
            msg = ("Problem graph incompatible with solver. Please use 'EmbeddingComposite' "
                   "to map the problem graph to the solver.")
            raise BinaryQuadraticModelStructureError(msg) from exc

        if warnings is None:
            warnings = self.warnings_default
        warninghandler = WarningHandler(warnings)
        warninghandler.energy_scale(bqm)

        # need a hook so that we can check the sampleset (lazily) for
        # warnings
        def _hook(computation):
            sampleset = computation.sampleset

            if warninghandler is not None:
                warninghandler.too_few_samples(sampleset)
                if warninghandler.action is WarningAction.SAVE:
                    sampleset.info['warnings'] = warninghandler.saved

            return sampleset

        return dimod.SampleSet.from_future(future, _hook)
Exemple #3
0
    def sample_qubo(self, Q, warnings=None, **kwargs):
        """Sample from the specified QUBO.

        Args:
            Q (dict):
                Coefficients of a quadratic unconstrained binary optimization (QUBO) model.

            warnings (:class:`~dwave.system.warnings.WarningAction`, optional):
                Defines what warning action to take, if any. See
                :mod:`~dwave.system.warnings`. The default behaviour is defined
                by :attr:`warnings_default`, which itself defaults to
                :class:`~dwave.system.warnings.IGNORE`

            **kwargs:
                Optional keyword arguments for the sampling method, specified per solver in
                :attr:`.DWaveSampler.parameters`. D-Wave System Documentation's
                `solver guide <https://docs.dwavesys.com/docs/latest/doc_solver_ref.html>`_
                describes the parameters and properties supported on the D-Wave system.

        Returns:
            :class:`dimod.SampleSet`: A `dimod` :obj:`~dimod.SampleSet` object.
            In it this sampler also provides timing information in the `info`
            field as described in the D-Wave System Documentation's
            `timing guide <https://docs.dwavesys.com/docs/latest/doc_timing.html>`_.

        Examples:
            This example submits a two-variable QUBO mapped directly to qubits
            0 and 4 on a D-Wave system.

            >>> from dwave.system.samplers import DWaveSampler
            >>> sampler = DWaveSampler()
            >>> Q = {(0, 0): -1, (4, 4): -1, (0, 4): 2}
            >>> sampleset = sampler.sample_qubo(Q)
            >>> for sample in sampleset.samples():    # doctest: +SKIP
            ...    print(sample)
            ...
            {0: 0, 4: 1}

        See `Ocean Glossary <https://docs.ocean.dwavesys.com/en/latest/glossary.html>`_
        for explanations of technical terms in descriptions of Ocean tools.

        """

        # developer note: in the future we should probably catch exceptions
        # from the cloud client, but for now this is simpler/cleaner. We use
        # the solver's nodes/edges because they are a set, so faster lookup
        nodes = self.solver.nodes
        edges = self.solver.edges
        if not all(u in nodes if u == v else ((u, v) in edges or (v, u) in edges)
                   for u, v in Q):
            msg = "Problem graph incompatible with solver."
            raise BinaryQuadraticModelStructureError(msg)

        future = self.solver.sample_qubo(Q, **kwargs)

        # do as much as possible after the future is returned

        variables = set().union(*Q)

        if warnings is None:
            warnings = self.warnings_default
        warninghandler = WarningHandler(warnings)
        warninghandler.energy_scale((Q,))

        hook = _result_to_response_hook(variables, dimod.BINARY, warninghandler)
        return dimod.SampleSet.from_future(future, hook)
Exemple #4
0
    def sample(self, bqm, warnings=None, **kwargs):
        """Sample from the specified Ising model.

        Args:
            bqm (:class:`~dimod.BinaryQuadraticModel`):
                The binary quadratic model. Must match :attr:`.nodelist` and
                :attr:`.edgelist`.

            warnings (:class:`~dwave.system.warnings.WarningAction`, optional):
                Defines what warning action to take, if any. See
                :mod:`~dwave.system.warnings`. The default behaviour is defined
                by :attr:`warnings_default`, which itself defaults to
                :class:`~dwave.system.warnings.IGNORE`

            **kwargs:
                Optional keyword arguments for the sampling method, specified per solver in
                :attr:`.DWaveSampler.parameters`. D-Wave System Documentation's
                `solver guide <https://docs.dwavesys.com/docs/latest/doc_solver_ref.html>`_
                describes the parameters and properties supported on the D-Wave system.

        Returns:
            :class:`dimod.SampleSet`: A `dimod` :obj:`~dimod.SampleSet` object.
            In it this sampler also provides timing information in the `info`
            field as described in the D-Wave System Documentation's
            `timing guide <https://docs.dwavesys.com/docs/latest/doc_timing.html>`_.

        Examples:
            This example submits a two-variable Ising problem mapped directly to qubits
            0 and 1 on a D-Wave system. Given sufficient reads (here 100), the quantum
            computer should return the best solution, :math:`{1, -1}` on qubits 0 and 1,
            respectively, as its first sample (samples are ordered from lowest energy).

            >>> from dwave.system import DWaveSampler
            >>> sampler = DWaveSampler(solver={'qubits__issuperset': {0, 1}})
            >>> sampleset = sampler.sample_ising({0: -1, 1: 1}, {}, num_reads=100)
            >>> sampleset.first.sample[0] == 1 and sampleset.first.sample[1] == -1
            True

        See `Ocean Glossary <https://docs.ocean.dwavesys.com/en/latest/glossary.html>`_
        for explanations of technical terms in descriptions of Ocean tools.

        """

        solver = self.solver

        if not (solver.nodes.issuperset(bqm.linear)
                and solver.edges.issuperset(bqm.quadratic)):
            msg = "Problem graph incompatible with solver."
            raise BinaryQuadraticModelStructureError(msg)

        future = solver.sample_bqm(bqm, **kwargs)

        if warnings is None:
            warnings = self.warnings_default
        warninghandler = WarningHandler(warnings)
        warninghandler.energy_scale(bqm)

        # need a hook so that we can check the sampleset (lazily) for
        # warnings
        def _hook(computation):
            sampleset = computation.sampleset

            if warninghandler is not None:
                warninghandler.too_few_samples(sampleset)
                if warninghandler.action is WarningAction.SAVE:
                    sampleset.info['warnings'] = warninghandler.saved

            return sampleset

        return dimod.SampleSet.from_future(future, _hook)
Exemple #5
0
    def sample_ising(self, h, J, warnings=None, **kwargs):
        """Sample from the specified Ising model.

        Args:
            h (dict/list):
                Linear biases of the Ising model. If a dict, should be of the
                form `{v: bias, ...}` where `v` is a spin-valued variable and
                `bias` is its associated bias. If a list, it is treated as a
                list of biases where the indices are the variable labels,
                except in the case of missing qubits in which case 0 biases are
                ignored while a non-zero bias set on a missing qubit raises an
                error.

            J (dict[(int, int): float]):
                Quadratic biases of the Ising model.

            warnings (:class:`~dwave.system.warnings.WarningAction`, optional):
                Defines what warning action to take, if any. See
                :mod:`~dwave.system.warnings`. The default behaviour is defined
                by :attr:`warnings_default`, which itself defaults to
                :class:`~dwave.system.warnings.IGNORE`

            **kwargs:
                Optional keyword arguments for the sampling method, specified per solver in
                :attr:`.DWaveSampler.parameters`. D-Wave System Documentation's
                `solver guide <https://docs.dwavesys.com/docs/latest/doc_solver_ref.html>`_
                describes the parameters and properties supported on the D-Wave system.

        Returns:
            :class:`dimod.SampleSet`: A `dimod` :obj:`~dimod.SampleSet` object.
            In it this sampler also provides timing information in the `info`
            field as described in the D-Wave System Documentation's
            `timing guide <https://docs.dwavesys.com/docs/latest/doc_timing.html>`_.

        Examples:
            This example submits a two-variable Ising problem mapped directly to qubits
            0 and 1 on a D-Wave system.

            >>> from dwave.system.samplers import DWaveSampler
            >>> sampler = DWaveSampler()
            >>> sampleset = sampler.sample_ising({0: -1, 1: 1}, {})
            >>> for sample in sampleset.samples():    # doctest: +SKIP
            ...    print(sample)
            ...
            {0: 1, 1: -1}

        See `Ocean Glossary <https://docs.ocean.dwavesys.com/en/latest/glossary.html>`_
        for explanations of technical terms in descriptions of Ocean tools.

        """
        nodes = self.solver.nodes  # set rather than .nodelist which is a list

        if isinstance(h, list):
            # to be consistent with the cloud-client, we ignore the 0 biases
            # on missing nodes.
            h = dict((v, b) for v, b in enumerate(h) if b or v in nodes)

        # developer note: in the future we should probably catch exceptions
        # from the cloud client, but for now this is simpler/cleaner. We use
        # the solver's nodes/edges because they are a set, so faster lookup
        edges = self.solver.edges
        if not (all(v in nodes for v in h) and
                all((u, v) in edges or (v, u) in edges for u, v in J)):
            msg = "Problem graph incompatible with solver."
            raise BinaryQuadraticModelStructureError(msg)

        future = self.solver.sample_ising(h, J, **kwargs)

        # do as much as possible after the future is returned

        variables = set(h).union(*J)

        if warnings is None:
            warnings = self.warnings_default
        warninghandler = WarningHandler(warnings)
        warninghandler.energy_scale((h, J))

        hook = _result_to_response_hook(variables, dimod.SPIN, warninghandler)
        return dimod.SampleSet.from_future(future, hook)