How to get constraints from one JuMP model and use them in another JuMP model


#1

Hello,

I have two JuMP model like following:

m1=Model(solver=ClpSolver())
@variable(m1, x[1:3]>=0)
@constraint(m1, sum(x[i] for i in 1:3)>=0)
@constraint(m1, sum(x[i] for i in [1,3])>=0)
@constraint(m1, sum(x[i] for i in [2,3])>=0)
@objective(m1, Min, sum(x[i] for i in 1:3))

And the second model is

m2=Model(solver=IpoptSolver())
@variable(m2, x[1:3]>=0)
@NLconstraint(m2, sum(x[i]^2 for i in 1:3)>=0)
@NLconstraint(m2, sum(x[i]^2 for i in [1,3])>=0)
@NLconstraint(m2, sum(x[i]^2 for i in [2,3])>=0)
@NLobjective(m2, Min, sum(x[i]^2 for i in 1:3))

Now I want to add last two constraints of model “m1” to model “m2”, that is I want to make model “m2” looks like the following:

m2=Model(solver=IpoptSolver())
@variable(m2, x[1:3]>=0)
@NLconstraint(m2, sum(x[i]^2 for i in 1:3)>=0)
@NLconstraint(m2, sum(x[i]^2 for i in [1,3])>=0)
@NLconstraint(m2, sum(x[i]^2 for i in [2,3])>=0)
@constraint(m2, sum(x[i] for i in [1,3])>=0)
@constraint(m2, sum(x[i] for i in [2,3])>=0)
@NLobjective(m2, Min, sum(x[i]^2 for i in 1:3))

I do not know how to do this. I will appreciate your opinion/suggestion on this issue. Thank you in advance.


#2

In general, no. Constraints are tied to a model and cannot be shared. Why do you want to do this?

If you want to add identical constraints to different models and you don’t want to write it out twice, we suggest using a function like:

function add_constraint(model, indices, lower_bound)
    x = model[:x]
    @constraint(model, sum(x[i] for i in indices) >= lower_bound)
end

add_constraint(m1, [2, 3], 10)
add_constraint(m2, [2, 3], 10)

P.s. you can put format code by enclosing it in triple backticks like so:

```julia
Code goes here
```


#3

Thank you very much for your reply on the constraint adding issue. Thanks again for showing me the proper way of code formatting.


#4

Since I had two models and they share some identical constraints. Is there anyway to extract sparse matrix corresponding to linear constraints of a JuMP model? Then later I can use that matrix to add constraints in another JuMP model. Can I use functions like MathProgBase. getconstrmatrix(m::Model)?


#5

You will need to pass MathProgBase.getconstrmatrix(JuMP.internalmodel(model)).

Note that a few caveats apply

  • you will need to call solve(model) or JuMP.build(model) first
  • some solvers won’t support getconstrmatrix
  • this will not work in the upcoming release of JuMP

Another approach, which will also break in the upcoming release of JuMP, is to look through the
model.linconstr field in a JuMP model. It stores everything you need.


#6

Thank you very much for your reply. You are right as I checked
MathProgBase.getconstrmatrix(JuMP.internalmodel(model))
method fails while I was using Ipopt solver. As you said getconstrmatrix will not work from upcoming release of JuMP, so its better to not rely on this method.

By this time, I got a solution method of my stated problem. Its the following:

A=JuMP.prepConstrMatrix(m1)
n=MathProgBase.numconstr(m1)

for i in (n-1):n
    @constraint(m2, A[i:i,:]*x[1:3].>=0)
end

Its solves the problem apparently but I cannot guarantee its correctness. Here I could not put constraints bound (i.e., lower bound or upper bound) automatically. Do you have any suggestion about the constraints bounds? And also I could not find way to get model.linconstr field. Thanks.


#7

Ipopt (or any nonlinear solver) also handles things differently.

The real question should be: Why do you want to do this? And can you change your code to avoid doing this?