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

**URL:** <https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729>\
**Category:** Optimization (Mathematical)\
**Created:** [February 13, 2019, 3:27am UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729 "2019-02-13T03:27:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mahbubar06](https://avatars.discourse-cdn.com/v4/letter/m/f07891/32.png) [@Mahbubar06](https://discourse.julialang.org/u/Mahbubar06)\
**Post date:** [February 13, 2019, 3:27am UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/1 "2019-02-13T03:27:40Z")

</div>

Hello,

I have two JuMP model like following:

```julia
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

```julia
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:

```julia
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.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 13, 2019, 2:37pm UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/2 "2019-02-13T14:37:09Z")

</div>

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:

```julia
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`  
`````

---

<div class="post-metadata">

**Author:** ![Mahbubar06](https://avatars.discourse-cdn.com/v4/letter/m/f07891/32.png) [@Mahbubar06](https://discourse.julialang.org/u/Mahbubar06)\
**Post date:** [February 13, 2019, 3:10pm UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/3 "2019-02-13T15:10:24Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Mahbubar06](https://avatars.discourse-cdn.com/v4/letter/m/f07891/32.png) [@Mahbubar06](https://discourse.julialang.org/u/Mahbubar06)\
**Post date:** [February 13, 2019, 3:27pm UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/4 "2019-02-13T15:27:43Z")

</div>

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)?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 14, 2019, 8:25pm UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/5 "2019-02-14T20:25:39Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Mahbubar06](https://avatars.discourse-cdn.com/v4/letter/m/f07891/32.png) [@Mahbubar06](https://discourse.julialang.org/u/Mahbubar06)\
**Post date:** [February 14, 2019, 10:57pm UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/6 "2019-02-14T22:57:59Z")

</div>

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:

```julia
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.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 15, 2019, 12:27am UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/7 "2019-02-15T00:27:48Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![jacob-roth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacob-roth/32/1862_2.png) [@jacob-roth](https://discourse.julialang.org/u/jacob-roth)\
**Post date:** [December 19, 2024, 1:26am UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/8 "2024-12-19T01:26:32Z")

</div>

Somewhat related: if I have a collection of JuMP models `i = 1...n` and I want to “combine” (exact way tbd) them into a single model, is there a “best” or suggested way of doing this? My attempt was to collect the expressions of variables/objectives/constraints and try to remap them. I’ve been able to extract the objectives as expressions and remap variables from the collection of models to a new monolithic model. However, I have trouble on constraints. E.g., if a model `i` has `@variable(modeli, y[1] >=0)` and `@constraint(modeli, y[1] >= 1)`, my method is not sure how to handle this. Is there a nice way of doing this for constraints?

MWE:

```julia
using JuMP, OrderedCollections
#=
start utilities --------------------------------------------------------------------------------------------------------------
=#
function substitute_variables(expr, mapping::Dict{JuMP.VariableRef, JuMP.VariableRef})
    if expr isa JuMP.QuadExpr
        # Handle Quadratic Expressions
        new_quad_terms = OrderedCollections.OrderedDict(
            UnorderedPair(get(mapping, pair.a, pair.a), get(mapping, pair.b, pair.b)) => coef
            for (pair, coef) in expr.terms
        )
        # Recursively substitute the affine part
        new_aff_expr = substitute_variables(expr.aff, mapping)
        return JuMP.QuadExpr(new_aff_expr, new_quad_terms)
    elseif expr isa JuMP.AffExpr
        # Handle Affine Expressions
        new_terms = OrderedCollections.OrderedDict(
            get(mapping, var, var) => coef for (var, coef) in expr.terms
        )
        return JuMP.AffExpr(expr.constant, new_terms...)
    elseif expr isa JuMP.VariableRef
        # Handle Single Variables
        return get(mapping, expr, expr)
    else
        # nonlinear expressions...see: https://jump.dev/JuMP.jl/stable/manual/nonlinear/#Nonlinear-expressions-in-detail
        error("Unsupported expression type: $(typeof(expr))")
    end
end
#=
end utilities --------------------------------------------------------------------------------------------------------------
=#

# Step 1: Define individual models
n = 3 # Number of individual models
models = []
for i in 1:n
    model = Model()
    @variable(model, y[1:2] >= 0) # Each model has a variable array `y` of size 2
    @objective(model, Min, y[1]^2 + i * y[2]) # Example objective
    @constraint(model, y[1] + i <= 10) # Example constraint
    @constraint(model, y[2] + i >= 10) # Example constraint
    push!(models, model)
end

# Step 2: Create the big model
big_model = Model()

# Step 3: Create variables for the big model and build a variable mapping
variable_mapping = Dict{JuMP.VariableRef, JuMP.VariableRef}()

for (model_idx, model) in enumerate(models)
    # Iterate over all variables in the model
    for var in all_variables(model)
        # Get the variable's symbolic name
        var_name = Symbol(var) # e.g., "y[1]", "y[2]"

        # Create a unique name for the big model variable
        unique_var_name = Symbol("m$(model_idx)_$(var_name)")

        # Get the variable's properties
        lb = JuMP.has_lower_bound(var) ? JuMP.lower_bound(var) : -Inf
        ub = JuMP.has_upper_bound(var) ? JuMP.upper_bound(var) : Inf
        is_bin = JuMP.is_binary(var)
        is_int = JuMP.is_integer(var)

        # Create the variable in the big model with the same properties
        if JuMP.has_lower_bound(var) && JuMP.has_upper_bound(var)
            new_var = @variable(big_model, lower_bound=lb, upper_bound=ub, base_name=string(unique_var_name))
        elseif JuMP.has_lower_bound(var) && !JuMP.has_upper_bound(var)
            new_var = @variable(big_model, lower_bound=lb, base_name=string(unique_var_name))
        elseif !JuMP.has_lower_bound(var) && JuMP.has_upper_bound(var)
            new_var = @variable(big_model, upper_bound=ub, base_name=string(unique_var_name))
        else
            new_var = @variable(big_model, base_name=string(unique_var_name))
        end
        
        # Map the small model variable to the newly created big model variable
        variable_mapping[var] = new_var
    end
end

# Verify the variable mapping
println("Variable Mapping:")
for (small_var, big_var) in variable_mapping
    println("Small model variable $small_var -> Big model variable $big_var")
end

# -------------------------------------------------------------------------------------------------------------------------------
# Step 4: Combine objectives and constraints from all models
combined_objective = 0.0 # Initialize the combined objective

for (model_idx, model) in enumerate(models)
    # Extract the objective function
    obj_expr = JuMP.objective_function(model)

    # Perform substitution for variables using the variable_mapping
    substituted_obj_expr = substitute_variables(obj_expr, variable_mapping)

    # Add the substituted objective to the combined objective
    combined_objective += substituted_obj_expr
end

# Add the combined objective to the big model
@objective(big_model, Min, combined_objective)

# Step 5: Extract and add constraints from individual models to the big model
for (model_idx, model) in enumerate(models)
    println("model=$model_idx")
    for (con_idx, con) in enumerate(JuMP.all_constraints(model, include_variable_in_set_constraints=true))
        println("con=$con, $con_idx")
        # Get the full constraint object
        constraint_obj = JuMP.constraint_object(con)

        # Access the left-hand side (expression) and right-hand side (set)
        con_expr = constraint_obj.func # The function or expression on the LHS
        @show con_expr
        con_set = constraint_obj.set # The set defining the constraint (e.g., `<=`, `>=`, `==`)
        @show con_set

        # Substitute variables in the constraint expression
        substituted_con_expr = substitute_variables(con_expr, variable_mapping)

        # Add the substituted constraint to the big model
        @constraint(big_model, substituted_con_expr in con_set)
    end
end

# Verify the big model
println("Big Model Objective:")
println(combined_objective)

println("Big Model Constraints:")
for con in JuMP.all_constraints(big_model)
    println(con)
end

```

gives an error

```julia
model=1
con=y[2] ≥ 9, 1
con_expr = y[2]
con_set = MathOptInterface.GreaterThan{Float64}(9.0)
con=y[1] ≤ 9, 2
con_expr = y[1]
con_set = MathOptInterface.LessThan{Float64}(9.0)
con=y[1] ≥ 0, 3
con_expr = y[1]
con_set = MathOptInterface.GreaterThan{Float64}(0.0)
ERROR: MathOptInterface.LowerBoundAlreadySet{MathOptInterface.GreaterThan{Float64}, MathOptInterface.GreaterThan{Float64}}: Cannot add `VariableIndex`-in-`MathOptInterface.GreaterThan{Float64}` constraint for variable MOI.VariableIndex(1) as a `VariableIndex`-in-`MathOptInterface.GreaterThan{Float64}` constraint was already set for this variable and both constraints set a lower bound.
Stacktrace:
  [1] _throw_if_lower_bound_set_inner(variable::MathOptInterface.VariableIndex, S2::Type, mask::UInt16, T::Type)
    @ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/gLl4d/src/Utilities/variables_container.jl:120
  [2] _throw_if_lower_bound_set
    @ ~/.julia/packages/MathOptInterface/gLl4d/src/Utilities/variables_container.jl:131 [inlined]
  [3] add_constraint
    @ ~/.julia/packages/MathOptInterface/gLl4d/src/Utilities/variables_container.jl:267 [inlined]
  [4] add_constraint
    @ ~/.julia/packages/MathOptInterface/gLl4d/src/Utilities/model.jl:348 [inlined]
  [5] add_constraint
    @ ~/.julia/packages/MathOptInterface/gLl4d/src/Utilities/universalfallback.jl:835 [inlined]
  [6] add_constraint(m::MathOptInterface.Utilities.CachingOptimizer{…}, func::MathOptInterface.VariableIndex, set::MathOptInterface.GreaterThan{…})
    @ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/gLl4d/src/Utilities/cachingoptimizer.jl:551
  [7] _moi_add_constraint(model::MathOptInterface.Utilities.CachingOptimizer{…}, f::MathOptInterface.VariableIndex, s::MathOptInterface.GreaterThan{…})
    @ JuMP ~/.julia/packages/JuMP/V9nZm/src/constraints.jl:1013
  [8] add_constraint(model::Model, con::ScalarConstraint{VariableRef, MathOptInterface.GreaterThan{Float64}}, name::String)
    @ JuMP ~/.julia/packages/JuMP/V9nZm/src/constraints.jl:1036
  [9] macro expansion
    @ ~/.julia/packages/JuMP/V9nZm/src/macros/@constraint.jl:173 [inlined]
 [10] macro expansion
    @ ~/.julia/packages/JuMP/V9nZm/src/macros.jl:393 [inlined]
 [11] top-level scope
    @ ./REPL[165]:18
Some type information was truncated. Use `show(err)` to see complete types.

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [December 19, 2024, 1:30am UTC](https://discourse.julialang.org/t/how-to-get-constraints-from-one-jump-model-and-use-them-in-another-jump-model/20729/9 "2024-12-19T01:30:53Z")

</div>

> Somewhat related: if I have a collection of JuMP models `i = 1...n` and I want to “combine” (exact way tbd) them into a single model, is there a “best” or suggested way of doing this?

You cannot combine JuMP models. Can you start a new thread and describe why you want to do this?
