Juniper integer-objective fails on specific parameters

Simple sum-of-squares toy example, succeeds with 5 variables, stack-trace with 6 variables.

I know it’s sort of a silly example, but it feels to me like the behaviour should be consistent between problem_size = 5 and 6. What’s my next steps here? Report a bug? If so, where?

Thanks.

Code:

import HiGHS
import Ipopt
import Juniper

using JuMP

function test()

    optimizer = Juniper.Optimizer
    nl_solver= optimizer_with_attributes(Ipopt.Optimizer,
                                         "print_level" => 0)
    mip_solver = optimizer_with_attributes(HiGHS.Optimizer,
                                           "output_flag" => true)
    model = Model(optimizer_with_attributes(
        optimizer,
        "nl_solver"=>nl_solver,
        "mip_solver"=>mip_solver,
        "log_levels"=>[:Info, :Table, :Timing, :AllOptions]))

    # 6 fails. 5 works.
    problem_size = 6

    # x .>= 0, sum(x) >= 4
    @variable(model, x[1:problem_size], integer=true)
    @constraint(model, x .>= zeros(Int, problem_size))
    @constraint(model, sum(x[i] for i in 1:problem_size) >= 4)

    # Minimize sum(x.^2)
    # Works if integer = false.
    @variable(model, x_squared[1:problem_size], integer=true)
    for i in 1:problem_size
        @NLconstraint(model, x_squared[i] == x[i] ^ 2)
    end

    @NLobjective(model, Min,
                 x_squared[1]
                 + x_squared[2]
                 + x_squared[3]
                 + x_squared[4]
                 + x_squared[5]
                 + x_squared[6])

    # Also fails.
    #@NLobjective(model, Min, sum(x_squared[i] for i in 1:problem_size))

    optimize!(model)

    #=
    @show termination_status(model)
    @show primal_status(model)
    solution_summary(model)
    println(value.(model[:x]))
    =#

    return model

end

@time m = test()

Stacktrace:

ERROR: MethodError: no method matching operate(::typeof(-), ::Type{Int64}, ::MathOptInterface.ScalarAffineFunction{Int64}, ::MathOptInterface.ScalarAffineFunction{Float64})
Closest candidates are:
  operate(::typeof(+), ::Type{T}, ::Any, ::Any, ::Any, ::Any...) where T at ~/.julia/packages/MathOptInterface/FHFUH/src/Utilities/functions.jl:1608
  operate(::typeof(-), ::Type{T}, ::MathOptInterface.ScalarAffineFunction{T}) where T at ~/.julia/packages/MathOptInterface/FHFUH/src/Utilities/functions.jl:1674
  operate(::Union{typeof(+), typeof(-)}, ::Type{T}, ::MathOptInterface.ScalarAffineFunction{T}, ::MathOptInterface.ScalarQuadraticFunction{T}) where T at ~/.julia/packages/MathOptInterface/FHFUH/src/Utilities/functions.jl:1691
  ...
Stacktrace:
  [1] -(arg::MathOptInterface.ScalarAffineFunction{Int64}, args::MathOptInterface.ScalarAffineFunction{Float64})                               
    @ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/FHFUH/src/Utilities/functions.jl:1776      
  [2] promote_operation_fallback(op::typeof(-), #unused#::Type{MathOptInterface.ScalarAffineFunction{Int64}}, #unused#::Type{MathOptInterface.ScalarAffineFunction{Float64}})                             
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/BOohi/src/interface.jl:37                                                               
  [3] promote_operation(::typeof(-), ::Type, ::Type)
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/BOohi/src/interface.jl:99                                                               
  [4] promote_operation_fallback(op::typeof(MutableArithmetics.sub_mul), #unused#::Type{MathOptInterface.ScalarAffineFunction{Int64}}, #unused#::Type{Float64}, #unused#::Type{MathOptInterface.VariableIndex})     
               
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/BOohi/src/interface.jl:69                                                               
  [5] promote_operation(::typeof(MutableArithmetics.sub_mul), ::Type, ::Type, ::Type)                                                                 
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/BOohi/src/interface.jl:99                                                               
  [6] mutability(::Type, ::Function, ::Type, ::Type, ::Type)
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/BOohi/src/interface.jl:232                                                              
  [7] mutability(::MathOptInterface.ScalarAffineFunction{Int64}, ::Function, ::MathOptInterface.ScalarAffineFunction{Int64}, ::Float64, ::MathOptInterface.VariableIndex)                                           
    
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/BOohi/src/interface.jl:240                                                              
  [8] operate!!(::typeof(MutableArithmetics.sub_mul), ::MathOptInterface.ScalarAffineFunction{Int64}, ::Float64, ::MathOptInterface.VariableIndex)
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/BOohi/src/rewrite.jl:88                                                                 
  [9] macro expansion
    @ ~/.julia/packages/MutableArithmetics/BOohi/src/rewrite.jl:288 [inlined]
 [10] generate_mip(optimizer::Juniper.Optimizer, m::Juniper.JuniperProblem, nlp_sol::Vector{Float64}, tabu_list::Juniper.TabuList, start_fpump::Float64)  
    @ Juniper ~/.julia/packages/Juniper/HEO6p/src/fpump.jl:74
 [11] fpump(optimizer::Juniper.Optimizer, m::Juniper.JuniperProblem)
    @ Juniper ~/.julia/packages/Juniper/HEO6p/src/fpump.jl:352
 [12] optimize!(model::Juniper.Optimizer)
    @ Juniper ~/.julia/packages/Juniper/HEO6p/src/MOI_wrapper/MOI_wrapper.jl:343                                                            
 [13] optimize!
    @ ~/.julia/packages/MathOptInterface/FHFUH/src/Bridges/bridge_optimizer.jl:348 [inlined]                                             
 [14] optimize!
    @ ~/.julia/packages/MathOptInterface/FHFUH/src/MathOptInterface.jl:81 [inlined]                                                                    
 [15] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Juniper.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float6
4}}})
    @ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/FHFUH/src/Utilities/cachingoptimizer.jl:313     
 [16] optimize!(model::Model; ignore_optimize_hook::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})                          
    @ JuMP ~/.julia/packages/JuMP/R2Knd/src/optimizer_interface.jl:161
 [17] optimize!
    @ ~/.julia/packages/JuMP/R2Knd/src/optimizer_interface.jl:143 [inlined]
 [18] test()
    @ Main ./REPL[506]:41
 [19] top-level scope
    @ ./timing.jl:220 [inlined]
 [20] top-level scope
    @ ./REPL[507]:0

Open an issue. That is a bug.

1 Like

Well I’m not crazy then. Against MOI? JuMP itself? Juniper? MutableArithmetics?

Thank you,

Juniper

1 Like

Cross-reference if anyone comes looking: https://github.com/lanl-ansi/Juniper.jl/issues/243

Thanks.

2 Likes

Why would you introduce the x_squared[i] variables instead of using x[i]^2 in the expressions of the functions?

Because my goal was to create a simple example reproducing this failure mode.

1 Like