56#define HEUR_NAME "twoopt"
57#define HEUR_DESC "primal heuristic to improve incumbent solution by flipping pairs of variables"
58#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_ITERATIVE
59#define HEUR_PRIORITY -20100
62#define HEUR_MAXDEPTH -1
64#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
65#define HEUR_USESSUBSCIP FALSE
68#define DEFAULT_INTOPT FALSE
69#define DEFAULT_WAITINGNODES 0
70#define DEFAULT_MATCHINGRATE 0.5
72#define DEFAULT_MAXNSLAVES 199
73#define DEFAULT_ARRAYSIZE 10
74#define DEFAULT_RANDSEED 37
193 assert(ncolmasterrows == 0 || masterrows !=
NULL);
199 assert(ncolslaverows == 0 || slaverows !=
NULL);
211 activities[rowpos] += mastercolvals[
i] * (int)masterdir * shiftval;
215 for(
int j = 0; j < ncolslaverows &&
SCIProwGetLPPos(slaverows[j]) >= 0; ++j )
225 activities[rowpos] += slavecolvals[j] * (int)slavedir * shiftval;
285 for(
int i = 0;
i < nnonzeros1 &&
i < nnonzeros2; ++
i )
294 return nnonzeros2 - nnonzeros1 ;
343 if( nnonzeros1 == 0 && nnonzeros2 == 0 )
347 if( matchingrate == 0.0 )
351 nrowmaximum =
MAX(nnonzeros1, nnonzeros2);
353 nrowabs =
ABS(nnonzeros1 - nnonzeros2);
354 nrows1not2 = nrowmaximum - nnonzeros2;
355 nrows2not1 = nrowmaximum - nnonzeros1;
362 if( (nrowmaximum - nrowabs) / (
SCIP_Real) nrowmaximum < matchingrate )
369 while(
i < nnonzeros1 && j < nnonzeros2 )
448 masterbound =
bound - mastersolval;
449 masterbound =
SCIPisFeasLE(
scip, mastersolval + ceil(masterbound),
bound) ? ceil(masterbound) : floor(masterbound);
454 masterbound = mastersolval -
bound;
455 masterbound =
SCIPisFeasGE(
scip, mastersolval - ceil(masterbound),
bound) ? ceil(masterbound) : floor(masterbound);
461 slavebound =
bound - slavesolval;
462 slavebound =
SCIPisFeasLE(
scip, slavesolval + ceil(slavebound),
bound) ? ceil(slavebound) : floor(slavebound);
467 slavebound = slavesolval -
bound;
468 slavebound =
SCIPisFeasGE(
scip, slavesolval - ceil(slavebound),
bound) ? ceil(slavebound) : floor(slavebound);
471 bound =
MIN(masterbound, slavebound);
488 assert(nslaverows == 0 || slavecolvals !=
NULL);
489 assert(nmasterrows == 0 || mastercolvals !=
NULL);
492 (
int)masterdirection, nmasterrows,
SCIPvarGetName(slave), (
int)slavedirection, nslaverows);
499 while(
i < nslaverows || j < nmasterrows )
522 slaveincrement =
FALSE;
528 slaveindex = INT_MAX;
530 if( j < nmasterrows )
533 masterindex = INT_MAX;
535 assert(0 <= slaveindex && 0 <= masterindex);
537 assert(slaveindex < INT_MAX || masterindex < INT_MAX);
540 if( slaveindex <= masterindex )
544 slaveincrement =
TRUE;
545 masterincrement = (slaveindex == masterindex);
553 masterincrement =
TRUE;
566 if( slaveindex <= masterindex )
567 effect += (slavecolvals[
i] * (int)slavedirection);
568 if( masterindex <= slaveindex )
569 effect += (mastercolvals[j] * (int)masterdirection);
585 SCIPdebugMsg(
scip,
" %g <= %g <= %g, bound = %g, effect = %g (%g * %d + %g * %d) (i=%d,j=%d)\n",
587 slaveindex <= masterindex ? slavecolvals[
i] : 0.0, (
int)slavedirection,
588 masterindex <= slaveindex ? mastercolvals[j] : 0.0, (
int)masterdirection,
i, j);
590 newval = (side -
activities[rowpos]) / effect;
597 activity =
activities[rowpos] + effect * ceil(newval);
601 bound = ceil(newval);
603 bound = floor(newval);
616 SCIPdebugMsg(
scip,
" No influence of row %s, effect %g, master coeff: %g slave coeff: %g (i=%d, j=%d)\n",
629 if( masterincrement )
650 assert(varindex <= *blockend);
699 for(
int v = 1; v <
nvars; ++v )
705 if( v - startindex >= 2 )
708 (*nblockvars) += v - startindex;
709 (*maxblocksize) =
MAX((*maxblocksize), v - startindex);
710 (*blockstart)[*nblocks] = startindex;
711 (*blockend)[*nblocks] = v - 1;
716 else if( v ==
nvars - 1 && v - startindex >= 1 )
719 (*nblockvars) += v - startindex + 1;
720 (*maxblocksize) =
MAX((*maxblocksize), v - startindex + 1);
721 (*blockstart)[*nblocks] = startindex;
722 (*blockend)[*nblocks] = v;
785 ntotalbinvars = nbinvars + nbinimplvars;
786 ntotalintvars = nintvars + nintimplvars;
790 heurdata->ntotalbinvars += ntotalbinvars;
795 if( ntotalbinvars > 1 )
802 for(;
i < nbinvars; ++
i )
804 for(;
i < ntotalbinvars; ++
i )
819 heurdata->binnblockvars += nbinblockvars;
822 SCIPstatisticMessage(
" Twoopt BINARY presolving finished with <%d> blocks, <%d> block variables \n",
823 heurdata->nbinblocks, nbinblockvars);
827 if(
heurdata->intopt && ntotalintvars > 1 )
834 for(;
i < nintvars; ++
i )
836 for(;
i < ntotalintvars; ++
i )
851 heurdata->intnblockvars += nintblockvars;
852 heurdata->ntotalintvars += ntotalintvars;
854 SCIPstatisticMessage(
" Twoopt Integer presolving finished with <%d> blocks, <%d> block variables \n",
855 heurdata->nintblocks, nintblockvars);
997 *varboundserr =
FALSE;
1006 for(
int b = 0;
b < nblocks; ++
b )
1010 blocklen = blockend[
b] - blockstart[
b] + 1;
1013 for(
int m = 0; m < blocklen; ++m )
1028 master =
vars[blockstart[
b] + m];
1036 *varboundserr =
TRUE;
1037 SCIPdebugMsg(
scip,
"Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
1057 bestimprovement = 0.0;
1068 firstslave = blockstart[
b] + m + 1;
1075 for(
int s = 0; s < nslaves; ++s )
1086 slaveindex = (firstslave + s - blockstart[
b]) % blocklen;
1087 slaveindex += blockstart[
b];
1090 if( (blocklen <= heurdata->maxnslaves ||
heurdata->maxnslaves == -1) && slaveindex < blockstart[
b] + m )
1093 if( slaveindex == blockstart[
b] + m )
1097 slave =
vars[slaveindex];
1109 *varboundserr =
TRUE;
1110 SCIPdebugMsg(
scip,
"Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
1131 equaldirbound = 0.0;
1138 changedobj = (masterobj - slaveobj) * diffdirbound;
1144 changedobj = (slaveobj - masterobj) * diffdirbound;
1150 if( (masterobj + slaveobj) * equaldirbound < changedobj )
1152 changedobj = (masterobj + slaveobj) * equaldirbound;
1159 if( -(masterobj + slaveobj) * equaldirbound < changedobj )
1161 changedobj = -(masterobj + slaveobj) * equaldirbound;
1172 && changedobj < bestimprovement )
1174 bestimprovement = changedobj;
1175 bestslavepos = slaveindex;
1176 bestdirection = directions;
1182 if( directions / 2 == 1 )
1187 if( directions % 2 == 1 )
1192 if( bestmasterdir == bestslavedir )
1193 bestbound = equaldirbound;
1195 bestbound = diffdirbound;
1200 if( bestslavepos >= 0 )
1202 if( npairs == arraysize )
1208 arraysize = 2 * arraysize;
1210 assert( npairs < arraysize );
1212 bestmasters[npairs] = master;
1213 bestslaves[npairs] =
vars[bestslavepos];
1214 objchanges[npairs] = ((int)bestslavedir *
SCIPvarGetObj(bestslaves[npairs]) + (int)bestmasterdir * masterobj) * bestbound;
1215 bestdirections[npairs] = bestdirection;
1217 assert(objchanges[npairs] < 0);
1219 SCIPdebugMsg(
scip,
" Saved candidate pair {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g} %d\n",
1222 + (
int)bestslavedir * bestbound, bestdirections[npairs]);
1234 for(
int b = 0;
b < npairs; ++
b )
1246 master = bestmasters[
b];
1247 slave = bestslaves[
b];
1253 assert(0 <= bestdirections[
b] && bestdirections[
b] < 4);
1255 if( bestdirections[
b] / 2 == 1 )
1260 if( bestdirections[
b] % 2 == 1 )
1274 SCIPdebugMsg(
scip,
" Promising candidates {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g}\n",
1276 masterobj, slaveobj, mastersolval + (
int)masterdir *
bound, slavesolval + (
int)slavedir *
bound);
1280 changedobj = ((int)slavedir * slaveobj + (int)masterdir * masterobj) *
bound;
1298 SCIPdebugMsg(
scip,
" Feasible shift: <%s>[%g, %g] (obj: %f) <%f> --> <%f>\n",
1303#ifdef SCIP_STATISTIC
1311 *improvement =
TRUE;
1336#ifdef SCIP_STATISTIC
1339 " Twoopt Binary Statistics : "
1340 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg. block size, max block size) \n",
1348 " Twoopt Integer statistics : "
1349 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg block size, max block size) \n",
1357 " Twoopt results : "
1358 "%6d %6d %4d %4.2g (runs, binary exchanges, Integer shiftings, matching rate)\n",
1444#ifdef SCIP_STATISTIC
1533 int ncolsforsorting;
1579 presolthiscall =
FALSE;
1581 ncolsforsorting =
MIN(ncols, ndiscvars);
1586 for(
int i = 0;
i < ncolsforsorting; ++
i )
1590 presolthiscall =
TRUE;
1634 if( !presolthiscall )
1636 for(
int i = 0;
i < ncolsforsorting; ++
i )
1639 SCIPdebugMsg(
scip,
" Twoopt heuristic has initialized activities and sorted rows! \n");
1642 improvement =
FALSE;
1643 varboundserr =
FALSE;
1668 if( ! improvement || varboundserr )
1689#ifdef SCIP_STATISTIC
1704 SCIPdebugMsg(
scip,
"shifted solution should be feasible -> solve LP to fix continuous variables to best values\n");
1711 SCIPdebugMsg(
scip,
" Cont. variable <%s>, status %d with bounds [%g <= %g <= x <= %g <= %g]\n",
1731 for(
int i = 0;
i < ndiscvars; ++
i )
1745 for(
int i = 0;
i < ndiscvars; ++
i )
1758 SCIPwarningMessage(
scip,
"Error while solving LP in Twoopt heuristic; LP solve terminated with code <%d>\n",retstat);
1796#ifdef SCIP_STATISTIC
1857 "nodes to wait after last best solution before calling heuristic",
1866 "parameter to determine the percentage of rows two variables have to share before they are considered equal",
#define SCIP_LONGINT_FORMAT
int SCIPgetNIntVars(SCIP *scip)
int SCIPgetNContVars(SCIP *scip)
int SCIPgetNBinImplVars(SCIP *scip)
int SCIPgetNVars(SCIP *scip)
SCIP_VAR ** SCIPgetVars(SCIP *scip)
int SCIPgetNIntImplVars(SCIP *scip)
int SCIPgetNContImplVars(SCIP *scip)
int SCIPgetNBinVars(SCIP *scip)
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
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_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_RETCODE SCIPincludeHeurTwoopt(SCIP *scip)
int SCIPcolGetNNonz(SCIP_COL *col)
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
void SCIPcolSort(SCIP_COL *col)
SCIP_Bool SCIPisExact(SCIP *scip)
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur,)
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
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 SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur,)
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur,)
void SCIPheurMarkExact(SCIP_HEUR *heur)
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur,)
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur,)
const char * SCIPheurGetName(SCIP_HEUR *heur)
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
SCIP_Real SCIPgetVarLbDive(SCIP *scip, SCIP_VAR *var)
SCIP_Real SCIPgetVarUbDive(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPstartDive(SCIP *scip)
SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
SCIP_RETCODE SCIPendDive(SCIP *scip)
SCIP_Bool SCIPinDive(SCIP *scip)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
int SCIPgetNLPRows(SCIP *scip)
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
#define SCIPallocBufferArray(scip, ptr, num)
#define SCIPreallocBufferArray(scip, ptr, num)
#define SCIPfreeBufferArray(scip, ptr)
#define SCIPallocBlockMemoryArray(scip, ptr, num)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
#define SCIPfreeBlockMemory(scip, ptr)
#define SCIPallocBlockMemory(scip, ptr)
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
int SCIProwGetLPPos(SCIP_ROW *row)
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
const char * SCIProwGetName(SCIP_ROW *row)
int SCIProwGetIndex(SCIP_ROW *row)
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
int SCIPsolGetIndex(SCIP_SOL *sol)
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)
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
const char * SCIPvarGetName(SCIP_VAR *var)
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPsortRealPtrPtrInt(SCIP_Real *realarray, void **ptrarray1, void **ptrarray2, int *intarray, int len)
SCIPfreeSol(scip, &heurdata->sol))
SCIPfreeRandom(scip, &heurdata->randnumgen)
#define DEFAULT_WAITINGNODES
SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE))
assert(minobj< SCIPgetCutoffbound(scip))
SCIPlinkLPSol(scip, sol))
static SCIP_Real determineBound(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *master, DIRECTION masterdirection, SCIP_VAR *slave, DIRECTION slavedirection, SCIP_Real *activities, int nrows)
static void disposeVariable(SCIP_VAR **vars, int *blockend, int varindex)
#define DEFAULT_MATCHINGRATE
static SCIP_Bool checkConstraintMatching(SCIP *scip, SCIP_VAR *var1, SCIP_VAR *var2, SCIP_Real matchingrate)
static SCIP_RETCODE innerPresolve(SCIP *scip, SCIP_VAR **vars, int nvars, int *nblocks, int *maxblocksize, int *nblockvars, int **blockstart, int **blockend, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
static int varColCompare(SCIP_VAR *var1, SCIP_VAR *var2)
#define DEFAULT_ARRAYSIZE
#define DEFAULT_MAXNSLAVES
static SCIP_RETCODE shiftValues(SCIP *scip, SCIP_VAR *master, SCIP_VAR *slave, SCIP_Real mastersolval, DIRECTION masterdir, SCIP_Real slavesolval, DIRECTION slavedir, SCIP_Real shiftval, SCIP_Real *activities, int nrows, SCIP_Bool *feasible)
static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
static SCIP_RETCODE presolveTwoOpt(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Primal heuristic to improve incumbent solution by flipping pairs of variables.
memory allocation routines
public methods for primal heuristics
public methods for LP management
public methods for message output
#define SCIPstatisticMessage
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for primal CIP solutions
public methods for problem variables
public methods for exact solving
public methods for primal heuristic plugins and divesets
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for random numbers
public methods for solutions
public methods for querying solving statistics
#define SCIP_DECL_HEURINITSOL(x)
#define SCIP_DECL_HEURCOPY(x)
struct SCIP_HeurData SCIP_HEURDATA
struct SCIP_Heur SCIP_HEUR
#define SCIP_DECL_HEURINIT(x)
#define SCIP_DECL_HEUREXIT(x)
#define SCIP_DECL_HEURFREE(x)
#define SCIP_DECL_HEUREXITSOL(x)
#define SCIP_DECL_HEUREXEC(x)
#define SCIP_DECL_SORTPTRCOMP(x)
struct SCIP_RandNumGen SCIP_RANDNUMGEN
enum SCIP_Retcode SCIP_RETCODE