Skip to content

Commit fc3fd04

Browse files
committed
Merge branch 'fix_cplex_handling_of_barrier' into 'v91-bugfix'
fix handling of barrier results in lpi_cpx See merge request integer/scip!3474
2 parents 2f86cde + aacdfcc commit fc3fd04

File tree

3 files changed

+173
-58
lines changed

3 files changed

+173
-58
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Fixed bugs
1414
- remove coefficient information from linear constraint hashes in order to compare keys with tolerances
1515
- fixed NULL pointer dereference in SCIPtpiGetNumThreads() of TinyCThread interface if called before SCIPtpiInit(); now returns 0 in this case
1616
- calling SCIPsolveConcurrent() when SCIP was compiled without a TPI now results in a plugin-not-found error
17+
- fixed LPI status functions of lpi_cpx if the barrier is called
1718

1819
Performance improvements
1920
------------------------

src/lpi/lpi_cpx.c

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ struct SCIP_LPi
147147
SCIP_CPXPARAM curparam; /**< current CPLEX parameters in the environment */
148148
CPXLPptr cpxlp; /**< CPLEX LP pointer */
149149
int solstat; /**< solution status of last optimization call */
150+
int method; /**< solution method of last optimization call */
150151
SCIP_CPXPARAM cpxparam; /**< current parameter values for this LP */
151152
char* larray; /**< array with 'L' entries for changing lower bounds */
152153
char* uarray; /**< array with 'U' entries for changing upper bounds */
@@ -711,6 +712,7 @@ void invalidateSolution(
711712
{
712713
assert(lpi != NULL);
713714
lpi->solstat = -1;
715+
lpi->method = CPX_ALG_NONE;
714716
lpi->instabilityignored = FALSE;
715717
}
716718

@@ -2293,16 +2295,16 @@ SCIP_RETCODE SCIPlpiSolvePrimal(
22932295
}
22942296

22952297
lpi->solstat = CPXgetstat(lpi->cpxenv, lpi->cpxlp);
2298+
lpi->method = CPX_ALG_PRIMAL;
22962299
lpi->instabilityignored = FALSE;
22972300

22982301
/* CPLEX outputs an error if the status is CPX_STAT_INForUNBD and the iterations are determined */
2299-
if( lpi->solstat != CPX_STAT_INForUNBD )
2302+
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, &primalfeasible, &dualfeasible) );
2303+
if( lpi->solstat != CPX_STAT_INForUNBD && solntype != CPX_NO_SOLN )
23002304
lpi->iterations = CPXgetphase1cnt(lpi->cpxenv, lpi->cpxlp) + CPXgetitcnt(lpi->cpxenv, lpi->cpxlp);
23012305
else
23022306
lpi->iterations = 0;
23032307

2304-
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, NULL, &primalfeasible, &dualfeasible) );
2305-
23062308
SCIPdebugMessage(" -> CPLEX returned solstat=%d, pfeas=%d, dfeas=%d (%d iterations)\n",
23072309
lpi->solstat, primalfeasible, dualfeasible, lpi->iterations);
23082310

@@ -2349,6 +2351,7 @@ SCIP_RETCODE SCIPlpiSolvePrimal(
23492351
assert( lpi->solstat != CPX_STAT_INForUNBD );
23502352

23512353
lpi->iterations += CPXgetphase1cnt(lpi->cpxenv, lpi->cpxlp) + CPXgetitcnt(lpi->cpxenv, lpi->cpxlp);
2354+
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, NULL, NULL) );
23522355

23532356
SCIPdebugMessage(" -> CPLEX returned solstat=%d (%d iterations)\n", lpi->solstat, lpi->iterations);
23542357

@@ -2365,7 +2368,6 @@ SCIP_RETCODE SCIPlpiSolvePrimal(
23652368

23662369
/* check whether the solution is basic: if Cplex, e.g., hits a time limit in data setup, this might not be the case,
23672370
* also for some pathological cases of infeasibility, e.g., contradictory bounds */
2368-
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, NULL, NULL) );
23692371
lpi->solisbasic = (solntype == CPX_BASIC_SOLN);
23702372
assert( lpi->solisbasic || lpi->solstat != CPX_STAT_OPTIMAL );
23712373

@@ -2418,16 +2420,16 @@ SCIP_RETCODE SCIPlpiSolveDual(
24182420
}
24192421

24202422
lpi->solstat = CPXgetstat(lpi->cpxenv, lpi->cpxlp);
2423+
lpi->method = CPX_ALG_DUAL;
24212424
lpi->instabilityignored = FALSE;
24222425

24232426
/* CPLEX outputs an error if the status is CPX_STAT_INForUNBD and the iterations are determined */
2424-
if( lpi->solstat != CPX_STAT_INForUNBD )
2427+
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, &primalfeasible, &dualfeasible) );
2428+
if( lpi->solstat != CPX_STAT_INForUNBD && solntype != CPX_NO_SOLN )
24252429
lpi->iterations = CPXgetphase1cnt(lpi->cpxenv, lpi->cpxlp) + CPXgetitcnt(lpi->cpxenv, lpi->cpxlp);
24262430
else
24272431
lpi->iterations = 0;
24282432

2429-
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, NULL, &primalfeasible, &dualfeasible) );
2430-
24312433
SCIPdebugMessage(" -> CPLEX returned solstat=%d, pfeas=%d, dfeas=%d (%d iterations)\n",
24322434
lpi->solstat, primalfeasible, dualfeasible, lpi->iterations);
24332435

@@ -2460,7 +2462,7 @@ SCIP_RETCODE SCIPlpiSolveDual(
24602462
assert( lpi->solstat != CPX_STAT_INForUNBD );
24612463

24622464
lpi->iterations += CPXgetphase1cnt(lpi->cpxenv, lpi->cpxlp) + CPXgetitcnt(lpi->cpxenv, lpi->cpxlp);
2463-
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, NULL, &primalfeasible, &dualfeasible) );
2465+
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, NULL, NULL) );
24642466

24652467
SCIPdebugMessage(" -> CPLEX returned solstat=%d (%d iterations)\n", lpi->solstat, lpi->iterations);
24662468

@@ -2478,7 +2480,6 @@ SCIP_RETCODE SCIPlpiSolveDual(
24782480
/* check whether the solution is basic: if Cplex, e.g., hits a time limit in data setup, this might not be the case,
24792481
* also for some pathological cases of infeasibility, e.g., contradictory bounds
24802482
*/
2481-
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, NULL, NULL) );
24822483
lpi->solisbasic = (solntype == CPX_BASIC_SOLN);
24832484
assert( lpi->solisbasic || lpi->solstat != CPX_STAT_OPTIMAL );
24842485

@@ -2601,9 +2602,10 @@ SCIP_RETCODE SCIPlpiSolveBarrier(
26012602

26022603
lpi->solisbasic = (solntype == CPX_BASIC_SOLN);
26032604
lpi->solstat = CPXgetstat(lpi->cpxenv, lpi->cpxlp);
2605+
lpi->method = CPX_ALG_BARRIER;
26042606
lpi->instabilityignored = FALSE;
26052607

2606-
if( lpi->solstat != CPX_STAT_INForUNBD )
2608+
if( lpi->solstat != CPX_STAT_INForUNBD && solntype != CPX_NO_SOLN )
26072609
lpi->iterations = CPXgetbaritcnt(lpi->cpxenv, lpi->cpxlp);
26082610
else
26092611
lpi->iterations = 0;
@@ -2635,12 +2637,17 @@ SCIP_RETCODE SCIPlpiSolveBarrier(
26352637
lpi->solisbasic = (solntype == CPX_BASIC_SOLN);
26362638
lpi->solstat = CPXgetstat(lpi->cpxenv, lpi->cpxlp);
26372639
lpi->instabilityignored = FALSE;
2638-
assert( lpi->solstat != CPX_STAT_INForUNBD );
26392640

26402641
lpi->iterations += CPXgetbaritcnt(lpi->cpxenv, lpi->cpxlp);
26412642
SCIPdebugMessage(" -> CPLEX returned solstat=%d\n", lpi->solstat);
26422643

26432644
setIntParam(lpi, CPX_PARAM_PREIND, CPX_ON);
2645+
2646+
if( lpi->solstat == CPX_STAT_INForUNBD )
2647+
{
2648+
/* if we could not resolve CPX_STAT_INForUNBD, we use the dual simplex */
2649+
SCIP_CALL( SCIPlpiSolveDual(lpi) );
2650+
}
26442651
}
26452652

26462653
return SCIP_OKAY;
@@ -3089,10 +3096,10 @@ SCIP_Bool SCIPlpiIsPrimalUnbounded(
30893096

30903097
/* If the solution status of CPLEX is CPX_STAT_UNBOUNDED, it only means, there is an unbounded ray,
30913098
* but not necessarily a feasible primal solution. If primalfeasible == FALSE, we cannot conclude,
3092-
* that the problem is unbounded
3099+
* that the problem is unbounded.
30933100
*/
30943101
return ((primalfeasible && (lpi->solstat == CPX_STAT_UNBOUNDED || lpi->solstat == CPX_STAT_INForUNBD))
3095-
|| lpi->solstat == CPX_STAT_OPTIMAL_FACE_UNBOUNDED);
3102+
|| lpi->solstat == CPX_STAT_OPTIMAL_FACE_UNBOUNDED || (primalfeasible && lpi->solstat == CPX_STAT_ABORT_PRIM_OBJ_LIM && lpi->method == CPX_ALG_BARRIER));
30963103
}
30973104

30983105
/** returns TRUE iff LP is proven to be primal infeasible */
@@ -3111,7 +3118,8 @@ SCIP_Bool SCIPlpiIsPrimalInfeasible(
31113118

31123119
ABORT_ZERO( CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, NULL, NULL, &dualfeasible) );
31133120

3114-
return (lpi->solstat == CPX_STAT_INFEASIBLE || (lpi->solstat == CPX_STAT_INForUNBD && dualfeasible));
3121+
return (lpi->solstat == CPX_STAT_INFEASIBLE || (lpi->solstat == CPX_STAT_INForUNBD && dualfeasible)
3122+
|| (lpi->solstat == CPX_STAT_ABORT_DUAL_OBJ_LIM && lpi->method == CPX_ALG_BARRIER));
31153123
}
31163124

31173125
/** returns TRUE iff LP is proven to be primal feasible */
@@ -3158,7 +3166,7 @@ SCIP_Bool SCIPlpiHasDualRay(
31583166
assert(lpi->cpxenv != NULL);
31593167
assert(lpi->solstat >= 0);
31603168

3161-
return (lpi->solstat == CPX_STAT_INFEASIBLE && CPXgetmethod(lpi->cpxenv, lpi->cpxlp) == CPX_ALG_DUAL);
3169+
return (lpi->solstat == CPX_STAT_INFEASIBLE && lpi->method == CPX_ALG_DUAL);
31623170
}
31633171

31643172
/** returns TRUE iff LP is proven to be dual unbounded */
@@ -3177,7 +3185,8 @@ SCIP_Bool SCIPlpiIsDualUnbounded(
31773185

31783186
ABORT_ZERO( CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, NULL, NULL, &dualfeasible) );
31793187

3180-
return (dualfeasible && (lpi->solstat == CPX_STAT_INFEASIBLE || lpi->solstat == CPX_STAT_INForUNBD));
3188+
return (dualfeasible && ((lpi->solstat == CPX_STAT_INFEASIBLE || lpi->solstat == CPX_STAT_INForUNBD)
3189+
|| (lpi->solstat == CPX_STAT_ABORT_DUAL_OBJ_LIM && lpi->method == CPX_ALG_BARRIER)));
31813190
}
31823191

31833192
/** returns TRUE iff LP is proven to be dual infeasible */
@@ -3198,7 +3207,8 @@ SCIP_Bool SCIPlpiIsDualInfeasible(
31983207

31993208
return (lpi->solstat == CPX_STAT_UNBOUNDED
32003209
|| lpi->solstat == CPX_STAT_OPTIMAL_FACE_UNBOUNDED
3201-
|| (lpi->solstat == CPX_STAT_INForUNBD && primalfeasible));
3210+
|| (lpi->solstat == CPX_STAT_INForUNBD && primalfeasible)
3211+
|| (lpi->solstat == CPX_STAT_ABORT_PRIM_OBJ_LIM && lpi->method == CPX_ALG_BARRIER));
32023212
}
32033213

32043214
/** returns TRUE iff LP is proven to be dual feasible */
@@ -3300,9 +3310,14 @@ SCIP_Bool SCIPlpiIsObjlimExc(
33003310
assert(lpi != NULL);
33013311
assert(lpi->solstat >= 0);
33023312

3303-
return (lpi->solstat == CPX_STAT_ABORT_OBJ_LIM
3304-
|| lpi->solstat == CPX_STAT_ABORT_DUAL_OBJ_LIM
3305-
|| lpi->solstat == CPX_STAT_ABORT_PRIM_OBJ_LIM);
3313+
if( lpi->solstat == CPX_STAT_ABORT_OBJ_LIM )
3314+
return TRUE;
3315+
else if( lpi->solstat == CPX_STAT_ABORT_DUAL_OBJ_LIM || lpi->solstat == CPX_STAT_ABORT_PRIM_OBJ_LIM )
3316+
{
3317+
if( lpi->method != CPX_ALG_BARRIER )
3318+
return TRUE;
3319+
}
3320+
return FALSE;
33063321
}
33073322

33083323
/** returns TRUE iff the iteration limit was reached */
@@ -3491,7 +3506,6 @@ SCIP_RETCODE SCIPlpiGetRealSolQuality(
34913506
)
34923507
{
34933508
int solntype;
3494-
int what;
34953509

34963510
assert(lpi != NULL);
34973511
assert(lpi->cpxlp != NULL);
@@ -3502,26 +3516,28 @@ SCIP_RETCODE SCIPlpiGetRealSolQuality(
35023516

35033517
SCIPdebugMessage("requesting solution quality from CPLEX: quality %d\n", qualityindicator);
35043518

3505-
switch( qualityindicator )
3519+
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, NULL, NULL) );
3520+
3521+
if( solntype == CPX_BASIC_SOLN )
35063522
{
3507-
case SCIP_LPSOLQUALITY_ESTIMCONDITION:
3508-
what = CPX_KAPPA;
3509-
break;
3523+
int what;
35103524

3511-
case SCIP_LPSOLQUALITY_EXACTCONDITION:
3512-
what = CPX_EXACT_KAPPA;
3513-
break;
3525+
switch( qualityindicator )
3526+
{
3527+
case SCIP_LPSOLQUALITY_ESTIMCONDITION:
3528+
what = CPX_KAPPA;
3529+
break;
35143530

3515-
default:
3516-
SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3517-
return SCIP_INVALIDDATA;
3518-
}
3531+
case SCIP_LPSOLQUALITY_EXACTCONDITION:
3532+
what = CPX_EXACT_KAPPA;
3533+
break;
35193534

3520-
CHECK_ZERO( lpi->messagehdlr, CPXsolninfo(lpi->cpxenv, lpi->cpxlp, NULL, &solntype, NULL, NULL) );
3535+
default:
3536+
SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3537+
return SCIP_INVALIDDATA;
3538+
}
35213539

3522-
if( solntype == CPX_BASIC_SOLN )
3523-
{
3524-
CHECK_ZERO( lpi->messagehdlr, CPXgetdblquality(lpi->cpxenv, lpi->cpxlp, quality, what) );
3540+
(void) CPXgetdblquality(lpi->cpxenv, lpi->cpxlp, quality, what);
35253541
}
35263542

35273543
return SCIP_OKAY;

0 commit comments

Comments
 (0)