Beispiel #1
0
    def sample_qubo(self, qubo, offset=0, label=None, **params):
        """Sample from the specified :term:`QUBO`.

        Args:
            qubo (dict[(int, int), float]):
                Coefficients of a quadratic unconstrained binary optimization
                (QUBO) problem. Should be a dict of the form `{(u, v): bias, ...}`
                where `u`, `v`, are binary-valued variables and `bias` is their
                associated coefficient.

            offset (optional, default=0):
                Constant offset applied to the model.

            label (str, optional):
                Problem label you can optionally tag submissions with for ease
                of identification.

            **params:
                Parameters for the sampling method, solver-specific.

        Returns:
            :class:`~dwave.cloud.computation.Future`

        Examples:
            This example creates a client using the local system's default D-Wave Cloud Client
            configuration file, which is configured to access a D-Wave 2000Q QPU, submits
            a :term:`QUBO` problem (a Boolean NOT gate represented by a penalty model), and
            samples 5 times.

            >>> from dwave.cloud import Client
            >>> with Client.from_config() as client:  # doctest: +SKIP
            ...     solver = client.get_solver()
            ...     u, v = next(iter(solver.edges))
            ...     Q = {(u, u): -1, (u, v): 0, (v, u): 2, (v, v): -1}
            ...     computation = solver.sample_qubo(Q, num_reads=5)
            ...     for i in range(5):
            ...         print(computation.samples[i][u], computation.samples[i][v])
            ...
            ...
            (0, 1)
            (1, 0)
            (1, 0)
            (0, 1)
            (1, 0)

        """
        linear, quadratic = reformat_qubo_as_ising(qubo)
        return self._sample('qubo',
                            linear,
                            quadratic,
                            offset,
                            params,
                            label=label)
Beispiel #2
0
    def sample_qubo(self, qubo, **params):
        """Sample from the specified :term:`QUBO`.

        Args:
            qubo (dict[(int, int), float]):
                Coefficients of a quadratic unconstrained binary optimization
                (QUBO) model.

            **params:
                Parameters for the sampling method, solver-specific.

        Returns:
            :class:`Future`

        Examples:
            This example creates a client using the local system's default D-Wave Cloud Client
            configuration file, which is configured to access a D-Wave 2000Q QPU, submits
            a :term:`QUBO` problem (a Boolean NOT gate represented by a penalty model), and
            samples 5 times.

            >>> from dwave.cloud import Client
            >>> with Client.from_config() as client:  # doctest: +SKIP
            ...     solver = client.get_solver()
            ...     u, v = next(iter(solver.edges))
            ...     Q = {(u, u): -1, (u, v): 0, (v, u): 2, (v, v): -1}
            ...     computation = solver.sample_qubo(Q, num_reads=5)
            ...     for i in range(5):
            ...         print(computation.samples[i][u], computation.samples[i][v])
            ...
            ...
            (0, 1)
            (1, 0)
            (1, 0)
            (0, 1)
            (1, 0)

        """
        linear, quadratic = reformat_qubo_as_ising(qubo)
        return self._sample('qubo', linear, quadratic, params)
Beispiel #3
0
def from_qmi_response(problem,
                      response,
                      embedding_context=None,
                      warnings=None,
                      params=None,
                      sampleset=None):
    """Construct problem data for visualization based on the low-level sampling
    problem definition and the low-level response.

    Args:
        problem ((list/dict, dict[(int, int), float]) or dict[(int, int), float]):
            Problem in Ising or QUBO form, conforming to solver graph.
            Note: if problem is given as tuple, it is assumed to be in Ising
            variable space, and if given as a dict, Binary variable space is
            assumed. Zero energy offset is always implied.

        response (:class:`dwave.cloud.computation.Future`):
            Sampling response, as returned by the low-level sampling interface
            in the Cloud Client (e.g. :meth:`dwave.cloud.Solver.sample_ising`
            for Ising problems).

        embedding_context (dict, optional):
            A map containing an embedding of logical problem onto the
            solver's graph (the ``embedding`` key) and embedding parameters
            used (e.g. ``chain_strength``).

        warnings (list[dict], optional):
            Optional list of warnings.

        params (dict, optional):
            Sampling parameters used.

        sampleset (:class:`dimod.SampleSet`, optional):
            Optional unembedded sampleset.

    """
    logger.debug("from_qmi_response({!r})".format(
        dict(problem=problem,
             response=response,
             response_energies=response['energies'],
             embedding_context=embedding_context,
             warnings=warnings,
             params=params,
             sampleset=sampleset)))

    try:
        linear, quadratic = problem
    except:
        linear, quadratic = reformat_qubo_as_ising(problem)

    # make sure lin/quad are not dimod views (that handle directed edges)
    if isinstance(linear, BQMView):
        linear = dict(linear)
    if isinstance(quadratic, BQMView):
        quadratic = dict(quadratic)

    solver = response.solver
    if not isinstance(response.solver, StructuredSolver):
        raise TypeError("only structured solvers are supported")

    topology = _get_solver_topology(solver)
    if topology['type'] not in SUPPORTED_SOLVER_TOPOLOGY_TYPES:
        raise TypeError("unsupported solver topology type")

    solver_id = solver.id
    problem_type = response.problem_type

    variables = list(response.variables)
    active = active_qubits(linear, quadratic)

    # filter out invalid values (user's error in problem definition), since
    # SAPI ignores them too
    active = {q for q in active if q in solver.variables}

    # sanity check
    active_variables = response['active_variables']
    assert set(active) == set(active_variables)

    solutions = list(map(itemsgetter(*active_variables),
                         response['solutions']))
    energies = response['energies']
    num_occurrences = response.num_occurrences
    num_variables = solver.num_qubits
    timing = response.timing

    # note: we can't use encode_problem_as_qp(solver, linear, quadratic) because
    # visualizer accepts decoded lists (and nulls instead of NaNs)
    problem_data = {
        "format":
        "qp",  # SAPI non-conforming (nulls vs nans)
        "lin": [
            uniform_get(linear, v, 0 if v in active else None)
            for v in solver._encoding_qubits
        ],
        "quad": [
            quadratic.get((q1, q2), 0) + quadratic.get((q2, q1), 0)
            for (q1, q2) in solver._encoding_couplers
            if q1 in active and q2 in active
        ]
    }

    # include optional embedding
    if embedding_context is not None and 'embedding' in embedding_context:
        problem_data['embedding'] = embedding_context['embedding']

    # try to reconstruct sampling params
    if params is None:
        params = {'num_reads': int(sum(num_occurrences))}

    # expand with defaults
    params = _expand_params(solver, params, timing)

    # construct problem stats
    problem_stats = _problem_stats(response=response,
                                   sampleset=sampleset,
                                   embedding_context=embedding_context)

    data = {
        "ready":
        True,
        "details":
        _details_dict(response),
        "data":
        _problem_dict(solver_id, problem_type, problem_data, params,
                      problem_stats),
        "answer":
        _answer_dict(solutions, active_variables, energies, num_occurrences,
                     timing, num_variables),
        "warnings":
        _warnings(warnings),
        "rel":
        dict(solver=solver),
    }

    if sampleset is not None:
        data["unembedded_answer"] = _unembedded_answer_dict(sampleset)

    logger.trace("from_qmi_response returned %r", data)

    return data
Beispiel #4
0
    def verify_data_encoding(self,
                             problem,
                             response,
                             solver,
                             params,
                             data,
                             embedding_context=None):
        # avoid persistent data modification
        data = data.copy()

        # make sure data correct after JSON decoding (minus the 'rel' data)
        del data['rel']
        data = json.loads(json.dumps(data))

        # test structure
        self.assertIsInstance(data, dict)
        self.assertTrue(
            all(k in data for k in 'details data answer warnings'.split()))

        # .details
        self.assertIn('id', data['details'])
        self.assertIn('label', data['details'])
        self.assertEqual(data['details']['solver'], solver.id)

        # .problem
        self.assertEqual(data['data']['type'], response.problem_type)

        # .problem.params, smoke tests
        self.assertIn('params', data['data'])
        self.assertEqual(data['data']['params']['num_reads'],
                         params['num_reads'])
        self.assertIn('annealing_time', data['data']['params'])
        self.assertIn('programming_thermalization', data['data']['params'])

        if response.problem_type == 'ising':
            linear, quadratic = problem
        elif response.problem_type == 'qubo':
            linear, quadratic = reformat_qubo_as_ising(problem)
        else:
            self.fail("Unknown problem type")

        active_variables = response['active_variables']
        problem_data = {
            "format":
            "qp",
            "lin": [
                uniform_get(linear, v, 0 if v in active_variables else None)
                for v in solver._encoding_qubits
            ],
            "quad": [
                quadratic.get((q1, q2), 0) + quadratic.get((q2, q1), 0)
                for (q1, q2) in solver._encoding_couplers
                if q1 in active_variables and q2 in active_variables
            ]
        }
        if embedding_context is not None:
            problem_data['embedding'] = embedding_context['embedding']
        self.assertDictEqual(data['data']['data'], problem_data)

        # .answer
        self.assertEqual(sum(data['answer']['num_occurrences']),
                         params['num_reads'])
        self.assertEqual(data['answer']['num_occurrences'],
                         response['num_occurrences'])
        self.assertEqual(data['answer']['num_variables'],
                         response['num_variables'])
        self.assertEqual(data['answer']['active_variables'], active_variables)
        solutions = [[sol[idx] for idx in active_variables]
                     for sol in response['solutions']]
        self.assertEqual(data['answer']['solutions'], solutions)
        self.assertEqual(data['answer']['energies'], response['energies'])
        self.assertEqual(data['answer']['timing'], response['timing'])