首页/博客/如何在变分量子算法中将采样次数削减 80%
OptimizationVQEQAOAQPU

如何在变分量子算法中将采样次数削减 80%

减少 VQE 与 QAOA 所需电路执行次数的实用技巧——采样节俭型优化器、梯度估计诀窍以及测量分组。

FreeQuantumComputing
·· 8 min read

每次在真实硬件上运行量子电路,都会消耗 QPU 时间和金钱。像 VQE 和 QAOA 这样的变分算法可能需要数十万次电路执行才能收敛——在云端 QPU 上每个任务的费用为 $0.075–$0.90,累加起来很快就会变得可观。

好消息是:大多数默认实现的采样效率极其低下。只要采用正确的技巧,你就可以在不牺牲结果质量的前提下,将采样需求削减 50–90%。

为什么默认的采样次数如此之高

VQE 计算 Pauli 算符的期望值。哈密顿量被分解为一组 Pauli 项之和,而每一项都需要单独执行一次电路。对于像 H₂(4 个量子比特)这样的分子,大约有 15 个 Pauli 项。对于更大的分子,数量则会爆炸式增长:

分子量子比特数Pauli 项数朴素方案每次迭代的采样次数
H₂41515,000
LiH12631631,000
BeH₂14666666,000
H₂O141,0861,086,000

若进行 200 次优化器迭代,H₂O 在朴素方案下需要 2.17 亿次采样。下面介绍的技巧可以将其削减 80–95%。

技巧 1:测量分组(收益最大)

许多 Pauli 项是对易的——它们可以在单次电路执行中同时测量,而不必分开测量。将对易的可观测量分组,是可用手段中单项收益最大的一种。

from qiskit.primitives import StatevectorEstimator
from qiskit_nature.second_q.mappers import JordanWignerMapper
from qiskit_algorithms import VQE
from qiskit_algorithms.optimizers import COBYLA

# Qiskit automatically groups commuting Paulis in the Estimator primitive
# This reduces shots from O(n_terms) to O(n_groups) — often 5-10x reduction
estimator = StatevectorEstimator()

# With PennyLane, use grouping explicitly:
import pennylane as qml

H = qml.Hamiltonian(coeffs, observables)

# Group commuting terms — usually reduces term count by 5-10x
groups = qml.grouping.group_observables(observables, grouping_type='qwc')
print(f"Original terms: {len(observables)}, Groups: {len(groups)}")
# Original terms: 631, Groups: 68  (for LiH)

预期节省:在典型的化学哈密顿量上可达 5–15×。

技巧 2:采样节俭型优化器

像 L-BFGS-B 或 ADAM 这样的经典优化器假设函数求值无噪声——当结果带有噪声时,它们请求的梯度求值次数超过了必要的数量。采样节俭型优化器会根据测量方差自适应地分配采样次数。

from pennylane.optimize import AdaptiveOptimizer, ShotAdaptiveOptimizer

dev = qml.device("default.qubit", wires=4)

@qml.qnode(dev)
def circuit(params):
    # ansatz
    ...
    return qml.expval(H)

# ShotAdaptiveOptimizer: allocates more shots to high-variance directions
opt = ShotAdaptiveOptimizer(min_shots=10)

params = np.random.uniform(-np.pi, np.pi, n_params)
for i in range(100):
    params, _, shots_used = opt.step_and_cost(circuit, params)
    print(f"Step {i}: shots used = {shots_used}")

该优化器起初每次求值只用很少的采样次数,只有当梯度不确定时才增加采样次数。一次典型的 VQE 运行相比固定采样次数的 COBYLA,可以减少 5–10× 的采样

技巧 3:参数移位梯度(使用更少的求值次数)

朴素的有限差分梯度估计 (f(x+ε) - f(x))/ε 在 ε 很小时方差很大,在 ε 很大时偏差很大。参数移位规则只需每个参数 2 次电路求值即可给出精确梯度:

# PennyLane uses parameter-shift by default for gradients
@qml.qnode(dev, diff_method="parameter-shift")  # 2 evals per param
def circuit(params):
    ...

# Compare to finite-difference (requires 1 eval per param but biased):
@qml.qnode(dev, diff_method="finite-diff")  # 1 eval but approximate

# For large circuits, use "best" — PennyLane chooses adjoint on simulator,
# parameter-shift on hardware
@qml.qnode(dev, diff_method="best")
def circuit(params):
    ...

对于 n 个参数,参数移位每一步梯度需要 2n 次求值。当 n 很大时,请使用无梯度优化器(COBYLA、SPSA、Nelder-Mead)。

技巧 4:SPSA——随机梯度估计

同步扰动随机逼近(SPSA)通过同时扰动所有参数,无论参数数量多少,都只需 2 次电路求值即可估计出完整梯度:

from qiskit_algorithms.optimizers import SPSA

# SPSA: 2 evaluations per step regardless of parameter count
# vs parameter-shift: 2n evaluations per step
optimizer = SPSA(maxiter=300, learning_rate=0.1, perturbation=0.05)

# For 10 parameters:
# - Parameter shift: 2×10 = 20 evals/step × 300 steps = 6,000 total
# - SPSA: 2 evals/step × 300 steps = 600 total  ← 10x reduction

最适用于: 电路含有大量参数(> 10)时。代价是每一步的收敛更慢,但总采样次数更少。

技巧 5:提前终止 + 方差阈值

当结果已经足够好时,不要把电路运行到底:

from pennylane.optimize import AdamOptimizer
import numpy as np

opt = AdamOptimizer(stepsize=0.02)
params = init_params.copy()
prev_energy = float('inf')

for step in range(max_steps):
    params, energy = opt.step_and_cost(circuit, params)

    # Stop when change is below shot-noise floor
    variance = 1.0 / np.sqrt(shots_per_eval)  # shot noise floor
    if abs(energy - prev_energy) < variance:
        print(f"Converged at step {step}")
        break

    prev_energy = energy

许多 VQE 运行会提前进入平台期——继续运行只是把采样浪费在噪声波动上。

技巧 6:热启动

用相关的经典解而非随机值来初始化 QAOA 或 VQE 参数:

# For QAOA on Max-Cut: warm start from a greedy classical solution
import networkx as nx

G = nx.from_edgelist(edges)
classical_cut = nx.algorithms.approximation.one_exchange(G)

# Map classical solution to initial QAOA angles
# γ₀ ≈ π/4 for a good cut, β₀ ≈ π/8
init_gamma = [np.pi / 4]
init_beta = [np.pi / 8]

# Warm-started QAOA typically converges in 30-50% fewer iterations

综合运用:一个实用的 VQE 模板

import pennylane as qml
import numpy as np
from pennylane.optimize import ShotAdaptiveOptimizer

dev = qml.device("default.qubit", wires=n_qubits, shots=512)

# 1. Group commuting terms (5-10x reduction in circuit count)
grouped_H = qml.Hamiltonian(*qml.grouping.group_observables(H))

@qml.qnode(dev, diff_method="parameter-shift")
def ansatz(params):
    # Hardware-efficient ansatz
    for i in range(n_qubits):
        qml.RY(params[i], wires=i)
    for i in range(n_qubits - 1):
        qml.CNOT(wires=[i, i + 1])
    return qml.expval(grouped_H)

# 2. Use shot-adaptive optimizer
opt = ShotAdaptiveOptimizer(min_shots=50)

# 3. Warm start
params = warm_start_params(H)

# 4. Run with early stopping
for step in range(300):
    params, energy, shots = opt.step_and_cost(ansatz, params)
    if check_convergence(energy, shots):
        break

print(f"Ground state energy: {energy:.4f} Ha")

速查表:各方法的采样预算

方法每步采样次数最适用于
COBYLA + 固定采样n_terms × shots参数数量较少
参数移位 + Adam2n_params × shots可微电路
SPSA2 × shots参数数量较多
ShotAdaptiveOptimizer自适应通用 VQE
分组 Pauli÷5–15×始终优先应用

请优先应用测量分组——它是单项收益最大的手段,而且无需改动你的优化器或电路。

相关内容: VQE with PennyLane · QPU access guide · HLQuantum