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, **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, 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_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, **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(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_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_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 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)