On Thursday, February 12, 2015 at 10:03:04 PM UTC-6, Zouhair Mahboubi wrote: > > > > I'm trying to find the column indices of non-zero elements of a given row > in a sparse matrix A > > I figured using findn would be a fast way to do that, but I was curious to > see how the implementation was done since all I cared about were the > columns for a given row and I thought I could have my own version that only > checked for a given row. > > But when I took a peek in > https://github.com/JuliaLang/julia/blob/master/base/sparse/sparsematrix.jl#L310 > I was surprised to see this in findn (and findnz) > > S.nzval[k] != 0 > > > > I would have expected nzval to always be != 0 by construction? > > Then I had a look at nnz and countnz, and I was again surprised to see > that they have slightly different implementations! > Especially given the help for the two functions (which makes sense since > one expects all stored elements in the sparse matrix to be non-zero) > > help?> nnz >> Base.nnz(A) >> Returns the number of stored (filled) elements in a sparse matrix. >> help?> countnz >> Base.countnz(A) >> Counts the number of nonzero values in array A (dense or sparse). >> Note that this is not a constant-time operation. For sparse >> matrices, one should usually use "nnz", which returns the number >> of stored values. > > > > The only way I can see that happening, is if the user manually modifies > nzval? i.e. > A = spdiagm(ones(5)); > println(nnz(A), countnz(A)) #prints 55 > A[1,1] = 0 > println(nnz(A), countnz(A)) #prints 44 > A.nzval[1] = 0 > println(nnz(A), countnz(A)) #prints 43 > > > So few questions: > > > - what is the fastet way to do what I was initially trying to > accomplish: find the column indices and values of a given row in a sparse > matrix A > - why the checking of nzval? > - is that because it's ok to change nzval manually? if not, why is > nzval not "protected" ? > > Regarding the question of changing elements of nzval, yes, there can be occasions when one wants to do this.
Remember that it only makes sense to use a sparse representation when working with large matrices - in my case sparse symmetric matrices with potentially millions of columns. Frequently these structures are associated with optimization problems in which the criterion to be optimized is repeatedly evaluated at different parameter values. In such cases you don't want to take copies unnecessarily so you may cheat a bit and rely on the structure staying the same even when the values of individual elements change. In my case some elements can become zero transiently but I don't want the structure to change when a potential non-zero happens to take on a value of zero. There isn't a concept of a protected value in Julia. Most things are pretty open to changes by the programmer, according to the "consenting adults" approach of the language developers. In other languages the inherent restrictions on what can be changed can lead to inefficiencies. For about the last decade that I was developing software in R I found myself bashing my head against the restriction that modifications to arguments within a function are not visible outside the function. That is, copy-on-write is enforced for arguments. That is wonderful until you want to modify a large structure in place and you can't. There are several functions that can modify the nzval member of a sparse matrix in place. According to convention the names of such functions usually end in '!', as in "scale!", "A_mul_B!", etc. You can cause yourself a lot of grief with these functions, which is why the names end in '!', but you can also do things that would otherwise be very difficult to achieve without creating many copies. And economizing on storage is the reason for sparse matrices in the first place. > > > Thanks, > -z >