All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
heur_twoopt.c
Go to the documentation of this file.
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
29 #define HEUR_DESC "primal heuristic to improve incumbent solution by flipping pairs of variables"
41 #define DEFAULT_WAITINGNODES 0 /**< default number of nodes to wait after current best solution before calling heuristic */
42 #define DEFAULT_MATCHINGRATE 0.5 /**< default percentage by which two variables have to match in their LP-row set to be
56 SCIP_Real matchingrate; /**< percentage by which two variables have have to match in their LP-row
58 SCIP_VAR** binvars; /**< Array of binary variables which are sorted with respect to their occurrence
61 int waitingnodes; /**< user parameter to determine number of nodes to wait after last best solution
95 int intnexchanges; /**< number of executed changes of Integer solution values leading to improvement in
119 /** tries to switch the values of two binary or integer variables and checks feasibility with respect to the LP.
153 assert(SCIPisFeasGE(scip, mastersolval + (int)masterdir * shiftval, SCIPvarGetLbGlobal(master)));
154 assert(SCIPisFeasLE(scip, mastersolval + (int)masterdir * shiftval, SCIPvarGetUbGlobal(master)));
204 assert(SCIPisFeasGE(scip, activities[SCIProwGetLPPos(masterrows[i])], SCIProwGetLhs(masterrows[i])));
205 assert(SCIPisFeasLE(scip, activities[SCIProwGetLPPos(masterrows[i])], SCIProwGetRhs(masterrows[i])));
213 /** compare two variables with respect to their columns. Columns are treated as {0,1} vector, where every nonzero entry
214 * is treated as '1', and compared to each other lexicographically. I.e. var1 is < var2 if the corresponding column of
215 * var2 has the smaller single nonzero index of the two columns. This comparison costs O(constraints) in the worst
256 * one can easily check that the difference of these two numbers always has the desired sign for comparison. */
275 SCIP_Real matchingrate /**< determines the ratio of shared LP rows compared to the total number of
317 /* if the numbers of nonzero rows differs too much, w.r.t.matching ratio, the more expensive check over the rows
318 * doesn't have to be applied anymore because the counters for not shared rows can only increase.
350 /* now apply the ratio based comparison, that is if the ratio of shared rows is greater or equal the matching rate
353 return ( SCIPisFeasLE(scip, matchingrate, (nnonzeros1 - nrows1not2) / (SCIP_Real)(nnonzeros1)) ||
354 SCIPisFeasLE(scip, matchingrate, (nnonzeros2 - nrows2not1) / (SCIP_Real)(nnonzeros2)) ); /*lint !e795 */
357 /** determines a bound by which the absolute solution value of two integer variables can be shifted at most.
359 * first implementation only considers shifting proportion 1:1, i.e. if master value is shifted by a certain
426 SCIPdebugMessage(" Master: %s with direction %d and %d rows, Slave: %s with direction %d and %d rows \n", SCIPvarGetName(master),
450 SCIPdebugMessage(" Slaverow %s is not in LP (i=%d, j=%d)\n", SCIProwGetName(slaverows[i]), i, j);
456 SCIPdebugMessage(" Masterrow %s is not in LP (i=%d, j=%d) \n", SCIProwGetName(masterrows[j]), i, j);
500 /* effect is the effect on the row activity by shifting the variables by 1 in the respective directions */
523 SCIPdebugMessage(" %g <= %g <= %g, bound = %g, effect = %g (%g * %d + %g * %d) (i=%d,j=%d)\n", lhs, activity, rhs, bound, effect,
524 slaveindex <= masterindex ? slavecolvals[i] : 0.0, (int)slavedirection, masterindex <= slaveindex ? mastercolvals[j] : 0.0,
527 /* if the row has a left hand side, ensure that shifting preserves feasibility of this ">="-constraint */
539 /* if the row has an upper bound, ensure that shifting preserves feasibility of this "<="-constraint */
550 assert(SCIPisFeasLE(scip, lhs, activity + effect * bound) && SCIPisFeasGE(scip, rhs, activity + effect * bound));
555 SCIPdebugMessage(" Zero effect on row %s, effect %g, master coeff: %g slave coeff: %g (i=%d, j=%d)\n",
573 /* due to numerical reasons, bound can be negative. A variable shift by a negative bound is not desired by
582 * disposes variable with no heuristic relevancy, e.g., due to a fixed solution value, from its neighborhood block.
635 /* start determining blocks, i.e. a set of at least two variables which share most of their row set.
648 if( !checkConstraintMatching(scip, (*varspointer)[startindex], (*varspointer)[v], heurdata->matchingrate) )
650 /* current block has its last variable at position v-1. If v differs from startindex by at least 2,
674 /* reallocate memory with respect to the number of found blocks; if there were none, free the memory */
693 * If objective coefficient functions are not all equal, each Binary and Integer variables are sorted
719 /* ensure that method is not executed if presolving was already applied once in current branch and bound process */
728 /* if number of binary problem variables exceeds 2, they are subject to 2-optimization algorithm, hence heuristic
733 SCIP_CALL( innerPresolve(scip, vars, &(heurdata->binvars), nbinvars, &(heurdata->nbinblocks), &maxbinblocksize,
748 SCIPstatisticMessage(" Twoopt BINARY presolving finished with <%d> blocks, <%d> block variables \n",
755 SCIP_CALL( innerPresolve(scip, &(vars[nbinvars]), &(heurdata->intvars), nintvars, &(heurdata->nintblocks), &maxintblocksize,
767 SCIPstatisticMessage(" Twoopt Integer presolving finished with <%d> blocks, <%d> block variables \n",
952 if( SCIPisFeasGT(scip, mastersolval, SCIPvarGetUbGlobal(master)) || SCIPisFeasLT(scip, mastersolval, SCIPvarGetLbGlobal(master)) )
1009 if( (blocklen <= heurdata->maxnslaves || heurdata->maxnslaves == -1) && slaveindex < blockstart[b] + m )
1027 if( SCIPisFeasGT(scip, slavesolval, SCIPvarGetUbGlobal(slave)) || SCIPisFeasLT(scip, slavesolval, SCIPvarGetLbGlobal(slave)) )
1035 /* if solution value of the variable is fixed, delete it from the remaining candidates in the block */
1058 diffdirbound = determineBound(scip, worksol, master, DIRECTION_UP, slave, DIRECTION_DOWN, activities, nrows);
1065 diffdirbound = determineBound(scip, worksol, master, DIRECTION_DOWN, slave, DIRECTION_UP, activities, nrows);
1072 equaldirbound = determineBound(scip, worksol, master, DIRECTION_UP, slave, DIRECTION_UP, activities, nrows);
1081 equaldirbound = determineBound(scip, worksol, master, DIRECTION_DOWN, slave, DIRECTION_DOWN, activities, nrows);
1137 objchanges[npairs] = ((int)bestslavedir * SCIPvarGetObj(bestslaves[npairs]) + (int)bestmasterdir * masterobj) * bestbound;
1142 SCIPdebugMessage(" Saved candidate pair {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g} %d\n",
1143 SCIPvarGetName(master), mastersolval, SCIPvarGetName(bestslaves[npairs]), SCIPgetSolVal(scip, worksol, bestslaves[npairs]) ,
1144 masterobj, SCIPvarGetObj(bestslaves[npairs]), mastersolval + (int)bestmasterdir * bestbound, SCIPgetSolVal(scip, worksol, bestslaves[npairs])
1155 SCIPsortRealPtrPtrInt(objchanges, (void**)bestmasters, (void**)bestslaves, bestdirections, npairs);
1198 SCIPdebugMessage(" Promising candidates {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g}\n",
1200 masterobj, slaveobj, mastersolval + (int)masterdir * bound, slavesolval + (int)slavedir * bound);
1208 assert(SCIPvarGetStatus(master) == SCIP_VARSTATUS_COLUMN && SCIPvarGetStatus(slave) == SCIP_VARSTATUS_COLUMN);
1211 SCIP_CALL( shiftValues(scip, master, slave, mastersolval, masterdir, slavesolval, slavedir, bound,
1223 SCIPvarGetName(master), SCIPvarGetLbGlobal(master), SCIPvarGetUbGlobal(master), masterobj, mastersolval, SCIPgetSolVal(scip, worksol, master));
1225 SCIPvarGetName(slave), SCIPvarGetLbGlobal(slave), SCIPvarGetUbGlobal(slave), slaveobj, slavesolval, SCIPgetSolVal(scip, worksol, slave));
1247 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
1264 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg. block size, max block size) \n",
1267 heurdata->ntotalbinvars == 0 ? 0.0 : (SCIP_Real)heurdata->binnblockvars/(heurdata->ntotalbinvars) * 100.0,
1273 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg block size, max block size) \n",
1276 heurdata->ntotalintvars == 0 ? 0.0 : (SCIP_Real)heurdata->intnblockvars/(heurdata->ntotalintvars) * 100.0,
1340 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
1373 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
1488 /* ensure that the user defined number of nodes after last best solution has been reached, return otherwise */
1512 /* ensure that presolve has detected structures in the problem to which the 2-optimization can be applied.
1524 if( SCIPgetNVars(scip) > ndiscvars && ( !SCIPhasCurrentNodeLP(scip) || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL ) )
1527 /* problem satisfies all necessary conditions for 2-optimization heuristic, execute heuristic! */
1573 SCIP_CALL( optimize(scip, worksol, heurdata->binvars, heurdata->binblockstart, heurdata->binblockend, heurdata->nbinblocks,
1588 SCIP_CALL( optimize(scip, worksol, heurdata->intvars, heurdata->intblockstart, heurdata->intblockend, heurdata->nintblocks,
1622 /* fix the integer variables and start diving to optimize continuous variables with respect to reduced domain */
1631 SCIPdebugMessage("shifted solution should be feasible -> solve LP to fix continuous variables to best values\n");
1639 SCIPvarGetName(allvars[i]), SCIPvarGetStatus(allvars[i]), SCIPvarGetLbGlobal(allvars[i]), SCIPvarGetLbLocal(allvars[i]), SCIPvarGetUbLocal(allvars[i]),
1665 assert(SCIPvarGetType(allvars[i]) != SCIP_VARTYPE_CONTINUOUS && SCIPisFeasIntegral(scip, solval));
1673 assert( SCIPisFeasEQ(scip, SCIPgetVarLbDive(scip, allvars[i]), SCIPgetVarUbDive(scip, allvars[i])) );
1676 SCIPdebugMessage(" -> old LP iterations: %"SCIP_LONGINT_FORMAT"\n", SCIPgetNLPIterations(scip));
1678 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
1679 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
1685 SCIPwarningMessage(scip, "Error while solving LP in Twoopt heuristic; LP solve terminated with code <%d>\n",retstat);
1691 SCIPdebugMessage(" -> new LP iterations: %"SCIP_LONGINT_FORMAT"\n", SCIPgetNLPIterations(scip));
1766 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/twoopt/intopt", " Should Integer-2-Optimization be applied or not?",
1770 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/twoopt/waitingnodes", "user parameter to determine number of "
1775 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/twoopt/maxnslaves", "maximum number of slaves for one master variable",
|