Пример #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
Пример #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
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()

# show execution profile
hybrid.profiling.print_counters(workflow)
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)
Пример #5
0
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, num_sweeps=n_sweeps) for beta in betas[1:]])

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

# we'll run update/swap sequence for `n_iterations`
workflow = hybrid.Loop(update | swap, max_iter=n_iterations) \
         | hybrid.MergeSamples(aggregate=True)

# execute the workflow
solution = workflow.run(replicas).result()
Пример #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