SCIP

    Solving Constraint Integer Programs

    heur_intshifting.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_intshifting.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief LP rounding heuristic that tries to recover from intermediate infeasibilities, shifts integer variables, and
    28 * solves a final LP to calculate feasible values for continuous variables
    29 * @author Tobias Achterberg
    30 */
    31
    32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    33
    36#include "scip/pub_heur.h"
    37#include "scip/pub_lp.h"
    38#include "scip/pub_message.h"
    39#include "scip/pub_misc.h"
    40#include "scip/pub_var.h"
    41#include "scip/scip_branch.h"
    42#include "scip/scip_exact.h"
    43#include "scip/scip_general.h"
    44#include "scip/scip_heur.h"
    45#include "scip/scip_lp.h"
    46#include "scip/scip_mem.h"
    47#include "scip/scip_message.h"
    48#include "scip/scip_numerics.h"
    49#include "scip/scip_prob.h"
    51#include "scip/scip_sol.h"
    53
    54
    55#define HEUR_NAME "intshifting"
    56#define HEUR_DESC "LP rounding heuristic with infeasibility recovering and final LP solving"
    57#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_ROUNDING
    58#define HEUR_PRIORITY -10000
    59#define HEUR_FREQ 10
    60#define HEUR_FREQOFS 0
    61#define HEUR_MAXDEPTH -1
    62#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
    63#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    64
    65#define MAXSHIFTINGS 50 /**< maximal number of non improving shiftings */
    66#define WEIGHTFACTOR 1.1
    67#define DEFAULT_RANDSEED 17
    68
    69/* locally defined heuristic data */
    70struct SCIP_HeurData
    71{
    72 SCIP_SOL* sol; /**< working solution */
    73 SCIP_Longint lastlp; /**< last LP number where the heuristic was applied */
    74 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    75};
    76
    77
    78/*
    79 * local methods
    80 */
    81
    82/** update row violation arrays after a row's activity value changed */
    83static
    85 SCIP* scip, /**< SCIP data structure */
    86 SCIP_ROW* row, /**< LP row */
    87 SCIP_ROW** violrows, /**< array with currently violated rows */
    88 int* violrowpos, /**< position of LP rows in violrows array */
    89 int* nviolrows, /**< pointer to the number of currently violated rows */
    90 int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
    91 int* nfracsinrow, /**< array with number of fractional variables for every row */
    92 SCIP_Real oldminactivity, /**< old minimal activity value of LP row */
    93 SCIP_Real oldmaxactivity, /**< old maximal activity value of LP row */
    94 SCIP_Real newminactivity, /**< new minimal activity value of LP row */
    95 SCIP_Real newmaxactivity /**< new maximal activity value of LP row */
    96 )
    97{
    98 SCIP_Real lhs;
    99 SCIP_Real rhs;
    100 SCIP_Bool oldviol;
    101 SCIP_Bool newviol;
    102
    103 assert(violrows != NULL);
    104 assert(violrowpos != NULL);
    105 assert(nviolrows != NULL);
    106
    107 lhs = SCIProwGetLhs(row);
    108 rhs = SCIProwGetRhs(row);
    109
    110 /* SCIPisFeasLT cannot handle comparing different infinities. To prevent this, we make a case distinction. */
    111 if( ! (SCIPisInfinity(scip, oldmaxactivity) || SCIPisInfinity(scip, -oldmaxactivity)
    112 || SCIPisInfinity(scip, oldminactivity) || SCIPisInfinity(scip, -oldminactivity)) )
    113 {
    114 oldviol = (SCIPisFeasLT(scip, oldmaxactivity, lhs) || SCIPisFeasGT(scip, oldminactivity, rhs));
    115 }
    116 else
    117 {
    118 oldviol = (SCIPisInfinity(scip, -oldmaxactivity) && !SCIPisInfinity(scip, -lhs)) ||
    119 (SCIPisInfinity(scip, oldminactivity) && !SCIPisInfinity(scip, rhs));
    120 }
    121
    122 /* SCIPisFeasLT cannot handle comparing different infinities. To prevent this, we make a case distinction. */
    123 if( ! (SCIPisInfinity(scip, newmaxactivity) || SCIPisInfinity(scip, -newmaxactivity)
    124 || SCIPisInfinity(scip, newminactivity) || SCIPisInfinity(scip, -newminactivity)) )
    125 {
    126 newviol = (SCIPisFeasLT(scip, newmaxactivity, lhs) || SCIPisFeasGT(scip, newminactivity, rhs));
    127 }
    128 else
    129 {
    130 newviol = (SCIPisInfinity(scip, -newmaxactivity) && !SCIPisInfinity(scip, -lhs)) ||
    131 (SCIPisInfinity(scip, newminactivity) && !SCIPisInfinity(scip, rhs));
    132 }
    133
    134 if( oldviol != newviol )
    135 {
    136 int rowpos;
    137 int violpos;
    138
    139 rowpos = SCIProwGetLPPos(row);
    140 assert(rowpos >= 0);
    141
    142 if( oldviol )
    143 {
    144 /* the row violation was repaired: remove row from violrows array, decrease violation count */
    145 violpos = violrowpos[rowpos];
    146 assert(0 <= violpos && violpos < *nviolrows);
    147 assert(violrows[violpos] == row);
    148 violrowpos[rowpos] = -1;
    149 /* first, move the row to the end of the subset of violated rows with fractional variables */
    150 if( nfracsinrow[rowpos] > 0 )
    151 {
    152 violrows[violpos] = violrows[*nviolrows-1];
    153 assert(violpos < *nviolfracrows);
    154
    155 /* replace with last violated row containing fractional variables */
    156 if( violpos != *nviolfracrows - 1 )
    157 {
    158 violrows[violpos] = violrows[*nviolfracrows - 1];
    159 violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
    160 violpos = *nviolfracrows - 1;
    161 }
    162 (*nviolfracrows)--;
    163 }
    164
    165 assert(violpos >= *nviolfracrows);
    166
    167 /* swap row at the end of the violated array to the position of this row and decrease the counter */
    168 if( violpos != *nviolrows - 1 )
    169 {
    170 violrows[violpos] = violrows[*nviolrows - 1];
    171 violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
    172 }
    173 (*nviolrows)--;
    174 }
    175 else
    176 {
    177 /* the row is now violated: add row to violrows array, increase violation count */
    178 assert(violrowpos[rowpos] == -1);
    179 violrows[*nviolrows] = row;
    180 violrowpos[rowpos] = *nviolrows;
    181 (*nviolrows)++;
    182
    183 /* if the row contains fractional variables, swap with the last violated row that has no fractional variables
    184 * at position *nviolfracrows
    185 */
    186 if( nfracsinrow[rowpos] > 0 )
    187 {
    188 if( *nviolfracrows < *nviolrows - 1 )
    189 {
    190 assert(nfracsinrow[SCIProwGetLPPos(violrows[*nviolfracrows])] == 0);
    191
    192 violrows[*nviolrows - 1] = violrows[*nviolfracrows];
    193 violrowpos[SCIProwGetLPPos(violrows[*nviolrows - 1])] = *nviolrows - 1;
    194
    195 violrows[*nviolfracrows] = row;
    196 violrowpos[rowpos] = *nviolfracrows;
    197 }
    198 (*nviolfracrows)++;
    199 }
    200 }
    201 }
    202}
    203
    204/** update row activities after a variable's solution value changed */
    205static
    207 SCIP* scip, /**< SCIP data structure */
    208 SCIP_Real* minactivities, /**< LP row minimal activities */
    209 SCIP_Real* maxactivities, /**< LP row maximal activities */
    210 SCIP_ROW** violrows, /**< array with currently violated rows */
    211 int* violrowpos, /**< position of LP rows in violrows array */
    212 int* nviolrows, /**< pointer to the number of currently violated rows */
    213 int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
    214 int* nfracsinrow, /**< array with number of fractional variables for every row */
    215 int nlprows, /**< number of rows in current LP */
    216 SCIP_VAR* var, /**< variable that has been changed */
    217 SCIP_Real oldsolval, /**< old solution value of variable */
    218 SCIP_Real newsolval /**< new solution value of variable */
    219 )
    220{
    221 SCIP_COL* col;
    222 SCIP_ROW** colrows;
    223 SCIP_Real* colvals;
    224 SCIP_Real delta;
    225 int ncolrows;
    226 int r;
    227
    228 assert(minactivities != NULL);
    229 assert(maxactivities != NULL);
    230 assert(nviolrows != NULL);
    231 assert(0 <= *nviolrows && *nviolrows <= nlprows);
    233
    234 delta = newsolval - oldsolval;
    235 col = SCIPvarGetCol(var);
    236 colrows = SCIPcolGetRows(col);
    237 colvals = SCIPcolGetVals(col);
    238 ncolrows = SCIPcolGetNLPNonz(col);
    239 assert(ncolrows == 0 || (colrows != NULL && colvals != NULL));
    240
    241 for( r = 0; r < ncolrows; ++r )
    242 {
    243 SCIP_ROW* row;
    244 int rowpos;
    245
    246 row = colrows[r];
    247 rowpos = SCIProwGetLPPos(row);
    248 assert(-1 <= rowpos && rowpos < nlprows);
    249
    250 if( rowpos >= 0 && !SCIProwIsLocal(row) )
    251 {
    252 SCIP_Real oldminactivity;
    253 SCIP_Real oldmaxactivity;
    254 SCIP_Real newminactivity;
    255 SCIP_Real newmaxactivity;
    256
    257 assert(SCIProwIsInLP(row));
    258
    259 /* update row activities */
    260 oldminactivity = minactivities[rowpos];
    261 oldmaxactivity = maxactivities[rowpos];
    262
    263 if( !SCIPisInfinity(scip, -oldminactivity) )
    264 {
    265 newminactivity = oldminactivity + delta * colvals[r];
    266 minactivities[rowpos] = newminactivity;
    267 }
    268 else
    269 newminactivity = -SCIPinfinity(scip);
    270 if( !SCIPisInfinity(scip, oldmaxactivity) )
    271 {
    272 newmaxactivity = oldmaxactivity + delta * colvals[r];
    273 maxactivities[rowpos] = newmaxactivity;
    274 }
    275 else
    276 newmaxactivity = SCIPinfinity(scip);
    277
    278 /* update row violation arrays */
    279 updateViolations(scip, row, violrows, violrowpos, nviolrows, nviolfracrows, nfracsinrow, oldminactivity, oldmaxactivity,
    280 newminactivity, newmaxactivity);
    281 }
    282 }
    283
    284 return SCIP_OKAY;
    285}
    286
    287/** returns an integer variable, that pushes activity of the row in the given direction with minimal negative impact on
    288 * other rows;
    289 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
    290 * prefer fractional integers over other variables in order to become integral during the process;
    291 * shifting in a direction is forbidden, if this forces the objective value over the upper bound, or if the variable
    292 * was already shifted in the opposite direction
    293 */
    294static
    296 SCIP* scip, /**< SCIP data structure */
    297 SCIP_SOL* sol, /**< primal solution */
    298 SCIP_ROW* row, /**< LP row */
    299 SCIP_Real rowactivity, /**< activity of LP row */
    300 int direction, /**< should the activity be increased (+1) or decreased (-1)? */
    301 SCIP_Real* nincreases, /**< array with weighted number of increasings per variables */
    302 SCIP_Real* ndecreases, /**< array with weighted number of decreasings per variables */
    303 SCIP_Real increaseweight, /**< current weight of increase/decrease updates */
    304 SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
    305 SCIP_Real* oldsolval, /**< pointer to store old solution value of shifting variable */
    306 SCIP_Real* newsolval /**< pointer to store new (shifted) solution value of shifting variable */
    307 )
    308{
    309 SCIP_COL** rowcols;
    310 SCIP_Real* rowvals;
    311 int nrowcols;
    312 SCIP_Real activitydelta;
    313 SCIP_Real bestshiftscore;
    314 SCIP_Real bestdeltaobj;
    315 int c;
    316
    317 assert(direction == +1 || direction == -1);
    318 assert(nincreases != NULL);
    319 assert(ndecreases != NULL);
    320 assert(shiftvar != NULL);
    321 assert(oldsolval != NULL);
    322 assert(newsolval != NULL);
    323
    324 /* get row entries */
    325 rowcols = SCIProwGetCols(row);
    326 rowvals = SCIProwGetVals(row);
    327 nrowcols = SCIProwGetNLPNonz(row);
    328
    329 /* calculate how much the activity must be shifted in order to become feasible */
    330 activitydelta = (direction == +1 ? SCIProwGetLhs(row) - rowactivity : SCIProwGetRhs(row) - rowactivity);
    331 assert((direction == +1 && SCIPisPositive(scip, activitydelta))
    332 || (direction == -1 && SCIPisNegative(scip, activitydelta)));
    333
    334 /* select shifting variable */
    335 bestshiftscore = SCIP_REAL_MAX;
    336 bestdeltaobj = SCIPinfinity(scip);
    337 *shiftvar = NULL;
    338 *newsolval = 0.0;
    339 *oldsolval = 0.0;
    340 for( c = 0; c < nrowcols; ++c )
    341 {
    342 SCIP_COL* col;
    343 SCIP_VAR* var;
    344 SCIP_Real val;
    345 SCIP_Real solval;
    346 SCIP_Real shiftval;
    347 SCIP_Real shiftscore;
    348 SCIP_Bool isfrac;
    349 SCIP_Bool increase;
    350 int probindex;
    351
    352 col = rowcols[c];
    353 var = SCIPcolGetVar(col);
    354 val = rowvals[c];
    355 assert(!SCIPisZero(scip, val));
    356 solval = SCIPgetSolVal(scip, sol, var);
    357
    358 /* only accept integer variables */
    360 continue;
    361
    362 isfrac = !SCIPisFeasIntegral(scip, solval);
    363 increase = (direction * val > 0.0);
    364 probindex = SCIPvarGetProbindex(var);
    365
    366 /* calculate the score of the shifting (prefer smaller values) */
    367 if( isfrac )
    368 shiftscore = increase ? -1.0 / (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) + 1.0) :
    370 else
    371 {
    372 if( increase )
    373 shiftscore = ndecreases[probindex]/increaseweight;
    374 else
    375 shiftscore = nincreases[probindex]/increaseweight;
    376 shiftscore += 1.0;
    377 }
    378
    379 if( shiftscore <= bestshiftscore )
    380 {
    381 SCIP_Real deltaobj;
    382
    383 if( !increase )
    384 {
    385 /* shifting down */
    386 assert(direction * val < 0.0);
    387 if( isfrac )
    388 shiftval = SCIPfeasFloor(scip, solval);
    389 else
    390 {
    391 SCIP_Real lb;
    392
    393 assert(activitydelta/val < 0.0);
    394 shiftval = solval + activitydelta/val;
    395 assert(shiftval <= solval); /* may be equal due to numerical digit erasement in the subtraction */
    396 shiftval = SCIPfeasFloor(scip, shiftval);
    397 lb = SCIPvarGetLbGlobal(var);
    398 shiftval = MAX(shiftval, lb);
    399 }
    400 }
    401 else
    402 {
    403 /* shifting up */
    404 assert(direction * val > 0.0);
    405 if( isfrac )
    406 shiftval = SCIPfeasCeil(scip, solval);
    407 else
    408 {
    409 SCIP_Real ub;
    410
    411 assert(activitydelta/val > 0.0);
    412 shiftval = solval + activitydelta/val;
    413 assert(shiftval >= solval); /* may be equal due to numerical digit erasement in the subtraction */
    414 shiftval = SCIPfeasCeil(scip, shiftval);
    415 ub = SCIPvarGetUbGlobal(var);
    416 shiftval = MIN(shiftval, ub);
    417 }
    418 }
    419
    420 if( SCIPisEQ(scip, shiftval, solval) )
    421 continue;
    422
    423 deltaobj = SCIPvarGetObj(var) * (shiftval - solval);
    424 if( (shiftscore < bestshiftscore || deltaobj < bestdeltaobj)
    425 && !SCIPisHugeValue(scip, REALABS(shiftval)) ) /* ignore candidates for which shiftval is too large */
    426 {
    427 bestshiftscore = shiftscore;
    428 bestdeltaobj = deltaobj;
    429 *shiftvar = var;
    430 *oldsolval = solval;
    431 *newsolval = shiftval;
    432 }
    433 }
    434 }
    435
    436 return SCIP_OKAY;
    437}
    438
    439/** returns a fractional variable, that has most impact on rows in opposite direction, i.e. that is most crucial to
    440 * fix in the other direction;
    441 * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
    442 * shifting in a direction is forbidden, if this forces the objective value over the upper bound
    443 */
    444static
    446 SCIP* scip, /**< SCIP data structure */
    447 SCIP_SOL* sol, /**< primal solution */
    448 SCIP_Real minobj, /**< minimal objective value possible after shifting remaining fractional vars */
    449 SCIP_VAR** lpcands, /**< fractional variables in LP */
    450 int nlpcands, /**< number of fractional variables in LP */
    451 SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
    452 SCIP_Real* oldsolval, /**< old (fractional) solution value of shifting variable */
    453 SCIP_Real* newsolval /**< new (shifted) solution value of shifting variable */
    454 )
    455{
    456 SCIP_VAR* var;
    457 SCIP_Real solval;
    458 SCIP_Real shiftval;
    459 SCIP_Real obj;
    460 SCIP_Real deltaobj;
    461 SCIP_Real bestdeltaobj;
    462 int maxnlocks;
    463 int nlocks;
    464 int v;
    465
    466 assert(shiftvar != NULL);
    467 assert(oldsolval != NULL);
    468 assert(newsolval != NULL);
    469
    470 /* select shifting variable */
    471 maxnlocks = -1;
    472 bestdeltaobj = SCIPinfinity(scip);
    473 *shiftvar = NULL;
    474 for( v = 0; v < nlpcands; ++v )
    475 {
    476 var = lpcands[v];
    478
    479 solval = SCIPgetSolVal(scip, sol, var);
    480 if( !SCIPisFeasIntegral(scip, solval) )
    481 {
    482 obj = SCIPvarGetObj(var);
    483
    484 /* shifting down */
    486 if( nlocks >= maxnlocks )
    487 {
    488 shiftval = SCIPfeasFloor(scip, solval);
    489 deltaobj = obj * (shiftval - solval);
    490 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj - obj < SCIPgetCutoffbound(scip) )
    491 {
    492 maxnlocks = nlocks;
    493 bestdeltaobj = deltaobj;
    494 *shiftvar = var;
    495 *oldsolval = solval;
    496 *newsolval = shiftval;
    497 }
    498 }
    499
    500 /* shifting up */
    502 if( nlocks >= maxnlocks )
    503 {
    504 shiftval = SCIPfeasCeil(scip, solval);
    505 deltaobj = obj * (shiftval - solval);
    506 if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj + obj < SCIPgetCutoffbound(scip) )
    507 {
    508 maxnlocks = nlocks;
    509 bestdeltaobj = deltaobj;
    510 *shiftvar = var;
    511 *oldsolval = solval;
    512 *newsolval = shiftval;
    513 }
    514 }
    515 }
    516 }
    517
    518 return SCIP_OKAY;
    519}
    520
    521/** adds a given value to the fractionality counters of the rows in which the given variable appears */
    522static
    524 int* nfracsinrow, /**< array to store number of fractional variables per row */
    525 SCIP_ROW** violrows, /**< array with currently violated rows */
    526 int* violrowpos, /**< position of LP rows in violrows array */
    527 int* nviolfracrows, /**< pointer to store the number of violated rows with fractional variables */
    528 int nviolrows, /**< the number of currently violated rows (stays unchanged in this method) */
    529 int nlprows, /**< number of rows in LP */
    530 SCIP_VAR* var, /**< variable for which the counting should be updated */
    531 int incval /**< value that should be added to the corresponding array entries */
    532 )
    533{
    534 SCIP_COL* col;
    535 SCIP_ROW** rows;
    536 int nrows;
    537 int r;
    538
    539 assert(incval != 0);
    540 assert(nviolrows >= *nviolfracrows);
    541
    542 col = SCIPvarGetCol(var);
    543 rows = SCIPcolGetRows(col);
    544 nrows = SCIPcolGetNLPNonz(col);
    545 for( r = 0; r < nrows; ++r )
    546 {
    547 int rowlppos;
    548 int theviolrowpos;
    549 SCIP_ROW* row;
    550
    551 row = rows[r];
    552 assert(NULL != row);
    553 rowlppos = SCIProwGetLPPos(row);
    554 assert(0 <= rowlppos && rowlppos < nlprows);
    555 assert(!SCIProwIsLocal(row) || violrowpos[rowlppos] == -1);
    556
    557 if( SCIProwIsLocal(row) )
    558 continue;
    559
    560 nfracsinrow[rowlppos] += incval;
    561 assert(nfracsinrow[rowlppos] >= 0);
    562
    563 theviolrowpos = violrowpos[rowlppos];
    564
    565 /* swap positions in violrows array if fractionality has changed to 0 */
    566 if( theviolrowpos >= 0 )
    567 {
    568 /* first case: the number of fractional variables has become zero: swap row in violrows array to the
    569 * second part, containing only violated rows without fractional variables
    570 */
    571 if( nfracsinrow[rowlppos] == 0 )
    572 {
    573 assert(theviolrowpos <= *nviolfracrows - 1);
    574
    575 /* nothing to do if row is already at the end of the first part, otherwise, swap it to the last position
    576 * and decrease the counter */
    577 if( theviolrowpos < *nviolfracrows - 1 )
    578 {
    579 violrows[theviolrowpos] = violrows[*nviolfracrows - 1];
    580 violrows[*nviolfracrows - 1] = row;
    581
    582 violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
    583 violrowpos[rowlppos] = *nviolfracrows - 1;
    584 }
    585 (*nviolfracrows)--;
    586 }
    587 /* second interesting case: the number of fractional variables was zero before, swap it with the first
    588 * violated row without fractional variables
    589 */
    590 else if( nfracsinrow[rowlppos] == incval )
    591 {
    592 assert(theviolrowpos >= *nviolfracrows);
    593
    594 /* nothing to do if the row is exactly located at index *nviolfracrows */
    595 if( theviolrowpos > *nviolfracrows )
    596 {
    597 violrows[theviolrowpos] = violrows[*nviolfracrows];
    598 violrows[*nviolfracrows] = row;
    599
    600 violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
    601 violrowpos[rowlppos] = *nviolfracrows;
    602 }
    603 (*nviolfracrows)++;
    604 }
    605 }
    606 }
    607}
    608
    609
    610/*
    611 * Callback methods
    612 */
    613
    614/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    615static
    616SCIP_DECL_HEURCOPY(heurCopyIntshifting)
    617{ /*lint --e{715}*/
    618 assert(scip != NULL);
    619 assert(heur != NULL);
    620
    622
    623 /* call inclusion method of primal heuristic */
    625
    626 return SCIP_OKAY;
    627}
    628
    629
    630/** initialization method of primal heuristic (called after problem was transformed) */
    631static
    632SCIP_DECL_HEURINIT(heurInitIntshifting) /*lint --e{715}*/
    633{ /*lint --e{715}*/
    634 SCIP_HEURDATA* heurdata;
    635
    636 assert(SCIPheurGetData(heur) == NULL);
    637
    639
    640 /* create heuristic data */
    641 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    642 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    643 heurdata->lastlp = -1;
    644 SCIPheurSetData(heur, heurdata);
    645
    646 /* create random number generator */
    647 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    649
    650 return SCIP_OKAY;
    651}
    652
    653/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    654static
    655SCIP_DECL_HEUREXIT(heurExitIntshifting) /*lint --e{715}*/
    656{ /*lint --e{715}*/
    657 SCIP_HEURDATA* heurdata;
    658
    660
    661 /* free heuristic data */
    662 heurdata = SCIPheurGetData(heur);
    663 assert(heurdata != NULL);
    664 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    665
    666 /* free random number generator */
    667 SCIPfreeRandom(scip, &heurdata->randnumgen);
    668
    669 SCIPfreeBlockMemory(scip, &heurdata);
    670 SCIPheurSetData(heur, NULL);
    671
    672 return SCIP_OKAY;
    673}
    674
    675/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    676static
    677SCIP_DECL_HEURINITSOL(heurInitsolIntshifting)
    678{
    679 SCIP_HEURDATA* heurdata;
    680
    682
    683 heurdata = SCIPheurGetData(heur);
    684 assert(heurdata != NULL);
    685 heurdata->lastlp = -1;
    686
    687 return SCIP_OKAY;
    688}
    689
    690
    691/** execution method of primal heuristic */
    692static
    693SCIP_DECL_HEUREXEC(heurExecIntshifting) /*lint --e{715}*/
    694{ /*lint --e{715}*/
    695 SCIP_HEURDATA* heurdata;
    696 SCIP_SOL* sol;
    697 SCIP_VAR** lpcands;
    698 SCIP_Real* lpcandssol;
    699 SCIP_ROW** lprows;
    700 SCIP_Real* minactivities;
    701 SCIP_Real* maxactivities;
    702 SCIP_ROW** violrows;
    703 SCIP_Real* nincreases;
    704 SCIP_Real* ndecreases;
    705 int* violrowpos;
    706 int* nfracsinrow;
    707 SCIP_Real increaseweight;
    708 SCIP_Real obj;
    709 SCIP_Real bestshiftval;
    710 SCIP_Real minobj;
    711 int nvars;
    712 int nfrac;
    713 int nlpcands;
    714 int nlprows;
    715 int nviolrows;
    716 int nviolfracrows;
    717 int nprevviolrows;
    718 int minnviolrows;
    719 int nnonimprovingshifts;
    720 int c;
    721 int r;
    722 SCIP_Longint nlps;
    723 SCIP_Longint ncalls;
    724 SCIP_Longint nsolsfound;
    726
    727 assert(scip != NULL);
    728 assert(result != NULL);
    729 assert(SCIPhasCurrentNodeLP(scip));
    730
    732
    733 *result = SCIP_DIDNOTRUN;
    734
    735 /* do not call heuristic of node was already detected to be infeasible */
    736 if( nodeinfeasible )
    737 return SCIP_OKAY;
    738
    739 /* don't call heuristic, if no continuous variables are present
    740 * -> in this case, it is equivalent to shifting heuristic
    741 */
    742 if( SCIPgetNContVars(scip) == 0 )
    743 return SCIP_OKAY;
    744
    745 /* only call heuristic, if an optimal LP solution is at hand */
    747 return SCIP_OKAY;
    748
    749 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    751 return SCIP_OKAY;
    752
    753 /* get heuristic data */
    754 heurdata = SCIPheurGetData(heur);
    755 assert(heurdata != NULL);
    756
    757 /* don't call heuristic, if we have already processed the current LP solution */
    758 nlps = SCIPgetNLPs(scip);
    759 if( nlps == heurdata->lastlp )
    760 return SCIP_OKAY;
    761 heurdata->lastlp = nlps;
    762
    763 /* don't call heuristic, if it was not successful enough in the past */
    764 ncalls = SCIPheurGetNCalls(heur);
    765 nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + SCIPheurGetNSolsFound(heur);
    767 if( nnodes % (ncalls/(nsolsfound+1)+1) != 0 ) /*?????????? ncalls/100 */
    768 return SCIP_OKAY;
    769
    770 /* get fractional variables, that should be integral */
    771 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL, NULL) );
    772
    773 /* only call heuristic, if LP solution is fractional */
    774 if( nlpcands == 0 )
    775 return SCIP_OKAY;
    776
    777 *result = SCIP_DIDNOTFIND;
    778
    779 /* get LP rows */
    780 SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
    781
    782 SCIPdebugMsg(scip, "executing intshifting heuristic: %d LP rows, %d LP candidates\n", nlprows, nlpcands);
    783
    784 /* get memory for activities, violated rows, and row violation positions */
    785 nvars = SCIPgetNVars(scip);
    786 nfrac = nlpcands;
    787 SCIP_CALL( SCIPallocBufferArray(scip, &minactivities, nlprows) );
    788 SCIP_CALL( SCIPallocBufferArray(scip, &maxactivities, nlprows) );
    789 SCIP_CALL( SCIPallocBufferArray(scip, &violrows, nlprows) );
    790 SCIP_CALL( SCIPallocBufferArray(scip, &violrowpos, nlprows) );
    791 SCIP_CALL( SCIPallocBufferArray(scip, &nfracsinrow, nlprows) );
    792 SCIP_CALL( SCIPallocBufferArray(scip, &nincreases, nvars) );
    793 SCIP_CALL( SCIPallocBufferArray(scip, &ndecreases, nvars) );
    794 BMSclearMemoryArray(nfracsinrow, nlprows);
    795 BMSclearMemoryArray(nincreases, nvars);
    796 BMSclearMemoryArray(ndecreases, nvars);
    797
    798 /* get the minimal and maximal activity for all globally valid rows for continuous variables in their full range;
    799 * these are the values of a*x' with x' being the LP solution for integer variables and the lower or upper bound
    800 * for the continuous variables
    801 */
    802 nviolrows = 0;
    803 for( r = 0; r < nlprows; ++r )
    804 {
    805 SCIP_ROW* row;
    806
    807 row = lprows[r];
    808 assert(SCIProwGetLPPos(row) == r);
    809
    810 if( !SCIProwIsLocal(row) )
    811 {
    812 SCIP_COL** cols;
    813 SCIP_Real* vals;
    814 int nnonz;
    815 SCIP_Bool mininf;
    816 SCIP_Bool maxinf;
    817
    818 mininf = FALSE;
    819 maxinf = FALSE;
    820 minactivities[r] = 0.0;
    821 maxactivities[r] = 0.0;
    822 cols = SCIProwGetCols(row);
    823 vals = SCIProwGetVals(row);
    824 nnonz = SCIProwGetNNonz(row);
    825 for( c = 0; c < nnonz && !(mininf && maxinf); ++c )
    826 {
    827 SCIP_VAR* var;
    828
    829 var = SCIPcolGetVar(cols[c]);
    831 {
    832 SCIP_Real act;
    833
    834 act = vals[c] * SCIPcolGetPrimsol(cols[c]);
    835 minactivities[r] += act;
    836 maxactivities[r] += act;
    837 }
    838 else if( vals[c] > 0.0 )
    839 {
    840 SCIP_Real lb;
    841 SCIP_Real ub;
    842
    843 lb = SCIPvarGetLbGlobal(var);
    844 ub = SCIPvarGetUbGlobal(var);
    845 if( SCIPisInfinity(scip, -lb) )
    846 mininf = TRUE;
    847 else
    848 minactivities[r] += vals[c] * lb;
    849 if( SCIPisInfinity(scip, ub) )
    850 maxinf = TRUE;
    851 else
    852 maxactivities[r] += vals[c] * ub;
    853 }
    854 else if( vals[c] < 0.0 )
    855 {
    856 SCIP_Real lb;
    857 SCIP_Real ub;
    858
    859 lb = SCIPvarGetLbGlobal(var);
    860 ub = SCIPvarGetUbGlobal(var);
    861 if( SCIPisInfinity(scip, ub) )
    862 mininf = TRUE;
    863 else
    864 minactivities[r] += vals[c] * ub;
    865 if( SCIPisInfinity(scip, -lb) )
    866 maxinf = TRUE;
    867 else
    868 maxactivities[r] += vals[c] * lb;
    869 }
    870
    871 if( mininf )
    872 minactivities[r] = -SCIPinfinity(scip);
    873 if( maxinf )
    874 maxactivities[r] = SCIPinfinity(scip);
    875 }
    876
    877 if( SCIPisFeasLT(scip, maxactivities[r], SCIProwGetLhs(row))
    878 || SCIPisFeasGT(scip, minactivities[r], SCIProwGetRhs(row)) )
    879 {
    880 violrows[nviolrows] = row;
    881 violrowpos[r] = nviolrows;
    882 nviolrows++;
    883 }
    884 else
    885 violrowpos[r] = -1;
    886 }
    887 else
    888 /* if row is a local row */
    889 violrowpos[r] = -1;
    890 }
    891
    892 nviolfracrows = 0;
    893 /* calc the current number of fractional variables in rows */
    894 for( c = 0; c < nlpcands; ++c )
    895 addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, lpcands[c], +1);
    896
    897 /* get the working solution from heuristic's local data */
    898 sol = heurdata->sol;
    899 assert(sol != NULL);
    900
    901 /* copy the current LP solution to the working solution */
    903
    904 /* calculate the minimal objective value possible after rounding fractional variables */
    905 minobj = SCIPgetSolTransObj(scip, sol);
    906 assert(minobj < SCIPgetCutoffbound(scip));
    907 for( c = 0; c < nlpcands; ++c )
    908 {
    909 obj = SCIPvarGetObj(lpcands[c]);
    910 bestshiftval = obj > 0.0 ? SCIPfeasFloor(scip, lpcandssol[c]) : SCIPfeasCeil(scip, lpcandssol[c]);
    911 minobj += obj * (bestshiftval - lpcandssol[c]);
    912 }
    913
    914 /* try to shift remaining variables in order to become/stay feasible */
    915 nnonimprovingshifts = 0;
    916 minnviolrows = INT_MAX;
    917 increaseweight = 1.0;
    918 while( (nfrac > 0 || nviolrows > 0) && nnonimprovingshifts < MAXSHIFTINGS && !SCIPisStopped(scip) )
    919 {
    920 SCIP_VAR* shiftvar;
    921 SCIP_Real oldsolval;
    922 SCIP_Real newsolval;
    923 SCIP_Bool oldsolvalisfrac;
    924 int probindex;
    925
    926 SCIPdebugMsg(scip, "intshifting heuristic: nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g), cutoff=%g\n",
    927 nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj),
    929
    930 nprevviolrows = nviolrows;
    931
    932 /* choose next variable to process:
    933 * - if a violated row exists, shift a variable decreasing the violation, that has least impact on other rows
    934 * - otherwise, shift a variable, that has strongest devastating impact on rows in opposite direction
    935 */
    936 shiftvar = NULL;
    937 oldsolval = 0.0;
    938 newsolval = 0.0;
    939 if( nviolrows > 0 && (nfrac == 0 || nnonimprovingshifts < MAXSHIFTINGS-1) )
    940 {
    941 SCIP_ROW* row;
    942 int rowidx;
    943 int rowpos;
    944 int direction;
    945
    946 assert(nviolfracrows == 0 || nfrac > 0);
    947 /* violated rows containing fractional variables are preferred; if such a row exists, choose the last one from the list
    948 * (at position nviolfracrows - 1) because removing this row will cause one swapping operation less than other rows
    949 */
    950 if( nviolfracrows > 0 )
    951 rowidx = nviolfracrows - 1;
    952 else
    953 rowidx = SCIPrandomGetInt(heurdata->randnumgen, 0, nviolrows-1);
    954
    955 assert(0 <= rowidx && rowidx < nviolrows);
    956 row = violrows[rowidx];
    957 rowpos = SCIProwGetLPPos(row);
    958 assert(0 <= rowpos && rowpos < nlprows);
    959 assert(violrowpos[rowpos] == rowidx);
    960 assert(nfracsinrow[rowpos] == 0 || rowidx == nviolfracrows - 1);
    961
    962 SCIPdebugMsg(scip, "intshifting heuristic: try to fix violated row <%s>: %g <= [%g,%g] <= %g\n",
    963 SCIProwGetName(row), SCIProwGetLhs(row), minactivities[rowpos], maxactivities[rowpos], SCIProwGetRhs(row));
    965
    966 /* get direction in which activity must be shifted */
    967 assert(SCIPisFeasLT(scip, maxactivities[rowpos], SCIProwGetLhs(row))
    968 || SCIPisFeasGT(scip, minactivities[rowpos], SCIProwGetRhs(row)));
    969 direction = SCIPisFeasLT(scip, maxactivities[rowpos], SCIProwGetLhs(row)) ? +1 : -1;
    970
    971 /* search an integer variable that can shift the activity in the necessary direction */
    972 SCIP_CALL( selectShifting(scip, sol, row, direction == +1 ? maxactivities[rowpos] : minactivities[rowpos],
    973 direction, nincreases, ndecreases, increaseweight, &shiftvar, &oldsolval, &newsolval) );
    974 }
    975
    976 if( shiftvar == NULL && nfrac > 0 )
    977 {
    978 SCIPdebugMsg(scip, "intshifting heuristic: search rounding variable and try to stay feasible\n");
    979 SCIP_CALL( selectEssentialRounding(scip, sol, minobj, lpcands, nlpcands, &shiftvar, &oldsolval, &newsolval) );
    980 }
    981
    982 /* check, whether shifting was possible */
    983 if( shiftvar == NULL || SCIPisEQ(scip, oldsolval, newsolval) )
    984 {
    985 SCIPdebugMsg(scip, "intshifting heuristic: -> didn't find a shifting variable\n");
    986 break;
    987 }
    988
    989 assert(SCIPvarGetType(shiftvar) != SCIP_VARTYPE_CONTINUOUS);
    990
    991 SCIPdebugMsg(scip, "intshifting heuristic: -> shift var <%s>[%g,%g], type=%d, oldval=%g, newval=%g, obj=%g\n",
    992 SCIPvarGetName(shiftvar), SCIPvarGetLbGlobal(shiftvar), SCIPvarGetUbGlobal(shiftvar), SCIPvarGetType(shiftvar),
    993 oldsolval, newsolval, SCIPvarGetObj(shiftvar));
    994
    995 /* update row activities of globally valid rows */
    996 SCIP_CALL( updateActivities(scip, minactivities, maxactivities, violrows, violrowpos, &nviolrows, &nviolfracrows,
    997 nfracsinrow, nlprows, shiftvar, oldsolval, newsolval) );
    998
    999 if( nviolrows >= nprevviolrows )
    1000 nnonimprovingshifts++;
    1001 else if( nviolrows < minnviolrows )
    1002 {
    1003 minnviolrows = nviolrows;
    1004 nnonimprovingshifts = 0;
    1005 }
    1006
    1007 /* store new solution value and decrease fractionality counter */
    1008 SCIP_CALL( SCIPsetSolVal(scip, sol, shiftvar, newsolval) );
    1009
    1010 /* update fractionality counter and minimal objective value possible after shifting remaining variables */
    1011 oldsolvalisfrac = !SCIPisFeasIntegral(scip, oldsolval);
    1012 obj = SCIPvarGetObj(shiftvar);
    1013 if( oldsolvalisfrac )
    1014 {
    1015 assert(SCIPisFeasIntegral(scip, newsolval));
    1016 nfrac--;
    1017 nnonimprovingshifts = 0;
    1018 minnviolrows = INT_MAX;
    1019 addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, shiftvar, -1);
    1020
    1021 /* the rounding was already calculated into the minobj -> update only if rounding in "wrong" direction */
    1022 if( obj > 0.0 && newsolval > oldsolval )
    1023 minobj += obj;
    1024 else if( obj < 0.0 && newsolval < oldsolval )
    1025 minobj -= obj;
    1026 }
    1027 else
    1028 {
    1029 /* update minimal possible objective value */
    1030 minobj += obj * (newsolval - oldsolval);
    1031 }
    1032
    1033 /* update increase/decrease arrays */
    1034 if( !oldsolvalisfrac )
    1035 {
    1036 probindex = SCIPvarGetProbindex(shiftvar);
    1037 assert(0 <= probindex && probindex < nvars);
    1038 increaseweight *= WEIGHTFACTOR;
    1039 if( newsolval < oldsolval )
    1040 ndecreases[probindex] += increaseweight;
    1041 else
    1042 nincreases[probindex] += increaseweight;
    1043 if( increaseweight >= 1e+09 )
    1044 {
    1045 int i;
    1046
    1047 for( i = 0; i < nvars; ++i )
    1048 {
    1049 nincreases[i] /= increaseweight;
    1050 ndecreases[i] /= increaseweight;
    1051 }
    1052 increaseweight = 1.0;
    1053 }
    1054 }
    1055
    1056 SCIPdebugMsg(scip, "intshifting heuristic: -> nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
    1057 nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj));
    1058 }
    1059
    1060 /* check, if the new solution is potentially feasible and solve the LP to calculate values for the continuous
    1061 * variables
    1062 */
    1063 if( nfrac == 0 && nviolrows == 0 )
    1064 {
    1065 SCIP_VAR** vars;
    1066 SCIP_Bool lperror;
    1067 int nintvars;
    1068 int v;
    1069#ifdef NDEBUG
    1070 SCIP_RETCODE retstat;
    1071#endif
    1072
    1073 SCIPdebugMsg(scip, "shifted solution is potentially feasible -> solve LP to fix continuous variables\n");
    1074
    1075 /* start diving to calculate the LP relaxation */
    1077
    1078 /* set the bounds of the variables: fixed for binaries and integers, global bounds for continuous */
    1079 vars = SCIPgetVars(scip);
    1081 assert(nintvars >= 0);
    1082 for( v = 0; v < nvars; ++v )
    1083 {
    1084 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_COLUMN )
    1085 {
    1086 SCIP_CALL( SCIPchgVarLbDive(scip, vars[v], SCIPvarGetLbGlobal(vars[v])) );
    1087 SCIP_CALL( SCIPchgVarUbDive(scip, vars[v], SCIPvarGetUbGlobal(vars[v])) );
    1088 }
    1089 }
    1090 for( v = 0; v < nintvars; ++v ) /* apply this after global bounds to not cause an error with intermediate empty domains */
    1091 {
    1092 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_COLUMN )
    1093 {
    1094 SCIP_Real solval;
    1095 solval = SCIPgetSolVal(scip, sol, vars[v]);
    1096 SCIP_CALL( SCIPchgVarLbDive(scip, vars[v], solval) );
    1097 SCIP_CALL( SCIPchgVarUbDive(scip, vars[v], solval) );
    1098 }
    1099 }
    1100
    1101 /* solve LP */
    1102 SCIPdebugMsg(scip, " -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    1103
    1104 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    1105 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    1106 */
    1107#ifdef NDEBUG
    1108 retstat = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
    1109 if( retstat != SCIP_OKAY )
    1110 {
    1111 SCIPwarningMessage(scip, "Error while solving LP in Intshifting heuristic; LP solve terminated with code <%d>\n",retstat);
    1112 }
    1113#else
    1114 SCIP_CALL( SCIPsolveDiveLP(scip, -1, &lperror, NULL) );
    1115#endif
    1116
    1117 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    1118 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
    1119
    1120 /* check if this is a feasible solution */
    1121 if( !lperror && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
    1122 {
    1123 SCIP_Bool stored;
    1124
    1125 /* copy the current LP solution to the working solution */
    1126 SCIP_CALL( SCIPlinkLPSol(scip, sol) );
    1127
    1128 /* in exact mode we have to end diving prior to trying the solution */
    1129 if( SCIPisExact(scip) )
    1130 {
    1131 SCIP_CALL( SCIPunlinkSol(scip, heurdata->sol) );
    1133 }
    1134
    1135 /* check solution for feasibility, and add it to solution store if possible
    1136 * neither integrality nor feasibility of LP rows has to be checked, because this is already
    1137 * done in the intshifting heuristic itself and due to the LP resolve
    1138 */
    1139 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, FALSE, FALSE, &stored) );
    1140
    1141 if( stored )
    1142 {
    1143 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
    1145 *result = SCIP_FOUNDSOL;
    1146 }
    1147 }
    1148
    1149 /* terminate the diving */
    1150 if( SCIPinDive(scip) )
    1151 {
    1153 }
    1154 }
    1155
    1156 /* free memory buffers */
    1157 SCIPfreeBufferArray(scip, &ndecreases);
    1158 SCIPfreeBufferArray(scip, &nincreases);
    1159 SCIPfreeBufferArray(scip, &nfracsinrow);
    1160 SCIPfreeBufferArray(scip, &violrowpos);
    1161 SCIPfreeBufferArray(scip, &violrows);
    1162 SCIPfreeBufferArray(scip, &maxactivities);
    1163 SCIPfreeBufferArray(scip, &minactivities);
    1164
    1165 return SCIP_OKAY;
    1166}
    1167
    1168
    1169/*
    1170 * heuristic specific interface methods
    1171 */
    1172
    1173/** creates the intshifting heuristic with infeasibility recovering and includes it in SCIP */
    1175 SCIP* scip /**< SCIP data structure */
    1176 )
    1177{
    1178 SCIP_HEUR* heur;
    1179
    1180 /* include primal heuristic */
    1183 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecIntshifting, NULL) );
    1184
    1185 assert(heur != NULL);
    1186
    1187 /* primal heuristic is safe to use in exact solving mode */
    1188 SCIPheurMarkExact(heur);
    1189
    1190 /* set non-NULL pointers to callback methods */
    1191 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyIntshifting) );
    1192 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitIntshifting) );
    1193 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitIntshifting) );
    1194 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolIntshifting) );
    1195
    1196 return SCIP_OKAY;
    1197}
    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_LONGINT_FORMAT
    Definition: def.h:157
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    #define nnodes
    Definition: gastrans.c:74
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNContImplVars(SCIP *scip)
    Definition: scip_prob.c:2522
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPincludeHeurIntshifting(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
    SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
    Definition: lp.c:17379
    int SCIPcolGetNLPNonz(SCIP_COL *col)
    Definition: lp.c:17534
    SCIP_Bool SCIPisExact(SCIP *scip)
    Definition: scip_exact.c:193
    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_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_lp.c:2384
    SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_lp.c:2416
    SCIP_RETCODE SCIPstartDive(SCIP *scip)
    Definition: scip_lp.c:2206
    SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
    Definition: scip_lp.c:2643
    SCIP_RETCODE SCIPendDive(SCIP *scip)
    Definition: scip_lp.c:2255
    SCIP_Bool SCIPinDive(SCIP *scip)
    Definition: scip_lp.c:2740
    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
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    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_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 SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1504
    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_Longint SCIPgetNLPIterations(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_Bool SCIPisHugeValue(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
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    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_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_DECL_HEUREXIT(heurExitIntshifting)
    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 void updateViolations(SCIP *scip, SCIP_ROW *row, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, SCIP_Real oldminactivity, SCIP_Real oldmaxactivity, SCIP_Real newminactivity, SCIP_Real newmaxactivity)
    #define HEUR_TIMING
    static void addFracCounter(int *nfracsinrow, SCIP_ROW **violrows, int *violrowpos, int *nviolfracrows, int nviolrows, int nlprows, SCIP_VAR *var, int incval)
    #define HEUR_FREQOFS
    #define HEUR_DESC
    static SCIP_RETCODE updateActivities(SCIP *scip, SCIP_Real *minactivities, SCIP_Real *maxactivities, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, int nlprows, SCIP_VAR *var, SCIP_Real oldsolval, SCIP_Real newsolval)
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    static SCIP_DECL_HEUREXEC(heurExecIntshifting)
    #define HEUR_NAME
    static SCIP_DECL_HEURINIT(heurInitIntshifting)
    #define DEFAULT_RANDSEED
    static SCIP_DECL_HEURINITSOL(heurInitsolIntshifting)
    #define HEUR_FREQ
    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)
    static SCIP_DECL_HEURCOPY(heurCopyIntshifting)
    #define HEUR_USESSUBSCIP
    #define WEIGHTFACTOR
    #define MAXSHIFTINGS
    LP rounding heuristic that tries to recover from intermediate infeasibilities, shifts integer variabl...
    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 exact solving
    general public methods
    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_VARSTATUS_COLUMN
    Definition: type_var.h:53
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141