Why after copying a JuMP model it does not own the initial model variables?

I am working on a MIP problem including two variables y[1] and y[2].

  • y[1] is a binary

  • y[2] is a positive real number

First I relax the binary restriction by 0 <=y[1] and -y[1] >= -1 and solve the relaxation.

c1 = [-2 ; 4]
A1 = [-3 1 ; -1 0 ]
b1 = [-2 ; -1]
sub = Model(GLPK.Optimizer)
@variable(sub, 0 ≤ y[1:2] )
@objective(sub, Min, c1' * y )
@constraint(sub, A1 * y .≥ b1)
optimize!(sub)
yᵏ = value.(y)
yᵏ = round.(yᵏ , digits = 2)
print(sub)
@show yᵏ;

The output of above code is:

yᵏ = [0.67, 0.0]

Now since y[1] = 0.67 is fractional I want to define two new linear models and call them sub_0 and sub_1.

Everything in sub_0 is same as sub except it has the extra constraint -y[0] >= 0.
Everything in sub_1 is same as sub except it has the extra constraint y[1] >= 1.

I script the below code for developing sub_0

sub_0 = copy(sub)
@show all_variables(sub_0)
c2 = @constraint(sub_0, - y[1] ≥ 0 )

and see this error:

all_variables(sub_0) = VariableRef[y[1], y[2]]
VariableNotOwned{VariableRef}(y[1])

Stacktrace:
 [1] check_belongs_to_model
   @ C:\Users\e29115\.julia\packages\JuMP\klrjG\src\variables.jl:208 [inlined]
 [2] check_belongs_to_model(a::AffExpr, model::Model)
   @ JuMP C:\Users\e29115\.julia\packages\JuMP\klrjG\src\aff_expr.jl:499
 [3] check_belongs_to_model
   @ C:\Users\e29115\.julia\packages\JuMP\klrjG\src\constraints.jl:453 [inlined]
 [4] add_constraint(model::Model, con::ScalarConstraint{AffExpr, MathOptInterface.GreaterThan{Float64}}, name::String)
   @ JuMP C:\Users\e29115\.julia\packages\JuMP\klrjG\src\constraints.jl:557
 [5] top-level scope
   @ In[29]:3
 [6] eval
   @ .\boot.jl:360 [inlined]
 [7] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base .\loading.jl:1116

Can somebody please help with this?

This minimal error-reproducing example

c1 = [-2 ; 4]
A1 = [-3 1 ; -1 0 ]
b1 = [-2 ; -1]
sub = Model()
@variable(sub, 0 ≤ y[1:2] )
@objective(sub, Min, c1' * y )
@constraint(sub, A1 * y .≥ b1)
sub_0 = copy(sub)
c2 = @constraint(sub_0, - y[1] ≥ 0 )

does not depend on solving the model, but on the fact that you are copying the model then trying to use the variable y[1], which belongs to the Model sub, with the Model sub_0.
I suppose your question is, how do you create a model copy that owns its own copy of the variable?

1 Like

So, you need to make the Julia variable y correspond to the JuMP variable y in Model sub_0:

y = sub_0[:y]

then you can use it to modify sub_0 using

c2 = @constraint(sub_0, - y[1] ≥ 0 )
1 Like

You can also use copy_model instead of copy to get a map that converts original models into their copied equivalents: Models · JuMP

c1 = [-2 ; 4]
A1 = [-3 1 ; -1 0 ]
b1 = [-2 ; -1]
sub = Model()
@variable(sub, 0 ≤ y[1:2] )
@objective(sub, Min, c1' * y )
@constraint(sub, A1 * y .≥ b1)
sub_0, index_map = copy_model(sub)
c2 = @constraint(sub_0, - index_map[y[1]] ≥ 0 )