def poly_energies(samples_like, poly): """Calculates energy of samples from a higher order polynomial. Args: sample (samples_like): A collection of raw samples. `samples_like` is an extension of NumPy's array_like structure. See :func:`.as_samples`. poly (dict): Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of variables and `bias` the associated bias. Variable labeling/indexing of terms in poly dict must match that of the sample(s). Returns: list/:obj:`numpy.ndarray`: The energy of the sample(s). """ sample, labels = as_samples(samples_like) idx, label = zip(*enumerate(labels)) labeldict = dict(zip(label, idx)) num_samples = len(sample) return sum(_prod_d([sample[:, labeldict[v]] for v in variables], num_samples) * bias for variables, bias in poly.items())
def energies(self, samples_like, dtype=np.float): """The energies of the given samples. Args: samples_like (samples_like): A collection of raw samples. `samples_like` is an extension of NumPy's array_like structure. See :func:`.as_samples`. dtype (:class:`numpy.dtype`, optional): The data type of the returned energies. Defaults to float. Returns: :obj:`numpy.ndarray`: The energies. """ samples, labels = as_samples(samples_like) if labels: idx, label = zip(*enumerate(labels)) labeldict = dict(zip(label, idx)) else: labeldict = {} num_samples = samples.shape[0] energies = np.zeros(num_samples, dtype=dtype) for term, bias in self.items(): if len(term) == 0: energies += bias else: energies += np.prod([samples[:, labeldict[v]] for v in term], axis=0) * bias return energies
def poly_energy(sample_like, poly): """Calculates energy of a sample from a higher order polynomial. Args: sample (samples_like): A raw sample. `samples_like` is an extension of NumPy's array_like structure. See :func:`.as_samples`. poly (dict): Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of variables and `bias` the associated bias. Returns: float: The energy of the sample. """ sample, labels = as_samples(sample_like) idx, label = zip(*enumerate(labels)) labeldict = dict(zip(label, idx)) num_samples = len(sample) if num_samples > 1: raise ValueError('poly_energy accepts a single sample. For multiple ' 'samples use poly_energies') else: return sum(_prod(sample[0][labeldict[v]] for v in variables) * bias for variables, bias in poly.items())
def energies(self, samples_like, dtype: DTypeLike = None): samples, labels = as_samples(samples_like) if len(labels) != self.num_variables(): raise ValueError("variable_order does not match the number of " "variables") ldata = np.asarray([self.get_linear(v) for v in labels]) label_to_idx = {v: idx for idx, v in enumerate(labels)} irow = [] icol = [] qdata = [] for u, v, bias in self.iter_quadratic(): irow.append(label_to_idx[u]) icol.append(label_to_idx[v]) qdata.append(bias) irow = np.asarray(irow, dtype=int) # type: ignore[assignment] icol = np.asarray(icol, dtype=int) # type: ignore[assignment] qdata = np.asarray(qdata) # type: ignore[assignment] energies = samples.dot(ldata) energies += (samples[:, irow] * samples[:, icol]).dot(qdata) energies += ldata.dtype.type(self.offset) return np.asarray(energies, dtype=dtype)
def energies(self, samples_like, dtype: DTypeLike = None): samples, labels = as_samples(samples_like, copy=True) if self._vartype is BINARY: # binary -> spin samples *= 2 samples -= 1 else: # spin -> binary samples += 1 samples //= 2 return self.data.energies((samples, labels), dtype=dtype)
def energies(self, samples): samples, labels = as_samples(samples, dtype=self._cydqm.case_dtype) # reorder as needed if len(labels) != self.num_variables(): raise ValueError( "Given sample(s) have incorrect number of variables") if self.variables != labels: # need to reorder the samples label_to_idx = dict((v, i) for i, v in enumerate(labels)) try: order = [label_to_idx[v] for v in self.variables] except KeyError: raise ValueError("given samples-like does not match labels") samples = samples[:, order] return np.asarray(self._cydqm.energies(samples))
def energies(self, samples_like, dtype=None): """Determine the energies of the given samples. Args: samples_like (samples_like): A collection of raw samples. `samples_like` is an extension of NumPy's array_like structure. See :func:`.as_samples`. dtype (:class:`numpy.dtype`, optional): The data type of the returned energies. Returns: :obj:`numpy.ndarray`: The energies. """ samples, labels = as_samples(samples_like) ldata, (irow, icol, qdata), offset \ = self.to_numpy_vectors(variable_order=labels, dtype=dtype) energies = samples.dot(ldata) + (samples[:, irow]*samples[:, icol]).dot(qdata) + offset return np.asarray(energies, dtype=dtype) # handle any type promotions
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 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)