# Copyright 2019 D-Wave Systems Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import enum
import logging
from dwave.cloud.utils.logging import configure_logging
from dwave.inspector.config import config
from dwave.inspector.server import app_server
from dwave.inspector.adapters import (
from_qmi_response, from_bqm_response, from_bqm_sampleset, from_objects,
enable_data_capture)
from dwave.inspector.storage import push_inspector_data
from dwave.inspector.viewers import view
from dwave.inspector.proxies import rewrite_url
from dwave.inspector.package_info import __version__, __author__, __description__
from dwave.inspector.utils import RichDisplayURL # bring back into top-level namespace
# expose the root logger to simplify access and configure it from the env var
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
if config.log_level:
configure_logging(logger, level=config.log_level)
# enable inspector data capture on import!
enable_data_capture()
[docs]
class Block(enum.Enum):
"""Flow-control settings for scripts.
An enum with values: ``NEVER``, ``ONCE``, ``FOREVER``. The default setting of
``once`` (``dwave.inspector.Block.ONCE``) blocks until your problem
is loaded from the inspector web server.
Examples:
This example does not block while the problem is loaded.
>>> dwave.inspector.show(response, block='never') # doctest: +SKIP
"""
NEVER = 'never'
ONCE = 'once'
FOREVER = 'forever'
def open_problem(problem_id, block=Block.ONCE, timeout=None):
"""Open the problem inspector for the specified problem.
Args:
problem_id (str):
Submitted problem identity, as returned by SAPI.
block (:class:`Block`/str/bool, optional, default: :obj:`Block.ONCE`):
Blocking behavior after opening up the web browser preview as set
by :class:`Block` value.
timeout (float):
Blocking behavior timeout in seconds.
Returns:
str:
URL of the inspector application. This URL is opened with the
highest-priority viewer that accepts it.
"""
# accept string name for `block`
if isinstance(block, str):
block = Block(block.lower())
app_server.ensure_started()
url = app_server.get_inspect_url(problem_id)
external_url = rewrite_url(url)
# open url and block
blockable = view(external_url)
if blockable is not False:
if block is Block.ONCE:
app_server.wait_problem_accessed(problem_id, timeout=timeout)
elif block is Block.FOREVER or block is True:
app_server.wait_shutdown(timeout=timeout)
return external_url
[docs]
def show_qmi(problem, response, embedding_context=None, warnings=None, params=None):
"""
Visualize a quantum machine instruction (QMI).
"""
data = from_qmi_response(problem=problem, response=response,
embedding_context=embedding_context,
warnings=warnings, params=params)
id_ = push_inspector_data(data)
return open_problem(id_)
[docs]
def show_bqm_response(bqm, embedding_context, response, warnings=None, params=None):
"""
Visualize a quantum machine instruction (QMI) response and binary quadratic model.
"""
data = from_bqm_response(bqm=bqm, embedding_context=embedding_context,
response=response, warnings=warnings, params=params)
id_ = push_inspector_data(data)
return open_problem(id_)
[docs]
def show_bqm_sampleset(bqm, sampleset, sampler, embedding_context=None,
warnings=None, params=None):
"""
Visualize a returned sampleset and binary quadratic model.
"""
data = from_bqm_sampleset(bqm=bqm, sampleset=sampleset, sampler=sampler,
embedding_context=embedding_context,
warnings=warnings, params=params)
id_ = push_inspector_data(data)
return open_problem(id_)
[docs]
def show(*args, **kwargs):
"""Auto-detect and forward to the ``show_*`` optimal for the specified
arguments.
For description of accepted arguments, see of :func:`.show_qmi`,
:func:`.show_bqm_response`, or :func:`.show_bqm_sampleset`.
Note:
Low-level data capture is enabled on `dwave.inspector` import. Data
captured includes the full quantum machine instruction (QMI), QPU
response, embedding context, warnings, and sampling parameters.
If data capture is enabled prior to embedding/sampling, you need
provide to :func:`~dwave.inspector.show` only a response or problem ID
for QMI inspection or a :class:`~dimod.SampleSet` for logical problem
and QMI inspection.
If data capture is not enabled prior to embedding/sampling, provide
all relevant data explicitly to :func:`~dwave.inspector.show`.
Examples:
This example shows ways to visualize just a QMI (not a logical problem)::
show(response)
show((h, J), response)
show(Q, response)
show('69ace80c-d3b1-448a-a028-b51b94f4a49d')
This example visualizes a QMI and explicit embedding::
show((h, J), response, dict(embedding=embedding, chain_strength=5))
This example shows embedding and warnings read from the sampleset::
show(bqm, sampleset)
This example shows embedding and warnings read from a :class:`~dimod.SampleSet`,
from which the logical problem is reconstructed::
show(sampleset)
"""
block = kwargs.pop('block', Block.ONCE)
timeout = kwargs.pop('timeout', None)
data = from_objects(*args, **kwargs)
id_ = push_inspector_data(data)
return open_problem(id_, block=block, timeout=timeout)