JuMPv0.21 and deepcopy

Hi,
In JuMP Version 0.21 it says

Calling deepcopy(::AbstractModel) now throws an error.
Is there a new way to do deepcopy()?
As far as I understand copy() is not what I want because the copied and original model are modified together (I am not sure to get the usage).

Ideally what I would like to do is define some model with optimize, constraints, objective variable etc…
Then copy all that in some model ML0 then

for m in 1 to M
 ML = deepcopy(ML0)
 @constraint( f(m) )
 optimize!(ML)
end

I would just turn the code that produces the model into a function,

function make_model()
    ...
    return model
end

and then change the loop to use the function instead, e.g.

for m in 1 to M
 ML = make_model()
 @constraint(ML, f(m) )
 optimize!(ML)
end

By the way, I’ve recategorized the question to the domains/optimization category which is more appropriate for JuMP questions.

1 Like

The problem with that is that I have to recreate from scratch the model at each iteration.
Typically in my case, ML0 that I want to copy, is very long to build (and way faster to copy as I noticed when I was using deepcopy() with the previous JuMP versions).

Maybe one of the JuMP devs can chime in then, since they know more than me about this, but I’m not sure there is a way to do that. I believe the problem is that deepcopying is not guaranteed to correctly do what you want it to do, because the model is also held by the solver which may be written in another language, and deepcopying won’t extend to copying things on the solver level too.

Maybe you can set it up so you can simply modify constraints within a single model? https://www.juliaopt.org/JuMP.jl/stable/constraints/#Constraint-modifications-1

1 Like

@ericphanson is correct on all counts.

Use constraint modifications, or delete the constraint and add a new one.

2 Likes

I will just chime in because this change (deepcopy throwing an error) was my contribution (first suggested by @Thuener here, then suggested by me again here, and finally implemented by me here).

The fact is: deepcopy has never ever worked, it always had basically the same behavior as copy that you say it is incompatible with your usage. There was never a code that correctly implemented deepcopy and now it was thrown out (replaced by an error), the fact deepcopy was implemented for JuMP.Model was mere accident, because deepcopy is automatically defined for all types but this does not work correctly/out-of-the-box if the type in question has a pointer to an external C object.

If your code was working correctly with old deepcopy then either: it was incorrect; or it will work with copy too. The other solutions given in this thread are far better however.

3 Likes

Thanks, everyone.
Constraint modifications work well and faster than before.
@Henrique_Becker, indeed maybe in my code it was doing the same as copy. However, I am sure at some point in time and version (before we could do constraints modifications), I tested in-depth deepcopy() vs ‘copy()’ with JuMP and actually saw a different behavior but as you said it was probably an uncontrolled effect.

1 Like

The behavior of copy and deepcopy come from different code (copy has a specific implementation in JuMP, while deepcopy defaulted to the generic type fallback), so it is entirely possible that you may have observed some difference between them; however, deepcopy should not really be fully working, as @Thuener suggested to make it an error exactly because they were surprised by a silent change to the deepcopied model after changing the original model.