How to add a constraint in a JuMP model using the obj function of another JuMP model

Hello,
I have the following JuMP model:

using JuMP
using MathProgBase
using Ipopt
model=Model(solver=IpoptSolver())
@variable(model, -100 <= x[1:5] <=100)
@constraint(model, sum(x[i] for i in 1:5) <= 50)
@NLconstraint(model, sum(x[i]^2 for i in 1:3) <= 50)
@NLobjective(model, Min, sum(x[i]^2 for i in 1:5))

I get the objective expression from the above model as below:

d = JuMP.NLPEvaluator(model)
MathProgBase.initialize(d, [:ExprGraph])
obj_expr=MathProgBase.obj_expr(d)

Now, I have a new model like this:

m=Model(solver=IpoptSolver())
@variable(m, -100 <= x[i=1:6] <= 100)
@constraint(m, sum(x[i] for i in 1:5) <=100)
@NLconstraint(m, sum(x[i]^2 for i in 1:5)<= 100)
@objectve(m, Min, sum(x[i] for i in 1:6))

And in the model “m” I need to add the following constraint:

JuMP.addNLconstraint(m, x[6]>= obj_expr)
or
JuMP.addNLconstraint(m, x[6]>=sum(x[i]^2 for i in 1:5) )

I have tried the following way:

expr=:(x[6]>=$(obj_expr))
JuMP.addNLconstraint(m, expr)

But it did not work. Can anyone help me with finding a way to add the constraint in model “m”. Thank you.
NOTE: I am using JuMPv0.18 and MathProgBase

Could you please elaborate? Did get an error message?

Do you have to use these versions, or could you upgrade to JuMP & MOI?

my process did not work because I got the following error message:

julia> exp= :(x[6]>= $(obj_expr))
:(x[6] >= x[1] ^ 2.0 + x[2] ^ 2.0 + x[3] ^ 2.0 + x[4] ^ 2.0 + x[5] ^ 2.0)

julia> JuMP.addNLconstraint(m, exp)
ERROR: Unrecognized expression x[6]. JuMP variable objects and input coefficients should be spliced directly into expressions.
Stacktrace:
 [1] spliceref at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:270 [inlined]
 [2] (::getfield(JuMP, Symbol("##138#139")){Model})(::Expr) at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:272
 [3] iterate at .\generator.jl:47 [inlined]
 [4] collect_to!(::Array{Symbol,1}, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}, ::Int64, ::Int64) at .\array.jl:651
 [5] collect_to_with_first!(::Array{Symbol,1}, ::Symbol, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}, ::Int64) at .\array.jl:630
 [6] _collect(::Array{Any,1}, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}, ::Base.EltypeUnknown, ::Base.HasShape{1}) at .\array.jl:624
 [7] collect_similar(::Array{Any,1}, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}) at .\array.jl:548
 [8] map(::Function, ::Array{Any,1}) at .\abstractarray.jl:2073
 [9] spliceref at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:272 [inlined]
 [10] JuMP.NonlinearExprData(::Model, ::Expr) at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:261
 [11] addNLconstraint(::Model, ::Expr) at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\nlp.jl:1439
 [12] top-level scope at none:0

And for the JuMP version and MathProgBase, I do want to upgrade to JuMPv0.20 and MathOptInterface but for some time I need to bear with the versions I am using. I am sorry for your inconvenience with the older versions. Thank you.

I’m not sure about the error message, but why don’t you

@NLconstraint(m, x[6]>= obj_expr)

to avoid some macro/quoting/expr issue.

I’m not sure whether that will work either, because the variable objects in JuMP contain references to the model in which they are created, right?

Also, is the code you posted now just a simplified example? For quadratic expressions you could also use the @constraint macro, right?

@NLconstraint(m, x[6]>= obj_expr)

the above line gives the following error:

julia> @NLconstraint(m,x[6]>=  obj_exp)
ERROR: Unexpected object x[6] >= x[1] ^ 2.0 + x[2] ^ 2.0 + x[3] ^ 2.0 + x[4] ^ 2.0 + x[5] ^ 2.0 in nonlinear expression.
Stacktrace:
 [1] parseNLExpr_runtime(::Model, ::Expr, ::Array{ReverseDiffSparse.NodeData,1}, ::Int64, ::Array{Float64,1}) at
C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:207
 [2] top-level scope at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:249
 [3] top-level scope at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\macros.jl:1352

And your are right the obj_expr expression has variables which are referenced to the model “model”. So how could I dereference the obj_expr to the variables of model “m”?

But even if I did dereferance the obj_expr with the model “m” variables I still get error messages. The code I used for dereferencing is the following:

#Used from https://github.com/lanl-ansi/Alpine.jl
function expr_dereferencing!(expr, m)
    for i in 2:length(expr.args)
        if isa(expr.args[i], Union{Float64,Int64})
            k = 0
        elseif expr.args[i].head == :ref
            @assert isa(expr.args[i].args[2], Int)
            expr.args[i] = Variable(m, expr.args[i].args[2])
        elseif expr.args[i].head == :call
            expr_dereferencing!(expr.args[i], m)
        else
            error("expr_dereferencing :: Unexpected term in expression tree.")
        end
    end
end

And the error message is the following:

julia> expr_dereferencing!(obj_expr, m)
julia> exp= :(x[6]>= $(obj_expr))
:(x[6] >= x[1] ^ 2.0 + x[2] ^ 2.0 + x[3] ^ 2.0 + x[4] ^ 2.0 + x[5] ^ 2.0)

julia> JuMP.addNLconstraint(m, exp)
ERROR: Unrecognized expression x[6]. JuMP variable objects and input coefficients should be spliced directly into expressions.
Stacktrace:
 [1] spliceref at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:270 [inlined]
 [2] (::getfield(JuMP, Symbol("##138#139")){Model})(::Expr) at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:272
 [3] iterate at .\generator.jl:47 [inlined]
 [4] collect_to!(::Array{Symbol,1}, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}, ::Int64, ::Int64) at .\array.jl:651
 [5] collect_to_with_first!(::Array{Symbol,1}, ::Symbol, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}, ::Int64) at .\array.jl:630
 [6] _collect(::Array{Any,1}, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}, ::Base.EltypeUnknown, ::Base.HasShape{1}) at .\array.jl:624
 [7] collect_similar(::Array{Any,1}, ::Base.Generator{Array{Any,1},getfield(JuMP, Symbol("##138#139")){Model}}) at .\array.jl:548
 [8] map(::Function, ::Array{Any,1}) at .\abstractarray.jl:2073
 [9] spliceref at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:272 [inlined]
 [10] JuMP.NonlinearExprData(::Model, ::Expr) at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\parsenlp.jl:261
 [11] addNLconstraint(::Model, ::Expr) at C:\Users\mahbu\.julia\packages\JuMP\I7whV\src\nlp.jl:1439
 [12] top-level scope at none:0

See the docs: https://www.juliaopt.org/JuMP.jl/v0.20.0/nlp/#Raw-expression-input-1

As it says, the variables need to be directly spliced into the expressions. So instead of

exp = :(x[6])

you need

exp = :($(x[6]))
1 Like

Thank you @odow. You have solved my problem.