使用量子化学工具箱高效模拟VQE算法

下载Notebook下载样例代码查看源文件

1. 引言

mqchem 是一个专为解决量子化学问题而设计的集成工具箱。它的核心优势在于基于 组态相互作用(Configuration Interaction, CI) 的模拟方法。与在整个 \(2^{N}\) 维希尔伯特空间中操作的通用模拟器不同,mqchem 的模拟器在一个由固定电子数(n_electrons)定义的子空间中进行演化。这种方法极大地减少了运行时间,使得我们可以在极短的时间内模拟20比特或更大规模的化学体系。

mqchem 模块主要包含三个协同工作的核心组件:

  • ``CIHamiltonian``: 用于高效表示化学问题的哈密顿量。

  • ``UCCExcitationGate``: UCCSD 等变分 ansatz 的基本构建块。

  • ``MQChemSimulator``: 在 CI 空间中执行量子线路演化和测量的高性能模拟器。

在本教程中,您将学习如何遵循自然的工作流程,使用 mqchem 模块的组件来解决化学问题:

  1. 了解 mqchem 的核心组件及其各自的职责。

  2. 学习如何将这些组件组合起来,以应用量子线路并计算期望值。

  3. 利用高阶函数 prepare_uccsd_vqe 快速搭建一个完整的 VQE 流程。

  4. 亲手完成一个 H₆ 线性链分子的基态能量计算。

前置依赖: 在开始之前,请确保您已经安装了 MindQuantum 以及用于化学计算的 openfermionopenfermionpyscf

pip install mindquantum openfermion openfermionpyscf

2. mqchem 核心组件

在解决一个量子化学问题时,我们通常需要定义问题本身(哈密顿量)、构建求解方案(ansatz 线路),并在一个模拟环境中执行它。mqchem 的三个核心组件正好对应这几个步骤。

2.1 CIHamiltonian:定义问题

CIHamiltonianFermionOperator 的一个包装类,它将费米子哈密顿量转换为一种适合在 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_gateapply_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 准备工作:定义分子

我们使用 openfermionopenfermionpyscf 来获取 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_vqemqchem 模块的一大亮点。这个高阶工厂函数为我们自动完成了 VQE 准备中最繁琐的步骤,它将我们之前学到的组件创建过程自动化了:

  1. 从分子数据生成费米子哈密顿量,并包装成 CIHamiltonian

  2. 基于 UCCSD(Unitary Coupled-Cluster Singles and Doubles)理论,生成一个参数化的 Circuit,其中包含一系列 UCCExcitationGate

  3. 从经典的 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 模块。我们从它的三个核心组件——CIHamiltonianUCCExcitationGateMQChemSimulator——出发,理解了它们在量子化学模拟工作流中各自的角色。

我们不仅学习了如何独立使用这些组件,更重要的是,我们看到了它们如何无缝集成,以解决实际问题。最后,通过一个计算 H₆ 分子基态能量的 VQE 实例,我们展示了如何利用 prepare_uccsd_vqe 等便捷工具,高效地搭建和运行一个完整的量子化学模拟流程。

mqchem 模块为在 MindQuantum 平台上进行高性能、高精度的量子化学研究提供了强大的支持。希望本教程能帮助您快速上手,并探索更多有趣的化学问题!