JuMP turning off/on a constraint

Hi there,

I was wondering if JuMP has a way to turn off/on a constraint.
According to the documentation, I can delete a constraint using the function delete (and then unregister if I want) but I cannot find a way to turn back on this exact same constraint (except by adding it back to the model as done initially).

Ideally, I would like to do something of this form:

model = Model()

@variable(model, x)
@constraint(model, con, 2x <= 1)
@objective(model, Max, x)

turn_off(model,con) # NOTE: this does not exist

... 

turn_on(model,con) # NOTE: this does not exist

...

Thank you for your help!

Julien

1 Like

If your constraint is an inequality constraint of the form a^{T}x \leq b, then you can set its right-hand side to a very large (or very negative depending on the sense) value.
The solver should be able to remove it at presolve.

1 Like

Agreed but this seems not ideal as I would have to keep track of the rhs to be able to turn it back on.

Another option is to use a slack variable:

using JuMP
model = Model()
@variable(model, x)
@variable(model, slack)
@constraint(model, 2x >= 1 + slack)
fix(slack, 0.0)
optimize!(model)
unfix(slack)
optimize!(model)
2 Likes

Right thank you, this work for both equality and inequlity constraints given that I am using different slacks :slight_smile: So I guess each constraint should be associated to a model, and one cannot define constraints independently from a model and then add the ones we want to the model.

You can have a workaround to define constraints separately. It is tricky to do with nonlinear constraints (= I failed), but linear constraints seem to work reasonably OK. In brief, you can create a basic model with variables/objectives/some constraints and then add new constraints in the form of expressions as you see fit. Depending on which constraints you need, you would use a new model based on the basic model. NB: I am not saying this is the best way.

For instance:

using JuMP
using Ipopt
# model = Model(HiGHS.Optimizer)

function basicModel(a,b) ####A function creating the basic model
    model = Model(Ipopt.Optimizer)
    @variable(model, x >= 0)
    @variable(model, a <= y <= b)

    @NLobjective(model, Min, 12x + 20y) ###You can also add the objective separately in another function in the same way as the constraints below
    return model
end

function addConstraint(mdl) ###Adding 'hard coded' constraints - I couldn't find a different (working) way for nonlinear constraints
    @NLconstraint(mdl, (mdl[:x]^4)>=0)
    return mdl
end

function addConstraint(mdl,expres) ###Adding constraints in the form of expres expressions
    @constraint(mdl, expres>=0)
    return mdl
end


modelTest = basicModel(0,3)
optimize!(modelTest) ###Solving the basic model w/o any constraints except the bounds

modelTestCstr = addConstraint(modelTest) ###Adding a dummy constraint for fun and in case you need nonlinear constraints
modelTestCstr = addConstraint(modelTest, 6*modelTest[:x]+8*modelTest[:y]-100)  ###Adding the first constraint to the basic model
print(modelTestCstr)
optimize!(modelTestCstr) ###Solving the basic model with the first constraint

modelTestCstr = addConstraint(modelTest, 7*modelTest[:x]+12*modelTest[:y]-120) ###Adding the second constraint
print(modelTestCstr)
optimize!(modelTestCstr)  ###Solving the basic model with both constraints

modelTestCstr2 = addConstraint(modelTest, 7*modelTest[:x]+12*modelTest[:y]-120) ###Adding the second constraint to the basic model
print(modelTestCstr2)
optimize!(modelTestCstr2)  ###Solving the basic model with the second constraint only

```

Summing up:

  1. Create the model with all the constraints, then disable them by changing the right-hand-side
    • pros: doesn’t require additional variables / constraints, requires only minimal modification of the problem (so it should be friendly to re-optimize).
    • cons: requires to put all constraints in the initial model, only works with inequality constraints, requires you to track the original RHS value
  2. Add an artificial slack variable (without bounds and zero objective) to each constraint. To enable a constraint, force the slack to zero. To disable the constraint, free the slack variable.
    • pros: works with all types of constraints, only requires you to track the slack variables
    • cons: if for some reason you are using lazy constraints too, then the disabled constraints will not be removed at presolve (because the solver cannot guarantee that the slack won’t appear in any lazy constraint), which may have a detrimental effect on performance. Requires additional variables
  3. Create an expression for each of your constraints (outside of the model itself). You can then delete constraints you don’t want, and re-instate constraints you want without having to re-form the expressions
    • pros: the underlying solver always sees exactly the model you want it to see. Does not require any additional variable
    • cons: requires you to track all the original expressions, and to write code that adds a constraint given the expression. You will also pay the price of adding/removing constraints from the model, which can be heavy if you do a lot of such operations.
3 Likes