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);
1000 *varboundserr =
FALSE;
1009 for(
int b = 0;
b < nblocks; ++
b )
1013 blocklen = blockend[
b] - blockstart[
b] + 1;
1016 for(
int m = 0; m < blocklen; ++m )
1031 master =
vars[blockstart[
b] + m];
1039 *varboundserr =
TRUE;
1040 SCIPdebugMsg(
scip,
"Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
1060 bestimprovement = 0.0;
1071 firstslave = blockstart[
b] + m + 1;
1078 for(
int s = 0; s < nslaves; ++s )
1089 slaveindex = (firstslave + s - blockstart[
b]) % blocklen;
1090 slaveindex += blockstart[
b];
1093 if( (blocklen <= heurdata->maxnslaves ||
heurdata->maxnslaves == -1) && slaveindex < blockstart[
b] + m )
1096 if( slaveindex == blockstart[
b] + m )
1100 slave =
vars[slaveindex];
1112 *varboundserr =
TRUE;
1113 SCIPdebugMsg(
scip,
"Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
1134 equaldirbound = 0.0;
1141 changedobj = (masterobj - slaveobj) * diffdirbound;
1147 changedobj = (slaveobj - masterobj) * diffdirbound;
1153 if( (masterobj + slaveobj) * equaldirbound < changedobj )
1155 changedobj = (masterobj + slaveobj) * equaldirbound;
1162 if( -(masterobj + slaveobj) * equaldirbound < changedobj )
1164 changedobj = -(masterobj + slaveobj) * equaldirbound;
1175 && changedobj < bestimprovement )
1177 bestimprovement = changedobj;
1178 bestslavepos = slaveindex;
1179 bestdirection = directions;
1185 if( directions / 2 == 1 )
1190 if( directions % 2 == 1 )
1195 if( bestmasterdir == bestslavedir )
1196 bestbound = equaldirbound;
1198 bestbound = diffdirbound;
1203 if( bestslavepos >= 0 )
1205 if( npairs == arraysize )
1211 arraysize = 2 * arraysize;
1213 assert( npairs < arraysize );
1215 bestmasters[npairs] = master;
1216 bestslaves[npairs] =
vars[bestslavepos];
1217 objchanges[npairs] = ((int)bestslavedir *
SCIPvarGetObj(bestslaves[npairs]) + (int)bestmasterdir * masterobj) * bestbound;
1218 bestdirections[npairs] = bestdirection;
1220 assert(objchanges[npairs] < 0);
1222 SCIPdebugMsg(
scip,
" Saved candidate pair {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g} %d\n",
1225 + (
int)bestslavedir * bestbound, bestdirections[npairs]);
1237 for(
int b = 0;
b < npairs; ++
b )
1249 master = bestmasters[
b];
1250 slave = bestslaves[
b];
1256 assert(0 <= bestdirections[
b] && bestdirections[
b] < 4);
1258 if( bestdirections[
b] / 2 == 1 )
1263 if( bestdirections[
b] % 2 == 1 )
1277 SCIPdebugMsg(
scip,
" Promising candidates {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g}\n",
1279 masterobj, slaveobj, mastersolval + (
int)masterdir *
bound, slavesolval + (
int)slavedir *
bound);
1283 changedobj = ((int)slavedir * slaveobj + (int)masterdir * masterobj) *
bound;
1301 SCIPdebugMsg(
scip,
" Feasible shift: <%s>[%g, %g] (obj: %f) <%f> --> <%f>\n",
1306#ifdef SCIP_STATISTIC
1314 *improvement =
TRUE;
1339#ifdef SCIP_STATISTIC
1342 " Twoopt Binary Statistics : "
1343 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg. block size, max block size) \n",
1351 " Twoopt Integer statistics : "
1352 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg block size, max block size) \n",
1360 " Twoopt results : "
1361 "%6d %6d %4d %4.2g (runs, binary exchanges, Integer shiftings, matching rate)\n",
1448#ifdef SCIP_STATISTIC
1538 int ncolsforsorting;
1584 presolthiscall =
FALSE;
1586 ncolsforsorting =
MIN(ncols, ndiscvars);
1591 for(
int i = 0;
i < ncolsforsorting; ++
i )
1595 presolthiscall =
TRUE;
1639 if( !presolthiscall )
1641 for(
int i = 0;
i < ncolsforsorting; ++
i )
1644 SCIPdebugMsg(
scip,
" Twoopt heuristic has initialized activities and sorted rows! \n");
1647 improvement =
FALSE;
1648 varboundserr =
FALSE;
1673 if( ! improvement || varboundserr )
1694#ifdef SCIP_STATISTIC
1709 SCIPdebugMsg(
scip,
"shifted solution should be feasible -> solve LP to fix continuous variables to best values\n");
1716 SCIPdebugMsg(
scip,
" Cont. variable <%s>, status %d with bounds [%g <= %g <= x <= %g <= %g]\n",
1736 for(
int i = 0;
i < ndiscvars; ++
i )
1750 for(
int i = 0;
i < ndiscvars; ++
i )
1763 SCIPwarningMessage(
scip,
"Error while solving LP in Twoopt heuristic; LP solve terminated with code <%d>\n",retstat);
1801#ifdef SCIP_STATISTIC
1862 "nodes to wait after last best solution before calling heuristic",
1871 "parameter to determine the percentage of rows two variables have to share before they are considered equal",
#define SCIP_STRINGEQ(name, reference, retcode)
#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