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)
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)
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
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'])