Skip to content

哈密顿量与 Pauli 算子

本教程介绍 pyqpanda3 中的哈密顿量与 Pauli 算子框架。你将学习如何构造 Pauli 算子、组合哈密顿量以及计算期望值——这些是变分量子算法(如 VQE 和 QAOA)的核心构建模块。

前置条件:模拟——你应该熟悉创建量子程序并在模拟器上运行它们。


目录


1. 什么是哈密顿量?

在量子力学中,哈密顿量 H 是对应系统总能量的算子。它通过薛定谔方程决定量子态如何随时间演化:

it|ψ(t)=H|ψ(t)

能量本征值问题

哈密顿量的本征态满足:

H|ψn=En|ψn

其中 En 是能量本征值。基态是具有最低能量 E0 的本征态。

变分原理

变分原理为近似基态能量提供了强有力的工具。对于任意试探态 |ψ

E0ψ|H|ψ

这个不等式意味着,对于任意状态 |ψH 的期望值始终大于或等于真实的基态能量。这一原理是变分量子本征求解器(VQE)算法的基础:

  1. 制备一个参数化试探态 |ψ(θ)
  2. 测量期望值 H=ψ(θ)|H|ψ(θ)
  3. 使用经典优化器在 θ 上最小化 H
  4. 最小值给出 E0 的上界。

为什么使用 Pauli 算子?

量子硬件只能在计算基(Z 基)下直接进行测量。为了测量一般的哈密顿量,我们需要将其分解为 Pauli 算子之和:

H=iciPi,Pi{I,X,Y,Z}n

其中每个 Pi 是单量子比特 Pauli 矩阵(包括单位矩阵)的张量积,ci 是实数或复数系数。根据期望值的线性性质:

H=iciPi

每一项 Pi 可以单独测量(或与其他对易项组合测量)。


2. Pauli 矩阵回顾

四个单量子比特 Pauli 矩阵为:

σI=(1001),σX=(0110)σY=(0ii0),σZ=(1001)

关键性质:

性质表达式
厄米性σi=σi
幺正性σi2=I
无迹性(X, Y, Z)Tr(σi)=0
反对易性σiσj=σjσi,当 ij
对易关系[σi,σj]=2iϵijkσk

多量子比特 Pauli 算子通过张量积构成。例如:

XZ=X0Z1=(0010000110000100)

下标表示 Pauli 门作用的量子比特索引。


3. PauliOperator 类

pyqpanda3.hamiltonian 中的 PauliOperator 类表示多量子比特 Pauli 项的线性组合。它是在 pyqpanda3 中定义哈密顿量和可观测量的主要方式。

python
from pyqpanda3.hamiltonian import PauliOperator

3.1 构造方法

PauliOperator 提供多种构造函数以适应不同的输入格式。下图总结了可用的构造路径:

默认和拷贝构造函数

python
# 创建空的 PauliOperator
op_empty = PauliOperator()

# 拷贝现有算子
op_copy = PauliOperator(op_existing)

从字符串构造

不带显式系数的单个 Pauli 项(默认系数为 1.0):

python
# 量子比特 0 上的单量子比特 Pauli-X
op_x = PauliOperator("X0")

# 多量子比特项:量子比特 0 上的 X,量子比特 1 上的 Z
op_xz = PauliOperator("X0 Z1")

# 三量子比特项
op_xyz = PauliOperator("X0 Y1 Z2")

字符串格式使用 <Pauli><量子比特索引> 的模式,以空格分隔。有效的 Pauli 字符为 XYZI

从字典构造

最常用的构造方法——将 Pauli 字符串映射到系数的字典:

python
# 带实数系数的多个项
op = PauliOperator({
    "X0 Z1": 1.0,
    "Z0 Z1": 0.5,
    "Y0 X1": -0.3
})

# 也支持复数系数
import numpy as np
op_complex = PauliOperator({
    "X0 Z1": 1.0 + 0.5j,
    "Z0 Z1": -0.2 + 0.1j
})

这是构造多项算子的推荐方式。

从字符串和系数列表构造

两个平行列表:一个用于 Pauli 字符串,一个用于系数:

python
paulis = ["X0 Z1", "Y2 I1"]
coefs = [1.1, 2.1]

op = PauliOperator(paulis, coefs)

两个列表的长度必须相同。

带 AB 标志的列表构造

AB_is_A1_B0=True 时,Pauli 字符串被解释为不带显式量子比特索引的紧凑序列。字符位置映射到量子比特:位置 0 映射到量子比特 0,位置 1 映射到量子比特 1,依此类推。

python
# "XZI" 表示:量子比特 0 上的 X,量子比特 1 上的 Z,量子比特 2 上的 I
# "IZX" 表示:量子比特 0 上的 I,量子比特 1 上的 Z,量子比特 2 上的 X
op = PauliOperator(["XZI", "IZX"], [1.1, 2.1], True)

AB_is_A1_B0=False 时,字符串位置按反向量子比特顺序解释(位置 0 映射到最高索引的量子比特)。

从元组列表构造

每个元组包含 (pauli_string, qubit_indices, coefficient)

python
# ("XZ", [0, 4], 1.1) 表示量子比特 0 上的 X,量子比特 4 上的 Z,系数为 1.1
# ("YX", [1, 2], 2.1) 表示量子比特 1 上的 Y,量子比特 2 上的 X,系数为 2.1
op = PauliOperator([
    ("XZ", [0, 4], 1.1),
    ("YX", [1, 2], 2.1)
])

此格式提供对每个 Pauli 字符作用量子比特的显式控制。

从 Numpy 矩阵构造

维度为 2n×2n 的实值方阵会自动分解为其 Pauli 表示:

python
import numpy as np

# 2x2 矩阵(单量子比特)
mat = np.array([[1.0, 0.0],
                [0.0, -1.0]])

op = PauliOperator(mat)
# 等价于 PauliOperator({"Z0": 1.0})

矩阵的维度必须是 2 的幂。pyqpanda3 内部会对输入矩阵执行 Pauli 分解。

3.2 代数运算

PauliOperator 支持标准算术运算符。所有操作返回对象(保持不可变性)。

加法和减法

python
from pyqpanda3.hamiltonian import PauliOperator

op1 = PauliOperator({"X0 Z1": 1.0, "Z0 Z1": 0.5})
op2 = PauliOperator({"Y0 X1": 0.3})

# 两个算子相加
op_sum = op1 + op2
# 结果: {"X0 Z1": 1.0, "Z0 Z1": 0.5, "Y0 X1": 0.3}

# 减法
op_diff = op1 - op2
# 结果: {"X0 Z1": 1.0, "Z0 Z1": 0.5, "Y0 X1": -0.3}

# 加标量(添加常数项,等价于 c * I)
op_shifted = op1 + 1.5

# 标量减法
op_lowered = op1 - 0.5

当两个项具有相同的 Pauli 字符串时,它们的系数会合并:

python
a = PauliOperator({"Z0": 1.0})
b = PauliOperator({"Z0": 2.5})
c = a + b
# 结果: {"Z0": 3.5}

如果系数相互抵消,该项会被自动移除:

python
a = PauliOperator({"X0": 1.0})
b = PauliOperator({"X0": 1.0})
c = a - b
# 结果:空算子(无项)

标量乘法和除法

python
op = PauliOperator({"X0 Z1": 2.0, "Y0": 1.0})

# 乘以标量
op_doubled = op * 2.0
# 结果: {"X0 Z1": 4.0, "Y0": 2.0}

# 也支持左乘
op_tripled = 3.0 * op
# 结果: {"X0 Z1": 6.0, "Y0": 3.0}

# 除法
op_halved = op * 0.5
# 结果: {"X0 Z1": 1.0, "Y0": 0.5}

算子乘法

* 运算符执行代数乘法。对于左右操作数中的每一对项,Pauli 字符串按照 Pauli 代数规则相乘:

XY=iZ,YZ=iX,ZX=iYXX=I,YY=I,ZZ=I
python
a = PauliOperator({"X0": 1.0})
b = PauliOperator({"Y0": 1.0})
c = a * b
# X * Y = iZ,所以结果: {"Z0": 1j}

@ 运算符(矩阵乘法)是 * 的别名:

python
d = a @ b
# 与 a * b 的结果相同

取负

python
op = PauliOperator({"X0 Z1": 1.5})
neg = -op
# 结果: {"X0 Z1": -1.5}

原地操作

虽然二元运算符返回新对象,但原地变体(+=-=*=)会修改左操作数:

python
op = PauliOperator({"X0": 1.0})
op += PauliOperator({"Y0": 0.5})
# op 现在为 {"X0": 1.0, "Y0": 0.5}

op *= 2.0
# op 现在为 {"X0": 2.0, "Y0": 1.0}

3.3 张量积

张量积(Kronecker 积)组合作用于不同量子比特集合的两个算子。在 pyqpanda3 中,使用 .tensor() 方法:

python
a = PauliOperator({"X0": 1.0})   # 作用于量子比特 0
b = PauliOperator({"Z0": 0.5})   # 作用于量子比特 0

# 张量积:a 的量子比特保持不变,b 的量子比特被偏移
result = a.tensor(b)
# 结果:量子比特 0 上的 X,量子比特 1 上的 Z,系数 0.5
# 等价于 PauliOperator({"X0 Z1": 0.5})

你也可以将算子与自身张量 n 次:

python
op = PauliOperator({"X0": 1.0})

# op 与自身张量 3 次
# 结果:量子比特 0 上的 X,量子比特 1 上的 X,量子比特 2 上的 X
result = op.tensor(3)

3.4 检查与转换

字符串表示

python
op = PauliOperator({"X0 Z1": 1.0, "Y2": 0.5, "I0 Z1": 0.3})

# 不含单位算子的字符串(默认 __str__)
print(op)
# 输出仅包含非平凡的 Pauli 项,例如 "X0 Z1" + 1.0, "Y2" + 0.5, ...

# 包含单位算子的字符串
print(op.str_with_I(True))
# 显示每个项的完整 Pauli 字符串(包括 I)

# 不含单位算子的字符串(替代方法)
print(op.str_no_I())

AB_is_A1_B0 参数控制字符串表示中量子比特索引的排序方式。

矩阵转换

将 PauliOperator 转换为其矩阵表示:

python
op = PauliOperator({"Z0": 1.0})
mat = op.matrix()
print(mat)
# 输出(numpy 复数矩阵):
# [[1+0j, 0+0j],
#  [0+0j, -1+0j]]

对于多量子比特算子,矩阵维度为 2n+1×2n+1,其中 n 是最高量子比特索引:

python
op2 = PauliOperator({"X0 Z1": 1.0})
mat2 = op2.matrix()
# 4x4 矩阵
print(mat2.shape)  # (4, 4)

访问内部数据

多种方法以不同格式公开算子的内部数据:

python
op = PauliOperator({"X0 Z1": 1.5, "Y2": -0.3})

# 三元组列表:(pauli_string, qubit_indices, complex_coefficient)
data_complex = op.data_3tuple_list_complex_coeff()
# [("XZ", [0, 1], 1.5+0j), ("Y", [2], -0.3+0j)]

# 带浮点系数的三元组列表
data_float = op.data_3tuple_list_float_coeff()
# [("XZ", [0, 1], 1.5), ("Y", [2], -0.3)]

# 字符串键和浮点值的字典
data_dict = op.data_dict_float_coeff()
# {"X0 Z1": 1.5, "Y2": -0.3}

# 字符串键和复数值的字典
data_dict_c = op.data_dict_complex_coeff()
# {"X0 Z1": (1.5+0j), "Y2": (-0.3+0j)}

获取量子比特列表

python
op = PauliOperator({"X0 I1 Z2": 1.0})
i_qubits, xyz_qubits = op.qubits()
# i_qubits: [1]          -- 仅被 I 作用的量子比特
# xyz_qubits: [0, 2]     -- 被 X、Y 或 Z 作用的量子比特

最大量子比特索引

python
op = PauliOperator({"X0 Z3": 1.0})
print(op.max_qbit_idx())  # 3

访问项

python
op = PauliOperator({"X0 Z1": 1.0, "Y2": 0.5})
terms = op.terms()
for term in terms:
    print(f"系数: {term.coef()}")
    paulis = term.paulis()
    for pwq in paulis:
        print(f"  量子比特 {pwq.qbit()}: {pwq.pauli_char()}")

序列化

python
op = PauliOperator({"Z0": 0.5, "X1": -0.3})

# 序列化为字符串
s = op.data_dict_str()
# 例如,'"Z0": 0.5, "X1": -0.3'

# 从字符串反序列化
op_restored = PauliOperator.from_dict_str(s)

3.5 对易分组

为了高效测量,你可以将对易的 Pauli 项分组在一起:

python
op = PauliOperator({
    "X0 X1": 1.0,
    "Z0 Z1": 0.5,
    "Y0 Y1": -0.3,
    "Z0": 0.2
})

# 按完全对易分组
groups = op.group_commuting(qubit_wise=False)

# 按逐量子比特对易分组(更严格的分组)
groups_qw = op.group_commuting(qubit_wise=True)

for i, group in enumerate(groups):
    print(f"组 {i}: {group}")

逐量子比特对易组可以使用每组单次基旋转同时测量,这对于减少变分算法中线路执行次数至关重要。


4. Hamiltonian 类

pyqpanda3.hamiltonian 中的 Hamiltonian 类是 PauliOperator 的轻量封装,表示量子哈密顿量。它支持与 PauliOperator 相同的构造函数和代数运算,但专门用于算子表示物理哈密顿量的场景。

python
from pyqpanda3.hamiltonian import Hamiltonian, PauliOperator

构造方法

Hamiltonian 支持与 PauliOperator 相同的构造模式:

python
# 默认构造(空)
H1 = Hamiltonian()

# 从 Pauli 字符串字典构造
H2 = Hamiltonian({"X0 Z1": 1.0, "Z0 Z1": 0.5})

# 从 PauliOperator 构造
pauli_op = PauliOperator({"X0 Z1": 1.0, "Z0 Z1": 0.5})
H3 = Hamiltonian(pauli_op)

# 从字符串构造(量子比特 0 上的单个 Pauli)
H4 = Hamiltonian("Z")

# 从列表构造
H5 = Hamiltonian(["X0 Z1", "Y2 I1"], [1.1, 2.1])

# 带 AB 标志的列表构造
H6 = Hamiltonian(["XZI", "IZX"], [1.1, 2.1], True)

# 从元组构造
H7 = Hamiltonian([("XZ", [0, 4], 1.1), ("YX", [1, 2], 2.1)])

# 从 numpy 矩阵构造
import numpy as np
H8 = Hamiltonian(np.array([[1, 0], [0, -1]]))

代数运算

算术运算符与 PauliOperator 完全相同:

python
ha = Hamiltonian({"X0 Z1": 1.0})
hb = Hamiltonian({"Y0 X1": 0.5})

# 加法
h_sum = ha + hb

# 减法
h_diff = ha - hb

# 标量乘法
h_scaled = ha * 2.0

# 算子乘法
h_prod = ha * hb

# 张量积
h_tensor = ha.tensor(hb)

# 取负
h_neg = -ha

提取底层 PauliOperator

python
H = Hamiltonian({"Z0": 1.0, "X0": 0.5})

# 获取底层的 PauliOperator
pauli = H.pauli_operator()

# 转换为矩阵
mat = H.matrix()

字符串表示

python
H = Hamiltonian({"X0 Z1": 1.0, "Y2": 0.5})

print(H)              # 默认字符串(不含 I)
print(H.str_with_I()) # 包含单位算子的完整字符串
print(H.str_no_I())   # 不含 I 的紧凑字符串

何时使用 Hamiltonian 与 PauliOperator

  • 当你需要细粒度访问各个项、Pauli 分解数据、对易组分析,或为通用目的构建可观测量时,使用 PauliOperator
  • 当你需要与专门期望 Hamiltonian 类型的函数(如 expval_hamiltonian())交互时,使用 Hamiltonian

在大多数期望值函数中,两种类型可以互换使用,因为 pyqpanda3 为每种类型提供了单独的 API。


5. 期望值计算

计算期望值 ψ|H|ψ 是变分量子算法中的核心操作。pyqpanda3 为此提供了两个函数。

5.1 核心 API

两个函数都由 pyqpanda3.core 导出:

python
from pyqpanda3.core import expval_hamiltonian, expval_pauli_operator, QProg, CPUQVM
from pyqpanda3.hamiltonian import Hamiltonian, PauliOperator

expval_hamiltonian

python
expval_hamiltonian(
    prog,             # QProg -- 量子程序
    hamiltonian,      # Hamiltonian -- 可观测量
    shots=1,          # int -- 测量次数(1 = 态矢量)
    model=NoiseModel(),  # 可选噪声模型
    used_threads=4,   # int -- 并行线程数
    backend="CPU"     # str -- "CPU" 或 "GPU"
) -> float

expval_pauli_operator

python
expval_pauli_operator(
    prog,             # QProg -- 量子程序
    pauli_operator,   # PauliOperator -- 可观测量
    shots=1,          # int -- 测量次数(1 = 态矢量)
    model=NoiseModel(),  # 可选噪声模型
    used_threads=4,   # int -- 并行线程数
    backend="CPU"     # str -- "CPU" 或 "GPU"
) -> float

下图说明了期望值计算流程:

shots=1 时,函数使用态矢量模拟计算精确期望值。当 shots > 1 时,它使用指定次数的测量进行基于采样的估计。

5.2 示例:Bell 态

让我们计算 Bell 态 |Φ+=12(|00+|11) 关于 Pauli 算子的期望值:

python
from pyqpanda3 import core
from pyqpanda3.hamiltonian import PauliOperator

# 创建 Bell 态: |00> + |11>
prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.BARRIER([0, 1])

# 定义可观测量: Z0 * Z1
# 对于 |00> + |11>,ZZ 的期望值为 1.0
# 因为 ZZ|00> = |00> 且 ZZ|11> = |11>
op_zz = PauliOperator({"Z0 Z1": 1.0})

# 计算精确期望值(shots=1)
exp_val = core.expval_pauli_operator(prog, op_zz)
print(f"<ZZ> = {exp_val}")  # 预期: 1.0

# 使用有限次数测量计算(统计估计)
exp_val_shots = core.expval_pauli_operator(prog, op_zz, shots=1000)
print(f"<ZZ> (1000 次测量) = {exp_val_shots}")  # 接近 1.0

多项算子

python
# 定义多项算子
op = PauliOperator({
    "Z0 Z1": 0.5,   # ZZ 相互作用
    "X0 X1": 0.3,   # XX 相互作用
    "Y0 Y1": 0.2    # YY 相互作用
})

exp_val = core.expval_pauli_operator(prog, op)
print(f"<H> = {exp_val}")

期望值计算为:

H=0.5Z0Z1+0.3X0X1+0.2Y0Y1

对于 Bell 态 |Φ+

Z0Z1=1,X0X1=1,Y0Y1=1

因此预期结果为 0.5(1)+0.3(1)+0.2(1)=0.6

使用 Hamiltonian API

python
from pyqpanda3.hamiltonian import Hamiltonian

H = Hamiltonian({"Z0 Z1": 0.5, "X0 X1": 0.3})

exp_val = core.expval_hamiltonian(prog, H)
print(f"<H> = {exp_val}")

5.3 使用噪声模型

在计算期望值时可以包含噪声模型,以模拟真实硬件条件:

python
from pyqpanda3.core import NoiseModel, pauli_x_error, depolarizing_error, GateType

# 构建噪声模型
model = NoiseModel()
model.add_all_qubit_quantum_error(pauli_x_error(0.01), GateType.H)
model.add_all_qubit_quantum_error(depolarizing_error(0.02), GateType.CNOT)

# 创建线路
prog = core.QProg()
prog << core.H(0) << core.CNOT(0, 1) << core.BARRIER([0, 1])

# 定义可观测量
op = PauliOperator({"Z0 Z1": 1.0})

# 计算含噪声的期望值
exp_val_noisy = core.expval_pauli_operator(
    prog, op,
    shots=1000,
    model=model
)
print(f"<ZZ> (含噪声) = {exp_val_noisy}")

在存在噪声的情况下,期望值会由于门误差而偏离理想值 1.0。


6. PauliTerm 和 PauliWithQbit 辅助类

在内部,PauliOperatorPauliTerm 对象组成,每个对象包含 PauliWithQbit 条目。这些类提供了检查各个项的结构化方式。

PauliTerm

PauliTerm 表示 Pauli 分解中的单个项 cP0P1

python
op = PauliOperator({"X0 Z1": 1.5, "Y2": -0.3})
terms = op.terms()

for term in terms:
    # 获取系数
    c = term.coef()
    print(f"系数: {c}")

    # 获取所有 Pauli-量子比特对
    paulis = term.paulis()
    for pwq in paulis:
        print(f"  量子比特 {pwq.qbit()}: Pauli {pwq.pauli_char()}")

    # 获取量子比特分类
    i_qubits, xyz_qubits = term.qubits()
    print(f"  仅 I 量子比特: {i_qubits}")
    print(f"  XYZ 量子比特: {xyz_qubits}")

    # 以各种格式导出数据
    data_3c = term.data_3tuple_complex_coeff()
    data_2c = term.data_2tuple_complex_coeff()
    data_3f = term.data_3tuple_float_coeff()
    data_2f = term.data_2tuple_float_coeff()

    # 转换为量子线路
    circuit = term.to_qcircuit()

PauliWithQbit

PauliWithQbit 将单个 Pauli 算子与特定量子比特配对:

python
op = PauliOperator({"X0 Y1 Z2": 1.0})
terms = op.terms()

for term in terms:
    for pwq in term.paulis():
        qubit = pwq.qbit()          # 量子比特索引
        is_x = pwq.is_X()           # 如果是 Pauli-X 则为 True
        is_y = pwq.is_Y()           # 如果是 Pauli-Y 则为 True
        is_z = pwq.is_Z()           # 如果是 Pauli-Z 则为 True
        is_i = pwq.is_I()           # 如果是单位矩阵则为 True
        char = pwq.pauli_char()     # 'X'、'Y'、'Z' 或 'I'
        gate = pwq.to_qgate()       # 对应的 QGate 对象

        print(f"量子比特 {qubit}: {char}")

7. 实践示例:H2 分子的 VQE

本节演示使用变分量子本征求解器(VQE)估算 H2 分子基态能量的完整工作流程。

背景

H2 在平衡键长下的电子哈密顿量,经过 Jordan-Wigner 变换并冻结核心轨道后,可以表示为 2 量子比特 Pauli 算子:

HH2=c0I+c1Z0+c2Z1+c3Z0Z1+c4X0X1

对于约 0.74 埃的键距,系数为:

系数
c0-1.0523792
c1-0.3979374
c2-0.3979374
c3-0.0112801
c40.1809313

精确基态能量约为 1.137 Hartree。

第 1 步:定义哈密顿量

python
from pyqpanda3.hamiltonian import PauliOperator

# H2 哈密顿量系数(Hartree 单位)
h2_coefficients = {
    "": -1.0523792,       # 常数(单位)项
    "Z0": -0.3979374,     # 量子比特 0 上的单量子比特 Z
    "Z1": -0.3979374,     # 量子比特 1 上的单量子比特 Z
    "Z0 Z1": -0.0112801,  # ZZ 相互作用
    "X0 X1": 0.1809313    # XX 相互作用
}

# 注意:单位项作为标量偏移添加
h2_hamiltonian = PauliOperator({
    "Z0": -0.3979374,
    "Z1": -0.3979374,
    "Z0 Z1": -0.0112801,
    "X0 X1": 0.1809313
})

# 添加常数(单位)项
h2_hamiltonian += -1.0523792

print("H2 哈密顿量:")
print(h2_hamiltonian)

第 2 步:构建拟设线路

我们使用带单个参数的硬件高效拟设:

python
from pyqpanda3 import core
import numpy as np

def build_ansatz(theta):
    """为 H2 构建参数化拟设线路。

    拟设制备:
    |psi(theta)> = RY(theta)_0 |01>

    这创建了一个探索与 H2 哈密顿量相关的 X0X1 子空间的状态。
    """
    prog = core.QProg()
    # 制备参考态
    prog << core.X(1)
    # 应用纠缠和旋转门
    prog << core.RY(0, theta)
    prog << core.CNOT(0, 1)
    prog << core.BARRIER([0, 1])
    return prog

第 3 步:定义目标函数

python
def objective(theta):
    """计算给定参数 theta 下的 <H2>。"""
    prog = build_ansatz(theta)
    expectation = core.expval_pauli_operator(prog, h2_hamiltonian)
    return expectation

第 4 步:优化

使用简单的网格搜索进行说明(实际中应使用 scipy.optimize.minimize):

python
# 在 theta 上进行网格搜索
thetas = np.linspace(0, 2 * np.pi, 100)
energies = [objective(t) for t in thetas]

# 寻找最小值
min_idx = np.argmin(energies)
optimal_theta = thetas[min_idx]
min_energy = energies[min_idx]

print(f"最优 theta: {optimal_theta:.4f}")
print(f"最小能量: {min_energy:.6f} Hartree")
print(f"精确基态能量: -1.137274 Hartree")
print(f"误差: {abs(min_energy - (-1.137274)):.6f} Hartree")

第 5 步:使用 scipy.optimize

更稳健的优化方式:

python
from scipy.optimize import minimize

result = minimize(
    objective,
    x0=[0.0],           # 初始猜测
    method='COBYLA',     # 无梯度优化器
    options={'maxiter': 200}
)

print(f"优化结果:")
print(f"  Theta: {result.x[0]:.6f}")
print(f"  能量: {result.fun:.6f} Hartree")
print(f"  是否收敛: {result.success}")

完整脚本

python
"""
使用 pyqpanda3 的 H2 分子 VQE
估算 H2 哈密顿量的基态能量。
"""
from pyqpanda3 import core
from pyqpanda3.hamiltonian import PauliOperator
import numpy as np
from scipy.optimize import minimize

# --- 定义 H2 哈密顿量 ---
h2 = PauliOperator({
    "Z0": -0.3979374,
    "Z1": -0.3979374,
    "Z0 Z1": -0.0112801,
    "X0 X1": 0.1809313
})
h2 += -1.0523792  # 单位偏移

# --- 拟设 ---
def build_ansatz(theta):
    prog = core.QProg()
    prog << core.X(1)
    prog << core.RY(0, theta)
    prog << core.CNOT(0, 1)
    prog << core.BARRIER([0, 1])
    return prog

# --- 目标函数 ---
def objective(params):
    theta = params[0]
    prog = build_ansatz(theta)
    return core.expval_pauli_operator(prog, h2)

# --- 优化 ---
result = minimize(objective, x0=[0.0], method='COBYLA')
print(f"基态能量估计: {result.fun:.6f} Hartree")
print(f"最优参数: {result.x[0]:.6f}")

输出应接近 1.137 Hartree,即 H2 分子在平衡位置的精确基态能量。


8. 总结

本教程涵盖了在 pyqpanda3 中使用哈密顿量和 Pauli 算子的核心组件:

组件描述
PauliOperator表示多量子比特 Pauli 项的线性组合
HamiltonianPauliOperator 的封装,用于物理哈密顿量
PauliTermPauli 分解中的单个项
PauliWithQbit作用于特定量子比特的 Pauli 算子
expval_pauli_operator()计算 PauliOperator 的 ψ|P|ψ
expval_hamiltonian()计算 Hamiltonian 的 ψ|H|ψ

关键要点

  1. 构造灵活性PauliOperatorHamiltonian 可以从字符串、字典、列表、元组或 numpy 矩阵构造。
  2. 代数运算:标准 Python 运算符(+-*@)和 .tensor() 方法支持富有表现力的算子代数。
  3. 期望值:使用 expval_pauli_operator()expval_hamiltonian()QProg 一起计算期望值,可选择包含噪声模型和多次测量。
  4. VQE 工作流程:将哈密顿量定义为 Pauli 分解,构建参数化拟设线路,计算期望值,然后进行经典优化。

下一步

  • 变分线路——了解 VQCircuit 用于自动梯度计算。
  • 量子信息——探索态矢量、密度矩阵和距离度量。
  • 噪声模拟——为硬件感知模拟构建真实噪声模型。

Released under the MIT License.