Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Local Simulated and Quantum Annealing

Maintained by the JuliaQUBO organization
SECQUOIA  ·  PSR Energy

Open In Colab

One JuliaQUBO model interface, five examples, local simulated annealing, and an explicitly optional handoff to a cloud-hosted D-Wave quantum annealer.

This clean-room tutorial uses original Julia code and prose. It cites, but does not copy implementation material from, the Five Starter Problems paper and its companion repository.

Setup

The default path is local, credential-free, deterministic after dependency installation, and covered by make verify-annealing-julia-local. It reads only the committed cancer-genomics aggregate under notebooks_data/.

The optional QPU section is disabled unless QUBONOTEBOOKS_ANNEALING_ENABLE_QPU=1. Set DWAVE_API_TOKEN in the process environment or hosted secret store before opting in. Never paste a token into a cell or save it in notebook output.

Local installation

From the repository root, instantiate the checked-in Julia project before opening Jupyter:

julia --project=notebooks_jl -e 'using Pkg; Pkg.instantiate()'

Google Colab

Open the badge above, select a Julia runtime, and run the setup cells. The bootstrap clones this repository only when necessary and activates the same checked-in Julia project used by local verification.

Notebook Cell
Notebook Cell

Learning objectives

By the end of this notebook you will be able to:

  1. Configure reproducible simulated annealing with explicit reads, sweeps, a schedule type, and a seed.

  2. Send five independently decoded QUBOs through one DWave.jl/JuMP runner.

  3. Compare sampled energies with exact optima where enumeration is appropriate.

  4. Distinguish local effective algorithm time, user-observed wall time, and QPU access time.

  5. Opt into a cloud-hosted D-Wave QPU without duplicating formulations or exposing secrets.

Prerequisites

Prior notebooks: QUBO objective conventions from Notebook 2; the three canonical formulations from Notebook 7; the corrected order-partitioning model from Notebook 8; and the aggregate-only cancer-genomics limitations from Notebook 9.

Julia 1.10+ and the checked-in notebooks_jl environment are required. No account or network call is needed after dependencies are installed unless you explicitly enable the QPU section.

Simulated annealing concepts

Simulated annealing starts at a comparatively high temperature, where an energy-increasing move of size ΔE>0\Delta E>0 may be accepted with Metropolis probability exp⁡(−ΔE/T)\exp(-\Delta E/T). As temperature falls (equivalently, inverse temperature β=1/T\beta=1/T rises), uphill moves become less likely.

  • A sweep proposes updates across all variables once.

  • A read is one complete annealing run and returns one sample.

  • Repeated samples are aggregated with occurrence counts.

  • The schedule determines how inverse temperature changes across sweeps.

The local wrapper reports an effective algorithm-call duration. We separately measure user-observed wall time around optimize!. Neither should be labeled as QPU access time. A live QPU result reports hardware timing in microseconds; that field has different scope and must not be compared as if it were local wall time.

Local annealing runtime ready: DWave 0.7.6, Ocean 9.3.0.

One solver interface for five models

Each problem record owns only formulation and decoding behavior. Optimizer selection lives in a separate configuration record, so the local and QPU paths cannot drift into different models.

(label = "DWave.Neal", optimizer = DWave.Neal.Optimizer, attributes = Dict{String, Any}("num_sweeps" => 1000, "num_reads" => 256, "beta_schedule_type" => "geometric", "seed" => 96096))
quadratic_density
build_order_model
decode_order (generic function with 1 method)
decode_cancer (generic function with 1 method)
Prepared five solver-interchangeable models.
run_annealing

Seeded local comparison

All five models now pass through the same runner. The four small examples use independent exhaustive baselines. For the 33-variable aggregate, every returned state is checked for energy and decoded-metric consistency, but the sampled best is not a proof of global optimality.

Seeded DWave.Neal comparison: seed=96096, reads=256, sweeps=1000.
Validated every returned state for all five models.
solver | problem | n | density | reads | best raw energy | decoded score | feasible | exact successes/probability | local effective s | user wall s | qpu access μs
DWave.Neal | number partitioning | 4 | 1.000 | 256 | 0.000 | imbalance=0 | true | 214/0.836 | 0.625441 | 8.217921 | n/a
DWave.Neal | weighted Max-Cut | 4 | 0.833 | 256 | -7.000 | cut weight=7 | true | 255/0.996 | 0.014620 | 0.016497 | n/a
DWave.Neal | minimum vertex cover | 4 | 0.667 | 256 | 2.000 | cover size=2 | true | 253/0.988 | 0.014708 | 0.016633 | n/a
DWave.Neal | order partitioning | 6 | 1.000 | 256 | 28.000 | value Δ=2; risk²=20 | true | 92/0.359 | 0.023844 | 0.025673 | n/a
DWave.Neal | cancer-genomics aggregate | 33 | 0.360 | 256 | -43.050 | coverage bounds=106–109 | true | n/a (exact optimum not claimed) | 0.152059 | 0.155185 | n/a

The exact-success columns answer a narrow reproducibility question: how many reads reached an independently enumerated optimum on a small instance. They do not establish solver superiority. The cancer row deliberately reports n/a for exact success; its aggregate supports exact QUBO energy and rigorous distinct-patient bounds, not a global-optimality or clinical claim.

Local effective seconds and user wall seconds are both local measurements with different overhead. They are not QPU access time and are not evidence of quantum advantage.

Optional D-Wave QPU path

Where the quantum annealing runs: in the cloud, not on this machine. The simulated annealing above is local, but there is no local quantum annealer: DWave.Optimizer submits the problem over the network to a physical quantum processing unit hosted in D-Wave’s Leap cloud service. Enabling this section therefore needs network access and a Leap account, adds queue wait to the elapsed time, and draws on that account’s solver quota.

This section uses the same maxcut_problem record as the local run. Opt-in changes only the optimizer/configuration. DWave.Optimizer discovers an available QPU through the configured Leap account; no device identifier is hard-coded. The initial DWave.jl import temporarily masks any ambient token, so solver discovery cannot occur on the default path. Missing credentials fail before optimize! can submit work.

Live QPU execution is a manual, credentialed target and its outputs are not committed. The default notebook run prints a disabled message.

sanitized_qpu_metadata
D-Wave QPU execution is disabled. Set QUBONOTEBOOKS_ANNEALING_ENABLE_QPU=1 and provide DWAVE_API_TOKEN through a secret store to opt in.
Topology and embedding plots skipped because QPU execution is disabled.

Reading a live result responsibly

If you opt in, record the discovered solver/topology, reads, annealing time, returned chain strength and embedding parameters when exposed, and qpu_access_time with its microsecond unit. QPU access time covers QPU programming and sampling components defined by D-Wave; it is not the elapsed time a notebook user sees, and it is not comparable to the local Neal timing columns as though they measure the same work.

Tutorial-scale success counts can demonstrate interface behavior. They cannot support claims of production performance, solver superiority, or quantum advantage.

Practice checkpoints

Use these small checks to connect the configuration and reporting choices to the concepts above.

Notebook Cell
At T=4, uphill acceptance is 0.6065; at T=0.5, it is 0.0183.
Notebook Cell
number partitioning: 214/256 exact-optimum reads
weighted Max-Cut: 255/256 exact-optimum reads
minimum vertex cover: 253/256 exact-optimum reads
order partitioning: 92/256 exact-optimum reads
Notebook Cell
Local effective algorithm time excludes some notebook overhead; user wall time surrounds optimize!; QPU access time measures hardware programming/sampling in microseconds. Their scopes differ.

Summary

  • One shared JuMP/DWave.jl runner handled number partitioning, weighted Max-Cut, minimum vertex cover, corrected order partitioning, and the bounded cancer-genomics aggregate.

  • The default Neal path fixed reads, sweeps, schedule type, and seed and independently recomputed every returned energy.

  • Four small examples were compared with exhaustive optima; the larger aggregate was decoded without claiming global optimality.

  • The optional QPU path fails closed on missing credentials, discovers a solver through DWave.jl, sanitizes metadata, and uses public topology/embedding APIs.

  • Timing fields remain explicitly separated, and no quantum-advantage claim is made.

Learning objectives met: You configured a deterministic local annealer, validated five formulations through one interface, separated timing scopes, and audited a fail-closed QPU handoff.

Next steps: Revisit Notebook 10 to compare the QAOA interface boundary, or run the QPU section manually with an approved Leap secret and record only the sanitized fields defined above.

Further reading:

References

References
  1. Mazumder, A. R., & Tayur, S. (2025). Five Starter Problems: Solving Quadratic Unconstrained Binary Optimization Models on Quantum Computers. In Tutorials in Operations Research: Advances in Analytics and Operations Research: Improving Decisions to Secure the Future (pp. 145–183). INFORMS. 10.1287/educ.2025.0288