Beispiel #1
0
def from_bqm_response(bqm,
                      embedding_context,
                      response,
                      warnings=None,
                      params=None,
                      sampleset=None):
    """Construct problem data for visualization based on the unembedded BQM,
    the embedding used when submitting, and the low-level sampling response.

    Args:
        bqm (:class:`dimod.BinaryQuadraticModel`/:class:`dimod.core.bqm.BQM`):
            Problem in logical (unembedded) space, given as a BQM.

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

        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).

        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_bqm_response({!r})".format(
        dict(bqm=bqm,
             response=response,
             response_energies=response['energies'],
             embedding_context=embedding_context,
             warnings=warnings,
             params=params,
             sampleset=sampleset)))

    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

    active_variables = response['active_variables']
    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

    # bqm vartype must match response vartype
    if problem_type == "ising":
        bqm = bqm.change_vartype(dimod.SPIN, inplace=False)
    else:
        bqm = bqm.change_vartype(dimod.BINARY, inplace=False)

    # get embedding parameters
    if 'embedding' not in embedding_context:
        raise ValueError("embedding not given")
    embedding = embedding_context.get('embedding')
    chain_strength = embedding_context.get('chain_strength')
    chain_break_method = embedding_context.get('chain_break_method')

    # if `embedding` is `dwave.embedding.transforms.EmbeddedStructure`, we don't
    # need `target_adjacency`
    emb_params = dict(embedding=embedding)
    if not hasattr(embedding, 'embed_bqm'):
        # proxy for detecting dict vs. EmbeddedStructure, without actually
        # importing EmbeddedStructure (did not exist in dwave-system<0.9.10)
        target_adjacency = edgelist_to_adjacency(solver.edges)
        emb_params.update(target_adjacency=target_adjacency)

    # get embedded bqm
    bqm_embedded = embed_bqm(bqm,
                             chain_strength=chain_strength,
                             smear_vartype=dimod.SPIN,
                             **emb_params)

    linear, quadratic, offset = bqm_embedded.to_ising()
    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
        ],
        "embedding":
        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)

    # TODO: if warnings are missing, calculate them here (since we have the
    # low-level response)

    # 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_bqm_response returned %r", data)

    return data
Beispiel #2
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
    def test_one(self):
        obj = list(range(3))
        f = itemsgetter(1)

        self.assertTrue(callable(f))
        self.assertEqual(f(obj), (obj[1], ))
    def test_multi(self):
        obj = list(range(3))
        f = itemsgetter(0, 2)

        self.assertTrue(callable(f))
        self.assertEqual(f(obj), (obj[0], obj[2]))
 def test_nil(self):
     with self.assertRaises(TypeError):
         itemsgetter()