In the following example the constraint x == sum(1.0 for i in 1:0) raises a loading error, Variable MathOptInterface.VariableIndex(1) is fixed. Cannot also set lower bound.. An equivalent form of the constraint x == 0.0 works fine.
using JuMP
using Ipopt
m = Model()
@variable(m, 0.0 <= x <= 1.0)
# works fine
# @constraint(m, x == 0.0)
# breaks
@constraint(m, x == sum(1.0 for i in 1:0))
println(m)
optimize!(m, with_optimizer(Ipopt.Optimizer))
To clarify,
@constraint(m, x == sum(1.0 for i in 1:0))
adds a constraint x == 0 of type SingleVariable-in-EqualTo (leading to the variable bounds already exist error), but the expected behavior is to throw the following error (from the empty sum):
ERROR: ArgumentError: reducing over an empty collection is not allowed
@odow the above is a valid JuMP v0.18 program. JuMP v0.18, supports empty collections, and I think the JuMP AML should as well. It is standard in AMPL and others. The alternative is to have conditional statements when defining constraints to determine if the collections are non-empty.
I don't immediately see any negative side effects of JuMP interpreting a sum over an empty collection to be 0, especially if this worked on 0.18 already.
My immediate concern was
julia> sum(1.0 for i in 1:0)
ERROR: ArgumentError: reducing over an empty collection is not allowed
Stacktrace:
[1] _empty_reduce_error() at ./reduce.jl:216
[2] mapreduce_empty_iter(::Function, ::Function, ::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##3#4"))}, ::Base.EltypeUnknown) at ./reduce.jl:261
[3] mapfoldl_impl at ./reduce.jl:57 [inlined]
[4] #mapfoldl#187 at ./reduce.jl:72 [inlined]
[5] mapfoldl at ./reduce.jl:72 [inlined]
[6] #mapreduce#191 at ./reduce.jl:205 [inlined]
[7] mapreduce at ./reduce.jl:205 [inlined]
[8] sum at ./reduce.jl:399 [inlined]
[9] sum(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##3#4"))}) at ./reduce.jl:416
[10] top-level scope at none:0
and that it isn't obvious to users that JuMP re-writes the sum to be
y = 0
for i in 1:0
y += 1
end
y
I agree we should generally try to be consistent with Julia. However, replacing an error with what's obviously intended isn't that much of a stretch. Users don't need to know about the internals of the macros. Sums over empty sets are universally defined to be zero (https://en.wikipedia.org/wiki/Empty_sum).
The motivation for Julia to throw an error is because Julia is bound to be type generic. In JuMP there's no harm in saying that an empty sum is Int(0) or 0.0 because we already have conversions to Float64 in numerous places.
I have some time today so I'll look into this.
Thanks!!!
On Tue, May 7, 2019 at 9:24 AM Oscar Dowson notifications@github.com
wrote:
I have some time today so I'll look into this.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/JuliaOpt/JuMP.jl/issues/1954#issuecomment-490127198,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAIN5KUKWGEUNWBP7F4QPE3PUGNKNANCNFSM4HLCY2KA
.
Most helpful comment
I agree we should generally try to be consistent with Julia. However, replacing an error with what's obviously intended isn't that much of a stretch. Users don't need to know about the internals of the macros. Sums over empty sets are universally defined to be zero (https://en.wikipedia.org/wiki/Empty_sum).
The motivation for Julia to throw an error is because Julia is bound to be type generic. In JuMP there's no harm in saying that an empty sum is
Int(0)or0.0because we already have conversions toFloat64in numerous places.