ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零搭建VQE:用参数化量子电路与优化器求解分子基态能量

从零搭建VQE:用参数化量子电路与优化器求解分子基态能量 2. 从零搭建 VQE先准备好你的量子算盘这里我默认你已经会写最基本的量子电路了——知道RX、RY、CNOT这些门怎么摆也知道 Bloch 球大概是怎么回事。如果这些还有点儿模糊建议先用手边的框架跑几个小例子热热身不然直接上 VQE 会被各种符号砸晕。另外Python 环境最好准备干净一点建议用 Anaconda 或者 venv 单独建一个虚拟环境避免依赖冲突。2.1 量子态制备用参数化电路捏出一个试探态VQE 的核心思路是先猜一个量子态然后不断调整它的形状直到它对应的能量最低。这个猜的过程就是用量子电路来实现的。我们把这种电路叫做参数化量子电路Parameterized Quantum Circuit, PQC也有人叫它变分电路。为什么非得用参数化电路因为量子态是个极其复杂的高维对象你不能凭空手写一个任意态出来——你是通过施加一系列量子门从一个初始态通常是 |0...0开始慢慢把它调制成目标态。而这些量子门的旋转角度就是我们要优化的参数。拿 H2 分子举例它只有 4 个自旋轨道所以量子比特数只需要 4 个。但现实中的分子动不动就几十上百个轨道你不能真的拿这么多量子比特去做实验。这时候就要用到一种叫映射的技巧把化学中的轨道空间映射到量子比特空间。最常用的映射有 Jordan-Wigner 变换和 Bravyi-Kitaev 变换前者实现简单、概念清晰后者更节省量子比特资源但电路复杂度更高。初学者建议先搞懂 Jordan-Wigner看代码的时候会轻松很多。所谓制备试探态字面意思就是用一组参数θ1, θ2, ...去控制量子门的旋转角度然后反复调节这组参数直到输出的量子态让能量期望值最小。就像捏橡皮泥你每捏一下形状就变一点直到捏出一个最满意的形状为止。2.2 Hamiltonian 的构造把分子的能量翻译成量子比特的语言物理学家早就告诉我们一个多电子体系的能量可以写成一个叫 Hamiltonian哈密顿量的算符它的本征值就是体系允许的能量。VQE 的目标就是找到这个 Hamiltonian 的最小本征值也就是体系的基态能量。但问题来了——Hamiltonian 是作用在电子上的电子是费米子它的数学描述用的是产生湮灭算符a†, a这套语言没法直接在量子比特上实现。所以你得把它翻译成泡利算符X, Y, Z的组合。翻译完之后你会得到一串这样的东西H -0.5 * (Z0 Z1) 0.2 * (X0 X1 Y0 Y1)每个项都对应量子线路中的一个测量任务。这个翻译过程非常关键因为 Hamiltonian 的项数直接决定了后续测量的复杂度。比如 H2 分子的 Hamiltonian 只有 15 项左右而更大的分子比如 LiH 或 BeH2项数会膨胀到几十上百项。每个项都要单独跑一次电路测量然后加权求和所以项数越多计算开销越大。这也是为什么 VQE 在 NISQ含噪声中等规模量子时代只能处理小分子的原因之一。2.3 优化器选择经典世界怎么指挥量子电路VQE 是个量子-经典混合算法意味着量子计算机负责测量经典计算机负责优化。你得有一个经典优化器根据测量结果反馈给量子电路告诉它下一步该往哪个方向调参数。这就是所谓的变分参数优化。最简单但也最经典的优化器是 COBYLA它不需要计算梯度只靠比较不同参数点的目标函数值来寻优。用在 VQE 上它的好处是抗噪声能力强因为每次评估都是个带统计误差的测量值COBYLA 这种直接比较型算法相对稳健。另一个常用的是 SPSA它是一种基于随机梯度估计的方法每次只做两次目标函数评估就能估算梯度特别适合量子测量这种高成本场景。至于 Adam 和 muon 这种经典机器学习优化器VQE 也能用但有个前提——你得能拿到梯度。要么通过参数平移规则parameter shift rule计算梯度要么用有限差分法近似。参数平移规则是量子计算里的一大法宝对某些门比如 RX、RY可以通过两侧平移 π/2 来精确估计梯度代价是要跑两倍电路。这个方法在理论上是精确的但在 NISQ 设备上会受到噪声干扰所以实际使用时还要结合去噪手段。注意优化器不是越先进越好。在噪声大的设备上花里胡哨的优化器往往不如简单的 COBYLA 实用。以小分子 VQE 为例COBYLA 在几十步内就能收敛到化学精度约千分之一 Hartree而 Adam 常常需要上百步耗时更长。3. 用代码撸一个 H2 分子的 VQE完整实操下面我就带你从零开始跑一个 H2 分子的基态能量计算。我这里用 Qiskit 这个框架主要是因为生态成熟、文档全面而且对初学者友好。当然你也完全可以改用 PennyLane 或其他框架原理完全一样。3.1 环境准备与安装这里我默认你已经装了 Python 3.9 以上版本然后一通操作pip install qiskit qiskit-natureqiskit-nature 是专门处理量子化学问题的库里面内置了分子数据库可以直接拿 H2、LiH 这些小分子来用而不用自己去推导 Hamiltonian。如果你不想用这个库那你就得手动做 Hartree-Fock 计算再手动算积分、做映射那过程会痛苦很多。作为从零开始的教程我们直接用现成工具把重点放在理解流程上。建议顺手装上 matplotlib 和 numpy因为后面要画收敛曲线pip install matplotlib numpy3.2 第一步构建分子的电子结构问题我们从最基础的 H2 分子开始。先定义它的几何构型——两个氢原子间距 0.735 埃这个距离大约是平衡键长附近。在 qiskit-nature 里这一步的代码非常简洁from qiskit_nature.units import DistanceUnit from qiskit_nature.second_q.drivers import PySCFDriver # 定义 H2 分子两个 H 原子距离 0.735 Å driver PySCFDriver( atomH 0.0 0.0 0.0; H 0.0 0.0 0.735, basissto3g, charge0, spin0, unitDistanceUnit.ANGSTROM ) # 生成电子结构问题 problem driver.run()这里选的是 STO-3G 基组是最小的基组。你可能会问为什么要用这么小的基组因为对教程来说最重要的不是化学精度而是把这个流程跑通。STO-3G 下的 H2 基态能量大约是 -1.85 Hartree 左右和实验值有偏差但完全够我们用来说明 VQE 算法的逻辑。等你自己理解了流程再换成更大的基组比如 6-31G也不迟。3.3 第二步获取 Hamiltonian 和初始态有了分子对象之后我们需要把它的电子结构问题转化成量子比特 Hamiltonian。这里涉及两步先做 HF 计算得到参考态再做费米子到比特的映射from qiskit_nature.second_q.mappers import JordanWignerMapper from qiskit_nature.second_q.transformers import ActiveSpaceTransformer # 定义活性空间保留 2 个空间轨道、2 个电子 transformer ActiveSpaceTransformer(num_electrons2, num_spatial_orbitals2) problem transformer.transform(problem) # 用 Jordan-Wigner 映射将费米子 Hamiltonian 转成泡利字符串 mapper JordanWignerMapper() hamiltonian mapper.map(problem.second_q_ops()[0]) # 获取 HF 初态参考态 initial_state problem.reference_occupied_occupations # 例如 [1, 1, 0, 0]这里的活性空间是一个非常工程化的概念你不必把所有轨道都纳入量子计算只需要选出一部分关键的轨道把其他轨道冻结掉。这既减少了量子比特数又不会损失太多精度。对于 H2 这种双电子体系两个空间轨道一个成键、一个反键足够了量子比特数被压缩到了 4 个。3.4 第三步设计参数化试探电路接下来是重头戏设计 PQC。我最常用的试探电路有两种一种是 Ry 旋转层 CX 纠缠层的交替结构硬件高效电路另一种是从化学直觉出发的 UCCSD 拟设酉耦合簇。前者电路简单、参数少适合跑通流程后者物理意义更强参数更多但表达能力更强。这里先用一个最简单的硬件高效电路from qiskit import QuantumCircuit import numpy as np # 量子比特数 4 num_qubits 4 params [] qc QuantumCircuit(num_qubits) # 第一层Ry 旋转 for i in range(num_qubits): theta Parameter(fθ_{i}_0) params.append(theta) qc.ry(theta, i) # 纠缠层相邻比特用 CX 门纠缠 for i in range(num_qubits - 1): qc.cx(i, i 1) # 第二层Ry 旋转 for i in range(num_qubits): theta Parameter(fθ_{i}_1) params.append(theta) qc.ry(theta, i) # 第三层再一组 CX 门增加表达力 for i in range(num_qubits - 1): qc.cx(i, i 1)这段代码的思路是先用旋转门把每个比特翻转到合适的位置再用纠缠门让它们产生量子关联最后再用旋转门做精细调整。这个结构在学术界有个名字叫硬件高效拟设Hardware Efficient Ansatz因为它在真实量子芯片上容易实现——只需要单比特旋转门和最近的 CNOT 门就能搭出来。注意这个电路只是众多选择之一。如果你在博客里看到 VQE 代码用 UCCSD 拟设也别觉得奇怪那是一种从量子化学理论出发、更化学友好的拟设只是电路深了很多在噪声设备上反而更难跑。3.5 第四步定义能量评估函数有了 Hamiltonian 和试探电路下一步就是定义一个函数给定一组参数 θ把电路跑一遍测量各个泡利项的期望值加权求和得到总能量。在 Qiskit 里有两种做法。初学者可以直接用 Estimator估计器这个 API它会封装好所有的测量和期望值计算from qiskit.primitives import Estimator estimator Estimator() def evaluate_energy(theta_values): param_dict dict(zip(params, theta_values)) # 测量 Hamiltonian 期望值 energy estimator.run(qc, hamiltonian, parameter_valuesparam_dict).result().values[0] return energy注意这里我没有额外加测量电路因为 Estimator 自动帮我们处理了测量。如果你用老版的 Qiskit0.x你就得手动对每个泡利项做基变换测量非常繁琐。新版确实香了不少。有一点必须提醒Estimator 默认使用理想无噪声模拟器所以结果很干净。如果你想模拟真实设备上的采样噪声就需要指定带噪声的后端或者限制 shots 数量。后面我会讲到这个坑。3.6 第五步优化器迭代跑起来现在到了整个 VQE 的心脏——优化循环。我用 scipy 里的 COBYLA 来当优化器因为它在评估次数少的情况下表现稳定from scipy.optimize import minimize import matplotlib.pyplot as plt history [] def callback(theta_values): energy evaluate_energy(theta_values) history.append(energy) print(f参数: {theta_values}, 能量: {energy:.6f} Hartree) # 初始参数全零其实就是没有旋转等于初始 HF 态 init_params np.zeros(len(params)) result minimize( evaluate_energy, init_params, methodCOBYLA, callbackcallback, options{maxiter: 200, tol: 1e-4} ) # 输出最终结果 print(f优化完成最小能量: {result.fun:.6f} Hartree) # 画收敛曲线 plt.plot(history) plt.xlabel(迭代次数) plt.ylabel(能量 (Hartree)) plt.title(VQE 收敛曲线) plt.show()跑完这个代码如果一切正常你会看到能量曲线从大约 -1.0 附近快速下降然后在一个平台期徘徊最终稳定在 -1.85 Hartree 左右。这个值就非常接近 FCI全组态相互作用的精确解了。这里有个细节为什么初始点是全零因为全零参数对应没有任何旋转此时电路输出的就是初始引用的 HF 态。从这个点出发优化器会让试探态逐渐由 HF 态演化加入电子关联效应从而把能量降下来。这非常直观——你只是把 HF 态当作起点然后在它周围探索更优的态。3.7 第四步真·第四步常见问题速查与避坑指南这一部分我把它单独拎出来因为 VQE 的报错和反直觉行为实在太多了几乎每个新人在跑通之前都会卡住一次。我把自己踩过的坑加上看别人踩过的坑整理成了一张速查表问题特征排查方向能量不收敛曲线上下震荡怎么都不下降优化器步长太大参数初始值不合适测量误差太大能量收敛到错误值曲线平滑但最终值和理论值差很远试探电路表达能力不足映射选择有误活性空间太小程序报错参数不匹配Parameter数量对不上参数化电路里 Parameter 对象和实际传入的数值数量不一致测量结果波动大同样的参数两次结果差距很大shots 太小噪声干扰建议增大 shots 或改用 Estimator 默认理想模拟优化器达到 maxiter还没收敛就停了增大 maxiter或改用带梯度的优化器收敛更快其中最常见的还是能量不收敛尤其是你一开始用 Adam 优化器的时候。Adam 是个特爱调学习率的优化器但在 VQE 这种采样有噪声的目标函数上它很容易被噪声带偏。我试验过很多次Adam 在无噪声模拟器上表现不错在带噪声的模拟器上就很容易炸相比之下 COBYLA 稳如老狗。3.8 再进一步从模拟器走向真实硬件前你必须知道的事如果你只是想在笔记本上体验一下 VQE那用模拟器足够了。但如果你真的打算把它跑在真实量子芯片上我建议你先冷静一下因为现实世界比模拟残酷得多。真实硬件上的噪声来源多种多样包括但不限于门误差每次量子门操作都可能有误差单比特门误差通常在 1e-3 量级双比特门在 1e-2 量级以上。读取误差测量比特时可能读错导致结果偏差。退相干量子比特的相干时间有限通常在几十微秒量级电路越长误差越大。这些误差积累起来会让 VQE 的能量评估非常不稳定。你在模拟器上测得的圆润收敛曲线放到真机上可能变成一坨毛刺。要缓解这个问题有两类思路一类是误差缓解error mitigation。最常用的包括 Zero-Noise ExtrapolationZNE和测量误差修正。Qiskit 里有 Mitiq 库可以做 ZNE思路是对电路做噪声放大然后外推回零噪声极限。这个方法在中小规模电路上效果还行但也不是万能的。另一类是降低电路深度。与其用深层的化学拟设不如用浅层的硬件高效拟设牺牲一部分表达能力换取更长的相干时间内能完成测量。在 NISQ 时代浅电路往往比深电路跑出来的结果更接近理论值因为门误差和退相干都更小。4. 让 VQE 更聪明的三种进阶技巧如果你已经顺利跑通了基础的 H2 VQE恭喜你踏入了量子化学模拟的门槛。但 H2 毕竟只是玩具想要处理更大的分子下面这几个进阶技巧你就必须掌握了。4.1 用更聪明的试探电路UCCSD 的物理直觉前面用的硬件高效拟设虽然简单但它没有利用分子体系的物理结构所以在大分子上往往需要很多层才能达到化学精度。这时候就该 UCCSD 登场了。UCCSD 的全称是 Unitary Coupled Cluster Singles and Doubles酉耦合簇单双激发。它的核心思想是基态波函数可以由 HF 参考态通过一系列指数化的单粒子、双粒子激发算符生成。物理直觉是基态不仅仅是一个 Slater 行列式而是很多行列式的叠加其中单激发和双激发占了主要成分。在量子电路里UCCSD 实现起来比硬件高效电路复杂得多因为它需要把指数算符分解成量子门序列。你可能需要在电路里塞进去几十个旋转门和 CNOT 门参数数量也大大增加。但好处也很明显它从一开始就朝着正确的化学方向搜索所以通常需要的优化迭代次数更少。实现 UCCSD 最省力的方式是用 qiskit-nature 自带的 UCCSD 类from qiskit_nature.second_q.circuit.library import UCCSD ansatz UCCSD( problem.num_spatial_orbitals, problem.num_particles, mapper, initial_stateinitial_state )它会自动根据活性空间的轨道数和电子数生成对应的参数化电路。你不需要手搓那一堆复杂的门序列——虽然如果你有兴趣手搓一遍能极大加深你对量子化学的理解但第一次跑通流程交给库就好。4.2 用并行化加速分子扫描一次跑一条势能曲线VQE 的一个典型应用场景是扫描势能曲线——比如把两个 H 原子的间距从 0.5 埃拉到 2.5 埃在每个间距上都跑一次 VQE得到能量曲线从而判断分子是否稳定、键长和离解能是多少。这个场景非常适合并行化因为每个几何构型的 VQE 是相互独立的。你可以用 multiprocessing 或者直接把任务丢到云端并行跑from multiprocessing import Pool def run_vqe_at_distance(dist): driver PySCFDriver( atomfH 0.0 0.0 0.0; H 0.0 0.0 {dist}, basissto3g ) # 省略中间步骤... return dist, final_energy distances np.linspace(0.4, 2.5, 10) with Pool(4) as pool: results pool.map(run_vqe_at_distance, distances)值得注意的是相邻几何构型的 VQE 优化结果是高度相关的。你可以用**热启动warm start**技巧先把上一个距离优化好的参数作为下一个距离的初始参数这样收敛速度会快很多。这就像你从一楼爬到二楼再上三楼比每次从一楼重新爬要省力得多。4.3 选择正确的工具Qiskit vs. PennyLane如果你准备认真做 VQE除了 Qiskit你还应该了解一下 PennyLane。PennyLane 最大的优势是它把量子计算和经典自动微分框架PyTorch、TensorFlow无缝集成在一起所以你在搭建 VQE 时可以直接用 PyTorch 的 autograd 来计算梯度代码写起来非常优雅。Qiskit 的优势则是生态完整量子化学模块 qiskit-nature 非常成熟内置的驱动和映射工具很省心。两个框架各有优劣我的建议是做量子化学模拟首选 Qiskit做机器学习相关实验首选 PennyLane。当然如果你已经熟悉其中一个也没有必要强行切换。我自己经常混合使用用 Qiskit 构建分子和 Hamiltonian再用 PennyLane 做优化。它们之间通过 OpenQASM 或者其他中间表示来传递电路。不过这种混合方式调试成本较高新手建议先专精一个框架。5. 一些容易被忽略但至关重要的小细节最后我把自己 VQE 实操中的几个独门心得分享一下。这些细节你在教科书上很难找到但它们常常决定了你的代码能不能收敛到化学精度。5.1 关于测量代价的控制VQE 的每个能量评估都要执行多次量子测量shots而 Hamiltonian 的项数往往很多。如果你不做任何优化一个 H2 分子的评估就要跑 15 次电路每次 1024 次射击大分子更夸张。这个成本在模拟器上无所谓但在真实硬件上是非常昂贵的。一个叫**分组测量commuting grouping**的技术可以把能对易的泡利项合并到一起一次电路测量同时得到多个项的值从而把测量次数从 O(N^4) 降到 O(N^3)。Qiskit 的 Estimator 和 SparsePauliOp 提供了这些功能默认就会做部分优化。你如果想要更细粒度地控制也可以自己实现分组策略。还有一个细节是shots 数量的动态调整。刚开始优化时参数变化幅度大能量梯度也大不需要太高的测量精度在快要收敛的区域能量曲线平坦需要更精确的测量来区分细微差异。你可以设计一个回调函数根据历史能量的变化幅度自动调整 shots 数。5.2 初始参数和热启动的价值我的经验是初始参数选择对 VQE 的收敛速度和最终精度影响极大。全零初始参数虽然稳定但如果你从 HF 态出发可能会卡在局部极小值尤其是体系有很强的关联效应时。一种提升鲁棒性的做法是先用小规模模拟跑一遍把优化好的参数作为真实硬件实验的初始参数。这被称为零噪声参数初始化或镜像初始化。另一种做法是用经典量子化学方法例如 CCSD算出的近似波函数来构造初始参数。好处是一开始就在好点附近优化器只需要做精细调整。5.3 VQE 的下一步测量误差消除与自适应变分方案最后再聊聊 VQE 这个方向目前还在发展中的几个热点。一个是ADAPT-VQE自适应变分量子本征求解器它不再使用固定的试探电路而是从一个空电路开始每次迭代根据梯度信息选择一个最重要的激发算符加进去。这样可以用最少的参数达到给定精度大大减少电路深度。我试过这个方案在模拟器效果非常好但代价是实现起来弧度复杂而且每一步都要做矩阵计算评估梯度计算瓶颈转移到了经典侧。另一个方向是把 VQE 纳入更大规模的量子-经典工作流中例如用于材料设计或催化剂筛选。这时候单个 VQE 的精度反而不是最关键的关键是整个流程如何自动化、如何并行化、如何把统计误差控制在可接受范围内。从这个角度看VQE 不仅仅是一个算法更是一整套工程实践。最后的最后回到最本质的一件事VQE 之所以能成立是因为量子计算机擅长处理高维波函数的叠加和干涉而经典计算机擅长参数优化。两者各司其职互相配合才让量子计算化学成为 NISQ 时代最有希望落地的应用之一。理解了这层逻辑你就掌握了 VQE 的精髓——剩下的不过是工程的打磨罢了。我在实际调试中体会最深的一件事是VQE 的报错信息往往非常不友好但你只要能沉下心一行行检查 Hamiltonian 的每一项、参数化电路的每一个门、优化器的每一步迭代就一定能找到问题所在。不要怕代码烦琐多调试几次你就会发现VQE 其实就是一个被包装得极其华丽的最小化问题——剥开那层量子力学的神秘外衣内核还是那个你熟悉的优化理论。把基础打牢后面的路就顺了。
返回列表