使用量子化学工具箱高效模拟VQE算法
1. 引言
mqchem
是一个专为解决量子化学问题而设计的集成工具箱。它的核心优势在于基于 组态相互作用(Configuration Interaction, CI) 的模拟方法。与在整个 \(2^{N}\) 维希尔伯特空间中操作的通用模拟器不同,mqchem
的模拟器在一个由固定电子数(n_electrons
)定义的子空间中进行演化。这种方法极大地减少了运行时间,使得我们可以在极短的时间内模拟20比特或更大规模的化学体系。
mqchem
模块主要包含三个协同工作的核心组件:
``CIHamiltonian``: 用于高效表示化学问题的哈密顿量。
``UCCExcitationGate``: UCCSD 等变分 ansatz 的基本构建块。
``MQChemSimulator``: 在 CI 空间中执行量子线路演化和测量的高性能模拟器。
在本教程中,您将学习如何遵循自然的工作流程,使用 mqchem
模块的组件来解决化学问题:
了解
mqchem
的核心组件及其各自的职责。学习如何将这些组件组合起来,以应用量子线路并计算期望值。
利用高阶函数
prepare_uccsd_vqe
快速搭建一个完整的 VQE 流程。亲手完成一个 H₆ 线性链分子的基态能量计算。
前置依赖: 在开始之前,请确保您已经安装了 MindQuantum 以及用于化学计算的 openfermion
和 openfermionpyscf
。
pip install mindquantum openfermion openfermionpyscf
2. mqchem
核心组件
在解决一个量子化学问题时,我们通常需要定义问题本身(哈密顿量)、构建求解方案(ansatz 线路),并在一个模拟环境中执行它。mqchem
的三个核心组件正好对应这几个步骤。
2.1 CIHamiltonian
:定义问题
CIHamiltonian
是 FermionOperator
的一个包装类,它将费米子哈密顿量转换为一种适合在 CI 空间中进行高效计算的格式。它是我们 VQE 计算的目标函数。
[1]:
from mindquantum.core.operators import FermionOperator
from mindquantum.simulator import mqchem
# 任何一个费米子算符都可以被包装
# 例如,我们定义一个简单的粒子数算符 H = n_0 + n_1
ham_op = FermionOperator('0^ 0') + FermionOperator('1^ 1')
# 将其包装为 CIHamiltonian
ci_ham = mqchem.CIHamiltonian(ham_op)
print("CI 哈密顿量:")
print(ci_ham)
CI 哈密顿量:
1 [0^ 0] +
1 [1^ 1]
2.2 UCCExcitationGate
:构建解法
UCCExcitationGate
是构建UCC(Unitary Coupled-Cluster)ansatz 的基本单元。它代表了酉算符 \(U(\theta) = e^{\theta(T - T^\dagger)}\),其中 \(T\) 是一个费米子激发算符(例如 \(a_p^\dagger a_q\)),而 \(\theta\) 是一个可训练的参数。
mqchem
模块中的模拟器经过特殊优化,可以极高效地应用这种门。
[2]:
# 创建一个从轨道 0 激发到轨道 2 的激发算符 T = a_2^\dagger a_0
# 'theta' 是一个可训练的参数名
t_op = FermionOperator('2^ 0', 'theta')
# 从该算符创建 UCC 激发门
ucc_gate = mqchem.UCCExcitationGate(t_op)
print("创建的 UCC 门:")
print(ucc_gate)
创建的 UCC 门:
exp{(theta)([2^ 0] + [2 0^])}
2.3 MQChemSimulator
:提供执行环境
MQChemSimulator
是执行模拟的引擎。它维护着一个 CI 基矢上的量子态,并提供了应用 UCCExcitationGate
和计算 CIHamiltonian
期望值的方法。
初始化时,需要指定系统的 n_qubits
(总自旋轨道数)和 n_electrons
(总电子数)。模拟器默认从 哈特里-福克(Hartree-Fock, HF) 态开始,这是量子化学计算中最常用的参考态。
[3]:
from mindquantum.core.circuit import Circuit
# 初始化一个4量子比特、2电子的模拟器
sim = mqchem.MQChemSimulator(n_qubits=4, n_electrons=2, seed=42)
print(f"模拟器量子比特数: {sim.n_qubits}")
print(f"模拟器电子数: {sim.n_electrons}")
# 默认的 HF 态是 |0011> (比特从右到左编号 0, 1, 2, 3)
print("\n初始 Hartree-Fock 态:")
print(sim.get_qs(ket=True))
模拟器量子比特数: 4
模拟器电子数: 2
初始 Hartree-Fock 态:
1¦0011⟩
3. 组合应用:模拟与计算
了解了三大组件后,我们来看看如何将它们组合起来,执行一个完整的模拟流程。
3.1 应用门与线路
我们可以使用 apply_gate
或 apply_circuit
方法,在 MQChemSimulator
维护的量子态上作用 UCCExcitationGate
。
[4]:
# 重置模拟器到 HF 态
sim.reset()
# 应用之前创建的 ucc_gate,并为参数 'theta' 赋值 0.1
sim.apply_gate(ucc_gate, pr={'theta': 0.1})
print("应用单个门之后的状态:")
print(sim.get_qs(ket=True))
# 也可以应用包含多个门的线路
sim.reset()
t_op2 = FermionOperator('3^ 1', 0.2) # 使用常数作为参数
ucc_gate2 = mqchem.UCCExcitationGate(t_op2)
circuit = Circuit([ucc_gate, ucc_gate2])
# 应用线路,并为参数 'theta' 赋值
sim.apply_circuit(circuit, pr={'theta': 0.1})
print("\n应用线路后的状态:")
print(sim.get_qs(ket=True))
应用单个门之后的状态:
0.99500417¦0011⟩
-0.09983342¦0110⟩
应用线路后的状态:
0.97517033¦0011⟩
-0.0978434¦0110⟩
0.19767681¦1001⟩
0.01983384¦1100⟩
3.2 计算期望值
get_expectation
方法用于计算当前量子态下,某个 CIHamiltonian
的期望值 \(\langle\psi|H|\psi\rangle\)。
例如,我们来验证 HF 态 \(|0011\rangle\) 下,哈密顿量 \(H = n_0 + n_1\) 的期望值。由于轨道 0 和 1 都被占据,我们期望结果为 \(1+1=2\)。
[5]:
sim.reset()
# 使用之前创建的 ci_ham
expectation = sim.get_expectation(ci_ham)
print(f"<HF| (n_0 + n_1) |HF> 的期望值为: {expectation}")
<HF| (n_0 + n_1) |HF> 的期望值为: 2.0
4. VQE 实战:计算 H₆ 分子基态能量
现在,我们将运用所学知识,通过 VQE 算法计算 H₆ 线性链分子的基态能量。这是一个展示 mqchem
模块强大功能的典型案例。
4.1 准备工作:定义分子
我们使用 openfermion
和 openfermionpyscf
来获取 H₆ 分子的数据。run_pyscf
会执行经典的量子化学计算(如 HF 和 CCSD),这些结果将作为我们量子算法的输入。
关键:我们必须设置 run_ccsd=True
,因为 prepare_uccsd_vqe
函数需要 CCSD 的计算结果来为 VQE 提供高质量的初始参数。
[6]:
from openfermion import MolecularData
from openfermionpyscf import run_pyscf
# 定义 H₆ 分子,键长为 1 埃
geometry = [("H", (i, 0, 0)) for i in range(6)]
basis = "sto-3g"
multiplicity = 1 # 自旋多重度 (2S+1),单重态 S=0
charge = 0
# 创建分子对象并运行 PySCF
# 注意:run_ccsd=True 对于获取初始振幅至关重要
molecule = MolecularData(geometry, basis, multiplicity, charge)
mol = run_pyscf(molecule, run_ccsd=True, run_fci=True)
print(f"分子: H₆ 线性链")
print(f"量子比特数 (自旋轨道数): {mol.n_qubits}")
print(f"电子数: {mol.n_electrons}")
print(f"精确基态能量 (FCI): {mol.fci_energy:.8f} Hartrees")
分子: H₆ 线性链
量子比特数 (自旋轨道数): 12
电子数: 6
精确基态能量 (FCI): -3.23606628 Hartrees
4.2 使用 prepare_uccsd_vqe
一键准备 VQE
prepare_uccsd_vqe
是 mqchem
模块的一大亮点。这个高阶工厂函数为我们自动完成了 VQE 准备中最繁琐的步骤,它将我们之前学到的组件创建过程自动化了:
从分子数据生成费米子哈密顿量,并包装成
CIHamiltonian
。基于 UCCSD(Unitary Coupled-Cluster Singles and Doubles)理论,生成一个参数化的
Circuit
,其中包含一系列UCCExcitationGate
。从经典的 CCSD 计算结果中提取耦合簇振幅,作为 VQE 优化的初始参数。这通常是一个非常好的起点。
[7]:
# 一键生成哈密顿量、UCCSD ansatz 线路和初始参数
# threshold=1e-6 用于过滤掉 CCSD 振幅过小的激发项,简化 ansatz
hamiltonian, ansatz_circuit, initial_amplitudes = mqchem.prepare_uccsd_vqe(mol, threshold=1e-6)
print("CI 哈密顿量 (部分项):")
print(str(hamiltonian.fermion_hamiltonian)[:200] + "...")
print(f"\n生成的 Ansatz 线路包含 {len(ansatz_circuit)} 个门。")
print("线路参数名称:", ansatz_circuit.params_name)
print(f"\n从 CCSD 提取的初始振幅 (共 {len(initial_amplitudes)} 个):")
print(initial_amplitudes)
CI 哈密顿量 (部分项):
4.6038 [] +
-2.2818 [0^ 0] +
-0.1459 [4 0^] +
0.0642 [8 0^] +
-2.2818 [1^ 1] +
-0.1459 [5 1^] +
0.0642 [9 1^] +
-2.0409 [2^ 2] +
-0.2111 [6 2^] +
0.0417 [10 2^] +
-2.0409 [3^ 3] +
-0.2111 [7 3^] +...
生成的 Ansatz 线路包含 59 个门。
线路参数名称: ['d1_0', 's_1', 'd1_1', 'd1_2', 's_3', 'd1_3', 'd1_4', 's_5', 'd1_5', 'd1_6', 's_7', 'd1_7', 'd1_8', 'd2_1', 'd2_3', 'd2_9', 'd2_5', 'd2_18', 'd2_7', 'd2_11', 'd2_16', 'd2_13', 'd2_20', 'd2_22', 'd2_24', 'd2_27', 'd2_29', 'd2_31', 'd2_34']
从 CCSD 提取的初始振幅 (共 29 个):
[-0.02172895 -0.00966027 -0.03288994 -0.10380602 0.0028648 -0.0143801
-0.03201595 -0.00681583 -0.02420889 -0.01695636 -0.00239016 -0.01001419
-0.01221332 0.00432926 0.01629623 0.00904958 -0.00799714 0.01818314
0.03079327 0.04406509 0.02507472 0.01007596 -0.00356389 -0.00956368
-0.01592823 -0.01108764 -0.01197809 -0.00586536 0.00582737]
4.3 获取期望与梯度计算函数
VQE 的核心是最小化能量期望值。高效的优化算法(如 L-BFGS-B)需要能量关于参数的梯度。get_expectation_with_grad
方法正是为此设计的。它返回一个函数,该函数接收参数值,并同时返回能量期望值和梯度。
[8]:
# 初始化一个新的模拟器用于 VQE 计算
vqe_sim = mqchem.MQChemSimulator(mol.n_qubits, mol.n_electrons)
# 获取可以计算期望和梯度的函数
# 这个函数与 scipy.optimize.minimize 的接口兼容
grad_ops = vqe_sim.get_expectation_with_grad(hamiltonian, ansatz_circuit)
# 我们可以测试一下这个函数
energy, gradient = grad_ops(initial_amplitudes)
print(f"使用初始参数计算的能量: {energy:.8f}")
print(f"对应的梯度 (前5个): {gradient[:5]}")
使用初始参数计算的能量: -3.21777544
对应的梯度 (前5个): [-0.03673877 0.02322724 -0.06124962 -0.10907011 -0.00220752]
4.4 运行优化器
最后,我们使用经典的优化器 scipy.optimize.minimize
来寻找最优参数,从而得到基态能量的变分近似值。
[9]:
from scipy.optimize import minimize
from time import time
t0 = time()
# 使用 L-BFGS-B 算法进行优化
# jac=True 表示我们的 grad_ops 函数同时返回期望值和雅可比矩阵(梯度)
result = minimize(grad_ops, initial_amplitudes, method="L-BFGS-B", jac=True)
vqe_energy = result.fun
print("\n--- VQE 优化完成 ---")
print(f"VQE 计算得到的基态能量: {vqe_energy:.8f} Hartrees")
print(f"精确的 FCI 基态能量: {mol.fci_energy:.8f} Hartrees")
print(f"误差: {abs(vqe_energy - mol.fci_energy):.2e} Hartrees")
print(f"运行时间: {time() - t0:.2f} 秒")
--- VQE 优化完成 ---
VQE 计算得到的基态能量: -3.23544945 Hartrees
精确的 FCI 基态能量: -3.23606628 Hartrees
误差: 6.17e-04 Hartrees
运行时间: 0.03 秒
可以看到,VQE 的计算结果与精确的 FCI 能量非常接近,并且整个优化过程在0.02秒内就完成了!这证明了 mqchem
模块中各个组件协同工作的正确性和高性能。
5. 总结
在本教程中,我们系统地介绍了 mqchem
模块。我们从它的三个核心组件——CIHamiltonian
、UCCExcitationGate
和 MQChemSimulator
——出发,理解了它们在量子化学模拟工作流中各自的角色。
我们不仅学习了如何独立使用这些组件,更重要的是,我们看到了它们如何无缝集成,以解决实际问题。最后,通过一个计算 H₆ 分子基态能量的 VQE 实例,我们展示了如何利用 prepare_uccsd_vqe
等便捷工具,高效地搭建和运行一个完整的量子化学模拟流程。
mqchem
模块为在 MindQuantum 平台上进行高性能、高精度的量子化学研究提供了强大的支持。希望本教程能帮助您快速上手,并探索更多有趣的化学问题!