Skip to content
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

diagm and spdiagm #457

Closed
5 of 9 tasks
fredrikekre opened this issue Aug 18, 2017 · 14 comments
Closed
5 of 9 tasks

diagm and spdiagm #457

fredrikekre opened this issue Aug 18, 2017 · 14 comments
Assignees
Labels
deprecation This change introduces or involves a deprecation

Comments

@fredrikekre
Copy link
Member

fredrikekre commented Aug 18, 2017

Current state of affairs

There is currently a lot of inconsistencies between diagm and spdiagm. Some methods of diagm and its behavior:

  • diagm(v::AbstractVector, k): place vector v on the kth diagonal
  • diagm(v::SparseMatrixCSC): Note SparseMatrixCSC, not SparseVector, and it has to be of size (n,1) or (1,n). This places places the entries on the 0th diagonal (no choice).
  • diagm(v::BitMatrix): Same thing here, matrix of size (n,1) or (1,n) and no choice of placement.

spdiagm is a bit more flexible: we can supply multiple vectors for multiple diagonals, e.g. spdiagm((v1, v2), (k1,k2)) places vector v1 and v2 on diagonal k1 and k2 respectively. We can also specify the resulting matrix size, e.g. spdiagm((v1, v2), (k1,k2), m, n) which will create a m×n matrix. Is this actually useful? Looking at the code, it seems like its there to kind of mirror the sparse(I,J,V) / sparse(I,J,V,m,n) methods.

Action plan

The most obvious things are:

  • Deprecate diagm(A::SparseMatrixCSC) in favor of spdiagm(sparsevec(A)) (#23341)
  • Deprecate diagm(A::BitMatrix) in favor of diagm(vec(A)) (#23373)

Change to nicer Pair API instead of the diagm(tuple_of_vecs, tuple_of_diags) methods.

  • Deprecate spdiagm(tuple_of_vecs, tuple_of_diags) in favor of spdiagm(p::Pair{<:Integer,<:AbstractVector}...) (#23757)
  • Implement diagm(p::Pair{<:Integer,<:AbstractVector}...) to match the spdiagm method. (#24047)

Then some other things:

  • Remove the option to supply resulting matrix size for spdiagm and always return a square matrix like diagm. (#23757)

So when we are here, we have diagm and spdiagm that match each other. Where could we go from here? We delete spdiagm! 🎉

  • Deprecate spdiagm(vecs, diags) in favor of diagm(sparsevec.(vecs), diags)

So now we only have diagm. Lets delete that too?

  • Deprecate diagm(v::AbstractVector) in favor of Matrix(Diagonal(v))
  • Deprecate diagm(v::SparseVector) in favor of sparse(Diagonal(v))
  • Deprecate diagm(v::BitVector) in favor of BitMatrix(Diagonal(v))

The only problem with this is that we can't really specify diagonals easily anymore, and lose the option to supply more than one vector. So perhaps this last step was just too much.

@fredrikekre fredrikekre added deprecation This change introduces or involves a deprecation linear algebra labels Aug 18, 2017
@fredrikekre fredrikekre self-assigned this Aug 18, 2017
@stevengj
Copy link
Member

Requiring diagm(sparsevec.(vecs), diags) seems odd. In most uses of spdiagm, I suspect that the diagonals themselves are not sparse, so it is weird to require a SparseVector copy.

@fredrikekre
Copy link
Member Author

Yea, I know and agree that it is suboptimal, but it would be nice to get rid of the sp* functions... Perhaps diagm(SparseMatrixCSC, vecs, diags) would be an alternative spelling?

@tkoolen
Copy link

tkoolen commented Aug 18, 2017

If this is being redesigned, could JuliaArrays/OffsetArrays.jl#25 be taken into account?

@StefanKarpinski
Copy link
Member

Would diagm(k₁ => d₁, k₂ => d₂, k₃ => d₃) be a nicer API?

@tkoolen
Copy link

tkoolen commented Aug 19, 2017

I'm in favor of those last three deprecations in the issue description, as that would allow us to not have to think about what the indices for diagm(::OffsetVector, ::Int) should be, which is unclear (see OffsetArrays issue).

OffsetArrays.jl could then choose to have diagm(::OffsetVector, ::Int) (or diagm(::Pair{Int, <:AbstractVector}...)) error, while still having the most common case (constructing a truly diagonal matrix) work by overloading Diagonal(::OffsetVector) and indices(::Diagonal{<:OffsetVector}) in OffsetArrays. Or perhaps better, change the Diagonal code in Base so that Diagonal{<:OffsetVector} automagically has the right behavior.

cc: @timholy

@stevengj
Copy link
Member

@fredrikekre, spdiagm is a lot easier to type, we have a lot of sp* functions, and some variant of spdiag is fairly common (Matlab, Numpy, R). diagm(SparseMatrixCSC, vecs, diags) doesn't seem like an improvement.

@ViralBShah
Copy link
Member

It is unsatisfying to have the sp* functions, but passing SparseMatrixCSC as an input argument is certainly not an improvement.

@fredrikekre
Copy link
Member Author

Alternative suggestions welcome.

@stevengj
Copy link
Member

My suggestion is to keep spdiagm

@fredrikekre
Copy link
Member Author

fredrikekre commented Aug 28, 2017

Here is another inconsistency:

julia> diagm(rand(3), 4)
7×7 Array{Float64,2}:
 0.0  0.0  0.0  0.0  0.519002  0.0       0.0    
 0.0  0.0  0.0  0.0  0.0       0.812178  0.0    
 0.0  0.0  0.0  0.0  0.0       0.0       0.64331
 0.0  0.0  0.0  0.0  0.0       0.0       0.0    
 0.0  0.0  0.0  0.0  0.0       0.0       0.0    
 0.0  0.0  0.0  0.0  0.0       0.0       0.0    
 0.0  0.0  0.0  0.0  0.0       0.0       0.0    

julia> full(spdiagm(rand(3), 4))
3×7 Array{Float64,2}:
 0.0  0.0  0.0  0.0  0.696544  0.0       0.0     
 0.0  0.0  0.0  0.0  0.0       0.100363  0.0     
 0.0  0.0  0.0  0.0  0.0       0.0       0.979094

Which behavior do we want here?

@KristofferC
Copy link
Member

Imo the first one.

@fredrikekre
Copy link
Member Author

From searching a bit it seems that the option to supply the resulting size for spdiagm (point four in the top post) is mostly used to make sure a square matrix is returned. So if we always return a square matrix, then we can probably remove the option to supply the resulting size.

@fredrikekre
Copy link
Member Author

I think we are done here -- now we have diagm and spdiagm that behaves identically. Leaving the rest to JuliaLang/julia#11557, JuliaLang/julia#16740.

@KristofferC
Copy link
Member

Good job!

@KristofferC KristofferC transferred this issue from JuliaLang/julia Nov 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deprecation This change introduces or involves a deprecation
Projects
None yet
Development

No branches or pull requests

6 participants