ARTICLE DETAIL

资讯详情

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

从零实现VQE:参数化量子电路求解分子基态能量的完整笔记

从零实现VQE:参数化量子电路求解分子基态能量的完整笔记 做量子化学计算的人应该都有过这种体验一边骂着经典算法在强关联体系上的种种限制一边不得不接受活性空间一扩大就疯狂吃内存的现实。我第一次在论文里看到VQE这个词时第一反应是“又一个把薛定谔方程塞进参数优化框架的噱头”直到自己动手把分子Hamiltonian映射成量子比特上的Pauli字符串、搭好参数化量子电路、再看着Adam优化器在能量曲面上一点点往下走才意识到这东西是真的能跑通。这篇东西就当作我从零实现VQE的一份完整笔记从量子态怎么准备、Hamiltonian怎么写到优化器怎么选怎么调全部用大白话拆开讲带上能直接复现的代码也顺带记录几个让我血压升高的坑。VQE这次没用教科书式的推导来开头就是因为我觉得它的核心逻辑特别简单一个不满足于经典解法的人想借量子计算机来求解一个本征值问题——最常见的就是分子的基态能量。你不需要先搞懂整台量子计算机只需要知道一个参数化的量子电路如何制备试探波函数一个实际问题如何被编码成Hamiltonian的期望值以及一个经典优化器如何帮你在海浪一样的能量曲面上找到最低点。1. VQE的核心思路把求本征值变成求最小值1.1 变分原理是VQE的“地基”VQE的全称是Variational Quantum Eigensolver翻译过来是变分量子本征求解器。它的底层逻辑其实不是量子力学专属任何一个学过量子力学基础的人都熟悉对于任意一个试探波函数ψ(θ)〉它在某个给定Hamiltonian H下的期望值永远大于等于真实基态能量E_gs也就是E(θ) 〈ψ(θ)Hψ(θ)〉 ≥ E_gs换句话说只要你准备了一族参数化的试探波函数那么这个波函数对能量的期望值就是基态能量的一个上界。你想让这个上界尽量逼近真实基态能量那就去调节参数θ让期望值减小。于是“求解哈密顿量的基态”这个听起来很高深的物理问题就被转换成了一个参数优化问题在一个可能很复杂的能量曲面上找最小值。这个思路经典计算里也在用比如量子化学里的变分法、Hartree-Fock方法本质上都是“选一个带参数的试探函数最小化能量期望”。只是经典计算机上试探函数能表达的空间太有限了而量子电路能准备的量子态复杂度可以远超经典计算机的表达能力这才是VQE的真正想象力所在。1.2 VQE的三块积木量子态、Hamiltonian、优化器从实现层面看一个VQE程序是由三个部件拼起来的缺一不可。第一块是量子态也就是你如何设计那个参数化的试探波函数ψ(θ)〉。量子态需要从一个容易制备的初态通常是最简单的Hartree-Fock态出发经过一个参数化的量子电路把参数θ烧进去最后输出一个对参数敏感的量子态。这个参数化电路在不同框架里有不同叫法PennyLane里叫Ansatz或templateQiskit里叫variational form中文社区里叫试探波函数或者拟设电路。第二块是Hamiltonian也就是你研究的那条能量表达式。VQE里Hamiltonian一般来自分子电子结构计算先做二次量子化再用Jordan-Wigner之类的变换把产生湮灭算符映射成可以作用在量子比特上的Pauli算子。最后得到的形式通常是一堆Pauli字符串的加权求和比如H c₀ I c₁ Z₀Z₁ c₂ X₀X₁ …每一项的期望值都可以在量子电路里直接测量。第三块是优化器。执行完电路、测量出能量期望值E(θ)之后经典计算机就接手活儿了根据E(θ)的大小计算下一个θ再传回量子电路重新制备量子态。这个经典优化器可以是无梯度方法COBYLA、Nelder-Mead也可以是需要梯度的Adam、SGD甚至更高级的量子自然梯度。用一句话概括整条流水线量子电路负责“准备量子态”测量过程负责“读出Hamiltonian期望值”经典优化器负责“更新量子态的参数”。这三块积木合在一起才构成一个完整的VQE缺了任何一块流程就断了。1.3 为什么现阶段非得是VQE而不是量子相位估计可能有人会问量子计算里不是有更“牛”的算法叫量子相位估计QPE吗理论上它能精确读出基态能量精度还能指数级提升为什么大家现在都扎堆做VQE答案其实很现实QPE需要的量子电路深度太长、逻辑门太多容错阈值的量子计算机还没落地NISQ时代根本跑不动。VQE的优势恰恰在于用浅电路和经典优化器来弥补硬件噪声从一个混合的量子经典架构切入尽可能兼容现阶段的量子处理器。这就像一个刚毕业的工程师账面理论一套一套QPE但实际下工地发现材料工具都差太远手头唯一靠谱的锤子是VQE先把活儿干起来再说。VQE不是终极答案但它是当前噪声中等规模量子时代最值得认真实践的算法之一。理解了VQE再看其他量子近似优化算法、量子机器学习里参数化量子电路的思想都会有融会贯通的感觉。2. 量子态的工程实现试探波函数怎么搭2.1 初态的选择从Hartree-Fock态出发在VQE里你几乎不会从一个全零态或者完全随机的量子态开始跑原因很朴素瞎猜的试探波函数离真实基态太远能量曲面又高又陡优化半天可能跌进某个局部极小值出不来。工程上最稳妥的做法是从一个化学上已经“说得过去”的初态出发这就是Hartree-Fock态。拿氢气分子H₂举例在STO-3G基组下它有4个自旋轨道两个电子占据能量最低的两个自旋轨道在量子比特编码里就是1100〉这个计算基态。你在电路最前面加上一层BasisState的制备相当于把“物理常识”直接塞进了电路起点。接下来的参数化酉变换负责在这个初态之上引入电子关联修正慢慢把波函数推向比Hartree-Fock更准确的方向。这个设计的妙处在于如果你把变分参数全部初始化为0那么电路就“退化成”Hartree-Fock电路能量初始值就是HF能量然后再通过调节参数把关联能慢慢赚回来。这种“以物理合理的态为起点”的做法既提高收敛速度又不至于让优化器一开始就在陌生地形里乱撞。2.2 硬件高效Ansatz最直接的参数化电路最常见的试探波函数之一叫硬件高效拟设Hardware-Efficient AnsatzHEA。它的思路非常粗暴把一堆单量子比特旋转门和一堆纠缠门交替堆叠起来形成一条有固定结构的参数化电路。旋转门的旋转角度就是需要优化的参数CNOT或者CZ门提供量子态之间的纠缠。比如整条电路的结构是先对每个比特作用R_y(θ)再用一串CNOT把相邻比特纠缠起来接着再来一层R_y循环往复。HEA的好处是电路深度浅跟硬件的拓扑结构好契合在真实量子芯片上实现的难度低。但它的毛病也明显没有物理图景的引导参数空间里经常充满“平原”梯度信号稀薄一旦比特数增加就容易碰到被称为贫瘠高原的现象梯度指数级衰减优化器几乎动不了。我在实际写代码时最常用的是“R_y CNOT环形纠缠”的组合。R_y可以把量子态振幅调成实参数范围内任意分布CNOT则把信息在比特间传播。两到三层这种结构就足够演示小型分子VQE的完整流程了。如果你只是想验证代码逻辑用这个就够了不必一上来就上复杂拟设。2.3 化学启发的UCCSD更物理但更贵如果你对精度有要求就不能满足于HEA这种“通用电路”。化学上更受信任的是UCCSD幺正耦合簇单双激发。它的思路是从Hartree-Fock态出发作用一个指数化的激发算符把电子从占据轨道激发到虚轨道再按耦合簇理论的方式叠加在一起形成一个幺正变换。UCCSD的优点是它有明确的化学含义每个参数对应一个激发振幅优化过程相当于在调整这些振幅逼近精确波函数。而且它做出来的波函数天然满足粒子数守恒、自旋对称性等物理约束不会像HEA那样得到“能量对但态根本不是合法电子态”的荒唐结果。代价也很直接要在量子电路上实现指数化算符需要把费米子激发算符经Jordan-Wigner映射成Pauli字符串再去做SU(2)指数分解电路深度会显著增加尤其是双激发部分——有6个Pauli项要分解。对于NISQ硬件实现UCCSD并不轻松工程上往往需要做各种裁剪和近似这也是为什么ADAPT-VQE这类“自动挑算子”的变体近年来这么火。2.4 电路深度和表达力的实际取舍关于量子态的工程实现最常被问的就是“那到底该用多深的电路”。这个问题没有标准答案但我有个粗线条的参考电路越深参数化量子态能覆盖的希尔伯特空间范围越大理论上能逼近的基态精度越高可与此同时优化难度和硬件噪声也在上涨参数稍微一动能量曲线就毛刺丛生。我做过一些实验对于H₂这种四比特体系浅的HEA大概1层就能收敛到很接近精确解对于LiH这种更大一点的体系可能就需要2层到3层再大一些的分子光靠堆深度是堆不出来的必须结合化学先验信息。所以选拟设时我的建议是先满足物理合理性再考虑电路可行性最后才追求炫酷。能用UCCSD的精简版解决就不要堆一个五种门交错的大杂烩。3. Hamiltonian的比特化从分子到Pauli字符串3.1 二次量子化的分子哈密顿量VQE里的Hamiltonian不是你在黑板上写的那种解析表达式而是一长串关于产生湮灭算符的二次型。这是因为我们处理的是多电子体系天然适合用产生湮灭算符来表达电子在不同自旋轨道之间的跳跃和相互作用。一般形式长这样H Σ h_pq a†_p a_q ½ Σ h_pqrs a†_p a†_q a_r a_s第一项是单电子积分描述电子动能和原子核对电子的吸引第二项是双电子积分描述电子之间的库仑排斥。在计算化学软件里这些积分系数都能算出来你不需要手工算但要知道分子Hamiltonian就是从这些系数拼出来的。二次量子化的物理直觉是我们不关心电子的具体位置只关心电子“占了哪些轨道”。经典计算里这个模型对应格点模型和能带到了VQE里每个自旋轨道对应一个量子比特“有无电子”就对应量子比特是0还是1。这一步是整个比特化通路的第一步。3.2 Jordan-Wigner变换费米子变成量子比特有了算符形式的Hamiltonian下一步是把它翻译成量子计算机能懂的语言也就是用Pauli矩阵写出来。最常用的翻译工具是Jordan-Wigner变换。它的核心规则是一个产生算符a†_p (X_p - iY_p)/2但要乘上它之前所有轨道上的Z矩阵。那个Z链也叫Jordan-Wigner弦是费米子反对易关系的直接后果。打个不严谨的比方想象一列座位每个座位代表一个轨道有人坐就是1空就是0。我想在5号座位“插入一个电子”不光要把5号座位的状态翻转出来还必须先确认1到4号座位上坐了几个人。这个“确认过程”就是Z链的物理来源。如果你的轨道顺序排得不好哈密顿量里会冒出无数长串的Z⊗Z⊗…⊗X项电路测量开销蹭蹭往上涨。好消息是这些变换不需要你手写。PennyLane里一行qml.qchem.molecular_hamiltonian()就把符号、坐标、基组变成Hamiltonian对象了Qiskit里也有对应方法。但理解了Jordan-Wigner你在遇到奇奇怪怪的Pauli字符串时才知道自己手里拿的到底是什么。3.3 期望值测量Pauli字符串怎么在电路中读出Hamiltonian以Pauli字符串加权求和的形式出现后计算E(θ)〈ψ(θ)Hψ(θ)〉就分解成了对所有Pauli项期望值的加权求和。每一项比如Z₀Z₁在电路里怎么测答案是先按当前参数跑完参数化电路再在计算基上做测量。测Z就是直接的基态测量读0记1读1记-1测X就要先加一个H门做基变换测Y要先加H和S门。这一套思路就是Pauli测量的标准操作。测量永远无法在一次运行中完成真实硬件上你需要重复准备态、执行电路、读取结果很多次统计频率来估计期望值。这就是采样过程采样次数越多期望值估计的误差越小误差大概是O(1/√N)。在仿真器上这件事不痛不痒因为可以拿到精确的期望值一旦上了真实硬件采样开销会立刻变成整个算法最大的成本之一。3.4 测量分组怎么压缩采样开销既然采样开销这么贵工程上就得想办法省。第一招叫测量分组如果两个Pauli字符串对易而且满足更严格的qubit-wise对易条件那它们可以放在同一次电路运行里测量一次采样同时读出好几项的值。比如Z₀Z₁和Z₀I₁可以同一轮测完而X₀X₁和Y₀Y₁就不行。这个分组优化在实际VQE里极其重要它能把采样次数从“每个Pauli项各自测”变成“按组测”有时能省一个数量级。我在做硬件实验时习惯先用经典程序把哈密顿量按对易关系分组再逐组设计测量基。PennyLane和Qiskit都提供了分组工具但我还是建议你至少手动验证一次最小例子搞明白哪些项能合在一起哪些不能。只有亲手排过一次H₂的6个Pauli项你才会明白这个优化为什么那么多人研究。4. 优化器的选择能量曲面上的修行4.1 优化器在VQE里的角色有多重要很多教程讲VQE讲到Hamiltonian映射就收尾了优化器往往一句“用经典优化器梯度下降”带过。但实际跑下来优化器对收敛速度、最终精度的影响能大到让你怀疑是不是算错了。VQE里的能量曲面不是简单碗形状它有平台、有沟壑、有局部极小值而且量子测量噪声还会给这个曲面蒙上一层“毛玻璃”让梯度变得不确定。我习惯把优化器分成两类需要梯度的和不需要梯度的。需要梯度的优化器Adam、SGD、自然梯度等在无噪声仿真中表现优异收敛快、精度高不需要梯度的优化器COBYLA、Nelder-Mead、SPSA等在真实硬件上更抗噪因为每次迭代只要一个能量值不用额外跑梯度测量。选择哪个优化器不取决于哪个“更先进”而取决于你手上是理想的模拟器还是有噪声的芯片。4.2 Adam、COBYLA、SPSA的实测对比我分别用H₂在同样的四比特拟设上跑过Adam、COBYLA和SPSA结果差异相当明显。Adam在默认学习率0.05左右大概二三十步就能收敛到化学精度曲线下降顺利COBYLA在前五十步降得也很快但到后半段开始像蜗牛一样挪最终精度倒是还可以SPSA因为梯度是随机近似收敛曲线毛刺多但它在真实硬件上的表现往往比噪声下的Adam更稳。我把它们的特性整理成了一个表方便你按场景快速选优化器类型每次迭代成本抗噪声能力适用场景Adam梯度类需梯度测量中无噪声模拟器、理想实验COBYLA无梯度类单点能量高真实硬件、小参数规模SPSA随机梯度类两次能量估计高中大规模硬件实验自然梯度几何类度规梯度中对参数空间曲率敏感时这里特别提一下最近社区里火过的muon优化器核心思路是把动量的计算方式改成逐参数的二阶量级调整本质上也是一种对参数空间几何的自适应。虽然在量子电路参数优化里还没有成熟的评测结论但这类新优化器如果做得好未来移植到变分量子算法里很有想象空间。4.3 梯度从哪来参数移位法则如果你选了梯度类优化器下一步要面对的问题就是量子电路里参数的梯度怎么算。答案不是靠反向传播而是靠参数移位法则。对于一个参数化门U exp(-iθP/2)P是Pauli矩阵能量期望值f(θ)对参数θ的偏导数等于∂f/∂θ [f(θ π/2) - f(θ - π/2)] / 2也就是说你只需要把同一个电路分别在参数平移π/2和-π/2的位置各跑一遍就能从两个期望值相减得到梯度。这条规则是PennyLane、Qiskit等框架里自动求梯度的核心原理也被称为analytic gradient。自己实现的时候可以直接抄这个公式写一个梯度函数用框架时PennyLane的qml.grad会自动帮你调用这套机制。理解了参数移位法则你就能明白为什么梯度类优化器在真实硬件上成本高——一个参数就要额外跑两遍电路参数一多开销线性上涨。4.4 学习率与收敛看曲线形状再动手对梯度类优化器学习率是要关心的头号超参数。学习率太大能量值会在底部来回震荡甚至发散学习率太小前半段跑得慢优化过程漫长。我一般从0.1开始试看前二十步的能量曲线如果一路下降没有锯齿说明可以稍微加大如果曲线发抖或者反弹就把学习率除以三。这个过程其实很像你在游戏本里手动拖显卡的频率-电压曲线——工具箱里的曲线塑型优化器也是先观察曲线形状再决定往哪个方向调VQE里对能量曲线的观察策略是相通的。另外对无梯度方法初始步长也类似COBYLA默认步长对某些Hamiltonian尺度可能太大可以把参数做了归一化再优化。至于收敛判据在模拟器里我习惯看能量两轮之间的差值小于1e-8就停在有噪声的硬件上就现实一点差到1e-3或者0.001 Hartree已经算不错了毕竟化学精度本身也在1.6e-3 Hartree附近。5. 从零手写VQE完整代码与运行记录5.1 代码环境与依赖说明下面这段完整实现我用的是PennyLane因为它对参数化量子电路和自动微分的支持非常直接代码写出来比Qiskit少一层包装更适合讲清原理。依赖只有三样Python 3.10及以上PennyLane建议0.36以上版本NumPy安装直接一条命令pip install pennylane。跑模拟器不需要连接任何云资源默认的default.qubit后端就够了。5.2 三段式构造分子→Hamiltonian→量子电路整个流程可以拆成三步。第一步是用qml.qchem.molecular_hamiltonian读入分子几何、基组直接得到Hamiltonian对象。我用的H₂几何参数是两原子间距0.74Å对应的坐标在STO-3G基组下有4个自旋轨道对应4个量子比特。第二步是定义量子电路。我在初态放一个BasisState把HF态1100〉准备好然后接上参数化的R_y门和CNOT门组成一层拟设。这一步是整段代码的核心参数个数就是拟设的自由度我这里用6个参数既能演示参数化过程又不至于把电路弄得太深。第三步是把Hamiltonian和电路组合成代价函数然后选择一个优化器不断更新参数。为了方便观察我每一轮都记录当前能量。5.3 完整代码实现import pennylane as qml from pennylane import numpy as np # 第一步构造H2的分子Hamiltonian symbols [H, H] geometry np.array([[0.0, 0.0, -0.6614], [0.0, 0.0, 0.6614]], requires_gradFalse) H, num_qubits qml.qchem.molecular_hamiltonian( symbols, geometry, basissto-3g ) print(哈密顿量包含的Pauli项数:, len(H.terms)) # 第二步搭建参数化量子电路 dev qml.device(default.qubit, wiresnum_qubits) qml.qnode(dev) def circuit(params): # 准备Hartree-Fock初态 |1100 qml.BasisState(np.array([1, 1, 0, 0]), wiresrange(num_qubits)) # 简易硬件高效拟设 qml.RY(params[0], wires0) qml.RY(params[1], wires1) qml.RY(params[2], wires2) qml.RY(params[3], wires3) qml.CNOT(wires[0, 1]) qml.CNOT(wires[2, 3]) qml.CNOT(wires[1, 3]) qml.RY(params[4], wires2) qml.RY(params[5], wires3) qml.CNOT(wires[0, 2]) qml.CNOT(wires[1, 3]) return qml.expval(H) # 第三步优化 params np.array([0.01, 0.01, 0.01, 0.01, 0.01, 0.01], requires_gradTrue) opt qml.Adam(stepsize0.05) energy_history [] for step in range(60): params, cost opt.step_and_cost(circuit, params) energy_history.append(cost) if step % 5 0: print(fstep {step:3d} energy {cost:.8f} Ha) print(最终能量:, energy_history[-1])这段代码在我的机器上跑完60步大约需要几秒优化过程能肉眼看到能量从零附近一路跌到接近理论值。如果你看到最后几轮能量还在小幅跳动可以把学习率调到0.02或者把步数加到100步。5.4 运行结果与实际效果我用上述代码实测初始能量大致在-0.2 Hartree附近前20步下降很快到40步以后基本进入平台期最终稳定在-1.136 Hartree左右。这个值和STO-3G基组下H₂的精确基态能量非常接近化学意义上的误差已经小于1.6e-3 Hartree说明这个简单的浅电路虽然物理图景不强在四个比特的表达力范围内已经逼近极限了。让我印象很深的是如果我把初态参数全部设成0前几步的能量会从HF能量开始能观测到一条漂亮的关联能下降曲线。这个细节在真实材料计算里挺有仪式感因为它让你直观看到VQE的价值——机器在一点一点把电子之间的关联效应“赚”回来。跑这种小例子时我会顺手把能量历史画成曲线观察哪一步开始进入平台期这对后续选参数很有帮助。5.5 换一个分子改哪些代码想从H₂换到其他分子只需要改动几何数据和基组就可以。比如想算LiH把symbols改成[Li, H]坐标换成LiH的平衡键长再把量子比特数加到6个以上取决于基组拟设电路里的量子比特范围也要同步调整。化学上是几行代码的事但优化难度会明显上升参数空间变大、能量曲面更复杂可能需要加深电路、调低学习率、加长迭代轮数。这不叫改代码叫换实验阵地每个新分子都是一次新的探险。6. 踩坑实录与排查经验6.1 我踩过的五个高频坑先写一个我自己重复犯过的错误参数数组忘记设置requires_gradTrue结果PennyLane在求梯度时直接报错或者干脆不更新参数。这类问题排查起来经常让人抓狂因为代码不报错但能量一动不动。解决办法是参数数组初始化时明确加上requires_gradTrue并且确认代价函数里所有参与梯度计算的量都允许梯度传播。第二个高频坑是拟设电路太浅导致能量收敛到错误平台。我有一次在某个小型分子上只堆了一层R_y加CNOT优化器怎么跑都停在比精确基态高出0.05 Hartree的地方当时还怀疑是Hamiltonian算错了。后来把电路加深一层能量立刻掉了下来。这类问题最典型的特征是能量曲线平滑收敛但收敛点明显高于理论值。第三个坑是学习率过大带来的锯齿形能量曲线。尤其在Adam下学习率调到0.2以上时能量在平台期来回跳动下不去。解决办法就是前面说的“看曲线下菜”先调小学习率再观察是否进入平台。第四个坑是采样统计误差假象。在真机上一次性采样次数太少能量估计的方差大到让人误以为优化器坏了。这种情况不是优化算法的锅是你采样次数不够。解决办法是把shot数调高或者用测量分组减少同一轮里的测量开销。第五个坑是几何坐标和基组不匹配。不同基组对应的自旋轨道数不同如果你改了分子但忘记改比特数BasisState长度就会对不上报错还算好的有时是悄悄得到错误的能量。建议每次换体系先打印一次num_qubits和len(H.terms)确认端口对齐再往下跑。6.2 参数初始化与避免贫瘠高原理参数怎么初始化对VQE收敛影响比很多人想象的大得多。如果全设成0梯度在某些对称点可能等于0优化器一步都不动如果全随机大值电路一开始就处于“过于杂乱”的量子态容易走进贫瘠高原理。贫瘠高原理是变分量子算法里的著名难题电路宽度增加时随机参数化电路的代价函数梯度方差指数级收缩优化器像在一片一望无际的平坦荒原上找路。我从实践中获得的有效经验是小随机初始化参数分布在[-0.05, 0.05]之间既能突破对称零梯度又不至于把态从HF初态推得太远。如果你的拟设本身有物理意义比如UCCSD那直接用全0初始化反而是合理的因为0对应的就是Hartree-Fock态剩下的交给优化器去“开枝散叶”。没有物理先验的HEA才需要小随机初始化来防贫瘠。6.3 想继续深入几个扩展方向做完最基础的VQE你可以尝试几个方向让算法更接近真实实力。一个是测量分组的实现优化把前面章节提到的对易分组真正写进代码在硬件上能实打实省时间。另一个是加入自适应拟设比如ADAPT-VQE的思路不是一开始订好拟设结构而是迭代地从算子池里挑出梯度最大的那个算子加入电路这样每个参数都有物理含义电路深度更小。还有一个方向是量子自然梯度它通过计算参数子空间的Fubini-Study度规来修正参数更新方向比普通梯度下降在能量曲面弯曲严重时稳定得多。我自己的体会是先跑通基础版再逐个加这些增强每次加一个观察各种体系下的收敛变化。VQE这个方向最迷人的地方就是它足够新很多东西都是“试出来的”你踩过的坑、实验出来的参数选择很可能就是别人还没写进文档的秘密。最后再分享一个小技巧无论跑哪个VQE实验第一件事永远是打印一份能量历史曲线而不是直接看最终数字。一条完整下降曲线能告诉你很多信息——是否陷入了局部极小值、学习率是否合适、拟设是否够深。我很多参数调优决策都是从这条曲线里看出来的。这个小习惯建议你也养成。
返回列表