Strange behavior with deepcopy

I’m getting a strange behavior with deepcopy. Deepcopy is still not supported? There is any way to copy JuMP model?

using JuMP, Clp

m = Model(solver = ClpSolver())
@variable(m, 0 <= x <= 2 )
@variable(m, 0 <= y <= 30 )
@objective(m, Max, 5x + 3*y )
@constraint(m, 1x + 5y <= 3.0 )
status = solve(m)
status ≠ :Optimal && erro(" status ≠ :Optimal $(status)")

m2 = deepcopy(m)
@constraint(m, 10*x + 15*y <= 3.0 ) # Add constraint to original problem
status = solve(m2)

And getting this error:

Array length must match number of rows in the model
chg_row_lower(::Clp.ClpCInterface.ClpModel, ::Array{Float64,1}) at ClpCInterface.jl:452
setconstrLB!(::Clp.ClpMathProgSolverInterface.ClpMathProgModel, ::Array{Float64,1}) at ClpSolverInterface.jl:131
#build#119(::Bool, ::Bool, ::JuMP.ProblemTraits, ::Function, ::JuMP.Model) at solvers.jl:337
(::JuMP.#kw##build)(::Array{Any,1}, ::JuMP.#build, ::JuMP.Model) at <missing>:0
#solve#116(::Bool, ::Bool, ::Bool, ::Array{Any,1}, ::Function, ::JuMP.Model) at solvers.jl:168
solve(::JuMP.Model) at solvers.jl:150
include_string(::String, ::String) at loading.jl:522
include_string(::String, ::String, ::Int64) at eval.jl:30
include_string(::Module, ::String, ::String, ::Int64, ::Vararg{Int64,N} where N) at eval.jl:34
(::Atom.##102#107{String,Int64,String})() at eval.jl:82
withpath(::Atom.##102#107{String,Int64,String}, ::Void) at utils.jl:30
withpath(::Function, ::String) at eval.jl:38
hideprompt(::Atom.##101#106{String,Int64,String}) at repl.jl:62
macro expansion at eval.jl:80 [inlined]
(::Atom.##100#105{Dict{String,Any}})() at task.jl:80

This doesn’t happen with copy(m).

You can’t use deepcopy on a JuMP model. Mostly because after solve it has a Clp model in internamModel and that leads to all kinds of issues.

Basically what is happening here is that m2 stores a pointer to the Clp model, so calling solve(m2) is equivalent to calling solve(m), but m2 doesn’t have the additional RHS information from the constraint you added.

1 Like

Ok. Thanks @odow!
There is any workaround? If I remove internamModel, for example?

Copy isn’t working for me either in JuMP 0.18.5, there is an issue with matrix constraints:

using JuMP
using CPLEX

m = Model(solver = CplexSolver())
@variable(m, 0 <= x <= 2 )
@variable(m, 0 <= y <= 30 )

@objective(m, Max, 5x + 3*y )
@constraint(m, 1x + 5y <= 3.0 )
@constraint(m, cons[i = 1:2, j=1:2], i*x + j*y <= 3.0 )
copy(m)
MethodError: no method matching copy(::Array{JuMP.ConstraintRef,2}, ::JuMP.Model)e[0m
Closest candidates are:
  copy(e[91m::JuMP.Variablee[39m, ::JuMP.Model) at /home/tas/.julia/v0.6/JuMP/src/JuMP.jl:502
  copy(e[91m::Voide[39m, ::JuMP.Model) at /home/tas/.julia/v0.6/JuMP/src/JuMP.jl:503
  copy(e[91m::JuMP.GenericAffExpr{Float64,JuMP.Variable}e[39m, ::JuMP.Model) at /home/tas/.julia/v0.6/JuMP/src/affexpr.jl:119
  ...
copy(::JuMP.Model) at JuMP.jl:300
include_string(::String, ::String) at loading.jl:522
include_string(::String, ::String, ::Int64) at eval.jl:30
include_string(::Module, ::String, ::String, ::Int64, ::Vararg{Int64,N} where N) at eval.jl:34
(::Atom.##102#107{String,Int64,String})() at eval.jl:82
withpath(::Atom.##102#107{String,Int64,String}, ::Void) at utils.jl:30
withpath(::Function, ::String) at eval.jl:38
hideprompt(::Atom.##101#106{String,Int64,String}) at repl.jl:62
macro expansion at eval.jl:80 [inlined]
(::Atom.##100#105{Dict{String,Any}})() at task.jl:80

In JuMP 0.19.0 this code works.

Great that it works in 0.19. Do you need to stay on 0.18.5?

I will port sometime in the future, but not now. The issue with copying constraints is just because of the named constraints. I removed the names and seems that everything is working now.

Just to finish this topic.
There are many people that use deepcopy with JuMP models and don’t know about this issue. Just two suggestions, I think this should be clear in JuMP documentation and using deepcopy in JuMP model should return an error.

3 Likes