我尝试使用以下代码获得以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))
,它会在抛出类型错误之前打印正确的结果。
我怀疑这个错误与csr矩阵的转换有关,因为在错误消息中提到了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]
你们的scipy
版本是什么?在当前设置中,我可以创建lil
并获得对角线:
In [16]: M = sparse.lil_matrix(np.eye(3))
In [17]: M
Out[17]:
<3x3 sparse matrix of type '<class 'numpy.float64'>'
with 3 stored elements in List of Lists format>
In [18]: M.A
Out[18]:
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
转换为csr
没有问题,对角线也没有问题:
In [19]: M.tocsr()
Out[19]:
<3x3 sparse matrix of type '<class 'numpy.float64'>'
with 3 stored elements in Compressed Sparse Row format>
In [20]: M.diagonal()
Out[20]: array([1., 1., 1.])
但问len
,给你的错误:
In [21]: len(M)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [21], in <cell line: 1>()
----> 1 len(M)
File ~anaconda3libsite-packagesscipysparsebase.py:291, in spmatrix.__len__(self)
290 def __len__(self):
--> 291 raise TypeError("sparse matrix length is ambiguous; use getnnz()"
292 " or shape[0]")
TypeError: sparse matrix length is ambiguous; use getnnz() or shape[0]
对于这个lil
,其他的步骤是好的:
In [22]: M.nnz
Out[22]: 3
In [23]: M.getnnz()
Out[23]: 3
In [24]: M.shape
Out[24]: (3, 3)
lil将值存储在两个对象类型数组中:
In [26]: M.data
Out[26]: array([list([1.0]), list([1.0]), list([1.0])], dtype=object)
In [27]: M.rows
Out[27]: array([list([0]), list([1]), list([2])], dtype=object)
如果我通过删除一个rows
元素来破坏矩阵,我会得到一个非常不同的错误。
看起来错误发生在tocsr
中,在这个块中,它从rows
元素的长度创建indptr
:
M, N = self.shape
if M*N <= np.iinfo(np.int32).max:
# fast path: it is known that 64-bit indexing will not be needed.
idx_dtype = np.int32
indptr = np.empty(M + 1, dtype=idx_dtype)
indptr[0] = 0
_csparsetools.lil_get_lengths(self.rows, indptr[1:])
np.cumsum(indptr, out=indptr)
nnz = indptr[-1]
lil_get_lengths
是经过编译的代码,遍历rows
的元素,并将它们的长度放在第二个参数中。