Can I set the default operation of a sparse Matrix to not store zeros?

I am building a sparse matrix II, however, when I assign some of its elements by zeros they are being stored with zero values unless I use dropzeros(II).

1- Why using sparse(II) below not dropping zeros from II?
2- Is there a way to set (as default) at the first of my code that assigning zeros will not be stored into II?

II=sparse([1 0;1 1;1 1;1 1;1 1])
julia> II=sparse([1 0;1 1;1 1;1 1;1 1])
5×2 SparseMatrixCSC{Int64, Int64} with 9 stored entries:
 1  ⋅
 1  1
 1  1
 1  1
 1  1
II[1:2,1]=sparse([0 0]);
julia> II
5×2 SparseMatrixCSC{Int64, Int64} with 9 stored entries:
 0  ⋅
 0  1
 1  1
 1  1
 1  1
julia> sparse(II)
5×2 SparseMatrixCSC{Int64, Int64} with 9 stored entries:
 0  ⋅
 0  1
 1  1
 1  1
 1  1
julia> dropzeros(II)
5×2 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
 ⋅  ⋅
 ⋅  1
 1  1
 1  1
 1  1

Because you might change them later, i.e. it could be intentional?

Not a real answer, but you could filter them out beforehand?

1 Like

Thanks for your reply!
This is because I have a for loop and inside it I change the value of II and then calculate X = A \II. So, I want to avoid using dropzeros(II) in the loop.

for i:11000
# change in II
II = dropzeros(II)
X = A \II
end

Note that you should do dropzeros!(II) and not II=dropzeros(II). In any case, this is not advisable if performance is a concern.
The real reason is that removing/inserting a single entry in SparseArrayCSC is very slow (O(n)) where n is the number of nonzeros. So that loop would be reeeally slow (O(n^2)). True, there is an overhead in dropzeros! for finding where the new zero is, but it would still be O(n^2) without that. Do you really need remove it? It’s probably faster by just setting it to zero.

1 Like

Generally yes, but of course it can depend on many things. I would benchmark to be sure.

1 Like

well, constructing the sparse matrix would be also slow (possibly slower!), so I wouldn’t advise that. Note that dropzeros! would not be needed in this case. But it’s really easy to benchmark, just use the BenchmarkTools package with the @btime macro. e.g.

julia> @btime $A \ $II 

julia> @btime sparse($A) \ sparse($II)

etc :smile:

That’s because the input in that case was already a sparse matrix. When the input is a dense array, it will drop the zeros on construction.

julia> sparse([0,0,1])
3-element SparseVector{Int64, Int64} with 1 stored entry:
  [3]  =  1
1 Like

In general, constructing sparse matrices element-by-element with A[i,j] = val is extremely slow. If you want to construct matrices element-by-element, use the sparse(I,J,V) constructor.

(Changing entries of a sparse matrix without changing the sparsity pattern is fast, though.)

3 Likes