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

Cannot multiply I by a variable and add it to a matrix. #206

Closed
araujoms opened this issue Mar 16, 2023 · 6 comments
Closed

Cannot multiply I by a variable and add it to a matrix. #206

araujoms opened this issue Mar 16, 2023 · 6 comments

Comments

@araujoms
Copy link
Contributor

If I create a variable @variable(model, x) and a numerical matrix a = randn(Float64,(2,2)), the expression a+x*I gives me the error MethodError: no method matching +(::Matrix{Float64}, ::AffExpr).

Of course, it works without any problem if instead of I one uses an explicit identity matrix like id = Symmetric(Matrix{Float64}(I,2,2))

@blegat
Copy link
Member

blegat commented Mar 16, 2023

The issue is that LinearAlgebra does not support holding a JuMP expression. We should probably create a Diagonal matrix here.

@odow
Copy link
Member

odow commented Mar 16, 2023

We should probably create a Diagonal matrix here.

How would we know the dimension of x * I?

@odow
Copy link
Member

odow commented Mar 16, 2023

There's a few things here to fix:

julia> using JuMP, LinearAlgebra

julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.

julia> @variable(model, x)
x

julia> a = rand(2, 2)
2×2 Matrix{Float64}:
 0.191126  0.178202
 0.71827   0.63977

julia> @expression(model, a + x * I)
ERROR: MethodError: no method matching zero(::Type{Matrix{Float64}})
Closest candidates are:
  zero(::Union{Type{P}, P}) where P<:Dates.Period at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/Dates/src/periods.jl:53
  zero(::GenericQuadExpr) at /Users/oscar/.julia/dev/JuMP/src/quad_expr.jl:113
  zero(::GenericAffExpr) at /Users/oscar/.julia/dev/JuMP/src/aff_expr.jl:200
  ...
Stacktrace:
  [1] _instantiate_zero(#unused#::Type{Matrix{Float64}})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:28
  [2] promote_operation_fallback(op::typeof(+), #unused#::Type{Matrix{Float64}}, #unused#::Type{AffExpr})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:51
  [3] promote_operation(::typeof(+), ::Type, ::Type)
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:113
  [4] promote_operation_fallback(op::typeof(MutableArithmetics.add_mul), #unused#::Type{Matrix{Float64}}, #unused#::Type{VariableRef}, #unused#::Type{UniformScaling{Bool}})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:83
  [5] promote_operation(::typeof(MutableArithmetics.add_mul), ::Type, ::Type, ::Type)
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:113
  [6] mutability(::Type, ::Function, ::Type, ::Type, ::Type)
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:260
  [7] mutability(::Matrix{Float64}, ::Function, ::Matrix{Float64}, ::VariableRef, ::UniformScaling{Bool})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:268
  [8] operate!!(::typeof(MutableArithmetics.add_mul), ::Matrix{Float64}, ::VariableRef, ::UniformScaling{Bool})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/rewrite.jl:89
  [9] macro expansion
    @ ~/.julia/packages/MutableArithmetics/geMUn/src/rewrite.jl:322 [inlined]
 [10] macro expansion
    @ ~/.julia/dev/JuMP/src/macros.jl:1564 [inlined]
 [11] top-level scope
    @ REPL[35]:1

julia> @expression(model, a + x * I(2))
ERROR: MethodError: no method matching similar_array_type(::Type{Diagonal{Bool, Vector{Bool}}}, ::Type{AffExpr})
Closest candidates are:
  similar_array_type(::Type{Symmetric{T, MT}}, ::Type{S}) where {S, T, MT} at /Users/oscar/.julia/packages/MutableArithmetics/geMUn/src/implementations/LinearAlgebra.jl:151
  similar_array_type(::Type{Array{T, N}}, ::Type{S}) where {S, T, N} at /Users/oscar/.julia/packages/MutableArithmetics/geMUn/src/implementations/LinearAlgebra.jl:158
  similar_array_type(::Type{var"#s12"} where var"#s12"<:Union{Adjoint{T, A}, Transpose{T, A}}, ::Type{S}) where {S, T, A} at /Users/oscar/.julia/packages/MutableArithmetics/geMUn/src/implementations/LinearAlgebra.jl:442
  ...
Stacktrace:
 [1] promote_operation(op::typeof(*), #unused#::Type{VariableRef}, A::Type{Diagonal{Bool, Vector{Bool}}})
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/implementations/LinearAlgebra.jl:173
 [2] promote_operation_fallback(op::typeof(MutableArithmetics.add_mul), #unused#::Type{Matrix{Float64}}, #unused#::Type{VariableRef}, #unused#::Type{Diagonal{Bool, Vector{Bool}}})
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:82
 [3] promote_operation(::typeof(MutableArithmetics.add_mul), ::Type, ::Type, ::Type)
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:113
 [4] mutability(::Type, ::Function, ::Type, ::Type, ::Type)
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:260
 [5] mutability(::Matrix{Float64}, ::Function, ::Matrix{Float64}, ::VariableRef, ::Diagonal{Bool, Vector{Bool}})
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/interface.jl:268
 [6] operate!!(::typeof(MutableArithmetics.add_mul), ::Matrix{Float64}, ::VariableRef, ::Diagonal{Bool, Vector{Bool}})
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/geMUn/src/rewrite.jl:89
 [7] macro expansion
   @ ~/.julia/packages/MutableArithmetics/geMUn/src/rewrite.jl:322 [inlined]
 [8] macro expansion
   @ ~/.julia/dev/JuMP/src/macros.jl:1564 [inlined]
 [9] top-level scope
   @ REPL[36]:1

julia> a + x * I
ERROR: MethodError: no method matching +(::Matrix{Float64}, ::AffExpr)
Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...) at operators.jl:560
  +(::Union{MathOptInterface.ScalarAffineFunction{T}, MathOptInterface.ScalarQuadraticFunction{T}}, ::T) where T at /Users/oscar/.julia/packages/MathOptInterface/wt3Qd/src/Utilities/functions.jl:1843
  +(::ChainRulesCore.AbstractThunk, ::Any) at /Users/oscar/.julia/packages/ChainRulesCore/a4mIA/src/tangent_arithmetic.jl:122
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[37]:1

julia> a + x * I(2)
2×2 Matrix{AffExpr}:
 x + 0.19112646574469405  0.17820240909659368
 0.7182696309995809       x + 0.6397701354899521

@odow
Copy link
Member

odow commented Nov 28, 2023

JuMP now gives a better error here too: jump-dev/JuMP.jl#3558

@odow
Copy link
Member

odow commented Nov 28, 2023

Closing because I think this is resolved by #205 and jump-dev/JuMP.jl#3558.

julia> using JuMP, LinearAlgebra

julia> model = Model();

julia> @variable(model, x);

julia> a = rand(2, 2);

julia> @expression(model, a + x * I)
ERROR: Addition between an array and a JuMP scalar is not supported: instead of `x + y`, do `x .+ y` for element-wise addition. If you are modifying the diagonal entries of a square matrix, do `x + y * LinearAlgebra.I(n)`, where `n` is the side length.
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] _throw_operator_error(#unused#::typeof(+), x::Matrix{Float64})
   @ JuMP ~/.julia/dev/JuMP/src/operators.jl:467
 [3] +(#unused#::AffExpr, x::Matrix{Float64})
   @ JuMP ~/.julia/dev/JuMP/src/operators.jl:485
 [4] muladd(x::VariableRef, y::UniformScaling{Bool}, z::Matrix{Float64})
   @ Base.Math ./math.jl:1430
 [5] add_mul(a::Matrix{Float64}, b::VariableRef, c::UniformScaling{Bool})
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/solfs/src/MutableArithmetics.jl:27
 [6] operate(op::typeof(MutableArithmetics.add_mul), x::Matrix{Float64}, y::VariableRef, args::UniformScaling{Bool})
   @ MutableArithmetics ~/.julia/packages/MutableArithmetics/solfs/src/interface.jl:210
 [7] macro expansion
   @ ~/.julia/packages/MutableArithmetics/solfs/src/rewrite.jl:321 [inlined]
 [8] macro expansion
   @ ~/.julia/dev/JuMP/src/macros.jl:721 [inlined]
 [9] top-level scope
   @ REPL[7]:1

julia> @expression(model, a + x * I(2))
2×2 Matrix{AffExpr}:
 x + 0.664436809229147  0.05946109185455417
 0.5136992768834855     x + 0.8550754973050526

julia> a + x * I
ERROR: Addition between an array and a JuMP scalar is not supported: instead of `x + y`, do `x .+ y` for element-wise addition. If you are modifying the diagonal entries of a square matrix, do `x + y * LinearAlgebra.I(n)`, where `n` is the side length.
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] _throw_operator_error(#unused#::typeof(+), x::Matrix{Float64})
   @ JuMP ~/.julia/dev/JuMP/src/operators.jl:467
 [3] +(x::Matrix{Float64}, #unused#::AffExpr)
   @ JuMP ~/.julia/dev/JuMP/src/operators.jl:486
 [4] top-level scope
   @ REPL[9]:1

julia> a + x * I(2)
2×2 Matrix{AffExpr}:
 x + 0.664436809229147  0.05946109185455417
 0.5136992768834855     x + 0.8550754973050526

@odow odow closed this as completed Nov 28, 2023
@araujoms
Copy link
Contributor Author

Honestly I'm more surprised that LinearAlgebra can do such a thing. At least now it's clear that JuMP is interpreting I as a 1x1 identity instead of a 2x2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants