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.

Using OMMX Quantum Benchmarks: Implementing and Benchmarking Quantum Algorithms with Qamomile

Tags: integration optimization variational

This tutorial shows how to run a Qamomile quantum algorithm on a problem from a public benchmark dataset and compare its solution quality with a classical solver in the same workflow.

Goal. Build a QAOA solver in Qamomile, run it on a Low Autocorrelation Binary Sequences (LABS) instance loaded from the OMMX Quantum Benchmarks dataset, and compare the result with the classical SCIP solver accessed through the ommx-pyscipopt-adapter. Because both the QAOA path and the SCIP path consume the same ommx.v1.Instance, the main difference is the algorithm itself. This makes the comparison direct.

What is OMMX Quantum Benchmarks?

OMMX (Open Mathematical prograMming eXchange) is a data format for exchanging mathematical optimization problems across tools. Its ommx.v1.Instance stores the objective, constraints, and decision-variable metadata.

OMMX Quantum Benchmarks is a curated collection of optimization benchmark instances distributed in this ommx.v1.Instance format. The first dataset shipped is QOBLIB (Quantum Optimization Benchmarking Library) arXiv:2504.03832, which contains nine problem families used in the recent quantum-optimization literature, including LABS, Market Split, Independent Set, and Steiner-tree packing.

Because each benchmark instance is represented as an ommx.v1.Instance, any Qamomile workflow that accepts ommx.v1.Instance, including QAOAConverter, can consume these problems without writing any extra code. In addition, a reference solution is provided in the ommx.v1.Solution format and can be used to evaluate benchmark results. The same Instance can also be passed to classical OMMX adapters such as ommx-pyscipopt-adapter, so one problem definition can support both quantum and classical workflows.

Problem: Low Autocorrelation Binary Sequences (LABS)

LABS asks for a binary sequence s=(s0,s1,…,sn−1)∈{−1,+1}n\boldsymbol{s} = (s_0, s_1, \dots, s_{n-1}) \in \{-1, +1\}^n whose off-diagonal autocorrelations

ck(s)=∑i=0n−k−1si si+k,k=1,2,…,n−1c_k(\boldsymbol{s}) = \sum_{i=0}^{n-k-1} s_i \, s_{i+k}, \qquad k = 1, 2, \dots, n-1

are as close to zero as possible. The benchmark objective is the sum of squared autocorrelations

E(s)=∑k=1n−1ck(s)2,E(\boldsymbol{s}) = \sum_{k=1}^{n-1} c_k(\boldsymbol{s})^2,

which we want to minimize. LABS is NP-hard and has long served as a stress test for both classical and quantum heuristics.

Loading a LABS instance

Labs exposes two models: "integer" (uses integer decision variables for ckc_k plus the constraints that tie them to s\boldsymbol{s}) and "quadratic_unconstrained" (a QUBO reformulation that introduces auxiliary binary variables zi,kz_{i,k} encoding the products xixi+k+1x_i x_{i+k+1} via a quadratic penalty). The QUBO form is the natural target for QAOA, so we use it here.

Dataset:           02_labs
Available models:  ['integer', 'quadratic_unconstrained']
Instance count:    99
First 5 instances: ['labs002', 'labs003', 'labs004', 'labs005', 'labs006']

We pick labs005, the n=5n=5 instance. The QUBO reformulation uses n+n(n−1)=25n + n(n-1) = 25 binary variables (5 sequence bits xix_i plus n(n−1)=20n(n-1) = 20 auxiliary zi,kz_{i,k} bits). After Instance.to_qubo() folds the penalty terms into the objective and inactive variables are pruned, this becomes a 15-qubit problem: small enough to simulate locally, but large enough that QAOA is non-trivial.

OMMX variables:    25
OMMX constraints:  0
Reference E(s):    2.0
Reference feasible: True

The bundled reference solution gives the known optimum E⋆=2E^\star = 2 for n=5n=5. We will compare both QAOA and SCIP against this value.

Algorithm: QAOA

Rather than use the high-level QAOAConverter, we build the QAOA workflow from scratch with @qkernel, following the recipe in QAOA for MaxCut: Building the Circuit from Scratch. Refer to that tutorial for the gate-by-gate derivation; here we focus on the implementation.

Spin model from the OMMX instance

Instance.to_qubo() converts the penalty-form ommx.v1.Instance into a QUBO. We then wrap it in a BinaryModel and switch to the spin (-1/+1) domain, which is what the QAOA cost layer expects. We also normalize the coefficients so the energy scale stays comparable across runs.

QAOA qubits: 15

Cost Hamiltonian

To use the exact expectation value rather than a shot estimate for the optimization, we build the Ising cost Hamiltonian directly from the spin-model coefficients: ZiZ_i terms for the linear part and ZiZjZ_i Z_j terms for the quadratic part.

QAOA qkernels

The ansatz uses three small qkernels: a uniform superposition, a cost layer, and a mixer layer. We compose them into a state-preparation qkernel qaoa_state, then wrap it twice: once with qmc.expval to get an expectation-value qkernel for the optimizer, and once with qmc.measure to get a sampling qkernel for the final shot histogram.

Transpile and optimize

Transpile both kernels with p=3p = 3. The expectation-value executable is used for the optimization; the sampling executable is used later for the final shot histogram. We feed the optimizer the exact expectation value of the cost Hamiltonian via Aer’s EstimatorV2 primitive, which keeps the BFGS finite-difference gradient free of sampling noise. We seed NumPy so the parameter trajectory is reproducible.

Optimized expectation value (normalized): 1.9622
Function evaluations:                     385
Wall time:                                9.34 s
<Figure size 800x400 with 1 Axes>

Final sampling

We sample once more with the optimized parameters and a larger shot count. Then we decode against the original ommx.v1.Instance, so the returned ommx.v1.SampleSet reports the original QUBO objective directly. In this QUBO formulation, samples whose auxiliary zz variables correctly encode the products xixi+k+1x_i x_{i+k+1} incur no penalty, and the objective equals the LABS energy E(s)=∑kck2E(\boldsymbol{s}) = \sum_k c_k^2. Samples that violate the implicit z=xixi+k+1z = x_i x_{i+k+1} relation incur an additive penalty.

Shots:                4096
QAOA best objective:  2
Reference E*:         2

Distribution of objective values

QAOA returns a distribution over bitstrings, not a single answer. The histogram below shows the QUBO objective of every shot at the optimized parameters. The red dashed line marks the reference optimum E⋆E^\star. Samples on, or just to the right of, that line have xx values that minimize the LABS sum and zz values that correctly encode the products. Samples far to the right pay a penalty for inconsistent zz values.

<Figure size 800x400 with 1 Axes>

Classical baseline: SCIP via the OMMX adapter

SCIP is a branch-and-bound-based MILP/QUBO solver that can find the exact optimal solution. The same ommx.v1.Instance is consumed by ommx_pyscipopt_adapter.OMMXPySCIPOptAdapter.solve, which hands the problem to SCIP via PySCIPOpt and returns an ommx.v1.Solution evaluated against the original instance. Its .objective is therefore directly comparable to QAOA’s.

SCIP E(s):    2
SCIP feasible: True
Wall time:    0.177 s

Results comparison

SCIP returns a single optimum deterministically, while QAOA returns a distribution over bitstrings. We report QAOA’s best shot (the lowest-objective bitstring seen across all samples) and its hit rate on the reference optimum (the fraction of shots that achieved E⋆E^\star).

Solver                     E(s)     Time (s)
----------------------------------------------
Reference (bundled)           2            -
SCIP (classical)              2        0.177
QAOA (best shot)              2         9.34

QAOA hit rate on E* = 2: 4.6%  (4096 shots)

Two observations make this benchmark meaningful:

  1. Optimum. Both SCIP and the best QAOA shot reach the reference optimum E⋆=2E^\star = 2, so QAOA is capable of finding the optimal sequence at n=5n = 5 with only p=3p = 3.

  2. Concentration. QAOA’s value lies in concentrating sampling probability on low-energy bitstrings. The hit rate above, together with the left tail of the histogram, is the quantitative version of that statement.

Note that the wall-time figures are only indicative. SCIP’s timing is just the solver’s runtime on the CPU, while the QAOA timing covers the full classical-quantum optimization loop on a state-vector simulator; both depend on the execution environment. A genuinely fair comparison would therefore require a more careful methodology. Either way, combining Qamomile with datasets like OMMX Quantum Benchmarks makes it easy to compare quantum algorithms and classical solvers across a variety of metrics.

Summary

In this tutorial we:

  1. Loaded a LABS instance straight from the OMMX Quantum Benchmarks dataset as an ommx.v1.Instance.

  2. Extracted the QUBO with Instance.to_qubo(), wrapped it in a BinaryModel, switched to the spin domain, and ran a hand-written QAOA ansatz (using @qkernel) against it through QiskitTranspiler + AerSimulator.

  3. Compared the QAOA output (best shot, hit rate, sampling distribution) against SCIP via ommx_pyscipopt_adapter.OMMXPySCIPOptAdapter.solve on the same instance, plus the reference optimum bundled with the benchmark.

The pattern generalizes: any other QOBLIB dataset (Marketsplit, IndependentSet, Network, …) plugs into the same pipeline: load with the corresponding dataset class, extract the QUBO via Instance.to_qubo(), and reuse the same BinaryModel + QAOA ansatz + transpile loop. Larger instances will eventually outgrow local simulators, at which point the same executable can be re-targeted to other Qamomile quantum SDK integrations (QuriPartsTranspiler, CudaqTranspiler, …) or real hardware.