29 #define HEUR_NAME "zirounding" 30 #define HEUR_DESC "LP rounding heuristic as suggested by C. Wallace taking row slacks and bounds into account" 31 #define HEUR_DISPCHAR 'z' 32 #define HEUR_PRIORITY -500 34 #define HEUR_FREQOFS 0 35 #define HEUR_MAXDEPTH -1 36 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE 37 #define HEUR_USESSUBSCIP FALSE 39 #define DEFAULT_MAXROUNDINGLOOPS 2 40 #define DEFAULT_STOPZIROUND TRUE 41 #define DEFAULT_STOPPERCENTAGE 0.02 42 #define DEFAULT_MINSTOPNCALLS 1000 87 return MIN(upgap, downgap);
110 assert(scip != NULL);
112 assert(upslacks != NULL);
113 assert(downslacks != NULL);
114 assert(upperbound != NULL);
115 assert(lowerbound != NULL);
127 assert(colvals != NULL);
128 assert(colrows != NULL);
147 for( i = 0; i < ncolvals && MAX(*lowerbound, *upperbound) >=
MINSHIFT; ++i )
159 assert(0 <= rowpos && rowpos < nslacks);
167 *numericalerror =
TRUE;
171 SCIPdebugMsg(scip,
"colval: %15.8g, downslack: %15.8g, upslack: %5.2g, lb: %5.2g, ub: %5.2g\n", colvals[i], downslacks[rowpos], upslacks[rowpos],
172 *lowerbound, *upperbound);
182 upslack =
MAX(upslacks[rowpos], 0.0);
183 *upperbound = MIN(*upperbound, upslack/colvals[i]);
189 downslack =
MAX(downslacks[rowpos], 0.0);
190 *lowerbound = MIN(*lowerbound, downslack/colvals[i]);
195 assert(colvals[i] != 0.0);
200 upslack =
MAX(upslacks[rowpos], 0.0);
201 *lowerbound = MIN(*lowerbound, -upslack/colvals[i]);
207 downslack =
MAX(downslacks[rowpos], 0.0);
208 *upperbound = MIN(*upperbound, -downslack/colvals[i]);
235 assert(scip != NULL);
238 assert(upslacks != NULL);
239 assert(downslacks != NULL);
240 assert(activities != NULL);
241 assert(nslacks >= 0);
249 assert(nrows == 0 || (rows != NULL && colvals != NULL));
252 for( i = 0; i < nrows; ++i )
257 assert(-1 <= rowpos && rowpos < nslacks);
264 val = colvals[i] * shiftvalue;
272 assert(slackvars[rowpos] != NULL);
273 assert(!
SCIPisZero(scip, slackcoeffs[rowpos]));
275 slackvarsolval =
SCIPgetSolVal(scip, sol, slackvars[rowpos]);
276 slackvarshiftval = -val / slackcoeffs[rowpos];
284 activities[rowpos] += val;
288 upslacks[rowpos] -= val;
290 downslacks[rowpos] += val;
314 assert(varpointer != NULL);
315 assert(coeffpointer != NULL);
321 assert(nrowvals == 0 || rowvals != NULL);
322 assert(nrowvals == 0 || rowcols != NULL);
325 for( v = nrowvals - 1; v >= 0; --v )
329 assert(rowcols[v] != NULL);
341 *coeffpointer = rowvals[v];
342 *varpointer = colvar;
362 assert(
scip != NULL);
363 assert(heur != NULL);
381 assert(heurdata != NULL);
399 assert(heurdata != NULL);
416 assert(heurdata != NULL);
433 assert(heurdata != NULL);
435 heurdata->lastlp = -1;
474 assert(result != NULL);
493 assert(heurdata != NULL);
503 if( nlps == heurdata->lastlp )
506 heurdata->lastlp = nlps;
510 nlpcands = nlpcands + nimplfracs;
515 assert(nlpcands > 0);
516 assert(lpcands != NULL);
517 assert(lpcandssol != NULL);
527 assert(rows != NULL);
560 numericalerror =
FALSE;
564 for( c = 0; c < nlpcands; ++c )
572 assert(cand != NULL);
578 assert(candrows == NULL || ncandrows > 0);
580 for( r = 0; r < ncandrows; ++r )
584 assert(candrows != NULL);
585 assert(candrows[r] != NULL);
590 rowneedsslackvar[rowpos] =
TRUE;
600 for( i = 0; i < nslacks; ++i )
621 downslacks[i] = activities[i] - lhs;
626 upslacks[i] = rhs - activities[i];
628 SCIPdebugMsg(
scip,
"lhs:%5.2f <= act:%5.2g <= rhs:%5.2g --> down: %5.2g, up:%5.2g\n", lhs, activities[i], rhs, downslacks[i], upslacks[i]);
639 if( slackvars[i] == NULL )
658 coeffslackvar = slackvarcoeffs[i];
661 ubgap =
MAX(0.0, ubslackvar - solvalslackvar);
662 lbgap =
MAX(0.0, solvalslackvar - lbslackvar);
667 upslacks[i] += coeffslackvar * lbgap;
671 downslacks[i] += coeffslackvar * ubgap;
678 upslacks[i] -= coeffslackvar * ubgap;
682 downslacks[i] -= coeffslackvar * lbgap;
686 SCIPdebugMsg(
scip,
" Slack variable for row %s at pos %d: %g <= %s = %g <= %g; Coeff %g, upslack = %g, downslack = %g \n",
688 upslacks[i], downslacks[i]);
698 assert(nslacks == 0 || (upslacks != NULL && downslacks != NULL && activities != NULL));
701 currentlpcands = nlpcands;
702 improvementfound =
TRUE;
705 while( currentlpcands > 0 && improvementfound && (heurdata->maxroundingloops == -1 || nroundings < heurdata->maxroundingloops) )
707 improvementfound =
FALSE;
709 SCIPdebugMsg(
scip,
"zirounding enters while loop for %d time with %d candidates left. \n", nroundings, currentlpcands);
712 for( c = 0; c < currentlpcands; ++c )
728 oldsolval = solarray[c];
737 calculateBounds(
scip, var, oldsolval, &upperbound, &lowerbound, upslacks, downslacks, nslacks, &numericalerror);
746 if( nroundings == heurdata->maxroundingloops )
753 up = oldsolval + upperbound;
754 down = oldsolval - lowerbound;
765 down =
MAX(down, floorx);
786 shiftval = (direction ==
DIRECTION_UP ? up - oldsolval : down - oldsolval);
790 shiftval = MIN(shiftval, upperbound);
792 shiftval = MIN(shiftval, lowerbound);
799 downslacks, activities, slackvars, slackvarcoeffs, nslacks) );
801 SCIPdebugMsg(
scip,
"zirounding update step : %d var index, oldsolval=%g, shiftval=%g\n",
805 improvementfound =
TRUE;
813 zilpcands[c] = zilpcands[currentlpcands - 1];
814 solarray[c] = solarray[currentlpcands - 1];
818 if( c < currentlpcands )
821 else if( nroundings == heurdata->maxroundingloops )
829 if( currentlpcands == 0 )
879 assert(heur != NULL);
890 "determines maximum number of rounding loops",
893 "flag to determine if Zirounding is deactivated after a certain percentage of unsuccessful calls",
896 "if percentage of found solutions falls below this parameter, Zirounding will be deactivated",
899 "determines the minimum number of calls before percentage-based deactivation of Zirounding is applied",
static void calculateBounds(SCIP *scip, SCIP_VAR *var, SCIP_Real currentvalue, SCIP_Real *upperbound, SCIP_Real *lowerbound, SCIP_Real *upslacks, SCIP_Real *downslacks, int nslacks, SCIP_Bool *numericalerror)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
static SCIP_Real getZiValue(SCIP *scip, SCIP_Real val)
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
int SCIProwGetNNonz(SCIP_ROW *row)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
const char * SCIProwGetName(SCIP_ROW *row)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
#define DEFAULT_MAXROUNDINGLOOPS
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
SCIP_Real SCIPinfinity(SCIP *scip)
enum SCIP_Retcode SCIP_RETCODE
#define SCIPstatisticMessage
struct SCIP_HeurData SCIP_HEURDATA
#define SCIPfreeBlockMemory(scip, ptr)
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
SCIP_RETCODE SCIPincludeHeurZirounding(SCIP *scip)
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
#define SCIPallocBlockMemory(scip, ptr)
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
static SCIP_DECL_HEUREXIT(heurExitZirounding)
#define DEFAULT_STOPZIROUND
const char * SCIPheurGetName(SCIP_HEUR *heur)
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
#define SCIPfreeBufferArrayNull(scip, ptr)
const char * SCIPvarGetName(SCIP_VAR *var)
static SCIP_DECL_HEURCOPY(heurCopyZirounding)
int SCIPgetNLPRows(SCIP *scip)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
#define DEFAULT_MINSTOPNCALLS
#define SCIPallocBufferArray(scip, ptr, num)
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
#define BMScopyMemoryArray(ptr, source, num)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
ZI Round primal heuristic.
#define DEFAULT_STOPPERCENTAGE
SCIP_Real SCIPgetLPObjval(SCIP *scip)
static SCIP_DECL_HEUREXEC(heurExecZirounding)
static SCIP_DECL_HEURINITSOL(heurInitsolZirounding)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
static SCIP_RETCODE updateSlacks(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real shiftvalue, SCIP_Real *upslacks, SCIP_Real *downslacks, SCIP_Real *activities, SCIP_VAR **slackvars, SCIP_Real *slackcoeffs, int nslacks)
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
int SCIProwGetLPPos(SCIP_ROW *row)
static SCIP_DECL_HEURFREE(heurFreeZirounding)
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
int SCIPvarGetIndex(SCIP_VAR *var)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
static void rowFindSlackVar(SCIP *scip, SCIP_ROW *row, SCIP_VAR **varpointer, SCIP_Real *coeffpointer)
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
static SCIP_DECL_HEURINIT(heurInitZirounding)
#define BMSclearMemoryArray(ptr, num)
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
int SCIPcolGetNLPNonz(SCIP_COL *col)
int SCIPcolGetLPPos(SCIP_COL *col)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)