You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

scipy调用lil_matrix.diagonal()触发sparse matrix length is ambiguous错误

问题描述

计算lil_matrix格式稀疏矩阵指定对角线元素和时抛出类型错误,复现代码如下:

sm1 = np.sum(board.diagonal(k=i1-row1))
sm2 = np.sum(board.diagonal(k=i2-row2))

抛出的错误信息:

TypeError: sparse matrix length is ambiguous; use getnnz() or shape[0]

已知信息:

  • type(board)返回值为<class 'scipy.sparse._lil.lil_matrix'>,参数row1, row2, i1, i2均为整数
  • 执行print(np.sum(board.diagonal(k=i1-row1)))时,程序会先打印正确计算结果,之后才抛出上述类型错误
  • 经排查diagonal方法内部实现为return self.tocsr().diagonal(k=k),直接调用board.tocsr()会抛出完全相同的错误
    完整错误日志:
Traceback (most recent call last):
  File "/usr/lib/python3.8/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "/snap/pycharm-professional/285/plugins/python/helpers/pydev/_pydev_bundle/pydev_umd.py", line 198, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "/snap/pycharm-professional/285/plugins/python/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/home/noah/PycharmProjects/nQueens/sa_sparse.py", line 94, in <module>
    y.run()
  File "/home/noah/PycharmProjects/nQueens/sa_sparse.py", line 63, in run
    self.swap(newSol)
  File "/home/noah/PycharmProjects/nQueens/sa_sparse.py", line 34, in swap
    newCost = self.calcFastCost(board.board, row1, row2)
  File "/home/noah/PycharmProjects/nQueens/sa_sparse.py", line 47, in calcFastCost
    sm1 = np.sum(board.diagonal(k=i1-row1))
  File "/home/noah/nQueens/lib/python3.8/site-packages/scipy/sparse/_base.py", line 1214, in diagonal
    return self.tocsr().diagonal(k=k)
  File "/home/noah/nQueens/lib/python3.8/site-packages/scipy/sparse/_lil.py", line 459, in tocsr
    _csparsetools.lil_get_lengths(self.rows, indptr[1:])
  File "_csparsetools.pyx", line 111, in scipy.sparse._csparsetools.lil_get_lengths
  File "_csparsetools.pyx", line 117, in scipy.sparse._csparsetools._lil_get_lengths_int32
  File "/home/noah/nQueens/lib/python3.8/site-packages/scipy/sparse/_base.py", line 345, in __len__
    raise TypeError("sparse matrix length is ambiguous; use getnnz()"
TypeError: sparse matrix length is ambiguous; use getnnz() or shape[0]
故障原因

核心问题是当前lil_matrix实例的内部rows属性被污染:
lil_matrix的rows属性本应是长度等于矩阵行数的嵌套列表,每个子列表存储对应行非零元素的列索引,tocsr()转换时C扩展会遍历每个子列表调用len()统计每行非零元素个数。
从错误栈可以判断,代码在之前的矩阵修改操作(比如皇后位置交换逻辑)中,错误地将一个稀疏矩阵对象赋值给了rows属性下的某个子列表位置,导致C扩展遍历到该位置时,对稀疏矩阵对象调用len(),触发了稀疏矩阵禁止直接取长度的类型错误。
先打印正确结果再报错的反常现象,是因为对角线提取操作在tocsr()流程的前半段已经完成并返回,后续遍历统计行长度的步骤触发异常时,求和、打印逻辑已经执行完毕。

解决方案
  1. 先定位污染位置,在调用对角线计算代码前增加校验逻辑,快速定位被错误赋值的行:
    # 校验rows属性合法性
    for row_idx, row_content in enumerate(board.rows):
        if not isinstance(row_content, list):
            print(f"第{row_idx}行rows数据类型异常,当前类型:{type(row_content)}")
            break
    
  2. 修正矩阵修改逻辑的赋值错误:操作lil_matrix元素时,不要直接修改内部rows属性,使用标准的board[row, col] = value接口赋值,避免将非整数、非列表类型的值写入rows结构。
  3. 临时规避方案(仅临时绕过,不能解决根本问题):提前将矩阵转为CSR格式缓存,避免每次取对角线都触发tocsr()转换:
    board_csr = board.tocsr()
    sm1 = np.sum(board_csr.diagonal(k=i1-row1))
    sm2 = np.sum(board_csr.diagonal(k=i2-row2))
    
    注意该方案无法修复rows属性污染问题,后续其他稀疏矩阵操作仍可能触发同类错误,必须修正赋值逻辑才能彻底解决。

内容的提问来源于stack exchange,提问作者Brot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:30:39