Scippy

SCIP

Solving Constraint Integer Programs

heur_shifting.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-2016 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_shifting.c
17  * @brief LP rounding heuristic that tries to recover from intermediate infeasibilities and shifts continuous variables
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 
26 #include "scip/heur_shifting.h"
27 
28 
29 #define HEUR_NAME "shifting"
30 #define HEUR_DESC "LP rounding heuristic with infeasibility recovering also using continuous variables"
31 #define HEUR_DISPCHAR 's'
32 #define HEUR_PRIORITY -5000
33 #define HEUR_FREQ 10
34 #define HEUR_FREQOFS 0
35 #define HEUR_MAXDEPTH -1
36 #define HEUR_TIMING SCIP_HEURTIMING_DURINGLPLOOP
37 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
38 
39 #define MAXSHIFTINGS 50 /**< maximal number of non improving shiftings */
40 #define WEIGHTFACTOR 1.1
41 
42 
43 /* locally defined heuristic data */
44 struct SCIP_HeurData
45 {
46  SCIP_SOL* sol; /**< working solution */
47  SCIP_Longint lastlp; /**< last LP number where the heuristic was applied */
48  unsigned int randseed; /**< seed value for random number generator */
49 };
50 
51 
52 /*
53  * local methods
54  */
55 
56 /** update row violation arrays after a row's activity value changed */
57 static
59  SCIP* scip, /**< SCIP data structure */
60  SCIP_ROW* row, /**< LP row */
61  SCIP_ROW** violrows, /**< array with currently violated rows */
62  int* violrowpos, /**< position of LP rows in violrows array */
63  int* nviolrows, /**< pointer to the number of currently violated rows */
64  int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
65  int* nfracsinrow, /**< array with number of fractional variables for every row */
66  SCIP_Real oldactivity, /**< old activity value of LP row */
67  SCIP_Real newactivity /**< new activity value of LP row */
68  )
69 {
70  SCIP_Real lhs;
71  SCIP_Real rhs;
72  SCIP_Bool oldviol;
73  SCIP_Bool newviol;
74 
75  assert(violrows != NULL);
76  assert(violrowpos != NULL);
77  assert(nviolrows != NULL);
78 
79  lhs = SCIProwGetLhs(row);
80  rhs = SCIProwGetRhs(row);
81  oldviol = (SCIPisFeasLT(scip, oldactivity, lhs) || SCIPisFeasGT(scip, oldactivity, rhs));
82  newviol = (SCIPisFeasLT(scip, newactivity, lhs) || SCIPisFeasGT(scip, newactivity, rhs));
83  if( oldviol != newviol )
84  {
85  int rowpos;
86  int violpos;
87 
88  rowpos = SCIProwGetLPPos(row);
89  assert(rowpos >= 0);
90 
91  if( oldviol )
92  {
93  /* the row violation was repaired: remove row from violrows array, decrease violation count */
94  violpos = violrowpos[rowpos];
95  assert(0 <= violpos && violpos < *nviolrows);
96  assert(violrows[violpos] == row);
97  violrowpos[rowpos] = -1;
98 
99  /* first, move the row to the end of the subset of violated rows with fractional variables */
100  if( nfracsinrow[rowpos] > 0 )
101  {
102  assert(violpos < *nviolfracrows);
103 
104  /* replace with last violated row containing fractional variables */
105  if( violpos != *nviolfracrows - 1 )
106  {
107  violrows[violpos] = violrows[*nviolfracrows - 1];
108  violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
109  violpos = *nviolfracrows - 1;
110  }
111  (*nviolfracrows)--;
112  }
113 
114  assert(violpos >= *nviolfracrows);
115 
116  /* swap row at the end of the violated array to the position of this row and decrease the counter */
117  if( violpos != *nviolrows - 1 )
118  {
119  violrows[violpos] = violrows[*nviolrows - 1];
120  violrowpos[SCIProwGetLPPos(violrows[violpos])] = violpos;
121  }
122  (*nviolrows)--;
123  }
124  else
125  {
126  /* the row is now violated: add row to violrows array, increase violation count */
127  assert(violrowpos[rowpos] == -1);
128  violrows[*nviolrows] = row;
129  violrowpos[rowpos] = *nviolrows;
130  (*nviolrows)++;
131 
132  /* if the row contains fractional variables, swap with the last violated row that has no fractional variables
133  * at position *nviolfracrows
134  */
135  if( nfracsinrow[rowpos] > 0 )
136  {
137  if( *nviolfracrows < *nviolrows - 1 )
138  {
139  assert(nfracsinrow[SCIProwGetLPPos(violrows[*nviolfracrows])] == 0);
140 
141  violrows[*nviolrows - 1] = violrows[*nviolfracrows];
142  violrowpos[SCIProwGetLPPos(violrows[*nviolrows - 1])] = *nviolrows - 1;
143 
144  violrows[*nviolfracrows] = row;
145  violrowpos[rowpos] = *nviolfracrows;
146  }
147  (*nviolfracrows)++;
148  }
149  }
150  }
151 }
152 
153 /** update row activities after a variable's solution value changed */
154 static
156  SCIP* scip, /**< SCIP data structure */
157  SCIP_Real* activities, /**< LP row activities */
158  SCIP_ROW** violrows, /**< array with currently violated rows */
159  int* violrowpos, /**< position of LP rows in violrows array */
160  int* nviolrows, /**< pointer to the number of currently violated rows */
161  int* nviolfracrows, /**< pointer to the number of violated rows with fractional candidates */
162  int* nfracsinrow, /**< array with number of fractional variables for every row */
163  int nlprows, /**< number of rows in current LP */
164  SCIP_VAR* var, /**< variable that has been changed */
165  SCIP_Real oldsolval, /**< old solution value of variable */
166  SCIP_Real newsolval /**< new solution value of variable */
167  )
168 {
169  SCIP_COL* col;
170  SCIP_ROW** colrows;
171  SCIP_Real* colvals;
172  SCIP_Real delta;
173  int ncolrows;
174  int r;
175 
176  assert(activities != NULL);
177  assert(nviolrows != NULL);
178  assert(0 <= *nviolrows && *nviolrows <= nlprows);
179 
180  delta = newsolval - oldsolval;
181  col = SCIPvarGetCol(var);
182  colrows = SCIPcolGetRows(col);
183  colvals = SCIPcolGetVals(col);
184  ncolrows = SCIPcolGetNLPNonz(col);
185  assert(ncolrows == 0 || (colrows != NULL && colvals != NULL));
186 
187  for( r = 0; r < ncolrows; ++r )
188  {
189  SCIP_ROW* row;
190  int rowpos;
191 
192  row = colrows[r];
193  rowpos = SCIProwGetLPPos(row);
194  assert(-1 <= rowpos && rowpos < nlprows);
195 
196  if( rowpos >= 0 && !SCIProwIsLocal(row) )
197  {
198  SCIP_Real oldactivity;
199  SCIP_Real newactivity;
200 
201  assert(SCIProwIsInLP(row));
202 
203  /* update row activity */
204  oldactivity = activities[rowpos];
205  if( !SCIPisInfinity(scip, -oldactivity) && !SCIPisInfinity(scip, oldactivity) )
206  {
207  newactivity = oldactivity + delta * colvals[r];
208  if( SCIPisInfinity(scip, newactivity) )
209  newactivity = SCIPinfinity(scip);
210  else if( SCIPisInfinity(scip, -newactivity) )
211  newactivity = -SCIPinfinity(scip);
212  activities[rowpos] = newactivity;
213 
214  /* update row violation arrays */
215  updateViolations(scip, row, violrows, violrowpos, nviolrows, nviolfracrows, nfracsinrow, oldactivity, newactivity);
216  }
217  }
218  }
219 
220  return SCIP_OKAY;
221 }
222 
223 /** returns a variable, that pushes activity of the row in the given direction with minimal negative impact on other rows;
224  * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
225  * prefer fractional integers over other variables in order to become integral during the process;
226  * shifting in a direction is forbidden, if this forces the objective value over the upper bound, or if the variable
227  * was already shifted in the opposite direction
228  */
229 static
231  SCIP* scip, /**< SCIP data structure */
232  SCIP_SOL* sol, /**< primal solution */
233  SCIP_ROW* row, /**< LP row */
234  SCIP_Real rowactivity, /**< activity of LP row */
235  int direction, /**< should the activity be increased (+1) or decreased (-1)? */
236  SCIP_Real* nincreases, /**< array with weighted number of increasings per variables */
237  SCIP_Real* ndecreases, /**< array with weighted number of decreasings per variables */
238  SCIP_Real increaseweight, /**< current weight of increase/decrease updates */
239  SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
240  SCIP_Real* oldsolval, /**< pointer to store old solution value of shifting variable */
241  SCIP_Real* newsolval /**< pointer to store new (shifted) solution value of shifting variable */
242  )
243 {
244  SCIP_COL** rowcols;
245  SCIP_Real* rowvals;
246  int nrowcols;
247  SCIP_Real activitydelta;
248  SCIP_Real bestshiftscore;
249  SCIP_Real bestdeltaobj;
250  int c;
251 
252  assert(direction == +1 || direction == -1);
253  assert(nincreases != NULL);
254  assert(ndecreases != NULL);
255  assert(shiftvar != NULL);
256  assert(oldsolval != NULL);
257  assert(newsolval != NULL);
258 
259  /* get row entries */
260  rowcols = SCIProwGetCols(row);
261  rowvals = SCIProwGetVals(row);
262  nrowcols = SCIProwGetNLPNonz(row);
263 
264  /* calculate how much the activity must be shifted in order to become feasible */
265  activitydelta = (direction == +1 ? SCIProwGetLhs(row) - rowactivity : SCIProwGetRhs(row) - rowactivity);
266  assert((direction == +1 && SCIPisPositive(scip, activitydelta))
267  || (direction == -1 && SCIPisNegative(scip, activitydelta)));
268 
269  /* select shifting variable */
270  bestshiftscore = SCIP_REAL_MAX;
271  bestdeltaobj = SCIPinfinity(scip);
272  *shiftvar = NULL;
273  *newsolval = 0.0;
274  *oldsolval = 0.0;
275  for( c = 0; c < nrowcols; ++c )
276  {
277  SCIP_COL* col;
278  SCIP_VAR* var;
279  SCIP_Real val;
280  SCIP_Real solval;
281  SCIP_Real shiftval;
282  SCIP_Real shiftscore;
283  SCIP_Bool isinteger;
284  SCIP_Bool isfrac;
285  SCIP_Bool increase;
286 
287  col = rowcols[c];
288  var = SCIPcolGetVar(col);
289  val = rowvals[c];
290  assert(!SCIPisZero(scip, val));
291  solval = SCIPgetSolVal(scip, sol, var);
292 
294  isfrac = (isinteger && !SCIPisFeasIntegral(scip, solval));
295  increase = (direction * val > 0.0);
296 
297  /* calculate the score of the shifting (prefer smaller values) */
298  if( isfrac )
299  shiftscore = increase ? -1.0 / (SCIPvarGetNLocksUp(var) + 1.0) :
300  -1.0 / (SCIPvarGetNLocksDown(var) + 1.0);
301  else
302  {
303  int probindex;
304  probindex = SCIPvarGetProbindex(var);
305 
306  if( increase )
307  shiftscore = ndecreases[probindex]/increaseweight;
308  else
309  shiftscore = nincreases[probindex]/increaseweight;
310  if( isinteger )
311  shiftscore += 1.0;
312  }
313 
314  if( shiftscore <= bestshiftscore )
315  {
316  SCIP_Real deltaobj;
317 
318  if( !increase )
319  {
320  /* shifting down */
321  assert(direction * val < 0.0);
322  if( isfrac )
323  shiftval = SCIPfeasFloor(scip, solval);
324  else
325  {
326  SCIP_Real lb;
327 
328  assert(activitydelta/val < 0.0);
329  shiftval = solval + activitydelta/val;
330  assert(shiftval <= solval); /* may be equal due to numerical digit erasement in the subtraction */
331  if( SCIPvarIsIntegral(var) )
332  shiftval = SCIPfeasFloor(scip, shiftval);
333  lb = SCIPvarGetLbGlobal(var);
334  shiftval = MAX(shiftval, lb);
335  }
336  }
337  else
338  {
339  /* shifting up */
340  assert(direction * val > 0.0);
341  if( isfrac )
342  shiftval = SCIPfeasCeil(scip, solval);
343  else
344  {
345  SCIP_Real ub;
346 
347  assert(activitydelta/val > 0.0);
348  shiftval = solval + activitydelta/val;
349  assert(shiftval >= solval); /* may be equal due to numerical digit erasement in the subtraction */
350  if( SCIPvarIsIntegral(var) )
351  shiftval = SCIPfeasCeil(scip, shiftval);
352  ub = SCIPvarGetUbGlobal(var);
353  shiftval = MIN(shiftval, ub);
354  }
355  }
356 
357  if( (SCIPisInfinity(scip, shiftval) && SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)))
358  || (SCIPisInfinity(scip, -shiftval) && SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)))
359  || SCIPisEQ(scip, shiftval, solval) )
360  continue;
361 
362  deltaobj = SCIPvarGetObj(var) * (shiftval - solval);
363  if( shiftscore < bestshiftscore || deltaobj < bestdeltaobj )
364  {
365  bestshiftscore = shiftscore;
366  bestdeltaobj = deltaobj;
367  *shiftvar = var;
368  *oldsolval = solval;
369  *newsolval = shiftval;
370  }
371  }
372  }
373 
374  return SCIP_OKAY;
375 }
376 
377 /** returns a fractional variable, that has most impact on rows in opposite direction, i.e. that is most crucial to
378  * fix in the other direction;
379  * if variables have equal impact, chooses the one with best objective value improvement in corresponding direction;
380  * shifting in a direction is forbidden, if this forces the objective value over the upper bound
381  */
382 static
384  SCIP* scip, /**< SCIP data structure */
385  SCIP_SOL* sol, /**< primal solution */
386  SCIP_Real minobj, /**< minimal objective value possible after shifting remaining fractional vars */
387  SCIP_VAR** lpcands, /**< fractional variables in LP */
388  int nlpcands, /**< number of fractional variables in LP */
389  SCIP_VAR** shiftvar, /**< pointer to store the shifting variable, returns NULL if impossible */
390  SCIP_Real* oldsolval, /**< old (fractional) solution value of shifting variable */
391  SCIP_Real* newsolval /**< new (shifted) solution value of shifting variable */
392  )
393 {
394  SCIP_VAR* var;
395  SCIP_Real solval;
396  SCIP_Real shiftval;
397  SCIP_Real obj;
398  SCIP_Real deltaobj;
399  SCIP_Real bestdeltaobj;
400  int maxnlocks;
401  int nlocks;
402  int v;
403 
404  assert(shiftvar != NULL);
405  assert(oldsolval != NULL);
406  assert(newsolval != NULL);
407 
408  /* select shifting variable */
409  maxnlocks = -1;
410  bestdeltaobj = SCIPinfinity(scip);
411  *shiftvar = NULL;
412  for( v = 0; v < nlpcands; ++v )
413  {
414  var = lpcands[v];
416 
417  solval = SCIPgetSolVal(scip, sol, var);
418  if( !SCIPisFeasIntegral(scip, solval) )
419  {
420  obj = SCIPvarGetObj(var);
421 
422  /* shifting down */
423  nlocks = SCIPvarGetNLocksUp(var);
424  if( nlocks >= maxnlocks )
425  {
426  shiftval = SCIPfeasFloor(scip, solval);
427  deltaobj = obj * (shiftval - solval);
428  if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj - obj < SCIPgetCutoffbound(scip) )
429  {
430  maxnlocks = nlocks;
431  bestdeltaobj = deltaobj;
432  *shiftvar = var;
433  *oldsolval = solval;
434  *newsolval = shiftval;
435  }
436  }
437 
438  /* shifting up */
439  nlocks = SCIPvarGetNLocksDown(var);
440  if( nlocks >= maxnlocks )
441  {
442  shiftval = SCIPfeasCeil(scip, solval);
443  deltaobj = obj * (shiftval - solval);
444  if( (nlocks > maxnlocks || deltaobj < bestdeltaobj) && minobj + obj < SCIPgetCutoffbound(scip) )
445  {
446  maxnlocks = nlocks;
447  bestdeltaobj = deltaobj;
448  *shiftvar = var;
449  *oldsolval = solval;
450  *newsolval = shiftval;
451  }
452  }
453  }
454  }
455 
456  return SCIP_OKAY;
457 }
458 
459 /** adds a given value to the fractionality counters of the rows in which the given variable appears */
460 static
462  int* nfracsinrow, /**< array to store number of fractional variables per row */
463  SCIP_ROW** violrows, /**< array with currently violated rows */
464  int* violrowpos, /**< position of LP rows in violrows array */
465  int* nviolfracrows, /**< pointer to store the number of violated rows with fractional variables */
466  int nviolrows, /**< the number of currently violated rows (stays unchanged in this method) */
467  int nlprows, /**< number of rows in LP */
468  SCIP_VAR* var, /**< variable for which the counting should be updated */
469  int incval /**< value that should be added to the corresponding array entries */
470  )
471 {
472  SCIP_COL* col;
473  SCIP_ROW** rows;
474  int nrows;
475  int r;
476 
477  assert(incval != 0);
478  assert(nviolrows >= *nviolfracrows);
479  col = SCIPvarGetCol(var);
480  rows = SCIPcolGetRows(col);
481  nrows = SCIPcolGetNLPNonz(col);
482  for( r = 0; r < nrows; ++r )
483  {
484  int rowidx;
485  int theviolrowpos;
486  rowidx = SCIProwGetLPPos(rows[r]);
487  assert(0 <= rowidx && rowidx < nlprows);
488  nfracsinrow[rowidx] += incval;
489  assert(nfracsinrow[rowidx] >= 0);
490  theviolrowpos = violrowpos[rowidx];
491 
492  if( SCIProwIsLocal(rows[r]) )
493  continue;
494 
495  /* swap positions in violrows array if fractionality has changed to 0 */
496  if( theviolrowpos >= 0 )
497  {
498  /* first case: the number of fractional variables has become zero: swap row in violrows array to the
499  * second part, containing only violated rows without fractional variables
500  */
501  if( nfracsinrow[rowidx] == 0 )
502  {
503  assert(theviolrowpos <= *nviolfracrows - 1);
504 
505  /* nothing to do if row is already at the end of the first part, otherwise, swap it to the last position
506  * and decrease the counter */
507  if( theviolrowpos < *nviolfracrows - 1 )
508  {
509  violrows[theviolrowpos] = violrows[*nviolfracrows - 1];
510  violrows[*nviolfracrows - 1] = rows[r];
511 
512 
513  violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
514  violrowpos[rowidx] = *nviolfracrows - 1;
515  }
516  (*nviolfracrows)--;
517  }
518  /* second interesting case: the number of fractional variables was zero before, swap it with the first
519  * violated row without fractional variables
520  */
521  else if( nfracsinrow[rowidx] == incval )
522  {
523  assert(theviolrowpos >= *nviolfracrows);
524 
525  /* nothing to do if the row is exactly located at index *nviolfracrows */
526  if( theviolrowpos > *nviolfracrows )
527  {
528  violrows[theviolrowpos] = violrows[*nviolfracrows];
529  violrows[*nviolfracrows] = rows[r];
530 
531 
532  violrowpos[SCIProwGetLPPos(violrows[theviolrowpos])] = theviolrowpos;
533  violrowpos[rowidx] = *nviolfracrows;
534  }
535  (*nviolfracrows)++;
536  }
537  }
538  }
539 }
540 
541 
542 /*
543  * Callback methods
544  */
545 
546 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
547 static
548 SCIP_DECL_HEURCOPY(heurCopyShifting)
549 { /*lint --e{715}*/
550  assert(scip != NULL);
551  assert(heur != NULL);
552  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
553 
554  /* call inclusion method of primal heuristic */
556 
557  return SCIP_OKAY;
558 }
559 
560 
561 /** initialization method of primal heuristic (called after problem was transformed) */
562 static
563 SCIP_DECL_HEURINIT(heurInitShifting) /*lint --e{715}*/
564 { /*lint --e{715}*/
565  SCIP_HEURDATA* heurdata;
566 
567  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
568  assert(SCIPheurGetData(heur) == NULL);
569 
570  /* create heuristic data */
571  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
572  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
573  heurdata->lastlp = -1;
574  heurdata->randseed = 0;
575  SCIPheurSetData(heur, heurdata);
576 
577  return SCIP_OKAY;
578 }
579 
580 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
581 static
582 SCIP_DECL_HEUREXIT(heurExitShifting) /*lint --e{715}*/
583 { /*lint --e{715}*/
584  SCIP_HEURDATA* heurdata;
585 
586  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
587 
588  /* free heuristic data */
589  heurdata = SCIPheurGetData(heur);
590  assert(heurdata != NULL);
591  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
592  SCIPfreeMemory(scip, &heurdata);
593  SCIPheurSetData(heur, NULL);
594 
595  return SCIP_OKAY;
596 }
597 
598 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
599 static
600 SCIP_DECL_HEURINITSOL(heurInitsolShifting)
601 {
602  SCIP_HEURDATA* heurdata;
603 
604  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
605 
606  heurdata = SCIPheurGetData(heur);
607  assert(heurdata != NULL);
608  heurdata->lastlp = -1;
609 
610  return SCIP_OKAY;
611 }
612 
613 
614 /** execution method of primal heuristic */
615 static
616 SCIP_DECL_HEUREXEC(heurExecShifting) /*lint --e{715}*/
617 { /*lint --e{715}*/
618  SCIP_HEURDATA* heurdata;
619  SCIP_SOL* sol;
620  SCIP_VAR** lpcands;
621  SCIP_Real* lpcandssol;
622  SCIP_ROW** lprows;
623  SCIP_Real* activities;
624  SCIP_ROW** violrows;
625  SCIP_Real* nincreases;
626  SCIP_Real* ndecreases;
627  int* violrowpos;
628  int* nfracsinrow;
629  SCIP_Real increaseweight;
630  SCIP_Real obj;
631  SCIP_Real bestshiftval;
632  SCIP_Real minobj;
633  int nlpcands;
634  int nlprows;
635  int nvars;
636  int nfrac;
637  int nviolrows;
638  int nviolfracrows;
639  int nprevviolrows;
640  int minnviolrows;
641  int nnonimprovingshifts;
642  int c;
643  int r;
644  SCIP_Longint nlps;
645  SCIP_Longint ncalls;
646  SCIP_Longint nsolsfound;
647  SCIP_Longint nnodes;
648 
649  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
650  assert(scip != NULL);
651  assert(result != NULL);
652  assert(SCIPhasCurrentNodeLP(scip));
653 
654  *result = SCIP_DIDNOTRUN;
655 
656  /* only call heuristic, if an optimal LP solution is at hand */
658  return SCIP_OKAY;
659 
660  /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
662  return SCIP_OKAY;
663 
664  /* get heuristic data */
665  heurdata = SCIPheurGetData(heur);
666  assert(heurdata != NULL);
667 
668  /* don't call heuristic, if we have already processed the current LP solution */
669  nlps = SCIPgetNLPs(scip);
670  if( nlps == heurdata->lastlp )
671  return SCIP_OKAY;
672  heurdata->lastlp = nlps;
673 
674  /* don't call heuristic, if it was not successful enough in the past */
675  ncalls = SCIPheurGetNCalls(heur);
676  nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + SCIPheurGetNSolsFound(heur);
677  nnodes = SCIPgetNNodes(scip);
678  if( nnodes % ((ncalls/100)/(nsolsfound+1)+1) != 0 )
679  return SCIP_OKAY;
680 
681  /* get fractional variables, that should be integral */
682  /* todo check if heuristic should include implicit integer variables for its calculations */
683  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL, NULL) );
684  nfrac = nlpcands;
685 
686  /* only call heuristic, if LP solution is fractional */
687  if( nfrac == 0 )
688  return SCIP_OKAY;
689 
690  *result = SCIP_DIDNOTFIND;
691 
692  /* get LP rows */
693  SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
694 
695  SCIPdebugMessage("executing shifting heuristic: %d LP rows, %d fractionals\n", nlprows, nfrac);
696 
697  /* get memory for activities, violated rows, and row violation positions */
698  nvars = SCIPgetNVars(scip);
699  SCIP_CALL( SCIPallocBufferArray(scip, &activities, nlprows) );
700  SCIP_CALL( SCIPallocBufferArray(scip, &violrows, nlprows) );
701  SCIP_CALL( SCIPallocBufferArray(scip, &violrowpos, nlprows) );
702  SCIP_CALL( SCIPallocBufferArray(scip, &nfracsinrow, nlprows) );
703  SCIP_CALL( SCIPallocBufferArray(scip, &nincreases, nvars) );
704  SCIP_CALL( SCIPallocBufferArray(scip, &ndecreases, nvars) );
705  BMSclearMemoryArray(nfracsinrow, nlprows);
706  BMSclearMemoryArray(nincreases, nvars);
707  BMSclearMemoryArray(ndecreases, nvars);
708 
709  /* get the activities for all globally valid rows;
710  * the rows should be feasible, but due to numerical inaccuracies in the LP solver, they can be violated
711  */
712  nviolrows = 0;
713  for( r = 0; r < nlprows; ++r )
714  {
715  SCIP_ROW* row;
716 
717  row = lprows[r];
718  assert(SCIProwGetLPPos(row) == r);
719 
720  if( !SCIProwIsLocal(row) )
721  {
722  activities[r] = SCIPgetRowActivity(scip, row);
723  if( SCIPisFeasLT(scip, activities[r], SCIProwGetLhs(row))
724  || SCIPisFeasGT(scip, activities[r], SCIProwGetRhs(row)) )
725  {
726  violrows[nviolrows] = row;
727  violrowpos[r] = nviolrows;
728  nviolrows++;
729  }
730  else
731  violrowpos[r] = -1;
732  }
733  }
734 
735  nviolfracrows = 0;
736  /* calc the current number of fractional variables in rows */
737  for( c = 0; c < nlpcands; ++c )
738  addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, lpcands[c], +1);
739 
740  /* get the working solution from heuristic's local data */
741  sol = heurdata->sol;
742  assert(sol != NULL);
743 
744  /* copy the current LP solution to the working solution */
745  SCIP_CALL( SCIPlinkLPSol(scip, sol) );
746 
747  /* calculate the minimal objective value possible after rounding fractional variables */
748  minobj = SCIPgetSolTransObj(scip, sol);
749  assert(minobj < SCIPgetCutoffbound(scip));
750  for( c = 0; c < nlpcands; ++c )
751  {
752  obj = SCIPvarGetObj(lpcands[c]);
753  bestshiftval = obj > 0.0 ? SCIPfeasFloor(scip, lpcandssol[c]) : SCIPfeasCeil(scip, lpcandssol[c]);
754  minobj += obj * (bestshiftval - lpcandssol[c]);
755  }
756 
757  /* try to shift remaining variables in order to become/stay feasible */
758  nnonimprovingshifts = 0;
759  minnviolrows = INT_MAX;
760  increaseweight = 1.0;
761  while( (nfrac > 0 || nviolrows > 0) && nnonimprovingshifts < MAXSHIFTINGS )
762  {
763  SCIP_VAR* shiftvar;
764  SCIP_Real oldsolval;
765  SCIP_Real newsolval;
766  SCIP_Bool oldsolvalisfrac;
767  int probindex;
768 
769  SCIPdebugMessage("shifting heuristic: nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g), cutoff=%g\n",
770  nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj),
772 
773  nprevviolrows = nviolrows;
774 
775  /* choose next variable to process:
776  * - if a violated row exists, shift a variable decreasing the violation, that has least impact on other rows
777  * - otherwise, shift a variable, that has strongest devastating impact on rows in opposite direction
778  */
779  shiftvar = NULL;
780  oldsolval = 0.0;
781  newsolval = 0.0;
782  if( nviolrows > 0 && (nfrac == 0 || nnonimprovingshifts < MAXSHIFTINGS-1) )
783  {
784  SCIP_ROW* row;
785  int rowidx;
786  int rowpos;
787  int direction;
788 
789  rowidx = -1;
790 
791  /* violated rows containing fractional variables are preferred; if such a row exists, choose the last one from the list
792  * (at position nviolfracrows - 1) because removing this row will cause one swapping operation less than other rows
793  */
794  if( nfrac > 0 )
795  {
796  if( nviolfracrows == 0 )
797  rowidx = -1;
798  else
799  rowidx = nviolfracrows - 1;
800  }
801 
802  /* there is no violated row containing a fractional variable, select a violated row uniformly at random */
803  if( rowidx == -1 )
804  rowidx = SCIPgetRandomInt(0, nviolrows-1, &heurdata->randseed);
805 
806  assert(0 <= rowidx && rowidx < nviolrows);
807  row = violrows[rowidx];
808  rowpos = SCIProwGetLPPos(row);
809  assert(0 <= rowpos && rowpos < nlprows);
810  assert(violrowpos[rowpos] == rowidx);
811  assert(nfracsinrow[rowpos] == 0 || rowidx == nviolfracrows - 1);
812 
813  SCIPdebugMessage("shifting heuristic: try to fix violated row <%s>: %g <= %g <= %g\n",
814  SCIProwGetName(row), SCIProwGetLhs(row), activities[rowpos], SCIProwGetRhs(row));
816 
817  /* get direction in which activity must be shifted */
818  assert(SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row))
819  || SCIPisFeasGT(scip, activities[rowpos], SCIProwGetRhs(row)));
820  direction = SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row)) ? +1 : -1;
821 
822  /* search a variable that can shift the activity in the necessary direction */
823  SCIP_CALL( selectShifting(scip, sol, row, activities[rowpos], direction,
824  nincreases, ndecreases, increaseweight, &shiftvar, &oldsolval, &newsolval) );
825  }
826 
827  if( shiftvar == NULL && nfrac > 0 )
828  {
829  SCIPdebugMessage("shifting heuristic: search rounding variable and try to stay feasible\n");
830  SCIP_CALL( selectEssentialRounding(scip, sol, minobj, lpcands, nlpcands, &shiftvar, &oldsolval, &newsolval) );
831  }
832 
833  /* check, whether shifting was possible */
834  if( shiftvar == NULL || SCIPisEQ(scip, oldsolval, newsolval) )
835  {
836  SCIPdebugMessage("shifting heuristic: -> didn't find a shifting variable\n");
837  break;
838  }
839 
840  SCIPdebugMessage("shifting heuristic: -> shift var <%s>[%g,%g], type=%d, oldval=%g, newval=%g, obj=%g\n",
841  SCIPvarGetName(shiftvar), SCIPvarGetLbGlobal(shiftvar), SCIPvarGetUbGlobal(shiftvar), SCIPvarGetType(shiftvar),
842  oldsolval, newsolval, SCIPvarGetObj(shiftvar));
843 
844  /* update row activities of globally valid rows */
845  SCIP_CALL( updateActivities(scip, activities, violrows, violrowpos, &nviolrows, &nviolfracrows, nfracsinrow, nlprows,
846  shiftvar, oldsolval, newsolval) );
847  if( nviolrows >= nprevviolrows )
848  nnonimprovingshifts++;
849  else if( nviolrows < minnviolrows )
850  {
851  minnviolrows = nviolrows;
852  nnonimprovingshifts = 0;
853  }
854 
855  /* store new solution value and decrease fractionality counter */
856  SCIP_CALL( SCIPsetSolVal(scip, sol, shiftvar, newsolval) );
857 
858  /* update fractionality counter and minimal objective value possible after shifting remaining variables */
859  oldsolvalisfrac = !SCIPisFeasIntegral(scip, oldsolval)
860  && (SCIPvarGetType(shiftvar) == SCIP_VARTYPE_BINARY || SCIPvarGetType(shiftvar) == SCIP_VARTYPE_INTEGER);
861  obj = SCIPvarGetObj(shiftvar);
862  if( (SCIPvarGetType(shiftvar) == SCIP_VARTYPE_BINARY || SCIPvarGetType(shiftvar) == SCIP_VARTYPE_INTEGER)
863  && oldsolvalisfrac )
864  {
865  assert(SCIPisFeasIntegral(scip, newsolval));
866  nfrac--;
867  nnonimprovingshifts = 0;
868  minnviolrows = INT_MAX;
869  addFracCounter(nfracsinrow, violrows, violrowpos, &nviolfracrows, nviolrows, nlprows, shiftvar, -1);
870 
871  /* the rounding was already calculated into the minobj -> update only if rounding in "wrong" direction */
872  if( obj > 0.0 && newsolval > oldsolval )
873  minobj += obj;
874  else if( obj < 0.0 && newsolval < oldsolval )
875  minobj -= obj;
876  }
877  else
878  {
879  /* update minimal possible objective value */
880  minobj += obj * (newsolval - oldsolval);
881  }
882 
883  /* update increase/decrease arrays */
884  if( !oldsolvalisfrac )
885  {
886  probindex = SCIPvarGetProbindex(shiftvar);
887  assert(0 <= probindex && probindex < nvars);
888  increaseweight *= WEIGHTFACTOR;
889  if( newsolval < oldsolval )
890  ndecreases[probindex] += increaseweight;
891  else
892  nincreases[probindex] += increaseweight;
893  if( increaseweight >= 1e+09 )
894  {
895  int i;
896 
897  for( i = 0; i < nvars; ++i )
898  {
899  nincreases[i] /= increaseweight;
900  ndecreases[i] /= increaseweight;
901  }
902  increaseweight = 1.0;
903  }
904  }
905 
906  SCIPdebugMessage("shifting heuristic: -> nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
907  nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj));
908  }
909 
910  /* check, if the new solution is feasible */
911  if( nfrac == 0 && nviolrows == 0 )
912  {
913  SCIP_Bool stored;
914 
915  /* check solution for feasibility, and add it to solution store if possible
916  * neither integrality nor feasibility of LP rows has to be checked, because this is already
917  * done in the shifting heuristic itself; however, we better check feasibility of LP rows,
918  * because of numerical problems with activity updating
919  */
920  SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, TRUE, &stored) );
921 
922  if( stored )
923  {
924  SCIPdebugMessage("found feasible shifted solution:\n");
926  *result = SCIP_FOUNDSOL;
927  }
928  }
929 
930  /* free memory buffers */
931  SCIPfreeBufferArray(scip, &ndecreases);
932  SCIPfreeBufferArray(scip, &nincreases);
933  SCIPfreeBufferArray(scip, &nfracsinrow);
934  SCIPfreeBufferArray(scip, &violrowpos);
935  SCIPfreeBufferArray(scip, &violrows);
936  SCIPfreeBufferArray(scip, &activities);
937 
938  return SCIP_OKAY;
939 }
940 
941 
942 /*
943  * heuristic specific interface methods
944  */
945 
946 /** creates the shifting heuristic with infeasibility recovering and includes it in SCIP */
948  SCIP* scip /**< SCIP data structure */
949  )
950 {
951  SCIP_HEUR* heur;
952 
953  /* include primal heuristic */
954  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
956  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecShifting, NULL) );
957 
958  assert(heur != NULL);
959 
960  /* set non-NULL pointers to callback methods */
961  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyShifting) );
962  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitShifting) );
963  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitShifting) );
964  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolShifting) );
965 
966  return SCIP_OKAY;
967 }
968 
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip.c:7361
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
static SCIP_DECL_HEUREXEC(heurExecShifting)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:33125
static void addFracCounter(int *nfracsinrow, SCIP_ROW **violrows, int *violrowpos, int *nviolfracrows, int nviolrows, int nlprows, SCIP_VAR *var, int incval)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
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_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1273
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7297
LP rounding heuristic that tries to recover from intermediate infeasibilities and shifts continuous v...
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1283
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41920
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:42032
#define HEUR_FREQ
Definition: heur_shifting.c:33
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18861
#define HEUR_FREQOFS
Definition: heur_shifting.c:34
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:34843
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, unsigned int timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:7252
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:18850
static SCIP_DECL_HEURINITSOL(heurInitsolShifting)
#define FALSE
Definition: def.h:56
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35113
static void updateViolations(SCIP *scip, SCIP_ROW *row, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, SCIP_Real oldactivity, SCIP_Real newactivity)
Definition: heur_shifting.c:58
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIP_CALL(x)
Definition: def.h:266
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
#define HEUR_DISPCHAR
Definition: heur_shifting.c:31
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:26482
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:42044
SCIP_RETCODE SCIPincludeHeurShifting(SCIP *scip)
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35066
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16634
#define HEUR_USESSUBSCIP
Definition: heur_shifting.c:37
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:18784
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
#define HEUR_PRIORITY
Definition: heur_shifting.c:32
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
static SCIP_RETCODE updateActivities(SCIP *scip, SCIP_Real *activities, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, int nlprows, SCIP_VAR *var, SCIP_Real oldsolval, SCIP_Real newsolval)
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:34002
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19126
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:19024
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition: scip.c:26750
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
#define WEIGHTFACTOR
Definition: heur_shifting.c:40
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:26354
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:18773
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:37435
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18974
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41946
#define HEUR_MAXDEPTH
Definition: heur_shifting.c:35
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
#define SCIP_Bool
Definition: def.h:53
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip.c:35198
static SCIP_DECL_HEURINIT(heurInitShifting)
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34648
#define HEUR_NAME
Definition: heur_shifting.c:29
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:7345
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
int SCIPgetRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:7700
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:7329
#define SCIP_REAL_MAX
Definition: def.h:128
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1293
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
static SCIP_DECL_HEURCOPY(heurCopyShifting)
#define MAXSHIFTINGS
Definition: heur_shifting.c:39
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_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18871
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
#define SCIP_Real
Definition: def.h:127
#define MIN(x, y)
Definition: memory.c:67
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:28334
#define SCIP_Longint
Definition: def.h:112
#define HEUR_DESC
Definition: heur_shifting.c:30
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:19104
SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28245
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1058
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:18794
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3149
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:36217
static SCIP_DECL_HEUREXIT(heurExitShifting)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:37372
#define HEUR_TIMING
Definition: heur_shifting.c:36
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:35397
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:34607