qalgora-Q Docs Hub量子文档 ✦ Ask AI✦ 问问文档

QAOA for Max-Cut

◐ Design-level API
This page documents qalgora-Q API design, architecture, or adaptation workflows. Code examples illustrate intended usage and are not guaranteed to run in the current reference implementation.

The Quantum Approximate Optimization Algorithm (QAOA) finds good cuts of a graph by alternating a problem (cost) layer with a mixer layer and classically tuning the per-layer angles. It is the canonical example of a variational quantum algorithm applied to combinatorial optimization.

The problem it solves

Given a graph, partition its vertices into two sets so that as many edges as possible cross the partition — this is Max-Cut. It is NP-hard: known exact classical algorithms grow exponentially with the number of vertices in the worst case. Max-Cut looks abstract, but it is the kernel of many practical tasks such as clustering, circuit layout, and network partitioning.

In QAOA each vertex maps to a qubit. Whether each bit of the string is 0 or 1 decides which side that vertex falls on; the cut is read directly from the measured bitstring. Our goal is to make the quantum circuit concentrate high probability on the bitstrings that correspond to high-quality cuts.

Encoding the problem into a Hamiltonian

The first step of QAOA is to translate "maximize the number of cut edges" into "minimize an energy". For each edge (i, j) we introduce a term 0.5·(ZiZj − 1). The Pauli Z operator gives +1 on bit 0 and −1 on bit 1, so:

  • When both endpoints are on the same side (both 0 or both 1), ZiZj = +1 and the term is 0 — this edge is not cut and contributes nothing.
  • When the endpoints are on opposite sides, ZiZj = −1 and the term is −1 — this edge is cut.

Summing over all edges gives the cost Hamiltonian HC. Its ground-state energy equals −(maximum number of cut edges). So "maximize the cut" turns into "minimize ⟨HC⟩" — a clear target a quantum computer can aim at.

The variational ansatz — two alternating unitaries

QAOA starts from a uniform superposition of all bitstrings (one layer of Hadamards), then alternately applies two kinds of unitary, for p layers total:

UnitaryRole
Cost unitary e−iγHCControlled by the parameter γ. It attaches a phase to each bitstring according to its cost: the better the cut, the more the phase turns. It does not change measurement probabilities by itself, but it engraves structure for the interference that follows.
Mixer unitary e−iβHMControlled by the parameter β, usually with HM = Σ Xi. Each X rotates a qubit about the x-axis, moving amplitude between bitstrings so that the phase differences engraved by the cost layer turn into gains and losses in probability.

One "cost + mixer" layer is parameterized by a pair of angles (γ, β). p layers thus have 2p parameters. A classical optimizer repeatedly tunes these angles to make the measured ⟨HC⟩ as low as possible. This is what variational means: the quantum circuit prepares and measures the trial state, while the classical loop searches for better angles.

Why it works — the connection to adiabatic evolution

Why does this alternating structure approach the answer? With a suitable angle sequence and a large enough number of layers p, QAOA can be understood as a discretized approximation of the adiabatic evolution path: prepare the system in the easy-to-make ground state of the mixer Hamiltonian (the uniform superposition), then gradually hand the Hamiltonian over from the mixer term to the cost term, so the system tends to stay near its instantaneous ground state and approach the ground state of HC — the optimal cut. The QAOA angle sequence (γ1, β1, …, γp, βp) can be seen as one discretized sampling of this adiabatic path. This connection offers intuition, but performance at small p still depends mainly on angle optimization and the structure of the problem.

The key point is that QAOA does not require slowness. Even for small p, optimized angles often achieve approximation ratios far better than random guessing. Because the circuit is shallow at small p, QAOA has been regarded as a candidate algorithm suited to NISQ hardware; in practice, however, its performance still depends strongly on noise, connectivity, compilation overhead, and the sampling budget.

What it is good at — and what it isn't

  • It gives an approximate solution, not a proven optimum. QAOA outputs a "good" cut with no guarantee of global optimality and usually no certificate of optimality.
  • Shallow depth limits expressive power. At a fixed small p there is a provable upper bound on the achievable approximation ratio; approaching the optimum often needs larger p, and deeper circuits accumulate more noise. There is a real tension between depth and quality.
  • The classical competition is strong. For Max-Cut, classical approximation algorithms like the Goemans–Williamson semidefinite program perform excellently and are well battle-tested. Demonstrating a clear quantum advantage for QAOA at practical scale remains an open problem.
  • The optimization itself can be hard. The angle landscape has barren plateaus and many local minima that the outer classical optimizer can get stuck in — a shared pain point of variational algorithms.
An honest positioning
QAOA is an elegant, general optimization template, especially well suited to teaching and near-term hardware experiments. But treat it as a "promising candidate", not a "settled winner": whether it beats the best classical heuristics on real problems must be verified case by case.

The algorithm, step by step

  1. Encode the target problem (here, Max-Cut) into a cost Hamiltonian HC.
  2. Prepare a uniform superposition of all bitstrings with Hadamard gates.
  3. Alternately apply the cost unitary (angle γl) and the mixer unitary (angle βl), for p layers.
  4. Measure and estimate ⟨HC⟩; hand it to the classical optimizer.
  5. The optimizer updates all 2p angles, repeating the above until convergence.
  6. Sample the circuit repeatedly at the optimal angles and read off the most probable bitstring as the recommended cut.

Seeing it in code

First encode the graph into the cost Hamiltonian. Note that 0.5 * (spin.z(i) * spin.z(j) - 1.0) is exactly the term above: it is −1 when the endpoints are on opposite sides, counting one cut edge.

import qalgora
from qalgora import spin

# square graph: 4 nodes, 4 edges
edges = [(0, 1), (1, 2), (2, 3), (3, 0)]
n_qubits = 4

# cost Hamiltonian: sum over edges of 0.5*(Z_i Z_j - 1)
cost = 0
for i, j in edges:
    cost += 0.5 * (spin.z(i) * spin.z(j) - 1.0)

The circuit ansatz carries the structure above directly into code: a Hadamard on every qubit prepares the uniform superposition; the inner x.ctrl … rz(γ) … x.ctrl sandwich is the cost unitary applied edge by edge (engraving a cost-dependent phase on each edge); the closing rx(2·β) on each qubit is the mixer unitary. layers is exactly the number of layers p.

Angle conventions. We take Rz(θ) = exp(−iθZ/2) and Rx(θ) = exp(−iθX/2). Under the per-edge cost term 0.5·(ZiZj − 1), the CNOT–Rz–CNOT sandwich realizes exp(−iγ·0.5·ZiZj) with the cost-layer rotation rz(γ) (not rz(2γ)), while the mixer is rx(2β) because exp(−iβX) = rx(2β).

@qalgora.kernel
def qaoa(gammas: list[float], betas: list[float], layers: int):
    q = qalgora.qvector(4)
    for i in range(4):
        h(q[i])                           # uniform superposition
    for l in range(layers):
        for i, j in [(0, 1), (1, 2), (2, 3), (3, 0)]:
            x.ctrl(q[i], q[j])
            rz(gammas[l], q[j])           # cost layer: Rz(gamma) for 0.5(Z_iZ_j-1)
            x.ctrl(q[i], q[j])
        for i in range(4):
            rx(2.0 * betas[l], q[i])       # mixer layer

Finally the outer classical optimization. objective sends the current angles into the circuit and returns the expectation value of cost — that is, the ⟨HC⟩ we want to minimize; COBYLA is a gradient-free optimizer that searches for better (γ, β). After convergence we sample once more and read off the most probable cut.

layers = 2
optimizer = qalgora.optimizers.COBYLA()

def objective(params):
    gammas, betas = params[:layers], params[layers:]
    return qalgora.observe(qaoa, cost, gammas, betas, layers).expectation()

energy, params = optimizer.optimize(dimensions=2 * layers, function=objective)
print("best cut value:", -energy)

# sample the optimized circuit to read out the partition
counts = qalgora.sample(qaoa, params[:layers], params[layers:], layers)
print("most probable cut:", counts.most_probable())
Specification API — not in the open reference build yet
This example shows a qalgora-Q specification API (or a third-party library) that the open reference build does not bundle today. It documents the intended interface; to run code now, use the reference build’s supported core API.
Try it yourself
Raise layers from 1 up to 3 and watch how the best cut value improves with depth — but also notice the optimization getting harder and more prone to sticking in local minima. The Grover and transverse-field Ising model pages reuse the same superposition-and-interference ideas.

References

  • E. Farhi, J. Goldstone, S. Gutmann, "A quantum approximate optimization algorithm," (2014). arXiv:1411.4028

QAOA 求解最大割问题

◐ 设计接口
本页描述的是 qalgora-Q 的接口设计、架构设计或适配工作流。相关代码用于说明预期用法,当前参考实现不保证可以直接运行。

量子近似优化算法 (QAOA) 通过交替施加问题(代价)层与混合层,并经典地调优各层角度,从而在图中找到较优的割。它是变分量子算法用于组合优化的范例。

它解决的问题

给定一张图,将其顶点划分为两个集合,使得跨越划分边界的边数尽可能多——这就是最大割。它是 NP 困难问题:精确求解的已知经典算法在最坏情况下随顶点数指数增长。最大割看似抽象,却是聚类、电路布局、网络划分等众多实际任务的内核。

在 QAOA 中,每个顶点对应一个量子比特。比特串中的每一位是 0 还是 1,决定该顶点落入哪一侧;割的结果直接从测量得到的比特串中读出。我们的目标,是让量子线路把高概率集中在那些对应高质量割的比特串上。

把问题编码进哈密顿量

QAOA 的第一步,是把"最大化割边数"翻译成"最小化一个能量"。对每条边 (i, j),我们引入一项 0.5·(ZiZj − 1)。泡利 Z 算符在比特 0 上取值 +1、在比特 1 上取值 −1,于是:

  • 当两端同侧(同为 0 或同为 1)时 ZiZj = +1,该项为 0——这条边没被割开,不贡献。
  • 当两端异侧时 ZiZj = −1,该项为 −1——这条边被割开了。

把所有边相加得到代价哈密顿量 HC。其基态能量等于 −(最大割边数)。于是"最大化割"就转化为"最小化 ⟨HC⟩"——一个量子计算机可以瞄准的明确目标。

变分拟设 交替的两类幺正算符

QAOA 从所有比特串的均匀叠加态出发(一层 Hadamard),随后交替施加两类幺正算符,共 p 层:

算符作用
代价幺正算符 e−iγHC由参数 γ 控制。它依据每个比特串的代价为其附加一个相位:割得越好的串,相位偏转越多。它本身不改变测量概率,却为后续的干涉刻下结构。
混合幺正算符 e−iβHM由参数 β 控制,通常取 HM = Σ Xi。每个 X 绕 x 轴旋转一个比特,在不同比特串之间搬运振幅,让代价层刻下的相位差转化为概率上的此消彼长。

一层"代价 + 混合"由一对角度 (γ, β) 参数化。p 层就有 2p 个参数。一个经典优化器反复调节这些角度,使测得的 ⟨HC⟩ 尽量低。这正是变分之意:量子线路负责制备并测量试探态,经典回路负责搜索更好的角度。

为何有效 与绝热演化的联系

为何这套交替结构能逼近答案?在合适的角度序列和足够大的层数 p 下,QAOA 可被理解为对绝热演化路径的一种离散化近似:先把系统制备在混合哈密顿量的易得基态(均匀叠加),再逐步地把哈密顿量从混合项过渡到代价项,系统便倾向于停留在瞬时基态附近,最终逼近 HC 的基态——即最优割。QAOA 的角度序列 (γ1, β1, …, γp, βp) 可看作这条绝热路径的一次离散化采样。这一联系提供直觉,但小 p 下的性能仍主要取决于角度优化与问题结构。

关键在于:QAOA 不要求缓慢。即便 p 很小,经过优化的角度也常能取得远好于随机猜测的近似比。由于小 p 线路较浅,QAOA 曾被视为适合 NISQ 硬件的候选算法;但实际性能仍强烈依赖噪声、连通性、编译开销与采样预算。

它擅长什么 又不擅长什么

  • 它给出的是近似解,而非证明的最优。QAOA 输出"较好"的割,并不保证全局最优,也通常不附带最优性证书。
  • 浅层深度限制表达力。在固定的小 p 下,可证明的近似比有上界;要逼近最优往往需要更大的 p,而更深的线路又会累积更多噪声。深度与质量之间存在真实的张力。
  • 经典对手很强。对最大割,Goemans–Williamson 半定规划等经典近似算法表现优异且久经检验。要在实用规模上证明 QAOA 的明确量子优势,至今仍是开放问题。
  • 优化本身可能很难。角度空间存在贫瘠高原与大量局部极小,外层经典优化器可能陷入其中——这是变分算法共同的痛点。
诚实的定位
QAOA 是一个优雅、通用的优化模板,尤其适合教学与近期硬件实验。但请把它当作"有前景的候选",而非"已经胜出的方案":它在实际问题上是否超越最好的经典启发式,仍需逐案验证。

算法逐步拆解

  1. 把目标问题(此处为最大割)编码成代价哈密顿量 HC
  2. 用 Hadamard 门制备所有比特串的均匀叠加。
  3. 交替施加代价幺正算符(角度 γl)与混合幺正算符(角度 βl),共 p 层。
  4. 测量并估计 ⟨HC⟩;把它交给经典优化器。
  5. 优化器更新全部 2p 个角度,重复上述步骤直至收敛。
  6. 用最优角度反复采样线路,读出概率最高的比特串作为推荐割。

对照代码理解

下面先把图编码成代价哈密顿量。注意 0.5 * (spin.z(i) * spin.z(j) - 1.0) 正是上文那一项:两端异侧时取 −1,记一条被割开的边。

import qalgora
from qalgora import spin

# square graph: 4 nodes, 4 edges
edges = [(0, 1), (1, 2), (2, 3), (3, 0)]
n_qubits = 4

# cost Hamiltonian: sum over edges of 0.5*(Z_i Z_j - 1)
cost = 0
for i, j in edges:
    cost += 0.5 * (spin.z(i) * spin.z(j) - 1.0)

线路拟设把上文的结构直接搬进代码:对每个比特施加 Hadamard 制备均匀叠加;内层 x.ctrl … rz(γ) … x.ctrl 这段夹层就是按边施加的代价幺正算符(在每条边上刻下依代价而定的相位);末尾对每个比特的 rx(2·β) 即混合幺正算符。layers 正是层数 p。

约定 Rz(θ)=exp(−iθZ/2)、Rx(θ)=exp(−iθX/2);在单边代价项 0.5(ZiZj−1) 下,代价层旋转角为 rz(γ),mixer 为 rx(2β)。

@qalgora.kernel
def qaoa(gammas: list[float], betas: list[float], layers: int):
    q = qalgora.qvector(4)
    for i in range(4):
        h(q[i])                           # uniform superposition
    for l in range(layers):
        for i, j in [(0, 1), (1, 2), (2, 3), (3, 0)]:
            x.ctrl(q[i], q[j])
            rz(gammas[l], q[j])           # cost layer: Rz(gamma) 对应 0.5(Z_iZ_j-1)
            x.ctrl(q[i], q[j])
        for i in range(4):
            rx(2.0 * betas[l], q[i])       # mixer layer

最后是外层经典优化。objective 把当前角度送进线路,返回 cost期望值——也就是上文要最小化的 ⟨HC⟩;COBYLA 是无梯度优化器,负责搜索更优的 (γ, β)。收敛后再 sample 一次,读出概率最高的割。

layers = 2
optimizer = qalgora.optimizers.COBYLA()

def objective(params):
    gammas, betas = params[:layers], params[layers:]
    return qalgora.observe(qaoa, cost, gammas, betas, layers).expectation()

energy, params = optimizer.optimize(dimensions=2 * layers, function=objective)
print("best cut value:", -energy)

# sample the optimized circuit to read out the partition
counts = qalgora.sample(qaoa, params[:layers], params[layers:], layers)
print("most probable cut:", counts.most_probable())
规范接口 · 参考实现暂未包含
此示例展示的是 qalgora-Q 规范中的接口(或第三方库),开放参考实现目前尚未内置,仅用于说明预期用法;如需立即运行,请使用参考实现已支持的核心 API。
动手试试
layers 从 1 逐步加到 3,观察最优割值如何随深度提升而改善——也留意优化变得更难、更易卡在局部极小。Grover横场 Ising 模型页面复用了同样的叠加与干涉思想。

参考文献

  • E. Farhi, J. Goldstone, S. Gutmann, "A quantum approximate optimization algorithm," (2014). arXiv:1411.4028