4. QuTiP基础对象与操作

在QuTiP中,几乎所有量子力学计算都围绕一个核心对象展开——Qobj(Quantum Object,量子对象)。理解Qobj的结构与操作方式,是后续构建哈密顿量、求解主方程、计算期望值的前提。本节从Qobj的创建入手,逐步展开量子态与算符的表示方法,以及加减乘、张量积、迹、本征值等基本运算和常用函数的使用。

一、Qobj的创建与核心属性

Qobj本质上是对一个矩阵(或向量)的封装,附带维度信息和类型标记。创建Qobj最直接的方式是传入一个NumPy数组:

import numpy as np
import qutip as qt

# 用NumPy数组创建Qobj
H = qt.Qobj(np.array([[1, 0], [0, -1]]))
print(H)
# Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True

输出中几个关键属性值得关注:dims表示子系统的维度结构,shape是矩阵形状,type标识对象类型(算符oper、态矢ket、左矢bra、超算符super等),isherm指示是否为厄米算符。这些属性不是装饰性的,它们直接影响后续运算的合法性判断和求解器的选择。

对于复合系统,dims会体现张量结构。例如两个二能级系统组成的四维空间,dims = [[2, 2], [2, 2]],第一个列表描述行空间的子系统维度,第二个描述列空间。当维度信息与实际矩阵形状不匹配时,QuTiP会报错,这是初学者常见的错误来源之一。

除了从数组创建,QuTiP提供了便捷函数:qt.basis(N, i)生成N维希尔伯特空间中第i个基矢;qt.fock(N, n)等价于粒子数基矢;qt.destroy(N)和qt.create(N)分别生成湮灭与产生算符;qt.sigmax()、qt.sigmaz()等生成泡利矩阵;qt.qeye(N)生成单位算符。这些函数返回的都是标准Qobj,可以直接参与运算。

二、量子态与算符的表示

量子态在QuTiP中用ket表示,即列向量。例如qt.basis(2, 0)对应|0⟩,qt.basis(2, 1)对应|1⟩。叠加态可以通过线性组合构造:

psi = (qt.basis(2, 0) + qt.basis(2, 1)).unit()
# 归一化后的 (|0> + |1>)/sqrt(2)

.unit()方法执行归一化,返回新的Qobj而不修改原对象。对应的左矢用.dag()获得,即psi.dag()得到bra。密度矩阵则通过psi * psi.dag()或qt.ket2dm(psi)构造,类型变为oper。

算符方面,厄米算符(可观测量)的isherm为True。非厄米算符如湮灭算符a,其isherm为False。判断一个Qobj是否为厄米,除了看属性,也可用H.isherm直接读取。对于混合态,密度矩阵的迹应为1,可用rho.tr()验证;纯态的纯度(rho * rho).tr()应等于1。

三、基本运算:加减乘、张量积、迹与本征值

Qobj之间的加减乘遵循矩阵运算规则,但QuTiP会检查维度兼容性。两个Qobj相加要求dims一致;相乘要求左对象的列空间维度与右对象的行空间维度匹配。标量与Qobj相乘直接使用*,例如2 * qt.sigmax()。

张量积用qt.tensor()或&运算符实现。例如两比特系统:

sx1 = qt.tensor(qt.sigmax(), qt.qeye(2))  # 第一个比特上的X
sx2 = qt.tensor(qt.qeye(2), qt.sigmax())  # 第二个比特上的X
# 等价写法:qt.sigmax() & qt.qeye(2)

张量积结果的dims会自动合并为[[2, 2], [2, 2]]。注意tensor的顺序与子系统顺序严格对应,交换顺序会得到不同的矩阵表示,虽然物理上描述的是同一组算符作用在不同子系统上。

迹用.tr()方法,返回复数标量。本征值用.eigenenergies()获取(仅返回本征值,按升序排列),或用.eigenstates()同时返回本征值和本征矢。对于厄米算符,本征值为实数;对于非厄米算符,返回复本征值。例如:

evals, evecs = qt.sigmaz().eigenstates()
# evals = [-1., 1.],evecs为对应的本征态列表

此外,.expm()计算矩阵指数,.sqrtm()计算矩阵平方根,.norm()计算范数,.ptrace(i)对第i个子系统求偏迹。偏迹在分析复合系统约化密度矩阵时非常常用,例如rho.ptrace(0)得到第一个子系统的约化态。

四、常用函数与操作要点

QuTiP还提供了一批便捷函数:qt.expect(op, state)计算期望值;qt.commutator(A, B)计算对易子AB−BA;qt.anticommutator(A, B)计算反对易子;qt.ket2dm(ket)将态矢转为密度矩阵;qt.tensor的别名&在链式构造多体算符时更简洁。需要强调的是,expect的第一个参数必须是算符,第二个参数可以是ket或密度矩阵,返回值是复数。

创建Qobj时若手动指定dims,务必保证其乘积与矩阵形状一致。例如qt.Qobj(np.eye(4), dims=[[2,2],[2,2]])是合法的,而dims=[[2],[2]]会因形状不匹配报错。建议优先使用tensor自动生成维度信息,减少手动出错。
Qobj 创建路径与运算关系总览 NumPy 数组 qt.basis / qt.fock qt.destroy / qt.create qt.sigmax / qt.qeye Qobj dims · shape · type · isherm 加减乘 (+ − *) 张量积 tensor / & 迹 .tr() 本征值 .eigenenergies() 偏迹 .ptrace(i) 期望值 qt.expect 类型分支 ket / bra / oper / super .dag() 转置共轭 · ket2dm 转密度矩阵 维度一致性检查: 相加要求 dims 相同;相乘要求左列空间维度 = 右行空间维度;tensor 自动合并 dims;手动指定 dims 时乘积须等于矩阵形状。

上图把Qobj的创建来源、核心属性、类型分支和常用运算放在同一张关系图中。可以看到,无论从数组还是从内置函数出发,最终都汇聚为带有dims、shape、type、isherm四个关键属性的Qobj;而所有运算都建立在这些属性的兼容性检查之上。实际编码时,建议养成先打印Qobj、确认dims和type再继续运算的习惯,这能避免大量因维度错位导致的隐蔽错误。

最后给出一个综合示例,把创建、张量积、本征值和期望值串起来:

# 两比特海森堡XX模型的一个简单项
sx1 = qt.sigmax() & qt.qeye(2)
sx2 = qt.qeye(2) & qt.sigmax()
H = 0.5 * (sx1 * sx2 + sx1 * sx2)  # 示例系数,非实测
evals = H.eigenenergies()
psi0 = qt.tensor(qt.basis(2,0), qt.basis(2,1))
print(qt.expect(H, psi0))  # 输出该态下的能量期望值

这段代码中,sx1 * sx2是两个算符的矩阵乘积,&完成张量积,eigenenergies()返回按升序排列的本征值,expect计算期望值。示例中的系数0.5仅为演示,实际物理模型需根据耦合强度设定。掌握这些基础操作后,就可以进入哈密顿量构建与时间演化求解的环节。