scipopt / scip

SCIP - Solving Constraint Integer Programs
Other
369 stars 63 forks source link

SCIP optimally solves a model, but claims it's infeasible if some constraints are removed #26

Closed Joao-Dionisio closed 1 year ago

Joao-Dionisio commented 1 year ago

Good afternoon.

I have created an example model where SCIP finds an optimal solution, but if certain constraints are removed, SCIP claims the model is infeasible.

With these constraints (plus some bound constraints): image

We get this optimal solution: image

And simply deleting the temperature constraints: image

We get an infeasible model: image

Maybe I am not thinking clearly, but it seems that this should not happen. You can see the code here: incorrect_infeasibility.zip.

svigerske commented 1 year ago

Could you write out a CIP file with the model instances? There seems to be a writeProblem() function for model.

Joao-Dionisio commented 1 year ago

Could you write out a CIP file with the model instances? There seems to be a writeProblem() function for model.

Sure, here they are: without_temperature.zip with_temperature.zip

svigerske commented 1 year ago

Removing these temperature constraints leads to fixing all variables in the problem (starting with the dualfix presolver). Some fixings seem to be done in a way that some remaining constraints are infeasible:

  [nonlinear] <c7>: <rul[1,Winding,1]>+(<rul[1,Winding,0]>+exp(((<real_temp[1,1]>*0.166667+(-16.3333))*log(2)))*(-1)+<chi[1,Winding,0]>*6000)*(-1) <= 0;
violation: right hand side is violated by 1.21111886528524e-05

This output is from this change:

diff --git a/src/scip/scip_solve.c b/src/scip/scip_solve.c
index d9280d3c14..57ef787163 100644
--- a/src/scip/scip_solve.c
+++ b/src/scip/scip_solve.c
@@ -1431,7 +1431,7 @@ SCIP_RETCODE presolve(
       SCIP_Bool stored;

       SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
-      SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, FALSE, FALSE, FALSE, &stored) );
+      SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, FALSE, FALSE, FALSE, FALSE, &stored) );

       if( scip->set->nactivepricers == 0 )
       {

Disabling the dualfix presolver helps, but not sure that this is the culprit.

svigerske commented 1 year ago

Problem is that the linear constraint handlers decides that some constraints are redundant:

  [linear] <c135>:  -1200.00001211119<t_chi[2,Winding,1]>[B] +<t_rul[2,Winding,33]>[C] <= 1199.99998788881;
[cons_linear.c:16471] debug: linear constraint <c135> is redundant: activitybounds=[-1200.00001211119,1200], sides=[-1e+20,1199.99998788881]

But the difference between 1200 and 1199.99998788881 matters here.
If the constraints are removed, more variables are fixed to their bound. For this fixing, the nonlinear constraints are violated, though.

Being more strict in the redundancy check for linear constraints helps:

diff --git a/src/scip/cons_linear.c b/src/scip/cons_linear.c
index dffbd4428b..3675f41121 100644
--- a/src/scip/cons_linear.c
+++ b/src/scip/cons_linear.c
@@ -16465,7 +16465,7 @@ SCIP_DECL_CONSPRESOL(consPresolLinear)
             cutoff = TRUE;
             break;
          }
-         else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
+         else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
          {
             SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
@@ -16476,7 +16476,7 @@ SCIP_DECL_CONSPRESOL(consPresolLinear)
                (*ndelconss)++;
             break;
          }
-         else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
+         else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
          {
             SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
@@ -16484,7 +16484,7 @@ SCIP_DECL_CONSPRESOL(consPresolLinear)
             if( !consdata->upgraded )
                (*nchgsides)++;
          }
-         else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
+         else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
          {
             SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);

Also https://git.zib.de/integer/scip/-/merge_requests/2913

Joao-Dionisio commented 1 year ago

Thank you for the very quick response, Stefan! Closing the issue as completed now.