SCIP

    Solving Constraint Integer Programs

    heur_shifting.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file heur_shifting.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LP rounding heuristic that tries to recover from intermediate infeasibilities and shifts continuous variables
    28 * @author Tobias Achterberg
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    34#include "scip/heur_shifting.h"
    35#include "scip/pub_heur.h"
    36#include "scip/pub_lp.h"
    37#include "scip/pub_message.h"
    38#include "scip/pub_misc.h"
    39#include "scip/pub_var.h"
    40#include "scip/scip_branch.h"
    41#include "scip/scip_heur.h"
    42#include "scip/scip_lp.h"
    43#include "scip/scip_mem.h"
    44#include "scip/scip_message.h"
    45#include "scip/scip_numerics.h"
    46#include "scip/scip_prob.h"
    48#include "scip/scip_sol.h"
    50
    51
    52#define HEUR_NAME "shifting"
    53#define HEUR_DESC "LP rounding heuristic with infeasibility recovering also using continuous variables"
    54#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_ROUNDING
    55#define HEUR_PRIORITY -5000
    56#define HEUR_FREQ 5
    57#define HEUR_FREQOFS 0
    58#define HEUR_MAXDEPTH -1
    59#define HEUR_TIMING SCIP_HEURTIMING_DURINGLPLOOP
    60#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    61
    62#define MAXSHIFTINGS 50 /**< maximal number of non improving shiftings */
    63#define WEIGHTFACTOR 1.1
    64#define DEFAULT_RANDSEED 31 /**< initial random seed */
    65
    66
    67/* locally defined heuristic data */
    68struct SCIP_HeurData
    69{
    70 SCIP_SOL* sol; /**< working solution */
    71 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    72 SCIP_Longint lastlp; /**< last LP number where the heuristic was applied */
    73};
    74
    75
    76/*
    77 * local methods
    78 */
    79
    80/** update row violation arrays after a row's activity value changed */
    81static
    83 SCIP* scip, /**< SCIP data structure */
    84 SCIP_ROW* row, /**< LP row */
    85 SCIP_ROW** violrows, /**< array with currently violated rows */
    86 int* violrowpos, /**< position of LP rows in violrows array */
    87 int* nviolrows, /**< pointer to the number of currently violated rows */
    88 int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
    89 int* nfracsinrow, /**< array with number of fractional variables for every row */
    90 SCIP_Real oldactivity, /**< old activity value of LP row */
    91 SCIP_Real newactivity /**< new activity value of LP row */
    92 )
    93{
    94 SCIP_Real lhs;
    95 SCIP_Real rhs;
    96 SCIP_Bool oldviol;
    97 SCIP_Bool newviol;
    98
    99 assert(violrows != NULL);
    100 assert(violrowpos != NULL);
    101 assert(nviolrows != NULL);
    102
    103 lhs = SCIProwGetLhs(row);
    104 rhs = SCIProwGetRhs(row);
    105
    106 /* SCIPisFeasLT cannot handle comparing different infinities. To prevent this, we make a case distinction. */
    107 if( !(SCIPisInfinity(scip, oldactivity) || SCIPisInfinity(scip, -oldactivity)) )
    108 {
    109 oldviol = (SCIPisFeasLT(scip, oldactivity, lhs) || SCIPisFeasGT(scip, oldactivity, rhs));
    110 }
    111 else
    112 {
    113 oldviol = (SCIPisInfinity(scip, -oldactivity) && !SCIPisInfinity(scip, -lhs)) ||
    114 (SCIPisInfinity(scip, oldactivity) && !SCIPisInfinity(scip, rhs));
    115 }
    116
    117 /* SCIPisFeasLT cannot handle comparing different infinities. To prevent this, we make a case distinction. */
    118 if( !(SCIPisInfinity(scip, newactivity) || SCIPisInfinity(scip, -newactivity)) )
    119 {
    120 newviol = (SCIPisFeasLT(scip, newactivity, lhs) || SCIPisFeasGT(scip, newactivity, rhs));
    121 }
    122 else
    123 {
    124 newviol = (SCIPisInfinity(scip, -newactivity) && !SCIPisInfinity(scip, -lhs)) ||
    125 (SCIPisInfinity(scip, newactivity) && !SCIPisInfinity(scip, rhs));
    126 }
    127
    128 if( oldviol != newviol )
    129 {
    130 int rowpos;
    131 int violpos;
    132
    133 rowpos = SCIProwGetLPPos(row);
    134 assert(rowpos >= 0);
    135
    136 if( oldviol )
    137 {
    138 /* the row violation was repaired: remove row from violrows array, decrease violation count */
    139 violpos = violrowpos[rowpos];
    140 assert(0 <= violpos && violpos < *nviolrows);
    141 assert(violrows[violpos] == row);
    142 violrowpos[rowpos] = -1;
    143
    144 /* first, move the row to the end of the subset of violated rows with fractional variables */
    145 if( nfracsinrow[rowpos] > 0 )
    146 {
    147 assert(violpos < *nviolfracrows);
    148
    149 /* replace with last violated row containing fractional variables */
    150 if( violpos != *nviolfracrows - 1 )
    151 {
    152 violrows[violpos] = violrows[*nviolfracrows - 1];
    153 violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
    154 violpos = *nviolfracrows - 1;
    155 }
    156 (*nviolfracrows)--;
    157 }
    158
    159 assert(violpos >= *nviolfracrows);
    160
    161 /* swap row at the end of the violated array to the position of this row and decrease the counter */
    162 if( violpos != *nviolrows - 1 )
    163 {
    164 violrows[violpos] = violrows[*nviolrows - 1];
    165 violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
    166 }
    167 (*nviolrows)--;
    168 }
    169 else
    170 {
    171 /* the row is now violated: add row to violrows array, increase violation count */
    172 assert(violrowpos[rowpos] == -1);
    173 violrows[*nviolrows] = row;
    174 violrowpos[rowpos] = *nviolrows;
    175 (*nviolrows)++;
    176
    177 /* if the row contains fractional variables, swap with the last violated row that has no fractional variables
    178 * at position *nviolfracrows
    179 */
    180 if( nfracsinrow[rowpos] > 0 )
    181 {
    182 if( *nviolfracrows < *nviolrows - 1 )
    183 {
    184 assert(nfracsinrow[SCIProwGetLPPos(violrows[*nviolfracrows])] == 0);
    185
    186 violrows[*nviolrows - 1] = violrows[*nviolfracrows];
    187 violrowpos[SCIProwGetLPPos(violrows[*nviolrows - 1])] = *nviolrows - 1;
    188
    189 violrows[*nviolfracrows] = row;
    190 violrowpos[rowpos] = *nviolfracrows;
    191 }
    192 (*nviolfracrows)++;
    193 }
    194 }
    195 }
    196}
    197
    198/** update row activities after a variable's solution value changed */
    199static
    201 SCIP* scip, /**< SCIP data structure */
    202 SCIP_Real* activities, /**< LP row activities */
    203 SCIP_ROW** violrows, /**< array with currently violated rows */
    204 int* violrowpos, /**< position of LP rows in violrows array */
    205 int* nviolrows, /**< pointer to the number of currently violated rows */
    206 int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
    207 int* nfracsinrow, /**< array with number of fractional variables for every row */
    208 int nlprows, /**< number of rows in current LP */
    209 SCIP_VAR* var, /**< variable that has been changed */
    210 SCIP_Real oldsolval, /**< old solution value of variable */
    211 SCIP_Real newsolval /**< new solution value of variable */
    212 )
    213{
    214 SCIP_COL* col;
    215 SCIP_ROW** colrows;
    216 SCIP_Real* colvals;
    217 SCIP_Real delta;
    218 int ncolrows;
    219 int r;
    220
    221 assert(activities != NULL);
    222 assert(nviolrows != NULL);
    223 assert(0 <= *nviolrows && *nviolrows <= nlprows);
    224
    225 delta = newsolval - oldsolval;
    226 col = SCIPvarGetCol(var);
    227 colrows = SCIPcolGetRows(col);
    228 colvals = SCIPcolGetVals(col);
    229 ncolrows = SCIPcolGetNLPNonz(col);
    230 assert(ncolrows == 0 || (colrows != NULL && colvals != NULL));
    231
    232 for( r = 0; r < ncolrows; ++r )
    233 {
    234 SCIP_ROW* row;
    235 int rowpos;
    236
    237 row = colrows[r];
    238 rowpos = SCIProwGetLPPos(row);
    239 assert(-1 <= rowpos && rowpos < nlprows);
    240
    241 if( rowpos >= 0 && !SCIProwIsLocal(row) )
    242 {
    243 SCIP_Real oldactivity;
    244 SCIP_Real newactivity;
    245
    246 assert(SCIProwIsInLP(row));
    247
    248 /* update row activity */
    249 oldactivity = activities[rowpos];
    250 if( !SCIPisInfinity(scip, -oldactivity) && !SCIPisInfinity(scip, oldactivity) )
    251 {
    252 newactivity = oldactivity + delta * colvals[r];
    253 if( SCIPisInfinity(scip, newactivity) )
    254 newactivity = SCIPinfinity(scip);
    255 else if( SCIPisInfinity(scip, -newactivity) )
    256 newactivity = -SCIPinfinity(scip);
    257 activities[rowpos] = newactivity;
    258
    259 /* update row violation arrays */
    260 updateViolations(scip, row, violrows, violrowpos, nviolrows, nviolfracrows, nfracsinrow, oldactivity, newactivity);
    261 }
    262 }
    263 }
    264
    265 return SCIP_OKAY;
    266}
    267
    268/** returns a variable, that pushes activity of the row in the given direction with minimal negative impact on other rows;
    269 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
    270 * prefer fractional integers over other variables in order to become integral during the process;
    271 * shifting in a direction is forbidden, if this forces the objective value over the upper bound, or if the variable
    272 * was already shifted in the opposite direction
    273 */
    274static
    276 SCIP* scip, /**< SCIP data structure */
    277 SCIP_SOL* sol, /**< primal solution */
    278 SCIP_ROW* row, /**< LP row */
    279 SCIP_Real rowactivity, /**< activity of LP row */
    280 int direction, /**< should the activity be increased (+1) or decreased (-1)? */
    281 SCIP_Real* nincreases, /**< array with weighted number of increasings per variables */
    282 SCIP_Real* ndecreases, /**< array with weighted number of decreasings per variables */
    283 SCIP_Real increaseweight, /**< current weight of increase/decrease updates */
    284 SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
    285 SCIP_Real* oldsolval, /**< pointer to store old solution value of shifting variable */
    286 SCIP_Real* newsolval /**< pointer to store new (shifted) solution value of shifting variable */
    287 )
    288{
    289 SCIP_COL** rowcols;
    290 SCIP_Real* rowvals;
    291 int nrowcols;
    292 SCIP_Real activitydelta;
    293 SCIP_Real bestshiftscore;
    294 SCIP_Real bestdeltaobj;
    295 int c;
    296
    297 assert(direction == +1 || direction == -1);
    298 assert(nincreases != NULL);
    299 assert(ndecreases != NULL);
    300 assert(shiftvar != NULL);
    301 assert(oldsolval != NULL);
    302 assert(newsolval != NULL);
    303
    304 /* get row entries */
    305 rowcols = SCIProwGetCols(row);
    306 rowvals = SCIProwGetVals(row);
    307 nrowcols = SCIProwGetNLPNonz(row);
    308
    309 /* calculate how much the activity must be shifted in order to become feasible */
    310 activitydelta = (direction == +1 ? SCIProwGetLhs(row) - rowactivity : SCIProwGetRhs(row) - rowactivity);
    311 assert((direction == +1 && SCIPisPositive(scip, activitydelta))
    312 || (direction == -1 && SCIPisNegative(scip, activitydelta)));
    313
    314 /* select shifting variable */
    315 bestshiftscore = SCIP_REAL_MAX;
    316 bestdeltaobj = SCIPinfinity(scip);
    317 *shiftvar = NULL;
    318 *newsolval = 0.0;
    319 *oldsolval = 0.0;
    320 for( c = 0; c < nrowcols; ++c )
    321 {
    322 SCIP_COL* col;
    323 SCIP_VAR* var;
    324 SCIP_Real val;
    325 SCIP_Real solval;
    326 SCIP_Real shiftval;
    327 SCIP_Real shiftscore;
    328 SCIP_Bool isinteger;
    329 SCIP_Bool isfrac;
    330 SCIP_Bool increase;
    331
    332 col = rowcols[c];
    333 var = SCIPcolGetVar(col);
    334 val = rowvals[c];
    335 assert(!SCIPisZero(scip, val));
    336 solval = SCIPgetSolVal(scip, sol, var);
    337
    338 isinteger = SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS;
    339 isfrac = (isinteger && !SCIPisFeasIntegral(scip, solval));
    340 increase = (direction * val > 0.0);
    341
    342 /* calculate the score of the shifting (prefer smaller values) */
    343 if( isfrac )
    344 shiftscore = increase ? -1.0 / (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) + 1.0) :
    346 else
    347 {
    348 int probindex;
    349 probindex = SCIPvarGetProbindex(var);
    350
    351 if( increase )
    352 shiftscore = ndecreases[probindex]/increaseweight;
    353 else
    354 shiftscore = nincreases[probindex]/increaseweight;
    355 if( isinteger )
    356 shiftscore += 1.0;
    357 }
    358
    359 if( shiftscore <= bestshiftscore )
    360 {
    361 SCIP_Real deltaobj;
    362
    363 if( !increase )
    364 {
    365 /* shifting down */
    366 assert(direction * val < 0.0);
    367 if( isfrac )
    368 shiftval = SCIPfeasFloor(scip, solval);
    369 else
    370 {
    371 SCIP_Real lb;
    372
    373 assert(activitydelta/val < 0.0);
    374 shiftval = solval + activitydelta/val;
    375 assert(shiftval <= solval); /* may be equal due to numerical digit erasement in the subtraction */
    376 if( SCIPvarIsIntegral(var) )
    377 shiftval = SCIPfeasFloor(scip, shiftval);
    378 lb = SCIPvarGetLbGlobal(var);
    379 shiftval = MAX(shiftval, lb);
    380 }
    381 }
    382 else
    383 {
    384 /* shifting up */
    385 assert(direction * val > 0.0);
    386 if( isfrac )
    387 shiftval = SCIPfeasCeil(scip, solval);
    388 else
    389 {
    390 SCIP_Real ub;
    391
    392 assert(activitydelta/val > 0.0);
    393 shiftval = solval + activitydelta/val;
    394 assert(shiftval >= solval); /* may be equal due to numerical digit erasement in the subtraction */
    395 if( SCIPvarIsIntegral(var) )
    396 shiftval = SCIPfeasCeil(scip, shiftval);
    397 ub = SCIPvarGetUbGlobal(var);
    398 shiftval = MIN(shiftval, ub);
    399 }
    400 }
    401
    402 if( (SCIPisInfinity(scip, shiftval) && SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)))
    403 || (SCIPisInfinity(scip, -shiftval) && SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)))
    404 || SCIPisEQ(scip, shiftval, solval) )
    405 continue;
    406
    407 deltaobj = SCIPvarGetObj(var) * (shiftval - solval);
    408 if( shiftscore < bestshiftscore || deltaobj < bestdeltaobj )
    409 {
    410 bestshiftscore = shiftscore;
    411 bestdeltaobj = deltaobj;
    412 *shiftvar = var;
    413 *oldsolval = solval;
    414 *newsolval = shiftval;
    415 }
    416 }
    417 }
    418
    419 return SCIP_OKAY;
    420}
    421
    422/** returns a fractional variable, that has most impact on rows in opposite direction, i.e. that is most crucial to
    423 * fix in the other direction;
    424 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
    425 * shifting in a direction is forbidden, if this forces the objective value over the upper bound
    426 */
    427static
    429 SCIP* scip, /**< SCIP data structure */
    430 SCIP_SOL* sol, /**< primal solution */
    431 SCIP_Real minobj, /**< minimal objective value possible after shifting remaining fractional vars */
    432 SCIP_VAR** lpcands, /**< fractional variables in LP */
    433 int nlpcands, /**< number of fractional variables in LP */
    434 SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
    435 SCIP_Real* oldsolval, /**< old (fractional) solution value of shifting variable */
    436 SCIP_Real* newsolval /**< new (shifted) solution value of shifting variable */
    437 )
    438{
    439 SCIP_VAR* var;
    440 SCIP_Real solval;
    441 SCIP_Real shiftval;
    442 SCIP_Real obj;
    443 SCIP_Real deltaobj;
    444 SCIP_Real bestdeltaobj;
    445 int maxnlocks;
    446 int nlocks;
    447 int v;
    448
    449 assert(shiftvar != NULL);
    450 assert(oldsolval != NULL);
    451 assert(newsolval != NULL);
    452
    453 /* select shifting variable */
    454 maxnlocks = -1;
    455 bestdeltaobj = SCIPinfinity(scip);
    456 *shiftvar = NULL;
    457 for( v = 0; v < nlpcands; ++v )
    458 {
    459 var = lpcands[v];
    461
    462 solval = SCIPgetSolVal(scip, sol, var);
    463 if( !SCIPisFeasIntegral(scip, solval) )
    464 {
    465 obj = SCIPvarGetObj(var);
    466
    467 /* shifting down */
    469 if( nlocks >= maxnlocks )
    470 {
    471 shiftval = SCIPfeasFloor(scip, solval);
    472 deltaobj = obj * (shiftval - solval);
    473 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj - obj < SCIPgetCutoffbound(scip) )
    474 {
    475 maxnlocks = nlocks;
    476 bestdeltaobj = deltaobj;
    477 *shiftvar = var;
    478 *oldsolval = solval;
    479 *newsolval = shiftval;
    480 }
    481 }
    482
    483 /* shifting up */
    485 if( nlocks >= maxnlocks )
    486 {
    487 shiftval = SCIPfeasCeil(scip, solval);
    488 deltaobj = obj * (shiftval - solval);
    489 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj + obj < SCIPgetCutoffbound(scip) )
    490 {
    491 maxnlocks = nlocks;
    492 bestdeltaobj = deltaobj;
    493 *shiftvar = var;
    494 *oldsolval = solval;
    495 *newsolval = shiftval;
    496 }
    497 }
    498 }
    499 }
    500
    501 return SCIP_OKAY;
    502}
    503
    504/** adds a given value to the fractionality counters of the rows in which the given variable appears */
    505static
    507 int* nfracsinrow, /**< array to store number of fractional variables per row */
    508 SCIP_ROW** violrows, /**< array with currently violated rows */
    509 int* violrowpos, /**< position of LP rows in violrows array */
    510 int* nviolfracrows, /**< pointer to store the number of violated rows with fractional variables */
    511 int nviolrows, /**< the number of currently violated rows (stays unchanged in this method) */
    512 int nlprows, /**< number of rows in LP */
    513 SCIP_VAR* var, /**< variable for which the counting should be updated */
    514 int incval /**< value that should be added to the corresponding array entries */
    515 )
    516{
    517 SCIP_COL* col;
    518 SCIP_ROW** rows;
    519 int nrows;
    520 int r;
    521
    522 assert(incval != 0);
    523 assert(nviolrows >= *nviolfracrows);
    524 col = SCIPvarGetCol(var);
    525 rows = SCIPcolGetRows(col);
    526 nrows = SCIPcolGetNLPNonz(col);
    527 for( r = 0; r < nrows; ++r )
    528 {
    529 int rowlppos;
    530 int theviolrowpos;
    531
    532 rowlppos = SCIProwGetLPPos(rows[r]);
    533 assert(0 <= rowlppos && rowlppos < nlprows);
    534 assert(!SCIProwIsLocal(rows[r]) || violrowpos[rowlppos] == -1);
    535
    536 /* skip local rows */
    537 if( SCIProwIsLocal(rows[r]) )
    538 continue;
    539
    540 nfracsinrow[rowlppos] += incval;
    541 assert(nfracsinrow[rowlppos] >= 0);
    542 theviolrowpos = violrowpos[rowlppos];
    543
    544 /* swap positions in violrows array if fractionality has changed to 0 */
    545 if( theviolrowpos >= 0 )
    546 {
    547 /* first case: the number of fractional variables has become zero: swap row in violrows array to the
    548 * second part, containing only violated rows without fractional variables
    549 */
    550 if( nfracsinrow[rowlppos] == 0 )
    551 {
    552 assert(theviolrowpos <= *nviolfracrows - 1);
    553
    554 /* nothing to do if row is already at the end of the first part, otherwise, swap it to the last position
    555 * and decrease the counter */
    556 if( theviolrowpos < *nviolfracrows - 1 )
    557 {
    558 violrows[theviolrowpos] = violrows[*nviolfracrows - 1];
    559 violrows[*nviolfracrows - 1] = rows[r];
    560
    561 violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
    562 violrowpos[rowlppos] = *nviolfracrows - 1;
    563 }
    564 (*nviolfracrows)--;
    565 }
    566 /* second interesting case: the number of fractional variables was zero before, swap it with the first
    567 * violated row without fractional variables
    568 */
    569 else if( nfracsinrow[rowlppos] == incval )
    570 {
    571 assert(theviolrowpos >= *nviolfracrows);
    572
    573 /* nothing to do if the row is exactly located at index *nviolfracrows */
    574 if( theviolrowpos > *nviolfracrows )
    575 {
    576 violrows[theviolrowpos] = violrows[*nviolfracrows];
    577 violrows[*nviolfracrows] = rows[r];
    578
    579 violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
    580 violrowpos[rowlppos] = *nviolfracrows;
    581 }
    582 (*nviolfracrows)++;
    583 }
    584 }
    585 }
    586}
    587
    588
    589/*
    590 * Callback methods
    591 */
    592
    593/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    594static
    595SCIP_DECL_HEURCOPY(heurCopyShifting)
    596{ /*lint --e{715}*/
    597 assert(scip != NULL);
    598 assert(heur != NULL);
    599
    601
    602 /* call inclusion method of primal heuristic */
    604
    605 return SCIP_OKAY;
    606}
    607
    608
    609/** initialization method of primal heuristic (called after problem was transformed) */
    610static
    611SCIP_DECL_HEURINIT(heurInitShifting) /*lint --e{715}*/
    612{ /*lint --e{715}*/
    613 SCIP_HEURDATA* heurdata;
    614
    615 assert(SCIPheurGetData(heur) == NULL);
    616
    618
    619 /* create heuristic data */
    620 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    621 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    622 heurdata->lastlp = -1;
    623
    624 /* create random number generator */
    625 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    627
    628 SCIPheurSetData(heur, heurdata);
    629
    630 return SCIP_OKAY;
    631}
    632
    633/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    634static
    635SCIP_DECL_HEUREXIT(heurExitShifting) /*lint --e{715}*/
    636{ /*lint --e{715}*/
    637 SCIP_HEURDATA* heurdata;
    638
    640
    641 /* free heuristic data */
    642 heurdata = SCIPheurGetData(heur);
    643 assert(heurdata != NULL);
    644 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    645
    646 /* free random number generator */
    647 SCIPfreeRandom(scip, &heurdata->randnumgen);
    648
    649 SCIPfreeBlockMemory(scip, &heurdata);
    650 SCIPheurSetData(heur, NULL);
    651
    652 return SCIP_OKAY;
    653}
    654
    655/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    656static
    657SCIP_DECL_HEURINITSOL(heurInitsolShifting)
    658{
    659 SCIP_HEURDATA* heurdata;
    660
    662
    663 heurdata = SCIPheurGetData(heur);
    664 assert(heurdata != NULL);
    665 heurdata->lastlp = -1;
    666
    667 return SCIP_OKAY;
    668}
    669
    670
    671/** execution method of primal heuristic */
    672static
    673SCIP_DECL_HEUREXEC(heurExecShifting) /*lint --e{715}*/
    674{ /*lint --e{715}*/
    675 SCIP_HEURDATA* heurdata;
    676 SCIP_SOL* sol;
    677 SCIP_VAR** lpcands;
    678 SCIP_Real* lpcandssol;
    679 SCIP_ROW** lprows;
    680 SCIP_Real* activities;
    681 SCIP_ROW** violrows;
    682 SCIP_Real* nincreases;
    683 SCIP_Real* ndecreases;
    684 int* violrowpos;
    685 int* nfracsinrow;
    686 SCIP_Real increaseweight;
    687 SCIP_Real obj;
    688 SCIP_Real bestshiftval;
    689 SCIP_Real minobj;
    690 int nvars;
    691 int nfrac;
    692 int nlpcands;
    693 int nlprows;
    694 int nviolrows;
    695 int nviolfracrows;
    696 int nprevviolrows;
    697 int minnviolrows;
    698 int nnonimprovingshifts;
    699 int c;
    700 int r;
    701 SCIP_Longint nlps;
    702 SCIP_Longint ncalls;
    703 SCIP_Longint nsolsfound;
    705
    706 assert(scip != NULL);
    707 assert(result != NULL);
    708 assert(SCIPhasCurrentNodeLP(scip));
    709
    711
    712 *result = SCIP_DIDNOTRUN;
    713
    714 /* only call heuristic, if an optimal LP solution is at hand */
    716 return SCIP_OKAY;
    717
    718 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    720 return SCIP_OKAY;
    721
    722 /* get heuristic data */
    723 heurdata = SCIPheurGetData(heur);
    724 assert(heurdata != NULL);
    725
    726 /* don't call heuristic, if we have already processed the current LP solution */
    727 nlps = SCIPgetNLPs(scip);
    728 if( nlps == heurdata->lastlp )
    729 return SCIP_OKAY;
    730 heurdata->lastlp = nlps;
    731
    732 /* don't call heuristic, if it was not successful enough in the past */
    733 ncalls = SCIPheurGetNCalls(heur);
    734 nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + SCIPheurGetNSolsFound(heur);
    736 if( nnodes % ((ncalls/100)/(nsolsfound+1)+1) != 0 )
    737 return SCIP_OKAY;
    738
    739 /* get fractional variables, that should be integral */
    740 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL, NULL) );
    741
    742 /* only call heuristic, if LP solution is fractional */
    743 if( nlpcands == 0 )
    744 return SCIP_OKAY;
    745
    746 *result = SCIP_DIDNOTFIND;
    747
    748 /* get LP rows */
    749 SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
    750
    751 SCIPdebugMsg(scip, "executing shifting heuristic: %d LP rows, %d LP candidates\n", nlprows, nlpcands);
    752
    753 /* get memory for activities, violated rows, and row violation positions */
    754 nvars = SCIPgetNVars(scip);
    755 nfrac = nlpcands;
    756 SCIP_CALL( SCIPallocBufferArray(scip, &activities, nlprows) );
    757 SCIP_CALL( SCIPallocBufferArray(scip, &violrows, nlprows) );
    758 SCIP_CALL( SCIPallocBufferArray(scip, &violrowpos, nlprows) );
    759 SCIP_CALL( SCIPallocBufferArray(scip, &nfracsinrow, nlprows) );
    760 SCIP_CALL( SCIPallocBufferArray(scip, &nincreases, nvars) );
    761 SCIP_CALL( SCIPallocBufferArray(scip, &ndecreases, nvars) );
    762 BMSclearMemoryArray(nfracsinrow, nlprows);
    763 BMSclearMemoryArray(nincreases, nvars);
    764 BMSclearMemoryArray(ndecreases, nvars);
    765
    766 /* get the activities for all globally valid rows;
    767 * the rows should be feasible, but due to numerical inaccuracies in the LP solver, they can be violated
    768 */
    769 nviolrows = 0;
    770 for( r = 0; r < nlprows; ++r )
    771 {
    772 SCIP_ROW* row;
    773
    774 row = lprows[r];
    775 assert(SCIProwGetLPPos(row) == r);
    776
    777 if( !SCIProwIsLocal(row) )
    778 {
    779 activities[r] = SCIPgetRowActivity(scip, row);
    780 if( SCIPisFeasLT(scip, activities[r], SCIProwGetLhs(row))
    781 || SCIPisFeasGT(scip, activities[r], SCIProwGetRhs(row)) )
    782 {
    783 violrows[nviolrows] = row;
    784 violrowpos[r] = nviolrows;
    785 nviolrows++;
    786 }
    787 else
    788 violrowpos[r] = -1;
    789 }
    790 else
    791 violrowpos[r] = -1;
    792 }
    793
    794 nviolfracrows = 0;
    795 /* calc the current number of fractional variables in rows */
    796 for( c = 0; c < nlpcands; ++c )
    797 addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, lpcands[c], +1);
    798
    799 /* get the working solution from heuristic's local data */
    800 sol = heurdata->sol;
    801 assert(sol != NULL);
    802
    803 /* copy the current LP solution to the working solution */
    805
    806 /* calculate the minimal objective value possible after rounding fractional variables */
    807 minobj = SCIPgetSolTransObj(scip, sol);
    808 assert(minobj < SCIPgetCutoffbound(scip));
    809 for( c = 0; c < nlpcands; ++c )
    810 {
    811 obj = SCIPvarGetObj(lpcands[c]);
    812 bestshiftval = obj > 0.0 ? SCIPfeasFloor(scip, lpcandssol[c]) : SCIPfeasCeil(scip, lpcandssol[c]);
    813 minobj += obj * (bestshiftval - lpcandssol[c]);
    814 }
    815
    816 /* try to shift remaining variables in order to become/stay feasible */
    817 nnonimprovingshifts = 0;
    818 minnviolrows = INT_MAX;
    819 increaseweight = 1.0;
    820 while( (nfrac > 0 || nviolrows > 0) && nnonimprovingshifts < MAXSHIFTINGS )
    821 {
    822 SCIP_VAR* shiftvar;
    823 SCIP_Real oldsolval;
    824 SCIP_Real newsolval;
    825 SCIP_Bool oldsolvalisfrac;
    826 int probindex;
    827
    828 SCIPdebugMsg(scip, "shifting heuristic: nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g), cutoff=%g\n",
    829 nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj),
    831
    832 nprevviolrows = nviolrows;
    833
    834 /* choose next variable to process:
    835 * - if a violated row exists, shift a variable decreasing the violation, that has least impact on other rows
    836 * - otherwise, shift a variable, that has strongest devastating impact on rows in opposite direction
    837 */
    838 shiftvar = NULL;
    839 oldsolval = 0.0;
    840 newsolval = 0.0;
    841 if( nviolrows > 0 && (nfrac == 0 || nnonimprovingshifts < MAXSHIFTINGS-1) )
    842 {
    843 SCIP_ROW* row;
    844 int rowidx;
    845 int rowpos;
    846 int direction;
    847
    848 assert(nviolfracrows == 0 || nfrac > 0);
    849 /* violated rows containing fractional variables are preferred; if such a row exists, choose the last one from the list
    850 * (at position nviolfracrows - 1) because removing this row will cause one swapping operation less than other rows
    851 */
    852 if( nviolfracrows > 0 )
    853 rowidx = nviolfracrows - 1;
    854 else
    855 /* there is no violated row containing a fractional variable, select a violated row uniformly at random */
    856 rowidx = SCIPrandomGetInt(heurdata->randnumgen, 0, nviolrows-1);
    857
    858 assert(0 <= rowidx && rowidx < nviolrows);
    859 row = violrows[rowidx];
    860 rowpos = SCIProwGetLPPos(row);
    861 assert(0 <= rowpos && rowpos < nlprows);
    862 assert(violrowpos[rowpos] == rowidx);
    863 assert(nfracsinrow[rowpos] == 0 || rowidx == nviolfracrows - 1);
    864
    865 SCIPdebugMsg(scip, "shifting heuristic: try to fix violated row <%s>: %g <= %g <= %g\n",
    866 SCIProwGetName(row), SCIProwGetLhs(row), activities[rowpos], SCIProwGetRhs(row));
    868
    869 /* get direction in which activity must be shifted */
    870 assert(SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row))
    871 || SCIPisFeasGT(scip, activities[rowpos], SCIProwGetRhs(row)));
    872 direction = SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row)) ? +1 : -1;
    873
    874 /* search a variable that can shift the activity in the necessary direction */
    875 SCIP_CALL( selectShifting(scip, sol, row, activities[rowpos], direction,
    876 nincreases, ndecreases, increaseweight, &shiftvar, &oldsolval, &newsolval) );
    877 }
    878
    879 if( shiftvar == NULL && nfrac > 0 )
    880 {
    881 SCIPdebugMsg(scip, "shifting heuristic: search rounding variable and try to stay feasible\n");
    882 SCIP_CALL( selectEssentialRounding(scip, sol, minobj, lpcands, nlpcands, &shiftvar, &oldsolval, &newsolval) );
    883 }
    884
    885 /* check, whether shifting was possible */
    886 if( shiftvar == NULL || SCIPisEQ(scip, oldsolval, newsolval) )
    887 {
    888 SCIPdebugMsg(scip, "shifting heuristic: -> didn't find a shifting variable\n");
    889 break;
    890 }
    891
    892 SCIPdebugMsg(scip, "shifting heuristic: -> shift var <%s>[%g,%g], type=%d, oldval=%g, newval=%g, obj=%g\n",
    893 SCIPvarGetName(shiftvar), SCIPvarGetLbGlobal(shiftvar), SCIPvarGetUbGlobal(shiftvar), SCIPvarGetType(shiftvar),
    894 oldsolval, newsolval, SCIPvarGetObj(shiftvar));
    895
    896 /* update row activities of globally valid rows */
    897 SCIP_CALL( updateActivities(scip, activities, violrows, violrowpos, &nviolrows, &nviolfracrows, nfracsinrow, nlprows,
    898 shiftvar, oldsolval, newsolval) );
    899 if( nviolrows >= nprevviolrows )
    900 nnonimprovingshifts++;
    901 else if( nviolrows < minnviolrows )
    902 {
    903 minnviolrows = nviolrows;
    904 nnonimprovingshifts = 0;
    905 }
    906
    907 /* store new solution value and decrease fractionality counter */
    908 SCIP_CALL( SCIPsetSolVal(scip, sol, shiftvar, newsolval) );
    909
    910 /* update fractionality counter and minimal objective value possible after shifting remaining variables */
    911 oldsolvalisfrac = (!SCIPisFeasIntegral(scip, oldsolval) && SCIPvarIsIntegral(shiftvar) && !SCIPvarIsImpliedIntegral(shiftvar));
    912 obj = SCIPvarGetObj(shiftvar);
    913 if( SCIPvarGetType(shiftvar) != SCIP_VARTYPE_CONTINUOUS && oldsolvalisfrac )
    914 {
    915 assert(SCIPisFeasIntegral(scip, newsolval));
    916 nfrac--;
    917 nnonimprovingshifts = 0;
    918 minnviolrows = INT_MAX;
    919 addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, shiftvar, -1);
    920
    921 /* the rounding was already calculated into the minobj -> update only if rounding in "wrong" direction */
    922 if( obj > 0.0 && newsolval > oldsolval )
    923 minobj += obj;
    924 else if( obj < 0.0 && newsolval < oldsolval )
    925 minobj -= obj;
    926 }
    927 else
    928 {
    929 /* update minimal possible objective value */
    930 minobj += obj * (newsolval - oldsolval);
    931 }
    932
    933 /* update increase/decrease arrays */
    934 if( !oldsolvalisfrac )
    935 {
    936 probindex = SCIPvarGetProbindex(shiftvar);
    937 assert(0 <= probindex && probindex < nvars);
    938 increaseweight *= WEIGHTFACTOR;
    939 if( newsolval < oldsolval )
    940 ndecreases[probindex] += increaseweight;
    941 else
    942 nincreases[probindex] += increaseweight;
    943 if( increaseweight >= 1e+09 )
    944 {
    945 int i;
    946
    947 for( i = 0; i < nvars; ++i )
    948 {
    949 nincreases[i] /= increaseweight;
    950 ndecreases[i] /= increaseweight;
    951 }
    952 increaseweight = 1.0;
    953 }
    954 }
    955
    956 SCIPdebugMsg(scip, "shifting heuristic: -> nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
    957 nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj));
    958 }
    959
    960 /* check, if the new solution is feasible */
    961 if( nfrac == 0 && nviolrows == 0 )
    962 {
    963 SCIP_Bool stored;
    964
    965 /* check solution for feasibility, and add it to solution store if possible
    966 * neither integrality nor feasibility of LP rows has to be checked, because this is already
    967 * done in the shifting heuristic itself; however, we better check feasibility of LP rows,
    968 * because of numerical problems with activity updating
    969 */
    970 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, FALSE, TRUE, &stored) );
    971
    972 if( stored )
    973 {
    974 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
    976 *result = SCIP_FOUNDSOL;
    977 }
    978 }
    979
    980 /* free memory buffers */
    981 SCIPfreeBufferArray(scip, &ndecreases);
    982 SCIPfreeBufferArray(scip, &nincreases);
    983 SCIPfreeBufferArray(scip, &nfracsinrow);
    984 SCIPfreeBufferArray(scip, &violrowpos);
    985 SCIPfreeBufferArray(scip, &violrows);
    986 SCIPfreeBufferArray(scip, &activities);
    987
    988 return SCIP_OKAY;
    989}
    990
    991
    992/*
    993 * heuristic specific interface methods
    994 */
    995
    996/** creates the shifting heuristic with infeasibility recovering and includes it in SCIP */
    998 SCIP* scip /**< SCIP data structure */
    999 )
    1000{
    1001 SCIP_HEUR* heur;
    1002
    1003 /* include primal heuristic */
    1006 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecShifting, NULL) );
    1007
    1008 assert(heur != NULL);
    1009
    1010 /* primal heuristic is safe to use in exact solving mode */
    1011 SCIPheurMarkExact(heur);
    1012
    1013 /* set non-NULL pointers to callback methods */
    1014 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyShifting) );
    1015 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitShifting) );
    1016 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitShifting) );
    1017 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolShifting) );
    1018
    1019 return SCIP_OKAY;
    1020}
    1021
    SCIP_Real * r
    Definition: circlepacking.c:59
    #define NULL
    Definition: def.h:257
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL(x)
    Definition: def.h:364
    #define nnodes
    Definition: gastrans.c:74
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPincludeHeurShifting(SCIP *scip)
    SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
    Definition: scip_branch.c:402
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
    Definition: lp.c:17555
    SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
    Definition: lp.c:17545
    int SCIPcolGetNLPNonz(SCIP_COL *col)
    Definition: lp.c:17534
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    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)
    Definition: scip_heur.c:122
    SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
    Definition: heur.c:1603
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
    Definition: heur.c:1613
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
    Definition: scip_heur.c:231
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
    Definition: scip_lp.c:576
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    SCIP_Real SCIPgetLPObjval(SCIP *scip)
    Definition: scip_lp.c:253
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    int SCIProwGetNLPNonz(SCIP_ROW *row)
    Definition: lp.c:17621
    int SCIProwGetLPPos(SCIP_ROW *row)
    Definition: lp.c:17895
    SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
    Definition: lp.c:17795
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:2068
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2351
    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)
    Definition: scip_sol.c:4017
    SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1293
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1890
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1569
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2003
    SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
    Definition: scip_sol.c:2134
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(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 SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23715
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23694
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
    Definition: misc.c:10223
    static SCIP_RETCODE selectEssentialRounding(SCIP *scip, SCIP_SOL *sol, SCIP_Real minobj, SCIP_VAR **lpcands, int nlpcands, SCIP_VAR **shiftvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
    static SCIP_DECL_HEURINITSOL(heurInitsolShifting)
    #define HEUR_TIMING
    Definition: heur_shifting.c:59
    static void addFracCounter(int *nfracsinrow, SCIP_ROW **violrows, int *violrowpos, int *nviolfracrows, int nviolrows, int nlprows, SCIP_VAR *var, int incval)
    static SCIP_DECL_HEUREXIT(heurExitShifting)
    #define HEUR_FREQOFS
    Definition: heur_shifting.c:57
    #define HEUR_DESC
    Definition: heur_shifting.c:53
    #define HEUR_DISPCHAR
    Definition: heur_shifting.c:54
    #define HEUR_MAXDEPTH
    Definition: heur_shifting.c:58
    #define HEUR_PRIORITY
    Definition: heur_shifting.c:55
    static SCIP_DECL_HEUREXEC(heurExecShifting)
    static SCIP_DECL_HEURCOPY(heurCopyShifting)
    #define HEUR_NAME
    Definition: heur_shifting.c:52
    static SCIP_RETCODE updateActivities(SCIP *scip, SCIP_Real *activities, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, int nlprows, SCIP_VAR *var, SCIP_Real oldsolval, SCIP_Real newsolval)
    static void updateViolations(SCIP *scip, SCIP_ROW *row, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, SCIP_Real oldactivity, SCIP_Real newactivity)
    Definition: heur_shifting.c:82
    #define DEFAULT_RANDSEED
    Definition: heur_shifting.c:64
    static SCIP_DECL_HEURINIT(heurInitShifting)
    #define HEUR_FREQ
    Definition: heur_shifting.c:56
    static SCIP_RETCODE selectShifting(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *row, SCIP_Real rowactivity, int direction, SCIP_Real *nincreases, SCIP_Real *ndecreases, SCIP_Real increaseweight, SCIP_VAR **shiftvar, SCIP_Real *oldsolval, SCIP_Real *newsolval)
    #define HEUR_USESSUBSCIP
    Definition: heur_shifting.c:60
    #define WEIGHTFACTOR
    Definition: heur_shifting.c:63
    #define MAXSHIFTINGS
    Definition: heur_shifting.c:62
    LP rounding heuristic that tries to recover from intermediate infeasibilities and shifts continuous v...
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for primal heuristics
    public methods for LP management
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    public methods for problem variables
    public methods for branching rule plugins and branching
    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 global and local (sub)problems
    public methods for random numbers
    public methods for solutions
    public methods for querying solving statistics
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141