简体   繁体   中英

Error in checking symmetric sparse matrix

 if  not (sp.csc_matrix.transpose(a) == a).all():        
            a_transpose=sp.csc_matrix.transpose(a)
            a=np.add(a,a_transpose)

I am keeping a check if the sparse matrix is symmetric or not but I am getting the following error- AttributeError: all not found

For some random explorations of the topic:

In [77]: from scipy import sparse

Make a sparse matrix

In [78]: M = sparse.random(100,100,.2, 'csr')
In [79]: M
Out[79]: 
<100x100 sparse matrix of type '<class 'numpy.float64'>'
    with 2000 stored elements in Compressed Sparse Row format>

It doesn't like the equality test - it does but gives a warning, the original 2000 nonzero values has increased 3x

In [80]: M==M.T
/usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:226: SparseEfficiencyWarning: Comparing sparse matrices using == is inefficient, try using != instead.
  " != instead.", SparseEfficiencyWarning)
Out[80]: 
<100x100 sparse matrix of type '<class 'numpy.bool_'>'
    with 6436 stored elements in Compressed Sparse Row format>

Difference still increases the number of nonzero terms, but not as much

In [81]: (M-M.T)
Out[81]: 
<100x100 sparse matrix of type '<class 'numpy.float64'>'
    with 3564 stored elements in Compressed Sparse Row format>

Python abs works, because it delegates to the sparse method: M.__abs__

In [85]: abs(M-M.T)
Out[85]: 
<100x100 sparse matrix of type '<class 'numpy.float64'>'
    with 3564 stored elements in Compressed Sparse Row format>

Another warning if we ask how many are small - the differences for the 0s are all 0:

In [86]: abs(M-M.T)<1e-10
/usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:274: SparseEfficiencyWarning: Comparing a sparse matrix with a scalar greater than zero using < is inefficient, try using >= instead.
  warn(bad_scalar_msg, SparseEfficiencyWarning)
Out[86]: 
<100x100 sparse matrix of type '<class 'numpy.bool_'>'
    with 6436 stored elements in Compressed Sparse Row format>

Create a symmetric matix:

In [87]: Ms = (M+M.T)/2

Now all terms are small

In [88]: abs(Ms-Ms.T)<1e-10
/usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:274: SparseEfficiencyWarning: Comparing a sparse matrix with a scalar greater than zero using < is inefficient, try using >= instead.
  warn(bad_scalar_msg, SparseEfficiencyWarning)
Out[88]: 
<100x100 sparse matrix of type '<class 'numpy.bool_'>'
    with 10000 stored elements in Compressed Sparse Row format>

Instead lets check how many differences are too large:

In [89]: abs(Ms-Ms.T)>1e-10
Out[89]: 
<100x100 sparse matrix of type '<class 'numpy.bool_'>'
    with 0 stored elements in Compressed Sparse Row format>
In [90]: abs(M-M.T)>1e-10
Out[90]: 
<100x100 sparse matrix of type '<class 'numpy.bool_'>'
    with 3564 stored elements in Compressed Sparse Row format>

So the matrix is symmetric if:

In [94]: (abs(Ms-Ms.T)>1e-10).nnz == 0
Out[94]: True

Even if the eq-operator would work here, it's dense. Compare with:

import scipy.sparse as sp
import numpy as np
np.random.seed(1)

a = sp.random(5, 5, density=0.5)
blub = a == a.T
print(blub.shape)
(5, 5)

So don't go this route.

Assuming the data.attribute is available (at least for csc) and of course symmetry, i would do:

sym_err = a - a.T
sym_check_res = np.all(np.abs(sym_err.data) < 1e-10)  # tune this value

The effect:

sym_err.data 

will be of shape (nnz,) , here: (12,) (of course sym_err is sparse too under mild conditions: see next note)

The introduced thresholding is necessary in many use-cases involving fp-math. Skip it or decrease the threshold only if you know what you are doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM