I am trying to figure out how to avoid type instability in my model that uses some constraints and objectives that include a variable. I can’t seem to avoid a “::Union{Val{false}, GenericAffExpr{Float64,VariableRef}}” even if I assert a type or use an expression. Am I missing an easy way to avoid this type instability?
Here is a simplified version of my code that should simply be returning the rows of the input array with the three highest values in the second column:
using GLPKMathProgInterface
using JuMP
using GLPK
using BenchmarkTools
function test_warntype(values, num_values)
m = Model(with_optimizer(GLPK.Optimizer))
@variable(m, used_values[i=1:num_values], Bin)
@constraint(m, sum(used_values[i] for i in 1:num_values) == 3)
@objective(m, Max, sum(values[i,2]*used_values[i] for i in 1:num_values))
optimize!(m)
return(used_values)
end
values = [1.5 4.6
2.6 7.3
1.1 3
3.7 0.3
4.4 6]
num_values = size(values)[2]
@code_warntype test_warntype(values, num_values)
And here is the relevant part of the code_warntype output:
Variables
#self#::Core.Compiler.Const(test_warntype, false)
values::Array{Float64,2}
num_values::Int64
m::Model
##76793::Array{VariableRef,1}
used_values::Array{VariableRef,1}
@_7::Union{Nothing, Tuple{Int64,Int64}}
i@_8::Int64
q@_9::Union{Val{false}, GenericAffExpr{Float64,VariableRef}, VariableRef}
@_10::Union{Nothing, Tuple{Int64,Int64}}
##76798::Union{Val{false}, GenericAffExpr{Float64,VariableRef}, VariableRef}
##76797::Union{Float64, GenericAffExpr{Float64,VariableRef}}
##76796::Union{Float64, GenericAffExpr{Float64,VariableRef}}
##76795::ConstraintRef{Model,_A,ScalarShape} where _A
i@_15::Int64
q@_16::Union{Val{false}, GenericAffExpr{Float64,VariableRef}}
@_17::Union{Nothing, Tuple{Int64,Int64}}
##76799::Union{Val{false}, GenericAffExpr{Float64,VariableRef}}
i@_19::Int64
Body::Array{VariableRef,1}
…
…
5 ┄─ %52 = @_10::Tuple{Int64,Int64}::Tuple{Int64,Int64}
│ (i@_15 = Core.getfield(%52, 1))
│ %54 = Core.getfield(%52, 2)::Int64
│ %55 = q@_9::Union{Val{false}, GenericAffExpr{Float64,VariableRef}, VariableRef}
│ %56 = Base.getindex(used_values, i@_15)::VariableRef
│ (q@_9 = JuMP._destructive_add_with_reorder!(%55, %56))
│ (@_10 = Base.iterate(%47, %54))
│ %59 = (@_10 === nothing)::Bool
│ %60 = Base.not_int(%59)::Bool
└─── goto #7 if not %60
6 ── goto #5
7 ┄─ (##76798 = q@_9)
│ (##76797 = JuMP._destructive_add_with_reorder!(##76798, -1.0, 3))
│ (##76796 = JuMP._destructive_add_with_reorder!(##76797, 0))
│ %66 = m::Model
│ %67 = JuMP.build_constraint(getfield(JuMP, Symbol(“#_error#55”)){Symbol}(Core.Box(Any[:m, :(sum((used_values[i] for i = 1:num_values)) == 3)]), :constraint), ##76796, MathOptInterface.EqualTo{Float64}(0.0))::ScalarConstraint{GenericAffExpr{Float64,VariableRef},MathOptInterface.EqualTo{Float64}}
│ (##76795 = JuMP.add_constraint(%66, %67, “”))
│ ##76795
│ JuMP._valid_model(m, :m)
│ Core.NewvarNode(:(##76799))
│ %72 = Core.apply_type(JuMP.Val, false)::Core.Compiler.Const(Val{false}, false)
│ (q@_16 = (%72)())
│ %74 = (1:num_values)::Core.Compiler.PartialStruct(UnitRange{Int64}, Any[Core.Compiler.Const(1, false), Int64])
│ (@_17 = Base.iterate(%74))
│ %76 = (@_17 === nothing)::Bool
│ %77 = Base.not_int(%76)::Bool
└─── goto #10 if not %77
8 ┄─ %79 = @_17::Tuple{Int64,Int64}::Tuple{Int64,Int64}
│ (i@_19 = Core.getfield(%79, 1))
│ %81 = Core.getfield(%79, 2)::Int64
│ %82 = q@_16::Union{Val{false}, GenericAffExpr{Float64,VariableRef}}
│ %83 = Base.getindex(values, i@_19, 2)::Float64
│ %84 = Base.getindex(used_values, i@_19)::VariableRef
│ (q@_16 = JuMP._destructive_add_with_reorder!(%82, %83, %84))
│ (@_17 = Base.iterate(%74, %81))
│ %87 = (@_17 === nothing)::Bool
│ %88 = Base.not_int(%87)::Bool
└─── goto #10 if not %88
9 ── goto #8
10 ┄ (##76799 = q@_16)
│ %92 = m::Model
│ %93 = JuMP._throw_error_for_invalid_sense(getfield(JuMP, Symbol(“#_error#57”)){Symbol,Tuple{Symbol,Expr}}(:m, (:Max, :(sum(($(Expr(:escape, :(values[i, 2]))) * $(Expr(:escape, :(used_values[i]))) for i = 1:num_values))))), MathOptInterface.MAX_SENSE)::Core.Compiler.Const(MathOptInterface.MAX_SENSE, false)
│ JuMP.set_objective(%92, %93, ##76799)
│ ##76799
│ Main.optimize!(m)
└─── return used_values
Edited for formatting