def sample(self, bqm, **kwargs): """Sample from a binary quadratic model. Args: bqm (:obj:`~dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. Returns: :obj:`~dimod.SampleSet` """ kwargs = self.remove_unknown_kwargs(**kwargs) n = len(bqm.variables) if n == 0: return SampleSet.from_samples([], bqm.vartype, energy=[]) samples = _graycode(bqm) if bqm.vartype is Vartype.SPIN: samples = 2 * samples - 1 response = SampleSet.from_samples_bqm((samples, list(bqm.variables)), bqm) return response
def sample(self, bqm): """Sample from a binary quadratic model. Args: bqm (:obj:`~dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. Returns: :obj:`~dimod.SampleSet` """ M = bqm.binary.to_numpy_matrix() off = bqm.binary.offset if M.shape == (0, 0): return SampleSet.from_samples([], bqm.vartype, energy=[]) sample = np.zeros((len(bqm),), dtype=bool) # now we iterate, flipping one bit at a time until we have # traversed all samples. This is a Gray code. # https://en.wikipedia.org/wiki/Gray_code def iter_samples(): sample = np.zeros((len(bqm)), dtype=bool) energy = 0.0 yield sample.copy(), energy + off for i in range(1, 1 << len(bqm)): v = _ffs(i) # flip the bit in the sample sample[v] = not sample[v] # for now just calculate the energy, but there is a more clever way by calculating # the energy delta for the single bit flip, don't have time, pull requests # appreciated! energy = sample.dot(M).dot(sample.transpose()) yield sample.copy(), float(energy) + off samples, energies = zip(*iter_samples()) response = SampleSet.from_samples(np.array(samples, dtype='int8'), Vartype.BINARY, energies) # make sure the response matches the given vartype, in-place. response.change_vartype(bqm.vartype, inplace=True) return response
def sample(self, bqm, *, components=None, **parameters): """Sample from the provided binary quadratic model. Args: bqm (:class:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. components (list(set)): A list of disjoint set of variables that fully partition the variables **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :class:`dimod.SampleSet` """ # make sure the BQM is shapeable bqm = as_bqm(bqm, cls=[AdjVectorBQM, AdjDictBQM]) # solve the problem on the child system child = self.child variables = bqm.variables if components is None: components = list(connected_components(bqm)) if isinstance(components, set): components = [components] sampleset = None fixed_value = min(bqm.vartype.value) for component in components: bqm_copy = bqm.copy() bqm_copy.fix_variables( {i: fixed_value for i in (variables - component)}) if sampleset is None: # here .truncate(1) is used to pick the best solution only. The other options # for future development is to combine all sample with all. # This way you'd get the same behaviour as the ExactSolver sampleset = child.sample(bqm_copy, **parameters).truncate(1) else: sampleset = append_variables( sampleset.truncate(1), child.sample(bqm_copy, **parameters).truncate(1)) if sampleset is None: return SampleSet.from_samples_bqm({}, bqm) else: return SampleSet.from_samples_bqm(sampleset, bqm)
def sample(self, bqm, num_reads=10): """Give random samples for a binary quadratic model. Variable assignments are chosen by coin flip. Args: bqm (:obj:`.BinaryQuadraticModel`): Binary quadratic model to be sampled from. num_reads (int, optional, default=10): Number of reads. Returns: :obj:`.SampleSet` """ values = tuple(bqm.vartype.value) def _itersample(): for __ in range(num_reads): sample = {v: choice(values) for v in bqm.linear} energy = bqm.energy(sample) yield sample, energy samples, energies = zip(*_itersample()) return SampleSet.from_samples(samples, bqm.vartype, energies)
def sample(self, bqm, lower_bound=None, upper_bound=None, **parameters): """Clip and sample from the provided binary quadratic model. If lower_bound and upper_bound are given variables with value above or below are clipped. Args: bqm (:obj:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. lower_bound (number): Value by which to clip the variables from below. upper_bound (number): Value by which to clip the variables from above. **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :obj:`dimod.SampleSet` """ child = self.child bqm_copy = _clip_bqm(bqm, lower_bound, upper_bound) response = child.sample(bqm_copy, **parameters) return SampleSet.from_samples_bqm(response, bqm, info=response.info)
def sample_cqm(self, cqm: 'ConstrainedQuadraticModel', rtol: float = 1e-6, atol: float = 1e-8, **kwargs) -> SampleSet: """Sample from a constrained quadratic model. Args: cqm (:class:`~dimod.ConstrainedQuadraticModel`): Constrained quadratic model to be sampled from. rtol (float): Relative tolerance for constraint violation. The fraction of a constraint's right hand side which any violation must be smaller than for the constraint to be satisfied. atol (float): Absolute tolerance for constraint violations. A constant any violation must be smaller than for the constraint to be satisfied. Returns: A sampleset of all possible samples, with the fields is_feasible and is_satisfied containing total and individual constraint violation information, respectively. """ Sampler.remove_unknown_kwargs(self, **kwargs) if not len(cqm.variables): return SampleSet.from_samples([], 'INTEGER', energy=[]) cases = _all_cases_cqm(cqm) energies = cqm.objective.energies(cases) is_satisfied = [[ info.violation <= atol + rtol * info.rhs_energy for info in cqm.iter_constraint_data((c, cases[1])) ] for c in cases[0]] is_feasible = [all(satisfied) for satisfied in is_satisfied] # from_samples requires a single vartype argument, but QuadraticModel # and therefore CQM allow mixed vartypes. For now, only passing 'INTEGER' return SampleSet.from_samples(cases, 'INTEGER', energies, is_feasible=is_feasible, is_satisfied=is_satisfied)
def sample(self, bqm, beta_range=None, num_reads=10, num_sweeps=1000): """Sample from low-energy spin states using simulated annealing. Args: bqm (:obj:`~dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. beta_range (tuple, optional): Beginning and end of the beta schedule (beta is the inverse temperature) as a 2-tuple. The schedule is applied linearly in beta. Default is chosen based on the total bias associated with each node. num_reads (int, optional): Number of reads. Each sample is the result of a single run of the simulated annealing algorithm. num_sweeps (int, optional): Number of sweeps or steps. Default is 1000. Returns: :obj:`.SampleSet` Note: This is a reference implementation, not optimized for speed and therefore not an appropriate sampler for benchmarking. Examples: This example provides samples for a two-variable QUBO model. >>> import dimod ... >>> sampler = dimod.SimulatedAnnealingSampler() >>> Q = {(0, 0): -1, (1, 1): -1, (0, 1): 2} >>> bqm = dimod.BinaryQuadraticModel.from_qubo(Q, offset = 0.0) >>> response = sampler.sample(bqm, num_reads=2) >>> response.data_vectors['energy'] # doctest: +SKIP array([-1., -1.]) """ # input checking # h, J are handled by the @ising decorator # beta_range, sweeps are handled by ising_simulated_annealing if not isinstance(num_reads, int): raise TypeError("'samples' should be a positive integer") if num_reads < 1: raise ValueError("'samples' should be a positive integer") h, J, offset = bqm.to_ising() # run the simulated annealing algorithm samples = [] energies = [] for __ in range(num_reads): sample, energy = ising_simulated_annealing(h, J, beta_range, num_sweeps) samples.append(sample) energies.append(energy) response = SampleSet.from_samples(samples, Vartype.SPIN, energies) response.change_vartype(bqm.vartype, offset, inplace=True) return response
def sample(self, bqm, beta_range=None, num_reads=10, num_sweeps=1000, **kwargs): """Sample from low-energy spin states using simulated annealing. Args: bqm (:obj:`.BinaryQuadraticModel`): Binary quadratic model to be sampled from. beta_range (tuple, optional): Beginning and end of the beta schedule (beta is the inverse temperature) as a 2-tuple. The schedule is applied linearly in beta. Default is chosen based on the total bias associated with each node. num_reads (int, optional, default=10): Number of reads. Each sample is the result of a single run of the simulated annealing algorithm. num_sweeps (int, optional, default=1000): Number of sweeps or steps. Returns: :obj:`.SampleSet` Note: This is a reference implementation, not optimized for speed and therefore not an appropriate sampler for benchmarking. """ # input checking # h, J are handled by the @ising decorator # beta_range, sweeps are handled by ising_simulated_annealing if not isinstance(num_reads, int): raise TypeError("'samples' should be a positive integer") if num_reads < 1: raise ValueError("'samples' should be a positive integer") kwargs = self.remove_unknown_kwargs(**kwargs) h, J, offset = bqm.to_ising() # run the simulated annealing algorithm samples = [] energies = [] for __ in range(num_reads): sample, energy = ising_simulated_annealing(h, J, beta_range, num_sweeps) samples.append(sample) energies.append(energy) response = SampleSet.from_samples(samples, Vartype.SPIN, energies) response.change_vartype(bqm.vartype, offset, inplace=True) return response
def _sample(*args, **kwargs): # avoid circular import from dimod.sampleset import SampleSet iterator = f(*args, **kwargs) # do the blocking part next(iterator) return SampleSet.from_future(None, lambda _: next(iterator))
def sample_dqm(self, dqm: 'DiscreteQuadraticModel', **kwargs) -> SampleSet: """Sample from a discrete quadratic model. Args: dqm (:class:`~dimod.DiscreteQuadraticModel`): Discrete quadratic model to be sampled from. Returns: :class:`~dimod.SampleSet` """ Sampler.remove_unknown_kwargs(self, **kwargs) if not dqm.num_variables(): return SampleSet.from_samples([], 'DISCRETE', energy=[]) cases = _all_cases_dqm(dqm) energies = dqm.energies(cases) return SampleSet.from_samples(cases, 'DISCRETE', energies)
def sample(self, sampler, *args, **kwargs): """ Sample the integer quadratic model with the given sampler. This will sample the underlying binary quadratic model, reconstruct the integer variables from the sampleset, and return a new sampleset containing the reconstructed integer variables with their original names. NOTE: If you print the SampleSet object returned by this function, you will not see the correct integer values. This is because Dwave's printing functionality does not support integers, but SampleSet object does indeed contain integers, this is just an issue with printing. If you desparately need printing, then you can just print the record inside the SampleSet object >>> sampleset = iqm.sample(sampler, num_reads=10) >>> print(sampleset.record) Args: sampler: A D-Wave sampler. *args: Positional arguments to the sampler's sample() function. **kwargs: Keyword arguments to the sampler's sample() function. Returns: A dimod.SampleSet object containing the samples. """ sampleset = sampler.sample(self._bqm, *args, **kwargs) record = sampleset.record variables = sampleset.variables info = sampleset.info vartype = sampleset.vartype reconstructed_samples = np.zeros( (record.shape[0], len(self._vartype_map))) original_variables = OrderedDict() for i, var in enumerate(variables): varname = var[0] if varname not in original_variables: original_variables[varname] = len(original_variables) ind = original_variables[varname] bc = self._binary_coefficients(self._vartype_map[varname]) reconstructed_samples[:, ind] += record['sample'][:, i] * bc[var[1]] type = (np.record, [('sample', 'i', (len(original_variables), )), ('energy', '<f8'), ('num_occurrences', '<i4')]) new_record = np.recarray(record.shape, type, names=('sample', 'energy', 'num_occurrences')) new_record['sample'] = reconstructed_samples new_record['energy'] = record['energy'] new_record['num_occurrences'] = record['num_occurrences'] return SampleSet(new_record, original_variables.keys(), info, vartype)
def sample_dqm(self, dqm, **kwargs): """Sample from a discrete quadratic model. Args: dqm (:obj:`~dimod.DiscreteQuadraticModel`): Discrete quadratic model to be sampled from. Returns: :obj:`~dimod.SampleSet` """ Sampler.remove_unknown_kwargs(self, **kwargs) n = dqm.num_variables() if n == 0: return SampleSet.from_samples([], 'DISCRETE', energy=[]) possible_samples = as_samples( (_all_cases_dqm(dqm), list(dqm.variables))) energies = dqm.energies(possible_samples) response = SampleSet.from_samples(possible_samples, 'DISCRETE', energies) return response
def dimod_object_hook(obj): """JSON-decoding for dimod objects. See Also: :class:`json.JSONDecoder` for using custom decoders. """ if _is_sampleset_v2(obj): # in the future we could handle subtypes but right now we just have the # one return SampleSet.from_serializable(obj) elif _is_bqm(obj): # in the future we could handle subtypes but right now we just have the # one return BinaryQuadraticModel.from_serializable(obj) return obj
def sample(self, bqm, fixed_variables=None, **parameters): """Sample from the provided binary quadratic model. Args: bqm (:obj:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. fixed_variables (dict): A dictionary of variable assignments. **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :obj:`dimod.SampleSet` """ if not fixed_variables: # None is falsey return self.child.sample(bqm, **parameters) # make sure that we're shapeable and that we have a BQM we can mutate bqm_copy = as_bqm(bqm, cls=[AdjVectorBQM, AdjDictBQM, AdjMapBQM], copy=True) bqm_copy.fix_variables(fixed_variables) sampleset = self.child.sample(bqm_copy, **parameters) def _hook(sampleset): # make RoofDualityComposite non-blocking if sampleset.variables: if len(sampleset): return sampleset.append_variables(fixed_variables) else: return sampleset.from_samples_bqm((np.empty((0, len(bqm))), bqm.variables), bqm=bqm) # there are only fixed variables, make sure that the correct number # of samples are returned samples = [fixed_variables]*max(len(sampleset), 1) return sampleset.from_samples_bqm(samples, bqm=bqm) return SampleSet.from_future(sampleset, _hook)
def sample(self, bqm, num_reads=10): """Give random samples for a binary quadratic model. Args: bqm (:obj:`.BinaryQuadraticModel`): Binary quadratic model to be sampled from. num_reads (int, optional, default=10): Number of reads. Returns: :obj:`.SampleSet` Notes: For each variable in each sample, the value is chosen by a coin flip. Examples: This example provides samples for a two-variable Ising model. >>> import dimod ... >>> sampler = dimod.RandomSampler() >>> h = {0: -1, 1: -1} >>> J = {(0, 1): -1} >>> bqm = dimod.BinaryQuadraticModel(h, J, -0.5, dimod.SPIN) >>> response = sampler.sample(bqm, num_reads=3) >>> len(response) 3 >>> response.data_vectors['energy'] # doctest: +SKIP array([ 0.5, -3.5, 0.5]) """ values = tuple(bqm.vartype.value) def _itersample(): for __ in range(num_reads): sample = {v: choice(values) for v in bqm.linear} energy = bqm.energy(sample) yield sample, energy samples, energies = zip(*_itersample()) return SampleSet.from_samples(samples, bqm.vartype, energies)
def sample(self, bqm, **kwargs): """Return an empty sample set. Args: bqm (:obj:`.BinaryQuadraticModel`): The binary quadratic model determines the variables labels in the sample set. kwargs: As specified when constructing the null sampler. Returns: :obj:`.SampleSet`: The empty sample set. """ samples = np.empty((0, len(bqm))) labels = iter(bqm.variables) kwargs = self.remove_unknown_kwargs(**kwargs) return SampleSet.from_samples_bqm((samples, labels), bqm)
def sample(self, bqm, **kwargs): """Return an empty sample set. Args: bqm (:obj:`.BinaryQuadraticModel`): The binary quadratic model determines the variables labels in the sample set. kwargs: As specified when constructing the null sampler. Returns: :obj:`.SampleSet`: The empty sample set. """ samples = np.empty((0, len(bqm))) labels = iter(bqm.variables) for kw in kwargs: if kw not in self.parameters: raise ValueError("unknown parameter {!r}".format(kw)) return SampleSet.from_samples_bqm((samples, labels), bqm)
def sample(self, bqm, num_spin_reversal_transforms=2, spin_reversal_variables=None, **kwargs): """Sample from the binary quadratic model. Args: bqm (:obj:`~dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. num_spin_reversal_transforms (integer, optional, default=2): Number of spin reversal transform runs. spin_reversal_variables (list/dict, optional, default=None): Variables to which to apply the spin reversal. If None, every variable has a 50% probability of being selected. Returns: :obj:`.SampleSet` Examples: This example runs 100 spin reversals applied to one variable of a QUBO problem. >>> import dimod ... >>> base_sampler = dimod.ExactSolver() >>> composed_sampler = dimod.SpinReversalTransformComposite(base_sampler) >>> Q = {('a', 'a'): -1, ('b', 'b'): -1, ('a', 'b'): 2} >>> response = composed_sampler.sample_qubo(Q, ... num_spin_reversal_transforms=100, ... spin_reversal_variables={'a'}) >>> len(response) 400 >>> print(next(response.data())) # doctest: +SKIP Sample(sample={'a': 0, 'b': 1}, energy=-1.0) """ # make a main response responses = [] for ii in range(num_spin_reversal_transforms): if spin_reversal_variables is None: # apply spin transform to each variable with 50% chance transform = list(v for v in bqm.linear if random() > .5) else: transform = list(spin_reversal_variables) flipped_bqm = bqm.copy() for v in transform: flipped_bqm.flip_variable(v) flipped_response = self.child.sample(bqm, **kwargs) tf_idxs = [flipped_response.variables.index[v] for v in flipped_response.variables] if bqm.vartype is Vartype.SPIN: flipped_response.record.sample[:, tf_idxs] = -1 * flipped_response.record.sample[:, tf_idxs] else: flipped_response.record.sample[:, tf_idxs] = 1 - flipped_response.record.sample[:, tf_idxs] responses.append(flipped_response) # # stack the records record = np.rec.array(np.hstack((resp.record for resp in responses))) vartypes = set(resp.vartype for resp in responses) if len(vartypes) > 1: raise RuntimeError("inconsistent vartypes returned") vartype = vartypes.pop() info = {} for resp in responses: info.update(resp.info) labels = responses[0].variables return SampleSet(record, labels, info, vartype)
def _sample(*args, **kwargs): iterator = f(*args, **kwargs) # resolve blocking part now, and make hook for the non-blocking part return SampleSet.from_future(next(iterator), lambda _: next(iterator))
def __init__(self, dimod_answer): solution = SampleSet.from_serializable(dimod_answer) Response.__init__(self, solution)
def parse_initial_states(self, bqm, initial_states=None, initial_states_generator='random', num_reads=None, seed=None): """Parses/generates initial states for an initialized sampler. Args: bqm (:class:`~dimod.BinaryQuadraticModel`): The binary quadratic model. num_reads (int, optional, default=len(initial_states) or 1): Number of reads. If `num_reads` is not explicitly given, it is selected to match the number of initial states given. If no initial states are given, it defaults to 1. initial_states (samples-like, optional, default=None): One or more samples, each defining an initial state for all the problem variables. Initial states are given one per read, but if fewer than `num_reads` initial states are defined, additional values are generated as specified by `initial_states_generator`. See func:`.as_samples` for a description of "samples-like". initial_states_generator ({'none', 'tile', 'random'}, optional, default='random'): Defines the expansion of `initial_states` if fewer than `num_reads` are specified: * "none": If the number of initial states specified is smaller than `num_reads`, raises ValueError. * "tile": Reuses the specified initial states if fewer than `num_reads` or truncates if greater. * "random": Expands the specified initial states with randomly generated states if fewer than `num_reads` or truncates if greater. seed (int (32-bit unsigned integer), optional): Seed to use for the PRNG. Specifying a particular seed with a constant set of parameters produces identical results. If not provided, a random seed is chosen. Returns: A named tuple with `['initial_states', 'initial_states_generator', 'num_reads', 'seed']` as generated by this function. """ num_variables = len(bqm) # validate/initialize initial_states if initial_states is None: initial_states_array = np.empty((0, num_variables), dtype=np.int8) initial_states_variables = list(bqm.variables) initial_states_vartype = bqm.vartype else: initial_states_array, initial_states_variables = \ as_samples(initial_states) # confirm that the vartype matches and/or make it match if isinstance(initial_states, SampleSet): initial_states_vartype = initial_states.vartype else: # check based on values, defaulting to match the current bqm initial_states_vartype = infer_vartype( initial_states_array) or bqm.vartype # confirm that the variables match if bqm.variables ^ initial_states_variables: raise ValueError("mismatch between variables in " "'initial_states' and 'bqm'") # match the vartype of the initial_states to the bqm if initial_states_vartype is Vartype.SPIN and bqm.vartype is Vartype.BINARY: initial_states_array += 1 initial_states_array //= 2 elif initial_states_vartype is Vartype.BINARY and bqm.vartype is Vartype.SPIN: initial_states_array *= 2 initial_states_array -= 1 # validate num_reads and/or infer them from initial_states if num_reads is None: num_reads = len(initial_states_array) or 1 if not isinstance(num_reads, Integral): raise TypeError("'num_reads' should be a positive integer") if num_reads < 1: raise ValueError("'num_reads' should be a positive integer") # fill/generate the initial states as needed if initial_states_generator not in self._generators: raise ValueError("unknown value for 'initial_states_generator'") extrapolate = self._generators[initial_states_generator] initial_states_array = extrapolate(initial_states=initial_states_array, num_reads=num_reads, num_variables=num_variables, seed=seed, vartype=bqm.vartype) initial_states_array = self._truncate_filter(initial_states_array, num_reads) sampleset = SampleSet.from_samples_bqm( (initial_states_array, initial_states_variables), bqm) return ParsedInputs(sampleset, initial_states_generator, num_reads, seed)
def __init__(self, fujitsu_answer): sampleset = SampleSet.from_serializable(fujitsu_answer) Response.__init__(self, sampleset) self.timing = self.sampleset.info["timing"]
def _release_response(response, fixed_variables): """will add the fixed variables and their assigned values to the samples of the response object. Energies of the response do not change since in fixing step the offset is populated by the constant energy shift associated with fixing the variables. Args: response (:obj:`.SampleSet`): Samples from the bqm with fixed variables. fixed_variables (dict): The dict of fixed variables and their assigned values. These are the variables that will be added back to the samples of the response object. Returns: :obj:`dimod.SampleSet`: Samples for the source binary quadratic model. Examples: This example uses :class:`.FixedVariableComposite` to instantiate a composed sampler that submits a simple Ising problem to a sampler. The composed sampler fixes a variable and modifies linear and quadratic biases according. >>> import dimod >>> sampler = dimod.FixedVariableComposite(dimod.ExactSolver()) >>> h = {'d': -4} >>> J = {('a', 'b'): 1, ('b', 'c'): 1, ('a', 'c'): 1, ('c', 'd'): -.1} >>> bqm = dimod.BinaryQuadraticModel.from_ising(h, J) >>> fixed_variables = dimod.roof_duality.fix_variables(bqm) >>> response = sampler.sample(bqm, fixed_variables=fixed_variables) >>> print(response.first) Sample(sample={'a': -1, 'b': 1, 'c': 1, 'd': 1}, energy=-5.1, num_occurrences=1) """ record = response.record original_variables = list(response.variables) samples = np.asarray(record.sample) energy = np.asarray(record.energy) num_samples, num_variables = np.shape(samples) num_variables += len(fixed_variables) if len(fixed_variables) > 0: b = [] for v, val in fixed_variables.items(): original_variables.append(v) b.append([val] * num_samples) samples = np.concatenate((samples, np.transpose(b)), axis=1) datatypes = [('sample', np.dtype(np.int8), (num_variables, )), ('energy', energy.dtype)] datatypes.extend((name, record[name].dtype, record[name].shape[1:]) for name in record.dtype.names if name not in {'sample', 'energy'}) data = np.rec.array(np.empty(num_samples, dtype=datatypes)) data.sample = samples data.energy = energy for name in record.dtype.names: if name not in {'sample', 'energy'}: data[name] = record[name] return SampleSet(data, original_variables, response.info, response.vartype)
def sample(self, bqm, **parameters): """Sample from the provided binary quadratic model. Args: bqm (:class:`dimod.BinaryQuadraticModel`): Binary quadratic model to be sampled from. fixed_variables (dict, optional, default=None): A dictionary of variable assignments used when ``self.algorithm`` is 'explicit'. strict (bool, optional, default=True): Only used if ``self.algorithm`` is 'roof_duality'. If True, only fixes variables for which assignments are true for all minimizing points (strong persistency). If False, also fixes variables for which the assignments are true for some but not all minimizing points (weak persistency). **parameters: Parameters for the sampling method, specified by the child sampler. Returns: :class:`dimod.SampleSet` """ if self.algorithm == 'explicit': fixed_variables = parameters.pop('fixed_variables', None) if fixed_variables is None: msg = ( "No fixed_variables passed in when algorithm is 'explicit'. " "Passing problem to child sampler without fixing.") warnings.warn(msg) return self.child.sample(bqm, **parameters) elif self.algorithm == 'roof_duality': fixed_variables = roof_duality(bqm, strict=parameters.pop( 'strict', True)) # make sure that we're shapeable and that we have a BQM we can mutate bqm_copy = as_bqm(bqm, cls=[AdjVectorBQM, AdjDictBQM], copy=True) bqm_copy.fix_variables(fixed_variables) sampleset = self.child.sample(bqm_copy, **parameters) def _hook(sampleset): # make RoofDualityComposite non-blocking if sampleset.variables: if len(sampleset): return append_variables(sampleset, fixed_variables) else: return sampleset.from_samples_bqm((np.empty( (0, len(bqm))), bqm.variables), bqm=bqm) # there are only fixed variables, make sure that the correct number # of samples are returned samples = [fixed_variables] * max(len(sampleset), 1) return sampleset.from_samples_bqm(samples, bqm=bqm) return SampleSet.from_future(sampleset, _hook)
def __init__(self, dwave_answer): sampleset = SampleSet.from_serializable(dwave_answer) Response.__init__(self, sampleset)
def polymorph_response(response, poly, bqm, penalty_strength=None, keep_penalty_variables=True, discard_unsatisfied=False): """ Transforms the sampleset for the higher order problem. Given a response of a penalized HUBO, this function creates a new sampleset object, taking into account penalty information and calculates the energies of samples for the higherorder problem. Args: response (:obj:`.SampleSet`): response for a penalized hubo. poly (:obj:`.BinaryPolynomial`): A binary polynomial. bqm (:obj:`dimod.BinaryQuadraticModel`): Binary quadratic model of the reduced problem. penalty_strength (float, optional): default is None, if provided, will be added to the info field of the returned sampleSet object. keep_penalty_variables (bool, optional): default is True. if False will remove the variables used for penalty from the samples discard_unsatisfied (bool, optional): default is False. If True will discard samples that do not satisfy the penalty conditions. Returns: (:obj:`.SampleSet'): A sampleSet object that has additional penalty information. The energies of samples are calculated for the HUBO ignoring the penalty variables. """ record = response.record penalty_vector = penalty_satisfaction(response, bqm) original_variables = bqm.variables if discard_unsatisfied: samples_to_keep = list(map(bool, list(penalty_vector))) penalty_vector = np.array([True] * np.sum(samples_to_keep)) else: samples_to_keep = list(map(bool, [1] * len(record.sample))) samples = record.sample[samples_to_keep] energy_vector = poly.energies((samples, response.variables)) if not keep_penalty_variables: original_variables = poly.variables idxs = [response.variables.index[v] for v in original_variables] samples = np.asarray(samples[:, idxs]) num_samples, num_variables = np.shape(samples) datatypes = [('sample', np.dtype(np.int8), (num_variables,)), ('energy', energy_vector.dtype), ('penalty_satisfaction', penalty_vector.dtype)] datatypes.extend((name, record[name].dtype, record[name].shape[1:]) for name in record.dtype.names if name not in {'sample', 'energy'}) data = np.rec.array(np.empty(num_samples, dtype=datatypes)) data.sample = samples data.energy = energy_vector for name in record.dtype.names: if name not in {'sample', 'energy'}: data[name] = record[name][samples_to_keep] data['penalty_satisfaction'] = penalty_vector response.info['reduction'] = bqm.info['reduction'] if penalty_strength is not None: response.info['penalty_strength'] = penalty_strength return SampleSet(data, original_variables, response.info, response.vartype)