def test_neg(self): """Correctly orders negative gains.""" # flipping any is equally good gains = flip_energy_gains(self.notall, {'a': 1, 'b': 1, 'c': 1}) self.assertEqual(gains, [(-4.0, 'c'), (-4.0, 'b'), (-4.0, 'a')]) # flipping B is the worst gains = flip_energy_gains(self.notb, {'a': 1, 'b': 1, 'c': 1}) self.assertEqual(gains, [(0.0, 'c'), (0.0, 'a'), (-4.0, 'b')])
def test_subset(self): """Flip energy is correctly calculated for a subset of variables.""" gains = flip_energy_gains(self.notb, {'a': 1, 'b': 1, 'c': 1}, {'b'}) self.assertEqual(gains, [(-4.0, 'b')]) gains = flip_energy_gains(self.notb, {'a': 1, 'b': 1, 'c': 1}, ['c']) self.assertEqual(gains, [(0.0, 'c')]) gains = flip_energy_gains(self.notb, {'a': 1, 'b': 1, 'c': 1}, 'ab') self.assertEqual(gains, [(0.0, 'a'), (-4.0, 'b')])
def test_pos(self): """Correctly orders positive gains.""" # flipping C makes for the highest energy gain gains = flip_energy_gains(self.notall, {'a': 1, 'b': 1, 'c': -1}) self.assertEqual(gains, [(4.0, 'c'), (0.0, 'b'), (0.0, 'a')]) gains = flip_energy_gains(self.notall, {'a': -1, 'b': -1, 'c': 1}) self.assertEqual(gains, [(4.0, 'c'), (0.0, 'b'), (0.0, 'a')]) # flipping any is equally bad gains = flip_energy_gains(self.notb, {'a': 1, 'b': -1, 'c': 1}) self.assertEqual(gains, [(4.0, 'c'), (4.0, 'b'), (4.0, 'a')])
def test_sample_as_list(self): """List samples (index bqms) are properly handled.""" bqm = dimod.BQM.from_ising({}, {(0, 1): 1}) sample = [1, 1] gains = flip_energy_gains(bqm, sample) self.assertEqual(gains, [(-2, 1), (-2, 0)])
def next(self, state, **runopts): # run time options override silent_rewind = runopts.get('silent_rewind', self.silent_rewind) bqm = state.problem sample = state.samples.change_vartype(bqm.vartype).first.sample size = self.size if self.size > len(bqm): logger.debug( "subproblem size greater than the problem size, adapting to problem size" ) size = len(bqm) bqm_changed = bqm != self._rolling_bqm sample_changed = sample != self._prev_sample if bqm_changed: self._rewind_rolling(state) if sample_changed: self._prev_sample = sample # cache energy impact calculation per (bqm, sample) if bqm_changed or sample_changed or not self._variable_priority: impact = flip_energy_gains(bqm, sample, min_gain=self.min_gain) self._variable_priority = collections.OrderedDict( (v, en) for en, v in impact) if self.rolling: if len(self._unrolled_vars) >= self.rolling_history * len(bqm): logger.debug("Rolling reset at unrolled history size = %d", len(self._unrolled_vars)) self._rewind_rolling(state) # reset before exception, to be ready on a subsequent call if not silent_rewind: raise EndOfStream # pick variables for the next subproblem next_vars = self.traverse(bqm, sample, ordered_priority=self._variable_priority, visited=self._unrolled_vars, size=self.size) logger.debug("Selected %d subproblem variables: %r", len(next_vars), next_vars) if self.rolling: self._unrolled_vars.update(next_vars) # induce sub-bqm based on selected variables and global sample subbqm = bqm_induced_by(bqm, next_vars, sample) return state.updated(subproblem=subbqm)
def next(self, states, **runopts): state_thesis, state_antithesis = states bqm = state_thesis.problem thesis = dict(state_thesis.samples.first.sample) thesis_en = state_thesis.samples.first.energy antithesis = dict(state_antithesis.samples.first.sample) synthesis = thesis.copy() synthesis_en = thesis_en # input sanity check # TODO: convert to hard input validation assert len(thesis) == len(antithesis) assert state_thesis.problem == state_antithesis.problem diff = {v for v in thesis if thesis[v] != antithesis[v]} while diff: flip_energies = flip_energy_gains(bqm, thesis, diff) en, v = flip_energies[-1] diff.remove(v) thesis[v] = antithesis[v] thesis_en += en if thesis_en <= synthesis_en: # note EQ also, because we want the latest thesis synthesis = thesis.copy() synthesis_en = thesis_en synthesis_samples = SampleSet.from_samples_bqm(synthesis, bqm) # calculation sanity check assert synthesis_samples.first.energy == synthesis_en return state_thesis.updated(samples=synthesis_samples)