线性代数算法
概述
unitarylab_algorithms.linear_algebra 包提供了用于线性代数任务的量子算法,包括量子傅里叶变换、线性方程组求解、非酉算符实现、信号处理和变分方法。
| 算法 | 类 | 任务 |
|---|---|---|
| QFT | QFTAlgorithm | 量子傅里叶变换 |
| HHL | HHLAlgorithm | 求解线性方程组 (相位估计路线) |
| LCU | LCUAlgorithm | 实现 |
| QSP | QSPAlgorithm | 基于 QSP 的 多项式变换 |
| QSVT-QLSA | QSVTLinearSolverAlgorithm | 基于 QSVT 的线性求解器 |
| VQLS | VQLSAlgorithm | 变分量子线性求解器(NISQ) |
| AQC | AQCAlgorithm | 离散绝热量子线性求解器(QLSP) |
返回与错误处理
算法正常完成时返回 status、circuit_path、plot、circuit 以及算法专属结果。矩阵维度、厄米性或后选择等条件不满足时会抛出 ValueError 或 RuntimeError,调用方可按需要捕获异常。数值质量应结合误差、残差、保真度或优化器结果判断。
量子傅里叶变换(QFT)
背景
量子傅里叶变换是离散傅里叶变换的量子类比,将计算基态 映射为:
QFT 是 Shor 算法、QPE、HHL 及许多其他算法的子程序。本模块同时支持逆 QFT(inverse=True)。
导入
from unitarylab_algorithms import QFTAlgorithm.run() 参数
def run(self, n: int, state: np.ndarray = None, inverse: bool = False,
backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
n | int | — (必填) | 量子比特数 |
state | np.ndarray | None | None | 初始态向量(省略则使用 ` |
inverse | bool | False | 是否执行逆 QFT |
返回值
真实的 output 字段(合并进最终返回字典):
{
"status": "ok",
"circuit_path": "....svg", # save_circuit(qc.decompose()),即完全分解后的线路图
"plot": [{"format": "txt", "filename": "quantum_fourier_transform_algorithm_result.txt"}], # 来自 save_txt(),是结果文本文件而非线路图
"circuit": <Circuit>,
"Final state": ..., # 模拟得到的末态向量
"Expected state": ..., # 用 numpy 的 fft/ifft 计算的理论期望态
"Verification error": ..., # 两者的 L2 范数误差(仅用于日志/参考,不影响 status)
"Computation time (s)": ...
}示例
import numpy as np
from unitarylab_algorithms import QFTAlgorithm
algo = QFTAlgorithm()
result = algo.run(n=4)
print(result['status']) # 'ok'
# 逆 QFT
result_inv = algo.run(n=4, inverse=True)快速演示
from unitarylab_algorithms.linear_algebra.qft.algorithm import test
test(n=4)注意事项
status字段恒为'ok',验证误差Verification error只是与经典numpy.fft/numpy.ifft计算结果的对比,不会导致status变化。- 保存的线路图使用
qc.decompose()之后的电路(所有子门都会展开显示),而返回字典中的circuit字段则是未分解的原始电路对象,二者结构不同。
HHL 线性方程组求解算法
背景
Harrow–Hassidim–Lloyd(HHL)算法求解线性方程组 ,时间复杂度为 ,其中 是 的条件数, 是矩阵维数。经典最优算法为 。
算法利用 QPE 将 的本征值编码到相位寄存器,然后通过受控旋转计算每个本征值的倒数 ,最后反计算相位寄存器,并对辅助比特和相位寄存器进行后选择以提取解向量。
要求:
- 必须是厄米方阵,维数必须是 2 的幂次
- 不能为全零向量
- 的所有本征值不能同时约等于零
导入
from unitarylab_algorithms import HHLAlgorithm.run() 参数
def run(self, A: np.ndarray, b: np.ndarray, d: int,
backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
A | np.ndarray | — (必填) | 厄米系数矩阵,维数必须为 |
b | np.ndarray | — (必填) | 右侧向量 |
d | int | — (必填) | 相位寄存器量子比特数(精度 );Web 界面建议范围 [7, 15] |
演化时间 、相位网格起点 k_start、是否启用”带符号相位模式”(当 含负本征值时自动开启)等均由算法根据 的本征谱自动确定,不作为用户可传入的参数。
返回值
{
"status": "ok",
"circuit_path": "....svg",
"plot": [...],
"circuit": <Circuit>,
"Estimated solution (quantum)": ..., # 量子后选择得到的解向量
"Exact solution (classical)": ..., # np.linalg.solve(A, b) 的经典解
"L2 error": ..., # 两者 L2 范数差
"Post-selection probability": ..., # 后选择成功概率 P(anc=1, phase=|0>)
"Computation time (s)": ...
}示例
import numpy as np
from unitarylab_algorithms import HHLAlgorithm
A = np.array([[0.8, 0], [0, 0.4]])
b = np.array([1, 2])
algo = HHLAlgorithm()
result = algo.run(A=A, b=b, d=11)
print(result['status'])快速演示
from unitarylab_algorithms.linear_algebra.hhl.algorithm import test
test(A=[[0.8, 0], [0, 0.4]], b=[1, 2], d=11)注意事项
- 较大的
d可获得更高精度,但会显著增加线路深度;d过小时算法会直接抛出ValueError(“Phase bits d=… insufficient to resolve minimum phase” 等),而不是返回失败状态。 - 若后选择成功概率为零(即
ancilla=1且相位寄存器为|0...0>的分支从未出现),会抛出ValueError("Post-selection probability is zero...")。 - 强烈建议使用条件数较小(条件良好)的矩阵进行实验。
线性酉组合(LCU)算法
背景
LCU 通过将系数 编码到辅助”制备”寄存器(比特数 , 为项数),并对该寄存器进行条件应用酉算符 ,来实现非酉算符 。LCU 是哈密顿量模拟、QSVT 和块编码的核心原语。
导入
from unitarylab_algorithms import LCUAlgorithm.run() 参数
def run(self, alphas: List[float], unitaries: List[Circuit], n_sys: int,
initial_state: Circuit = None,
backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
alphas | List[float] | — (必填) | 非负系数列表 ,长度须与 unitaries 一致 |
unitaries | List[Circuit] | — (必填) | 酉算符线路列表 |
n_sys | int | — (必填) | 系统寄存器量子比特数 |
initial_state | Circuit | None | None | 制备系统初始态的线路(可选,量子比特数须等于 n_sys,否则抛出 ValueError) |
返回值
{
"status": "ok",
"circuit_path": "....svg",
"plot": [...],
"circuit": <Circuit>,
"Success probability": ..., # 全部辅助比特测得 |0...0> 的概率
"Computation time (s)": ...,
"Result state": ... # 辅助比特为 |0...0> 分支下的系统寄存器(未归一化)态切片
}示例
from unitarylab_algorithms import LCUAlgorithm
# 构造酉线路(如 Pauli 算符),然后与系数一起传入
algo = LCUAlgorithm()
result = algo.run(alphas=[0.6, 0.4], unitaries=[U_I, U_X], n_sys=1)
print(result['status'])快速演示
from unitarylab_algorithms.linear_algebra.lcu.algorithm import test
test(n=1, alphas=[0.6, 0.4], paulis=['I', 'X'])test() 会根据 paulis(Pauli 字符串列表,如 'IX'、'ZZ')自动构造对应的酉线路:系数为负时会取其绝对值并附加一个全局相位门 U.gp(np.angle(-1))(代表符号翻转)以正确表示该项,而非跳过;只有系数恰为 0 的项才会被直接丢弃且不计入线路。paulis 参数还支持传入用英文逗号 ,、中文逗号 ,、英文分号 ; 或中文分号 ; 分隔的字符串(format_pauli_list 会自动转换为列表);当前实现不支持中文顿号 、。
注意事项
is_success = success_prob > 1e-6是源码内部真实计算的成功判据,仅用于日志打印(“Valid” / “Very low success rate…”),不会反映到返回字典的status字段中。- 辅助寄存器比特数由
n_anc = ceil(log2(m))自动确定(m为alphas长度),无需用户指定。
量子信号处理(QSP,线性代数版本)
背景
linear_algebra.qsp.QSPAlgorithm 通过经典优化(scipy.optimize.minimize,L-BFGS-B)搜索一组相位序列 ,用单比特线路(交替施加信号旋转 与相位旋转 )实现对给定本征值 的 多项式逼近,是 QSVT 及其它高级算法的子程序。
命名易混淆提示:本模块与
hamiltonian_simulation.qsp.QSPHSAlgorithm是两个完全不同的类,源码目录都叫qsp/但用途不同:本模块(linear_algebra.qsp.QSPAlgorithm)只在单比特上对标量本征值 做 逼近,用于演示/验证 QSP 相位查找本身;hamiltonian_simulation.qsp.QSPHSAlgorithm则是对任意厄米矩阵 做真正的时间演化 模拟。导入时请务必确认路径。
导入
from unitarylab_algorithms import QSPAlgorithm.run() 参数
def run(self, t: float, d: int, x: float = 0.5,
backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
t | float | — (必填) | 目标演化参数;Web 界面建议范围 [0.1, 10.0] |
d | int | — (必填) | 多项式(相位)阶数;Web 界面建议范围 [5, 50] |
x | float | 0.5 | 测试本征值,须落在 [-1, 1] |
返回值
{
"status": "ok",
"circuit_path": "....svg",
"plot": [...],
"circuit": <Circuit>,
"Estimated value": ..., # 电路模拟得到的复数振幅
"Ideal value": ..., # np.cos(t * x) 理论值
"Absolute error": ...,
"Computation time (s)": ...
}示例
from unitarylab_algorithms import QSPAlgorithm
algo = QSPAlgorithm()
result = algo.run(t=1.0, d=10, x=0.5)
print(result['status'])快速演示
from unitarylab_algorithms.linear_algebra.qsp.algorithm import test
test(t=1.0, d=10, x=0.5)注意事项
- 相位序列搜索的初始猜测为
np.random.randn(d+1) * 0.1,未设置随机种子,因此同样的(t, d, x)多次调用可能收敛到不同的相位解、得到不同的Absolute error(结果不完全可复现),这与哈密顿量模拟包中 qDrift 的不可复现问题属于同一类原因。 - L-BFGS-B 是局部优化,没有多起点重试机制;当
d较小或t较大时可能收敛到较差的局部最优,导致Absolute error偏大,但status依旧恒为'ok'。
基于 QSVT 的线性方程组求解算法
背景
量子奇异值变换(QSVT)通过块编码将 QSP 推广到任意矩阵,从而对奇异值进行多项式变换。QSVT 线性求解器利用这一框架对 的奇异值实现矩阵逆函数 ,以逼近最优查询复杂度求解 。
导入
from unitarylab_algorithms import QSVTLinearSolverAlgorithm.run() 参数
def run(self, A, b, epsilon,
backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
A | np.ndarray | — (必填) | 系数矩阵 |
b | np.ndarray | — (必填) | 右侧向量 |
epsilon | float | — (必填) | 目标近似精度;Web 界面建议范围 [1e-10, 1.0] |
返回值
{
"status": "ok",
"circuit_path": "....svg",
"plot": [...],
"circuit": <Circuit>,
"Solution vector": ..., # 解向量
"Scaling factor applied": ..., # QSVTSolver 内部应用的缩放系数
"Simulation time (s)": ...
}示例
import numpy as np
from unitarylab_algorithms import QSVTLinearSolverAlgorithm
A = np.array([[0.8, 0.1], [0.1, 0.6]])
b = np.array([1.0, 0.5])
algo = QSVTLinearSolverAlgorithm()
result = algo.run(A=A, b=b, epsilon=1e-3)
print(result['status'])快速演示
from unitarylab_algorithms.linear_algebra.qsvt_qlsa.algorithm import test
test(A=[[0.8, 0], [0, 0.4]], b=[1., 2.], epsilon=0.01)注意事项
- 本算法的核心逻辑(矩阵合法性检查、块编码、QSVT 相位角求解)完全委托给库内部的
unitarylab.library.linear_solver.QSVTSolver,QSVTLinearSolverAlgorithm.run()本身只是一个薄封装,不在 Python 层做任何 A/b 的显式校验(例如是否厄米、维度是否匹配等),任何校验失败都表现为QSVTSolver内部抛出的异常。 - 模块级
test()函数没有独立的文档字符串。
变分量子线性求解器(VQLS)
背景
VQLS 是一种适用于近期量子设备(NISQ)的变分算法,用于求解线性方程组 :用硬件高效拟设(RY-RZ 旋转 + 环形 CNOT 纠缠层)参数化解态 ,通过最小化基于残差的代价函数来迭代优化参数。系数矩阵内部通过 unitarylab.library.pauli_operator.pauli_string_decomposition 自动做 Pauli 分解(),无需用户手动提供分解。
导入
from unitarylab_algorithms import VQLSAlgorithm.run() 参数
def run(self, A: np.ndarray, b: np.ndarray, cost_function: str = "local_ht",
n_layers: int = 4, maxiter: int = 500, tol: float = 1e-6,
seed: int = 42, epsilon: Optional[float] = None,
backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
A | np.ndarray | — (必填) | 系数矩阵 |
b | np.ndarray | — (必填) | 维右侧向量 |
cost_function | str | "local_ht" | "local_ht"(Hadamard-test 线路,最慢但最贴近真实硬件路径)/"local_classical"(经典矩阵运算,快)/"global"($C_G = 1- |
n_layers | int | 4 | 拟设层数(每层 RY+RZ+环形 CNOT) |
maxiter | int | 500 | COBYLA 最大迭代次数 |
tol | float | 1e-6 | COBYLA 收敛容差 |
seed | int | 42 | 初始参数随机种子 |
epsilon | float | None | None | 目标解误差阈值;设置后当 时提前停止(仅对 local_ht/local_classical 生效,global 模式忽略) |
返回值
{
"status": "ok",
"circuit_path": "....svg",
"plot": [...],
"circuit": <Circuit>,
"Fidelity": ..., # 量子解与经典解的保真度;A 奇异时为 None
"Ax Fidelity": ..., # A|x_quantum> 归一化后与 |b> 的保真度
"Cost Function": "local_ht" | "local_classical" | "global",
"Condition Number": ..., # np.linalg.cond(A)
"Solution State (Quantum)": ...,
"Solution State (Classical)": ..., # 可能为 None(A 奇异时)
"Computation Time (s)": ...,
"Cost History": [...], # 每次代价函数求值的历史记录
"Early Stopped": True | False
}示例
import numpy as np
from unitarylab_algorithms import VQLSAlgorithm
A = np.array([[1.5, 0.2], [0.2, 1.8]])
b = np.array([1.0, 0.5])
algo = VQLSAlgorithm()
result = algo.run(A=A, b=b, cost_function="local_ht", n_layers=4, maxiter=500)
print(result['status']) # 恒为 'ok'快速演示
from unitarylab_algorithms.linear_algebra.vqls.algorithm import test
test(cost_function="local_ht", n_layers=4, maxiter=500, tol=1e-6, seed=42)
# A、b 缺省时分别取 [[1.5, 0.2], [0.2, 1.8]] 与 [1.0, 0.5]注意事项
- 优化器收敛情况会写入保存的结果文本;API 调用方还可结合
Fidelity、Cost History和Early Stopped判断求解质量。 - Web 界面参数与 Python 参数名不一致:
parameters.json中暴露的 UI 参数名为max_iterations、tolerance,但 Python 端.run()的实际关键字参数分别是maxiter、tol。 - Web 界面缺少
A/b/seed/epsilon参数:与 HHL、QSVT-QLSA 不同,VQLS 的parameters.json只暴露了cost_function、n_layers、max_iterations、tolerance四项,并未提供矩阵A、向量b、随机种子seed或早停阈值epsilon的输入项,意味着当前 Web 界面上运行 VQLS 时使用的是代码内置的默认 2x2 示例问题,用户无法通过界面自定义待求解的线性系统。 n_layers的parameters.json默认值为2,与 Python.run()/test()自身默认值4不一致。A为奇异矩阵(np.linalg.solve抛出LinAlgError)时,Fidelity与Solution State (Classical)均返回None,而不是报错,算法仍会继续输出量子侧结果。- 早停机制存在已知限制:源码注释明确指出 COBYLA 由 Fortran 实现,Python 异常无法从代价函数回调中真正中断其内部循环,因此
_cost_with_stop中设置_early_stop_flag后并不能让 COBYLA 立即退出,只是提前记录标志位供后续判断,实际优化仍可能继续运行到maxiter(该行为在源码中以注释形式承认为已知设计限制)。
离散绝热量子线性求解器(AQC)
背景
AQCAlgorithm 实现离散绝热量子线性系统求解(QLSP):通过 Trotter 化的离散绝热演化,在 个系统量子比特与 5 个辅助量子比特上求解 。算法对系数矩阵 做 SVD 块编码( 归一化后嵌入 酉矩阵),用 Householder 反射构造制备 的酉算符 ,再按绝热调度参数 逐步演化 步,最终对辅助寄存器做后选择提取解向量。
本算法不接受用户自定义的 、:与本包其它求解器(HHL、QSVT-QLSA、VQLS)不同,
AQCAlgorithm.run()完全不暴露A/b参数——运行时会先执行np.random.seed(42),然后自动生成一个良态厄米矩阵A = randn(N,N)对称化后加10·I(保证对角占优、条件数较小),以及随机右侧向量b = randn(N)。由于种子固定,同一个n下每次运行生成的A、b完全相同(可复现),但用户无法用它求解自己指定的线性系统,仅能用于演示/基准测试离散绝热求解流程本身。
导入
from unitarylab_algorithms import AQCAlgorithm.run() 参数
def run(self, n: int = 2, T: int = 0, p: float = 1.4,
backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
n | int | 2 | 系统量子比特数(建议 1–6),矩阵维数 ;总量子比特数为 (另加 5 个固定辅助比特) |
T | int | 0 | 绝热演化步数;0 表示自动选择,取 (并向上取偶数), 为(内部生成的) 的条件数 |
p | float | 1.4 | 绝热调度参数,须 > 1;Web 界面建议范围 [1.01, 5.0] |
返回值
一般情形():
{
"status": "ok",
"circuit_path": ["....svg", "....svg"], # [完整线路图, 单步切片线路图](与 Trotter 算法同构)
"plot": [...],
"circuit": <Circuit>,
"Quantum Solution (x)": ...,
"Classical Solution": ..., # np.linalg.solve(A, b) 经典解
"Residual Norm ||Ax-b||": ...,
"Error vs Classical (L2)": ...,
"Internal Scale Factor": ...,
"Post-selection Amplitude": ...,
"Simulation Time (s)": ...,
"Elapsed Time (s)": ...
}当内部生成的 恰好条件数 (即近似为单位矩阵的标量倍数)时,算法会走平凡快速路径:直接令 x = b(按比例还原),跳过量子线路演化;此时返回字典结构略有不同——缺少 Post-selection Amplitude 与 Simulation Time (s) 两项,且 circuit_path 是单个字符串而非长度为 2 的列表(因为只保存了未经绝热演化步骤的初始化线路)。
示例
from unitarylab_algorithms import AQCAlgorithm
algo = AQCAlgorithm()
result = algo.run(n=2, T=0, p=1.4) # T=0 → 自动根据条件数选择步数
print(result['status'])快速演示
from unitarylab_algorithms.linear_algebra.aqc.algorithm import test
test(n=2, T=0, p=1.4)注意事项
- 后选择投影到辅助寄存器的
|10000>分支(4 个比特为0,1 个比特为1);若该分支振幅趋于零,会抛出RuntimeError("Post-selection returned a near-zero state..."),提示增大T或说明系统病态。 T未指定(即T=0)时自动取 并保证为偶数;显式传入的T若为奇数则不会被自动调整。- 线路规模会随
T线性增长(每步 11 个子操作);完整线路较深时可查看单步切片图aqc_one_step.svg了解单步结构。 - 保存线路图期间源码会临时重定向
sys.stdout到内存缓冲区(用于抑制绘图过程中的噪声输出),执行完毕后恢复,属正常实现细节。
版本引用
如需一次性导入本模块的多个算法类,可直接从顶层包批量导入:
from unitarylab_algorithms import (
HHLAlgorithm, LCUAlgorithm, QFTAlgorithm, QSPAlgorithm,
QSVTLinearSolverAlgorithm, VQLSAlgorithm, AQCAlgorithm,
)