SciPy 1.3.2 维护版本全解析:Python 3.8 支持与 14 项关键 Bug 修复
2026/9/22 11:13:50 网站建设 项目流程

SciPy 1.3.2 维护版本全解析:Python 3.8 支持与 14 项关键 Bug 修复

【免费下载链接】scipySciPy library main repository项目地址: https://gitcode.com/gh_mirrors/sc/scipy

SciPy 1.3.2 是 1.3.x 系列的一个重要 bug-fix 与维护版本,其核心使命是为当时新发布的 Python 3.8 提供正式支持,并集中修复了信号处理、优化、稀疏矩阵、统计等多个子模块中报告的十余个缺陷。阅读本文后,你将全面了解该版本修复的每一个具体问题、对应的底层根因、以及这些修复在 SciPy 源码中的落点,能够据此评估升级收益、规避同类陷阱,并为排查相关问题提供直接线索。

本文内容以官方发布说明 doc/source/release/1.3.2-notes.rst 为主体骨架,结合当前仓库源码与测试用例进行深度印证与扩充。

一、版本定位:Bug-fix 与维护更新

根据官方发布说明,SciPy 1.3.2 的定位非常明确:

SciPy 1.3.2 is a bug-fix and maintenance release that adds support for Python 3.8.

即:这是一个纯缺陷修复与维护型版本,不带入任何新功能,唯一的"新能力"是对 Python 3.8 的正式支持。对于仍停留在 1.3.x 分支的存量用户而言,该版本相当于一个"安全补丁包 + 新 Python 版本适配包",升级风险极低,收益明确。

从维护内容看,该版本横跨了以下子模块与工程维度:

维度涉及模块 / 工程典型问题
数值计算正确性scipy.statsscipy.sparsescipy.linalg非中心 F 分布方差公式错误、Floyd-Warshall 丢失零权边、复数子空间角
求解器行为scipy.optimizeNaN 最小值仍报告 success、root_scalarlru_cache不兼容
输入类型兼容scipy.sparse.linalgscipy.sparseexpm拒绝np.matrix、CSR 矩阵花式索引赋值
构建与 CIpyproject.toml、Travis CI、SuperLUPython 3.8 适配、macOS 构建失败

二、scipy.signal:unique_roots 根分组修复

2.1 问题背景(Issue #4915)

scipy.signal.unique_roots是一个从根列表中确定"唯一根及其重数"的实用函数,在部分分式展开(residue/invres)等场景中承担着关键角色。Issue #4915 报告了该函数在特定根组合下的分组错误:当多个根相互靠近(距离小于容差tol)时,函数的输出与预期不符。

2.2 源码落点与修复方式(PR #10961)

修复后的实现位于 scipy/signal/_signaltools.py。其核心算法在修复后稳定采用"基于cKDTree的贪心分组"策略:

  1. 将复数根p拆分为实部与虚部,构造二维点集;
  2. 使用cKDTree构建空间索引;
  3. 对每个尚未使用的根,调用tree.query_ball_point(points[i], tol)找出其容差范围内的邻域根集合;
  4. rtype指定的归约规则(max/min/avg)合并该组根,并统计重数。

实现中有两点值得注意的设计细节:

  • 分组不具传递性:文档中明确说明,若ab接近、bc接近,不代表ac接近,因此分组结果依赖输入顺序,采用"按输入顺序贪心分组";
  • 复数比较规则:当rtypemax/min时,复数根先按实部比较、再按虚部比较。

unique_roots的完整签名及参数含义如下:

unique_roots(p, tol=1e-3, rtype='min')
参数默认值含义
p必填根列表(array_like)
tol1e-3判定两个根"相等"的距离容差
rtype'min'组内代表根的选取方式:'max'/'maximum'取最大、'min'/'minimum'取最小、'avg'/'mean'取平均

官方文档中的典型用法:

>>> from scipy import signal >>> vals = [0, 1.3, 1.31, 2.8, 1.25, 2.2, 10.3] >>> uniq, mult = signal.unique_roots(vals, tol=2e-2, rtype='avg') >>> uniq[mult > 1] array([1.305])

三、scipy.optimize:三个关键行为修复

3.1 NaN 最小值不再误报成功(Issue #5161,PR #10756)

Issue #5161 报告了一个隐蔽且危险的缺陷:当目标函数的最小值本身是 NaN 时,部分优化器仍然返回success=True,导致用户在完全无效的数值上继续下游计算。PR #10756 修复了该问题,核心改动是确保求解器在目标函数值为 NaN 时以success=False退出,避免对 NaN 结果做出"成功"的误判。

该修复直接关乎 scipy/optimize 下众多求解器的终止条件判断逻辑。在数值优化实践中,这一改动具有重要意义:它把"算法达到收敛条件"与"计算结果数值有效"两个维度区分开来,NaN 结果一律不得被视为优化成功。

3.2 root_scalar 与 functools.lru_cache 的兼容性(Issue #10846,PR #10891)

Issue #10846 报告:当用户向root_scalar传入一个被functools.lru_cache装饰的目标函数时,求解会失败。根因在于 C 层实现的标量求根器在每次调用f复用同一个args元组对象,而有状态的lru_cache装饰器会持有对该元组的引用,导致缓存键混乱。

修复落点位于 scipy/optimize/_zerosmodule.c。修复后,C 层代码在每次调用目标函数前都会重新构造一个全新的args元组(将当前迭代点x作为第一个参数、其余参数依次复制),源码注释明确写道:

Need to create a new 'args' tuple on each call in case 'f' is stateful and keeps references to it (e.g. functools.lru_cache)

这一改动对brentqbrenthridderbisecttoms748等所有 C 实现的标量求根器均生效。对应的回归测试位于 scipy/optimize/tests/test_zeros.py:

@lru_cache def f_lrucached(x): return x @pytest.mark.parametrize('method', bracket_methods) def test_lru_cached_individual(self, method): # check that https://github.com/scipy/scipy/issues/10846 is fixed a, b = -1, 1 root, r = method(f_lrucached, a, b, full_output=True) assert r.converged assert_allclose(root, 0)

实战启示:在使用lru_cache对目标函数做记忆化加速时,SciPy 的 C 层求根器从 1.3.2 起可以安全配合使用。

3.3 linprog revised simplex 文档测试修复(Issue #10124,PR #10498)

Issue #10124 指出linprog(method='revised simplex')的 doctest 存在缺陷——当用户以"disp": True方式开启显示输出时,修订单纯形法的行为与文档示例不一致。PR #10498(TST: optimize: fixed linprog "disp": True bug)修复了该问题,属于测试与文档一致性的修正,相关实现位于 scipy/optimize/_linprog.py 及其修订单纯形法模块 scipy/optimize/_linprog_simplex.py。

四、scipy.sparse 与稀疏线性代数:四项底层修复

4.1 expm 支持 np.matrix 输入(Issue #5546,PR #10906)

Issue #5546 报告:scipy.sparse.linalg.expm在接收np.matrix类型输入时抛出ValueError。修复(BUG: sparse/linalg: fix expm for np.matrix inputs)位于 scipy/sparse/linalg/_matfuncs.py。expm采用 Al-Mohy 与 Higham(2009)的 Scaling and Squaring 算法(算法 6.1,即 5.1 的简化版),此前对np.matrix的维度/类型校验过于严格。修复后该函数可正确接受np.matrix、密集数组与稀疏数组等多种 2D 输入:

from scipy.sparse import csc_array from scipy.sparse.linalg import expm A = csc_array([[1, 0, 0], [0, 2, 0], [0, 0, 3]]) Aexp = expm(A) # 返回 CSC 稀疏数组

4.2 CSR 矩阵花式索引赋值修复(Issue #10695,PR #10700)

Issue #10695 报告了csr_matrix在使用花式索引(fancy indexing)赋值时出现的错误。修复(BUG: sparse: Loosen checks on sparse fancy assignment)适当放宽了对稀疏数组赋值的检查逻辑,相关实现位于 scipy/sparse/_csr.py 与底层索引机制 scipy/sparse/_index.py。

4.3 Floyd-Warshall 支持零权边(Issue #10609,PR #10709)

Issue #10609 揭示了一个影响图算法正确性的缺陷:scipy.sparse.csgraph中基于 Floyd-Warshall 的最短路算法会把显式的零权边错误地当作"无边"处理并丢弃,导致最短路结果失真。

修复(BUG: Fix floyd_warshall to support zero-weight edges)位于 scipy/sparse/csgraph/_shortest_path.pyx。该模块中的shortest_pathfloyd_warshall是图论计算的底层支撑,零权边(如"免费通行"的路径)在建模中非常常见,此修复保证了权重为零的边与"无连接"(稀疏矩阵中的缺失项)被严格区分。

4.4 ARPACK 复数 Hermitian 求解修复(PR #10882)

PR #10882(BUG: sparse/arpack: fix incorrect code for complex hermitian...)修复了 ARPACK 特征值求解器在复数 Hermitian 问题上的不正确代码路径。这属于稀疏特征值计算 scipy/sparse/linalg/_eigen 相关实现中的底层修正,直接影响eigsh对复数 Hermitian 矩阵的求解正确性。

五、scipy.stats:非中心 F 分布方差公式修正

5.1 问题背景(Issue #10658,PR #10671)

Issue #10658 报告:非中心 F 分布(noncentral F distribution)的方差公式存在错误。作为参数估计、假设检验等统计推断的基础,方差公式错误会直接污染置信区间与检验统计量的计算。

修复(BUG: stats: Fix the formula for the variance of the noncentral F distribution)更新了 scipy/stats/_continuous_distns.py 中ncf_gen分布的方差计算实现。

5.2 回归测试佐证

当前仓库中保留了针对该修复的回归测试 scipy/stats/tests/test_distributions.py:

def test_ncf_variance(): # Regression test for gh-10658 (incorrect variance formula for ncf). # The correct value of ncf.var(2, 6, 4), 42.75, can be verified with, # for example, Wolfram Alpha with the expression # Variance[NoncentralFRatioDistribution[2, 6, 4]] # or with the implementation of the noncentral F distribution in the C++ # library Boost. v = stats.ncf.var(2, 6, 4) assert_allclose(v, 42.75, rtol=1e-14)

测试表明,修复后ncf.var(2, 6, 4)的精确期望值为42.75(与 Wolfram Alpha、Boost C++ 库实现交叉验证)。这是 1.3.2 中为数不多的"数值结果可精确断言"的修复,充分体现了数值正确性修复的严谨性。

5.3 文档拼写修正(Issue #10976,PR #10977)

PR #10977(DOC: Fix typo in sp.stats.wilcoxon docstring)修正了scipy.stats.wilcoxon文档字符串中的拼写错误。尽管是小修,但体现了该版本对 API 文档质量的维护。

六、scipy.linalg:subspace_angles 支持复数输入

PR #10833(BUG: Fix subspace_angles for complex values)修复了scipy.linalg.subspace_angles复数矩阵输入下的计算错误。该函数用于计算两个矩阵列空间之间的主夹角,实现在 scipy/linalg/_decomp_svd.py,基于 SVD 分解计算,返回形状为(min(N, K),)的降序夹角数组:

def subspace_angles(A, B): """ Compute the subspace angles between two matrices. ... angles : ndarray, shape (min(N, K),) The subspace angles between the column spaces of `A` and `B` in descending order. """

复数版本的修复对量子计算、信号子空间分析等依赖复数子空间度量的领域尤为关键。

七、Python 3.8 支持与构建维护

1.3.2 版本的另一条主线是 Python 3.8 适配,涉及从 CI 到构建配置的一揽子改动:

PR类型内容
#10536CI在 Travis 中增加3.8-dev构建
#10930MAINTPython 3.8 相关维护性更新
#10938MAINT在 pyproject.toml 中登记 Python 3.8
#10943BLD将 Cython 版本升级至0.29.13(首个官方支持 Python 3.8 的 Cython 版本线)
#10971CI在 CI 中改用 3.8 稳定版

同时修复了两个平台相关构建问题:

  • Issue #10902 / PR #10917:Travis 上的 macOS(osx)构建失败,通过 CI 配置修正解决;
  • Issue #10967:macOS 上SuperLU的构建失败(发生于 maintenance/1.3.x 分支),属于平台相关的底层库编译问题。

此外 PR #11025 对 scipy/signal/_peak_finding.py 进行了更新,完善了峰值查找相关代码。

八、完整修复清单:Issues 与 Pull Requests

8.1 本版本关闭的 Issues

Issue主题
#4915scipy.signal.unique_roots的根分组 Bug
#5161优化器在最小值为 NaN 时错误报告成功
#5546scipy.sparse.linalg.expm收到np.matrix输入时抛出ValueError
#10124linprog(method='revised simplex')doctest Bug
#10609Floyd-Warshall 最短路会丢弃显式零权边
#10658非中心 F 分布方差公式错误
#10695csr_matrix花式索引赋值问题
#10846root_scalar处理functools.lru_cache装饰函数时失败
#10902Travis osx 构建失败
#10967macOS 上 SuperLU 构建失败(maintenance/1.3.x)
#10976sp.stats.wilcoxon文档字符串拼写错误

8.2 本版本合入的 Pull Requests

PR类型内容
#10498TST修复linprog"disp": TrueBug
#10536CITravis 增加 3.8-dev
#10671BUG修复非中心 F 分布方差公式
#10693BUGScalarFunction保存原始数组
#10700BUG放宽稀疏花式赋值的检查
#10709BUG修复floyd_warshall对零权边的支持
#10756BUG确保求解器对 NaN 结果以success=False退出
#10833BUG修复复数输入的subspace_angles
#10882BUG修复 ARPACK 复数 Hermitian 代码
#10891BUG让 C 实现的求根器兼容functools.lru_cache
#10906BUG修复expmnp.matrix输入的处理
#10917CI修复 Travis osx CI
#10930MAINTPython 3.8 适配更新
#10938MAINTpyproject.toml中添加 Python 3.8
#10943BLD升级 Cython 至 0.29.13
#10961BUG修复signal.unique_roots
#10971CICI 改用 3.8 稳定版
#10977DOC修复sp.stats.wilcoxon文档字符串拼写
#11025DOC更新_peak_finding.py

九、版本贡献者与升级建议

9.1 贡献者名单

本版本共有14 位贡献者参与(名单由工具自动生成,可能不完全):CJ Carey、Dany Vohl、Martin Gauch(+)、Ralf Gommers、Matt Haberland、Eric Larson、Nikolay Mayorov、Sam McCormack(+)、Andrew Nelson、Tyler Reddy、Pauli Virtanen、Huize Wang(+)、Warren Weckesser、Joseph Weston(+)。其中带"+"标记的 4 位(Martin Gauch、Sam McCormack、Huize Wang、Joseph Weston)是首次贡献补丁的新贡献者

9.2 升级建议

综合本版本内容,以下几点值得关注:

  1. Python 3.8 用户应尽快升级:1.3.2 是 1.3.x 系列中首个正式支持 Python 3.8 的版本,配套的 Cython 0.29.13 也完成了适配;
  2. 依赖数值正确性的场景优先升级:非中心 F 分布方差公式修正(涉及假设检验与置信区间)、Floyd-Warshall 零权边支持(涉及图算法)、复数subspace_angles(涉及子空间分析)都属于静默性数值错误,在旧版本上不会报错但结果有误,应优先升级并回归验证;
  3. 求解器可靠性提升:NaN 不再误报 success、root_scalar支持lru_cache装饰函数,使优化代码在极端输入下更安全、更易集成记忆化加速。

从仓库结构看,本版本的修复痕迹完整保留在 scipy/signal/_signaltools.py、scipy/sparse/csgraph/_shortest_path.pyx、scipy/sparse/linalg/_matfuncs.py、scipy/optimize/_zerosmodule.c、scipy/stats/_continuous_distns.py 等文件中,对应回归测试则分布于 scipy/optimize/tests/test_zeros.py 与 scipy/stats/tests/test_distributions.py 等测试套件中,可作为验证升级正确性的参考锚点。

【免费下载链接】scipySciPy library main repository项目地址: https://gitcode.com/gh_mirrors/sc/scipy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询