Cannot add solution when using addConsIndicator
It might be my implementation error, but whenever I have indicator constraints, the constraints seem always needs to be satisfied regardless of the value of the binary variable. Minimum example:
from pyscipopt import Model
if __name__ == "__main__":
m = Model()
control = m.addVar(vtype='B')
v = m.addVar(vtype='C', lb=1, ub=3)
m.addConsIndicator(v <= 2, control)
m.setObjective(v, "maximize")
sol = m.createSol(None)
m.setSolVal(sol, v, 3)
m.setSolVal(sol, control, 0)
m.addSol(sol)
m.optimize()
sol = m.getBestSol()
print(sol[v])
print(sol[control])
Good afternoon, @skyu0221! Thank you for your organized issue!
I think the problem here is a different one. Look at the beginning of the solving process:
PySCIPOpt is saying that the provided solution is infeasible, so it disregards it. The same thing happens if you set control to 1. Sorry for not helping more, I am a bit busy, I will try looking into it more tomorrow.
Hi @Joao-Dionisio ,
Thanks for replying! Yes, that is basically my question about using an indicator constraint. As you can see, the optimal solution should be v = 3 and control = 0, which I cannot add manually.
If I'm not misunderstanding the concept, I assume if control = 1, then the constraint v <= 2 must hold (https://www.scipopt.org/doc/html/cons__indicator_8c.php). But is it valid to say if I set control = 0, then SCIP can ignore the constraint automatically? Or do I have to do something with the slack variable added by the indicator constraint to make my solution feasible?
Hello @skyu0221, sorry for the delay. This is indeed a bit puzzling. It's not that SCIP cannot arrive at the optimal solution. At least on my end, he correctly arrives at the solution v = 3, control = 0.
And the constraint seems to be activated correctly.
But, as you say, SCIP claims that the optimal solution is infeasible, if added manually, even though it arrives at the exact same solution.
Trying to add the solution v = 2, control = 1 doesn't get us any problems. I don't know what's going on here, but at least it seems that the optimization process runs smoothly, it's the adding the solution part that's not correct.
Dear @Joao-Dionisio,
As the question is interesting to me, let me add some points that may be useful. I think the strange behavior is back to the point that the logical constraint is basically redundant. Now, if you comment the constraint the result would be:
SCIP version 8.0.4 [precision: 8 byte] [memory: block] [mode: optimized] [LP solver: Soplex 6.0.4] [GitHash: a8e51afd1e]
Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)
presolving:
(0.0s) symmetry computation started: requiring (bin +, int +, cont +), (fixed: bin -, int -, cont -)
(0.0s) no symmetry present
presolving (0 rounds: 0 fast, 0 medium, 0 exhaustive):
0 deleted vars, 0 deleted constraints, 0 added constraints, 0 tightened bounds, 0 added holes, 0 changed sides, 0 changed coefficients
0 implications, 0 cliques
presolved problem has 2 variables (1 bin, 0 int, 0 impl, 1 cont) and 0 constraints
Presolving Time: 0.00
time | node | left |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr| dualbound | primalbound | gap | compl.
* 0.0s| 1 | 0 | 0 | - | LP | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 3.000000e+00 | 3.000000e+00 | 0.00%| unknown
0.0s| 1 | 0 | 0 | - | 569k | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 3.000000e+00 | 3.000000e+00 | 0.00%| unknown
SCIP Status : problem is solved [optimal solution found]
Solving Time (sec) : 0.01
Solving Nodes : 1
Primal Bound : +3.00000000000000e+00 (1 solutions)
Dual Bound : +3.00000000000000e+00
Gap : 0.00 %
The logical expression can be translated into the linear one as follows:
$$v \leq 2 + M*(1-control) \quad (1)$$
By assuming the control equals 1 the solution would be v=2 and control=1.
Also, if you write the problem in the .cip format, you can see the following details: (these details cannot be seen in other formats like .lp or .mps)
STATISTICS
Problem name : model
Variables : 3 (1 binary, 0 integer, 0 implicit integer, 2 continuous)
Constraints : 2 initial, 2 maximal
OBJECTIVE
Sense : maximize
VARIABLES
[binary] <x1>: obj=0, original bounds=[0,1]
[continuous] <x2>: obj=1, original bounds=[1,3]
[continuous] <indslack_IndicatorCons>: obj=0, original bounds=[0,+inf]
CONSTRAINTS
[linear] <indlin_IndicatorCons>: -<indslack_IndicatorCons>[C] +<x2>[C] <= 2;
[indicator] <IndicatorCons>: <x1> = 1 -> <indslack_IndicatorCons> = 0 (<indlin_IndicatorCons>);
END
The first constraint is the same as what is mentioned in the SCIP host and is equal to:
$$v - slack \leq 2$$
The second is equivalent to: $$\text{IF:} \quad (control = 1) \implies (slack = 0)$$
It derives the following linear inequalities:
$$slack \geq 0 - m*(1-control) \quad (2)$$
$$slack \leq 0 + M*(1-control) \quad (3)$$
Now, based on the latest two constraints, if control is equal to 1 then slack is equal to 0 and the original constraint is valid. But if we set v to 3 and control to 0 as an initial start, slack can be valued on $+INF$ and causes some violation on the $RHS$. This is why when you are trying to add the solution v = 2, control = 1 it doesn't get us any problems.
Regards Abbas
Thank you for the help, @abb-omidi!
But I don't understand your conclusion. If control is 0, then slack can take a value in [0,M]. The "worst" possible case (slack = M) simply gives us v <= 2 + M. But we also have a bound constraint on the variable itself, and so the constraint simplifies to v <= 3. I don't understand why this should cause problems.
Dear @Joao-Dionisio,
I am actually not sure how the SCIP can deal with the slack variable internally. There are two things that may come:
- As the constraint is basically redundant, SCIP may remove this slack variable in the solving process. By that, the predefined solution causes the constraint being violated.
3 <= 2. - When We set
controlto0, theslackvariable actually falls in $[- \infty, + \infty ]$. (In my previous comment I bounded it just from the positive side). Again in many cases, e.g.M=0, the constraint would be violated.
I managed to ask some questions w.r.t. the slack variable and its rule in the constraints from the SCIP community. I will update this issue if I can get any feedback.
Regards Abbas