Example #1
0
def HybridizedPopulationAnnealing(num_reads=20, num_iter=20, num_sweeps=1000):
    """Workflow generator for population annealing initialized with QPU samples.

    Args:
        num_reads (int):
            Size of the population of samples.

        num_iter (int):
            Number of temperatures over which we iterate fixed-temperature
            sampling / resampling.

        num_sweeps (int):
            Number of sweeps in the fixed temperature sampling step.

    Returns:
        Workflow (:class:`~hybrid.core.Runnable` instance).
    """

    # QPU initial sampling: limits the PA workflow to QPU-sized problems
    qpu_init = (hybrid.IdentityDecomposer()
                | hybrid.QPUSubproblemAutoEmbeddingSampler(num_reads=num_reads)
                | hybrid.IdentityComposer()) | hybrid.AggregatedSamples(False)

    # PA workflow: after initial QPU sampling and initial beta schedule estimation,
    # we do `num_iter` steps (one per beta/temperature) of fixed-temperature
    # sampling / weighted resampling
    workflow = qpu_init | CalculateAnnealingBetaSchedule(
        length=num_iter) | hybrid.Loop(
            ProgressBetaAlongSchedule()
            | hybrid.FixedTemperatureSampler(num_sweeps=num_sweeps)
            | EnergyWeightedResampler(),
            max_iter=num_iter)

    return workflow
Example #2
0
def HybridizedPopulationAnnealing(num_reads=100,
                                  num_iter=100,
                                  num_sweeps=100,
                                  beta_range=None):
    """Workflow generator for population annealing initialized with QPU samples.

    Args:
        num_reads (int):
            Size of the population of samples.

        num_iter (int):
            Number of temperatures over which we iterate fixed-temperature
            sampling / resampling.

        num_sweeps (int):
            Number of sweeps in the fixed temperature sampling step.

        beta_range (tuple[float], optional):
            A 2-tuple defining the beginning and end of the beta
            schedule, where beta is the inverse temperature. Passed to
            :class:`.CalculateAnnealingBetaSchedule` for linear schedule
            generation.

    Returns:
        Workflow (:class:`~hybrid.core.Runnable` instance).
    """

    # QPU initial sampling: limits the PA workflow to QPU-sized problems
    qpu_init = (hybrid.IdentityDecomposer()
                | hybrid.QPUSubproblemAutoEmbeddingSampler(num_reads=num_reads)
                | hybrid.IdentityComposer()) | hybrid.AggregatedSamples(False)

    # PA workflow: after initial QPU sampling and initial beta schedule estimation,
    # we do `num_iter` steps (one per beta/temperature) of fixed-temperature
    # sampling / weighted resampling

    schedule_init = CalculateAnnealingBetaSchedule(length=num_iter,
                                                   beta_range=beta_range,
                                                   interpolation='linear')

    workflow = qpu_init | schedule_init | hybrid.Loop(
        ProgressBetaAlongSchedule()
        | hybrid.FixedTemperatureSampler(num_sweeps=num_sweeps)
        | EnergyWeightedResampler(),
        max_iter=num_iter)

    return workflow
    bqm = dimod.BinaryQuadraticModel.from_coo(fp)

print("BQM: {} nodes, {} edges, {:.2f} density".format(
    len(bqm), len(bqm.quadratic), hybrid.bqm_density(bqm)))

# sweeps per fixed-temperature sampling step
num_sweeps = 1000

# number of generations, or temperatures to progress through
num_iter = 20

# population size
num_samples = 20

# QPU initial sampling: limits the PA workflow to QPU-sized problems
qpu_init = (hybrid.IdentityDecomposer()
            | hybrid.QPUSubproblemAutoEmbeddingSampler(num_reads=num_samples)
            | hybrid.IdentityComposer()) | hybrid.AggregatedSamples(False)

# PA workflow: after initial beta schedule estimation, we do `num_iter` steps
# (one per beta/temperature) of fixed-temperature sampling / weighted resampling
workflow = qpu_init | CalculateAnnealingBetaSchedule(
    length=num_iter) | hybrid.Loop(
        ProgressBetaAlongSchedule() | FixedTemperatureSampler(
            num_sweeps=num_sweeps) | EnergyWeightedResampler(),
        max_iter=num_iter)

# run the workflow
state = hybrid.State.from_problem(bqm)
solution = workflow.run(state).result()
"""

from __future__ import print_function

import sys

import dimod
import hybrid

# load a problem
problem = sys.argv[1]
with open(problem) as fp:
    bqm = dimod.BinaryQuadraticModel.from_coo(fp)

# construct a Dialectic Search workflow
generate_antithesis = (hybrid.IdentityDecomposer()
                       | hybrid.RandomSubproblemSampler()
                       | hybrid.SplatComposer()
                       | hybrid.TabuProblemSampler())

generate_synthesis = (hybrid.GreedyPathMerge() | hybrid.TabuProblemSampler())

tracker = hybrid.TrackMin()

local_update = hybrid.LoopWhileNoImprovement(
    hybrid.Parallel(hybrid.Identity(), generate_antithesis)
    | generate_synthesis | tracker,
    max_tries=10)

global_update = hybrid.Loop(generate_antithesis | local_update, max_iter=10)
n_sweeps = 10000
n_replicas = 10
n_iterations = 10

# replicas are initialized with random samples
state = hybrid.State.from_problem(bqm)
replicas = hybrid.States(*[state.updated() for _ in range(n_replicas)])

# get a reasonable beta range
beta_hot, beta_cold = neal.default_beta_range(bqm)

# generate betas for all branches/replicas
betas = np.geomspace(beta_hot, beta_cold, n_replicas)

# QPU branch: limits the PT workflow to QPU-sized problems
qpu = hybrid.IdentityDecomposer() | hybrid.QPUSubproblemAutoEmbeddingSampler(
) | hybrid.IdentityComposer()

# use QPU as the hottest temperature sampler and `n_replicas-1` fixed-temperature-samplers
update = hybrid.Branches(
    qpu, *[
        FixedTemperatureSampler(beta=beta, num_sweeps=n_sweeps)
        for beta in betas[1:]
    ])

# swap step is `n_replicas-1` pairwise potential swaps
swap = SwapReplicasDownsweep(betas=betas)

# we'll run update/swap sequence for `n_iterations`
workflow = hybrid.Loop(update | swap, max_iter=n_iterations) \
         | hybrid.MergeSamples(aggregate=True)
Example #6
0
def HybridizedParallelTempering(num_sweeps=10000,
                                num_replicas=10,
                                max_iter=None,
                                max_time=None,
                                convergence=3):
    """Parallel tempering workflow generator.

    Args:
        num_sweeps (int, optional):
            Number of sweeps in the fixed temperature sampling.

        num_replicas (int, optional):
            Number of replicas (parallel states / workflow branches).

        max_iter (int/None, optional):
            Maximum number of iterations of the update/swaps loop.

        max_time (int/None, optional):
            Maximum wall clock runtime (in seconds) allowed in the update/swaps
            loop.

        convergence (int/None, optional):
            Number of times best energy of the coldest replica has to repeat
            before we terminate.

    Returns:
        Workflow (:class:`~hybrid.core.Runnable` instance).

    """

    # expand single input state into `num_replicas` replica states
    preprocess = SpawnParallelTemperingReplicas(num_replicas=num_replicas)

    # QPU branch: limits the PT workflow to QPU-sized problems
    qpu = (hybrid.IdentityDecomposer()
           | hybrid.QPUSubproblemAutoEmbeddingSampler()
           | hybrid.IdentityComposer())

    # use QPU as the hottest temperature sampler and `num_replicas-1` fixed-temperature-samplers
    update = hybrid.Branches(
        qpu, *[
            FixedTemperatureSampler(num_sweeps=num_sweeps)
            for _ in range(num_replicas - 1)
        ])

    # replica exchange step: do the top-down sweep over adjacent pairs
    # (good hot samples sink to bottom)
    swap = SwapReplicasDownsweep()

    # loop termination key function
    def key(states):
        if states is not None:
            return states[-1].samples.first.energy

    # replicas update/swap until Loop termination criteria reached
    loop = hybrid.Loop(update | swap,
                       max_iter=max_iter,
                       max_time=max_time,
                       convergence=convergence,
                       key=key)

    # collapse all replicas (although the bottom one should be the best)
    postprocess = hybrid.MergeSamples(aggregate=True)

    workflow = preprocess | loop | postprocess

    return workflow
Example #7
0
    chain(
        sorted(glob('../problems/qbsolv/bqp50_*'))[:problems_per_group],
        sorted(glob('../problems/qbsolv/bqp100_*'))[:problems_per_group],
        sorted(glob('../problems/qbsolv/bqp250_*'))[:problems_per_group],
        sorted(glob('../problems/qbsolv/bqp500_*'))[:problems_per_group],
        sorted(glob('../problems/qbsolv/bqp1000_*'))[:problems_per_group],
        sorted(glob('../problems/qbsolv/bqp2500_*'))[:problems_per_group],
        sorted(glob('../problems/random-chimera/2048*'))[:problems_per_group],
        sorted(glob('../problems/random-chimera/8192*'))[:problems_per_group],
        sorted(glob('../problems/ac3/*'))[:problems_per_group],
    ))

workflows = [
    ("10s-tabu", lambda **kw: hybrid.TabuProblemSampler(timeout=10000)),
    ("10k-sa", lambda **kw:
     (hybrid.IdentityDecomposer()
      | hybrid.SimulatedAnnealingSubproblemSampler(sweeps=10000)
      | hybrid.SplatComposer())),
    ("qbsolv-like",
     lambda qpu, energy_threshold, **kw: hybrid.Loop(hybrid.Race(
         hybrid.InterruptableTabuSampler(timeout=200),
         hybrid.EnergyImpactDecomposer(
             size=50, rolling=True, rolling_history=0.15)
         | hybrid.QPUSubproblemAutoEmbeddingSampler(qpu_sampler=qpu)
         | hybrid.SplatComposer()) | hybrid.ArgMin(),
                                                     max_iter=100,
                                                     convergence=10,
                                                     terminate=None
                                                     if energy_threshold is
                                                     None else lambda en: en <=
                                                     energy_threshold)),