Jump.jl: Should we define zero(AffExpr) and one(AffExpr)?

Created on 18 Dec 2017  路  9Comments  路  Source: jump-dev/JuMP.jl

The implementation of zeros(AffExpr, n) looks like fill!(Array{AffExpr}(n), zero(AffExpr)), which is problematic because the result is n entries that refer to the same AffExpr (https://github.com/JuliaOpt/JuMP.jl/issues/1113). Same for ones.

This leads me to question if we should define zero(AffExpr) or one(AffExpr) at all given that code may be written assuming that these return immutable objects. The replacement is AffExpr(0.0) and AffExpr(1.0).

@daschw

Most helpful comment

Having both a mutable and immutable AffExpr is worth considering, but I'd put it off until after 0.19.

All 9 comments

If Base is doing this, they may be implicitly assuming that only immutable objects should define zero and one.

Maybe we could have two version of AffExpr ? One immutable and one mutable.
The mutability of AffExpr is only used inside JuMP macros so we could take care of using the mutable version there.
If the user do operation on variables outside JuMP macros it will become the immutable version.

The mutability of AffExpr is only used inside JuMP macros so we could take care of using the mutable version there.

Not true, we also expose push! and some other functions to append to AffExprs. These are pretty useful in performance-critical situations.

The replacement is AffExpr(0.0) and AffExpr(1.0)

seems reasonable.

Not true, we also expose push! and some other functions to append to AffExprs. These are pretty useful in performance-critical situations.

We could have a warning push! not supported in AffExpr, please convert it to a MutableAffExpr.

Having both a mutable and immutable AffExpr is worth considering, but I'd put it off until after 0.19.

What is the advantage of having the immutable version?

This example by @jdlara-berkeley suggests a similar issue with convert:

m = Model()
x = @variable(m, x >= 0)
NetInjectionVar =  Array{AffExpr,2}(undef, 5, 24)
NetInjectionVar[:] .= 0.0
JuMP.add_to_expression!(NetInjectionVar[1,1],x)
NetInjectionVar
5脳24 Array{JuMP.GenericAffExpr{Float64,JuMP.VariableRef},2}:
 x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
 x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
 x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
 x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x
 x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x  x

I claim that this would be less of a gotcha if you had to write

NetInjectionVar[:] .= AffExpr(0.0)

instead of

NetInjectionVar[:] .= 0.0

Now that we've changed to Dicts, is this still relevant?

m = Model()
x = @variable(m, x >= 0)
NetInjectionVar =  Array{JuMP.AffExpr,2}(undef, 5, 24)
NetInjectionVar[:] .= zero(AffExpr)
NetInjectionVar[1,1] += x

julia> NetInjectionVar
5脳24 Array{JuMP.GenericAffExpr{Float64,VariableRef},2}:
 x  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  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  0  0  0  0  0  0  0

I just updated my example. The issue still exists on Julia 1.0 and JuMP/MOI.

Was this page helpful?
0 / 5 - 0 ratings