Removing small elements from a sparse matrix

Hi, I am interested in removing entries in a sparse (SparseMatrixCSC{Float64,Int64}) matrix which are very small, for example, less than 1E-16 in absolute value. Often in the middle of operations with sparse matrices, these residual values build up, and it would be good to get rid of these.

Is there an inbuilt function to make all entries with values below a threshold zero ?

I tried writing my own routine

for x in A

end

I don’t know what to put in the …, as x is passed by value within the body of the loop,

The non-sparse values are stored in A.nzval, which is a vector, you should be able to set values below a threshold to 0 like in any other vector. This will not change the sparsity structure though, but may be sufficient for your purposes.

julia> a = sprand(5, 5, 1.0) / 10^6;

julia> SparseArrays.fkeep!(a, (i,j,x) -> abs(x) > 1e-4)
5×5 SparseMatrixCSC{Float64,Int64} with 0 stored entries
3 Likes

I think droptol! is exactly what you need. The docstring contains an error. It should read

droptol!(A::SparseMatrixCSC, tol; trim::Bool = true)

  Removes stored values from A whose absolute value is less or equal to tol,
  optionally trimming resulting excess space from A.rowval and A.nzval when trim is
  true.

EDIT: The docstring is fixed now.

9 Likes

Thanks ! This is exactly what I need.

Thanks. I also found this function fkeep being used in the sparematrix.jl file

Thanks. I do want to trim the matrix though. So I could use droptol!, as suggested by @dkarrasch

1 Like

What a shame! I authored the erroneous docstring myself… :scream: Will fix it.

2 Likes

Although I see that droptol! makes most sense for sparse matrices I’d find it convenient to have a similar function for regular (or even abstract) arrays as well. Effective zeros occur frequently in numerics.

The drop in the name could be misleading in this case though. Maybe something like zerotol!?

It is rather trivial to do, eg

function zero_small!(M::AbstractMatrix, tol)
    for ι in eachindex(M)
        if abs(M[ι]) ≤ tol
            M[ι] = 0
        end
    end
    M
end

or something similar. I don’t think it is worth packaging up in a library.

It makes sense to have a specialized version for sparse matrices though, because of the efficiency gains.

I fully agree. I gave a very related problem in an “introduction to programming (in julia, of course!)” exam last year, and tested several approaches that I thought student could come up with beforehand: logical indexing, for loop, findall, and I don’t remember what else I had in mind. I was very happy to see that the most straightforward for-loop with if-conditional (as written by @Tamas_Papp), using only the most elementary programming tools that you teach in a one-week course, yielded the fastest implementation.

2 Likes