@@ -147,6 +147,7 @@ struct SCIP_LPi
147
147
SCIP_CPXPARAM curparam ; /**< current CPLEX parameters in the environment */
148
148
CPXLPptr cpxlp ; /**< CPLEX LP pointer */
149
149
int solstat ; /**< solution status of last optimization call */
150
+ int method ; /**< solution method of last optimization call */
150
151
SCIP_CPXPARAM cpxparam ; /**< current parameter values for this LP */
151
152
char * larray ; /**< array with 'L' entries for changing lower bounds */
152
153
char * uarray ; /**< array with 'U' entries for changing upper bounds */
@@ -711,6 +712,7 @@ void invalidateSolution(
711
712
{
712
713
assert (lpi != NULL );
713
714
lpi -> solstat = -1 ;
715
+ lpi -> method = CPX_ALG_NONE ;
714
716
lpi -> instabilityignored = FALSE;
715
717
}
716
718
@@ -2293,16 +2295,16 @@ SCIP_RETCODE SCIPlpiSolvePrimal(
2293
2295
}
2294
2296
2295
2297
lpi -> solstat = CPXgetstat (lpi -> cpxenv , lpi -> cpxlp );
2298
+ lpi -> method = CPX_ALG_PRIMAL ;
2296
2299
lpi -> instabilityignored = FALSE;
2297
2300
2298
2301
/* 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 )
2300
2304
lpi -> iterations = CPXgetphase1cnt (lpi -> cpxenv , lpi -> cpxlp ) + CPXgetitcnt (lpi -> cpxenv , lpi -> cpxlp );
2301
2305
else
2302
2306
lpi -> iterations = 0 ;
2303
2307
2304
- CHECK_ZERO ( lpi -> messagehdlr , CPXsolninfo (lpi -> cpxenv , lpi -> cpxlp , NULL , NULL , & primalfeasible , & dualfeasible ) );
2305
-
2306
2308
SCIPdebugMessage (" -> CPLEX returned solstat=%d, pfeas=%d, dfeas=%d (%d iterations)\n" ,
2307
2309
lpi -> solstat , primalfeasible , dualfeasible , lpi -> iterations );
2308
2310
@@ -2349,6 +2351,7 @@ SCIP_RETCODE SCIPlpiSolvePrimal(
2349
2351
assert ( lpi -> solstat != CPX_STAT_INForUNBD );
2350
2352
2351
2353
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 ) );
2352
2355
2353
2356
SCIPdebugMessage (" -> CPLEX returned solstat=%d (%d iterations)\n" , lpi -> solstat , lpi -> iterations );
2354
2357
@@ -2365,7 +2368,6 @@ SCIP_RETCODE SCIPlpiSolvePrimal(
2365
2368
2366
2369
/* check whether the solution is basic: if Cplex, e.g., hits a time limit in data setup, this might not be the case,
2367
2370
* 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 ) );
2369
2371
lpi -> solisbasic = (solntype == CPX_BASIC_SOLN );
2370
2372
assert ( lpi -> solisbasic || lpi -> solstat != CPX_STAT_OPTIMAL );
2371
2373
@@ -2418,16 +2420,16 @@ SCIP_RETCODE SCIPlpiSolveDual(
2418
2420
}
2419
2421
2420
2422
lpi -> solstat = CPXgetstat (lpi -> cpxenv , lpi -> cpxlp );
2423
+ lpi -> method = CPX_ALG_DUAL ;
2421
2424
lpi -> instabilityignored = FALSE;
2422
2425
2423
2426
/* 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 )
2425
2429
lpi -> iterations = CPXgetphase1cnt (lpi -> cpxenv , lpi -> cpxlp ) + CPXgetitcnt (lpi -> cpxenv , lpi -> cpxlp );
2426
2430
else
2427
2431
lpi -> iterations = 0 ;
2428
2432
2429
- CHECK_ZERO ( lpi -> messagehdlr , CPXsolninfo (lpi -> cpxenv , lpi -> cpxlp , NULL , NULL , & primalfeasible , & dualfeasible ) );
2430
-
2431
2433
SCIPdebugMessage (" -> CPLEX returned solstat=%d, pfeas=%d, dfeas=%d (%d iterations)\n" ,
2432
2434
lpi -> solstat , primalfeasible , dualfeasible , lpi -> iterations );
2433
2435
@@ -2460,7 +2462,7 @@ SCIP_RETCODE SCIPlpiSolveDual(
2460
2462
assert ( lpi -> solstat != CPX_STAT_INForUNBD );
2461
2463
2462
2464
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 ) );
2464
2466
2465
2467
SCIPdebugMessage (" -> CPLEX returned solstat=%d (%d iterations)\n" , lpi -> solstat , lpi -> iterations );
2466
2468
@@ -2478,7 +2480,6 @@ SCIP_RETCODE SCIPlpiSolveDual(
2478
2480
/* check whether the solution is basic: if Cplex, e.g., hits a time limit in data setup, this might not be the case,
2479
2481
* also for some pathological cases of infeasibility, e.g., contradictory bounds
2480
2482
*/
2481
- CHECK_ZERO ( lpi -> messagehdlr , CPXsolninfo (lpi -> cpxenv , lpi -> cpxlp , NULL , & solntype , NULL , NULL ) );
2482
2483
lpi -> solisbasic = (solntype == CPX_BASIC_SOLN );
2483
2484
assert ( lpi -> solisbasic || lpi -> solstat != CPX_STAT_OPTIMAL );
2484
2485
@@ -2601,9 +2602,10 @@ SCIP_RETCODE SCIPlpiSolveBarrier(
2601
2602
2602
2603
lpi -> solisbasic = (solntype == CPX_BASIC_SOLN );
2603
2604
lpi -> solstat = CPXgetstat (lpi -> cpxenv , lpi -> cpxlp );
2605
+ lpi -> method = CPX_ALG_BARRIER ;
2604
2606
lpi -> instabilityignored = FALSE;
2605
2607
2606
- if ( lpi -> solstat != CPX_STAT_INForUNBD )
2608
+ if ( lpi -> solstat != CPX_STAT_INForUNBD && solntype != CPX_NO_SOLN )
2607
2609
lpi -> iterations = CPXgetbaritcnt (lpi -> cpxenv , lpi -> cpxlp );
2608
2610
else
2609
2611
lpi -> iterations = 0 ;
@@ -2635,12 +2637,17 @@ SCIP_RETCODE SCIPlpiSolveBarrier(
2635
2637
lpi -> solisbasic = (solntype == CPX_BASIC_SOLN );
2636
2638
lpi -> solstat = CPXgetstat (lpi -> cpxenv , lpi -> cpxlp );
2637
2639
lpi -> instabilityignored = FALSE;
2638
- assert ( lpi -> solstat != CPX_STAT_INForUNBD );
2639
2640
2640
2641
lpi -> iterations += CPXgetbaritcnt (lpi -> cpxenv , lpi -> cpxlp );
2641
2642
SCIPdebugMessage (" -> CPLEX returned solstat=%d\n" , lpi -> solstat );
2642
2643
2643
2644
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
+ }
2644
2651
}
2645
2652
2646
2653
return SCIP_OKAY ;
@@ -3089,10 +3096,10 @@ SCIP_Bool SCIPlpiIsPrimalUnbounded(
3089
3096
3090
3097
/* If the solution status of CPLEX is CPX_STAT_UNBOUNDED, it only means, there is an unbounded ray,
3091
3098
* 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.
3093
3100
*/
3094
3101
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 ) );
3096
3103
}
3097
3104
3098
3105
/** returns TRUE iff LP is proven to be primal infeasible */
@@ -3111,7 +3118,8 @@ SCIP_Bool SCIPlpiIsPrimalInfeasible(
3111
3118
3112
3119
ABORT_ZERO ( CPXsolninfo (lpi -> cpxenv , lpi -> cpxlp , NULL , NULL , NULL , & dualfeasible ) );
3113
3120
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 ));
3115
3123
}
3116
3124
3117
3125
/** returns TRUE iff LP is proven to be primal feasible */
@@ -3158,7 +3166,7 @@ SCIP_Bool SCIPlpiHasDualRay(
3158
3166
assert (lpi -> cpxenv != NULL );
3159
3167
assert (lpi -> solstat >= 0 );
3160
3168
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 );
3162
3170
}
3163
3171
3164
3172
/** returns TRUE iff LP is proven to be dual unbounded */
@@ -3177,7 +3185,8 @@ SCIP_Bool SCIPlpiIsDualUnbounded(
3177
3185
3178
3186
ABORT_ZERO ( CPXsolninfo (lpi -> cpxenv , lpi -> cpxlp , NULL , NULL , NULL , & dualfeasible ) );
3179
3187
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 )));
3181
3190
}
3182
3191
3183
3192
/** returns TRUE iff LP is proven to be dual infeasible */
@@ -3198,7 +3207,8 @@ SCIP_Bool SCIPlpiIsDualInfeasible(
3198
3207
3199
3208
return (lpi -> solstat == CPX_STAT_UNBOUNDED
3200
3209
|| 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 ));
3202
3212
}
3203
3213
3204
3214
/** returns TRUE iff LP is proven to be dual feasible */
@@ -3300,9 +3310,14 @@ SCIP_Bool SCIPlpiIsObjlimExc(
3300
3310
assert (lpi != NULL );
3301
3311
assert (lpi -> solstat >= 0 );
3302
3312
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;
3306
3321
}
3307
3322
3308
3323
/** returns TRUE iff the iteration limit was reached */
@@ -3491,7 +3506,6 @@ SCIP_RETCODE SCIPlpiGetRealSolQuality(
3491
3506
)
3492
3507
{
3493
3508
int solntype ;
3494
- int what ;
3495
3509
3496
3510
assert (lpi != NULL );
3497
3511
assert (lpi -> cpxlp != NULL );
@@ -3502,26 +3516,28 @@ SCIP_RETCODE SCIPlpiGetRealSolQuality(
3502
3516
3503
3517
SCIPdebugMessage ("requesting solution quality from CPLEX: quality %d\n" , qualityindicator );
3504
3518
3505
- switch ( qualityindicator )
3519
+ CHECK_ZERO ( lpi -> messagehdlr , CPXsolninfo (lpi -> cpxenv , lpi -> cpxlp , NULL , & solntype , NULL , NULL ) );
3520
+
3521
+ if ( solntype == CPX_BASIC_SOLN )
3506
3522
{
3507
- case SCIP_LPSOLQUALITY_ESTIMCONDITION :
3508
- what = CPX_KAPPA ;
3509
- break ;
3523
+ int what ;
3510
3524
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 ;
3514
3530
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 ;
3519
3534
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
+ }
3521
3539
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 );
3525
3541
}
3526
3542
3527
3543
return SCIP_OKAY ;
0 commit comments