Scippy

SCIP

Solving Constraint Integer Programs

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