Skip to content

Repository files navigation

bloqade-python-mis

A Bloqade plugin implementing quantum-classical hybrid optimization for Maximal Independent Set (MIS) and k-MaxCut problems on neutral atom quantum computers.

This repo is the code associated with the paper "Solving non-native combinatorial optimization problems using hybrid quantum-classical algorithms" (Wurtz, Sack, Wang — IEEE Transactions on Quantum Engineering, 2024). Also on arXiv:2403.03153.

Warning: This is unmanaged research code intended to reproduce results of the paper.

Background

Classical combinatorial optimization problems like MIS are not naturally expressed as Rydberg Hamiltonian ground states. This codebase implements the Non-Native Hybrid Algorithm (NNHA) framework from the paper, which avoids that limitation: instead of requiring the quantum device to directly produce solutions, it uses quantum measurement outcomes as a resource for classical postprocessing routines.

The framework defines three algorithm types, each using the quantum device differently:

TypeQuantum roleClassical roleProblem
Type 1Individual bitstrings as warm starts1-local greedy add/remove to enforce independenceUnit disk MIS
Type 2Connected correlation functions as featuresSpectral clustering (k-means on eigenvectors)Max k-Cut
Type 3Full measurement distribution as a reservoirCluster simulated annealing with sandpile updatesUnit disk MIS

The quantum ansatz is a piecewise-linear adiabatic state preparation on neutral atom arrays, run on QuEra's Aquila (256-qubit). Pulse parameters (time, initial/final detuning) are optimized variationally.

Installation

Requires Python ≥ 3.10.

uv sync

Architecture

Problem

Defines the combinatorial optimization target and its cost function.

ClassModuleDescription
unit_disk_maximum_independent_setbloqade.postprocess.problem.MIS_problemMIS on a unit disk graph defined by atom positions and a blockade radius
maximum_independent_setbloqade.postprocess.problem.MIS_problemMIS on an arbitrary graph
k_maxcutbloqade.postprocess.problem.k_maxcutGraph k-partitioning (MaxCut generalization)

Solution

Wraps a parameterized Rydberg ansatz and a classical postprocessing strategy.

ClassTypeDescription
greedy_MIS_solutionType 1Quantum bitstrings warm-start a greedy MIS algorithm (remove conflicts, then greedily add)
classical_greedy_MIS_solutionType 1 baselineSame postprocessing from all-zeros (no quantum)
spectral_kmaxcut_solutionType 2Eigenvectors of the quantum connected-correlation matrix feed k-means clustering
tempering_MIS_solutionType 3Quantum distribution seeds cluster simulated annealing via sandpile-model updates
classical_tempering_MIS_solutionType 3 baselineSame annealing from classical sampling (greedy or all-zeros)

All solutions share a common interface:

  • ansatz(quantum_parameters) — builds the parameterized Bloqade program
  • get_solution(quantum_parameters, classical_parameters) — returns candidate solutions
  • objective(...) — scalar cost for the optimizer
  • submit(quantum_parameters) — dispatches to the configured backend

Optimizer

bloqade.postprocess.optimizer.base_optimizer.Optimizer — a VQE-style loop supporting:

  • "SPSA" — simultaneous perturbation stochastic approximation
  • "Bayesian" — Gaussian process optimization via scikit-optimize
  • "Random" — uniform random search over bounds
  • Any scipy.optimize.minimize method string

Supports parameter bounds, fixed indices, callback tracking, and JSON serialization for resuming runs.

Backends

Pass a backend dict to any Solution constructor:

{"quantum": "python_emulate", "num_shots": 20} # local Python ODE solver
{"quantum": "braket_emulate", "num_shots": 100} # Braket local emulator
{"quantum": "braket_aquila", "num_shots": 100} # AWS Braket → Aquila hardware
{"quantum": "internal_aquila","num_shots": 100} # QuEra direct hardware access

Usage

Type 1: Greedy MIS (local emulator)

frombloqade.postprocess.problem.MIS_problemimportunit_disk_maximum_independent_setfrombloqade.postprocess.solution.greedy_MISimportgreedy_MIS_solution, classical_greedy_MIS_solutionfrombloqade.postprocess.optimizer.base_optimizerimportOptimizerimportbloqade.postprocessaspostprocessimportnumpyasnp# Define a unit disk MIS problem from atom positionspositions=np.array(...) # shape (N, 2), coordinates in units of blockade radiusproblem=unit_disk_maximum_independent_set(positions, threshold=0.72)
# Build a quantum solution using the local Python emulatorsolution=greedy_MIS_solution(problem, backend={"quantum": "python_emulate", "num_shots": 20})
# Optimize pulse parameters with SPSAx_init=solution.flatten_parameters(
{"time": 1.5, "initial_detuning": -15, "final_detuning": 15}, {}
)
optimizer=Optimizer(solution, method="SPSA", initial_guess=x_init, max_iter=50)
optimizer()

See postprocessing_implementations/ for complete runnable examples:

ScriptPaper typeProblemBackendStrategy
type1_MIS.pyType 1Unit disk MISpython_emulateGreedy warm-start postprocessing
type2_kmaxcut.pyType 2Max 3-Cutbraket_aquilaSpectral clustering of correlations
type3_MIS.pyType 3Unit disk MISbraket_aquilaSandpile cluster simulated annealing

Development

uv sync # install dependencies
uv run pytest tests/ # run tests
uv run black src/ tests/ # format
uv run ruff check src/ tests/ # lint

Namespace package

This package extends the bloqade namespace. It requires bloqade >= 0.34.0 (which provides bloqade.analog) and contributes bloqade.postprocess and bloqade.utils subpackages.

About

Bloqade plug-in for generating Maximal Independent Set problems for Bloqade.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages