使用 ArcQML 求解 H₂ 基态能量
运行前请准备 ArcQML 源码仓库及对应示例数据。下文命令和 examples/ 路径均以该仓库为基准;本文展示关键代码片段,完整程序位于文中标注的示例路径。
本教程使用变分量子本征求解器(Variational Quantum Eigensolver,VQE)估计氢分子 H₂ 的基态能量,并展示 ArcQML 的电路、Pauli 可观测量、伴随自动微分和 Adam 优化器如何组成完整训练流程。
完整可运行代码位于 examples/rust/h2_vqe.rs。
use arcqml::prelude::*;
type AppResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
问题定义
本例采用以下量子化学设置:
| 配置 | 数值 |
|---|---|
| 分子几何 | H (0, 0, -0.35 Å),H (0, 0, 0.35 Å) |
| 原子间距 | 0.70 Å |
| 基组 | STO-3G |
| 活性电子数 | 2 |
| 活性轨道数 | 2 |
| 费米子映射 | Jordan–Wigner |
| 量子比特数 | 4 |
| Hamiltonian 项数 | 15 |
| 固定粒子数子空间维数 | 6 |
| Hartree–Fock 能量 | -1.1173490350562805 Ha |
| 精确基态能量 | -1.1361894542078266 Ha |
VQE 最小化参数化量子态的能量期望值:
根据变分原理,任意归一化试探态均满足 E(θ) ≥ E₀。优化的目标就是让试探态逐渐接近基态。
构造 Hamiltonian
Jordan–Wigner 变换后,H₂ Hamiltonian 是 15 个 Pauli 字符串的实系数线性组合。ArcQML 使用 SparsePauliOp 表示这种算符,并原生支持从 JSON 导入。
本例将完整数据保存在 examples/data/h2_hamiltonian.json,直接调用:
let hamiltonian = SparsePauliOp::from_json(include_str!(
"../data/h2_hamiltonian.json"
))?;
assert_eq!(hamiltonian.num_qubits(), 4);
assert_eq!(hamiltonian.len(), 15);
include_str! 在编译时把 JSON 嵌入可执行文件,运行时无需寻找数据文件。如果 Hamiltonian 来自用户文件,也可以用 std::fs::read_to_string 读取后传给同一个 API:
let json = std::fs::read_to_string("examples/data/h2_hamiltonian.json")?;
let hamiltonian = SparsePauliOp::from_json(&json)?;
ArcQML 的 JSON 格式由顶层 num_qubits 和 terms 组成;每个 Pauli 操作显式记录 qubit 与 pauli。例如常数项和 X(q0)X(q1)Y(q2)Y(q3) 项写作:
{
"num_qubits": 4,
"terms": [
{
"coefficient": -0.042078985845795724,
"paulis": []
},
{
"coefficient": -0.04475014386992153,
"paulis": [
{ "qubit": 0, "pauli": "X" },
{ "qubit": 1, "pauli": "X" },
{ "qubit": 2, "pauli": "Y" },
{ "qubit": 3, "pauli": "Y" }
]
}
]
}
空 paulis 数组表示单位算符。
准备 Hartree–Fock 初态
在 Jordan–Wigner 编码中,每个量子比特表示一个自旋轨道是否被占据。两个活性电子占据最低的两个自旋轨道,因此从 |0000⟩ 出发对 q0、q1 施加 X 门:
let mut circuit = Circuit::new(4)?;
circuit.x(0)?.x(1)?;
ArcQML 抽样字符串按 q3q2q1q0 显示,所以这个状态显示为 |0011⟩;内部状态索引采用 little-endian。
构造参数化 ansatz
本例使用 6 层硬件高效 ansatz。每层首先在每个量子比特上施加 RY、RZ,随后使用环形 CNOT 纠缠:
const NUM_QUBITS: usize = 4;
const LAYERS: usize = 6;
let mut parameter_index = 0usize;
for _ in 0..LAYERS {
for qubit in 0..NUM_QUBITS {
let ry = 0.04 * (0.37 * (parameter_index + 1) as f64).sin();
parameter_index += 1;
let rz = 0.04 * (0.37 * (parameter_index + 1) as f64).sin();
parameter_index += 1;
circuit.ry(ry, qubit)?;
circuit.rz(rz, qubit)?;
}
for control in 0..NUM_QUBITS {
circuit.cnot(control, (control + 1) % NUM_QUBITS)?;
}
}
线路共有 6 × 4 × 2 = 48 个可训练参数。非零、非对称且确定性的初值可以打破参数对称性,同时保证重复运行从同一点开始。
这个硬件高效 ansatz 不严格保持粒子数。它适合演示通用 VQE 和 ArcQML 自动微分,但在化学计算中也可以改用保持粒子数的激发 ansatz。
执行 VQE 优化
StateVectorSimulator::run 返回能量期望值 Tensor。调用 backward() 后,ArcQML 使用整条量子线路的伴随反向传播计算所有参数梯度。
let simulator = StateVectorSimulator::new(4)?;
let mut optimizer = Adam::new(0.05, 0.9, 0.999, 1e-8, 0.0)?;
for step in 1..=100 {
let energy = simulator.run(&circuit, &hamiltonian)?;
energy.backward()?;
optimizer.step(circuit.parameters())?;
optimizer.zero_grad(circuit.parameters());
if step == 1 || step % 10 == 0 {
let current = simulator.run(&circuit, &hamiltonian)?.value()?;
println!("step {step:>3}: energy = {current:.12} Ha");
}
}
每轮训练的顺序不能颠倒:
run计算当前参数对应的能量。backward计算参数梯度。step使用当前梯度更新线路参数。zero_grad清除本轮梯度,为下一轮反向传播做准备。
线路参数刚创建时梯度为空,因此第一次迭代不需要预先调用 zero_grad。之后每轮都在参数更新后清空梯度,避免下一轮 backward 累加旧梯度。
模拟器始终保存 |0000⟩。Hartree–Fock 制备门已包含在线路中,而 run 不会修改模拟器自身,因此同一个模拟器可以在全部训练轮次中复用。
运行示例
在仓库根目录执行:
cargo run --release -p arcqml --example h2_vqe
程序每 10 步输出一次能量以及相对精确基态能量的绝对误差,最后判断是否达到化学精度:
H2/STO-3G, Jordan-Wigner, 4 qubits
Hamiltonian terms : 15
Trainable params : 48
Hartree-Fock : -1.117349035056 Ha
Exact ground : -1.136189454208 Ha
...
VQE energy : <优化得到的能量> Ha
Absolute error : <与精确值的差> Ha
Chemical accuracy: reached/not reached (threshold 1.6e-3 Ha)
具体迭代值由优化轨迹决定。由于本例初值固定,在相同 ArcQML 版本与数值环境下结果应当可复现。
如何理解结果
- 能量应从初始值总体向下收敛,并受变分原理约束,不应显著低于精确基态能量。
- Hartree–Fock 与精确能量之差约为
0.0188404 Ha,这部分差异主要来自电子关联。 - 绝对误差小于
1.6 × 10⁻³ Ha时,通常称为达到化学精度。 - 若 100 步尚未收敛,可增加训练步数、调整学习率,或增加 ansatz 层数;更深线路也更可能出现优化平台或冗余参数。
下一步
可以在此示例上继续尝试:
- 将 Adam 替换为
Sgd,比较收敛速度。 - 使用保持粒子数的激发 ansatz,限制搜索空间到 6 维双电子子空间。
- 保存训练后的线路权重,并在新进程中通过
load_weights恢复。 - 改变 H–H 键长,计算势能曲线。