Composers#

Class#

Subsample to Sample Composers#

class IdentityComposer[source]#

Copy subsamples to samples verbatim.

class SplatComposer[source]#

A composer that overwrites current samples with subproblem samples.

See Examples.

Sample Processors#

class GreedyPathMerge[source]#

Dialectic-search merge operation [KS]. Generates a path from one input state, representing the thesis, to another input state, representing the antithesis, using a greedy method of single bit flips selected by decreasing energy.

Returns the best sample on the path, which represents the synthesis.

Note: only the lowest-energy sample, is considered from either input state.

See Examples.

References

[KS]

Kadioglu S., Sellmann M. (2009) Dialectic Search. In: Gent I.P. (eds) Principles and Practice of Constraint Programming - CP 2009. CP 2009. Lecture Notes in Computer Science, vol 5732. Springer, Berlin, Heidelberg

class IsoenergeticClusterMove(seed=None, **runopts)[source]#

Isoenergetic cluster move (ICM), also know as Houdayer move.

ICM creates two new samples from a pair of samples by identifying, among connected variables, clusters with exactly complementary values and swapping one such randomly chosen cluster between the two samples. The total energy of the two samples remains unchanged, yet such moves on variables reasonably grouped together can enable better exploration of the solution space.

Parameters:

seed (int, optional, default=None/current time) – Pseudo-random number generator seed.

Input:
States:

Two states with at least one sample each. First state should also contain a relevant problem.

Output:
States:

Two states from input with updated first sample in each.

Primitive Sample Operations#

class AggregatedSamples(aggregate=True, **runopts)[source]#

Aggregates or spreads (“un-aggregates”) samples, controlled via aggregate boolean flag.

Parameters:

aggregate (bool, default=True) – Aggregate samples vs. spread / un-aggregate them.

class ExplodeSamples[source]#

Produce one output state per input sample.

Example

This example uses Tabu sampler to produce two samples on a simple problem, and then ExplodeSamples to produce two states, each with one sample.

>>> import dimod
>>> import hybrid
>>> workflow = hybrid.TabuProblemSampler(num_reads=2) | hybrid.ExplodeSamples()
>>> state = hybrid.State(problem=dimod.BQM.from_ising({}, {'ab': 1}))
>>> result = workflow.run(state).result()
>>> len(result)
2
class MergeSamples(aggregate=False, **runopts)[source]#

Merge multiple input states by concatenating samples from all the states in to the first state.

Parameters:

aggregate (bool, default=False) – Aggregate samples after merging.

Example

This example runs two branches, a classical simulated annealing and a tabu search, acquiring one sample per branch. It then merges the samples, producing the final state with a sampleset of size two.

>>> import dimod
>>> import hybrid
>>> workflow = hybrid.Parallel(
...     hybrid.SimulatedAnnealingProblemSampler(num_reads=1),
...     hybrid.TabuProblemSampler(num_reads=1)
... ) | hybrid.MergeSamples()
>>> state = hybrid.State.from_problem(
...    dimod.BinaryQuadraticModel.from_ising({}, {'ab': 1}))
>>> result = workflow.run(state).result()
>>> len(result.samples)
2
class SliceSamples(*slice_args, **runopts)[source]#

Slice input sampleset acting on samples in a selected order.

Parameters:
  • start (int, optional, default=None) – Start index for slice.

  • stop (int) – Stop index for slice.

  • step (int, optional, default=None) – Step value for slice.

  • sorted_by (str/None, optional, default='energy') – Selects the record field used to sort the samples before slicing.

Examples

Truncate to 5 with lowest energy:

>>> top5 = SliceSamples(5)

Truncate to 5 with highest energy:

>>> bottom5 = SliceSamples(-5, None)

Slice the sample set ordered by num_occurrences, instead by energy:

>>> five_with_highest_num_occurrences = SliceSamples(-5, None, sorted_by='num_occurrences')

Halve the sample set by selecting only every other sample:

>>> odd = SliceSamples(None, None, 2)

Examples#

SplatComposer#

This example runs one iteration of a SplatComposer composer, overwriting an initial solution to a 6-variable binary quadratic model of all zeros with a solution to a 3-variable subproblem that was manually set to all ones.

import dimod
from hybrid.composers import SplatComposer
from hybrid.core import State, SampleSet
from hybrid.utils import min_sample

bqm = dimod.BinaryQuadraticModel({t: 0 for t in range(6)},
                                 {(t, (t+1) % 6): 1 for t in range(6)},
                                 0, 'BINARY')

composer = SplatComposer()
state0 = State.from_sample(min_sample(bqm), bqm)
state1 = state0.updated(subsamples=SampleSet.from_samples({3: 1, 4: 1, 5: 1}, 'BINARY', 0.0))

composed_state = composer.run(state1).result()
>>> print(composed_state.samples)
Response(rec.array([([0, 0, 0, 1, 1, 1], 1, 2)],
        dtype=[('sample', 'i1', (6,)), ('num_occurrences', '<i8'), ('energy', '<i8')]), [0, 1, 2, 3, 4, 5], {}, 'BINARY')

GreedyPathMerge#

This example runs one iteration of a GreedyPathMerge composer on a thesis and antithesis State to find a ground state of a square graph. By inverting the state of variable \(d\) and \(c\) in samples_d and then variable \(a\) of the lowest energy sample of samples_a (second sample), the composer finds a path between these two samples that contains the ground state shown on the right of the top figure.

Block diagram

Square problem with two ground states.#

Block diagram

Path from thesis to antithesis.#

import dimod
bqm = dimod.BinaryQuadraticModel({}, {'ab': 1.0, 'bc': 1.0, 'cd': 1.0, 'da': 1}, 0, 'SPIN')
samples_d = {'a': 1, 'b': 1, 'c': -1, 'd': -1}
samples_a = [{'a': -1, 'b': -1, 'c': 1, 'd': 1}, {'a': -1, 'b': 1, 'c': 1, 'd': 1}]
states = [hybrid.State.from_samples(samples_d, bqm),
          hybrid.State.from_samples(samples_a, bqm)]
synthesis = GreedyPathMerge().next(states)
>>> print(synthesis.samples)
       a   b   c   d  energy  num_occ.
   0  +1  +1  +1  +1    -4.0         1
   [ 1 rows, 4 variables ]