def _fix_embedding(self, embedding): target_edgelist = self.target_structure.edgelist embedding = EmbeddedStructure(target_edgelist, embedding) # save the embedding and overwrite the find_embedding function self.embedding = embedding self.properties.update(embedding=embedding) def find_embedding(S, T): return embedding self.find_embedding = find_embedding
def sample(self, bqm, chain_strength=None, 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/mapping/callable, optional): Magnitude of the quadratic bias (in SPIN-space) applied between variables to create chains. The energy penalty of chain breaks is 2 * `chain_strength`. If a mapping is passed, a chain-specific strength is applied. If a callable is passed, it will be called on `chain_strength(bqm, embedding)` and should return a float or mapping, to be interpreted as above. By default, `chain_strength` is calculated with :func:`~dwave.embedding.chain_strength.uniform_torque_compensation`. chain_break_method (function/list, optional): Method or methods used to resolve chain breaks. If multiple methods are given, the results are concatenated and a new field called "chain_break_method" specifying the index of the method is appended to the sample set. See :func:`~dwave.embedding.unembed_sampleset` and :mod:`dwave.embedding.chain_breaks`. 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 bqm and not embedding: raise ValueError("no embedding found") if not hasattr(embedding, 'embed_bqm'): embedding = EmbeddedStructure(target_edgelist, embedding) bqm_embedded = embedding.embed_bqm(bqm, chain_strength=chain_strength, smear_vartype=dimod.SPIN) if warnings is None: warnings = self.warnings_default elif 'warnings' in child.parameters: parameters.update(warnings=warnings) warninghandler = WarningHandler(warnings) warninghandler.chain_strength(bqm, embedding.chain_strength, embedding) warninghandler.chain_length(embedding) 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) def async_unembed(response): # unembed the sampleset aysnchronously. 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=embedding.chain_strength) if chain_break_fraction and len(sampleset): warninghandler.issue( "All samples have 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 return dimod.SampleSet.from_future(response, async_unembed)