SCIP

    Solving Constraint Integer Programs

    heur_twoopt.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_twoopt.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief primal heuristic to improve incumbent solution by flipping pairs of variables
    28 * @author Timo Berthold
    29 * @author Gregor Hendel
    30 */
    31
    32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    33
    35#include "scip/heur_twoopt.h"
    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_misc_sort.h"
    41#include "scip/pub_sol.h"
    42#include "scip/pub_var.h"
    43#include "scip/scip_exact.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_param.h"
    50#include "scip/scip_prob.h"
    52#include "scip/scip_sol.h"
    54
    55
    56#define HEUR_NAME "twoopt"
    57#define HEUR_DESC "primal heuristic to improve incumbent solution by flipping pairs of variables"
    58#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_ITERATIVE
    59#define HEUR_PRIORITY -20100
    60#define HEUR_FREQ -1
    61#define HEUR_FREQOFS 0
    62#define HEUR_MAXDEPTH -1
    63
    64#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
    65#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    66
    67/* default parameter values */
    68#define DEFAULT_INTOPT FALSE /**< optional integer optimization is applied by default */
    69#define DEFAULT_WAITINGNODES 0 /**< default number of nodes to wait after current best solution before calling heuristic */
    70#define DEFAULT_MATCHINGRATE 0.5 /**< default percentage by which two variables have to match in their LP-row set to be
    71 * associated as pair by heuristic */
    72#define DEFAULT_MAXNSLAVES 199 /**< default number of slave candidates for a master variable */
    73#define DEFAULT_ARRAYSIZE 10 /**< the default array size for temporary arrays */
    74#define DEFAULT_RANDSEED 37 /**< initial random seed */
    75
    76/*
    77 * Data structures
    78 */
    79
    80/** primal heuristic data */
    81struct SCIP_HeurData
    82{
    83 int lastsolindex; /**< index of last solution for which heuristic was performed */
    84 SCIP_Real matchingrate; /**< percentage by which two variables have to match in their LP-row
    85 * set to be associated as pair by heuristic */
    86 SCIP_VAR** binvars; /**< Array of binary variables which are sorted with respect to their occurrence
    87 * in the LP-rows */
    88 int nbinvars; /**< number of binary variables stored in heuristic array */
    89 int waitingnodes; /**< user parameter to determine number of nodes to wait after last best solution
    90 * before calling heuristic */
    91 SCIP_Bool presolved; /**< flag to indicate whether presolving has already been executed */
    92 int* binblockstart; /**< array to store the start indices of each binary block */
    93 int* binblockend; /**< array to store the end indices of each binary block */
    94 int nbinblocks; /**< number of blocks */
    95
    96 /* integer variable twoopt data */
    97 SCIP_Bool intopt; /**< parameter to determine if integer 2-opt should be applied */
    98 SCIP_VAR** intvars; /**< array to store the integer variables in non-decreasing order
    99 * with respect to their objective coefficient */
    100 int nintvars; /**< the number of integer variables stored in array intvars */
    101 int* intblockstart; /**< array to store the start indices of each binary block */
    102 int* intblockend; /**< array to store the end indices of each binary block */
    103 int nintblocks; /**< number of blocks */
    104
    105 SCIP_Bool execute; /**< has presolveTwoOpt detected necessary structure for execution of heuristic? */
    106 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    107 int maxnslaves; /**< delimits the maximum number of slave candidates for a master variable */
    108
    109#ifdef SCIP_STATISTIC
    110 /* statistics */
    111 int ntotalbinvars; /**< total number of binary variables over all runs */
    112 int ntotalintvars; /**< total number of Integer variables over all runs */
    113 int nruns; /**< counts the number of runs, i.e. the number of initialized
    114 * branch and bound processes */
    115 int maxbinblocksize; /**< maximum size of a binary block */
    116 int maxintblocksize; /**< maximum size of an integer block */
    117 int binnblockvars; /**< number of binary variables that appear in blocks */
    118 int binnblocks; /**< number of blocks with at least two variables */
    119 int intnblockvars; /**< number of Integer variables that appear in blocks */
    120 int intnblocks; /**< number of blocks with at least two variables */
    121 int binnexchanges; /**< number of executed changes of binary solution values leading to
    122 * improvement in objective function */
    123 int intnexchanges; /**< number of executed changes of Integer solution values leading to improvement in
    124 * objective function */
    125#endif
    126};
    127
    128/** indicator for optimizing for binaries or integer variables */
    130{
    134typedef enum Opttype OPTTYPE;
    135
    136/** indicator for direction of shifting variables */
    138{
    143typedef enum Direction DIRECTION;
    144
    145/*
    146 * Local methods
    147 */
    148
    149/** Tries to switch the values of two binary or integer variables and checks feasibility with respect to the LP.
    150 *
    151 * @todo Adapt method not to copy entire activities array, but only the relevant region.
    152 */
    153static
    155 SCIP* scip, /**< scip instance */
    156 SCIP_VAR* master, /**< first variable of variable pair */
    157 SCIP_VAR* slave, /**< second variable of pair */
    158 SCIP_Real mastersolval, /**< current value of variable1 in solution */
    159 DIRECTION masterdir, /**< the direction into which the master variable has to be shifted */
    160 SCIP_Real slavesolval, /**< current value of variable2 in solution */
    161 DIRECTION slavedir, /**< the direction into which the slave variable has to be shifted */
    162 SCIP_Real shiftval, /**< the value that variables should be shifted by */
    163 SCIP_Real* activities, /**< the LP-row activities */
    164 int nrows, /**< size of activities array */
    165 SCIP_Bool* feasible /**< set to true if method has successfully switched the variable values */
    166 )
    167{ /*lint --e{715}*/
    168 SCIP_COL* col;
    169 SCIP_ROW** masterrows;
    170 SCIP_ROW** slaverows;
    171 SCIP_Real* mastercolvals;
    172 SCIP_Real* slavecolvals;
    173 int ncolmasterrows;
    174 int ncolslaverows;
    175
    176 assert(scip != NULL);
    177 assert(master != NULL);
    178 assert(slave != NULL);
    179 assert(activities != NULL);
    180 assert(SCIPisFeasGT(scip, shiftval, 0.0));
    181
    182 assert(SCIPisFeasGE(scip, mastersolval + (int)masterdir * shiftval, SCIPvarGetLbGlobal(master)));
    183 assert(SCIPisFeasLE(scip, mastersolval + (int)masterdir * shiftval, SCIPvarGetUbGlobal(master)));
    184
    185 assert(SCIPisFeasGE(scip, slavesolval + (int)slavedir * shiftval, SCIPvarGetLbGlobal(slave)));
    186 assert(SCIPisFeasLE(scip, slavesolval + (int)slavedir * shiftval, SCIPvarGetUbGlobal(slave)));
    187
    188 /* get variable specific rows and coefficients for both master and slave. */
    189 col = SCIPvarGetCol(master);
    190 masterrows = SCIPcolGetRows(col);
    191 mastercolvals = SCIPcolGetVals(col);
    192 ncolmasterrows = SCIPcolGetNNonz(col);
    193 assert(ncolmasterrows == 0 || masterrows != NULL);
    194
    195 col = SCIPvarGetCol(slave);
    196 slaverows = SCIPcolGetRows(col);
    197 slavecolvals = SCIPcolGetVals(col);
    198 ncolslaverows = SCIPcolGetNNonz(col);
    199 assert(ncolslaverows == 0 || slaverows != NULL);
    200
    201 /* update the activities of the LP rows of the master variable */
    202 for( int i = 0; i < ncolmasterrows && SCIProwGetLPPos(masterrows[i]) >= 0; ++i )
    203 {
    204 int rowpos;
    205
    206 rowpos = SCIProwGetLPPos(masterrows[i]);
    207 assert(rowpos < nrows);
    208
    209 /* skip local rows */
    210 if( rowpos >= 0 && ! SCIProwIsLocal(masterrows[i]) )
    211 activities[rowpos] += mastercolvals[i] * (int)masterdir * shiftval;
    212 }
    213
    214 /* update the activities of the LP rows of the slave variable */
    215 for( int j = 0; j < ncolslaverows && SCIProwGetLPPos(slaverows[j]) >= 0; ++j )
    216 {
    217 int rowpos;
    218
    219 rowpos = SCIProwGetLPPos(slaverows[j]);
    220 assert(rowpos < nrows);
    221
    222 /* skip local rows */
    223 if( rowpos >= 0 && ! SCIProwIsLocal(slaverows[j]) )
    224 {
    225 activities[rowpos] += slavecolvals[j] * (int)slavedir * shiftval;
    226 assert(SCIPisFeasGE(scip, activities[rowpos], SCIProwGetLhs(slaverows[j])));
    227 assert(SCIPisFeasLE(scip, activities[rowpos], SCIProwGetRhs(slaverows[j])));
    228 }
    229 }
    230
    231 /* in debug mode, the master rows are checked for feasibility which should be granted by the
    232 * decision for a shift value */
    233#ifndef NDEBUG
    234 for( int i = 0; i < ncolmasterrows && SCIProwGetLPPos(masterrows[i]) >= 0; ++i )
    235 {
    236 /* local rows can be skipped */
    237 if( SCIProwIsLocal(masterrows[i]) )
    238 continue;
    239
    240 assert(SCIPisFeasGE(scip, activities[SCIProwGetLPPos(masterrows[i])], SCIProwGetLhs(masterrows[i])));
    241 assert(SCIPisFeasLE(scip, activities[SCIProwGetLPPos(masterrows[i])], SCIProwGetRhs(masterrows[i])));
    242 }
    243#endif
    244
    245 *feasible = TRUE;
    246
    247 return SCIP_OKAY;
    248}
    249
    250/** Compare two variables with respect to their columns.
    251 *
    252 * Columns are treated as {0,1} vector, where every nonzero entry is treated as '1', and compared to each other
    253 * lexicographically. I.e. var1 is < var2 if the corresponding column of var2 has the smaller single nonzero index of
    254 * the two columns. This comparison costs O(constraints) in the worst case
    255 */
    256static
    258 SCIP_VAR* var1, /**< left argument of comparison */
    259 SCIP_VAR* var2 /**< right argument of comparison */
    260 )
    261{
    262 SCIP_COL* col1;
    263 SCIP_COL* col2;
    264 SCIP_ROW** rows1;
    265 SCIP_ROW** rows2;
    266 int nnonzeros1;
    267 int nnonzeros2;
    268
    269 assert(var1 != NULL);
    270 assert(var2 != NULL);
    271
    272 /* get the necessary row and column data */
    273 col1 = SCIPvarGetCol(var1);
    274 col2 = SCIPvarGetCol(var2);
    275 rows1 = SCIPcolGetRows(col1);
    276 rows2 = SCIPcolGetRows(col2);
    277 nnonzeros1 = SCIPcolGetNNonz(col1);
    278 nnonzeros2 = SCIPcolGetNNonz(col2);
    279
    280 assert(nnonzeros1 == 0 || rows1 != NULL);
    281 assert(nnonzeros2 == 0 || rows2 != NULL);
    282
    283 /* loop over the rows, stopped as soon as they differ in one index,
    284 * or if counter reaches the end of a variables row set */
    285 for( int i = 0; i < nnonzeros1 && i < nnonzeros2; ++i )
    286 {
    287 if( SCIProwGetIndex(rows1[i]) != SCIProwGetIndex(rows2[i]) )
    288 return SCIProwGetIndex(rows1[i]) - SCIProwGetIndex(rows2[i]);
    289 }
    290
    291 /* loop is finished, without differing in one of common row indices, due to loop invariant
    292 * variable i reached either nnonzeros1 or nnonzeros2 or both.
    293 * one can easily check that the difference of these two numbers always has the desired sign for comparison. */
    294 return nnonzeros2 - nnonzeros1 ;
    295}
    296
    297/** implements a comparator to compare two variables with respect to their column entries */
    298static
    300{
    301 return varColCompare((SCIP_VAR*) elem1, (SCIP_VAR*) elem2);
    302}
    303
    304/** checks if two given variables are contained in common LP rows,
    305 * returns true if variables share the necessary percentage (matchingrate) of rows.
    306 */
    307static
    309 SCIP* scip, /**< current SCIP instance */
    310 SCIP_VAR* var1, /**< first variable */
    311 SCIP_VAR* var2, /**< second variable */
    312 SCIP_Real matchingrate /**< determines the ratio of shared LP rows compared to the total number of
    313 * LP-rows each variable appears in */
    314 )
    315{
    316 SCIP_COL* col1;
    317 SCIP_COL* col2;
    318 SCIP_ROW** rows1;
    319 SCIP_ROW** rows2;
    320 int nnonzeros1;
    321 int nnonzeros2;
    322 int i;
    323 int j;
    324 int nrows1not2; /* the number of LP-rows of variable 1 which variable 2 doesn't appear in */
    325 int nrows2not1; /* vice versa */
    326 int nrowmaximum;
    327 int nrowabs;
    328
    329 assert(var1 != NULL);
    330 assert(var2 != NULL);
    331
    332 /* get the necessary row and column data */
    333 col1 = SCIPvarGetCol(var1);
    334 col2 = SCIPvarGetCol(var2);
    335 rows1 = SCIPcolGetRows(col1);
    336 rows2 = SCIPcolGetRows(col2);
    337 nnonzeros1 = SCIPcolGetNNonz(col1);
    338 nnonzeros2 = SCIPcolGetNNonz(col2);
    339
    340 assert(nnonzeros1 == 0 || rows1 != NULL);
    341 assert(nnonzeros2 == 0 || rows2 != NULL);
    342
    343 if( nnonzeros1 == 0 && nnonzeros2 == 0 )
    344 return TRUE;
    345
    346 /* if matching rate is 0.0, we don't need to check anything */
    347 if( matchingrate == 0.0 )
    348 return TRUE;
    349
    350 /* initialize the counters for the number of rows not shared. */
    351 nrowmaximum = MAX(nnonzeros1, nnonzeros2);
    352
    353 nrowabs = ABS(nnonzeros1 - nnonzeros2);
    354 nrows1not2 = nrowmaximum - nnonzeros2;
    355 nrows2not1 = nrowmaximum - nnonzeros1;
    356
    357 /* if the numbers of nonzero rows differs too much, w.r.t.matching ratio, the more expensive check over the rows
    358 * doesn't have to be applied anymore because the counters for not shared rows can only increase.
    359 */
    360 assert(nrowmaximum > 0);
    361
    362 if( (nrowmaximum - nrowabs) / (SCIP_Real) nrowmaximum < matchingrate )
    363 return FALSE;
    364
    365 i = 0;
    366 j = 0;
    367
    368 /* loop over all rows and determine number of non-shared rows */
    369 while( i < nnonzeros1 && j < nnonzeros2 )
    370 {
    371 /* variables share a common row */
    372 if( SCIProwGetIndex(rows1[i]) == SCIProwGetIndex(rows2[j]) )
    373 {
    374 ++i;
    375 ++j;
    376 }
    377 /* variable 1 appears in rows1[i], variable 2 doesn't */
    378 else if( SCIProwGetIndex(rows1[i]) < SCIProwGetIndex(rows2[j]) )
    379 {
    380 ++i;
    381 ++nrows1not2;
    382 }
    383 /* variable 2 appears in rows2[j], variable 1 doesn't */
    384 else
    385 {
    386 ++j;
    387 ++nrows2not1;
    388 }
    389 }
    390
    391 /* now apply the ratio based comparison, that is if the ratio of shared rows is greater or equal the matching rate
    392 * for each variable */
    393 /* nnonzeros1 = 0 or nnonzeros2 = 0 iff matching rate is 0, but in this case, we return TRUE at the beginning */
    394 /* coverity[divide_by_zero] */
    395 return ( SCIPisFeasLE(scip, matchingrate, (nnonzeros1 - nrows1not2) / (SCIP_Real)(nnonzeros1)) ||
    396 SCIPisFeasLE(scip, matchingrate, (nnonzeros2 - nrows2not1) / (SCIP_Real)(nnonzeros2)) ); /*lint !e795 */
    397}
    398
    399/** Determines a bound by which the absolute solution value of two integer variables can be shifted at most.
    400 *
    401 * The criterion is the maintenance of feasibility of any global LP row.
    402 * The first implementation only considers shifting proportion 1:1, i.e. if master value is shifted by a certain
    403 * integer value k downwards, the value of slave is simultaneously shifted by k upwards.
    404 */
    405static
    407 SCIP* scip, /**< current scip instance */
    408 SCIP_SOL* sol, /**< current incumbent */
    409 SCIP_VAR* master, /**< current master variable */
    410 DIRECTION masterdirection, /**< the shifting direction of the master variable */
    411 SCIP_VAR* slave, /**< slave variable with same LP_row set as master variable */
    412 DIRECTION slavedirection, /**< the shifting direction of the slave variable */
    413 SCIP_Real* activities, /**< array of LP row activities */
    414 int nrows /**< the number of rows in LP and the size of the activities array */
    415 )
    416{ /*lint --e{715}*/
    417 SCIP_Real masterbound;
    418 SCIP_Real slavebound;
    420 SCIP_Real mastersolval;
    421 SCIP_Real slavesolval;
    422
    423 SCIP_COL* col;
    424 SCIP_ROW** slaverows;
    425 SCIP_ROW** masterrows;
    426 SCIP_Real* mastercolvals;
    427 SCIP_Real* slavecolvals;
    428 int nslaverows;
    429 int nmasterrows;
    430 int i;
    431 int j;
    432
    433 assert(scip != NULL);
    434 assert(sol != NULL);
    435 assert(master != NULL);
    436 assert(slave != NULL);
    437 assert(SCIPvarIsIntegral(master) && SCIPvarIsIntegral(slave));
    438 assert(masterdirection == DIRECTION_UP || masterdirection == DIRECTION_DOWN);
    439 assert(slavedirection == DIRECTION_UP || slavedirection == DIRECTION_DOWN);
    440
    441 mastersolval = SCIPgetSolVal(scip, sol, master);
    442 slavesolval = SCIPgetSolVal(scip, sol, slave);
    443
    444 /* determine the trivial variable bounds for shift */
    445 if( masterdirection == DIRECTION_UP )
    446 {
    447 bound = SCIPvarGetUbGlobal(master);
    448 masterbound = bound - mastersolval;
    449 masterbound = SCIPisFeasLE(scip, mastersolval + ceil(masterbound), bound) ? ceil(masterbound) : floor(masterbound);
    450 }
    451 else
    452 {
    453 bound = SCIPvarGetLbGlobal(master);
    454 masterbound = mastersolval - bound;
    455 masterbound = SCIPisFeasGE(scip, mastersolval - ceil(masterbound), bound) ? ceil(masterbound) : floor(masterbound);
    456 }
    457
    458 if( slavedirection == DIRECTION_UP )
    459 {
    460 bound = SCIPvarGetUbGlobal(slave);
    461 slavebound = bound - slavesolval;
    462 slavebound = SCIPisFeasLE(scip, slavesolval + ceil(slavebound), bound) ? ceil(slavebound) : floor(slavebound);
    463 }
    464 else
    465 {
    466 bound = SCIPvarGetLbGlobal(slave);
    467 slavebound = slavesolval - bound;
    468 slavebound = SCIPisFeasGE(scip, slavesolval - ceil(slavebound), bound) ? ceil(slavebound) : floor(slavebound);
    469 }
    470
    471 bound = MIN(masterbound, slavebound);
    472
    473 /* due to numerical reasons, bound can be negative -> Return value zero */
    474 if( bound <= 0.0 )
    475 return 0.0;
    476
    477 /* get the necessary row and and column data for each variable */
    478 col = SCIPvarGetCol(slave);
    479 slaverows = SCIPcolGetRows(col);
    480 slavecolvals = SCIPcolGetVals(col);
    481 nslaverows = SCIPcolGetNNonz(col);
    482
    483 col = SCIPvarGetCol(master);
    484 mastercolvals = SCIPcolGetVals(col);
    485 masterrows = SCIPcolGetRows(col);
    486 nmasterrows = SCIPcolGetNNonz(col);
    487
    488 assert(nslaverows == 0 || slavecolvals != NULL);
    489 assert(nmasterrows == 0 || mastercolvals != NULL);
    490
    491 SCIPdebugMsg(scip, " Master: %s with direction %d and %d rows, Slave: %s with direction %d and %d rows \n", SCIPvarGetName(master),
    492 (int)masterdirection, nmasterrows, SCIPvarGetName(slave), (int)slavedirection, nslaverows);
    493
    494 /* loop over all LP rows and determine the maximum integer bound by which both variables
    495 * can be shifted without loss of feasibility
    496 */
    497 i = 0;
    498 j = 0;
    499 while( i < nslaverows || j < nmasterrows )
    500 {
    501 SCIP_ROW* row;
    502 int rowpos;
    503 int masterindex;
    504 int slaveindex;
    505 SCIP_Bool slaveincrement;
    506 SCIP_Bool masterincrement;
    507
    508 /* check if one pointer already reached the end of the respective array */
    509 if( i < nslaverows && SCIProwGetLPPos(slaverows[i]) == -1 )
    510 {
    511 SCIPdebugMsg(scip, " Slaverow %s is not in LP (i=%d, j=%d)\n", SCIProwGetName(slaverows[i]), i, j);
    512 i = nslaverows;
    513 continue;
    514 }
    515 if( j < nmasterrows && SCIProwGetLPPos(masterrows[j]) == -1 )
    516 {
    517 SCIPdebugMsg(scip, " Masterrow %s is not in LP (i=%d, j=%d) \n", SCIProwGetName(masterrows[j]), i, j);
    518 j = nmasterrows;
    519 continue;
    520 }
    521
    522 slaveincrement = FALSE;
    523 /* If one counter has already reached its limit, assign a huge number to the corresponding
    524 * row index to simulate an always greater row position. */
    525 if( i < nslaverows )
    526 slaveindex = SCIProwGetIndex(slaverows[i]);
    527 else
    528 slaveindex = INT_MAX;
    529
    530 if( j < nmasterrows )
    531 masterindex = SCIProwGetIndex(masterrows[j]);
    532 else
    533 masterindex = INT_MAX;
    534
    535 assert(0 <= slaveindex && 0 <= masterindex);
    536
    537 assert(slaveindex < INT_MAX || masterindex < INT_MAX);
    538
    539 /* the current row is the one with the smaller index */
    540 if( slaveindex <= masterindex )
    541 {
    542 rowpos = SCIProwGetLPPos(slaverows[i]);
    543 row = slaverows[i];
    544 slaveincrement = TRUE;
    545 masterincrement = (slaveindex == masterindex);
    546 }
    547 else
    548 {
    549 assert(j < nmasterrows);
    550
    551 rowpos = SCIProwGetLPPos(masterrows[j]);
    552 row = masterrows[j];
    553 masterincrement = TRUE;
    554 }
    555 assert(row != NULL);
    556
    557 /* only global rows need to be valid */
    558 if( rowpos >= 0 && !SCIProwIsLocal(row) )
    559 {
    560 SCIP_Real effect;
    561 SCIP_Real side;
    562 SCIP_Bool left;
    563
    564 /* effect is the effect on the row activity by shifting the variables by 1 in the respective directions */
    565 effect = 0.0;
    566 if( slaveindex <= masterindex )
    567 effect += (slavecolvals[i] * (int)slavedirection);
    568 if( masterindex <= slaveindex )
    569 effect += (mastercolvals[j] * (int)masterdirection);
    570 left = effect < 0.0;
    571 side = left ? SCIProwGetLhs(row) : SCIProwGetRhs(row);
    572
    573 /* only non-zero effects and finite bounds need to be considered */
    574 if( !SCIPisZero(scip, effect) && !SCIPisInfinity(scip, left ? -side : side) )
    575 {
    576 SCIP_Real newval;
    577
    578 /* effect does not equal zero, the bound is determined as maximum positive integer such that
    579 * feasibility of this constraint is maintained
    580 */
    581 assert( rowpos < nrows );
    582 assert( SCIPisFeasGE(scip, activities[rowpos], SCIProwGetLhs(row)) && SCIPisFeasLE(scip, activities[rowpos], SCIProwGetRhs(row)) );
    583 assert( effect );
    584
    585 SCIPdebugMsg(scip, " %g <= %g <= %g, bound = %g, effect = %g (%g * %d + %g * %d) (i=%d,j=%d)\n",
    586 SCIProwGetLhs(row), activities[rowpos], SCIProwGetRhs(row), bound, effect,
    587 slaveindex <= masterindex ? slavecolvals[i] : 0.0, (int)slavedirection,
    588 masterindex <= slaveindex ? mastercolvals[j] : 0.0, (int)masterdirection, i, j);
    589
    590 newval = (side - activities[rowpos]) / effect;
    591
    592 /* update shifting distance */
    593 if( newval < bound )
    594 {
    595 SCIP_Real activity;
    596
    597 activity = activities[rowpos] + effect * ceil(newval);
    598
    599 /* ensure that shifting preserves feasibility */
    600 if( ( left && SCIPisFeasGE(scip, activity, side) ) || ( !left && SCIPisFeasLE(scip, activity, side) ) )
    601 bound = ceil(newval);
    602 else
    603 bound = floor(newval);
    604
    605 /* due to numerical reasons, bound can be negative. A variable shift by a negative bound is not desired by
    606 * the heuristic -> Return value zero */
    607 if( bound <= 0.0 )
    608 return 0.0;
    609 }
    610
    611 assert( SCIPisFeasGE(scip, activities[rowpos] + effect * bound, SCIProwGetLhs(row)) && SCIPisFeasLE(scip, activities[rowpos] + effect * bound, SCIProwGetRhs(row)) );
    612 assert( SCIPisFeasIntegral(scip, bound) );
    613 }
    614 else
    615 {
    616 SCIPdebugMsg(scip, " No influence of row %s, effect %g, master coeff: %g slave coeff: %g (i=%d, j=%d)\n",
    617 SCIProwGetName(row), effect, mastercolvals[j], slavecolvals[i], i, j);
    618 }
    619 }
    620 else
    621 {
    622 SCIPdebugMsg(scip, " Row %s is local.\n", SCIProwGetName(row));
    623 }
    624
    625 /* increase the counters which belong to the corresponding row. Both counters are increased by
    626 * 1 iff rowpos1 <= rowpos2 <= rowpos1 */
    627 if( slaveincrement )
    628 ++i;
    629 if( masterincrement )
    630 ++j;
    631 }
    632
    633 /* we must not shift variables to infinity */
    634 return SCIPisInfinity(scip, bound + MAX((int)masterdirection * mastersolval, (int)slavedirection * slavesolval)) ? 0.0 : bound;
    635}
    636
    637
    638/** Disposes variable with no heuristic relevancy, e.g., due to a fixed solution value, from its neighborhood block.
    639 *
    640 * The affected neighborhood block is reduced by 1.
    641 */
    642static
    644 SCIP_VAR** vars, /**< problem variables */
    645 int* blockend, /**< contains end index of block */
    646 int varindex /**< variable index */
    647 )
    648{
    649 assert(blockend != NULL);
    650 assert(varindex <= *blockend);
    651
    652 vars[varindex] = vars[*blockend];
    653 --(*blockend);
    654}
    655
    656/** realizes the presolve independently from type of variables it's applied to */
    657static
    659 SCIP* scip, /**< current scip */
    660 SCIP_VAR** vars, /**< heuristic specific variables */
    661 int nvars, /**< the number of variables */
    662 int* nblocks, /**< pointer to store the number of detected blocks */
    663 int* maxblocksize, /**< maximum size of a block */
    664 int* nblockvars, /**< pointer to store the number of block variables */
    665 int** blockstart, /**< pointer to store the array of block start indices */
    666 int** blockend, /**< pointer to store the array of block end indices */
    667 SCIP_HEUR* heur, /**< the heuristic */
    668 SCIP_HEURDATA* heurdata /**< the heuristic data */
    669 )
    670{
    671 int startindex;
    672
    673 assert(scip != NULL);
    674 assert(vars != NULL);
    675 assert(nvars > 1);
    676 assert(nblocks != NULL);
    677 assert(maxblocksize != NULL);
    678 assert(nblockvars != NULL);
    679 assert(blockstart != NULL);
    680 assert(blockend != NULL);
    681 assert(heur != NULL);
    682 assert(heurdata != NULL);
    683
    684 /* sort the variables with respect to their columns */
    685 SCIPsortPtr((void**)vars, SCIPvarcolComp, nvars);
    686
    687 /* start determining blocks, i.e. a set of at least two variables which share most of their row set.
    688 * If there is none, heuristic does not need to be executed.
    689 */
    690 startindex = 0;
    691 *nblocks = 0;
    692 *maxblocksize = 0;
    693 *nblockvars = 0;
    694
    695 SCIP_CALL( SCIPallocBlockMemoryArray(scip, blockstart, nvars/2) );
    696 SCIP_CALL( SCIPallocBlockMemoryArray(scip, blockend, nvars/2) );
    697
    698 /* loop over variables and compare neighbors */
    699 for( int v = 1; v < nvars; ++v )
    700 {
    701 if( !checkConstraintMatching(scip, vars[startindex], vars[v], heurdata->matchingrate) )
    702 {
    703 /* current block has its last variable at position v-1. If v differs from startindex by at least 2,
    704 * a block is detected. Update the data correspondingly */
    705 if( v - startindex >= 2 )
    706 {
    707 assert(*nblocks < nvars/2);
    708 (*nblockvars) += v - startindex;
    709 (*maxblocksize) = MAX((*maxblocksize), v - startindex);
    710 (*blockstart)[*nblocks] = startindex;
    711 (*blockend)[*nblocks] = v - 1;
    712 (*nblocks)++;
    713 }
    714 startindex = v;
    715 }
    716 else if( v == nvars - 1 && v - startindex >= 1 )
    717 {
    718 assert(*nblocks < nvars/2);
    719 (*nblockvars) += v - startindex + 1;
    720 (*maxblocksize) = MAX((*maxblocksize), v - startindex + 1);
    721 (*blockstart)[*nblocks] = startindex;
    722 (*blockend)[*nblocks] = v;
    723 (*nblocks)++;
    724 }
    725 }
    726
    727 /* reallocate memory with respect to the number of found blocks; if there were none, free the memory */
    728 if( *nblocks > 0 )
    729 {
    730 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, blockstart, nvars/2, *nblocks) );
    731 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, blockend, nvars/2, *nblocks) );
    732 }
    733 else
    734 {
    735 SCIPfreeBlockMemoryArray(scip, blockstart, nvars/2);
    736 SCIPfreeBlockMemoryArray(scip, blockend, nvars/2);
    737
    738 *blockstart = NULL;
    739 *blockend = NULL;
    740 }
    741
    742 return SCIP_OKAY;
    743}
    744
    745/** initializes the required structures for execution of heuristic.
    746 *
    747 * If objective coefficient functions are not all equal, each Binary and Integer variables are sorted
    748 * into heuristic-specific arrays with respect to their lexicographical column order,
    749 * where every zero in a column is interpreted as zero and every nonzero as '1'.
    750 * After the sorting, the variables are compared with respect to user parameter matchingrate and
    751 * the heuristic specific blocks are determined.
    752 */
    753static
    755 SCIP* scip, /**< current scip instance */
    756 SCIP_HEUR* heur, /**< heuristic */
    757 SCIP_HEURDATA* heurdata /**< the heuristic data */
    758 )
    759{
    760 SCIP_VAR** vars;
    761 int nbinvars;
    762 int nintvars;
    763 int nbinimplvars;
    764 int nintimplvars;
    765 int ntotalbinvars;
    766 int ntotalintvars;
    767 int nbinblockvars;
    768 int nintblockvars;
    769 int maxbinblocksize;
    770 int maxintblocksize;
    771 int i;
    772
    773 assert(scip != NULL);
    774 assert(heurdata != NULL);
    775
    776 /* initialize execution flag */
    777 heurdata->execute = FALSE;
    778
    779 /* get necessary variable information, i.e. number of binary and integer variable types */
    780 vars = SCIPgetVars(scip);
    781 nbinvars = SCIPgetNBinVars(scip);
    782 nintvars = SCIPgetNIntVars(scip);
    783 nbinimplvars = SCIPgetNBinImplVars(scip);
    784 nintimplvars = SCIPgetNIntImplVars(scip);
    785 ntotalbinvars = nbinvars + nbinimplvars;
    786 ntotalintvars = nintvars + nintimplvars;
    787
    788#ifdef SCIP_STATISTIC
    789 /* update statistics */
    790 heurdata->ntotalbinvars += ntotalbinvars;
    791#endif
    792
    793 /* if number of binary problem variables exceeds one, they are subject to 2-optimization algorithm, hence heuristic
    794 * calls innerPresolve method to detect necessary structures */
    795 if( ntotalbinvars > 1 )
    796 {
    797 /* allocate the heuristic specific binary variables */
    798 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->binvars), ntotalbinvars) );
    799
    800 /* copy binary variables */
    801 i = 0;
    802 for(; i < nbinvars; ++i )
    803 heurdata->binvars[i] = vars[i];
    804 for(; i < ntotalbinvars; ++i )
    805 heurdata->binvars[i] = vars[i + nintvars];
    806 heurdata->nbinvars = ntotalbinvars;
    807
    808 /* execute block presolving */
    809 SCIP_CALL( innerPresolve(scip, heurdata->binvars, heurdata->nbinvars, &(heurdata->nbinblocks), &maxbinblocksize,
    810 &nbinblockvars, &(heurdata->binblockstart), &(heurdata->binblockend), heur, heurdata) );
    811
    812 /* detect binary block */
    813 if( heurdata->nbinblocks > 0 )
    814 heurdata->execute = TRUE;
    815
    816#ifdef SCIP_STATISTIC
    817 /* update statistics */
    818 heurdata->binnblocks += heurdata->nbinblocks;
    819 heurdata->binnblockvars += nbinblockvars;
    820 heurdata->maxbinblocksize = MAX(maxbinblocksize, heurdata->maxbinblocksize);
    821
    822 SCIPstatisticMessage(" Twoopt BINARY presolving finished with <%d> blocks, <%d> block variables \n",
    823 heurdata->nbinblocks, nbinblockvars);
    824#endif
    825 }
    826
    827 if( heurdata->intopt && ntotalintvars > 1 )
    828 {
    829 /* allocate the heuristic specific integer variables */
    830 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->intvars), ntotalintvars) );
    831
    832 /* copy integer variables */
    833 i = 0;
    834 for(; i < nintvars; ++i )
    835 heurdata->intvars[i] = vars[i + nbinvars];
    836 for(; i < ntotalintvars; ++i )
    837 heurdata->intvars[i] = vars[i + ntotalbinvars];
    838 heurdata->nintvars = ntotalintvars;
    839
    840 /* execute block presolving */
    841 SCIP_CALL( innerPresolve(scip, heurdata->intvars, heurdata->nintvars, &(heurdata->nintblocks), &maxintblocksize,
    842 &nintblockvars, &(heurdata->intblockstart), &(heurdata->intblockend), heur, heurdata) );
    843
    844 /* detect integer block */
    845 if( heurdata->nintblocks > 0 )
    846 heurdata->execute = TRUE;
    847
    848#ifdef SCIP_STATISTIC
    849 /* update statistics */
    850 heurdata->intnblocks += heurdata->nintblocks;
    851 heurdata->intnblockvars += nintblockvars;
    852 heurdata->ntotalintvars += ntotalintvars;
    853 heurdata->maxintblocksize = MAX(maxintblocksize, heurdata->maxintblocksize);
    854 SCIPstatisticMessage(" Twoopt Integer presolving finished with <%d> blocks, <%d> block variables \n",
    855 heurdata->nintblocks, nintblockvars);
    856 SCIPstatisticMessage(" INTEGER coefficients are all equal \n");
    857#endif
    858 }
    859
    860 /* presolving is finished, heuristic data is updated*/
    861 heurdata->presolved = TRUE;
    862 SCIPheurSetData(heur, heurdata);
    863
    864 return SCIP_OKAY;
    865}
    866
    867/*
    868 * Callback methods of primal heuristic
    869 */
    870
    871/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    872static
    873SCIP_DECL_HEURCOPY(heurCopyTwoopt)
    874{ /*lint --e{715}*/
    875 assert(scip != NULL);
    876 assert(heur != NULL);
    877
    879
    880 /* call inclusion method of primal heuristic */
    882
    883 return SCIP_OKAY;
    884}
    885
    886/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    887static
    888SCIP_DECL_HEURFREE(heurFreeTwoopt)
    889{ /*lint --e{715}*/
    890 SCIP_HEURDATA* heurdata;
    891
    892 assert(heur != NULL);
    893 assert(scip != NULL);
    894
    896
    897 /* free heuristic data */
    898 heurdata = SCIPheurGetData(heur);
    899 assert(heurdata != NULL);
    900
    901 SCIPfreeBlockMemory(scip, &heurdata);
    902 SCIPheurSetData(heur, NULL);
    903
    904 return SCIP_OKAY;
    905}
    906
    907/** initialization method of primal heuristic (called after problem was transformed) */
    908static
    909SCIP_DECL_HEURINIT(heurInitTwoopt)
    910{
    911 SCIP_HEURDATA* heurdata;
    912 assert(heur != NULL);
    913 assert(scip != NULL);
    914
    916
    917 heurdata = SCIPheurGetData(heur);
    918 assert(heurdata != NULL);
    919
    920 /* heuristic has not run yet, all heuristic specific data is set to initial values */
    921 heurdata->nbinvars = 0;
    922 heurdata->nintvars = 0;
    923 heurdata->lastsolindex = -1;
    924 heurdata->presolved = FALSE;
    925 heurdata->nbinblocks = 0;
    926 heurdata->nintblocks = 0;
    927
    928 /* create random number generator */
    929 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    931
    932#ifdef SCIP_STATISTIC
    933 /* initialize statistics */
    934 heurdata->binnexchanges = 0;
    935 heurdata->intnexchanges = 0;
    936 heurdata->binnblockvars = 0;
    937 heurdata->intnblockvars = 0;
    938 heurdata->binnblocks = 0;
    939 heurdata->intnblocks = 0;
    940
    941 heurdata->maxbinblocksize = 0;
    942 heurdata->maxintblocksize = 0;
    943
    944 heurdata->ntotalbinvars = 0;
    945 heurdata->ntotalintvars = 0;
    946 heurdata->nruns = 0;
    947#endif
    948
    949 /* all pointers are initially set to NULL. Since presolving
    950 * of the heuristic requires a lot of calculation time on some instances,
    951 * but might not be needed e.g. if problem is infeasible, presolving is applied
    952 * when heuristic is executed for the first time
    953 */
    954 heurdata->binvars = NULL;
    955 heurdata->intvars = NULL;
    956 heurdata->binblockstart = NULL;
    957 heurdata->binblockend = NULL;
    958 heurdata->intblockstart = NULL;
    959 heurdata->intblockend = NULL;
    960
    961 SCIPheurSetData(heur, heurdata);
    962
    963 return SCIP_OKAY;
    964}
    965
    966/* Realizes the 2-optimization algorithm, which tries to improve incumbent solution
    967 * by shifting pairs of variables which share a common row set.
    968 */
    969static
    971 SCIP* scip, /**< current SCIP instance */
    972 SCIP_SOL* worksol, /**< working solution */
    973 SCIP_VAR** vars, /**< binary or integer variables */
    974 int* blockstart, /**< contains start indices of blocks */
    975 int* blockend, /**< contains end indices of blocks */
    976 int nblocks, /**< the number of blocks */
    977 OPTTYPE opttype, /**< are binaries or integers optimized */
    978 SCIP_Real* activities, /**< the LP-row activities */
    979 int nrows, /**< the number of LP rows */
    980 SCIP_Bool* improvement, /**< was there a successful shift? */
    981 SCIP_Bool* varboundserr, /**< has the current incumbent already been cut off */
    982 SCIP_HEURDATA* heurdata /**< the heuristic data */
    983 )
    984{ /*lint --e{715}*/
    985 SCIP_Real* objchanges;
    986 SCIP_VAR** bestmasters;
    987 SCIP_VAR** bestslaves;
    988 int* bestdirections;
    989 int arraysize;
    990 int npairs = 0;
    991
    992 assert(scip != NULL);
    993 assert(nblocks > 0);
    994 assert(blockstart != NULL && blockend != NULL);
    995 assert(varboundserr != NULL);
    996 assert(activities != NULL);
    997 assert(worksol != NULL);
    998 assert(improvement != NULL);
    999
    1000 *varboundserr = FALSE;
    1001
    1006 arraysize = DEFAULT_ARRAYSIZE;
    1007
    1008 /* iterate over blocks */
    1009 for( int b = 0; b < nblocks; ++b )
    1010 {
    1011 int blocklen;
    1012
    1013 blocklen = blockend[b] - blockstart[b] + 1;
    1014
    1015 /* iterate over variables in current block */
    1016 for( int m = 0; m < blocklen; ++m )
    1017 {
    1018 /* determine the new master variable for heuristic's optimization method */
    1019 SCIP_VAR* master;
    1020 SCIP_Real masterobj;
    1021 SCIP_Real mastersolval;
    1022 SCIP_Real bestimprovement;
    1023 SCIP_Real bestbound;
    1024 int bestslavepos;
    1025 int firstslave;
    1026 int nslaves;
    1027 int bestdirection;
    1028 DIRECTION bestmasterdir;
    1029 DIRECTION bestslavedir;
    1030
    1031 master = vars[blockstart[b] + m]; /*lint !e679*/
    1032 masterobj = SCIPvarGetObj(master);
    1033 mastersolval = SCIPgetSolVal(scip, worksol, master);
    1034
    1035 /* due to cuts or fixings of solution values, worksol might not be feasible w.r.t. its bounds.
    1036 * Exit method in that case. */
    1037 if( SCIPisFeasGT(scip, mastersolval, SCIPvarGetUbGlobal(master)) || SCIPisFeasLT(scip, mastersolval, SCIPvarGetLbGlobal(master)) )
    1038 {
    1039 *varboundserr = TRUE;
    1040 SCIPdebugMsg(scip, "Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
    1041 SCIPvarGetName(master), SCIPvarGetLbGlobal(master), mastersolval, SCIPvarGetUbGlobal(master));
    1042 goto TERMINATE;
    1043 }
    1044
    1045 /* if variable has fixed solution value, it is deleted from heuristic array */
    1047 {
    1048 disposeVariable(vars, &(blockend[b]), blockstart[b] + m);
    1049 --blocklen;
    1050 continue;
    1051 }
    1052 else if( SCIPvarGetStatus(master) != SCIP_VARSTATUS_COLUMN )
    1053 continue;
    1054
    1055 assert(SCIPisFeasIntegral(scip, mastersolval));
    1056
    1057 assert(opttype == OPTTYPE_INTEGER || (SCIPisFeasLE(scip, mastersolval, 1.0) || SCIPisFeasGE(scip, mastersolval, 0.0)));
    1058
    1059 /* initialize the data of the best available shift */
    1060 bestimprovement = 0.0;
    1061 bestslavepos = -1;
    1062 bestbound = 0.0;
    1063 bestmasterdir = DIRECTION_NONE;
    1064 bestslavedir = DIRECTION_NONE;
    1065 bestdirection = -1;
    1066
    1067 /* in blocks with more than heurdata->maxnslaves variables, a slave candidate region is chosen */
    1068 if( heurdata->maxnslaves >= 0 && blocklen > heurdata->maxnslaves )
    1069 firstslave = SCIPrandomGetInt(heurdata->randnumgen, blockstart[b] + m, blockend[b]);
    1070 else
    1071 firstslave = blockstart[b] + m + 1;
    1072
    1073 nslaves = MIN((heurdata->maxnslaves == -1 ? INT_MAX : heurdata->maxnslaves), blocklen);
    1074
    1075 /* Loop over block and determine a slave shift candidate for master variable.
    1076 * If more than one candidate is available, choose the shift which improves objective function
    1077 * the most. */
    1078 for( int s = 0; s < nslaves; ++s )
    1079 {
    1080 SCIP_VAR* slave;
    1081 SCIP_Real slaveobj;
    1082 SCIP_Real slavesolval;
    1083 SCIP_Real changedobj;
    1084 SCIP_Real diffdirbound;
    1085 SCIP_Real equaldirbound;
    1086 int directions;
    1087 int slaveindex;
    1088
    1089 slaveindex = (firstslave + s - blockstart[b]) % blocklen;
    1090 slaveindex += blockstart[b];
    1091
    1092 /* in case of a small block, we do not want to try possible pairings twice */
    1093 if( (blocklen <= heurdata->maxnslaves || heurdata->maxnslaves == -1) && slaveindex < blockstart[b] + m )
    1094 break;
    1095 /* master and slave should not be the same variable */
    1096 if( slaveindex == blockstart[b] + m )
    1097 continue;
    1098
    1099 /* get the next slave variable */
    1100 slave = vars[slaveindex];
    1101 slaveobj = SCIPvarGetObj(slave);
    1102 slavesolval = SCIPgetSolVal(scip, worksol, slave);
    1103 changedobj = 0.0;
    1104
    1105 assert(SCIPvarGetType(master) == SCIPvarGetType(slave));
    1106 assert(SCIPisFeasIntegral(scip, slavesolval));
    1107 assert(opttype == OPTTYPE_INTEGER || (SCIPisFeasLE(scip, mastersolval, 1.0) || SCIPisFeasGE(scip, mastersolval, 0.0)));
    1108
    1109 /* solution is not feasible w.r.t. the variable bounds, stop optimization in this case */
    1110 if( SCIPisFeasGT(scip, slavesolval, SCIPvarGetUbGlobal(slave)) || SCIPisFeasLT(scip, slavesolval, SCIPvarGetLbGlobal(slave)) )
    1111 {
    1112 *varboundserr = TRUE;
    1113 SCIPdebugMsg(scip, "Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
    1114 SCIPvarGetName(slave), SCIPvarGetLbGlobal(slave), slavesolval, SCIPvarGetUbGlobal(slave));
    1115 goto TERMINATE;
    1116 }
    1117
    1118 /* if solution value of the variable is fixed, delete it from the remaining candidates in the block */
    1120 {
    1121 disposeVariable(vars, &(blockend[b]), slaveindex);
    1122 --blocklen;
    1123 continue;
    1124 }
    1125 else if( SCIPvarGetStatus(master) != SCIP_VARSTATUS_COLUMN )
    1126 continue;
    1127
    1128 /* determine the shifting direction to improve the objective function */
    1129 /* The heuristic chooses the shifting direction and the corresponding maximum nonnegative
    1130 * integer shift value for the two variables which preserves feasibility and improves
    1131 * the objective function value. */
    1132 directions = -1;
    1133 diffdirbound = 0.0;
    1134 equaldirbound = 0.0;
    1135
    1136 if( SCIPisPositive(scip, slaveobj - masterobj) )
    1137 {
    1138 diffdirbound = determineBound(scip, worksol, master, DIRECTION_UP, slave, DIRECTION_DOWN, activities, nrows);
    1139 directions = 2;
    1140 /* the improvement of objective function is calculated */
    1141 changedobj = (masterobj - slaveobj) * diffdirbound;
    1142 }
    1143 else if( SCIPisPositive(scip, masterobj - slaveobj) )
    1144 {
    1145 diffdirbound = determineBound(scip, worksol, master, DIRECTION_DOWN, slave, DIRECTION_UP, activities, nrows);
    1146 directions = 1;
    1147 changedobj = (slaveobj - masterobj) * diffdirbound;
    1148 }
    1149
    1150 if( SCIPisPositive(scip, -(masterobj + slaveobj)) )
    1151 {
    1152 equaldirbound = determineBound(scip, worksol, master, DIRECTION_UP, slave, DIRECTION_UP, activities, nrows);
    1153 if( (masterobj + slaveobj) * equaldirbound < changedobj )
    1154 {
    1155 changedobj = (masterobj + slaveobj) * equaldirbound;
    1156 directions = 3;
    1157 }
    1158 }
    1159 else if( SCIPisPositive(scip, masterobj + slaveobj) )
    1160 {
    1161 equaldirbound = determineBound(scip, worksol, master, DIRECTION_DOWN, slave, DIRECTION_DOWN, activities, nrows);
    1162 if( -(masterobj + slaveobj) * equaldirbound < changedobj )
    1163 {
    1164 changedobj = -(masterobj + slaveobj) * equaldirbound;
    1165 directions = 0;
    1166 }
    1167 }
    1168 assert(SCIPisFeasIntegral(scip, equaldirbound));
    1169 assert(SCIPisFeasIntegral(scip, diffdirbound));
    1170 assert(SCIPisFeasGE(scip, equaldirbound, 0.0));
    1171 assert(SCIPisFeasGE(scip, diffdirbound, 0.0));
    1172
    1173 /* choose the candidate which improves the objective function the most */
    1174 if( (SCIPisFeasGT(scip, equaldirbound, 0.0) || SCIPisFeasGT(scip, diffdirbound, 0.0))
    1175 && changedobj < bestimprovement )
    1176 {
    1177 bestimprovement = changedobj;
    1178 bestslavepos = slaveindex;
    1179 bestdirection = directions;
    1180
    1181 /* the most promising shift, i.e., the one which can improve the objective
    1182 * the most, is recorded by the integer 'directions'. It is recovered via the use
    1183 * of a binary representation of the four different combinations for the shifting directions
    1184 * of two variables */
    1185 if( directions / 2 == 1 )
    1186 bestmasterdir = DIRECTION_UP;
    1187 else
    1188 bestmasterdir = DIRECTION_DOWN;
    1189
    1190 if( directions % 2 == 1 )
    1191 bestslavedir = DIRECTION_UP;
    1192 else
    1193 bestslavedir = DIRECTION_DOWN;
    1194
    1195 if( bestmasterdir == bestslavedir )
    1196 bestbound = equaldirbound;
    1197 else
    1198 bestbound = diffdirbound;
    1199 }
    1200 }
    1201
    1202 /* choose the most promising candidate, if one exists */
    1203 if( bestslavepos >= 0 )
    1204 {
    1205 if( npairs == arraysize )
    1206 {
    1207 SCIP_CALL( SCIPreallocBufferArray(scip, &bestmasters, 2 * arraysize) );
    1208 SCIP_CALL( SCIPreallocBufferArray(scip, &bestslaves, 2 * arraysize) );
    1209 SCIP_CALL( SCIPreallocBufferArray(scip, &objchanges, 2 * arraysize) );
    1210 SCIP_CALL( SCIPreallocBufferArray(scip, &bestdirections, 2 * arraysize) );
    1211 arraysize = 2 * arraysize;
    1212 }
    1213 assert( npairs < arraysize );
    1214
    1215 bestmasters[npairs] = master;
    1216 bestslaves[npairs] = vars[bestslavepos];
    1217 objchanges[npairs] = ((int)bestslavedir * SCIPvarGetObj(bestslaves[npairs]) + (int)bestmasterdir * masterobj) * bestbound;
    1218 bestdirections[npairs] = bestdirection;
    1219
    1220 assert(objchanges[npairs] < 0);
    1221
    1222 SCIPdebugMsg(scip, " Saved candidate pair {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g} %d\n",
    1223 SCIPvarGetName(master), mastersolval, SCIPvarGetName(bestslaves[npairs]), SCIPgetSolVal(scip, worksol, bestslaves[npairs]) ,
    1224 masterobj, SCIPvarGetObj(bestslaves[npairs]), mastersolval + (int)bestmasterdir * bestbound, SCIPgetSolVal(scip, worksol, bestslaves[npairs])
    1225 + (int)bestslavedir * bestbound, bestdirections[npairs]);
    1226
    1227 ++npairs;
    1228 }
    1229 }
    1230 }
    1231
    1232 if( npairs == 0 )
    1233 goto TERMINATE;
    1234
    1235 SCIPsortRealPtrPtrInt(objchanges, (void**)bestmasters, (void**)bestslaves, bestdirections, npairs);
    1236
    1237 for( int b = 0; b < npairs; ++b )
    1238 {
    1239 SCIP_VAR* master;
    1240 SCIP_VAR* slave;
    1241 SCIP_Real mastersolval;
    1242 SCIP_Real slavesolval;
    1243 SCIP_Real masterobj;
    1244 SCIP_Real slaveobj;
    1246 DIRECTION masterdir;
    1247 DIRECTION slavedir;
    1248
    1249 master = bestmasters[b];
    1250 slave = bestslaves[b];
    1251 mastersolval = SCIPgetSolVal(scip, worksol, master);
    1252 slavesolval = SCIPgetSolVal(scip, worksol, slave);
    1253 masterobj =SCIPvarGetObj(master);
    1254 slaveobj = SCIPvarGetObj(slave);
    1255
    1256 assert(0 <= bestdirections[b] && bestdirections[b] < 4);
    1257
    1258 if( bestdirections[b] / 2 == 1 )
    1259 masterdir = DIRECTION_UP;
    1260 else
    1261 masterdir = DIRECTION_DOWN;
    1262
    1263 if( bestdirections[b] % 2 == 1 )
    1264 slavedir = DIRECTION_UP;
    1265 else
    1266 slavedir = DIRECTION_DOWN;
    1267
    1268 bound = determineBound(scip, worksol, master, masterdir, slave, slavedir, activities, nrows);
    1269
    1270 if( !SCIPisZero(scip, bound) )
    1271 {
    1272 SCIP_Bool feasible;
    1273#ifndef NDEBUG
    1274 SCIP_Real changedobj;
    1275#endif
    1276
    1277 SCIPdebugMsg(scip, " Promising candidates {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g}\n",
    1278 SCIPvarGetName(master), mastersolval, SCIPvarGetName(slave), slavesolval,
    1279 masterobj, slaveobj, mastersolval + (int)masterdir * bound, slavesolval + (int)slavedir * bound);
    1280
    1281#ifndef NDEBUG
    1282 /* the improvement of objective function is calculated */
    1283 changedobj = ((int)slavedir * slaveobj + (int)masterdir * masterobj) * bound;
    1284 assert( SCIPisPositive(scip, -changedobj) );
    1285#endif
    1286
    1288 /* try to change the solution values of the variables */
    1289 feasible = FALSE;
    1290 SCIP_CALL( shiftValues(scip, master, slave, mastersolval, masterdir, slavesolval, slavedir, bound,
    1291 activities, nrows, &feasible) );
    1292
    1293 if( feasible )
    1294 {
    1295 /* The variables' solution values were successfully shifted and can hence be updated. */
    1296 assert(SCIPisFeasIntegral(scip, mastersolval + ((int)masterdir * bound)));
    1297 assert(SCIPisFeasIntegral(scip, slavesolval + ((int)slavedir * bound)));
    1298
    1299 SCIP_CALL( SCIPsetSolVal(scip, worksol, master, mastersolval + (int)masterdir * bound) );
    1300 SCIP_CALL( SCIPsetSolVal(scip, worksol, slave, slavesolval + (int)slavedir * bound) );
    1301 SCIPdebugMsg(scip, " Feasible shift: <%s>[%g, %g] (obj: %f) <%f> --> <%f>\n",
    1302 SCIPvarGetName(master), SCIPvarGetLbGlobal(master), SCIPvarGetUbGlobal(master), masterobj, mastersolval, SCIPgetSolVal(scip, worksol, master));
    1303 SCIPdebugMsg(scip, " <%s>[%g, %g] (obj: %f) <%f> --> <%f>\n",
    1304 SCIPvarGetName(slave), SCIPvarGetLbGlobal(slave), SCIPvarGetUbGlobal(slave), slaveobj, slavesolval, SCIPgetSolVal(scip, worksol, slave));
    1305
    1306#ifdef SCIP_STATISTIC
    1307 /* update statistics */
    1308 if( opttype == OPTTYPE_BINARY )
    1309 ++(heurdata->binnexchanges);
    1310 else
    1311 ++(heurdata->intnexchanges);
    1312#endif
    1313
    1314 *improvement = TRUE;
    1315 }
    1316 }
    1317 }
    1318 TERMINATE:
    1319 SCIPfreeBufferArray(scip, &bestdirections);
    1320 SCIPfreeBufferArray(scip, &objchanges);
    1321 SCIPfreeBufferArray(scip, &bestslaves);
    1322 SCIPfreeBufferArray(scip, &bestmasters);
    1323
    1324 return SCIP_OKAY;
    1325}
    1326
    1327/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    1328static
    1329SCIP_DECL_HEUREXIT(heurExitTwoopt)
    1330{
    1331 SCIP_HEURDATA* heurdata;
    1332
    1333 heurdata = SCIPheurGetData(heur);
    1334 assert(heurdata != NULL);
    1335
    1336 /*ensure that initialization was successful */
    1337 assert(heurdata->nbinvars <= 1 || heurdata->binvars != NULL);
    1338
    1339#ifdef SCIP_STATISTIC
    1340 /* print relevant statistics to console */
    1342 " Twoopt Binary Statistics : "
    1343 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg. block size, max block size) \n",
    1344 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->binnblocks/(heurdata->nruns),
    1345 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->binnblockvars/(heurdata->nruns),
    1346 heurdata->ntotalbinvars == 0 ? 0.0 : (SCIP_Real)heurdata->binnblockvars/(heurdata->ntotalbinvars) * 100.0,
    1347 heurdata->binnblocks == 0 ? 0.0 : heurdata->binnblockvars/(SCIP_Real)(heurdata->binnblocks),
    1348 heurdata->maxbinblocksize);
    1349
    1351 " Twoopt Integer statistics : "
    1352 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg block size, max block size) \n",
    1353 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->intnblocks/(heurdata->nruns),
    1354 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->intnblockvars/(heurdata->nruns),
    1355 heurdata->ntotalintvars == 0 ? 0.0 : (SCIP_Real)heurdata->intnblockvars/(heurdata->ntotalintvars) * 100.0,
    1356 heurdata->intnblocks == 0 ? 0.0 : heurdata->intnblockvars/(SCIP_Real)(heurdata->intnblocks),
    1357 heurdata->maxintblocksize);
    1358
    1360 " Twoopt results : "
    1361 "%6d %6d %4d %4.2g (runs, binary exchanges, Integer shiftings, matching rate)\n",
    1362 heurdata->nruns,
    1363 heurdata->binnexchanges,
    1364 heurdata->intnexchanges,
    1365 heurdata->matchingrate);
    1366
    1367 /* set statistics to initial values*/
    1368 heurdata->binnblockvars = 0;
    1369 heurdata->binnblocks = 0;
    1370 heurdata->intnblocks = 0;
    1371 heurdata->intnblockvars = 0;
    1372 heurdata->binnexchanges = 0;
    1373 heurdata->intnexchanges = 0;
    1374#endif
    1375
    1376 /* free the allocated memory for the binary variables */
    1377 if( heurdata->binvars != NULL )
    1378 {
    1379 SCIPfreeBlockMemoryArray(scip, &heurdata->binvars, heurdata->nbinvars);
    1380 }
    1381
    1382 if( heurdata->nbinblocks > 0 )
    1383 {
    1384 assert(heurdata->binblockstart != NULL);
    1385 assert(heurdata->binblockend != NULL);
    1386
    1387 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockstart, heurdata->nbinblocks);
    1388 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockend, heurdata->nbinblocks);
    1389 }
    1390 heurdata->nbinvars = 0;
    1391 heurdata->nbinblocks = 0;
    1392
    1393 if( heurdata->nintblocks > 0 )
    1394 {
    1395 assert(heurdata->intblockstart != NULL);
    1396 assert(heurdata->intblockend != NULL);
    1397
    1398 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockstart, heurdata->nintblocks);
    1399 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockend, heurdata->nintblocks);
    1400 }
    1401
    1402 /* free the allocated memory for the integers */
    1403 if( heurdata->intvars != NULL )
    1404 {
    1405 SCIPfreeBlockMemoryArray(scip, &heurdata->intvars, heurdata->nintvars);
    1406 }
    1407
    1408 heurdata->nbinblocks = 0;
    1409 heurdata->nintblocks = 0;
    1410 heurdata->nbinvars = 0;
    1411 heurdata->nintvars = 0;
    1412
    1413 assert(heurdata->binvars == NULL);
    1414 assert(heurdata->intvars == NULL);
    1415
    1416 /* free random number generator */
    1417 SCIPfreeRandom(scip, &heurdata->randnumgen);
    1418
    1419 SCIPheurSetData(heur, heurdata);
    1420
    1421 return SCIP_OKAY;
    1422}
    1423
    1424/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    1425static
    1426SCIP_DECL_HEURINITSOL(heurInitsolTwoopt)
    1427{
    1428 SCIP_HEURDATA* heurdata;
    1429 assert(heur != NULL);
    1430 assert(scip != NULL);
    1431
    1433
    1434 /* get heuristic data */
    1435 heurdata = SCIPheurGetData(heur);
    1436
    1437 assert(heurdata != NULL);
    1438 assert(heurdata->binvars == NULL && heurdata->intvars == NULL);
    1439 assert(heurdata->binblockstart == NULL && heurdata->binblockend == NULL);
    1440 assert(heurdata->intblockstart == NULL && heurdata->intblockend == NULL);
    1441
    1442 /* set heuristic data to initial values, but increase the total number of runs */
    1443 heurdata->nbinvars = 0;
    1444 heurdata->nintvars = 0;
    1445 heurdata->lastsolindex = -1;
    1446 heurdata->presolved = FALSE;
    1447
    1448#ifdef SCIP_STATISTIC
    1449 ++(heurdata->nruns);
    1450#endif
    1451
    1452 SCIPheurSetData(heur, heurdata);
    1453
    1454 return SCIP_OKAY;
    1455}
    1456
    1457
    1458/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
    1459static
    1460SCIP_DECL_HEUREXITSOL(heurExitsolTwoopt)
    1461{
    1462 SCIP_HEURDATA* heurdata;
    1463 int nbinvars;
    1464 int nintvars;
    1465
    1466 assert(heur != NULL);
    1467 assert(scip != NULL);
    1468 assert(scip != NULL);
    1469
    1471
    1472 /* get heuristic data */
    1473 heurdata = SCIPheurGetData(heur);
    1474
    1475 assert(heurdata != NULL);
    1476
    1477 nbinvars = heurdata->nbinvars;
    1478 nintvars = heurdata->nintvars;
    1479
    1480 /* free the allocated memory for the binary variables */
    1481 if( heurdata->binvars != NULL )
    1482 {
    1483 SCIPfreeBlockMemoryArray(scip, &heurdata->binvars, nbinvars);
    1484 }
    1485 if( heurdata->binblockstart != NULL )
    1486 {
    1487 assert(heurdata->binblockend != NULL);
    1488
    1489 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockstart, heurdata->nbinblocks);
    1490 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockend, heurdata->nbinblocks);
    1491 }
    1492 heurdata->nbinvars = 0;
    1493 heurdata->nbinblocks = 0;
    1494
    1495 if( heurdata->intblockstart != NULL )
    1496 {
    1497 assert(heurdata->intblockend != NULL);
    1498
    1499 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockstart, heurdata->nintblocks);
    1500 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockend, heurdata->nintblocks);
    1501 }
    1502 heurdata->nintblocks = 0;
    1503
    1504 /* free the allocated memory for the integers */
    1505 if( heurdata->intvars != NULL )
    1506 {
    1507 SCIPfreeBlockMemoryArray(scip, &heurdata->intvars, nintvars);
    1508 }
    1509
    1510 heurdata->nintvars = 0;
    1511
    1512 assert(heurdata->binvars == NULL && heurdata->intvars == NULL);
    1513 assert(heurdata->binblockstart == NULL && heurdata->binblockend == NULL);
    1514 assert(heurdata->intblockstart == NULL && heurdata->intblockend == NULL);
    1515
    1516 /* set heuristic data */
    1517 SCIPheurSetData(heur, heurdata);
    1518
    1519 return SCIP_OKAY;
    1520}
    1521
    1522/** execution method of primal heuristic */
    1523static
    1524SCIP_DECL_HEUREXEC(heurExecTwoopt)
    1525{ /*lint --e{715}*/
    1526 SCIP_HEURDATA* heurdata;
    1527 SCIP_ROW** lprows;
    1528 SCIP_COL** cols;
    1529 SCIP_SOL* bestsol;
    1530 SCIP_SOL* worksol;
    1531 SCIP_Real* activities;
    1532 SCIP_Bool improvement;
    1533 SCIP_Bool presolthiscall;
    1534 SCIP_Bool varboundserr;
    1535 int ncols;
    1536 int ndiscvars;
    1537 int nlprows;
    1538 int ncolsforsorting;
    1539
    1540 assert(heur != NULL);
    1541 assert(scip != NULL);
    1542 assert(result != NULL);
    1543
    1544 /* get heuristic data */
    1545 heurdata = SCIPheurGetData(heur);
    1546 assert(heurdata != NULL);
    1547
    1548 *result = SCIP_DIDNOTRUN;
    1549
    1550 /* we need an LP */
    1551 if( SCIPgetNLPRows(scip) == 0 )
    1552 return SCIP_OKAY;
    1553
    1554 bestsol = SCIPgetBestSol(scip);
    1555
    1556 /* ensure that heuristic has not already been processed on current incumbent */
    1557 if( bestsol == NULL || heurdata->lastsolindex == SCIPsolGetIndex(bestsol) )
    1558 return SCIP_OKAY;
    1559
    1560 heurdata->lastsolindex = SCIPsolGetIndex(bestsol);
    1561
    1562 /* we can only work on solutions valid in the transformed space */
    1563 if( SCIPsolIsOriginal(bestsol) )
    1564 return SCIP_OKAY;
    1565
    1566#ifdef SCIP_DEBUG
    1567 SCIP_CALL( SCIPprintSol(scip, bestsol, NULL, TRUE) );
    1568#endif
    1569
    1570 /* ensure that the user defined number of nodes after last best solution has been reached, return otherwise */
    1571 if( (SCIPgetNNodes(scip) - SCIPsolGetNodenum(bestsol)) < heurdata->waitingnodes )
    1572 return SCIP_OKAY;
    1573
    1575 assert(ndiscvars >= 0);
    1576
    1577 /* we need to be able to start diving from current node in order to resolve the LP
    1578 * with continuous variables
    1579 */
    1581 return SCIP_OKAY;
    1582
    1583 /* ensure that heuristic specific presolve is applied when heuristic is executed first */
    1584 presolthiscall = FALSE;
    1585 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    1586 ncolsforsorting = MIN(ncols, ndiscvars);
    1587 if( !heurdata->presolved )
    1588 {
    1589 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    1590
    1591 for( int i = 0; i < ncolsforsorting; ++i )
    1592 SCIPcolSort(cols[i]);
    1593
    1594 SCIP_CALL( presolveTwoOpt(scip, heur, heurdata) );
    1595 presolthiscall = TRUE;
    1596 }
    1597 assert(heurdata->presolved);
    1598 assert(heurdata->nbinvars + heurdata->nintvars <= ndiscvars);
    1599
    1600 SCIPdebugMsg(scip, " Twoopt heuristic is %sexecuting.\n", heurdata->execute ? "" : "not ");
    1601
    1602 /* ensure that presolve has detected structures in the problem to which the 2-optimization can be applied.
    1603 * That is if variables exist which share a common set of LP-rows. */
    1604 if( !heurdata->execute )
    1605 return SCIP_OKAY;
    1606 assert(heurdata->nbinvars + heurdata->nintvars > 1);
    1607
    1608 /* problem satisfies all necessary conditions for 2-optimization heuristic, execute heuristic! */
    1609 *result = SCIP_DIDNOTFIND;
    1610
    1611 /* initialize a working solution as a copy of the current incumbent to be able to store
    1612 * possible improvements obtained by 2-optimization */
    1613 SCIP_CALL( SCIPcreateSolCopy(scip, &worksol, bestsol) );
    1614 SCIPsolSetHeur(worksol, heur);
    1615
    1616 /* get the LP row activities from current incumbent bestsol */
    1617 SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
    1618 SCIP_CALL( SCIPallocBufferArray(scip, &activities, nlprows) );
    1619
    1620 for( int i = 0; i < nlprows; ++i )
    1621 {
    1622 SCIP_ROW* row;
    1623
    1624 row = lprows[i];
    1625 assert(row != NULL);
    1626 assert(SCIProwGetLPPos(row) == i);
    1627 SCIPdebugMsg(scip, " Row <%d> is %sin LP: \n", i, SCIProwGetLPPos(row) >= 0 ? "" : "not ");
    1629 activities[i] = SCIPgetRowSolActivity(scip, row, bestsol);
    1630
    1631 /* Heuristic does not provide infeasibility recovery, thus if any constraint is violated,
    1632 * execution has to be terminated.
    1633 */
    1634 if( !SCIProwIsLocal(row) && (SCIPisFeasLT(scip, activities[i], SCIProwGetLhs(row))
    1635 || SCIPisFeasGT(scip, activities[i], SCIProwGetRhs(row))) )
    1636 goto TERMINATE;
    1637 }
    1638
    1639 if( !presolthiscall )
    1640 {
    1641 for( int i = 0; i < ncolsforsorting; ++i )
    1642 SCIPcolSort(cols[i]);
    1643 }
    1644 SCIPdebugMsg(scip, " Twoopt heuristic has initialized activities and sorted rows! \n");
    1645
    1646 /* start with binary optimization */
    1647 improvement = FALSE;
    1648 varboundserr = FALSE;
    1649
    1650 if( heurdata->nbinblocks > 0 )
    1651 {
    1652 SCIP_CALL( optimize(scip, worksol, heurdata->binvars, heurdata->binblockstart, heurdata->binblockend, heurdata->nbinblocks,
    1653 OPTTYPE_BINARY, activities, nlprows, &improvement, &varboundserr, heurdata) );
    1654
    1655 SCIPdebugMsg(scip, " Binary Optimization finished!\n");
    1656 }
    1657
    1658 if( varboundserr )
    1659 goto TERMINATE;
    1660
    1661 /* ensure that their are at least two integer variables which do not have the same coefficient
    1662 * in the objective function. In one of these cases, the heuristic will automatically skip the
    1663 * integer variable optimization */
    1664 if( heurdata->nintblocks > 0 )
    1665 {
    1666 assert(heurdata->intopt);
    1667 SCIP_CALL( optimize(scip, worksol, heurdata->intvars, heurdata->intblockstart, heurdata->intblockend, heurdata->nintblocks,
    1668 OPTTYPE_INTEGER, activities, nlprows, &improvement, &varboundserr, heurdata) );
    1669
    1670 SCIPdebugMsg(scip, " Integer Optimization finished!\n");
    1671 }
    1672
    1673 if( ! improvement || varboundserr )
    1674 goto TERMINATE;
    1675
    1676 if( SCIPgetNVars(scip) == ndiscvars )
    1677 {
    1678 /* the problem is a pure IP, hence, no continuous variables are left for diving.
    1679 * try if new working solution is feasible in original problem */
    1680 SCIP_Bool success;
    1681#ifndef NDEBUG
    1682 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    1683#else
    1684 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, FALSE, FALSE, TRUE, &success) );
    1685#endif
    1686
    1687 if( success )
    1688 {
    1689 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
    1690 SCIPdebug( SCIP_CALL( SCIPprintSol(scip, worksol, NULL, FALSE) ) );
    1691 heurdata->lastsolindex = SCIPsolGetIndex(bestsol);
    1692 *result = SCIP_FOUNDSOL;
    1693
    1694#ifdef SCIP_STATISTIC
    1695 SCIPstatisticMessage("***Twoopt improved solution found by %10s . \n",
    1696 SCIPsolGetHeur(bestsol) != NULL ? SCIPheurGetName(SCIPsolGetHeur(bestsol)) :"Tree");
    1697#endif
    1698 }
    1699 }
    1700 /* fix the integer variables and start diving to optimize continuous variables with respect to reduced domain */
    1701 else
    1702 {
    1703 SCIP_VAR** allvars;
    1704 SCIP_Bool lperror;
    1705#ifdef NDEBUG
    1706 SCIP_RETCODE retstat;
    1707#endif
    1708
    1709 SCIPdebugMsg(scip, "shifted solution should be feasible -> solve LP to fix continuous variables to best values\n");
    1710
    1711 allvars = SCIPgetVars(scip);
    1712
    1713#ifdef SCIP_DEBUG
    1714 for( int i = ndiscvars; i < SCIPgetNVars(scip); ++i )
    1715 {
    1716 SCIPdebugMsg(scip, " Cont. variable <%s>, status %d with bounds [%g <= %g <= x <= %g <= %g]\n",
    1717 SCIPvarGetName(allvars[i]), SCIPvarGetStatus(allvars[i]), SCIPvarGetLbGlobal(allvars[i]), SCIPvarGetLbLocal(allvars[i]), SCIPvarGetUbLocal(allvars[i]),
    1718 SCIPvarGetUbGlobal(allvars[i]));
    1719 }
    1720#endif
    1721
    1722 /* start diving to calculate the LP relaxation */
    1724
    1725 /* set the bounds of the variables: fixed for integers, global bounds for continuous */
    1726 for( int i = 0; i < SCIPgetNVars(scip); ++i )
    1727 {
    1728 if( SCIPvarGetStatus(allvars[i]) == SCIP_VARSTATUS_COLUMN )
    1729 {
    1730 SCIP_CALL( SCIPchgVarLbDive(scip, allvars[i], SCIPvarGetLbGlobal(allvars[i])) );
    1731 SCIP_CALL( SCIPchgVarUbDive(scip, allvars[i], SCIPvarGetUbGlobal(allvars[i])) );
    1732 }
    1733 }
    1734
    1735 /* apply this after global bounds to not cause an error with intermediate empty domains */
    1736 for( int i = 0; i < ndiscvars; ++i )
    1737 {
    1738 if( SCIPvarGetStatus(allvars[i]) == SCIP_VARSTATUS_COLUMN )
    1739 {
    1740 SCIP_Real solval;
    1741
    1742 solval = SCIPgetSolVal(scip, worksol, allvars[i]);
    1743
    1744 assert(SCIPvarIsIntegral(allvars[i]) && SCIPisFeasIntegral(scip, solval));
    1745
    1746 SCIP_CALL( SCIPchgVarLbDive(scip, allvars[i], solval) );
    1747 SCIP_CALL( SCIPchgVarUbDive(scip, allvars[i], solval) );
    1748 }
    1749 }
    1750 for( int i = 0; i < ndiscvars; ++i )
    1751 {
    1752 assert( SCIPisFeasEQ(scip, SCIPgetVarLbDive(scip, allvars[i]), SCIPgetVarUbDive(scip, allvars[i])) );
    1753 }
    1754 /* solve LP */
    1755 SCIPdebugMsg(scip, " -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    1756
    1757 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    1758 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
    1759#ifdef NDEBUG
    1760 retstat = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
    1761 if( retstat != SCIP_OKAY )
    1762 {
    1763 SCIPwarningMessage(scip, "Error while solving LP in Twoopt heuristic; LP solve terminated with code <%d>\n",retstat);
    1764 }
    1765#else
    1766 SCIP_CALL( SCIPsolveDiveLP(scip, -1, &lperror, NULL) );
    1767#endif
    1768
    1769 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    1770 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
    1771
    1772 /* check if this is a feasible solution */
    1773 if( !lperror && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
    1774 {
    1775 SCIP_Bool success;
    1776
    1777 /* copy the current LP solution to the working solution */
    1778 SCIP_CALL( SCIPlinkLPSol(scip, worksol) );
    1779
    1780 /* in exact mode we have to end diving prior to trying the solution */
    1781 if( SCIPisExact(scip) )
    1782 {
    1783 SCIP_CALL( SCIPunlinkSol(scip, worksol) );
    1785 }
    1786
    1787 /* check solution for feasibility */
    1788#ifndef NDEBUG
    1789 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    1790#else
    1791 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, FALSE, FALSE, TRUE, &success) );
    1792#endif
    1793
    1794 if( success )
    1795 {
    1796 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
    1797 SCIPdebug( SCIP_CALL( SCIPprintSol(scip, worksol, NULL, FALSE) ) );
    1798 heurdata->lastsolindex = SCIPsolGetIndex(bestsol);
    1799 *result = SCIP_FOUNDSOL;
    1800
    1801#ifdef SCIP_STATISTIC
    1802 SCIPstatisticMessage("*** Twoopt improved solution found by %10s . \n",
    1803 SCIPsolGetHeur(bestsol) != NULL ? SCIPheurGetName(SCIPsolGetHeur(bestsol)) :"Tree");
    1804#endif
    1805 }
    1806 }
    1807
    1808 /* terminate the diving */
    1809 if( SCIPinDive(scip) )
    1810 {
    1812 }
    1813 }
    1814
    1815 TERMINATE:
    1816 SCIPdebugMsg(scip, "Termination of Twoopt heuristic\n");
    1817 SCIPfreeBufferArray(scip, &activities);
    1818 SCIP_CALL( SCIPfreeSol(scip, &worksol) );
    1819
    1820 return SCIP_OKAY;
    1821}
    1822
    1823/*
    1824 * primal heuristic specific interface methods
    1825 */
    1826
    1827/** creates the twoopt primal heuristic and includes it in SCIP */
    1829 SCIP* scip /**< SCIP data structure */
    1830 )
    1831{
    1832 SCIP_HEURDATA* heurdata;
    1833 SCIP_HEUR* heur;
    1834
    1835 /* create Twoopt primal heuristic data */
    1836 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1837
    1838 /* include primal heuristic */
    1841 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecTwoopt, heurdata) );
    1842
    1843 assert(heur != NULL);
    1844
    1845 /* primal heuristic is safe to use in exact solving mode */
    1846 SCIPheurMarkExact(heur);
    1847
    1848 /* set non-NULL pointers to callback methods */
    1849 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyTwoopt) );
    1850 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeTwoopt) );
    1851 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitTwoopt) );
    1852 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitTwoopt) );
    1853 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolTwoopt) );
    1854 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolTwoopt) );
    1855
    1856 /* include boolean flag intopt */
    1857 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/twoopt/intopt", " Should Integer-2-Optimization be applied or not?",
    1858 &heurdata->intopt, TRUE, DEFAULT_INTOPT, NULL, NULL) );
    1859
    1860 /* include parameter waitingnodes */
    1861 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/twoopt/waitingnodes", "user parameter to determine number of "
    1862 "nodes to wait after last best solution before calling heuristic",
    1863 &heurdata->waitingnodes, TRUE, DEFAULT_WAITINGNODES, 0, 10000, NULL, NULL));
    1864
    1865 /* include parameter maxnslaves */
    1866 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/twoopt/maxnslaves", "maximum number of slaves for one master variable",
    1867 &heurdata->maxnslaves, TRUE, DEFAULT_MAXNSLAVES, -1, 1000000, NULL, NULL) );
    1868
    1869 /* include parameter matchingrate */
    1870 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/twoopt/matchingrate",
    1871 "parameter to determine the percentage of rows two variables have to share before they are considered equal",
    1872 &heurdata->matchingrate, TRUE, DEFAULT_MATCHINGRATE, 0.0, 1.0, NULL, NULL) );
    1873
    1874 return SCIP_OKAY;
    1875}
    static long bound
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    #define NULL
    Definition: def.h:257
    #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 ABS(x)
    Definition: def.h:225
    #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 SCIP_CALL(x)
    Definition: def.h:364
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNBinImplVars(SCIP *scip)
    Definition: scip_prob.c:2432
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNIntImplVars(SCIP *scip)
    Definition: scip_prob.c:2477
    int SCIPgetNContImplVars(SCIP *scip)
    Definition: scip_prob.c:2522
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPincludeHeurTwoopt(SCIP *scip)
    Definition: heur_twoopt.c:1828
    int SCIPcolGetNNonz(SCIP_COL *col)
    Definition: lp.c:17520
    SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
    Definition: lp.c:17555
    SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
    Definition: lp.c:17545
    void SCIPcolSort(SCIP_COL *col)
    Definition: lp.c:3630
    SCIP_Bool SCIPisExact(SCIP *scip)
    Definition: scip_exact.c:193
    SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
    Definition: scip_heur.c:247
    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_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    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_Real SCIPgetVarLbDive(SCIP *scip, SCIP_VAR *var)
    Definition: scip_lp.c:2581
    SCIP_Real SCIPgetVarUbDive(SCIP *scip, SCIP_VAR *var)
    Definition: scip_lp.c:2610
    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 SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
    Definition: scip_lp.c:477
    SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
    Definition: scip_lp.c:576
    int SCIPgetNLPRows(SCIP *scip)
    Definition: scip_lp.c:632
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #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_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    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
    int SCIProwGetIndex(SCIP_ROW *row)
    Definition: lp.c:17755
    SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
    Definition: scip_lp.c:2108
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:882
    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_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
    Definition: sol.c:4254
    SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
    Definition: sol.c:4274
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1504
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4155
    int SCIPsolGetIndex(SCIP_SOL *sol)
    Definition: sol.c:4305
    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_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
    void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
    Definition: sol.c:4319
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23715
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    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
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    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
    void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    void SCIPsortRealPtrPtrInt(SCIP_Real *realarray, void **ptrarray1, void **ptrarray2, int *intarray, int len)
    static SCIP_Real determineBound(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *master, DIRECTION masterdirection, SCIP_VAR *slave, DIRECTION slavedirection, SCIP_Real *activities, int nrows)
    Definition: heur_twoopt.c:406
    static SCIP_DECL_HEURINITSOL(heurInitsolTwoopt)
    Definition: heur_twoopt.c:1426
    Direction
    Definition: heur_twoopt.c:138
    @ DIRECTION_DOWN
    Definition: heur_twoopt.c:140
    @ DIRECTION_UP
    Definition: heur_twoopt.c:139
    @ DIRECTION_NONE
    Definition: heur_twoopt.c:141
    static void disposeVariable(SCIP_VAR **vars, int *blockend, int varindex)
    Definition: heur_twoopt.c:643
    static SCIP_DECL_HEUREXIT(heurExitTwoopt)
    Definition: heur_twoopt.c:1329
    #define HEUR_TIMING
    Definition: heur_twoopt.c:64
    static SCIP_DECL_HEURFREE(heurFreeTwoopt)
    Definition: heur_twoopt.c:888
    #define HEUR_FREQOFS
    Definition: heur_twoopt.c:61
    #define HEUR_DESC
    Definition: heur_twoopt.c:57
    enum Direction DIRECTION
    Definition: heur_twoopt.c:143
    #define DEFAULT_MATCHINGRATE
    Definition: heur_twoopt.c:70
    static SCIP_DECL_HEUREXEC(heurExecTwoopt)
    Definition: heur_twoopt.c:1524
    #define DEFAULT_WAITINGNODES
    Definition: heur_twoopt.c:69
    static SCIP_Bool checkConstraintMatching(SCIP *scip, SCIP_VAR *var1, SCIP_VAR *var2, SCIP_Real matchingrate)
    Definition: heur_twoopt.c:308
    static SCIP_DECL_SORTPTRCOMP(SCIPvarcolComp)
    Definition: heur_twoopt.c:299
    static SCIP_DECL_HEURCOPY(heurCopyTwoopt)
    Definition: heur_twoopt.c:873
    #define HEUR_DISPCHAR
    Definition: heur_twoopt.c:58
    #define HEUR_MAXDEPTH
    Definition: heur_twoopt.c:62
    #define HEUR_PRIORITY
    Definition: heur_twoopt.c:59
    static SCIP_RETCODE innerPresolve(SCIP *scip, SCIP_VAR **vars, int nvars, int *nblocks, int *maxblocksize, int *nblockvars, int **blockstart, int **blockend, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur_twoopt.c:658
    static int varColCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: heur_twoopt.c:257
    #define HEUR_NAME
    Definition: heur_twoopt.c:56
    static SCIP_DECL_HEUREXITSOL(heurExitsolTwoopt)
    Definition: heur_twoopt.c:1460
    #define DEFAULT_ARRAYSIZE
    Definition: heur_twoopt.c:73
    enum Opttype OPTTYPE
    Definition: heur_twoopt.c:134
    #define DEFAULT_RANDSEED
    Definition: heur_twoopt.c:74
    #define DEFAULT_MAXNSLAVES
    Definition: heur_twoopt.c:72
    static SCIP_DECL_HEURINIT(heurInitTwoopt)
    Definition: heur_twoopt.c:909
    static SCIP_RETCODE shiftValues(SCIP *scip, SCIP_VAR *master, SCIP_VAR *slave, SCIP_Real mastersolval, DIRECTION masterdir, SCIP_Real slavesolval, DIRECTION slavedir, SCIP_Real shiftval, SCIP_Real *activities, int nrows, SCIP_Bool *feasible)
    Definition: heur_twoopt.c:154
    #define DEFAULT_INTOPT
    Definition: heur_twoopt.c:68
    #define HEUR_FREQ
    Definition: heur_twoopt.c:60
    static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
    Definition: heur_twoopt.c:970
    #define HEUR_USESSUBSCIP
    Definition: heur_twoopt.c:65
    Opttype
    Definition: heur_twoopt.c:130
    @ OPTTYPE_INTEGER
    Definition: heur_twoopt.c:132
    @ OPTTYPE_BINARY
    Definition: heur_twoopt.c:131
    static SCIP_RETCODE presolveTwoOpt(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur_twoopt.c:754
    Primal heuristic to improve incumbent solution by flipping pairs of variables.
    memory allocation routines
    public methods for primal heuristics
    public methods for LP management
    public methods for message output
    #define SCIPstatisticMessage
    Definition: pub_message.h:123
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for primal CIP solutions
    public methods for problem variables
    public methods for exact solving
    public methods for primal heuristic plugins and divesets
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for random numbers
    public methods for solutions
    public methods for querying solving statistics
    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_VARSTATUS_COLUMN
    Definition: type_var.h:53