lanl-ansi / Juniper.jl

A JuMP-based Nonlinear Integer Program Solver
https://lanl-ansi.github.io/Juniper.jl/stable/
MIT License
179 stars 22 forks source link

constraint was already set for this variable and both constraints set a lower bound. #239

Closed lilianping closed 2 years ago

lilianping commented 2 years ago

I got an error when doing mixed integer nonlinear optimization with juniper, so I did a small test, what is the problem?

this is code:

optimizer = Alpine.Optimizer
nl_solver= optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
mip_solver = optimizer_with_attributes(GLPK.Optimizer, "output_flag" => false)
m = Model(optimizer_with_attributes(optimizer, "nl_solver"=>nl_solver, "mip_solver"=>mip_solver))

@variable(m, objvar)
i_Idx = Any[1, 2]
@variable(m, 1 <= i[i_Idx] <= 5, Int)

@constraint(m, e1, -3*i[1] - 2*i[2] + objvar == 0.0)
@NLconstraint(m, e2, -i[1]*i[2] <= -3.5)

@objective(m, Min, objvar)
println("Solving...")
optimize!(room)
solution_summary(room)
println("min temp: ", objective_value(m))`

this is error:

Solving...
nl_solver   : MathOptInterface.OptimizerWithAttributes(Ipopt.Optimizer, Pair{MathOptInterface.AbstractOptimizerAttribute, Any}[MathOptInterface.RawParameter("print_level") => 0])
mip_solver  : MathOptInterface.OptimizerWithAttributes(GLPK.Optimizer, Pair{MathOptInterface.AbstractOptimizerAttribute, Any}[MathOptInterface.RawParameter("output_flag") => false])
log_levels  : [:Options, :Table, :Info]

#Variables: 161
#IntBinVar: 80
Obj Sense: Min

Incumbent using start values: 3055.5626136260244
Status of relaxation: LOCALLY_SOLVED
Time for relaxation: 0.24300003051757812
Relaxation Obj: 1312.7042971790263

       MIPobj              NLPobj       Time 
=============================================
         -                  0.0          0.1 
MathOptInterface.LowerBoundAlreadySet{MathOptInterface.EqualTo{Float64}, MathOptInterface.EqualTo{Float64}}: Cannot add `SingleVariable`-in`MathOptInterface.EqualTo{Float64}` constraint for variable MathOptInterface.VariableIndex(2) as a `SingleVariable`-in`MathOptInterface.EqualTo{Float64}` constraint was already set for this variable and both constraints set a lower bound.

Stacktrace:
  [1] add_constraint(model::Ipopt.Optimizer, v::MathOptInterface.SingleVariable, eq::MathOptInterface.EqualTo{Float64})
    @ Ipopt C:\Users\86198\.julia\packages\Ipopt\vtrOr\src\MOI_wrapper.jl:816
  [2] _broadcast_getindex_evalf
    @ .\broadcast.jl:648 [inlined]
  [3] _broadcast_getindex
    @ .\broadcast.jl:621 [inlined]
  [4] getindex
    @ .\broadcast.jl:575 [inlined]
  [5] macro expansion
    @ .\broadcast.jl:984 [inlined]
  [6] macro expansion
    @ .\simdloop.jl:77 [inlined]
  [7] copyto!
    @ .\broadcast.jl:983 [inlined]
  [8] copyto!
    @ .\broadcast.jl:936 [inlined]
  [9] copy
    @ .\broadcast.jl:908 [inlined]
 [10] materialize
    @ .\broadcast.jl:883 [inlined]
 [11] add_constraints(model::Ipopt.Optimizer, funcs::Vector{MathOptInterface.SingleVariable}, sets::Vector{MathOptInterface.EqualTo{Float64}})
    @ MathOptInterface C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\constraints.jl:229
 [12] add_constraints(b::MathOptInterface.Bridges.LazyBridgeOptimizer{Ipopt.Optimizer}, f::Vector{MathOptInterface.SingleVariable}, s::Vector{MathOptInterface.EqualTo{Float64}})
    @ MathOptInterface.Bridges C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Bridges\bridge_optimizer.jl:1510
 [13] copy_constraints(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{Ipopt.Optimizer}, src::Juniper.FixVariables{Float64, Juniper.IntegerRelaxation{Juniper.Optimizer}}, idxmap::MathOptInterface.Utilities.IndexMap, cis_src::Vector{MathOptInterface.ConstraintIndex{MathOptInterface.SingleVariable, MathOptInterface.EqualTo{Float64}}}, filter_constraints::Nothing)
    @ MathOptInterface.Utilities C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:419
 [14] copy_constraints(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{Ipopt.Optimizer}, src::Juniper.FixVariables{Float64, Juniper.IntegerRelaxation{Juniper.Optimizer}}, idxmap::MathOptInterface.Utilities.IndexMap, cis_src::Vector{MathOptInterface.ConstraintIndex{MathOptInterface.SingleVariable, MathOptInterface.EqualTo{Float64}}})
    @ MathOptInterface.Utilities C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:409
 [15] pass_constraints(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{Ipopt.Optimizer}, src::Juniper.FixVariables{Float64, Juniper.IntegerRelaxation{Juniper.Optimizer}}, copy_names::Bool, idxmap::MathOptInterface.Utilities.IndexMap, single_variable_types::Vector{DataType}, single_variable_indices::Vector{Vector{T} where T}, vector_of_variables_types::Vector{DataType}, vector_of_variables_indices::Vector{Any}, pass_cons::typeof(MathOptInterface.Utilities.copy_constraints), pass_attr::typeof(MathOptInterface.set); filter_constraints::Nothing)
    @ MathOptInterface.Utilities C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:502
 [16] default_copy_to(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{Ipopt.Optimizer}, src::Juniper.FixVariables{Float64, Juniper.IntegerRelaxation{Juniper.Optimizer}}, copy_names::Bool, filter_constraints::Nothing)
    @ MathOptInterface.Utilities C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:714
 [17] #automatic_copy_to#127
    @ C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:24 [inlined]
 [18] #copy_to#4
    @ C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Bridges\bridge_optimizer.jl:401 [inlined]
 [19] generate_real_nlp(optimizer::Juniper.Optimizer, m::Juniper.JuniperProblem, sol::Vector{Float64}; random_start::Bool)
    @ Juniper C:\Users\86198\.julia\packages\Juniper\8wso7\src\fpump.jl:161
 [20] generate_real_nlp(optimizer::Juniper.Optimizer, m::Juniper.JuniperProblem, sol::Vector{Float64})
    @ Juniper C:\Users\86198\.julia\packages\Juniper\8wso7\src\fpump.jl:154
 [21] fpump(optimizer::Juniper.Optimizer, m::Juniper.JuniperProblem)
    @ Juniper C:\Users\86198\.julia\packages\Juniper\8wso7\src\fpump.jl:354
 [22] optimize!(model::Juniper.Optimizer)
    @ Juniper C:\Users\86198\.julia\packages\Juniper\8wso7\src\MOI_wrapper\MOI_wrapper.jl:283
 [23] optimize!(b::MathOptInterface.Bridges.LazyBridgeOptimizer{Juniper.Optimizer})
    @ MathOptInterface.Bridges C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Bridges\bridge_optimizer.jl:319
 [24] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}})
    @ MathOptInterface.Utilities C:\Users\86198\.julia\packages\MathOptInterface\YDdD3\src\Utilities\cachingoptimizer.jl:252
 [25] optimize!(model::Model, optimizer_factory::Nothing; bridge_constraints::Bool, ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ JuMP C:\Users\86198\.julia\packages\JuMP\klrjG\src\optimizer_interface.jl:185
 [26] optimize! (repeats 2 times)
    @ C:\Users\86198\.julia\packages\JuMP\klrjG\src\optimizer_interface.jl:157 [inlined]
 [27] top-level scope
    @ In[31]:2
 [28] eval
    @ .\boot.jl:360 [inlined]
 [29] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base .\loading.jl:1094
ccoffrin commented 2 years ago

After making a few minor fixes, I tried your model with the latest versions of JuMP v0.23, Juniper v0.9, Ipopt v1.0 and it seemed to work.

I noticed in your example that you have optimizer = Alpine.Optimizer This makes me wonder if this issue is related to that solver? If so please close this one and repost a working example at, https://github.com/lanl-ansi/Alpine.jl

Here is the code I tested,

using JuMP, Juniper, Ipopt

m = Model(Juniper.Optimizer)
set_optimizer_attribute(m, "nl_solver", optimizer_with_attributes(Ipopt.Optimizer, "tol"=>1e-4, "print_level"=>0))

@variable(m, objvar)
i_Idx = Any[1, 2]
@variable(m, 1 <= i[i_Idx] <= 5, Int)

@constraint(m, e1, -3*i[1] - 2*i[2] + objvar == 0.0)
@constraint(m, e2, -i[1]*i[2] <= -3.5)

@objective(m, Min, objvar)
println("Solving...")
optimize!(m)
solution_summary(m)

solution summary output,

julia> solution_summary(m)
* Solver : Juniper

* Status
  Termination status : LOCALLY_SOLVED
  Primal status      : FEASIBLE_POINT
  Dual status        : FEASIBLE_POINT
  Message from the solver:
  "LOCALLY_SOLVED"

* Candidate solution
  Objective value      : 1.00000e+01
  Objective bound      : 1.00000e+01

* Work counters
  Solve time (sec)   : 2.18911e-01
lilianping commented 2 years ago

After making a few minor fixes, I tried your model with the latest versions of JuMP v0.23, Juniper v0.9, Ipopt v1.0 and it seemed to work.

I noticed in your example that you have optimizer = Alpine.Optimizer This makes me wonder if this issue is related to that solver? If so please close this one and repost a working example at, https://github.com/lanl-ansi/Alpine.jl

Here is the code I tested,

using JuMP, Juniper, Ipopt

m = Model(Juniper.Optimizer)
set_optimizer_attribute(m, "nl_solver", optimizer_with_attributes(Ipopt.Optimizer, "tol"=>1e-4, "print_level"=>0))

@variable(m, objvar)
i_Idx = Any[1, 2]
@variable(m, 1 <= i[i_Idx] <= 5, Int)

@constraint(m, e1, -3*i[1] - 2*i[2] + objvar == 0.0)
@constraint(m, e2, -i[1]*i[2] <= -3.5)

@objective(m, Min, objvar)
println("Solving...")
optimize!(m)
solution_summary(m)

solution summary output,

julia> solution_summary(m)
* Solver : Juniper

* Status
  Termination status : LOCALLY_SOLVED
  Primal status      : FEASIBLE_POINT
  Dual status        : FEASIBLE_POINT
  Message from the solver:
  "LOCALLY_SOLVED"

* Candidate solution
  Objective value      : 1.00000e+01
  Objective bound      : 1.00000e+01

* Work counters
  Solve time (sec)   : 2.18911e-01

Thank you, I was originally using Julia1.6.1, after I updated to 1.7 and upgraded all the packages, it worked, and also, alpine appeared because I didn't find any relevant tutorials for juniper, so I was using alpine's Example learning, in the process of learning, after I used juniper to make an error, I used alpine to test it again. Is there any example of mixed integer nonlinear programming related to juniper? In addition, thank you again for your help

ccoffrin commented 2 years ago

I am glad to hear it! I am going to close this issue because there is no known bug.

Regarding tutorials, Juniper supports almost any model that can be written in the JuMP modeling language. So I would suggest having a look at those. For example here are the ones on nonlinear programming, https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/introduction/

If have you have suggestions for improving any aspect of the JuMP documentation you can post your ideas here, https://discourse.julialang.org/t/please-suggest-improvements-to-the-jump-documentation/55596

CC @odow