diff --git a/docs/conf.py b/docs/conf.py index 50346e02..e11b7419 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -45,7 +45,8 @@ add_module_names = False -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'sdk_index.rst'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'sdk_index.rst', + 'README.rst',] linkcheck_retries = 2 linkcheck_anchors = False @@ -80,8 +81,8 @@ html_sidebars = {"**": ["search-field", "sidebar-nav-bs"]} # remove ads intersphinx_mapping = {'python': ('https://docs.python.org/3', None), - 'networkx': ('https://networkx.github.io/documentation/stable/', None), - 'numpy': ('http://numpy.org/doc/stable/', None), + 'networkx': ('https://networkx.org/documentation/stable/', None), + 'numpy': ('https://numpy.org/doc/stable/', None), 'dwave': ('https://docs.dwavequantum.com/en/latest/', None), } diff --git a/docs/samplers.rst b/docs/samplers.rst index e5ab13c7..dc764c73 100644 --- a/docs/samplers.rst +++ b/docs/samplers.rst @@ -25,7 +25,7 @@ DWaveSampler ============ .. autoclass:: DWaveSampler - :show-inheritance: + :show-inheritance: Properties ---------- @@ -34,27 +34,32 @@ For parameters and properties of D-Wave systems, see the :ref:`qpu_index_solver_properties` and :ref:`qpu_solver_parameters` sections. .. autosummary:: - :toctree: generated/ + :toctree: generated/ - DWaveSampler.properties - DWaveSampler.parameters - DWaveSampler.nodelist - DWaveSampler.edgelist - DWaveSampler.adjacency - DWaveSampler.structure + ~DWaveSampler.adjacency + ~DWaveSampler.edgelist + ~DWaveSampler.nodelist + ~DWaveSampler.parameters + ~DWaveSampler.properties + ~DWaveSampler.structure + ~DWaveSampler.warnings_default Methods ------- .. autosummary:: - :toctree: generated/ + :toctree: generated/ + + ~DWaveSampler.close + ~DWaveSampler.remove_unknown_kwargs + ~DWaveSampler.sample + ~DWaveSampler.sample_ising + ~DWaveSampler.sample_qubo + ~DWaveSampler.to_networkx_graph + ~DWaveSampler.trigger_failover + ~DWaveSampler.valid_bqm_graph + ~DWaveSampler.validate_anneal_schedule - DWaveSampler.sample - DWaveSampler.sample_ising - DWaveSampler.sample_qubo - DWaveSampler.validate_anneal_schedule - DWaveSampler.to_networkx_graph - DWaveSampler.close DWaveCliqueSampler ================== @@ -65,27 +70,29 @@ Properties ---------- .. autosummary:: - :toctree: generated/ - - DWaveCliqueSampler.largest_clique_size - DWaveCliqueSampler.qpu_linear_range - DWaveCliqueSampler.qpu_quadratic_range - DWaveCliqueSampler.properties - DWaveCliqueSampler.parameters - DWaveCliqueSampler.target_graph + :toctree: generated/ + ~DWaveCliqueSampler.largest_clique_size + ~DWaveCliqueSampler.parameters + ~DWaveCliqueSampler.properties + ~DWaveCliqueSampler.qpu_linear_range + ~DWaveCliqueSampler.qpu_quadratic_range + ~DWaveCliqueSampler.target_graph Methods ------- .. autosummary:: - :toctree: generated/ + :toctree: generated/ - DWaveCliqueSampler.largest_clique - DWaveCliqueSampler.sample - DWaveCliqueSampler.sample_ising - DWaveCliqueSampler.sample_qubo - DWaveCliqueSampler.close + ~DWaveCliqueSampler.clique + ~DWaveCliqueSampler.close + ~DWaveCliqueSampler.largest_clique + ~DWaveCliqueSampler.remove_unknown_kwargs + ~DWaveCliqueSampler.sample + ~DWaveCliqueSampler.sample_ising + ~DWaveCliqueSampler.sample_qubo + ~DWaveCliqueSampler.trigger_failover LeapHybridSampler @@ -97,24 +104,25 @@ Properties ---------- .. autosummary:: - :toctree: generated/ - - LeapHybridSampler.properties - LeapHybridSampler.parameters - LeapHybridSampler.default_solver + :toctree: generated/ + ~LeapHybridSampler.default_solver + ~LeapHybridSampler.parameters + ~LeapHybridSampler.properties Methods ------- .. autosummary:: - :toctree: generated/ + :toctree: generated/ + + ~LeapHybridSampler.close + ~LeapHybridSampler.min_time_limit + ~LeapHybridSampler.remove_unknown_kwargs + ~LeapHybridSampler.sample + ~LeapHybridSampler.sample_ising + ~LeapHybridSampler.sample_qubo - LeapHybridSampler.sample - LeapHybridSampler.sample_ising - LeapHybridSampler.sample_qubo - LeapHybridSampler.min_time_limit - LeapHybridSampler.close LeapHybridCQMSampler ==================== @@ -125,21 +133,22 @@ Properties ---------- .. autosummary:: - :toctree: generated/ - - LeapHybridCQMSampler.properties - LeapHybridCQMSampler.parameters + :toctree: generated/ + ~LeapHybridCQMSampler.default_solver + ~LeapHybridCQMSampler.properties + ~LeapHybridCQMSampler.parameters Methods ------- .. autosummary:: - :toctree: generated/ + :toctree: generated/ + + ~LeapHybridCQMSampler.close + ~LeapHybridCQMSampler.min_time_limit + ~LeapHybridCQMSampler.sample_cqm - LeapHybridCQMSampler.sample_cqm - LeapHybridCQMSampler.min_time_limit - LeapHybridCQMSampler.close LeapHybridNLSampler ==================== @@ -150,21 +159,22 @@ Properties ---------- .. autosummary:: - :toctree: generated/ + :toctree: generated/ - LeapHybridNLSampler.properties - LeapHybridNLSampler.parameters - LeapHybridNLSampler.default_solver + ~LeapHybridNLSampler.default_solver + ~LeapHybridNLSampler.parameters + ~LeapHybridNLSampler.properties Methods ------- .. autosummary:: - :toctree: generated/ + :toctree: generated/ + + ~LeapHybridNLSampler.close + ~LeapHybridNLSampler.estimated_min_time_limit + ~LeapHybridNLSampler.sample - LeapHybridNLSampler.sample - LeapHybridNLSampler.estimated_min_time_limit - LeapHybridNLSampler.close LeapHybridDQMSampler ==================== @@ -175,19 +185,18 @@ Properties ---------- .. autosummary:: - :toctree: generated/ - - LeapHybridDQMSampler.properties - LeapHybridDQMSampler.parameters - LeapHybridDQMSampler.default_solver + :toctree: generated/ + ~LeapHybridDQMSampler.default_solver + ~LeapHybridDQMSampler.parameters + ~LeapHybridDQMSampler.properties Methods ------- .. autosummary:: - :toctree: generated/ + :toctree: generated/ - LeapHybridDQMSampler.sample_dqm - LeapHybridDQMSampler.min_time_limit - LeapHybridDQMSampler.close + ~LeapHybridDQMSampler.close + ~LeapHybridDQMSampler.min_time_limit + ~LeapHybridDQMSampler.sample_dqm diff --git a/docs/utilities.rst b/docs/utilities.rst index d54658ea..12039dd2 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -4,6 +4,8 @@ Utilities ========= +.. todo:: add dwave_sampler.qpu_graph post https://github.com/dwavesystems/dwave-system/pull/585 + .. automodule:: dwave.system.utilities .. currentmodule:: dwave.system diff --git a/dwave/system/exceptions.py b/dwave/system/exceptions.py index ca049858..5bb4c49b 100644 --- a/dwave/system/exceptions.py +++ b/dwave/system/exceptions.py @@ -14,12 +14,12 @@ class FailoverCondition(Exception): - """QPU or Solver API call failed with an error that might be mitigated by - retrying on a different solver. + """QPU or :term:`SAPI` call failed with an error that might be mitigated by + retrying on a different :term:`solver`. """ class RetryCondition(FailoverCondition): - """QPU or Solver API call failed with an error that might be mitigated by - retrying on the same solver. + """QPU or :term:`SAPI` call failed with an error that might be mitigated by + retrying (on the same :term:`solver`). """ diff --git a/dwave/system/samplers/clique.py b/dwave/system/samplers/clique.py index 0fcd94ff..272dd948 100644 --- a/dwave/system/samplers/clique.py +++ b/dwave/system/samplers/clique.py @@ -56,10 +56,10 @@ def properties(self): @dimod.decorators.nonblocking_sample_method def sample(self, bqm, **parameters): - """ Scale and sample from the provided binary quadratic model. + """Scale and sample from the provided binary quadratic model. - Problem is scaled based on the per qubit coupling range when - that range is exceeded. + Problem is scaled based on the per qubit coupling range when that range + is exceeded. Args: bqm (:obj:`~dimod.BinaryQuadraticModel`): @@ -99,8 +99,8 @@ def sample(self, bqm, **parameters): max_coupling_range = max(total_coupling_range.values()) if (min_coupling_range < min_lim or max_coupling_range > max_lim): - # scaling - inv_scalar = max(min_coupling_range / min_lim, + # scaling + inv_scalar = max(min_coupling_range / min_lim, max_coupling_range / max_lim) scalar = 1.0 / inv_scalar @@ -131,30 +131,33 @@ def sample(self, bqm, **parameters): class DWaveCliqueSampler(dimod.Sampler): - r"""A sampler for solving clique binary quadratic models on the D-Wave system. + r"""Submits clique binary quadratic models to D-Wave quantum computers. - This sampler wraps - :func:`~minorminer.busclique.find_clique_embedding` to generate embeddings - with even chain length. These embeddings work well for dense - binary quadratic models. For sparse models, using - :class:`.EmbeddingComposite` with :class:`.DWaveSampler` is preferred. + This sampler wraps :func:`~minorminer.busclique.find_clique_embedding` to + generate an :term:`embedding` with even :term:`chain length`. These + embeddings work well for a dense :term:`binary quadratic model`. For sparse + models, using :class:`.EmbeddingComposite` with :class:`.DWaveSampler` is + preferred. Configuration such as :term:`solver` selection is similar to that of :class:`.DWaveSampler`. + :ref:`Clique embeddings ` are cached for each + QPU but the initial finding of embeddings can take several minutes. + Args: failover (bool, optional, default=False): - Signal a failover condition if a sampling error occurs. When ``True``, - raises :exc:`~dwave.system.exceptions.FailoverCondition` or - :exc:`~dwave.system.exceptions.RetryCondition` on sampleset resolve - to signal failover. - - Actual failover, i.e. selection of a new solver, has to be handled - by the user. A convenience method :meth:`.trigger_failover` is available - for this. Note that hardware graphs vary between QPUs, so triggering - failover results in regenerated :attr:`~dimod.Structured.nodelist`, - :attr:`~dimod.Structured.edgelist`, :attr:`.properties` and - :attr:`.parameters`. + Signal a failover condition if a sampling error occurs. When + ``True``, raises :exc:`~dwave.system.exceptions.FailoverCondition` + or :exc:`~dwave.system.exceptions.RetryCondition` on sampleset + :meth:`~dimod.SampleSet.resolve` to signal failover. + Actual failover (i.e., selection of a new solver) has to be handled + by the user. A convenience method :meth:`.trigger_failover` is + available for this. Note that hardware graphs vary between QPUs, so + triggering failover results in regenerated + :attr:`~dwave.system.samplers.DWaveSampler.nodelist`, + :attr:`~dwave.system.samplers.DWaveSampler.edgelist`, + :attr:`.properties` and :attr:`.parameters`. .. versionchanged:: 1.16.0 @@ -172,7 +175,7 @@ class DWaveCliqueSampler(dimod.Sampler): Ignored since 1.16.0. See note for ``failover`` parameter above. **config: - Keyword arguments, as accepted by :class:`.DWaveSampler` + Keyword arguments, as accepted by :class:`.DWaveSampler`. .. versionadded:: 1.29.0 Support for context manager protocol. @@ -209,6 +212,9 @@ class DWaveCliqueSampler(dimod.Sampler): ... sampleset = sampler.sample(bqm, num_reads=100) True + See also: + :class:`~minorminer.busclique.busgraph_cache`. + """ def __init__(self, *, failover: bool = False, retry_interval: Number = -1, @@ -219,12 +225,12 @@ def __init__(self, *, def close(self): """Close the child sampler to release system resources such as threads. - .. note:: + The method blocks for all the currently scheduled work (sampling + requests) to finish. - The method blocks for all the currently scheduled work (sampling - requests) to finish. + See also: + :meth:`~dwave.system.samplers.dwave_sampler.DWaveSampler.close`. - See: :meth:`~dwave.system.samplers.dwave_sampler.DWaveSampler.close`. """ self.child.close() @@ -256,12 +262,19 @@ def properties(self) -> dict: @property def largest_clique_size(self) -> int: - """The maximum number of variables that can be embedded.""" + """Maximum number of variables that can be embedded. + + :ref:`Clique embeddings ` are cached for + each QPU but the initial finding of embeddings can take several minutes. + """ return len(self.largest_clique()) @property def qpu_linear_range(self) -> Tuple[float, float]: - """Range of linear biases allowed by the QPU.""" + """Range of linear biases allowed by the QPU. + + See the :ref:`property_qpu_h_range` QPU property. + """ try: return self._qpu_linear_range except AttributeError: @@ -283,7 +296,10 @@ def qpu_linear_range(self) -> Tuple[float, float]: @property def qpu_quadratic_range(self) -> Tuple[float, float]: - """Range of quadratic biases allowed by the QPU.""" + """Range of quadratic biases allowed by the QPU. + + See the :ref:`property_qpu_extended_j_range` QPU property. + """ try: return self._qpu_quadratic_range except AttributeError: @@ -307,7 +323,7 @@ def qpu_quadratic_range(self) -> Tuple[float, float]: @property def target_graph(self) -> nx.Graph: - """The QPU topology.""" + """Selected QPU's :term:`working graph` in NetworkX format.""" try: return self._target_graph except AttributeError: @@ -331,7 +347,7 @@ def clique(self, variables): return find_clique_embedding(variables, self.target_graph) def largest_clique(self): - """The clique embedding with the maximum number of source variables. + """Return the clique embedding with the maximum number of variables. Returns: dict: The clique embedding with the maximum number of source @@ -365,15 +381,15 @@ def sample(self, bqm, chain_strength=None, **kwargs): Args: bqm (:class:`~dimod.BinaryQuadraticModel`): - Any binary quadratic model with up to + Any :term:`binary quadratic model` with up to :attr:`.largest_clique_size` variables. This BQM is embedded - using a clique embedding. + using a :term:`clique` embedding. chain_strength (float/mapping/callable, optional): Sets the coupling strength between qubits representing variables that form a :term:`chain`. Mappings should specify the required - chain strength for each variable. Callables should accept the BQM - and embedding and return a float or mapping. By default, + chain strength for each variable. Callables should accept the + BQM and embedding and return a float or mapping. By default, ``chain_strength`` is calculated with :func:`~dwave.embedding.chain_strength.uniform_torque_compensation`. @@ -382,14 +398,14 @@ def sample(self, bqm, chain_strength=None, **kwargs): per solver in :attr:`.parameters`. The :ref:`qpu_index_solver_properties` and :ref:`qpu_solver_parameters` sections describe the parameters - and properties supported on the D-Wave - system. Note that ``auto_scale`` is not supported by this - sampler, because it scales the problem as part of the embedding - process. + and properties supported on D-Wave quantum computers. Note that + the :ref:`parameter_qpu_auto_scale` parameter is not supported + by this sampler because it scales the problem as part of the + embedding process. Returns: - :class:`~dimod.SampleSet`: Sample set constructed from a (non-blocking) - :class:`~concurrent.futures.Future`-like object. + :class:`~dimod.SampleSet`: Sample set constructed from a + (non-blocking) :class:`~concurrent.futures.Future`-like object. """ diff --git a/dwave/system/samplers/dwave_sampler.py b/dwave/system/samplers/dwave_sampler.py index f1b88709..237b1d82 100644 --- a/dwave/system/samplers/dwave_sampler.py +++ b/dwave/system/samplers/dwave_sampler.py @@ -14,9 +14,6 @@ """ A :ref:`dimod ` :term:`sampler` for D-Wave quantum computers. - -See :ref:`Ocean Glossary ` -for explanations of technical terms in descriptions of Ocean tools. """ import copy @@ -41,25 +38,31 @@ def qpu_graph(topology_type, topology_shape, nodelist, edgelist): - """Converts node and edge lists to a dwave-networkx compatible graph. + """Convert node and edge lists to a ``dwave-networkx`` graph. - Creates a D-Wave Chimera, Pegasus or Zephyr graph compatible with - dwave-networkx libraries. + Creates a QPU topology (Chimera, Pegasus or Zephyr) graph compatible with + Ocean software's :ref:`index_dnx`. Args: topology_type (string): - The type of lattice. Valid strings are `chimera`, `pegasus` - and `zephyr`. + Type of lattice. Valid strings are `chimera`, `pegasus` and + `zephyr`. topology_shape(iterable of ints): - Specifies dimensions of the lattice. + Dimensions of the lattice. nodelist (list of ints): - List of nodes in the graph. Node labeling is integer, - and compatible with the topology_type linear labeling scheme. + List of nodes in the graph. Node labeling is integer and compatible + with the linear labeling scheme for the specified ``topology_type``. edgelist (list of Tuples): - List of edges in the graph, each edge consisting of a pair - of nodes. + List of edges in the graph, with each edge consisting of a pair of + nodes. + + See also: + :func:`dwave_networkx.chimera_graph`, + :func:`dwave_networkx.pegasus_graph`, + :func:`dwave_networkx.zephyr_graph` for descriptions of the lattice + parameters and indexing. """ - + if topology_type == 'chimera': if not (1 <= len(topology_shape) <=3): raise ValueError('topology_shape is incompatible with a chimera lattice.') @@ -86,27 +89,30 @@ def qpu_graph(topology_type, topology_shape, nodelist, edgelist): class DWaveSampler(dimod.Sampler, dimod.Structured): - """A class for using D-Wave quantum computers as samplers for binary quadratic models. - - You can configure your :term:`solver` selection and usage by setting parameters, - hierarchically, in a configuration file, as environment variables, or - explicitly as input arguments. For more information, see the - :ref:`D-Wave Cloud Client ` package's + r"""Submits binary quadratic models directly to D-Wave quantum computers. + + Linear and quadratic terms of the :term:`binary quadratic model` (BQM) must + map directly to qubit and coupler indices of the selected :term:`QPU`. + Typically this mapping (:term:`minor-embedding`) is handled by software + (e.g., the :class:`.EmbeddingComposite` class) but for small problems can be + manual. + You can configure your :term:`solver` selection and usage by setting + parameters, hierarchically, in a configuration file, as environment + variables, or explicitly as input arguments. For more information, see the :meth:`~dwave.cloud.client.Client.get_solvers` method. By default, online - D-Wave systems are returned ordered by highest number of qubits. + QPUs are returned ordered by highest number of qubits. Args: failover (bool, optional, default=False): - Signal a failover condition if a sampling error occurs. When ``True``, - raises :exc:`~dwave.system.exceptions.FailoverCondition` or - :exc:`~dwave.system.exceptions.RetryCondition` on sampleset resolve - to signal failover. - - Actual failover, i.e. selection of a new solver, has to be handled - by the user. A convenience method :meth:`.trigger_failover` is available - for this. Note that hardware graphs vary between QPUs, so triggering - failover results in regenerated :attr:`.nodelist`, :attr:`.edgelist`, - :attr:`.properties` and :attr:`.parameters`. + Signal a failover condition if a sampling error occurs. When + ``True``, raises :exc:`~dwave.system.exceptions.FailoverCondition` + or :exc:`~dwave.system.exceptions.RetryCondition` on sampleset + :meth:`~dimod.SampleSet.resolve` to signal failover. + Actual failover (i.e., selection of a new solver) has to be handled + by the user. A convenience method :meth:`.trigger_failover` is + available for this. Note that hardware graphs vary between QPUs, so + triggering failover results in regenerated :attr:`.nodelist`, + :attr:`.edgelist`, :attr:`.properties` and :attr:`.parameters`. .. versionchanged:: 1.16.0 @@ -124,7 +130,8 @@ class DWaveSampler(dimod.Sampler, dimod.Structured): Ignored since 1.16.0. See note for ``failover`` parameter above. **config: - Keyword arguments passed to :meth:`~dwave.cloud.client.Client.from_config`. + Keyword arguments passed to + :meth:`~dwave.cloud.client.Client.from_config`. .. versionadded:: 1.29.0 Support for context manager protocol. @@ -151,16 +158,15 @@ class DWaveSampler(dimod.Sampler, dimod.Structured): 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 + adjacent qubits on a :term:`QPU`. ``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. Other required parameters for communication with the system, such - as its URL and an authentication token, are implicitly set in a configuration file - or as environment variables, as described in the - :ref:`ocean_sapi_access_basic` section. - 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). + coupled to it. Other required parameters for communication with the + system, such as its URL and an authentication token, are implicitly set + in a configuration file or as environment variables, as described in the + :ref:`ocean_sapi_access_basic` section. 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 ... @@ -173,9 +179,12 @@ class DWaveSampler(dimod.Sampler, dimod.Structured): ... print(sampleset.first.sample[qubit_a] == 1 and sampleset.first.sample[qubit_b] == -1) True - See the :ref:`index_concepts` section - for explanations of technical terms in descriptions of Ocean tools. + For additional examples, see: + + * :ref:`Beginner examples ` of using + :class:`.DWaveSampler`. + * :ref:`qpu_basic_config`. """ def __init__(self, failover=False, retry_interval=-1, **config): # strongly prefer QPU solvers; requires kwarg-level override @@ -199,12 +208,11 @@ def close(self): """Close the underlying cloud client to release system resources such as threads. - .. note:: - - The method blocks for all the currently scheduled work (sampling - requests) to finish. + The method blocks for all the currently scheduled work (sampling + requests) to finish. - See: :meth:`~dwave.cloud.client.Client.close`. + See also: + :meth:`~dwave.cloud.client.Client.close`. """ self.client.close() @@ -212,7 +220,8 @@ def _get_solver(self, *, refresh: bool = False, penalty: Optional[Dict[str, int] """Get the least penalized solver from the list of solvers filtered and ordered according to user config. - Note: we need to partially replicate :class:`dwave.cloud.Client.get_solver` logic. + Note: we need to partially replicate + :class:`dwave.cloud.Client.get_solver` logic. """ if penalty is None: penalty = {} @@ -232,31 +241,27 @@ def _get_solver(self, *, refresh: bool = False, penalty: Optional[Dict[str, int] raise SolverNotFoundError("Solver with the requested features not available") warnings_default = WarningAction.IGNORE - """Defines the default behavior for :meth:`.sample_ising`'s and - :meth:`sample_qubo`'s `warnings` kwarg. + """Defines default behavior for ``warnings`` keyword arguments of the + :meth:`~DWaveSampler.sample_ising` and :meth:`~DWaveSampler.sample_qubo` + methods. """ @property def properties(self): - """dict: D-Wave solver properties as returned by a SAPI query. + """dict: Solver properties as returned by a :term:`SAPI` query. - Solver properties are dependent on the selected D-Wave solver and subject to change; - for example, new released features may add properties. The + Solver properties are dependent on the selected solver and subject to + change; for example, new features may add properties. The :ref:`qpu_index_solver_properties` and :ref:`qpu_solver_parameters` - sections describe the parameters and properties supported on the D-Wave system. + sections describe the parameters and properties supported on D-Wave + quantum computers. Examples: >>> from dwave.system import DWaveSampler - >>> with DWaveSampler() as sampler: # doctest: +SKIP - ... sampler.properties - {'anneal_offset_ranges': [[-0.2197463755538704, 0.03821687759418928], - [-0.2242514597680286, 0.01718456460967399], - [-0.20860153999435985, 0.05511969218508182], - # Snipped above response for brevity - - See the :ref:`Ocean Glossary ` section - for explanations of technical terms in descriptions of Ocean tools. + >>> with DWaveSampler() as sampler: + ... print(sampler.properties['category']) + qpu """ try: @@ -267,29 +272,25 @@ def properties(self): @property def parameters(self): - """dict[str, list]: D-Wave solver parameters in the form of a dict, where keys are - keyword parameters accepted by a SAPI query and values are lists of properties in + """dict[str, list]: Solver parameters as returned by a :term:`SAPI` + query. + + Keys of the returned dict are keyword parameters accepted by a SAPI + query and values are lists of properties in :attr:`~DWaveSampler.properties` for each key. - Solver parameters are dependent on the selected D-Wave solver and subject to change; - for example, new released features may add parameters. The + Solver parameters are dependent on the selected solver and subject to + change; for example, new features may add parameters. The :ref:`qpu_index_solver_properties` and :ref:`qpu_solver_parameters` - sections describe the parameters and properties supported on the D-Wave system. + sections describe the parameters and properties supported on D-Wave + quantum computers. Examples: >>> from dwave.system import DWaveSampler - >>> with DWaveSampler() as sampler: # doctest: +SKIP - ... sampler.parameters - {'anneal_offsets': ['parameters'], - 'anneal_schedule': ['parameters'], - 'annealing_time': ['parameters'], - 'answer_mode': ['parameters'], - 'auto_scale': ['parameters'], - # Snipped above response for brevity - - See the :ref:`Ocean Glossary ` section - for explanations of technical terms in descriptions of Ocean tools. + >>> with DWaveSampler() as sampler: + ... 'auto_scale' in sampler.parameters + True """ try: @@ -304,18 +305,18 @@ def parameters(self): @property def edgelist(self): - """list: List of active couplers for the D-Wave solver. + """list: List of active couplers for the solver. + + Active couplers are those that are included in the + :ref:`working graph `. Examples: - First 5 entries of the coupler list for one Advantage system. + First coupler for a selected Advantage2 system. >>> from dwave.system import DWaveSampler - >>> with DWaveSampler() as sampler: # doctest: +SKIP - ... sampler.edgelist[:5] - [(30, 31), (30, 45), (30, 2940), (30, 2955), (30, 2970)] - - See the :ref:`index_concepts` section - for explanations of technical terms in descriptions of Ocean tools. + >>> with DWaveSampler(topology_type='zephyr') as sampler: + ... sampler.edgelist[0] + (0, 1) """ # Assumption: cloud client nodes are always integer-labelled @@ -328,18 +329,18 @@ def edgelist(self): @property def nodelist(self): - """list: List of active qubits for the D-Wave solver. + """list: List of active qubits for the solver. + + Active qubits are those that are included in the + :ref:`working graph `. Examples: - First 5 entries of the node list for one Advantage system. + First three qubits for a selected Advantage2 system. >>> from dwave.system import DWaveSampler - >>> with DWaveSampler() as sampler: # doctest: +SKIP - ... sampler.nodelist[:5] - [30, 31, 32, 33, 34] - - See the :ref:`index_concepts` section - for explanations of technical terms in descriptions of Ocean tools. + >>> with DWaveSampler(topology_type='zephyr') as sampler: + ... sampler.nodelist[:3] + [0, 1, 2] """ # Assumption: cloud client nodes are always integer-labelled @@ -385,7 +386,7 @@ def sample(self, bqm, warnings=None, **kwargs): Args: bqm (:class:`~dimod.BinaryQuadraticModel`): - The binary quadratic model. Must match + The :term:`binary quadratic model`. Must match :attr:`~DWaveSampler.nodelist` and :attr:`~DWaveSampler.edgelist`. warnings (:class:`~dwave.system.warnings.WarningAction`, optional): @@ -394,15 +395,16 @@ def sample(self, bqm, warnings=None, **kwargs): ignore warnings. **kwargs: - Optional keyword arguments for the sampling method, specified per solver in - :attr:`.parameters`. The :ref:`qpu_index_solver_properties` and + Optional keyword arguments for the sampling method, specified + per solver in :attr:`.parameters`. The + :ref:`qpu_index_solver_properties` and :ref:`qpu_solver_parameters` sections describe the parameters - and properties supported on the D-Wave system. + and properties supported on D-Wave quantum computers. 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` + :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 :ref:`qpu_sapi_qpu_timing` section. Examples: @@ -425,9 +427,6 @@ def sample(self, bqm, warnings=None, **kwargs): ... print(sampleset.first.sample[qubit_a] == 1 and sampleset.first.sample[qubit_b] == -1) True - See the :ref:`index_concepts` section - for explanations of technical terms in descriptions of Ocean tools. - """ solver = self.solver @@ -499,39 +498,33 @@ def sample_ising(self, h, *args, **kwargs): return super().sample_ising(h, *args, **kwargs) def validate_anneal_schedule(self, anneal_schedule): - """Raise an exception if the specified schedule is invalid for the sampler. + """Raise an exception if the specified schedule is invalid for the + sampler. Args: anneal_schedule (list): - An anneal schedule variation is defined by a series of pairs of floating-point - numbers identifying points in the schedule at which to change slope. The first - element in the pair is time t in microseconds; the second, normalized persistent - current s in the range [0,1]. The resulting schedule is the piecewise-linear curve - that connects the provided points. + An anneal schedule is defined by a series of pairs of + floating-point numbers identifying points in the schedule at + which to change slope. The first element in the pair is time, + :math:`t` in microseconds; the second, normalized anneal + fraction (persistent current) :math:`s` in the range [0,1]. The + resulting schedule is the piecewise-linear curve that connects + the provided points. + + An anneal schedule must satisfy the conditions described in the + :ref:`parameter_qpu_anneal_schedule` section. Raises: - ValueError: If the schedule violates any of the conditions listed below. - - RuntimeError: If the sampler does not accept the `anneal_schedule` parameter or - if it does not have `annealing_time_range` or `max_anneal_schedule_points` - properties. - - As described in the :ref:`qpu_index_solver_properties` section, - an anneal schedule must satisfy the following conditions: - - * Time t must increase for all points in the schedule. - * For forward annealing, the first point must be (0,0) and the anneal fraction s must - increase monotonically. - * For reverse annealing, the anneal fraction s must start and end at s=1. - * In the final point, anneal fraction s must equal 1 and time t must not exceed the - maximum value in the `annealing_time_range` property. - * The number of points must be >=2. - * The upper bound is system-dependent; check the `max_anneal_schedule_points` property. - For reverse annealing, the maximum number of points allowed is one more than the - number given by this property. + ValueError: If the schedule violates any of the conditions + described in the :ref:`parameter_qpu_anneal_schedule` section. + + RuntimeError: If the sampler does not accept the ``anneal_schedule`` + parameter or if it does not have + :ref:`property_qpu_annealing_time_range` or + :ref:`property_qpu_max_anneal_schedule_points` properties. Examples: - This example sets a quench schedule on a D-Wave system. + This example sets a quench schedule on a D-Wave quantum computer. >>> from dwave.system import DWaveSampler >>> with DWaveSampler() as sampler: # doctest: +SKIP @@ -591,25 +584,27 @@ def validate_anneal_schedule(self, anneal_schedule): max_slope = 1.0 / min_anneal_time for (t0, s0), (t1, s1) in zip(anneal_schedule, anneal_schedule[1:]): if round(abs((s0 - s1) / (t0 - t1)),10) > max_slope: - raise ValueError("the maximum slope cannot exceed {}".format(max_slope)) - + raise ValueError("the maximum slope cannot exceed {}".format(max_slope)) + def to_networkx_graph(self): - """Converts DWaveSampler's structure to a Chimera, Pegasus or Zephyr NetworkX graph. + """Output the QPU's :term:`working graph` in NetworkX format. Returns: :class:`networkx.Graph`: - Either a Chimera lattice of shape [m, n, t], a Pegasus - lattice of shape [m] or a Zephyr lattice of size [m,t]. + Either a :ref:`Chimera lattice `, a + :ref:`Pegasus lattice ` or a + :ref:`Zephyr lattice `. Examples: - This example converts a selected D-Wave system solver to a graph - and verifies it has over 5000 nodes. + This example converts a selected :term:`QPU` to a graph and verifies + that it has a greater number of edges (couplers) than nodes + (qubits). >>> from dwave.system import DWaveSampler ... - >>> with DWaveSampler() as sampler: # doctest: +SKIP + >>> with DWaveSampler() as sampler: ... g = sampler.to_networkx_graph() - ... len(g.nodes) > 5000 + ... len(g.edges) > len(g.nodes) True """ return qpu_graph(self.properties['topology']['type'], diff --git a/dwave/system/samplers/leap_hybrid_sampler.py b/dwave/system/samplers/leap_hybrid_sampler.py index 88124824..1f8604fb 100644 --- a/dwave/system/samplers/leap_hybrid_sampler.py +++ b/dwave/system/samplers/leap_hybrid_sampler.py @@ -13,7 +13,8 @@ # limitations under the License. """ -A :ref:`dimod ` :term:`sampler` for Leap's hybrid solvers. +:ref:`dimod ` :term:`samplers ` for the Leap service's +:term:`hybrid` solvers. """ import concurrent.futures @@ -60,51 +61,44 @@ def close(self): class LeapHybridSampler(_ScopedSamplerMixin, dimod.Sampler): - """A class for using Leap's cloud-based hybrid BQM solvers. + r"""Submits binary quadratic models to a hybrid solver in the Leap service. - Leap's quantum-classical hybrid binary quadratic models (BQM) solvers are - intended to solve arbitrary application problems formulated as BQMs. + The :term:`Leap` service's quantum-classical :term:`hybrid` + :term:`binary quadratic model` (BQM) solvers are intended to solve arbitrary + application problems formulated as BQMs. - You can configure your :term:`solver` selection and usage by setting parameters, - hierarchically, in a configuration file, as environment variables, or - explicitly as input arguments, as described in the - :ref:`D-Wave Cloud Client ` package. - - :ref:`dwave-cloud-client `'s - :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers you have - access to by :ref:`solver properties ` - ``category=hybrid`` and ``supported_problem_type=bqm``. By default, online - hybrid BQM solvers are returned ordered by latest ``version``. - - The default specification for filtering and ordering solvers by features is - available as :attr:`.default_solver` property. Explicitly specifying a - solver in a configuration file, an environment variable, or keyword - arguments overrides this specification. See the example below on how to - extend it instead. + You can configure your :term:`solver` selection as described in the + :ref:`cloud_configuration` section.\ [#]_ Args: **config: - Keyword arguments passed to :meth:`~dwave.cloud.client.Client.from_config`. + Keyword arguments passed to + :meth:`~dwave.cloud.client.Client.from_config`. Examples: - This example builds a random sparse graph and uses a hybrid solver to find a - maximum independent set. + This example samples a randomly generated binary quadratic model with 10 + variables and 15 interactions. - >>> import dimod - >>> import networkx as nx - >>> import dwave_networkx as dnx - >>> import numpy as np + >>> from dimod.generators import gnm_random_bqm >>> from dwave.system import LeapHybridSampler ... - >>> # Create a maximum-independent set problem from a random graph - >>> problem_node_count = 300 - >>> G = nx.random_geometric_graph(problem_node_count, radius=0.0005*problem_node_count) - >>> qubo = dnx.algorithms.independent_set.maximum_weighted_independent_set_qubo(G) - >>> bqm = dimod.BQM.from_qubo(qubo) - ... - >>> # Find a good solution + >>> bqm = gnm_random_bqm(10, 15, 'SPIN') >>> with LeapHybridSampler() as sampler: # doctest: +SKIP ... sampleset = sampler.sample(bqm) + + .. [#] + :ref:`dwave-cloud-client `'s + :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers + you have access to by + :ref:`solver properties ` ``category=hybrid`` + and ``supported_problem_type=bqm``. By default, online hybrid BQM + solvers are returned ordered by latest ``version``. + + The default specification for filtering and ordering solvers by features + is available as :attr:`.default_solver` property. Explicitly specifying + a solver in a configuration file, an environment variable, or keyword + arguments overrides this specification. + """ _INTEGER_BQM_SIZE_THRESHOLD = 10000 @@ -147,10 +141,11 @@ def __init__(self, **config): @property def properties(self) -> Dict[str, Any]: - """Solver properties as returned by a SAPI query. + """Solver properties as returned by a :term:`SAPI` query. - :ref:`Solver properties ` - are dependent on the selected solver and subject to change. + :ref:`Solver properties ` are dependent on + the selected solver and subject to change; for example, new features may + add properties. """ try: return self._properties @@ -160,12 +155,15 @@ def properties(self) -> Dict[str, Any]: @property def parameters(self) -> Dict[str, list]: - """Solver parameters in the form of a dict, where keys are - keyword parameters accepted by a SAPI query and values are lists of properties in + """Solver parameters as returned by a :term:`SAPI` query. + + Keys of the returned dict are keyword parameters accepted by a SAPI + query and values are lists of properties in :attr:`~dwave.system.samplers.LeapHybridSampler.properties` for each key. :ref:`Solver parameters ` - are dependent on the selected solver and subject to change. + are dependent on the selected solver and subject to change; for example, + new features may add parameters. """ try: return self._parameters @@ -180,8 +178,8 @@ def sample(self, bqm, time_limit=None, **kwargs): """Sample from the specified binary quadratic model. Args: - bqm (:obj:`dimod.BinaryQuadraticModel`): - Binary quadratic model. + bqm (:obj:`~dimod.binary.BinaryQuadraticModel`): + :term:`Binary quadratic model`. time_limit (int): Maximum run time, in seconds, to allow the solver to work on the @@ -200,21 +198,13 @@ def sample(self, bqm, time_limit=None, **kwargs): :class:`~concurrent.futures.Future`-like object. Examples: - This example builds a random sparse graph and uses a hybrid solver to - find a maximum independent set. + This example samples a randomly generated binary quadratic model + with 10 variables and 15 interactions. - >>> import dimod - >>> import networkx as nx - >>> import dwave_networkx as dnx - >>> import numpy as np - ... - >>> # Create a maximum-independent set problem from a random graph - >>> problem_node_count = 300 - >>> G = nx.random_geometric_graph(problem_node_count, radius=0.0005*problem_node_count) - >>> qubo = dnx.algorithms.independent_set.maximum_weighted_independent_set_qubo(G) - >>> bqm = dimod.BQM.from_qubo(qubo) + >>> from dimod.generators import gnm_random_bqm + >>> from dwave.system import LeapHybridSampler ... - >>> # Find a good solution + >>> bqm = gnm_random_bqm(10, 15, 'SPIN') >>> with LeapHybridSampler() as sampler: # doctest: +SKIP ... sampleset = sampler.sample(bqm) """ @@ -265,20 +255,20 @@ def _sample_large(self, bqm, **kwargs): def min_time_limit(self, bqm): """Return the minimum ``time_limit`` accepted for the given problem. - The minimum time for a hybrid BQM solver is specified as a piecewise-linear - curve defined by a set of floating-point pairs, the ``minimum_time_limit`` - field under :attr:`~dwave.system.samplers.LeapHybridSampler.properties`. - The first element in each pair is the number of problem variables; the - second is the minimum required time. The minimum time for any number of - variables is a linear interpolation calculated on two pairs that represent - the relevant range for the given number of variables. + The minimum time for a hybrid BQM solver is specified as a + piecewise-linear curve defined by a set of floating-point pairs, + the :ref:`property_bqm_minimum_time_limit` property. + + Args: + bqm (:class:`~dimod.binary.BinaryQuadraticModel`): + A :term:`binary quadratic model`. Examples: For a solver where - `LeapHybridSampler().properties["minimum_time_limit"]` returns - `[[1, 0.1], [100, 10.0], [1000, 20.0]]`, the minimum time for a - problem of 50 variables is 5 seconds (the linear interpolation of the - first two pairs that represent problems with between 1 to 100 + ``LeapHybridSampler().properties["minimum_time_limit"]`` returns + ``[[1, 0.1], [100, 10.0], [1000, 20.0]]``, the minimum time for a + problem of 50 variables is 5 seconds (the linear interpolation of + the first two pairs that represent problems with between 1 to 100 variables). """ @@ -289,31 +279,19 @@ def min_time_limit(self, bqm): class LeapHybridDQMSampler(_ScopedSamplerMixin): - """A class for using Leap's cloud-based hybrid DQM solvers. - - Leap's quantum-classical hybrid DQM solvers are intended to solve arbitrary - application problems formulated as **discrete** quadratic models (DQM). + r"""Submits discrete quadratic models to a hybrid solver in the Leap service. - You can configure your :term:`solver` selection and usage by setting parameters, - hierarchically, in a configuration file, as environment variables, or - explicitly as input arguments, as described in the - :ref:`D-Wave Cloud Client ` package. + The :term:`Leap` service's quantum-classical :term:`hybrid` + :term:`discrete quadratic model` (DQM) solvers are intended to solve + arbitrary application problems formulated as DQMs. - :ref:`dwave-cloud-client `'s - :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers you have - access to by :ref:`solver properties ` - ``category=hybrid`` and ``supported_problem_type=dqm``. By default, online - hybrid DQM solvers are returned ordered by latest ``version``. - - The default specification for filtering and ordering solvers by features is - available as :attr:`.default_solver` property. Explicitly specifying a - solver in a configuration file, an environment variable, or keyword - arguments overrides this specification. See the example in :class:`.LeapHybridSampler` - on how to extend it instead. + You can configure your :term:`solver` selection as described in the + :ref:`cloud_configuration` section.\ [#]_ Args: **config: - Keyword arguments passed to :meth:`~dwave.cloud.client.Client.from_config`. + Keyword arguments passed to + :meth:`~dwave.cloud.client.Client.from_config`. Examples: This example solves a small, illustrative problem: a game of @@ -321,8 +299,8 @@ class LeapHybridDQMSampler(_ScopedSamplerMixin): with cases for rock, paper, scissors. Quadratic biases are set to produce a lower value of the DQM for cases of variable ``my_hand`` interacting with cases of variable ``their_hand`` such that the former - wins over the latter; for example, the interaction of ``rock-scissors`` is - set to -1 while ``scissors-rock`` is set to +1. + wins over the latter; for example, the interaction of ``rock-scissors`` + is set to -1 while ``scissors-rock`` is set to +1. >>> import dimod >>> from dwave.system import LeapHybridDQMSampler @@ -349,6 +327,19 @@ class LeapHybridDQMSampler(_ScopedSamplerMixin): ... print(f"{} beats {}".format(cases[sampleset.first.sample['my_hand']], ... cases[sampleset.first.sample['their_hand']])) rock beats scissors + + .. [#] + :ref:`dwave-cloud-client `'s + :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers + you have access to by + :ref:`solver properties ` ``category=hybrid`` + and ``supported_problem_type=dqm``. By default, online hybrid DQM + solvers are returned ordered by latest ``version``. + + The default specification for filtering and ordering solvers by features + is available as :attr:`.default_solver` property. Explicitly specifying + a solver in a configuration file, an environment variable, or keyword + arguments overrides this specification. """ @classproperty @@ -388,10 +379,11 @@ def __init__(self, **config): @property def properties(self) -> Dict[str, Any]: - """Solver properties as returned by a SAPI query. + """Solver properties as returned by a :term:`SAPI` query. - :ref:`Solver properties ` - are dependent on the selected solver and subject to change. + :ref:`Solver properties ` are dependent on + the selected solver and subject to change; for example, new features may + add properties. """ try: return self._properties @@ -401,14 +393,16 @@ def properties(self) -> Dict[str, Any]: @property def parameters(self) -> Dict[str, list]: - """Solver parameters in the form of a dict, where keys - are keyword parameters accepted by a SAPI query and values are lists of - properties in + """Solver parameters as returned by a :term:`SAPI` query. + + Keys of the returned dict are keyword parameters accepted by a SAPI + query and values are lists of properties in :attr:`~dwave.system.samplers.LeapHybridDQMSampler.properties` for each key. :ref:`Solver parameters ` - are dependent on the selected solver and subject to change. + are dependent on the selected solver and subject to change; for example, + new features may add parameters. """ try: return self._parameters @@ -424,28 +418,25 @@ def sample_dqm(self, dqm, time_limit=None, compress=False, compressed=None, **kw """Sample from the specified discrete quadratic model. Args: - dqm (:obj:`dimod.DiscreteQuadraticModel`): - Discrete quadratic model (DQM). - - Note that if `dqm` is a :class:`dimod.CaseLabelDQM`, then - :meth:`~dimod.CaseLabelDQM.map_sample` will need to be used to - restore the case labels in the returned sample set. + dqm (:class:`~dimod.DiscreteQuadraticModel`): + Discrete quadratic model (:term:`DQM`). + If ``dqm`` is a :class:`~dimod.CaseLabelDQM` class, use the + :meth:`~dimod.CaseLabelDQM.map_sample` method to restore case + labels in the returned sample set. time_limit (int, optional): Maximum run time, in seconds, to allow the solver to work on the problem. Must be at least the minimum required for the number of problem variables, which is calculated and set by default. - :meth:`~dwave.system.samplers.LeapHybridDQMSampler.min_time_limit` calculates (and describes) the minimum time for your problem. compress (binary, optional): Compresses the DQM data when set to True. Use if your problem somewhat exceeds the maximum allowed size. Compression tends to - be slow and more effective on homogenous data, which in this - case means it is more likely to help on DQMs with many identical - integer-valued biases than ones with random float-valued biases, - for example. + be slow and more effective on homogenous data; for example, it + is more likely to help on DQMs with many identical + integer-valued biases than ones with random float-valued biases. compressed (binary, optional): Deprecated; please use ``compress`` instead. @@ -508,26 +499,23 @@ def sample_dqm(self, dqm, time_limit=None, compress=False, compressed=None, **kw yield sampleset def min_time_limit(self, dqm): - """Return the minimum `time_limit` accepted for the given problem. + """Return the minimum ``time_limit`` accepted for the given problem. The minimum time for a hybrid DQM solver is specified as a piecewise-linear curve defined by a set of floating-point pairs, - the ``minimum_time_limit`` field under - :attr:`~dwave.system.samplers.LeapHybridDQMSampler.properties`. - The first element in each pair is a combination of the numbers of - interactions, variables, and cases that reflects the "density" of - connectivity between the problem's variables; - the second is the minimum required time. The minimum time for any - particular problem size is a linear interpolation calculated on - two pairs that represent the relevant range for the given problem. + the :ref:`property_dqm_minimum_time_limit` property. + + Args: + dqm (:class:`~dimod.DiscreteQuadraticModel`): + A :term:`discrete quadratic model`. Examples: For a solver where - `LeapHybridDQMSampler().properties["minimum_time_limit"]` returns - `[[1, 0.1], [100, 10.0], [1000, 20.0]]`, the minimum time for a - problem of "density" 50 is 5 seconds (the linear interpolation of the - first two pairs that represent problems with "density" between 1 to - 100). + ``LeapHybridDQMSampler().properties["minimum_time_limit"]`` returns + ``[[1, 0.1], [100, 10.0], [1000, 20.0]]``, the minimum time for a + problem of "density" 50 is 5 seconds (the linear interpolation of + the first two pairs that represent problems with "density" between 1 + to 100). """ ec = (dqm.num_variable_interactions() * dqm.num_cases() / max(dqm.num_variables(), 1)) @@ -537,26 +525,19 @@ def min_time_limit(self, dqm): class LeapHybridCQMSampler(_ScopedSamplerMixin): - """A class for using Leap's cloud-based hybrid CQM solvers. - - Leap's quantum-classical hybrid CQM solvers are intended to solve - application problems formulated as - :ref:`constrained quadratic models (CQM) `. + r"""Submits constrained quadratic models to a hybrid solver in the Leap service. - You can configure your :term:`solver` selection and usage by setting parameters, - hierarchically, in a configuration file, as environment variables, or - explicitly as input arguments, as described in the - :ref:`D-Wave Cloud Client ` package. + The :term:`Leap` service's quantum-classical :term:`hybrid` + :term:`constrained quadratic model` (CQM) solvers are intended to solve + arbitrary application problems formulated as CQMs. - :ref:`dwave-cloud-client `'s - :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers you have - access to by :ref:`solver properties ` - ``category=hybrid`` and ``supported_problem_type=cqm``. By default, online - hybrid CQM solvers are returned ordered by latest ``version``. + You can configure your :term:`solver` selection as described in the + :ref:`cloud_configuration` section.\ [#]_ Args: **config: - Keyword arguments passed to :meth:`~dwave.cloud.client.Client.from_config`. + Keyword arguments passed to + :meth:`~dwave.cloud.client.Client.from_config`. Examples: This example solves a simple problem of finding the rectangle with the @@ -600,6 +581,19 @@ class LeapHybridCQMSampler(_ScopedSamplerMixin): The best (lowest-energy) solution found has :math:`i=j=2` as expected, a solution that is feasible because all the constraints (one in this example) are satisfied. + + .. [#] + :ref:`dwave-cloud-client `'s + :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers + you have access to by + :ref:`solver properties ` ``category=hybrid`` + and ``supported_problem_type=cqm``. By default, online hybrid CQM + solvers are returned ordered by latest ``version``. + + The default specification for filtering and ordering solvers by features + is available as :attr:`.default_solver` property. Explicitly specifying + a solver in a configuration file, an environment variable, or keyword + arguments overrides this specification. """ def __init__(self, **config): @@ -639,10 +633,11 @@ def default_solver(cls) -> Dict[str, str]: @property def properties(self) -> Dict[str, Any]: - """Solver properties as returned by a SAPI query. + """Solver properties as returned by a :term:`SAPI` query. :ref:`Solver properties ` - are dependent on the selected solver and subject to change. + are dependent on the selected solver and subject to change; for example, + new features may add properties. """ try: return self._properties @@ -652,14 +647,16 @@ def properties(self) -> Dict[str, Any]: @property def parameters(self) -> Dict[str, List[str]]: - """Solver parameters in the form of a dict, where keys - are keyword parameters accepted by a SAPI query and values are lists of - properties in + """Solver parameters as returned by a :term:`SAPI` query. + + Keys of the returned dict are keyword parameters accepted by a SAPI + query and values are lists of properties in :attr:`~dwave.system.samplers.LeapHybridCQMSampler.properties` for each key. - :ref:`Solver parameters ` - are dependent on the selected solver and subject to change. + :ref:`Solver parameters ` are dependent on + the selected solver and subject to change; for example, new features may + add parameters. """ try: return self._parameters @@ -675,14 +672,13 @@ def sample_cqm(self, cqm: dimod.ConstrainedQuadraticModel, """Sample from the specified constrained quadratic model. Args: - cqm (:obj:`dimod.ConstrainedQuadraticModel`): - Constrained quadratic model (CQM). + cqm (:obj:`~dimod.ConstrainedQuadraticModel`): + Constrained quadratic model (:term:`CQM`). time_limit (int, optional): Maximum run time, in seconds, to allow the solver to work on the problem. Must be at least the minimum required for the problem, which is calculated and set by default. - :meth:`~dwave.system.samplers.LeapHybridCQMSampler.min_time_limit` calculates (and describes) the minimum time for your problem. @@ -772,7 +768,38 @@ def num_biases(): return self.solver.sample_cqm(sapi_problem_id, time_limit=time_limit, **kwargs).sampleset def min_time_limit(self, cqm: dimod.ConstrainedQuadraticModel) -> float: - """Return the minimum `time_limit`, in seconds, accepted for the given problem.""" + """Return the minimum ``time_limit``, in seconds, accepted for the given + problem. + + This minimum runtime is always at least the minimum specified by the CQM + solver's :ref:`property_cqm_minimum_time_limit_s` property. As the size + and complexity of the CQM increases, the minimum runtime may increase. + This method calculates, for the given CQM, the minimum runtime as a + function of its number of variables, constraints, and biases, weighted + by solver properties such as + :ref:`property_cqm_num_variables_multiplier` and others described in the + :ref:`opt_solver_cqm_properties` section. See the code for the + calculation. + + Args: + cqm (:class:`~dimod.ConstrainedQuadraticModel`): + A :term:`constrained quadratic model`. + + Examples: + This example generates a small CQM that requires only the minimum + runtime of the :ref:`property_cqm_minimum_time_limit_s` property and + a more complex CQM that requires a larger minimum ``time_limit``. + + >>> from dimod.generators import bin_packing + >>> from dwave.system import LeapHybridCQMSampler + ... + >>> cqm = bin_packing([5]*5, 10) + >>> sampler.min_time_limit(cqm) > sampler.properties["minimum_time_limit_s"] # doctest: +SKIP + False + >>> cqm = bin_packing([5]*5, 10) + >>> sampler.min_time_limit(cqm) > sampler.properties["minimum_time_limit_s"] # doctest: +SKIP + True + """ # todo: remove the hard-coded defaults num_variables_multiplier = self.properties.get('num_variables_multiplier', 1.57e-04) @@ -793,31 +820,23 @@ def min_time_limit(self, cqm: dimod.ConstrainedQuadraticModel) -> float: class LeapHybridNLSampler(_ScopedSamplerMixin): - r"""A class for using Leap's cloud-based hybrid nonlinear-model solvers. + r"""Submits nonlinear models to a hybrid solver in the Leap service. - Leap's quantum-classical hybrid nonlinear-model solvers are intended to - solve application problems formulated as - :ref:`nonlinear models `. + The :term:`Leap` service's quantum-classical :term:`hybrid` + :term:`nonlinear model` solvers are intended to solve arbitrary application + problems formulated as :ref:`nonlinear models `. - You can configure your :term:`solver` selection and usage by setting - parameters, hierarchically, in a configuration file, as environment - variables, or explicitly as input arguments, as described in the - :ref:`D-Wave Cloud Client ` package. - - :ref:`dwave-cloud-client `'s - :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers you - have access to by - :ref:`solver properties ` - ``category=hybrid`` and ``supported_problem_type=nl``. By default, online - hybrid nonlinear-model solvers are returned ordered by latest ``version``. + You can configure your :term:`solver` selection as described in the + :ref:`cloud_configuration` section.\ [#]_ Args: **config: - Keyword arguments passed to :meth:`~dwave.cloud.client.Client.from_config`. + Keyword arguments passed to + :meth:`~dwave.cloud.client.Client.from_config`. Examples: This example submits a model for a - :class:`flow-shop-scheduling ` + :func:`flow-shop-scheduling ` problem. >>> from dwave.optimization.generators import flow_shop_scheduling @@ -832,6 +851,20 @@ class LeapHybridNLSampler(_ScopedSamplerMixin): ... f"objective value {model.objective.state(0)} for order " ... f"{job_order.state(0)}.") State 0 of 8 has an objective value 50.0 for order [1. 2. 0.]. + + .. [#] + :ref:`dwave-cloud-client `'s + :meth:`~dwave.cloud.client.Client.get_solvers` method filters solvers + you have access to by + :ref:`solver properties ` ``category=hybrid`` + and ``supported_problem_type=nl``. By default, online hybrid NL + solvers are returned ordered by latest ``version``. + + The default specification for filtering and ordering solvers by features + is available as :attr:`.default_solver` property. Explicitly specifying + a solver in a configuration file, an environment variable, or keyword + arguments overrides this specification. + """ def __init__(self, **config): @@ -869,12 +902,11 @@ def close(self): """Close the underlying cloud client to release system resources such as threads. - .. note:: - - The method blocks for all the currently scheduled work (sampling - requests) to finish. + The method blocks for all the currently scheduled work (sampling + requests) to finish. - See: :meth:`~dwave.cloud.client.Client.close`. + See also: + :meth:`~dwave.cloud.client.Client.close`. """ super().close() self._executor.shutdown() @@ -887,10 +919,11 @@ def default_solver(cls) -> Dict[str, str]: @property def properties(self) -> Dict[str, Any]: - """Solver properties as returned by a SAPI query. + """Solver properties as returned by a :term:`SAPI` query. :ref:`Solver properties ` - are dependent on the selected solver and subject to change. + are dependent on the selected solver and subject to change; for example, + new features may add properties. """ try: return self._properties @@ -900,13 +933,16 @@ def properties(self) -> Dict[str, Any]: @property def parameters(self) -> Dict[str, List[str]]: - """Solver parameters in the form of a dict, where keys - are keyword parameters accepted by a SAPI query and values are lists of - properties in :attr:`~dwave.system.samplers.LeapHybridNLSampler.properties` - for each key. + """Solver parameters as returned by a :term:`SAPI` query. - :ref:`Solver parameters ` - are dependent on the selected solver and subject to change. + Keys of the returned dict are keyword parameters accepted by a SAPI + query and values are lists of properties in + :attr:`~dwave.system.samplers.LeapHybridNLSampler.properties` for each + key. + + :ref:`Solver parameters ` are dependent on + the selected solver and subject to change; for example, new features may + add parameters. """ try: return self._parameters @@ -927,14 +963,13 @@ def sample(self, model: dwave.optimization.Model, """Sample from the specified nonlinear model. Args: - model (:class:`~dwave.optimization.Model`): + model (:class:`~dwave.optimization.model.Model`): Nonlinear model. time_limit (float, optional): Maximum runtime, in seconds, the solver should work on the - problem. Should be at least the estimated minimum required for the - problem, which is calculated and set by default. - + problem. Should be at least the estimated minimum required for + the problem, which is calculated and set by default. :meth:`~dwave.system.samplers.LeapHybridNLSampler.estimated_min_time_limit` estimates the minimum time for your problem. For ``time_limit`` values shorter than the estimated minimum, runtime (and charge @@ -946,8 +981,9 @@ def sample(self, model: dwave.optimization.Model, Returns: :class:`~concurrent.futures.Future` [SampleResult]: - Named tuple, in a Future, containing the nonlinear model and general - result information such as timing and the identity of the problem data. + Named tuple, in a Future, containing the nonlinear model and + general result information such as timing and the identity of + the problem data. .. versionchanged:: 1.31.0 The return value includes timing information as part of the ``info`` @@ -998,9 +1034,15 @@ def collect(): return result def estimated_min_time_limit(self, nlm: dwave.optimization.Model) -> float: - """Return the minimum required time, in seconds, estimated for the given problem. + """Return the minimum required time, in seconds, estimated for the given + problem. + + Runtime (and charge time) is not guaranteed to be shorter than this + minimum time. - Runtime (and charge time) is not guaranteed to be shorter than this minimum time. + Args: + nlm (:class:`~dwave.optimization.model.Model`): + A :term:`nonlinear model`. """ num_nodes_multiplier = self.properties.get('num_nodes_multiplier', 8.306792043756981e-05)