-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sparse setindex and stored zeros #9906
Comments
I agree that a |
Yes, I use ones to preallocate, which is fine. But the other problem does not have a workaround: if I update the Jacobian |
dup of JuliaLang/LinearAlgebra.jl#60 Looks like it is possible to have explicit zeros by calling the |
Thanks for pointing out that issue. I am aware that zeros can be stored in a sparse matrix, but not easily as |
I don't want to rehash JuliaLang/LinearAlgebra.jl#60, but I believe the conclusion is that explicit zeros are allowed in |
That's true; if you want (1) fast changes to individual elements, (2) keeping zeros in place, it seems the best thing to do is directly manipulate the representation. |
I don't think a new type would be a good idea for dealing with this, at least not with the current design. You'd have to reimplement a lot of methods for any new type, or introduce an AbstractCSC level to the hierarchy. Maybe a boolean type parameter could work, but that could also get pretty messy. I think the best solution at the moment would be to add a specific |
New type is definitely not a good idea. The best thing for now is perhaps to have new methods for this. We could even have a module with various methods that store their zeros. |
Thanks for all the input. So I suggest two things:
Let me know if that is good and I can make a pull request for those two points Also, I just discovered this: julia> sparse([1,1], [2,2], [1,-1])
1x2 sparse matrix with 1 Int64 entries:
[1, 2] = 0 Is this a bug? |
I guess the only constructor where this makes sense is Yes - that is a bug. Could you file a separate issue for that? |
Filed issue #9928 |
I feel that a better approach may be to have I prefer the tags to be in the type system, rather than in the function arguments or flags in the data structure, and multiple dispatch will do the rest for us. The code will have to be refactored to use accessor methods, but I feel that overall, this is the better approach. |
I thought the majority opinion in #9928 was that no one actually thinks removing structural nonzeros with values numerically equal to zero is all that important. |
IMO, that will only be true until scores of users send in bug reports. |
It's good enough for SciPy? |
Matlab religiously squeezes out zeroes in all sparse matrix operations. This is SciPy's behaviour:
|
In #6769 (comment), I also looked up UMFPACK and MKL's documentation, which both state that they allow explicitly stored zeros. |
Pardiso in fact requires them on the diagonal. |
Here's the behaviour I would like to have for 0.4, which will not be a ton of work.
|
Point 2. Sounds both dangerous and a bit odd to me, as it's inconsistent with dense arrays, and implementation-wise, it would be very easy for |
Ah I remember that now. That is why we have the current behaviour. Thanks. |
Having an API to easily set an explicit zero without having to dig into the internal representation would be exceedingly helpful. That API does not have to be I'd be okay with just trying to change the behavior in the #9928 case and deferring other changes to post-0.4. But any proposed solution to #9928 should be carefully vetted that it does not cause significant performance regressions in other cases. |
Hello everyone, I was trying to follow the discussion on this thread to figure out how to explicitly store zeros in a sparse matrix. I haven't figured it out yet, so it would be helpful if someone could point out a reference. I need this in order to implement knot interval vectors in an unstructured t-spline mesh. Such a mesh can have empty entries which store no information (which I would like to treat as the usual omitted zeros in a sparse matrix). Zero and positive real numbers are considered valid entries in the knot interval vector. I am not anticipating performing any linear algebra directly on these matrices. I'd like to store it in a sparse format to allow for efficient storage of very large meshes. I also think that the algorithms to extract information from these meshes can be more easily implemented if the data is in a sparse format. If you have any alternative suggestions, I'd be very glad to hear them. Cheers, |
You need to directly modify the |
Or in this case, @ArjunNarayanan could build the matrix with |
Thanks @tkelman and @mlubin. I can enter zero values by setting the nzval field directly, so @mlubin's first suggestion could work pretty well for me. I think a CSC or CSR could work equally well in my case, as long as I am sensible about ordering my data so that it is accessed correctly (the only difference between CSC and CSR is that one would access CSC row-wise and CSR column-wise, correct?). If I could work more elegantly by dealing directly with SparseMatrixCSC, that would be great. Could you point out a reference from where I can figure out how to do this? Thanks for the help! |
Other way around, it's better to iterate through CSC by columns and CSR by rows. There's a pretty good selection of resources online if you search on google/duckduckgo for "compressed sparse column." Tim Davis' book Direct Methods for Sparse Linear Systems is also good, there's even a series of lectures on youtube - https://www.youtube.com/playlist?list=PL5EvFKC69QIyRLFuxWRnH6hIw6e1-bBXB. The main thing to keep in mind with these references and standard data structures is whether the indexing is 1-based or 0-based. Julia and Fortran are 1-based, C and Python are 0-based. |
@tkelman thanks for your reply. I was actually interested in a reference for how to directly use SparseMatrixCSC in Julia. But your references will surely come in handy in the long run, thank you. |
Depends what you want to do. The source is at https://github.com/JuliaLang/julia/blob/master/base/sparse/sparsematrix.jl and in related files in that same directory. There are several packages that make use of sparse matrices in various ways, but most sparse matrix code tends to be pretty application-specific. You can also look through @ViralBShah's JuliaCon presentation notebook at https://github.com/JuliaSparse/JuliaCon2015/blob/master/Sparse%20Matrices%20in%20Julia.ipynb, hopefully the videos will get posted too one of these days. |
@tkelman like I mentioned eariler, I'm only using these matrices for storage, and my only special need is the ability to easily store explicit zeros in my sparse matrix. Doing this via nzval works for me, and I was wondering how I would do it (as @mlubin suggested) by directly dealing with SparseMatrixCSC. I'm not sure if I am at the stage where I can figure out how to do it from the source (beginner woes!) but I'll give it a shot. Thanks again! |
Ah, sorry, if all you're asking for is how to translate @mlubin's suggestion into code, it would look something like this:
|
Ah, I think I was completely confused! I figured out how to do it through nzval from @mlubin's comment. I think I misunderstood the additional statement -- "then it's worth figuring out how to interact with SparseMatrixCSC" -- as meaning that there was another way of doing the same thing. My bad! Anyway, it looks like I'm good to go for now. Thanks for all the help! |
Slightly off-topic: If you're on 0.4
If on 0.3, just copy the definition of julia/base/sparse/sparsematrix.jl Line 33 in cceac50
|
Is there a SparseMatrixCSC that can keep zeros in it yet? @mauro3 thanks for pointing out the nzrange. Use this idea I come out with a version of sparse matrix that can keep zero values. function SparseMatrix.sparse(I,J,V, M, N;keepzeros=false)
if(!keepzeros)
return sparse(I,J,V,M,N)
else
full = sparse(I,J,ones(Float64,length(I)),M,N)
actual = sparse(I,J,V,M,N)
fill!(full.nzval,0.0)
for c = 1:N
crange = nzrange(actual,c)
full.nzval[crange] = actual.nzval[crange]
end
return full
end
end |
As of #15242, |
Did #17404 resolve this issue? Do any points from this issue still stand? Best! |
Yep, resolved. Thanks for all hard work in this area! |
During construction of sparse matrices and when using
setindex!
, entries with values0
are not included/dropped from the underlying storage. This is no good for certain applications. In particular when preallocating sparse matrices.For example we currently got:
Instead
or
My use case are preallocated Jacobian matrices when solving PDEs. Usually the pattern of potential non-zeros in the Jacobian is known, so it can be preallocated. However, when repeatedly filling the Jacobian during the calculation there is no guarantee that its underlaying storage will be kept fixed.
Maybe there could be a sparse type for fixed size sparse matrix, say
SparseMatrixCSCfixed
. Constructed withsparse([1],[1], [1.], 5 ,5, keepzeros=true)
. Thensetindex!
would not drop zeros and error when trying to assign to a not-allocated entry.The text was updated successfully, but these errors were encountered: