diff --git a/CHANGELOG b/CHANGELOG index c299585a1e..656ea54420 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -67,6 +67,7 @@ Fixed bugs - in SCIPsolveProbingLP() when objective has been changed do not return cutoff due to exceeding the cutoff bound - set probing LP to be a relaxation only when objective has not been changed - declare contradicting infinities in getMinActivity() and getMaxActivity() as non-tight +- reject farkas solution with large values to bound magnification of errors in SCIPgetFarkasProof() Miscellaneous ------------- diff --git a/src/scip/conflict_general.c b/src/scip/conflict_general.c index 4aafd690dd..d838fe5224 100644 --- a/src/scip/conflict_general.c +++ b/src/scip/conflict_general.c @@ -94,6 +94,10 @@ * 2^53 = 9007199254740992 */ #define NUMSTOP 9007199254740992.0 +/* because row violations might be magnified, we stop the infeasibility analysis if a dual weight is bigger than + * 10^7 = 10000000 + */ +#define SOLSTOP 10000000.0 /** returns the current number of conflict sets in the conflict set storage */ int SCIPconflictGetNConflicts( @@ -1210,17 +1214,26 @@ SCIP_RETCODE SCIPgetFarkasProof( /* allocate temporary memory */ SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, nrows) ); BMSclearMemoryArray(dualfarkas, nrows); + localrowinds = NULL; + localrowdepth = NULL; + nlocalrows = 0; /* get dual Farkas values of rows */ SCIP_CALL( SCIPlpiGetDualfarkas(lpi, dualfarkas) ); - localrowinds = NULL; - localrowdepth = NULL; - nlocalrows = 0; + /* check whether the Farkas solution is numerically stable */ + for( r = 0; r < nrows; ++r ) + { + if( REALABS(dualfarkas[r]) > SOLSTOP ) + { + *valid = FALSE; + goto TERMINATE; + } + } /* calculate the Farkas row */ - (*valid) = TRUE; - (*validdepth) = 0; + *valid = TRUE; + *validdepth = 0; for( r = 0; r < nrows; ++r ) { @@ -1254,7 +1267,7 @@ SCIP_RETCODE SCIPgetFarkasProof( /* due to numerical reasons we want to stop */ if( REALABS(SCIPaggrRowGetRhs(farkasrow)) > NUMSTOP ) { - (*valid) = FALSE; + *valid = FALSE; goto TERMINATE; } } @@ -1310,7 +1323,7 @@ SCIP_RETCODE SCIPgetFarkasProof( } else { - (*valid) = FALSE; + *valid = FALSE; SCIPsetDebugMsg(set, " -> proof is not valid to due infinite activity delta\n"); } } @@ -1347,7 +1360,6 @@ SCIP_RETCODE SCIPgetDualProof( SCIP_Real* redcosts; int* localrowinds; int* localrowdepth; - SCIP_Real maxabsdualsol; SCIP_Bool infdelta; int nlocalrows; int nrows; @@ -1386,7 +1398,7 @@ SCIP_RETCODE SCIPgetDualProof( retcode = SCIPlpiGetSol(lpi, NULL, primsols, dualsols, NULL, redcosts); if( retcode == SCIP_LPERROR ) /* on an error in the LP solver, just abort the conflict analysis */ { - (*valid) = FALSE; + *valid = FALSE; goto TERMINATE; } SCIP_CALL( retcode ); @@ -1399,20 +1411,13 @@ SCIP_RETCODE SCIPgetDualProof( #endif /* check whether the dual solution is numerically stable */ - maxabsdualsol = 0; - for( r = 0; r < nrows; r++ ) - { - SCIP_Real absdualsol = REALABS(dualsols[r]); - - if( absdualsol > maxabsdualsol ) - maxabsdualsol = absdualsol; - } - - /* don't consider dual solution with maxabsdualsol > 1e+07, this would almost cancel out the objective constraint */ - if( maxabsdualsol > 1e+07 ) + for( r = 0; r < nrows; ++r ) { - (*valid) = FALSE; - goto TERMINATE; + if( REALABS(dualsols[r]) > SOLSTOP ) + { + *valid = FALSE; + goto TERMINATE; + } } /* clear the proof */ @@ -1477,7 +1482,7 @@ SCIP_RETCODE SCIPgetDualProof( /* due to numerical reasons we want to stop */ if( REALABS(SCIPaggrRowGetRhs(farkasrow)) > NUMSTOP ) { - (*valid) = FALSE; + *valid = FALSE; goto TERMINATE; } } @@ -1533,7 +1538,7 @@ SCIP_RETCODE SCIPgetDualProof( } else { - (*valid) = FALSE; + *valid = FALSE; SCIPsetDebugMsg(set, " -> proof is not valid to due infinite activity delta\n"); } }