Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot add solution when using addConsIndicator #717

Open
skyu0221 opened this issue Aug 8, 2023 · 6 comments
Open

Cannot add solution when using addConsIndicator #717

skyu0221 opened this issue Aug 8, 2023 · 6 comments
Labels

Comments

@skyu0221
Copy link

skyu0221 commented Aug 8, 2023

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])
@Joao-Dionisio
Copy link
Collaborator

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:

image

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.

@skyu0221
Copy link
Author

skyu0221 commented Aug 8, 2023

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?

@Joao-Dionisio
Copy link
Collaborator

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.

image

And the constraint seems to be activated correctly.

image

But, as you say, SCIP claims that the optimal solution is infeasible, if added manually, even though it arrives at the exact same solution.

image

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.

@abb-omidi
Copy link

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

@Joao-Dionisio
Copy link
Collaborator

Joao-Dionisio commented Aug 17, 2023

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.

@abb-omidi
Copy link

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:

  1. 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.
  2. When We set control to 0, the slack variable 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Backlog
Development

No branches or pull requests

4 participants