Scippy

    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-2025 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#include <string.h>
    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 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 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    878
    879 /* call inclusion method of primal heuristic */
    881
    882 return SCIP_OKAY;
    883}
    884
    885/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    886static
    887SCIP_DECL_HEURFREE(heurFreeTwoopt)
    888{ /*lint --e{715}*/
    889 SCIP_HEURDATA* heurdata;
    890
    891 assert(heur != NULL);
    892 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    893 assert(scip != NULL);
    894
    895 /* free heuristic data */
    896 heurdata = SCIPheurGetData(heur);
    897 assert(heurdata != NULL);
    898
    899 SCIPfreeBlockMemory(scip, &heurdata);
    900 SCIPheurSetData(heur, NULL);
    901
    902 return SCIP_OKAY;
    903}
    904
    905/** initialization method of primal heuristic (called after problem was transformed) */
    906static
    907SCIP_DECL_HEURINIT(heurInitTwoopt)
    908{
    909 SCIP_HEURDATA* heurdata;
    910 assert(heur != NULL);
    911 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    912 assert(scip != NULL);
    913
    914 heurdata = SCIPheurGetData(heur);
    915 assert(heurdata != NULL);
    916
    917 /* heuristic has not run yet, all heuristic specific data is set to initial values */
    918 heurdata->nbinvars = 0;
    919 heurdata->nintvars = 0;
    920 heurdata->lastsolindex = -1;
    921 heurdata->presolved = FALSE;
    922 heurdata->nbinblocks = 0;
    923 heurdata->nintblocks = 0;
    924
    925 /* create random number generator */
    926 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    928
    929#ifdef SCIP_STATISTIC
    930 /* initialize statistics */
    931 heurdata->binnexchanges = 0;
    932 heurdata->intnexchanges = 0;
    933 heurdata->binnblockvars = 0;
    934 heurdata->intnblockvars = 0;
    935 heurdata->binnblocks = 0;
    936 heurdata->intnblocks = 0;
    937
    938 heurdata->maxbinblocksize = 0;
    939 heurdata->maxintblocksize = 0;
    940
    941 heurdata->ntotalbinvars = 0;
    942 heurdata->ntotalintvars = 0;
    943 heurdata->nruns = 0;
    944#endif
    945
    946 /* all pointers are initially set to NULL. Since presolving
    947 * of the heuristic requires a lot of calculation time on some instances,
    948 * but might not be needed e.g. if problem is infeasible, presolving is applied
    949 * when heuristic is executed for the first time
    950 */
    951 heurdata->binvars = NULL;
    952 heurdata->intvars = NULL;
    953 heurdata->binblockstart = NULL;
    954 heurdata->binblockend = NULL;
    955 heurdata->intblockstart = NULL;
    956 heurdata->intblockend = NULL;
    957
    958 SCIPheurSetData(heur, heurdata);
    959
    960 return SCIP_OKAY;
    961}
    962
    963/* Realizes the 2-optimization algorithm, which tries to improve incumbent solution
    964 * by shifting pairs of variables which share a common row set.
    965 */
    966static
    968 SCIP* scip, /**< current SCIP instance */
    969 SCIP_SOL* worksol, /**< working solution */
    970 SCIP_VAR** vars, /**< binary or integer variables */
    971 int* blockstart, /**< contains start indices of blocks */
    972 int* blockend, /**< contains end indices of blocks */
    973 int nblocks, /**< the number of blocks */
    974 OPTTYPE opttype, /**< are binaries or integers optimized */
    975 SCIP_Real* activities, /**< the LP-row activities */
    976 int nrows, /**< the number of LP rows */
    977 SCIP_Bool* improvement, /**< was there a successful shift? */
    978 SCIP_Bool* varboundserr, /**< has the current incumbent already been cut off */
    979 SCIP_HEURDATA* heurdata /**< the heuristic data */
    980 )
    981{ /*lint --e{715}*/
    982 SCIP_Real* objchanges;
    983 SCIP_VAR** bestmasters;
    984 SCIP_VAR** bestslaves;
    985 int* bestdirections;
    986 int arraysize;
    987 int npairs = 0;
    988
    989 assert(scip != NULL);
    990 assert(nblocks > 0);
    991 assert(blockstart != NULL && blockend != NULL);
    992 assert(varboundserr != NULL);
    993 assert(activities != NULL);
    994 assert(worksol != NULL);
    995 assert(improvement != NULL);
    996
    997 *varboundserr = FALSE;
    998
    1003 arraysize = DEFAULT_ARRAYSIZE;
    1004
    1005 /* iterate over blocks */
    1006 for( int b = 0; b < nblocks; ++b )
    1007 {
    1008 int blocklen;
    1009
    1010 blocklen = blockend[b] - blockstart[b] + 1;
    1011
    1012 /* iterate over variables in current block */
    1013 for( int m = 0; m < blocklen; ++m )
    1014 {
    1015 /* determine the new master variable for heuristic's optimization method */
    1016 SCIP_VAR* master;
    1017 SCIP_Real masterobj;
    1018 SCIP_Real mastersolval;
    1019 SCIP_Real bestimprovement;
    1020 SCIP_Real bestbound;
    1021 int bestslavepos;
    1022 int firstslave;
    1023 int nslaves;
    1024 int bestdirection;
    1025 DIRECTION bestmasterdir;
    1026 DIRECTION bestslavedir;
    1027
    1028 master = vars[blockstart[b] + m]; /*lint !e679*/
    1029 masterobj = SCIPvarGetObj(master);
    1030 mastersolval = SCIPgetSolVal(scip, worksol, master);
    1031
    1032 /* due to cuts or fixings of solution values, worksol might not be feasible w.r.t. its bounds.
    1033 * Exit method in that case. */
    1034 if( SCIPisFeasGT(scip, mastersolval, SCIPvarGetUbGlobal(master)) || SCIPisFeasLT(scip, mastersolval, SCIPvarGetLbGlobal(master)) )
    1035 {
    1036 *varboundserr = TRUE;
    1037 SCIPdebugMsg(scip, "Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
    1038 SCIPvarGetName(master), SCIPvarGetLbGlobal(master), mastersolval, SCIPvarGetUbGlobal(master));
    1039 goto TERMINATE;
    1040 }
    1041
    1042 /* if variable has fixed solution value, it is deleted from heuristic array */
    1044 {
    1045 disposeVariable(vars, &(blockend[b]), blockstart[b] + m);
    1046 --blocklen;
    1047 continue;
    1048 }
    1049 else if( SCIPvarGetStatus(master) != SCIP_VARSTATUS_COLUMN )
    1050 continue;
    1051
    1052 assert(SCIPisFeasIntegral(scip, mastersolval));
    1053
    1054 assert(opttype == OPTTYPE_INTEGER || (SCIPisFeasLE(scip, mastersolval, 1.0) || SCIPisFeasGE(scip, mastersolval, 0.0)));
    1055
    1056 /* initialize the data of the best available shift */
    1057 bestimprovement = 0.0;
    1058 bestslavepos = -1;
    1059 bestbound = 0.0;
    1060 bestmasterdir = DIRECTION_NONE;
    1061 bestslavedir = DIRECTION_NONE;
    1062 bestdirection = -1;
    1063
    1064 /* in blocks with more than heurdata->maxnslaves variables, a slave candidate region is chosen */
    1065 if( heurdata->maxnslaves >= 0 && blocklen > heurdata->maxnslaves )
    1066 firstslave = SCIPrandomGetInt(heurdata->randnumgen, blockstart[b] + m, blockend[b]);
    1067 else
    1068 firstslave = blockstart[b] + m + 1;
    1069
    1070 nslaves = MIN((heurdata->maxnslaves == -1 ? INT_MAX : heurdata->maxnslaves), blocklen);
    1071
    1072 /* Loop over block and determine a slave shift candidate for master variable.
    1073 * If more than one candidate is available, choose the shift which improves objective function
    1074 * the most. */
    1075 for( int s = 0; s < nslaves; ++s )
    1076 {
    1077 SCIP_VAR* slave;
    1078 SCIP_Real slaveobj;
    1079 SCIP_Real slavesolval;
    1080 SCIP_Real changedobj;
    1081 SCIP_Real diffdirbound;
    1082 SCIP_Real equaldirbound;
    1083 int directions;
    1084 int slaveindex;
    1085
    1086 slaveindex = (firstslave + s - blockstart[b]) % blocklen;
    1087 slaveindex += blockstart[b];
    1088
    1089 /* in case of a small block, we do not want to try possible pairings twice */
    1090 if( (blocklen <= heurdata->maxnslaves || heurdata->maxnslaves == -1) && slaveindex < blockstart[b] + m )
    1091 break;
    1092 /* master and slave should not be the same variable */
    1093 if( slaveindex == blockstart[b] + m )
    1094 continue;
    1095
    1096 /* get the next slave variable */
    1097 slave = vars[slaveindex];
    1098 slaveobj = SCIPvarGetObj(slave);
    1099 slavesolval = SCIPgetSolVal(scip, worksol, slave);
    1100 changedobj = 0.0;
    1101
    1102 assert(SCIPvarGetType(master) == SCIPvarGetType(slave));
    1103 assert(SCIPisFeasIntegral(scip, slavesolval));
    1104 assert(opttype == OPTTYPE_INTEGER || (SCIPisFeasLE(scip, mastersolval, 1.0) || SCIPisFeasGE(scip, mastersolval, 0.0)));
    1105
    1106 /* solution is not feasible w.r.t. the variable bounds, stop optimization in this case */
    1107 if( SCIPisFeasGT(scip, slavesolval, SCIPvarGetUbGlobal(slave)) || SCIPisFeasLT(scip, slavesolval, SCIPvarGetLbGlobal(slave)) )
    1108 {
    1109 *varboundserr = TRUE;
    1110 SCIPdebugMsg(scip, "Solution has violated variable bounds for var %s: %g <= %g <= %g \n",
    1111 SCIPvarGetName(slave), SCIPvarGetLbGlobal(slave), slavesolval, SCIPvarGetUbGlobal(slave));
    1112 goto TERMINATE;
    1113 }
    1114
    1115 /* if solution value of the variable is fixed, delete it from the remaining candidates in the block */
    1117 {
    1118 disposeVariable(vars, &(blockend[b]), slaveindex);
    1119 --blocklen;
    1120 continue;
    1121 }
    1122 else if( SCIPvarGetStatus(master) != SCIP_VARSTATUS_COLUMN )
    1123 continue;
    1124
    1125 /* determine the shifting direction to improve the objective function */
    1126 /* The heuristic chooses the shifting direction and the corresponding maximum nonnegative
    1127 * integer shift value for the two variables which preserves feasibility and improves
    1128 * the objective function value. */
    1129 directions = -1;
    1130 diffdirbound = 0.0;
    1131 equaldirbound = 0.0;
    1132
    1133 if( SCIPisPositive(scip, slaveobj - masterobj) )
    1134 {
    1135 diffdirbound = determineBound(scip, worksol, master, DIRECTION_UP, slave, DIRECTION_DOWN, activities, nrows);
    1136 directions = 2;
    1137 /* the improvement of objective function is calculated */
    1138 changedobj = (masterobj - slaveobj) * diffdirbound;
    1139 }
    1140 else if( SCIPisPositive(scip, masterobj - slaveobj) )
    1141 {
    1142 diffdirbound = determineBound(scip, worksol, master, DIRECTION_DOWN, slave, DIRECTION_UP, activities, nrows);
    1143 directions = 1;
    1144 changedobj = (slaveobj - masterobj) * diffdirbound;
    1145 }
    1146
    1147 if( SCIPisPositive(scip, -(masterobj + slaveobj)) )
    1148 {
    1149 equaldirbound = determineBound(scip, worksol, master, DIRECTION_UP, slave, DIRECTION_UP, activities, nrows);
    1150 if( (masterobj + slaveobj) * equaldirbound < changedobj )
    1151 {
    1152 changedobj = (masterobj + slaveobj) * equaldirbound;
    1153 directions = 3;
    1154 }
    1155 }
    1156 else if( SCIPisPositive(scip, masterobj + slaveobj) )
    1157 {
    1158 equaldirbound = determineBound(scip, worksol, master, DIRECTION_DOWN, slave, DIRECTION_DOWN, activities, nrows);
    1159 if( -(masterobj + slaveobj) * equaldirbound < changedobj )
    1160 {
    1161 changedobj = -(masterobj + slaveobj) * equaldirbound;
    1162 directions = 0;
    1163 }
    1164 }
    1165 assert(SCIPisFeasIntegral(scip, equaldirbound));
    1166 assert(SCIPisFeasIntegral(scip, diffdirbound));
    1167 assert(SCIPisFeasGE(scip, equaldirbound, 0.0));
    1168 assert(SCIPisFeasGE(scip, diffdirbound, 0.0));
    1169
    1170 /* choose the candidate which improves the objective function the most */
    1171 if( (SCIPisFeasGT(scip, equaldirbound, 0.0) || SCIPisFeasGT(scip, diffdirbound, 0.0))
    1172 && changedobj < bestimprovement )
    1173 {
    1174 bestimprovement = changedobj;
    1175 bestslavepos = slaveindex;
    1176 bestdirection = directions;
    1177
    1178 /* the most promising shift, i.e., the one which can improve the objective
    1179 * the most, is recorded by the integer 'directions'. It is recovered via the use
    1180 * of a binary representation of the four different combinations for the shifting directions
    1181 * of two variables */
    1182 if( directions / 2 == 1 )
    1183 bestmasterdir = DIRECTION_UP;
    1184 else
    1185 bestmasterdir = DIRECTION_DOWN;
    1186
    1187 if( directions % 2 == 1 )
    1188 bestslavedir = DIRECTION_UP;
    1189 else
    1190 bestslavedir = DIRECTION_DOWN;
    1191
    1192 if( bestmasterdir == bestslavedir )
    1193 bestbound = equaldirbound;
    1194 else
    1195 bestbound = diffdirbound;
    1196 }
    1197 }
    1198
    1199 /* choose the most promising candidate, if one exists */
    1200 if( bestslavepos >= 0 )
    1201 {
    1202 if( npairs == arraysize )
    1203 {
    1204 SCIP_CALL( SCIPreallocBufferArray(scip, &bestmasters, 2 * arraysize) );
    1205 SCIP_CALL( SCIPreallocBufferArray(scip, &bestslaves, 2 * arraysize) );
    1206 SCIP_CALL( SCIPreallocBufferArray(scip, &objchanges, 2 * arraysize) );
    1207 SCIP_CALL( SCIPreallocBufferArray(scip, &bestdirections, 2 * arraysize) );
    1208 arraysize = 2 * arraysize;
    1209 }
    1210 assert( npairs < arraysize );
    1211
    1212 bestmasters[npairs] = master;
    1213 bestslaves[npairs] = vars[bestslavepos];
    1214 objchanges[npairs] = ((int)bestslavedir * SCIPvarGetObj(bestslaves[npairs]) + (int)bestmasterdir * masterobj) * bestbound;
    1215 bestdirections[npairs] = bestdirection;
    1216
    1217 assert(objchanges[npairs] < 0);
    1218
    1219 SCIPdebugMsg(scip, " Saved candidate pair {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g} %d\n",
    1220 SCIPvarGetName(master), mastersolval, SCIPvarGetName(bestslaves[npairs]), SCIPgetSolVal(scip, worksol, bestslaves[npairs]) ,
    1221 masterobj, SCIPvarGetObj(bestslaves[npairs]), mastersolval + (int)bestmasterdir * bestbound, SCIPgetSolVal(scip, worksol, bestslaves[npairs])
    1222 + (int)bestslavedir * bestbound, bestdirections[npairs]);
    1223
    1224 ++npairs;
    1225 }
    1226 }
    1227 }
    1228
    1229 if( npairs == 0 )
    1230 goto TERMINATE;
    1231
    1232 SCIPsortRealPtrPtrInt(objchanges, (void**)bestmasters, (void**)bestslaves, bestdirections, npairs);
    1233
    1234 for( int b = 0; b < npairs; ++b )
    1235 {
    1236 SCIP_VAR* master;
    1237 SCIP_VAR* slave;
    1238 SCIP_Real mastersolval;
    1239 SCIP_Real slavesolval;
    1240 SCIP_Real masterobj;
    1241 SCIP_Real slaveobj;
    1243 DIRECTION masterdir;
    1244 DIRECTION slavedir;
    1245
    1246 master = bestmasters[b];
    1247 slave = bestslaves[b];
    1248 mastersolval = SCIPgetSolVal(scip, worksol, master);
    1249 slavesolval = SCIPgetSolVal(scip, worksol, slave);
    1250 masterobj =SCIPvarGetObj(master);
    1251 slaveobj = SCIPvarGetObj(slave);
    1252
    1253 assert(0 <= bestdirections[b] && bestdirections[b] < 4);
    1254
    1255 if( bestdirections[b] / 2 == 1 )
    1256 masterdir = DIRECTION_UP;
    1257 else
    1258 masterdir = DIRECTION_DOWN;
    1259
    1260 if( bestdirections[b] % 2 == 1 )
    1261 slavedir = DIRECTION_UP;
    1262 else
    1263 slavedir = DIRECTION_DOWN;
    1264
    1265 bound = determineBound(scip, worksol, master, masterdir, slave, slavedir, activities, nrows);
    1266
    1267 if( !SCIPisZero(scip, bound) )
    1268 {
    1269 SCIP_Bool feasible;
    1270#ifndef NDEBUG
    1271 SCIP_Real changedobj;
    1272#endif
    1273
    1274 SCIPdebugMsg(scip, " Promising candidates {%s=%g, %s=%g} with objectives <%g>, <%g> to be set to {%g, %g}\n",
    1275 SCIPvarGetName(master), mastersolval, SCIPvarGetName(slave), slavesolval,
    1276 masterobj, slaveobj, mastersolval + (int)masterdir * bound, slavesolval + (int)slavedir * bound);
    1277
    1278#ifndef NDEBUG
    1279 /* the improvement of objective function is calculated */
    1280 changedobj = ((int)slavedir * slaveobj + (int)masterdir * masterobj) * bound;
    1281 assert( SCIPisPositive(scip, -changedobj) );
    1282#endif
    1283
    1285 /* try to change the solution values of the variables */
    1286 feasible = FALSE;
    1287 SCIP_CALL( shiftValues(scip, master, slave, mastersolval, masterdir, slavesolval, slavedir, bound,
    1288 activities, nrows, &feasible) );
    1289
    1290 if( feasible )
    1291 {
    1292 /* The variables' solution values were successfully shifted and can hence be updated. */
    1293 assert(SCIPisFeasIntegral(scip, mastersolval + ((int)masterdir * bound)));
    1294 assert(SCIPisFeasIntegral(scip, slavesolval + ((int)slavedir * bound)));
    1295
    1296 SCIP_CALL( SCIPsetSolVal(scip, worksol, master, mastersolval + (int)masterdir * bound) );
    1297 SCIP_CALL( SCIPsetSolVal(scip, worksol, slave, slavesolval + (int)slavedir * bound) );
    1298 SCIPdebugMsg(scip, " Feasible shift: <%s>[%g, %g] (obj: %f) <%f> --> <%f>\n",
    1299 SCIPvarGetName(master), SCIPvarGetLbGlobal(master), SCIPvarGetUbGlobal(master), masterobj, mastersolval, SCIPgetSolVal(scip, worksol, master));
    1300 SCIPdebugMsg(scip, " <%s>[%g, %g] (obj: %f) <%f> --> <%f>\n",
    1301 SCIPvarGetName(slave), SCIPvarGetLbGlobal(slave), SCIPvarGetUbGlobal(slave), slaveobj, slavesolval, SCIPgetSolVal(scip, worksol, slave));
    1302
    1303#ifdef SCIP_STATISTIC
    1304 /* update statistics */
    1305 if( opttype == OPTTYPE_BINARY )
    1306 ++(heurdata->binnexchanges);
    1307 else
    1308 ++(heurdata->intnexchanges);
    1309#endif
    1310
    1311 *improvement = TRUE;
    1312 }
    1313 }
    1314 }
    1315 TERMINATE:
    1316 SCIPfreeBufferArray(scip, &bestdirections);
    1317 SCIPfreeBufferArray(scip, &objchanges);
    1318 SCIPfreeBufferArray(scip, &bestslaves);
    1319 SCIPfreeBufferArray(scip, &bestmasters);
    1320
    1321 return SCIP_OKAY;
    1322}
    1323
    1324/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    1325static
    1326SCIP_DECL_HEUREXIT(heurExitTwoopt)
    1327{
    1328 SCIP_HEURDATA* heurdata;
    1329
    1330 heurdata = SCIPheurGetData(heur);
    1331 assert(heurdata != NULL);
    1332
    1333 /*ensure that initialization was successful */
    1334 assert(heurdata->nbinvars <= 1 || heurdata->binvars != NULL);
    1335
    1336#ifdef SCIP_STATISTIC
    1337 /* print relevant statistics to console */
    1339 " Twoopt Binary Statistics : "
    1340 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg. block size, max block size) \n",
    1341 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->binnblocks/(heurdata->nruns),
    1342 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->binnblockvars/(heurdata->nruns),
    1343 heurdata->ntotalbinvars == 0 ? 0.0 : (SCIP_Real)heurdata->binnblockvars/(heurdata->ntotalbinvars) * 100.0,
    1344 heurdata->binnblocks == 0 ? 0.0 : heurdata->binnblockvars/(SCIP_Real)(heurdata->binnblocks),
    1345 heurdata->maxbinblocksize);
    1346
    1348 " Twoopt Integer statistics : "
    1349 "%6.2g %6.2g %4.2g %4.0g %6d (blocks/run, variables/run, varpercentage, avg block size, max block size) \n",
    1350 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->intnblocks/(heurdata->nruns),
    1351 heurdata->nruns == 0 ? 0.0 : (SCIP_Real)heurdata->intnblockvars/(heurdata->nruns),
    1352 heurdata->ntotalintvars == 0 ? 0.0 : (SCIP_Real)heurdata->intnblockvars/(heurdata->ntotalintvars) * 100.0,
    1353 heurdata->intnblocks == 0 ? 0.0 : heurdata->intnblockvars/(SCIP_Real)(heurdata->intnblocks),
    1354 heurdata->maxintblocksize);
    1355
    1357 " Twoopt results : "
    1358 "%6d %6d %4d %4.2g (runs, binary exchanges, Integer shiftings, matching rate)\n",
    1359 heurdata->nruns,
    1360 heurdata->binnexchanges,
    1361 heurdata->intnexchanges,
    1362 heurdata->matchingrate);
    1363
    1364 /* set statistics to initial values*/
    1365 heurdata->binnblockvars = 0;
    1366 heurdata->binnblocks = 0;
    1367 heurdata->intnblocks = 0;
    1368 heurdata->intnblockvars = 0;
    1369 heurdata->binnexchanges = 0;
    1370 heurdata->intnexchanges = 0;
    1371#endif
    1372
    1373 /* free the allocated memory for the binary variables */
    1374 if( heurdata->binvars != NULL )
    1375 {
    1376 SCIPfreeBlockMemoryArray(scip, &heurdata->binvars, heurdata->nbinvars);
    1377 }
    1378
    1379 if( heurdata->nbinblocks > 0 )
    1380 {
    1381 assert(heurdata->binblockstart != NULL);
    1382 assert(heurdata->binblockend != NULL);
    1383
    1384 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockstart, heurdata->nbinblocks);
    1385 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockend, heurdata->nbinblocks);
    1386 }
    1387 heurdata->nbinvars = 0;
    1388 heurdata->nbinblocks = 0;
    1389
    1390 if( heurdata->nintblocks > 0 )
    1391 {
    1392 assert(heurdata->intblockstart != NULL);
    1393 assert(heurdata->intblockend != NULL);
    1394
    1395 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockstart, heurdata->nintblocks);
    1396 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockend, heurdata->nintblocks);
    1397 }
    1398
    1399 /* free the allocated memory for the integers */
    1400 if( heurdata->intvars != NULL )
    1401 {
    1402 SCIPfreeBlockMemoryArray(scip, &heurdata->intvars, heurdata->nintvars);
    1403 }
    1404
    1405 heurdata->nbinblocks = 0;
    1406 heurdata->nintblocks = 0;
    1407 heurdata->nbinvars = 0;
    1408 heurdata->nintvars = 0;
    1409
    1410 assert(heurdata->binvars == NULL);
    1411 assert(heurdata->intvars == NULL);
    1412
    1413 /* free random number generator */
    1414 SCIPfreeRandom(scip, &heurdata->randnumgen);
    1415
    1416 SCIPheurSetData(heur, heurdata);
    1417
    1418 return SCIP_OKAY;
    1419}
    1420
    1421/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    1422static
    1423SCIP_DECL_HEURINITSOL(heurInitsolTwoopt)
    1424{
    1425 SCIP_HEURDATA* heurdata;
    1426 assert(heur != NULL);
    1427 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1428 assert(scip != NULL);
    1429
    1430 /* get heuristic data */
    1431 heurdata = SCIPheurGetData(heur);
    1432
    1433 assert(heurdata != NULL);
    1434 assert(heurdata->binvars == NULL && heurdata->intvars == NULL);
    1435 assert(heurdata->binblockstart == NULL && heurdata->binblockend == NULL);
    1436 assert(heurdata->intblockstart == NULL && heurdata->intblockend == NULL);
    1437
    1438 /* set heuristic data to initial values, but increase the total number of runs */
    1439 heurdata->nbinvars = 0;
    1440 heurdata->nintvars = 0;
    1441 heurdata->lastsolindex = -1;
    1442 heurdata->presolved = FALSE;
    1443
    1444#ifdef SCIP_STATISTIC
    1445 ++(heurdata->nruns);
    1446#endif
    1447
    1448 SCIPheurSetData(heur, heurdata);
    1449
    1450 return SCIP_OKAY;
    1451}
    1452
    1453
    1454/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
    1455static
    1456SCIP_DECL_HEUREXITSOL(heurExitsolTwoopt)
    1457{
    1458 SCIP_HEURDATA* heurdata;
    1459 int nbinvars;
    1460 int nintvars;
    1461
    1462 assert(heur != NULL);
    1463 assert(scip != NULL);
    1464 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1465 assert(scip != NULL);
    1466
    1467 /* get heuristic data */
    1468 heurdata = SCIPheurGetData(heur);
    1469
    1470 assert(heurdata != NULL);
    1471
    1472 nbinvars = heurdata->nbinvars;
    1473 nintvars = heurdata->nintvars;
    1474
    1475 /* free the allocated memory for the binary variables */
    1476 if( heurdata->binvars != NULL )
    1477 {
    1478 SCIPfreeBlockMemoryArray(scip, &heurdata->binvars, nbinvars);
    1479 }
    1480 if( heurdata->binblockstart != NULL )
    1481 {
    1482 assert(heurdata->binblockend != NULL);
    1483
    1484 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockstart, heurdata->nbinblocks);
    1485 SCIPfreeBlockMemoryArray(scip, &heurdata->binblockend, heurdata->nbinblocks);
    1486 }
    1487 heurdata->nbinvars = 0;
    1488 heurdata->nbinblocks = 0;
    1489
    1490 if( heurdata->intblockstart != NULL )
    1491 {
    1492 assert(heurdata->intblockend != NULL);
    1493
    1494 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockstart, heurdata->nintblocks);
    1495 SCIPfreeBlockMemoryArray(scip, &heurdata->intblockend, heurdata->nintblocks);
    1496 }
    1497 heurdata->nintblocks = 0;
    1498
    1499 /* free the allocated memory for the integers */
    1500 if( heurdata->intvars != NULL )
    1501 {
    1502 SCIPfreeBlockMemoryArray(scip, &heurdata->intvars, nintvars);
    1503 }
    1504
    1505 heurdata->nintvars = 0;
    1506
    1507 assert(heurdata->binvars == NULL && heurdata->intvars == NULL);
    1508 assert(heurdata->binblockstart == NULL && heurdata->binblockend == NULL);
    1509 assert(heurdata->intblockstart == NULL && heurdata->intblockend == NULL);
    1510
    1511 /* set heuristic data */
    1512 SCIPheurSetData(heur, heurdata);
    1513
    1514 return SCIP_OKAY;
    1515}
    1516
    1517/** execution method of primal heuristic */
    1518static
    1519SCIP_DECL_HEUREXEC(heurExecTwoopt)
    1520{ /*lint --e{715}*/
    1521 SCIP_HEURDATA* heurdata;
    1522 SCIP_ROW** lprows;
    1523 SCIP_COL** cols;
    1524 SCIP_SOL* bestsol;
    1525 SCIP_SOL* worksol;
    1526 SCIP_Real* activities;
    1527 SCIP_Bool improvement;
    1528 SCIP_Bool presolthiscall;
    1529 SCIP_Bool varboundserr;
    1530 int ncols;
    1531 int ndiscvars;
    1532 int nlprows;
    1533 int ncolsforsorting;
    1534
    1535 assert(heur != NULL);
    1536 assert(scip != NULL);
    1537 assert(result != NULL);
    1538
    1539 /* get heuristic data */
    1540 heurdata = SCIPheurGetData(heur);
    1541 assert(heurdata != NULL);
    1542
    1543 *result = SCIP_DIDNOTRUN;
    1544
    1545 /* we need an LP */
    1546 if( SCIPgetNLPRows(scip) == 0 )
    1547 return SCIP_OKAY;
    1548
    1549 bestsol = SCIPgetBestSol(scip);
    1550
    1551 /* ensure that heuristic has not already been processed on current incumbent */
    1552 if( bestsol == NULL || heurdata->lastsolindex == SCIPsolGetIndex(bestsol) )
    1553 return SCIP_OKAY;
    1554
    1555 heurdata->lastsolindex = SCIPsolGetIndex(bestsol);
    1556
    1557 /* we can only work on solutions valid in the transformed space */
    1558 if( SCIPsolIsOriginal(bestsol) )
    1559 return SCIP_OKAY;
    1560
    1561#ifdef SCIP_DEBUG
    1562 SCIP_CALL( SCIPprintSol(scip, bestsol, NULL, TRUE) );
    1563#endif
    1564
    1565 /* ensure that the user defined number of nodes after last best solution has been reached, return otherwise */
    1566 if( (SCIPgetNNodes(scip) - SCIPsolGetNodenum(bestsol)) < heurdata->waitingnodes )
    1567 return SCIP_OKAY;
    1568
    1570 assert(ndiscvars >= 0);
    1571
    1572 /* we need to be able to start diving from current node in order to resolve the LP
    1573 * with continuous variables
    1574 */
    1576 return SCIP_OKAY;
    1577
    1578 /* ensure that heuristic specific presolve is applied when heuristic is executed first */
    1579 presolthiscall = FALSE;
    1580 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    1581 ncolsforsorting = MIN(ncols, ndiscvars);
    1582 if( !heurdata->presolved )
    1583 {
    1584 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    1585
    1586 for( int i = 0; i < ncolsforsorting; ++i )
    1587 SCIPcolSort(cols[i]);
    1588
    1589 SCIP_CALL( presolveTwoOpt(scip, heur, heurdata) );
    1590 presolthiscall = TRUE;
    1591 }
    1592 assert(heurdata->presolved);
    1593 assert(heurdata->nbinvars + heurdata->nintvars <= ndiscvars);
    1594
    1595 SCIPdebugMsg(scip, " Twoopt heuristic is %sexecuting.\n", heurdata->execute ? "" : "not ");
    1596
    1597 /* ensure that presolve has detected structures in the problem to which the 2-optimization can be applied.
    1598 * That is if variables exist which share a common set of LP-rows. */
    1599 if( !heurdata->execute )
    1600 return SCIP_OKAY;
    1601 assert(heurdata->nbinvars + heurdata->nintvars > 1);
    1602
    1603 /* problem satisfies all necessary conditions for 2-optimization heuristic, execute heuristic! */
    1604 *result = SCIP_DIDNOTFIND;
    1605
    1606 /* initialize a working solution as a copy of the current incumbent to be able to store
    1607 * possible improvements obtained by 2-optimization */
    1608 SCIP_CALL( SCIPcreateSolCopy(scip, &worksol, bestsol) );
    1609 SCIPsolSetHeur(worksol, heur);
    1610
    1611 /* get the LP row activities from current incumbent bestsol */
    1612 SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
    1613 SCIP_CALL( SCIPallocBufferArray(scip, &activities, nlprows) );
    1614
    1615 for( int i = 0; i < nlprows; ++i )
    1616 {
    1617 SCIP_ROW* row;
    1618
    1619 row = lprows[i];
    1620 assert(row != NULL);
    1621 assert(SCIProwGetLPPos(row) == i);
    1622 SCIPdebugMsg(scip, " Row <%d> is %sin LP: \n", i, SCIProwGetLPPos(row) >= 0 ? "" : "not ");
    1624 activities[i] = SCIPgetRowSolActivity(scip, row, bestsol);
    1625
    1626 /* Heuristic does not provide infeasibility recovery, thus if any constraint is violated,
    1627 * execution has to be terminated.
    1628 */
    1629 if( !SCIProwIsLocal(row) && (SCIPisFeasLT(scip, activities[i], SCIProwGetLhs(row))
    1630 || SCIPisFeasGT(scip, activities[i], SCIProwGetRhs(row))) )
    1631 goto TERMINATE;
    1632 }
    1633
    1634 if( !presolthiscall )
    1635 {
    1636 for( int i = 0; i < ncolsforsorting; ++i )
    1637 SCIPcolSort(cols[i]);
    1638 }
    1639 SCIPdebugMsg(scip, " Twoopt heuristic has initialized activities and sorted rows! \n");
    1640
    1641 /* start with binary optimization */
    1642 improvement = FALSE;
    1643 varboundserr = FALSE;
    1644
    1645 if( heurdata->nbinblocks > 0 )
    1646 {
    1647 SCIP_CALL( optimize(scip, worksol, heurdata->binvars, heurdata->binblockstart, heurdata->binblockend, heurdata->nbinblocks,
    1648 OPTTYPE_BINARY, activities, nlprows, &improvement, &varboundserr, heurdata) );
    1649
    1650 SCIPdebugMsg(scip, " Binary Optimization finished!\n");
    1651 }
    1652
    1653 if( varboundserr )
    1654 goto TERMINATE;
    1655
    1656 /* ensure that their are at least two integer variables which do not have the same coefficient
    1657 * in the objective function. In one of these cases, the heuristic will automatically skip the
    1658 * integer variable optimization */
    1659 if( heurdata->nintblocks > 0 )
    1660 {
    1661 assert(heurdata->intopt);
    1662 SCIP_CALL( optimize(scip, worksol, heurdata->intvars, heurdata->intblockstart, heurdata->intblockend, heurdata->nintblocks,
    1663 OPTTYPE_INTEGER, activities, nlprows, &improvement, &varboundserr, heurdata) );
    1664
    1665 SCIPdebugMsg(scip, " Integer Optimization finished!\n");
    1666 }
    1667
    1668 if( ! improvement || varboundserr )
    1669 goto TERMINATE;
    1670
    1671 if( SCIPgetNVars(scip) == ndiscvars )
    1672 {
    1673 /* the problem is a pure IP, hence, no continuous variables are left for diving.
    1674 * try if new working solution is feasible in original problem */
    1675 SCIP_Bool success;
    1676#ifndef NDEBUG
    1677 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    1678#else
    1679 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, FALSE, FALSE, TRUE, &success) );
    1680#endif
    1681
    1682 if( success )
    1683 {
    1684 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
    1685 SCIPdebug( SCIP_CALL( SCIPprintSol(scip, worksol, NULL, FALSE) ) );
    1686 heurdata->lastsolindex = SCIPsolGetIndex(bestsol);
    1687 *result = SCIP_FOUNDSOL;
    1688
    1689#ifdef SCIP_STATISTIC
    1690 SCIPstatisticMessage("***Twoopt improved solution found by %10s . \n",
    1691 SCIPsolGetHeur(bestsol) != NULL ? SCIPheurGetName(SCIPsolGetHeur(bestsol)) :"Tree");
    1692#endif
    1693 }
    1694 }
    1695 /* fix the integer variables and start diving to optimize continuous variables with respect to reduced domain */
    1696 else
    1697 {
    1698 SCIP_VAR** allvars;
    1699 SCIP_Bool lperror;
    1700#ifdef NDEBUG
    1701 SCIP_RETCODE retstat;
    1702#endif
    1703
    1704 SCIPdebugMsg(scip, "shifted solution should be feasible -> solve LP to fix continuous variables to best values\n");
    1705
    1706 allvars = SCIPgetVars(scip);
    1707
    1708#ifdef SCIP_DEBUG
    1709 for( int i = ndiscvars; i < SCIPgetNVars(scip); ++i )
    1710 {
    1711 SCIPdebugMsg(scip, " Cont. variable <%s>, status %d with bounds [%g <= %g <= x <= %g <= %g]\n",
    1712 SCIPvarGetName(allvars[i]), SCIPvarGetStatus(allvars[i]), SCIPvarGetLbGlobal(allvars[i]), SCIPvarGetLbLocal(allvars[i]), SCIPvarGetUbLocal(allvars[i]),
    1713 SCIPvarGetUbGlobal(allvars[i]));
    1714 }
    1715#endif
    1716
    1717 /* start diving to calculate the LP relaxation */
    1719
    1720 /* set the bounds of the variables: fixed for integers, global bounds for continuous */
    1721 for( int i = 0; i < SCIPgetNVars(scip); ++i )
    1722 {
    1723 if( SCIPvarGetStatus(allvars[i]) == SCIP_VARSTATUS_COLUMN )
    1724 {
    1725 SCIP_CALL( SCIPchgVarLbDive(scip, allvars[i], SCIPvarGetLbGlobal(allvars[i])) );
    1726 SCIP_CALL( SCIPchgVarUbDive(scip, allvars[i], SCIPvarGetUbGlobal(allvars[i])) );
    1727 }
    1728 }
    1729
    1730 /* apply this after global bounds to not cause an error with intermediate empty domains */
    1731 for( int i = 0; i < ndiscvars; ++i )
    1732 {
    1733 if( SCIPvarGetStatus(allvars[i]) == SCIP_VARSTATUS_COLUMN )
    1734 {
    1735 SCIP_Real solval;
    1736
    1737 solval = SCIPgetSolVal(scip, worksol, allvars[i]);
    1738
    1739 assert(SCIPvarIsIntegral(allvars[i]) && SCIPisFeasIntegral(scip, solval));
    1740
    1741 SCIP_CALL( SCIPchgVarLbDive(scip, allvars[i], solval) );
    1742 SCIP_CALL( SCIPchgVarUbDive(scip, allvars[i], solval) );
    1743 }
    1744 }
    1745 for( int i = 0; i < ndiscvars; ++i )
    1746 {
    1747 assert( SCIPisFeasEQ(scip, SCIPgetVarLbDive(scip, allvars[i]), SCIPgetVarUbDive(scip, allvars[i])) );
    1748 }
    1749 /* solve LP */
    1750 SCIPdebugMsg(scip, " -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    1751
    1752 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    1753 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
    1754#ifdef NDEBUG
    1755 retstat = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
    1756 if( retstat != SCIP_OKAY )
    1757 {
    1758 SCIPwarningMessage(scip, "Error while solving LP in Twoopt heuristic; LP solve terminated with code <%d>\n",retstat);
    1759 }
    1760#else
    1761 SCIP_CALL( SCIPsolveDiveLP(scip, -1, &lperror, NULL) );
    1762#endif
    1763
    1764 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    1765 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
    1766
    1767 /* check if this is a feasible solution */
    1768 if( !lperror && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
    1769 {
    1770 SCIP_Bool success;
    1771
    1772 /* copy the current LP solution to the working solution */
    1773 SCIP_CALL( SCIPlinkLPSol(scip, worksol) );
    1774
    1775 /* in exact mode we have to end diving prior to trying the solution */
    1776 if( SCIPisExact(scip) )
    1777 {
    1778 SCIP_CALL( SCIPunlinkSol(scip, worksol) );
    1780 }
    1781
    1782 /* check solution for feasibility */
    1783#ifndef NDEBUG
    1784 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    1785#else
    1786 SCIP_CALL( SCIPtrySol(scip, worksol, FALSE, FALSE, FALSE, FALSE, TRUE, &success) );
    1787#endif
    1788
    1789 if( success )
    1790 {
    1791 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
    1792 SCIPdebug( SCIP_CALL( SCIPprintSol(scip, worksol, NULL, FALSE) ) );
    1793 heurdata->lastsolindex = SCIPsolGetIndex(bestsol);
    1794 *result = SCIP_FOUNDSOL;
    1795
    1796#ifdef SCIP_STATISTIC
    1797 SCIPstatisticMessage("*** Twoopt improved solution found by %10s . \n",
    1798 SCIPsolGetHeur(bestsol) != NULL ? SCIPheurGetName(SCIPsolGetHeur(bestsol)) :"Tree");
    1799#endif
    1800 }
    1801 }
    1802
    1803 /* terminate the diving */
    1804 if( SCIPinDive(scip) )
    1805 {
    1807 }
    1808 }
    1809
    1810 TERMINATE:
    1811 SCIPdebugMsg(scip, "Termination of Twoopt heuristic\n");
    1812 SCIPfreeBufferArray(scip, &activities);
    1813 SCIP_CALL( SCIPfreeSol(scip, &worksol) );
    1814
    1815 return SCIP_OKAY;
    1816}
    1817
    1818/*
    1819 * primal heuristic specific interface methods
    1820 */
    1821
    1822/** creates the twoopt primal heuristic and includes it in SCIP */
    1824 SCIP* scip /**< SCIP data structure */
    1825 )
    1826{
    1827 SCIP_HEURDATA* heurdata;
    1828 SCIP_HEUR* heur;
    1829
    1830 /* create Twoopt primal heuristic data */
    1831 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1832
    1833 /* include primal heuristic */
    1836 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecTwoopt, heurdata) );
    1837
    1838 assert(heur != NULL);
    1839
    1840 /* primal heuristic is safe to use in exact solving mode */
    1841 SCIPheurMarkExact(heur);
    1842
    1843 /* set non-NULL pointers to callback methods */
    1844 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyTwoopt) );
    1845 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeTwoopt) );
    1846 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitTwoopt) );
    1847 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitTwoopt) );
    1848 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolTwoopt) );
    1849 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolTwoopt) );
    1850
    1851 /* include boolean flag intopt */
    1852 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/twoopt/intopt", " Should Integer-2-Optimization be applied or not?",
    1853 &heurdata->intopt, TRUE, DEFAULT_INTOPT, NULL, NULL) );
    1854
    1855 /* include parameter waitingnodes */
    1856 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/twoopt/waitingnodes", "user parameter to determine number of "
    1857 "nodes to wait after last best solution before calling heuristic",
    1858 &heurdata->waitingnodes, TRUE, DEFAULT_WAITINGNODES, 0, 10000, NULL, NULL));
    1859
    1860 /* include parameter maxnslaves */
    1861 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/twoopt/maxnslaves", "maximum number of slaves for one master variable",
    1862 &heurdata->maxnslaves, TRUE, DEFAULT_MAXNSLAVES, -1, 1000000, NULL, NULL) );
    1863
    1864 /* include parameter matchingrate */
    1865 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/twoopt/matchingrate",
    1866 "parameter to determine the percentage of rows two variables have to share before they are considered equal",
    1867 &heurdata->matchingrate, TRUE, DEFAULT_MATCHINGRATE, 0.0, 1.0, NULL, NULL) );
    1868
    1869 return SCIP_OKAY;
    1870}
    static long bound
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    #define NULL
    Definition: def.h:248
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIP_CALL(x)
    Definition: def.h:355
    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:1823
    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:2981
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:884
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2349
    SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
    Definition: sol.c:4239
    SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
    Definition: sol.c:4259
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1506
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4140
    int SCIPsolGetIndex(SCIP_SOL *sol)
    Definition: sol.c:4290
    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:4012
    SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1295
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
    Definition: sol.c:4304
    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:23683
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    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:1423
    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:1326
    #define HEUR_TIMING
    Definition: heur_twoopt.c:64
    static SCIP_DECL_HEURFREE(heurFreeTwoopt)
    Definition: heur_twoopt.c:887
    #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:1519
    #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:1456
    #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:907
    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:967
    #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
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53