4. 参数化量子电路构建
变分量子本征求解器(VQE)的核心计算单元是参数化量子电路(Parameterized Quantum Circuit, PQC)。它由固定结构的量子门序列和一组可调参数 θ 组成,通过不断调整 θ 使测量得到的期望值逼近目标哈密顿量的基态能量。本节聚焦工程实现层面:如何用 Qiskit 和 PennyLane 搭建可微分电路、如何绑定参数、以及如何获得梯度接口。
一、参数化电路的基本结构
一个典型的 VQE 拟设(ansatz)由三部分组成:初态制备、参数化层、测量。以 4 量子比特的硬件高效拟设为例,初态通常为 |0000⟩,参数化层由交替的旋转门层和纠缠层构成。旋转层使用 Ry(θ) 或 Rz(θ) 对每个量子比特施加单比特旋转,纠缠层使用 CNOT 或 CZ 构建量子比特间的关联。层数 L 与量子比特数 n 共同决定参数总数:若每层每个量子比特一个旋转参数,则参数维度为 n×L。
选择拟设时需权衡表达能力与训练难度。硬件高效拟设参数少、易映射到真实拓扑,但可能无法覆盖目标基态;UCCSD 等化学启发拟设表达能力强,但参数多、电路深。工程上常从硬件高效拟设起步,若能量收敛不理想再增加层数或改用问题定制拟设。
二、Qiskit 实现:从电路到梯度
在 Qiskit 中,参数化电路通过 QuantumCircuit 配合 Parameter 对象构建。每个可调角度用 Parameter('θ_i') 表示,电路构建完成后得到一个含自由参数的模板。参数绑定使用 assign_parameters() 方法,将具体数值字典注入模板,生成可执行的绑定电路。
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
import numpy as np
n, L = 4, 2
params = [Parameter(f'θ{i}') for i in range(n * L)]
qc = QuantumCircuit(n)
idx = 0
for layer in range(L):
for q in range(n):
qc.ry(params[idx], q)
idx += 1
for q in range(n - 1):
qc.cx(q, q + 1)
# 绑定一组具体参数
values = np.random.uniform(0, 2*np.pi, n * L)
bound = qc.assign_parameters(dict(zip(params, values)))
梯度计算方面,Qiskit 提供 Estimator 原语配合 Gradient 对象。参数移位规则(parameter-shift rule)是核心:对每个参数 θ_i,梯度由两个偏移电路期望值之差除以 2 得到,即 ∂⟨H⟩/∂θ_i = [⟨H⟩(θ_i+π/2) − ⟨H⟩(θ_i−π/2)] / 2。这一规则适用于所有形如 exp(−iθP/2) 的门,Ry、Rz、Rx 均满足。
from qiskit.primitives import Estimator
from qiskit.algorithms.gradients import ParamShiftEstimatorGradient
estimator = Estimator()
gradient = ParamShiftEstimatorGradient(estimator)
job = gradient.run([qc], [hamiltonian], [values])
grads = job.result().gradients[0]
需要注意:Estimator 返回的是每个观测量项的期望值加权和,梯度对象则对每个参数分别计算偏导。若哈密顿量有 M 项,参数移位法每轮需 2×n×L 次电路执行,工程上应尽量复用中间结果或采用伴随梯度(adjoint)降低开销。
三、PennyLane 实现:自动微分与接口统一
PennyLane 的设计哲学是“量子电路即函数”。用 @qml.qnode(dev) 装饰器将量子函数编译为可微节点,参数以张量形式传入,框架自动追踪计算图并调用反向传播或参数移位规则求梯度。与 Qiskit 相比,PennyLane 的接口更接近经典深度学习,适合与 PyTorch、TensorFlow、JAX 混合使用。
import pennylane as qml
from pennylane import numpy as pnp
dev = qml.device("default.qubit", wires=4)
@qml.qnode(dev, interface="autograd")
def circuit(params):
for layer in range(2):
for q in range(4):
qml.RY(params[layer, q], wires=q)
for q in range(3):
qml.CNOT(wires=[q, q + 1])
return qml.expval(hamiltonian)
params = pnp.random.uniform(0, 2*np.pi, (2, 4), requires_grad=True)
grad_fn = qml.grad(circuit)
grads = grad_fn(params)
PennyLane 的 qml.grad 默认对含参门使用参数移位规则,对 default.qubit 等模拟器也可启用反向传播(diff_method="backprop"),后者在参数较多时速度优势明显。若后端为真实硬件,则必须使用参数移位或有限差分,因为硬件无法执行反向传播。
四、参数绑定与梯度接口的工程要点
参数绑定不是一次性动作,而是优化循环中的高频操作。每次迭代都需要将当前参数向量注入电路模板,再提交执行。为降低开销,应尽量在编译阶段完成电路结构固定,仅将参数作为运行时输入。Qiskit 的 ParameterVector 和 PennyLane 的数组参数都支持这种“模板+绑定”模式。
梯度接口的选择直接影响训练效率与精度。参数移位规则精确但电路执行次数随参数线性增长;反向传播精确且一次前向即可得全部梯度,但仅适用于模拟器;有限差分实现简单但存在截断误差,步长选择敏感。工程建议:模拟器阶段优先用反向传播快速验证拟设与优化器;迁移到硬件前切换为参数移位,并检查梯度数值是否与模拟器一致。
五、一个可运行的训练片段
以下示例用 PennyLane 搭建 4 量子比特、2 层拟设,目标哈密顿量取横场伊辛模型的简化形式,优化器用 Adam,学习率 0.1,迭代 50 步。每步记录能量,观察是否单调下降并趋于稳定。
import pennylane as qml
from pennylane import numpy as pnp
dev = qml.device("default.qubit", wires=4)
# 示例哈密顿量:H = -Σ Z_i Z_{i+1} - 0.5 Σ X_i
coeffs = [-1.0]*3 + [-0.5]*4
obs = [qml.PauliZ(i) @ qml.PauliZ(i+1) for i in range(3)] + \
[qml.PauliX(i) for i in range(4)]
H = qml.Hamiltonian(coeffs, obs)
@qml.qnode(dev, interface="autograd", diff_method="parameter-shift")
def cost(params):
for layer in range(2):
for q in range(4):
qml.RY(params[layer, q], wires=q)
for q in range(3):
qml.CNOT(wires=[q, q+1])
return qml.expval(H)
params = pnp.random.uniform(0, 2*np.pi, (2, 4), requires_grad=True)
opt = qml.AdamOptimizer(stepsize=0.1)
for step in range(50):
params, energy = opt.step_and_cost(cost, params)
if step % 10 == 0:
print(f"step {step:3d} energy = {energy:.6f}")
运行后典型输出会显示能量从初始随机值逐步下降,50 步后趋于某个稳定值。该稳定值是否接近真实基态能量,取决于拟设表达能力与优化是否收敛。若能量停滞在较高值,可尝试增加层数、更换纠缠拓扑或调整学习率。