Function zero() with type"Any"

Hi!

Nowadays I’m learning about Julia, mainly to solve non-linear optimization problem. Because of the low efficiency of dense matrix, I transfer some of the matrix into sparse matrix. When I’m trying to multiply two matrix with type"Any", an error trough out:
ERROR: MethodError: no method matching zero(::Type{Any})

It seems that function zero() cannot have type “Any” as input, but I don’t understand why and how to solve this problem.

Blockquote
julia> matrix
2×2 SparseMatrixCSC{Any,Int64} with 3 stored entries:
[1, 1] = 1
[2, 1] = 1
[2, 2] = 1
julia> matrix=Any[1 1;1 2]
2×2 Array{Any,2}:
1 1
1 2
julia> matrix-matrix
ERROR: MethodError: no method matching zero(::Type{Any})
Closest candidates are:
zero(::Type{Union{Missing, T}}) where T at missing.jl:87
zero(::Type{LibGit2.GitHash}) at C:\Users\julia\AppData\Local\Julia-1.1.1\share\julia\stdlib\v1.1\LibGit2\src\oid.jl:220
zero(::Type{Pkg.Resolve.VersionWeights.VersionWeight}) at C:\Users\julia\AppData\Local\Julia-1.1.1\share\julia\stdlib\v1.1\Pkg\src\resolve\VersionWeights.jl:19

It seems that while operating sparse matrix, function zero() is used, in missing.jl, I find that:

Blockquote
for f in (:(Base.zero), :(Base.one), :(Base.oneunit))
@eval function $(f)(::Type{Union{T, Missing}}) where T
T === Any && throw(MethodError($f, (Any,))) # To prevent StackOverflowError
$f(T)
end
end

I try to delete that ,but it doesn’t work

Why not write matrix = [1 1;1 2]?



julia> matrix = [1 1;1 2]
2×2 Array{Int64,2}:
 1  1
 1  2

julia> matrix - matrix
2×2 Array{Int64,2}:
 0  0
 0  0

While using Any as an element type is probably not good style unless you have a good reason, the methods should work, so this looks like a bug. Probably non-numeric types should just use 0 here.

Please make a self-contained MWE and open an issue.

It appears they do work (Julia v1.1.1)

julia>  matrix=Any[1 1;1 2]
2×2 Array{Any,2}:
 1  1
 1  2

julia> matrix - matrix
2×2 Array{Int64,2}:
 0  0
 0  0

yeah it works in this situation… but in my problem I try to use sparse matrix to improve the operating speed, it seems like something wrong with sparse matrix in type “Any”

yeah… actually I’m using JuMP to do nonlinear optimization, my input is a 1*144 matrix, in the value function some entries of the matrix is constant, e.g., zero, but some others are VariableRef , so I need to use Any

I really need them in my question, I need to build a matrix with some entries are variable, thank you for your advice!

zero(Any) should definitely not be 0, and throwing an error is the right thing in the absence of a generic additive-identity object. See also #8092, #4808, and #27766, for example.

That being said, it should be possible to perform a matrix multiplication or subtraction for non-empty arrays without calling zero on the element type, by instead using the first element of the matrices to initialize the sums.

4 Likes

I can’t reproduce? Not sure what is the problem.
I am on Julia 1.0.3, by the way.

julia> using SparseArrays

julia> A = sparse([1,2,2],[1,1,2],[1,1,1])
2×2 SparseMatrixCSC{Int64,Int64} with 3 stored entries:
  [1, 1]  =  1
  [2, 1]  =  1
  [2, 2]  =  1

julia> B=Any[1 1;1 2]
2×2 Array{Any,2}:
 1  1
 1  2

julia> A-B
2×2 Array{Int64,2}:
 0  -1
 0  -1

julia> A-A
2×2 SparseMatrixCSC{Int64,Int64} with 0 stored entries

julia> B-B
2×2 Array{Int64,2}:
 0  0
 0  0

how did you make this?
SparseMatrixCSC{Any,Int64}, a {Any, Int64}?

Edit:
oh

julia> C = sparse([1,2,2],[1,1,2],Any[1,1,1])
2×2 SparseMatrixCSC{Any,Int64} with 3 stored entries:
  [1, 1]  =  1
  [2, 1]  =  1
  [2, 2]  =  1

julia> A-C
ERROR: MethodError: no method matching zero(::Type{Any})

right!But I really need sparse matrix with type Any, I don’t know how to solve this problem…

thank you for your reply! I’m sorry but I don’t fully understand how to use the first element of the matrices to initialize the sums, Could you show more details or give a simple example? thank you very much!

Why?

I think this was a suggestion as a fix for the implementation of the relevant methods, not something the user would do.

You could use Union{Real,VariableRef} and then define Base.zero(::Type{Union,VariableRef}) = 0.

Arguably, JuMP should define AbstractJuMPScalar <: Real (or maybe <: Number) to help with this sort of problem (AbstractJuMPScalar is the supertype of VariableRef).

1 Like