Skip to Content

线性代数算法

概述

unitarylab_algorithms.linear_algebra 包提供了用于线性代数任务的量子算法,包括量子傅里叶变换、线性方程组求解、非酉算符实现、信号处理和变分方法。

算法任务
QFTQFTAlgorithm量子傅里叶变换
HHLHHLAlgorithm求解线性方程组 (相位估计路线)
LCULCUAlgorithm实现
QSPQSPAlgorithm基于 QSP 的 多项式变换
QSVT-QLSAQSVTLinearSolverAlgorithm基于 QSVT 的线性求解器
VQLSVQLSAlgorithm变分量子线性求解器(NISQ)
AQCAQCAlgorithm离散绝热量子线性求解器(QLSP)

返回与错误处理

算法正常完成时返回 statuscircuit_pathplotcircuit 以及算法专属结果。矩阵维度、厄米性或后选择等条件不满足时会抛出 ValueErrorRuntimeError,调用方可按需要捕获异常。数值质量应结合误差、残差、保真度或优化器结果判断。


量子傅里叶变换(QFT)

背景

量子傅里叶变换是离散傅里叶变换的量子类比,将计算基态 映射为:

QFT 是 Shor 算法、QPE、HHL 及许多其他算法的子程序。本模块同时支持逆 QFTinverse=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]
参数类型默认值说明
nint— (必填)量子比特数
statenp.ndarray | NoneNone初始态向量(省略则使用 `
inverseboolFalse是否执行逆 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]
参数类型默认值说明
Anp.ndarray— (必填)厄米系数矩阵,维数必须为
bnp.ndarray— (必填)右侧向量
dint— (必填)相位寄存器量子比特数(精度 );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]
参数类型默认值说明
alphasList[float]— (必填)非负系数列表 ,长度须与 unitaries 一致
unitariesList[Circuit]— (必填)酉算符线路列表
n_sysint— (必填)系统寄存器量子比特数
initial_stateCircuit | NoneNone制备系统初始态的线路(可选,量子比特数须等于 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)) 自动确定(malphas 长度),无需用户指定。

量子信号处理(QSP,线性代数版本)

背景

linear_algebra.qsp.QSPAlgorithm 通过经典优化(scipy.optimize.minimizeL-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]
参数类型默认值说明
tfloat— (必填)目标演化参数;Web 界面建议范围 [0.1, 10.0]
dint— (必填)多项式(相位)阶数;Web 界面建议范围 [5, 50]
xfloat0.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]
参数类型默认值说明
Anp.ndarray— (必填)系数矩阵
bnp.ndarray— (必填)右侧向量
epsilonfloat— (必填)目标近似精度;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.QSVTSolverQSVTLinearSolverAlgorithm.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]
参数类型默认值说明
Anp.ndarray— (必填) 系数矩阵
bnp.ndarray— (必填) 维右侧向量
cost_functionstr"local_ht""local_ht"(Hadamard-test 线路,最慢但最贴近真实硬件路径)/"local_classical"(经典矩阵运算,快)/"global"($C_G = 1-
n_layersint4拟设层数(每层 RY+RZ+环形 CNOT)
maxiterint500COBYLA 最大迭代次数
tolfloat1e-6COBYLA 收敛容差
seedint42初始参数随机种子
epsilonfloat | NoneNone目标解误差阈值;设置后当 时提前停止(仅对 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 调用方还可结合 FidelityCost HistoryEarly Stopped 判断求解质量。
  • Web 界面参数与 Python 参数名不一致parameters.json 中暴露的 UI 参数名为 max_iterationstolerance,但 Python 端 .run() 的实际关键字参数分别是 maxitertol
  • Web 界面缺少 A/b/seed/epsilon 参数:与 HHL、QSVT-QLSA 不同,VQLS 的 parameters.json 只暴露了 cost_functionn_layersmax_iterationstolerance 四项,并未提供矩阵 A、向量 b、随机种子 seed 或早停阈值 epsilon 的输入项,意味着当前 Web 界面上运行 VQLS 时使用的是代码内置的默认 2x2 示例问题,用户无法通过界面自定义待求解的线性系统。
  • n_layersparameters.json 默认值为 2,与 Python .run()/test() 自身默认值 4 不一致。
  • A 为奇异矩阵(np.linalg.solve 抛出 LinAlgError)时,FidelitySolution 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 下每次运行生成的 Ab 完全相同(可复现),但用户无法用它求解自己指定的线性系统,仅能用于演示/基准测试离散绝热求解流程本身。

导入

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]
参数类型默认值说明
nint2系统量子比特数(建议 1–6),矩阵维数 ;总量子比特数为 (另加 5 个固定辅助比特)
Tint0绝热演化步数;0 表示自动选择,取 (并向上取偶数), 为(内部生成的) 的条件数
pfloat1.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 AmplitudeSimulation 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, )
最后更新于