Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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
Пример #6
0
    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
Пример #7
0
    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)
Пример #8
0
    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
Пример #9
0
    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)