Suppose I have three slightly different problems, the second two being variations of the first.

So Problem 1 that has a set of linear constraints and an objective function, say.

Then Problem 2 shares all of Problem 1's constraints/objective, but one of the constraints is slightly adjusted (say the RHS is halved).

And Problem 3 shares all of Problem 1's constraints/objective, but one of the constraints (not the one in Problem 2) is changed.

Essentially, Problems 2 and 3 'inherit' everything from Problem 1 and change it slightly.

How should this be modelled in a compact way? I understand that if I use separate mpproblems that constraints can't be shared, so I'm not sure if that is the correct approach. I could just change the constraints directly but once I've changed the constraint for Problem 2, how do I get back the original Problem 1 to use in building Problem 3?

It is correct that constraints cannot be shared by several mpproblem. However, if you have a large common definition part for your different problem versions (and don't need to access this portion of the constraints eg for reporting) you could do something along these lines:

declarations

R=1..10

x, y: array(R) of mpvar

P1,P2: mpproblem

end-declarations

with P1 do

C1:= sum(i in R) x(i) >= 1

C2:= sum(i in R | not isodd(i)) i*x(i) <= 20

forall(i in R) x(i) is_binary

writeln("####Problem P1:")

exportprob("")

end-do

P2:=P1 ! Copy the common portion, then complete constraints

with P2 do

! State some extra constraint

C3_2:= sum(i in R) 10*random*x(i) >= 50

end-do

with P1 do

! State some additional constraints for the first problem

C3_1:= sum(i in R) 10*random*x(i) >= 10

maximize(someObjective)

end-do

with P2 do

minimize(someotherObjective)

end-do

with P1 do

writeln("Solution of P1: ", getobjval)

forall(i in R) writeln(" ", i, ": ", x(i).sol)

end-do

with P2 do

writeln("Solution of P2: ", getobjval)

forall(i in R) writeln(" ", i, ": ", x(i).sol)

end-do

Using multiple "mpproblem" has the advantage that solution information remains accessible within each problem (unless it is explicitly "reset").

Alternatively, if you work with a single problem for which some constraints get redefined and you would like to keep solution information accessible, you need to save the solution information (either into custom arrays or an "mpsol" object) after each solving call, and then redefine the corresponding constraints to switch back and forth; or use "sethidden" to blend out temporarily certain constraints from the problem to be solved.