DeepQuantum 哈密顿量 API 完全指南¶
📋 目录¶
核心概念¶
什么是哈密顿量?¶
在量子计算中,哈密顿量(Hamiltonian)是描述量子系统能量的算符。对于 VQE 算法,我们需要:
-
将哈密顿量分解为泡利算符的线性组合
-
计算每个泡利算符的期望值
-
加权求和得到总能量
DeepQuantum 的核心组件¶
| 组件 | 说明 | 文件位置 |
|---|---|---|
Observable |
表示泡利算符(X, Y, Z 的张量积) | deepquantum/layer.py |
expectation() |
计算期望值的函数 | deepquantum/qmath.py |
QubitCircuit.observable() |
在电路中添加可观测量的方法 | deepquantum/circuit.py |
QubitCircuit.expectation() |
计算电路期望值的方法 | deepquantum/circuit.py |
Observable 类详解¶
类定义¶
from deepquantum import Observable
class Observable(SingleLayer):
"""表示可以用泡利字符串表达的可观测量
Args:
nqubit (int): 量子比特数(必需)
wires (int, List[int], List[List[int]]): 要测量的量子比特索引
basis (str): 测量基底,可选 'x', 'y', 'z' 或组合
den_mat (bool): 是否作用于密度矩阵(默认 False)
tsr_mode (bool): 是否为张量模式(默认 False)
"""
基本用法¶
1. 单量子比特观测¶
import deepquantum as dq
import torch
# 创建状态:|+⟩ = H|0⟩
qc = dq.QubitCircuit(1)
qc.h(0)
state = qc()
# 创建可观测量:Z
obs_z = dq.Observable(nqubit=1, wires=[0], basis='z')
# 计算期望值:⟨+|Z|+⟩ = 0
exp_val = dq.expectation(state, obs_z)
print(f"⟨Z⟩ = {exp_val.item():.6f}") # 输出: 0.000000
# 创建可观测量:X
obs_x = dq.Observable(nqubit=1, wires=[0], basis='x')
exp_val = dq.expectation(state, obs_x)
print(f"⟨X⟩ = {exp_val.item():.6f}") # 输出: 1.000000
2. 多量子比特观测¶
# 创建贝尔态:|Φ⁺⟩ = (|00⟩ + |11⟩)/√2
qc = dq.QubitCircuit(2)
qc.h(0)
qc.cx(0, 1)
state = qc()
# 观测 Z⊗Z
obs_zz = dq.Observable(nqubit=2, wires=[0, 1], basis='zz')
exp_val = dq.expectation(state, obs_zz)
print(f"⟨Z⊗Z⟩ = {exp_val.item():.6f}") # 输出: 1.000000
# 观测 X⊗X
obs_xx = dq.Observable(nqubit=2, wires=[0, 1], basis='xx')
exp_val = dq.expectation(state, obs_xx)
print(f"⟨X⊗X⟩ = {exp_val.item():.6f}") # 输出: 1.000000
# 观测 Y⊗Y
obs_yy = dq.Observable(nqubit=2, wires=[0, 1], basis='yy')
exp_val = dq.expectation(state, obs_yy)
print(f"⟨Y⊗Y⟩ = {exp_val.item():.6f}") # 输出: -1.000000
3. 不同基底的组合¶
# 创建 GHZ 态:|000⟩ + |111⟩
qc = dq.QubitCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)
state = qc()
# 观测 Z⊗Z⊗I
obs_zzi = dq.Observable(nqubit=3, wires=[0, 1], basis='zz')
exp_val = dq.expectation(state, obs_zzi)
print(f"⟨Z⊗Z⊗I⟩ = {exp_val.item():.6f}") # 输出: 1.000000
# 观测 X⊗Y⊗Z
obs_xyz = dq.Observable(nqubit=3, wires=[0, 1, 2], basis='xyz')
exp_val = dq.expectation(state, obs_xyz)
print(f"⟨X⊗Y⊗Z⟩ = {exp_val.item():.6f}") # 输出: -1.000000
Observable 的关键属性¶
obs = dq.Observable(nqubit=2, wires=[0, 1], basis='zz')
print(f"量子比特数: {obs.nqubit}") # nqubit: 2
print(f"测量比特: {obs.wires}") # wires: [0, 1]
print(f"测量基底: {obs.basis}") # basis: 'zz'
print(f"单位矩阵: {obs.get_unitary()}") # 4x4 矩阵
期望值计算¶
方法一:直接使用 dq.expectation()¶
这是最常用的方法,适用于任何量子状态。
from deepquantum import expectation
import torch
# 创建量子态
state = torch.tensor([1, 0, 0, 1], dtype=torch.cfloat) / torch.sqrt(torch.tensor(2.0))
# 创建可观测量
obs = dq.Observable(nqubit=2, wires=[0, 1], basis='zz')
# 计算期望值
exp_val = expectation(state, observable=obs)
print(f"期望值: {exp_val.item()}") # 输出标量值
支持的参数:
expectation(
state: Union[torch.Tensor, List[torch.Tensor]], # 量子态
observable: Observable, # 可观测量
den_mat: bool = False, # 是否为密度矩阵
chi: Optional[int] = None # MPS 的键维度
) -> torch.Tensor
方法二:使用电路的 expectation() 方法¶
先在电路中添加可观测量,然后一次性计算所有期望值。
# 创建电路
cir = dq.QubitCircuit(2)
cir.h(0)
cir.cx(0, 1)
# 添加可观测量
cir.observable(wires=[0], basis='z') # Z₀
cir.observable(wires=[1], basis='z') # Z₁
cir.observable(wires=[0, 1], basis='zz') # Z₀Z₁
# 执行电路
state = cir()
# 获取所有期望值
expectation_values = cir.expectation()
print(f"期望值列表: {expectation_values}") # tensor([0., 0., 1.])
密度矩阵的期望值¶
# 创建密度矩阵:|0⟩⟨0|
rho = torch.tensor([[1, 0],
[0, 0]], dtype=torch.cfloat)
# 可观测量:X
obs = dq.Observable(nqubit=1, wires=[0], basis='x')
# 计算期望值(指定 den_mat=True)
exp_val = expectation(rho, observable=obs, den_mat=True)
print(f"⟨0|X|0⟩ = {exp_val.item():.6f}") # 输出: 0.000000
哈密顿量构建方法¶
方法一:手动构建简单哈密顿量¶
适用于教学和简单系统。
from deepquantum import Observable
def build_simple_hamiltonian():
"""构建简单哈密顿量:H = 0.5*Z₀ + 0.3*Z₁ + 0.2*Z₀Z₁"""
observable_list = [
(0.5, Observable(nqubit=2, wires=[0], basis='z')),
(0.3, Observable(nqubit=2, wires=[1], basis='z')),
(0.2, Observable(nqubit=2, wires=[0, 1], basis='zz'))
]
return observable_list
# 计算能量
state = torch.tensor([1, 0, 0, 0], dtype=torch.cfloat) # |00⟩
observable_list = build_simple_hamiltonian()
energy = 0.0
for coeff, obs in observable_list:
exp_val = dq.expectation(state, obs).item()
energy += coeff * exp_val
print(f"能量: {energy:.6f}")
方法二:从泡利字符串构建¶
适用于从文献或外部输入的哈密顿量。
def pauli_string_to_observable(pauli_string, n_qubits, coeff=1.0):
"""
将泡利字符串转换为 Observable 对象
Args:
pauli_string: 泡利字符串,如 "ZIX" 或 "XYYZ"
n_qubits: 总量子比特数
coeff: 系数
Returns:
(coeff, Observable) 元组
"""
# 提取非 Identity 的比特和基底
wires = []
bases = []
for i, char in enumerate(pauli_string):
if char in 'XYZ':
wires.append(i)
bases.append(char.lower())
if len(wires) == 0:
# 全是 Identity,这是常数项
return (coeff, None)
else:
obs = Observable(nqubit=n_qubits, wires=wires, basis=''.join(bases))
return (coeff, obs)
# 示例:横场 Ising 模型
# H = -J∑ZᵢZᵢ₊₁ - h∑Xᵢ
def build_ising_model(n_qubits, J=1.0, h=1.0):
"""构建横场 Ising 模型哈密顿量"""
hamiltonian_terms = []
# ZZ 相互作用项
for i in range(n_qubits - 1):
pauli_string = 'I' * i + 'ZZ' + 'I' * (n_qubits - i - 2)
coeff, obs = pauli_string_to_observable(pauli_string, n_qubits, coeff=-J)
if obs is not None:
hamiltonian_terms.append((coeff, obs))
else:
constant_term = coeff # 保存常数项
# X 项(横场)
for i in range(n_qubits):
pauli_string = 'I' * i + 'X' + 'I' * (n_qubits - i - 1)
coeff, obs = pauli_string_to_observable(pauli_string, n_qubits, coeff=-h)
if obs is not None:
hamiltonian_terms.append((coeff, obs))
else:
constant_term = coeff
return constant_term, hamiltonian_terms
# 使用示例
n_qubits = 3
constant, terms = build_ising_model(n_qubits, J=1.0, h=1.0)
print(f"常数项: {constant:.6f}")
print(f"泡利项数: {len(terms)}")
for coeff, obs in terms:
print(f" {coeff:+.2f} * {obs.basis} on wires {obs.wires}")
方法三:从 PennyLane 获取分子哈密顿量¶
这是实际应用中最常用的方法,用于真实量子化学计算。
import pennylane as qml
from pennylane import qchem
from deepquantum import Observable
import numpy as np
def get_molecular_hamiltonian(symbols, coordinates, charge=0, basis="sto-3g"):
"""
使用 PennyLane 获取分子哈密顿量
Args:
symbols: 原子符号列表,如 ["H", "H"]
coordinates: 原子坐标(埃),形状为 (n_atoms * 3,)
charge: 分子电荷
basis: 基组名称
Returns:
constant_term: 常数项(Identity 系数)
observable_list: [(coeff, Observable), ...] 列表
n_qubits: 所需量子比特数
"""
# 计算分子哈密顿量
H, n_qubits = qchem.molecular_hamiltonian(
symbols, coordinates, charge=charge, basis=basis
)
# 提取泡利项
coeffs, pauli_terms = H.terms()
# 解析泡利项
constant_term = 0.0
observable_list = []
for coeff, term in zip(coeffs, pauli_terms):
# 处理单算符项
if hasattr(term, 'name'):
if term.name == 'Identity':
# 常数项
constant_term = coeff.item() if hasattr(coeff, 'item') else float(coeff)
else:
wires = [term.wires[0]]
bases = [term.name.lower().replace('pauli', '')]
obs = Observable(nqubit=n_qubits, wires=wires, basis=''.join(bases))
observable_list.append((coeff, obs))
# 处理多算符项
elif hasattr(term, 'operands'):
wires = []
bases = []
all_identity = True
for op in term.operands:
if op.name != 'Identity':
all_identity = False
wires.append(op.wires[0])
bases.append(op.name.lower().replace('pauli', ''))
if all_identity:
# 全是 Identity,这是常数项
constant_term = coeff.item() if hasattr(coeff, 'item') else float(coeff)
elif len(wires) > 0:
obs = Observable(nqubit=n_qubits, wires=wires, basis=''.join(bases))
observable_list.append((coeff, obs))
return constant_term, observable_list, n_qubits
# 使用示例:H₂ 分子
symbols = ["H", "H"]
coordinates = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.74]) # 键长 0.74 Å
constant, observables, n_qubits = get_molecular_hamiltonian(symbols, coordinates)
print(f"H₂ 分子哈密顿量")
print(f" 量子比特数: {n_qubits}")
print(f" 常数项: {constant:.6f} Hartree")
print(f" 泡利项数: {len(observables)}")
关键注意事项:
1. 必须处理常数项:Identity 算符的系数是能量计算的关键部分
2. 系数类型转换:PennyLane 可能返回 numpy 数组,需要转换为 Python 标量
3. 活性空间简化:对于大分子,可以指定 active_electrons 和 active_orbitals
方法四:使用活性空间(推荐用于大分子)¶
def get_active_space_hamiltonian(symbols, coordinates, active_electrons, active_orbitals):
"""
使用活性空间简化分子哈密顿量
Args:
active_electrons: 活性电子数
active_orbitals: 活性轨道数
"""
H_h2o, qubits = qchem.molecular_hamiltonian(
symbols, coordinates,
active_electrons=active_electrons,
active_orbitals=active_orbitals,
basis="sto-3g"
)
# 尝试对称性简化(tapering)
try:
generators = qchem.symmetry_generators(H_h2o)
paulixops = qchem.paulix_ops(generators, qubits)
# 选择最低能量的 sector
n_generators = len(generators)
target_sector = [-1] * n_generators
H_tapered = qchem.taper(H_h2o, generators, paulixops, target_sector)
# 提取泡利项
coeffs, pauli_terms = H_tapered.terms()
# 计算实际量子比特数
max_wire = 0
for term in pauli_terms:
if hasattr(term, 'wires'):
for w in term.wires:
max_wire = max(max_wire, w)
elif hasattr(term, 'operands'):
for op in term.operands:
for w in op.wires:
max_wire = max(max_wire, w)
actual_n_qubits = max_wire + 1
except Exception as e:
print(f"对称性简化失败,使用完整哈密顿量: {e}")
coeffs, pauli_terms = H_h2o.terms()
actual_n_qubits = qubits
# 解析泡利项(同上)
# ...
return constant_term, observable_list, actual_n_qubits
# 水分子示例(4 个活性电子,4 个活性轨道)
symbols = ['O', 'H', 'H']
coordinates = np.array([
0.0, 0.0, 0.0,
0.757, 0.0, 0.587,
-0.757, 0.0, 0.587
])
constant, observables, n_q = get_active_space_hamiltonian(
symbols, coordinates,
active_electrons=4,
active_orbitals=4
)
VQE 中的哈密顿量处理¶
完整的 VQE 哈密顿量类¶
import deepquantum as dq
import torch
import torch.nn as nn
class VQEHHamiltonian:
"""VQE 专用的哈密顿量处理类"""
def __init__(self, coeffs, pauli_terms, n_qubits, fci_energy=None):
"""
Args:
coeffs: 泡利项系数列表
pauli_terms: 泡利项列表(PennyLane 格式)
n_qubits: 量子比特数
fci_energy: FCI 参考能量(可选)
"""
self.n_qubits = n_qubits
self.fci_energy = fci_energy
# 解析哈密顿量
self.constant_term = 0.0
self.observable_list = self._parse_pauli_terms(coeffs, pauli_terms)
print(f"VQE 哈密顿量初始化完成")
print(f" 量子比特数: {self.n_qubits}")
print(f" 泡利项数: {len(self.observable_list)}")
print(f" 常数项: {self.constant_term:+.6f}")
if self.fci_energy:
print(f" FCI 能量: {self.fci_energy:.6f}")
def _parse_pauli_terms(self, coeffs, pauli_terms):
"""解析 PennyLane 泡利项为 DeepQuantum Observable"""
observable_list = []
for coeff, term in zip(coeffs, pauli_terms):
# 处理多算符项
if hasattr(term, 'operands'):
wires = []
bases = []
all_identity = True
for op in term.operands:
if op.name != 'Identity':
all_identity = False
wires.append(op.wires[0])
bases.append(op.name.lower().replace('pauli', ''))
if all_identity:
# 常数项
self.constant_term = coeff.item() if hasattr(coeff, 'item') else float(coeff)
elif len(wires) > 0:
obs = dq.Observable(nqubit=self.n_qubits, wires=wires, basis=''.join(bases))
observable_list.append((coeff, obs))
# 处理单算符项
elif hasattr(term, 'name'):
if term.name == 'Identity':
self.constant_term = coeff.item() if hasattr(coeff, 'item') else float(coeff)
else:
wires = [term.wires[0]]
bases = [term.name.lower().replace('pauli', '')]
obs = dq.Observable(nqubit=self.n_qubits, wires=wires, basis=''.join(bases))
observable_list.append((coeff, obs))
return observable_list
def compute_energy(self, state):
"""
计算给定量子态的能量
Args:
state: 量子态张量
Returns:
总能量(包括常数项)
"""
# 从常数项开始
energy = self.constant_term
# 累加所有泡利项的贡献
for coeff, obs in self.observable_list:
try:
exp_val = dq.expectation(state, obs).item()
energy += coeff * exp_val
except Exception as e:
print(f"警告:项计算失败: {e}")
exp_val = 0.0
energy += coeff * exp_val
return energy
def compute_energy_with_circuit(self, qc):
"""
通过电路计算能量
Args:
qc: QubitCircuit 对象
Returns:
总能量
"""
state = qc()
return self.compute_energy(state)
VQE 优化循环示例¶
class VQEOptimizer:
"""VQE 优化器"""
def __init__(self, hamiltonian, n_qubits, n_electrons=None):
"""
Args:
hamiltonian: VQEHHamiltonian 对象
n_qubits: 量子比特数
n_electrons: 电子数(用于 HF 初始化)
"""
self.hamiltonian = hamiltonian
self.n_qubits = n_qubits
self.n_electrons = n_electrons or n_qubits // 2
def create_ansatz(self, theta, layers=3):
"""创建硬件高效 Ansatz"""
qc = dq.QubitCircuit(self.n_qubits)
# Hartree-Fock 参考态
for i in range(self.n_electrons):
qc.x(i)
param_idx = 0
# 构建多层结构
for layer in range(layers):
# 旋转层:RY → RZ
for q in range(self.n_qubits):
qc.ry(q, theta[param_idx])
param_idx += 1
qc.rz(q, theta[param_idx])
param_idx += 1
# 纠缠层:CZ 线性链
for q in range(self.n_qubits - 1):
qc.cz(q, q + 1)
# 最后一层旋转
for q in range(self.n_qubits):
qc.ry(q, theta[param_idx])
param_idx += 1
qc.rz(q, theta[param_idx])
param_idx += 1
return qc
def optimize(self, layers=3, learning_rate=0.1, max_iter=100):
"""运行 VQE 优化"""
# 初始化参数
n_params = 2 * self.n_qubits * (layers + 1)
params = nn.Parameter(torch.randn(n_params) * 0.01)
# 创建优化器
optimizer = torch.optim.Adam([params], lr=learning_rate)
# 记录历史
loss_history = []
print(f"\n开始 VQE 优化")
print(f" 参数数量: {n_params}")
print(f" 最大迭代: {max_iter}")
for i in range(max_iter):
optimizer.zero_grad()
# 计算当前能量
qc = self.create_ansatz(params, layers)
current_energy = self.hamiltonian.compute_energy_with_circuit(qc)
loss_history.append(current_energy)
# 数值微分计算梯度
eps = 1e-5
grad = torch.zeros_like(params)
for j in range(len(params)):
params_plus = params.detach().numpy().copy()
params_plus[j] += eps
qc_plus = self.create_ansatz(torch.tensor(params_plus), layers)
energy_plus = self.hamiltonian.compute_energy_with_circuit(qc_plus)
params_minus = params.detach().numpy().copy()
params_minus[j] -= eps
qc_minus = self.create_ansatz(torch.tensor(params_minus), layers)
energy_minus = self.hamiltonian.compute_energy_with_circuit(qc_minus)
grad[j] = (energy_plus - energy_minus) / (2 * eps)
# 更新参数
params.grad = grad
optimizer.step()
# 打印进度
if i % 10 == 0 or i == max_iter - 1:
if self.hamiltonian.fci_energy:
error = abs(current_energy - self.hamiltonian.fci_energy)
print(f"Iter {i:>3d}: E = {current_energy:>10.6f}, Error = {error:>10.6f}")
else:
print(f"Iter {i:>3d}: E = {current_energy:>10.6f}")
return params.detach().numpy(), loss_history
完整示例¶
示例 1:简单横场 Ising 模型¶
"""
横场 Ising 模型的 VQE 求解
H = -J∑ZᵢZᵢ₊₁ - h∑Xᵢ
"""
import deepquantum as dq
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np
class TransverseIsingModel:
"""横场 Ising 模型"""
def __init__(self, n_qubits, J=1.0, h=1.0):
self.n_qubits = n_qubits
self.J = J # 耦合强度
self.h = h # 横场强度
# 构建哈密顿量
self.constant_term, self.observable_list = self._build_hamiltonian()
def _build_hamiltonian(self):
"""构建哈密顿量"""
constant_term = 0.0
observable_list = []
# ZZ 相互作用项
for i in range(self.n_qubits - 1):
obs = dq.Observable(nqubit=self.n_qubits, wires=[i, i+1], basis='zz')
observable_list.append((-self.J, obs))
# 横场 X 项
for i in range(self.n_qubits):
obs = dq.Observable(nqubit=self.n_qubits, wires=[i], basis='x')
observable_list.append((-self.h, obs))
return constant_term, observable_list
def compute_energy(self, state):
"""计算能量"""
energy = self.constant_term
for coeff, obs in self.observable_list:
exp_val = dq.expectation(state, obs).item()
energy += coeff * exp_val
return energy
def exact_diagonalization(self):
"""精确对角化(用于验证)"""
# 构建完整矩阵
dim = 2 ** self.n_qubits
H = np.zeros((dim, dim))
for coeff, obs in self.observable_list:
unitary = obs.get_unitary().numpy()
H += coeff.numpy() * unitary if hasattr(coeff, 'numpy') else coeff * unitary
# 对角化
eigenvalues = np.linalg.eigvalsh(H)
return eigenvalues[0] # 基态能量
# VQE 求解
def vqe_ising_model(n_qubits=3, J=1.0, h=1.0, layers=2):
"""VQE 求解横场 Ising 模型"""
print(f"\n横场 Ising 模型 VQE")
print(f" 量子比特数: {n_qubits}")
print(f" J = {J}, h = {h}")
# 创建哈密顿量
model = TransverseIsingModel(n_qubits, J, h)
# 精确解
exact_energy = model.exact_diagonalization()
print(f" 精确基态能量: {exact_energy:.6f}")
# VQE 优化
n_params = n_qubits * 2 * (layers + 1)
params = nn.Parameter(torch.randn(n_params) * 0.01)
optimizer = torch.optim.Adam([params], lr=0.1)
loss_history = []
for i in range(100):
optimizer.zero_grad()
# 创建电路
qc = dq.QubitCircuit(n_qubits)
param_idx = 0
for layer in range(layers):
for q in range(n_qubits):
qc.ry(q, params[param_idx])
param_idx += 1
qc.rz(q, params[param_idx])
param_idx += 1
for q in range(n_qubits - 1):
qc.cz(q, q + 1)
for q in range(n_qubits):
qc.ry(q, params[param_idx])
param_idx += 1
qc.rz(q, params[param_idx])
param_idx += 1
# 计算能量
state = qc()
energy = model.compute_energy(state)
loss_history.append(energy)
# 数值梯度
eps = 1e-5
grad = torch.zeros_like(params)
for j in range(len(params)):
params_plus = params.clone()
params_plus[j] += eps
# ... (重新计算电路和能量)
energy_plus = energy # 简化示例
params_minus = params.clone()
params_minus[j] -= eps
energy_minus = energy # 简化示例
grad[j] = (energy_plus - energy_minus) / (2 * eps)
params.grad = grad
optimizer.step()
if i % 20 == 0:
error = abs(energy - exact_energy)
print(f"Iter {i:3d}: E = {energy:.6f}, Error = {error:.6f}")
vqe_energy = loss_history[-1]
error = abs(vqe_energy - exact_energy)
print(f"\n结果:")
print(f" VQE 能量: {vqe_energy:.6f}")
print(f" 精确能量: {exact_energy:.6f}")
print(f" 绝对误差: {error:.6f}")
return loss_history, exact_energy
# 运行
if __name__ == "__main__":
loss_history, exact_energy = vqe_ising_model(n_qubits=3, J=1.0, h=1.0, layers=2)
# 绘制收敛曲线
plt.figure(figsize=(10, 6))
plt.plot(loss_history, 'b-', linewidth=2, label='VQE Energy')
plt.axhline(y=exact_energy, color='r', linestyle='--',
linewidth=2, label='Exact Ground State')
plt.xlabel('Iteration', fontsize=12)
plt.ylabel('Energy', fontsize=12)
plt.title('Transverse Ising Model VQE', fontsize=14)
plt.legend(fontsize=12)
plt.grid(True, alpha=0.3)
plt.show()
示例 2:水分子 VQE(完整版)¶
"""
水分子 VQE:使用 PennyLane 哈密顿量 + DeepQuantum
"""
import pennylane as qml
from pennylane import qchem
from deepquantum import Observable
import deepquantum as dq
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
def get_water_hamiltonian():
"""获取水分子哈密顿量"""
# 水分子几何参数
symbols = ['O', 'H', 'H']
coordinates = np.array([
0.0, 0.0, 0.0, # 氧原子
0.757, 0.0, 0.587, # 氢原子1
-0.757, 0.0, 0.587 # 氢原子2
])
# 计算哈密顿量(使用活性空间)
H_h2o, qubits = qchem.molecular_hamiltonian(
symbols, coordinates,
active_electrons=4,
active_orbitals=4,
basis="sto-3g"
)
# 对称性简化
try:
generators = qchem.symmetry_generators(H_h2o)
paulixops = qchem.paulix_ops(generators, qubits)
target_sector = [-1] * len(generators)
H_tapered = qchem.taper(H_h2o, generators, paulixops, target_sector)
coeffs, pauli_terms = H_tapered.terms()
except:
coeffs, pauli_terms = H_h2o.terms()
# 计算 FCI 能量
matrix = qml.matrix(H_tapered if 'H_tapered' in locals() else H_h2o)
fci_energy = np.linalg.eigvalsh(matrix)[0]
return coeffs, pauli_terms, qubits, fci_energy
# 主程序
if __name__ == "__main__":
print("=" * 70)
print("水分子 VQE (DeepQuantum)")
print("=" * 70)
# 获取哈密顿量
coeffs, pauli_terms, n_qubits, fci_energy = get_water_hamiltonian()
print(f"\n哈密顿量信息:")
print(f" 量子比特数: {n_qubits}")
print(f" 泡利项数: {len(coeffs)}")
print(f" FCI 能量: {fci_energy:.6f} Hartree")
# 创建 VQE 哈密顿量对象
from vqe_hamiltonian import VQEHHamiltonian, VQEOptimizer
hamiltonian = VQEHHamiltonian(coeffs, pauli_terms, n_qubits, fci_energy)
optimizer = VQEOptimizer(hamiltonian, n_qubits, n_electrons=4)
# 运行优化
final_params, loss_history = optimizer.optimize(
layers=3,
learning_rate=0.1,
max_iter=100
)
# 绘图
plt.figure(figsize=(10, 6))
plt.plot(loss_history, 'b-', linewidth=2, label='VQE Energy')
plt.axhline(y=fci_energy, color='r', linestyle='--',
linewidth=2, label='FCI Energy')
plt.xlabel('Iteration', fontsize=12)
plt.ylabel('Energy (Hartree)', fontsize=12)
plt.title('Water Molecule VQE', fontsize=14)
plt.legend(fontsize=12)
plt.grid(True, alpha=0.3)
plt.savefig('water_vqe.png', dpi=300)
plt.show()
print(f"\n最终结果:")
print(f" VQE 能量: {loss_history[-1]:.6f} Hartree")
print(f" FCI 能量: {fci_energy:.6f} Hartree")
print(f" 绝对误差: {abs(loss_history[-1] - fci_energy):.6f} Hartree")
print(f" 相对误差: {abs(loss_history[-1] - fci_energy)/abs(fci_energy)*100:.4f}%")
常见问题¶
Q1: 为什么能量计算结果是 0?¶
原因: 忘记处理常数项(Identity 算符)。
解决:
# 错误示例
energy = 0.0
for coeff, obs in observable_list:
energy += coeff * dq.expectation(state, obs).item()
# 结果:energy 可能接近 0
# 正确示例
energy = constant_term # ← 加上常数项!
for coeff, obs in observable_list:
energy += coeff * dq.expectation(state, obs).item()
Q2: expectation() 返回的是什么?¶
回答: 返回一个 torch.Tensor 标量(0 维张量)。
exp_val = dq.expectation(state, obs)
print(type(exp_val)) # <class 'torch.Tensor'>
print(exp_val.shape) # torch.Size([])
# 获取 Python 标量
scalar_value = exp_val.item()
print(type(scalar_value)) # <class 'float'>
Q3: 如何验证哈密顿量构建是否正确?¶
方法: 使用精确对角化验证。
def verify_hamiltonian(constant_term, observable_list, n_qubits):
"""验证哈密顿量是否正确"""
# 构建完整矩阵
dim = 2 ** n_qubits
H = torch.zeros((dim, dim), dtype=torch.cfloat)
# 添加常数项
H += constant_term * torch.eye(dim)
# 添加泡利项
for coeff, obs in observable_list:
unitary = obs.get_unitary()
H += coeff * unitary
# 检查是否为厄米矩阵
is_hermitian = torch.allclose(H, H.conj().T)
print(f"哈密顿量是厄米的: {is_hermitian}")
# 对角化
eigenvalues = torch.linalg.eigvalsh(H)
print(f"最小本征值: {eigenvalues[0]:.6f}")
return eigenvalues
Q4: 如何处理大型哈密顿量?¶
建议: 1. **不要**构建完整矩阵(指数级复杂度) 2. **要**直接计算泡利项期望值(线性复杂度)
# ❌ 错误:大型系统
n_qubits = 50
dim = 2 ** 50 # 不可能!
H = np.zeros((dim, dim)) # 内存溢出
# ✅ 正确:逐项计算
for coeff, obs in observable_list:
exp_val = dq.expectation(state, obs).item()
energy += coeff * exp_val
Q5: Observable 的 wires 参数可以是任意顺序吗?¶
回答: 可以,但要注意顺序对应关系。
# 这两个是不同的:
obs1 = dq.Observable(nqubit=3, wires=[0, 1], basis='zz') # Z₀⊗Z₁⊗I₂
obs2 = dq.Observable(nqubit=3, wires=[1, 0], basis='zz') # I₀⊗Z₁⊗Z₀
# 基底字符顺序与 wires 顺序对应
obs3 = dq.Observable(nqubit=3, wires=[0, 1, 2], basis='xzy') # X₀⊗Z₁⊗Y₂
最佳实践¶
1. 哈密顿量构建¶
✅ 推荐:
# 使用函数封装,支持多种输入格式
def build_hamiltonian(source, **kwargs):
"""
Args:
source: 'manual', 'pennylane', 'qasm', ...
"""
if source == 'pennylane':
return _build_from_pennylane(**kwargs)
elif source == 'manual':
return _build_from_manual(**kwargs)
# ...
❌ 不推荐:
2. 常数项处理¶
✅ 推荐:
class Hamiltonian:
def __init__(self):
self.constant_term = 0.0
self.observables = []
def add_term(self, coeff, obs):
if obs is None or len(obs.wires) == 0:
self.constant_term += coeff
else:
self.observables.append((coeff, obs))
❌ 不推荐:
3. 能量计算优化¶
✅ 推荐:
# 批处理多个态
def batch_compute_energy(states, hamiltonian):
energies = []
for state in states:
energy = hamiltonian.compute_energy(state)
energies.append(energy)
return torch.tensor(energies)
❌ 不推荐:
# 重复计算
for _ in range(100):
state = create_circuit(params)()
energy = compute_energy(state) # 每次都重新创建
4. 梯度计算¶
✅ 推荐:
# Parameter Shift Rule(解析梯度)
def parameter_shift_gradient(circuit, params, i):
shift = np.pi / 2
params_plus = params.clone()
params_plus[i] += shift
E_plus = compute_energy(circuit(params_plus))
params_minus = params.clone()
params_minus[i] -= shift
E_minus = compute_energy(circuit(params_minus))
return (E_plus - E_minus) / 2
❌ 不推荐:
5. 错误处理¶
✅ 推荐:
def safe_compute_energy(state, obs_list):
energy = 0.0
failed_terms = []
for i, (coeff, obs) in enumerate(obs_list):
try:
exp_val = dq.expectation(state, obs).item()
energy += coeff * exp_val
except Exception as e:
failed_terms.append(i)
print(f"警告:第 {i} 项计算失败: {e}")
if failed_terms:
print(f"失败项索引: {failed_terms}")
return energy
6. 单位和尺度¶
✅ 推荐:
# 明确标注单位
class Hamiltonian:
def __init__(self, unit='Hartree'):
self.unit = unit
self.constant_term = 0.0
def compute_energy(self, state):
energy_eh = self.constant_term # Hartree
for coeff, obs in self.observables:
energy_eh += coeff * exp_val
# 转换
if self.unit == 'Hartree':
return energy_eh
elif self.unit == 'eV':
return energy_eh * 27.2114
elif self.unit == 'kcal/mol':
return energy_eh * 627.509
附录¶
A. 泡利矩阵¶
# 单量子比特泡利矩阵
I = np.array([[1, 0], [0, 1]]) # 单位矩阵
X = np.array([[0, 1], [1, 0]]) # 泡利-X (NOT门)
Y = np.array([[0, -1j], [1j, 0]]) # 泡利-Y
Z = np.array([[1, 0], [0, -1]]) # 泡利-Z
# 两量子比特泡利张量积
XX = np.kron(X, X)
XY = np.kron(X, Y)
# ...
B. 期望值公式¶
对于量子态 |ψ⟩,可观测量 A 的期望值:
对于哈密顿量 H = Σ cᵢPᵢ:
C. 化学精度¶
VQE 目标:误差 < 0.0016 Hartree
D. 常用基组¶
| 基组 | 说明 | 适用场景 |
|---|---|---|
| STO-3G | 最小基组 | 快速测试 |
| 6-31G | 分裂价键基 | 一般计算 |
| cc-pVDZ | 相关一致基 | 精确计算 |
| cc-pVTZ | 三重ζ | 高精度 |
E. 活性空间选择¶
# 水分子 (10 电子)
H₂O: 1s²O 2s²2p⁶O 1s²H₁ 1s²H₂
# 最小活性空间 (4e, 4o)
active_electrons = 4 # 2p 轨道的 4 个电子
active_orbitals = 4 # 2s, 2px, 2py, 2pz
# 完整活性空间 (10e, 7o)
active_electrons = 10
active_orbitals = 7 # 1s, 2s, 2px, 2py, 2pz, 1s(H1), 1s(H2)
参考资源¶
- DeepQuantum 文档: https://github.com/DeepQUAntum/deepquantum
- PennyLane 文档: https://pennylane.ai/
- VQE 原始论文: Peruzzo et al. (2014)
- 量子化学计算: Szabo & Ostlund, "Modern Quantum Chemistry"
文档版本: 1.0 创建日期: 2025年 最后更新: 2025年 作者: 基于实际代码和 DeepQuantum 源码分析 许可: MIT