Skip to content

SparseArrays.SparseMatrixCSC support #4005

@odow

Description

@odow

Adding #4003 made me wonder if we should do something like:

julia> using JuMP, SparseArrays

julia> _check_rectangular(::Any) = error("Unsupported iterator type")
_check_rectangular (generic function with 1 method)

julia> function _check_rectangular(indices::Containers.NestedIterator)
           if length(indices.iterators) != 2
               error(
                   "Unable to construct a SparseMatrixCSC: the set must be " *
                   "two-dimensional. Got: $(length(indices.iterators))",
               )
           end
           I = indices.iterators[1]()
           if I != Base.OneTo(length(I))
               error(
                   "Unable to construct a SparseMatrixCSC: the first dimension must " *
                   "be of the form `1:M`. Got: $I",
               )
           end
           J = indices.iterators[2](1)
           if J != Base.OneTo(length(J))
               error(
                   "Unable to construct a SparseMatrixCSC: the second dimension " *
                   "must be of the form `1:N`. Got: $J",
               )
           end
           for i in I  # Check that there is no triangular indexing
               if indices.iterators[2](i) != J
                   error(
                       "Unable to construct a SparseMatrixCSC: the second dimension " *
                       "must not depend on the value of the first dimension.",
                   )
               end
           end
           return length(I), length(J)
       end
_check_rectangular (generic function with 2 methods)

julia> function Containers.container(
           f::Function,
           indices,
           ::Type{SparseArrays.SparseMatrixCSC},
       )
           m, n = _check_rectangular(indices)
           x = map(args -> args => f(args...), indices)
           I, J, V = first.(first.(x)), last.(first.(x)), last.(x)
           return SparseArrays.sparse(I, J, V, m, n)
       end

julia> model = Model()
A JuMP Model
├ solver: none
├ objective_sense: FEASIBILITY_SENSE
├ num_variables: 0
├ num_constraints: 0
└ Names registered in the model: none

julia> @variable(model, x[i in 1:4, j in 1:4; isodd(i + j)], container = SparseMatrixCSC)
4×4 SparseMatrixCSC{VariableRef, Int64} with 8 stored entries:
        x[1,2]         x[1,4]
 x[2,1]         x[2,3]  
        x[3,2]         x[3,4]
 x[4,1]         x[4,3]  

The downside is that it is pretty finicky with what shapes we can detect, and iterating over every element isn't very efficient.

It might be better to leave the suggestion in the docs?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions