# この時点でIsing形式用のJ, h, BINARY形式用のQが生成済みである。 # ISING形式の場合 #bqm = dimod.BinaryQuadraticModel.from_ising(h, J) # BINARY形式の場合 bqm = dimod.BinaryQuadraticModel.from_qubo(Q) url = "https://cloud.dwavesys.com/sapi" token = "your_token" solver_name = "DW_2000Q_5" sampler = DWaveSampler(endpoint=url, token=token, solver=solver_name) # minorminerでエンベディング embedding = minorminer.find_embedding(S, sampler.edgelist) bqm_embed = embed_bqm(bqm, embedding, sampler.adjacency) # D-Waveによるサンプリング result = sampler.sample(bqm_embed, num_reads=1000, postprocess="optimization", beta=3.0) # minimize energyによる後処理 cbm = MinimizeEnergy(bqm, embedding) unembedded, idx = cbm(result, list(embedding.values())) # アンエンベッドされた解に関して、エネルギーの再計算や重複解などの整理をする # 出力結果はdimod.SampleSetの形式 (Ocean SDKによる他のサンプリング結果と同じデータ形式) sample = dimod.SampleSet.from_samples_bqm(unembedded, bqm, num_occurrences=result.record['num_occurrences']).aggregate() # 出力のテンプレート print(sample) print(sample.record['sample'])
# Confirm that a P variable has been removed from the BQM, for example, "p0" print("Variable p0 in BQM: ", 'p0' in bqm) print("Variable a0 in BQM: ", 'a0' in bqm) # Use a D-Wave system as the sampler # sampler = DWaveSampler(solver={'qpu': True}) # Some accounts need to replace this line with the next: sampler = DWaveSampler(solver='DW_2000Q_2_1', token='DEV-289c9dcb0d1d85f3a9059f77fd53bc84e3935d52') _, target_edgelist, target_adjacency = sampler.structure # Find an embedding embedding = minorminer.find_embedding(bqm.quadratic, target_edgelist) if bqm and not embedding: raise ValueError("no embedding found") bqm_embedded = embed_bqm(bqm, embedding, target_adjacency, 3.0) # Confirm mapping of variables from a0, b0, etc to indexed qubits print("Variable a0 in embedded BQM: ", 'a0' in bqm_embedded) print("First five nodes in QPU graph: ", sampler.structure.nodelist[:5]) kwargs = {} if 'num_reads' in sampler.parameters: kwargs['num_reads'] = 5 if 'answer_mode' in sampler.parameters: kwargs['answer_mode'] = 'histogram' # Request num_reads samples kwargs['num_reads'] = 1000 response = sampler.sample(bqm_embedded, **kwargs)
def sample(self, bqm, chain_strength=1.0, chain_break_method=None, chain_break_fraction=True, embedding_parameters=None, return_embedding=None, warnings=None, **parameters): """Sample from the provided binary quadratic model. Args: bqm (:obj:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. chain_strength (float, optional, default=1.0): Magnitude of the quadratic bias (in SPIN-space) applied between variables to create chains. The energy penalty of chain breaks is 2 * `chain_strength`. chain_break_method (function, optional): Method used to resolve chain breaks during sample unembedding. See :func:`~dwave.embedding.unembed_sampleset`. chain_break_fraction (bool, optional, default=True): Add a `chain_break_fraction` field to the unembedded response with the fraction of chains broken before unembedding. embedding_parameters (dict, optional): If provided, parameters are passed to the embedding method as keyword arguments. Overrides any `embedding_parameters` passed to the constructor. return_embedding (bool, optional): If True, the embedding, chain strength, chain break method and embedding parameters are added to :attr:`dimod.SampleSet.info` of the returned sample set. The default behaviour is defined by :attr:`return_embedding_default`, which itself defaults to False. warnings (:class:`~dwave.system.warnings.WarningAction`, optional): Defines what warning action to take, if any. See :mod:`~dwave.system.warnings`. The default behaviour is defined by :attr:`warnings_default`, which itself defaults to :class:`~dwave.system.warnings.IGNORE` **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :obj:`dimod.SampleSet` Examples: See the example in :class:`EmbeddingComposite`. """ if return_embedding is None: return_embedding = self.return_embedding_default # solve the problem on the child system child = self.child # apply the embedding to the given problem to map it to the child sampler __, target_edgelist, target_adjacency = self.target_structure # add self-loops to edgelist to handle singleton variables source_edgelist = list(bqm.quadratic) + [(v, v) for v in bqm.linear] # get the embedding if embedding_parameters is None: embedding_parameters = self.embedding_parameters else: # we want the parameters provided to the constructor, updated with # the ones provided to the sample method. To avoid the extra copy # we do an update, avoiding the keys that would overwrite the # sample-level embedding parameters embedding_parameters.update( (key, val) for key, val in self.embedding_parameters if key not in embedding_parameters) embedding = self.find_embedding(source_edgelist, target_edgelist, **embedding_parameters) if warnings is None: warnings = self.warnings_default elif 'warnings' in child.parameters: parameters.update(warnings=warnings) warninghandler = WarningHandler(warnings) warninghandler.chain_strength(bqm, chain_strength) warninghandler.chain_length(embedding) if bqm and not embedding: raise ValueError("no embedding found") bqm_embedded = embed_bqm(bqm, embedding, target_adjacency, chain_strength=chain_strength, smear_vartype=dimod.SPIN) if 'initial_state' in parameters: # if initial_state was provided in terms of the source BQM, we want # to modify it to now provide the initial state for the target BQM. # we do this by spreading the initial state values over the # chains state = parameters['initial_state'] parameters['initial_state'] = { u: state[v] for v, chain in embedding.items() for u in chain } if self.scale_aware and 'ignored_interactions' in child.parameters: ignored = [] for chain in embedding.values(): # just use 0 as a null value because we don't actually need # the biases, just the interactions ignored.extend(chain_to_quadratic(chain, target_adjacency, 0)) parameters['ignored_interactions'] = ignored response = child.sample(bqm_embedded, **parameters) warninghandler.chain_break(response, embedding) sampleset = unembed_sampleset( response, embedding, source_bqm=bqm, chain_break_method=chain_break_method, chain_break_fraction=chain_break_fraction, return_embedding=return_embedding) if return_embedding: sampleset.info['embedding_context'].update( embedding_parameters=embedding_parameters, chain_strength=chain_strength) if chain_break_fraction and len(sampleset): warninghandler.issue( "all samples had broken chains", func=lambda: (sampleset.record.chain_break_fraction.all(), None)) if warninghandler.action is WarningAction.SAVE: # we're done with the warning handler so we can just pass the list # off, if later we want to pass in a handler or similar we should # do a copy sampleset.info.setdefault('warnings', []).extend(warninghandler.saved) return sampleset
} chainstrength = 1.01 numruns = 100 dwave_sampler = DWaveSampler() A = dwave_sampler.edgelist Adj = dwave_sampler.adjacency embedding = find_embedding(Q, A) print(embedding) bqm = BinaryQuadraticModel.from_qubo(Q) # Cannot use a Composite to get the broken chains, so do the embedding # directly bqm_embedded = embed_bqm(bqm, embedding, Adj, chain_strength=chainstrength) response = DWaveSampler().sample(bqm_embedded, num_reads=numruns) # We need to get the chains directly, as a list chains = [embedding[v] for v in list(bqm)] # Obtain the broken chains broken = broken_chains(response, chains) # Interpret the results in terms of the embedding. Be sure to # tell the method to compute the chain_break_frequency. print( unembed_sampleset(response, embedding, source_bqm=bqm, chain_break_fraction=True), broken)
def from_bqm_sampleset(bqm, sampleset, sampler, embedding_context=None, warnings=None, params=None): """Construct problem data for visualization based on the BQM and sampleset in logical space (both unembedded). In order for the embedded problem/response to be reconstructed, an embedding is required in either the sampleset, or as a standalone argument. Note: This adapter can only provide best-effort estimate of the submitted problem and received samples. Namely, because values of logical variables in `sampleset` are produced by a chain break resolution method, information about individual physical qubit values is lost. Please have in mind you will never see "broken chains" when using this adapter. Args: bqm (:class:`dimod.BinaryQuadraticModel`/:class:`dimod.core.bqm.BQM`): Problem in logical (unembedded) space, given as a BQM. sampleset (:class:`~dimod.sampleset.SampleSet`): Sampling response as a sampleset. sampler (:class:`~dimod.Sampler` or :class:`~dimod.ComposedSampler`): The :class:`~dwave.system.samplers.dwave_sampler.DWaveSampler`- derived sampler used to produce the sampleset off the bqm. 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``). It is optional only if ``sampleset.info`` contains it (see `return_embedding` argument of :meth:`~dwave.system.composites.embedding.EmbeddingComposite`). warnings (list[dict], optional): Optional list of warnings. params (dict, optional): Sampling parameters used. """ logger.debug("from_bqm_sampleset({!r})".format( dict(bqm=bqm, sampleset=sampleset, sampler=sampler, warnings=warnings, embedding_context=embedding_context, params=params))) if not isinstance(sampler, dimod.Sampler): raise TypeError("dimod.Sampler instance expected for 'sampler'") # get embedding parameters if embedding_context is None: embedding_context = sampleset.info.get('embedding_context', {}) if embedding_context is None: raise ValueError("embedding_context not given") embedding = embedding_context.get('embedding') if embedding is None: raise ValueError("embedding not given") chain_strength = embedding_context.get('chain_strength') def find_solver(sampler): if hasattr(sampler, 'solver'): return sampler.solver for child in getattr(sampler, 'children', []): try: return find_solver(child) except: pass raise TypeError("'sampler' doesn't use DWaveSampler") solver = find_solver(sampler) if not isinstance(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 = "ising" if sampleset.vartype is dimod.SPIN else "qubo" # bqm vartype must match sampleset vartype if bqm.vartype is not sampleset.vartype: bqm = bqm.change_vartype(sampleset.vartype, inplace=False) # 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) # best effort reconstruction of (unembedded/qmi) response/solutions # NOTE: we **can not** reconstruct physical qubit values from logical variables # (sampleset we have access to has variable values after chain breaks resolved!) active_variables = sorted(list(bqm_embedded.variables)) active_variables_set = set(active_variables) logical_variables = list(sampleset.variables) var_to_idx = {var: idx for idx, var in enumerate(logical_variables)} unembedding = {q: var_to_idx[v] for v, qs in embedding.items() for q in qs} # sanity check assert set(unembedding) == active_variables_set def expand_sample(sample): return [int(sample[unembedding[q]]) for q in active_variables] solutions = [expand_sample(sample) for sample in sampleset.record.sample] # adjust energies to values returned by SAPI (offset embedding) energies = list(map(float, sampleset.record.energy - bqm_embedded.offset)) num_occurrences = list(map(int, sampleset.record.num_occurrences)) num_variables = solver.num_qubits timing = sampleset.info.get('timing') 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_variables_set 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_set and q2 in active_variables_set ], "embedding": embedding } # try to get problem id. if not available, auto-generate one problem_id = sampleset.info.get('problem_id') if problem_id is None: problem_id = "local-%s" % uuid.uuid4() # 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) # try to get warnings from sampleset.info if warnings is None: warnings = sampleset.info.get('warnings') # construct problem stats problem_stats = _problem_stats(response=None, sampleset=sampleset, embedding_context=embedding_context) data = { "ready": True, "details": { "id": problem_id, "type": problem_type, "solver": solver.id, "label": sampleset.info.get('problem_label'), }, "data": _problem_dict(solver_id, problem_type, problem_data, params, problem_stats), "answer": _answer_dict(solutions, active_variables, energies, num_occurrences, timing, num_variables), "unembedded_answer": _unembedded_answer_dict(sampleset), "warnings": _warnings(warnings), "rel": dict(solver=solver), } logger.trace("from_bqm_sampleset returned %r", data) return data
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
def sample(self, bqm, chain_strength=1.0, chain_break_fraction=True, **parameters): """Sample from the provided binary quadratic model. Also set parameters for handling a chain, the set of vertices in a target graph that represents a source-graph vertex; when a D-Wave system is the sampler, it is a set of qubits that together represent a variable of the binary quadratic model being minor-embedded. Args: bqm (:obj:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. chain_strength (float, optional, default=1.0): Magnitude of the quadratic bias (in SPIN-space) applied between variables to create chains. The energy penalty of chain breaks is 2 * `chain_strength`. chain_break_fraction (bool, optional, default=True): If True, the unembedded response contains a ‘chain_break_fraction’ field that reports the fraction of chains broken before unembedding. **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :class:`dimod.SampleSet`: A `dimod` :obj:`~dimod.SampleSet` object. Examples: This example submits an triangle-structured problem to a D-Wave solver, selected by the user's default :std:doc:`D-Wave Cloud Client configuration file <cloud-client:intro>`, using a specified minor-embedding of the problem’s variables to physical qubits. >>> from dwave.system.samplers import DWaveSampler >>> from dwave.system.composites import FixedEmbeddingComposite >>> import dimod ... >>> sampler = FixedEmbeddingComposite(DWaveSampler(), {'a': [0, 4], 'b': [1, 5], 'c': [2, 6]}) >>> response = sampler.sample_ising({}, {'ab': 0.5, 'bc': 0.5, 'ca': 0.5}, chain_strength=2) >>> response.first # doctest: +SKIP Sample(sample={'a': 1, 'b': -1, 'c': 1}, energy=-0.5, num_occurrences=1, chain_break_fraction=0.0) See `Ocean Glossary <https://docs.ocean.dwavesys.com/en/latest/glossary.html>`_ for explanations of technical terms in descriptions of Ocean tools. """ # solve the problem on the child system child = self.child # apply the embedding to the given problem to map it to the child sampler __, __, target_adjacency = child.structure # get the embedding embedding = self.embedding bqm_embedded = embed_bqm(bqm, embedding, target_adjacency, chain_strength=chain_strength, smear_vartype=dimod.SPIN) if 'initial_state' in parameters: parameters['initial_state'] = _embed_state( embedding, parameters['initial_state']) response = child.sample(bqm_embedded, **parameters) return unembed_sampleset(response, embedding, source_bqm=bqm, chain_break_fraction=chain_break_fraction)
_, edgelist, adjacency = sampler.structure from minorminer import find_embedding embedding = find_embedding(qubo, edgelist, random_seed=0) # random_seed=0 - which ensures that the same embedding is always generated. if manual_embed: # Pick the method for fixing broken chains. from dwave.embedding.chain_breaks import majority_vote # weighted_random method = majority_vote # Submit the job via an embedded BinaryQuadraticModel. from dimod import BinaryQuadraticModel as BQM from dwave.embedding import embed_bqm, unembed_sampleset # Generate a BQM from the QUBO. q = BQM.from_qubo(qubo) # Embed the BQM onto the target structure. embedded_q = embed_bqm(q, embedding, adjacency) # chain_strength=chain_strength, smear_vartype=dimod.SPIN # Collect the sample output. response = unembed_sampleset( sampler.sample(embedded_q, num_reads=num_samples), embedding, q, chain_break_method=method, chain_break_fraction=True) else: # Use a FixedEmbeddingComposite if we don't care about chains. from dwave.system.composites import FixedEmbeddingComposite system_composite = FixedEmbeddingComposite(sampler, embedding) response = system_composite.sample_qubo(qubo, num_reads=num_samples) constant = 0 # Cycle through the results and yield them to the caller.