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