Scippy

SCIP

Solving Constraint Integer Programs

heur_shiftandpropagate.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-2015 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_shiftandpropagate.c
17  * @brief shiftandpropagate primal heuristic
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 <assert.h>
25 #include <string.h>
26 #include "scip/pub_misc.h"
28 
29 #define HEUR_NAME "shiftandpropagate"
30 #define HEUR_DESC "Pre-root heuristic to expand an auxiliary branch-and-bound tree and apply propagation techniques"
31 #define HEUR_DISPCHAR 'T'
32 #define HEUR_PRIORITY 1000
33 #define HEUR_FREQ 0
34 #define HEUR_FREQOFS 0
35 #define HEUR_MAXDEPTH -1
36 #define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
37 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
38 
39 #define DEFAULT_WEIGHT_INEQUALITY 1 /**< the heuristic row weight for inequalities */
40 #define DEFAULT_WEIGHT_EQUALITY 3 /**< the heuristic row weight for equations */
41 #define DEFAULT_RELAX TRUE /**< Should continuous variables be relaxed from the problem? */
42 #define DEFAULT_PROBING TRUE /**< Is propagation of solution values enabled? */
43 #define DEFAULT_ONLYWITHOUTSOL TRUE /**< Should heuristic only be executed if no primal solution was found, yet? */
44 #define DEFAULT_NPROPROUNDS 10 /**< The default number of propagation rounds for each propagation used */
45 #define DEFAULT_PROPBREAKER 65000 /**< fixed maximum number of propagations */
46 #define DEFAULT_CUTOFFBREAKER 15 /**< fixed maximum number of allowed cutoffs before the heuristic stops */
47 #define DEFAULT_RANDSEED 3141598 /**< the default random seed for random number generation */
48 #define DEFAULT_SORTKEY 'v' /**< the default key for variable sorting */
49 #define DEFAULT_SORTVARS TRUE /**< should variables be processed in sorted order? */
50 #define DEFAULT_COLLECTSTATS TRUE /**< should variable statistics be collected during probing? */
51 #define DEFAULT_STOPAFTERFEASIBLE TRUE /**< Should the heuristic stop calculating optimal shift values when no more rows are violated? */
52 #define DEFAULT_PREFERBINARIES TRUE /**< Should binary variables be shifted first? */
53 #define DEFAULT_SELECTBEST FALSE /**< should the heuristic choose the best candidate in every round? (set to FALSE for static order)? */
54 #define DEFAULT_MAXCUTOFFQUOT 0.0 /**< maximum percentage of allowed cutoffs before stopping the heuristic */
55 #define SORTKEYS "nrtuv"/**< options sorting key: (n)orms down, norms (u)p, (v)iolated rows decreasing,
56  * viola(t)ed rows increasing, or (r)andom */
57 #define DEFAULT_NOZEROFIXING FALSE /**< should variables with a zero shifting value be delayed instead of being fixed? */
58 #define DEFAULT_FIXBINLOCKS TRUE /**< should binary variables with no locks in one direction be fixed to that direction? */
59 #define DEFAULT_BINLOCKSFIRST FALSE /**< should binary variables with no locks be preferred in the ordering? */
60 #define DEFAULT_NORMALIZE TRUE /**< should coefficients and left/right hand sides be normalized by max row coeff? */
61 #define DEFAULT_UPDATEWEIGHTS FALSE /**< should row weight be increased every time the row is violated? */
62 #define DEFAULT_IMPLISCONTINUOUS TRUE /**< should implicit integer variables be treated as continuous variables? */
63 
64 #define EVENTHDLR_NAME "eventhdlrshiftandpropagate"
65 #define EVENTHDLR_DESC "event handler to catch bound changes"
66 
67 /*
68  * Data structures
69  */
70 
71 /** primal heuristic data */
72 struct SCIP_HeurData
73 {
74  SCIP_COL** lpcols; /**< stores lp columns with discrete variables before cont. variables */
75  int* rowweights; /**< row weight storage */
76  SCIP_Bool relax; /**< should continuous variables be relaxed from the problem */
77  SCIP_Bool probing; /**< should probing be executed? */
78  SCIP_Bool onlywithoutsol; /**< Should heuristic only be executed if no primal solution was found, yet? */
79  int nlpcols; /**< the number of lp columns */
80  int nproprounds; /**< The default number of propagation rounds for each propagation used */
81  int cutoffbreaker; /**< the number of cutoffs before heuristic execution is stopped, or -1 for no
82  * limit */
83  SCIP_EVENTHDLR* eventhdlr; /**< event handler to register and process variable bound changes */
84 
85  SCIP_Real maxcutoffquot; /**< maximum percentage of allowed cutoffs before stopping the heuristic */
86  unsigned int randseed; /**< seed for random number generation */
87  char sortkey; /**< the key by which variables are sorted */
88  SCIP_Bool sortvars; /**< should variables be processed in sorted order? */
89  SCIP_Bool collectstats; /**< should variable statistics be collected during probing? */
90  SCIP_Bool stopafterfeasible; /**< Should the heuristic stop calculating optimal shift values when no
91  * more rows are violated? */
92  SCIP_Bool preferbinaries; /**< Should binary variables be shifted first? */
93  SCIP_Bool nozerofixing; /**< should variables with a zero shifting value be delayed instead of being fixed? */
94  SCIP_Bool fixbinlocks; /**< should binary variables with no locks in one direction be fixed to that direction? */
95  SCIP_Bool binlocksfirst; /**< should binary variables with no locks be preferred in the ordering? */
96  SCIP_Bool normalize; /**< should coefficients and left/right hand sides be normalized by max row coeff? */
97  SCIP_Bool updateweights; /**< should row weight be increased every time the row is violated? */
98  SCIP_Bool impliscontinuous; /**< should implicit integer variables be treated as continuous variables? */
99  SCIP_Bool selectbest; /**< should the heuristic choose the best candidate in every round? (set to FALSE for static order)? */
101  SCIP_LPSOLSTAT lpsolstat; /**< the probing status after probing */
102  SCIP_Longint ntotaldomredsfound; /**< the total number of domain reductions during heuristic */
103  SCIP_Longint nlpiters; /**< number of LP iterations which the heuristic needed */
104  int nremainingviols; /**< the number of remaining violations */
105  int nprobings; /**< how many probings has the heuristic executed? */
106  int ncutoffs; /**< has the probing node been cutoff? */
107  )
108 };
109 
110 /** status of a variable in heuristic transformation */
111 enum TransformStatus
112 {
113  TRANSFORMSTATUS_NONE = 0, /**< variable has not been transformed yet */
114  TRANSFORMSTATUS_LB = 1, /**< variable has been shifted by using lower bound (x-lb) */
115  TRANSFORMSTATUS_NEG = 2, /**< variable has been negated by using upper bound (ub-x) */
116  TRANSFORMSTATUS_FREE = 3 /**< variable does not have to be shifted */
117 };
118 typedef enum TransformStatus TRANSFORMSTATUS;
120 /** information about the matrix after its heuristic transformation */
121 struct ConstraintMatrix
122 {
123  SCIP_Real* rowmatvals; /**< matrix coefficients row by row */
124  int* rowmatind; /**< the indices of the corresponding variables */
125  int* rowmatbegin; /**< the starting indices of each row */
126  SCIP_Real* colmatvals; /**< matrix coefficients column by column */
127  int* colmatind; /**< the indices of the corresponding rows for each coefficient */
128  int* colmatbegin; /**< the starting indices of each column */
129  int* violrows; /**< the number of violated rows for every variable */
130  TRANSFORMSTATUS* transformstatus; /**< information about transform status of every discrete variable */
131  SCIP_Real* lhs; /**< left hand side vector after normalization */
132  SCIP_Real* rhs; /**< right hand side vector after normalization */
133  SCIP_Real* colnorms; /**< vector norms of all discrete problem variables after normalization */
134  SCIP_Real* upperbounds; /**< the upper bounds of every non-continuous variable after transformation*/
135  SCIP_Real* transformshiftvals; /**< values by which original discrete variable bounds were shifted */
136  int nnonzs; /**< number of nonzero column entries */
137  int nrows; /**< number of rows of matrix */
138  int ncols; /**< the number of columns in matrix (including continuous vars) */
139  int ndiscvars; /**< number of discrete problem variables */
140  SCIP_Bool normalized; /**< indicates if the matrix data has already been normalized */
141 };
142 typedef struct ConstraintMatrix CONSTRAINTMATRIX;
144 struct SCIP_EventhdlrData
145 {
146  CONSTRAINTMATRIX* matrix; /**< the constraint matrix of the heuristic */
147  SCIP_HEURDATA* heurdata; /**< heuristic data */
148  int* violatedrows; /**< all currently violated LP rows */
149  int* violatedrowpos; /**< position in violatedrows array for every row */
150  int* nviolatedrows; /**< pointer to the total number of currently violated rows */
151 };
152 
153 struct SCIP_EventData
154 {
155  int colpos; /**< column position of the event-related variable */
156 };
157 /*
158  * Local methods
159  */
160 
161 /** returns whether a given variable is counted as discrete, depending on the parameter impliscontinuous */
162 static
164  SCIP_VAR* var, /**< variable to check for discreteness */
165  SCIP_Bool impliscontinuous /**< should implicit integer variables be counted as continuous? */
166  )
167 {
168  return SCIPvarIsIntegral(var) && (SCIPvarGetType(var) != SCIP_VARTYPE_IMPLINT || !impliscontinuous);
169 }
170 
171 /** returns whether a given column is counted as discrete, depending on the parameter impliscontinuous */
172 static
174  SCIP_COL* col, /**< column to check for discreteness */
175  SCIP_Bool impliscontinuous /**< should implicit integer variables be counted as continuous? */
176  )
177 {
178  return SCIPcolIsIntegral(col) && (!impliscontinuous || SCIPvarGetType(SCIPcolGetVar(col)) != SCIP_VARTYPE_IMPLINT);
179 }
180 
181 /** returns nonzero values and corresponding columns of given row */
182 static
183 void getRowData(
184  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
185  int rowindex, /**< index of the desired row */
186  SCIP_Real** valpointer, /**< pointer to store the nonzero coefficients of the row */
187  SCIP_Real* lhs, /**< lhs of the row */
188  SCIP_Real* rhs, /**< rhs of the row */
189  int** indexpointer, /**< pointer to store column indices which belong to the nonzeros */
190  int* nrowvals /**< pointer to store number of nonzeros in the desired row (or NULL) */
191  )
192 {
193  int arrayposition;
194 
195  assert(matrix != NULL);
196  assert(0 <= rowindex && rowindex < matrix->nrows);
197 
198  arrayposition = matrix->rowmatbegin[rowindex];
199 
200  if ( nrowvals != NULL )
201  {
202  if( rowindex == matrix->nrows - 1 )
203  *nrowvals = matrix->nnonzs - arrayposition;
204  else
205  *nrowvals = matrix->rowmatbegin[rowindex + 1] - arrayposition; /*lint !e679*/
206  }
207 
208  if( valpointer != NULL )
209  *valpointer = &(matrix->rowmatvals[arrayposition]);
210  if( indexpointer != NULL )
211  *indexpointer = &(matrix->rowmatind[arrayposition]);
212 
213  if( lhs != NULL )
214  *lhs = matrix->lhs[rowindex];
215 
216  if( rhs != NULL )
217  *rhs = matrix->rhs[rowindex];
218 }
219 
220 /** returns nonzero values and corresponding rows of given column */
221 static
222 void getColumnData(
223  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
224  int colindex, /**< the index of the desired column */
225  SCIP_Real** valpointer, /**< pointer to store the nonzero coefficients of the column */
226  int** indexpointer, /**< pointer to store row indices which belong to the nonzeros */
227  int* ncolvals /**< pointer to store number of nonzeros in the desired column */
228  )
229 {
230  int arrayposition;
231 
232  assert(matrix != NULL);
233  assert(0 <= colindex && colindex < matrix->ncols);
234 
235  arrayposition = matrix->colmatbegin[colindex];
236 
237  if( ncolvals != NULL )
238  {
239  if( colindex == matrix->ncols - 1 )
240  *ncolvals = matrix->nnonzs - arrayposition;
241  else
242  *ncolvals = matrix->colmatbegin[colindex + 1] - arrayposition; /*lint !e679*/
243  }
244  if( valpointer != NULL )
245  *valpointer = &(matrix->colmatvals[arrayposition]);
246 
247  if( indexpointer != NULL )
248  *indexpointer = &(matrix->colmatind[arrayposition]);
249 }
250 
251 /** relaxes a continuous variable from all its rows, which has influence
252  * on both the left and right hand side of the constraint.
253  */
254 static
255 void relaxVar(
256  SCIP* scip, /**< current scip instance */
257  SCIP_VAR* var, /**< variable which is relaxed from the problem */
258  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
259  SCIP_Bool normalize /**< should coefficients and be normalized by rows maximum norms? */
260  )
261 {
262  SCIP_ROW** colrows;
263  SCIP_COL* varcol;
264  SCIP_Real* colvals;
265  SCIP_Real ub;
266  SCIP_Real lb;
267  int ncolvals;
268  int r;
269 
270  assert(var != NULL);
271  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
272 
273  varcol = SCIPvarGetCol(var);
274  assert(varcol != NULL);
275 
276  /* get nonzero values and corresponding rows of variable */
277  colvals = SCIPcolGetVals(varcol);
278  ncolvals = SCIPcolGetNLPNonz(varcol);
279  colrows = SCIPcolGetRows(varcol);
280 
281  ub = SCIPvarGetUbGlobal(var);
282  lb = SCIPvarGetLbGlobal(var);
283 
284  assert(colvals != NULL || ncolvals == 0);
285 
286  SCIPdebugMessage("Relaxing variable <%s> with lb <%g> and ub <%g>\n",
287  SCIPvarGetName(var), lb, ub);
288 
289  assert(matrix->normalized);
290  /* relax variable from all its constraints */
291  for( r = 0; r < ncolvals; ++r )
292  {
293  SCIP_ROW* colrow;
294  SCIP_Real lhs;
295  SCIP_Real rhs;
296  SCIP_Real lhsvarbound;
297  SCIP_Real rhsvarbound;
298  SCIP_Real rowabs;
299  SCIP_Real colval;
300  int rowindex;
301 
302  colrow = colrows[r];
303  rowindex = SCIProwGetLPPos(colrow);
304 
305  if( rowindex == -1 )
306  break;
307 
308  rowabs = SCIPgetRowMaxCoef(scip, colrow);
309  assert(colvals != NULL); /* to please flexelint */
310  colval = colvals[r];
311  if( normalize && SCIPisFeasGT(scip, rowabs, 0.0) )
312  colval /= rowabs;
313 
314  assert(0 <= rowindex && rowindex < matrix->nrows);
315  getRowData(matrix, rowindex, NULL, &lhs, &rhs, NULL, NULL);
316  /* variables bound influence the lhs and rhs of current row depending on the sign
317  * of the variables coefficient.
318  */
319  if( SCIPisFeasPositive(scip, colval) )
320  {
321  lhsvarbound = ub;
322  rhsvarbound = lb;
323  }
324  else if( SCIPisFeasNegative(scip, colval) )
325  {
326  lhsvarbound = lb;
327  rhsvarbound = ub;
328  }
329  else
330  continue;
331 
332  /* relax variable from the current row */
333  if( !SCIPisInfinity(scip, -matrix->lhs[rowindex]) && !SCIPisInfinity(scip, ABS(lhsvarbound)) )
334  matrix->lhs[rowindex] -= colval * lhsvarbound;
335  else
336  matrix->lhs[rowindex] = -SCIPinfinity(scip);
337 
338  if( !SCIPisInfinity(scip, matrix->rhs[rowindex]) && !SCIPisInfinity(scip, ABS(rhsvarbound)) )
339  matrix->rhs[rowindex] -= colval * rhsvarbound;
340  else
341  matrix->rhs[rowindex] = SCIPinfinity(scip);
342 
343  SCIPdebugMessage("Row <%s> changed:Coefficient <%g>, LHS <%g> --> <%g>, RHS <%g> --> <%g>\n",
344  SCIProwGetName(colrow), colval, lhs, matrix->lhs[rowindex], rhs, matrix->rhs[rowindex]);
345  }
346 }
347 
348 /** transforms bounds of a given variable s.t. its lower bound equals zero afterwards.
349  * If the variable already has lower bound zero, the variable is not transformed,
350  * if not, the variable's bounds are changed w.r.t. the smaller absolute value of its
351  * bounds in order to avoid numerical inaccuracies. If both lower and upper bound
352  * of the variable differ from infinity, there are two cases. If |lb| <= |ub|,
353  * the bounds are shifted by -lb, else a new variable ub - x replaces x.
354  * The transformation is memorized by the transform status of the variable s.t.
355  * retransformation is possible.
356  */
357 static
358 void transformVariable(
359  SCIP* scip, /**< current scip instance */
360  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
361  SCIP_HEURDATA* heurdata, /**< heuristic data */
362  int colpos /**< position of variable column in matrix */
363  )
364 {
365  SCIP_COL* col;
366  SCIP_VAR* var;
367  SCIP_Real lb;
368  SCIP_Real ub;
369 
370  SCIP_Bool negatecoeffs; /* do the row coefficients need to be negated? */
371  SCIP_Real deltashift; /* difference from previous transformation */
372 
373  assert(matrix != NULL);
374  assert(0 <= colpos && colpos < heurdata->nlpcols);
375  col = heurdata->lpcols[colpos];
376  assert(col != NULL);
377  assert(SCIPcolIsInLP(col));
378 
379  var = SCIPcolGetVar(col);
380  assert(var != NULL);
381  assert(SCIPvarIsIntegral(var));
382  lb = SCIPvarGetLbLocal(var);
383  ub = SCIPvarGetUbLocal(var);
384 
385  deltashift = 0.0;
386  negatecoeffs = FALSE;
387  /* if both lower and upper bound are -infinity and infinity, resp., this is reflected by a free transform status.
388  * If the lower bound is already zero, this is reflected by identity transform status. In both cases, none of the
389  * corresponding rows needs to be modified.
390  */
391  if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
392  {
393  if( matrix->transformstatus[colpos] == TRANSFORMSTATUS_NEG )
394  negatecoeffs = TRUE;
395 
396  deltashift = matrix->transformshiftvals[colpos];
397  matrix->transformshiftvals[colpos] = 0.0;
398  matrix->transformstatus[colpos] = TRANSFORMSTATUS_FREE;
399  }
400  else if( SCIPisFeasLE(scip, ABS(lb), ABS(ub)) )
401  {
402  assert(!SCIPisInfinity(scip, lb));
403  matrix->transformstatus[colpos] = TRANSFORMSTATUS_LB;
404  deltashift = lb;
405  matrix->transformshiftvals[colpos] = lb;
406  }
407  else
408  {
409  assert(!SCIPisInfinity(scip, ub));
410  if( matrix->transformstatus[colpos] != TRANSFORMSTATUS_NEG )
411  negatecoeffs = TRUE;
412  matrix->transformstatus[colpos] = TRANSFORMSTATUS_NEG;
413  deltashift = ub;
414  matrix->transformshiftvals[colpos] = ub;
415  }
416 
417  /* determine the upper bound for this variable in heuristic transformation (lower bound is implicit; always 0) */
418  if( !SCIPisInfinity(scip, ub) && !SCIPisInfinity(scip, lb) )
419  matrix->upperbounds[colpos] = ub - lb;
420  else
421  matrix->upperbounds[colpos] = SCIPinfinity(scip);
422 
423  /* a real transformation is necessary. The variable x is either shifted by -lb or
424  * replaced by ub - x, depending on the smaller absolute of lb and ub.
425  */
426  if( !SCIPisFeasZero(scip, deltashift) || negatecoeffs )
427  {
428  SCIP_Real* vals;
429  int* rows;
430  int nrows;
431  int i;
432 
433  assert(!SCIPisInfinity(scip, deltashift));
434 
435  /* get nonzero values and corresponding rows of column */
436  getColumnData(matrix, colpos, &vals, &rows, &nrows);
437  assert(nrows == 0 ||(vals != NULL && rows != NULL));
438 
439  /* go through rows and modify its lhs, rhs and the variable coefficient, if necessary */
440  for( i = 0; i < nrows; ++i )
441  {
442  int rowpos = rows[i];
443  assert(rowpos >= 0);
444  assert(rowpos < matrix->nrows);
445 
446  if( !SCIPisInfinity(scip, -(matrix->lhs[rowpos])) )
447  matrix->lhs[rowpos] -= (vals[i]) * deltashift;
448 
449  if( !SCIPisInfinity(scip, matrix->rhs[rowpos]) )
450  matrix->rhs[rowpos] -= (vals[i]) * deltashift;
451 
452  if( negatecoeffs )
453  (vals[i]) = -(vals[i]);
454 
455  assert(SCIPisFeasLE(scip, matrix->lhs[rowpos], matrix->rhs[rowpos]));
456  }
457  }
458  SCIPdebugMessage("Variable <%s> at colpos %d transformed. LB <%g> --> <%g>, UB <%g> --> <%g>\n",
459  SCIPvarGetName(var), colpos, lb, 0.0, ub, matrix->upperbounds[colpos]);
460 }
461 
462 /** initializes copy of the original coefficient matrix and applies heuristic specific adjustments: normalizing row
463  * vectors, transforming variable domains such that lower bound is zero, and relaxing continuous variables.
464  */
465 static
467  SCIP* scip, /**< current scip instance */
468  CONSTRAINTMATRIX* matrix, /**< constraint matrix object to be initialized */
469  SCIP_HEURDATA* heurdata, /**< heuristic data */
470  SCIP_Bool normalize, /**< should coefficients and be normalized by rows maximum norms? */
471  int* nmaxrows, /**< maximum number of rows a variable appears in */
472  SCIP_Bool relax, /**< should continuous variables be relaxed from the problem? */
473  SCIP_Bool* initialized, /**< was the initialization successful? */
474  SCIP_Bool* infeasible /**< is the problem infeasible? */
475  )
476 {
477  SCIP_ROW** lprows;
478  SCIP_COL** lpcols;
479  SCIP_Bool impliscontinuous;
480  int i;
481  int j;
482  int currentpointer;
483 
484  int nrows;
485  int ncols;
486 
487  assert(scip != NULL);
488  assert(matrix != NULL);
489  assert(initialized!= NULL);
490  assert(infeasible != NULL);
491  assert(nmaxrows != NULL);
492 
493  SCIPdebugMessage("entering Matrix Initialization method of SHIFTANDPROPAGATE heuristic!\n");
494 
495  /* get LP row data; column data is already initialized in heurdata */
496  SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nrows) );
497  lpcols = heurdata->lpcols;
498  ncols = heurdata->nlpcols;
499 
500  matrix->nrows = nrows;
501  matrix->nnonzs = 0;
502  matrix->normalized = FALSE;
503  matrix->ndiscvars = 0;
504  *nmaxrows = 0;
505  impliscontinuous = heurdata->impliscontinuous;
506 
507  /* count the number of nonzeros of the LP constraint matrix */
508  for( j = 0; j < ncols; ++j )
509  {
510  assert(lpcols[j] != NULL);
511  assert(SCIPcolGetLPPos(lpcols[j]) >= 0);
512 
513  if( colIsDiscrete(lpcols[j], impliscontinuous) )
514  {
515  matrix->nnonzs += SCIPcolGetNLPNonz(lpcols[j]);
516  ++matrix->ndiscvars;
517  }
518  }
519 
520  matrix->ncols = matrix->ndiscvars;
521 
522  if( matrix->nnonzs == 0 )
523  {
524  SCIPdebugMessage("No matrix entries - Terminating initialization of matrix.\n");
525 
526  *initialized = FALSE;
527 
528  return SCIP_OKAY;
529  }
530 
531  /* allocate memory for the members of heuristic matrix */
532  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->rowmatvals, matrix->nnonzs) );
533  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->rowmatind, matrix->nnonzs) );
534  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->colmatvals, matrix->nnonzs) );
535  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->colmatind, matrix->nnonzs) );
536  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->rowmatbegin, nrows) );
537  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->colmatbegin, matrix->ncols) );
538  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->lhs, matrix->nrows) );
539  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->rhs, matrix->nrows) );
540  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->colnorms, matrix->ncols) );
541  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->violrows, matrix->ncols) );
542  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->transformstatus, matrix->ndiscvars) );
543  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->upperbounds, matrix->ndiscvars) );
544  SCIP_CALL( SCIPallocMemoryArray(scip, &matrix->transformshiftvals, matrix->ndiscvars) );
545 
546  /* set transform status of variables */
547  for( j = 0; j < matrix->ndiscvars; ++j )
548  matrix->transformstatus[j] = TRANSFORMSTATUS_NONE;
549 
550  currentpointer = 0;
551  *infeasible = FALSE;
552 
553  /* initialize the rows vector of the heuristic matrix together with its corresponding
554  * lhs, rhs.
555  */
556  for( i = 0; i < nrows; ++i )
557  {
558  SCIP_COL** cols;
559  SCIP_ROW* row;
560  SCIP_Real* rowvals;
561  SCIP_Real constant;
562  SCIP_Real maxval;
563  int nrowlpnonz;
564 
565  /* get LP row information */
566  row = lprows[i];
567  rowvals = SCIProwGetVals(row);
568  nrowlpnonz = SCIProwGetNLPNonz(row);
569  maxval = SCIPgetRowMaxCoef(scip, row);
570  cols = SCIProwGetCols(row);
571  constant = SCIProwGetConstant(row);
572 
573  SCIPdebugMessage(" %s : lhs=%g, rhs=%g, maxval=%g \n", SCIProwGetName(row), matrix->lhs[i], matrix->rhs[i], maxval);
574  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
575  assert(!SCIPisInfinity(scip, constant));
576 
577  matrix->rowmatbegin[i] = currentpointer;
578 
579  /* modify the lhs and rhs w.r.t to the rows constant and normalize by 1-norm, i.e divide the lhs and rhs by the
580  * maximum absolute value of the row
581  */
582  if( !SCIPisInfinity(scip, -SCIProwGetLhs(row)) )
583  matrix->lhs[i] = (SCIProwGetLhs(row) - constant);
584  else
585  matrix->lhs[i] = -SCIPinfinity(scip);
586 
587  if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) )
588  matrix->rhs[i] = (SCIProwGetRhs(row) - constant);
589  else
590  matrix->rhs[i] = SCIPinfinity(scip);
591 
592  /* make sure that maxval is larger than zero before normalization.
593  * Maxval may be zero if the constraint contains no variables but is modifiable, hence not redundant
594  */
595  if( normalize && !SCIPisFeasZero(scip, maxval) )
596  {
597  if( !SCIPisInfinity(scip, -matrix->lhs[i]) )
598  matrix->lhs[i] /= maxval;
599  if( !SCIPisInfinity(scip, matrix->rhs[i]) )
600  matrix->rhs[i] /= maxval;
601  }
602 
603 
604  /* in case of empty rows with a 0 < lhs <= 0.0 or 0.0 <= rhs < 0 we deduce the infeasibility of the problem */
605  if( nrowlpnonz == 0 && (SCIPisFeasPositive(scip, matrix->lhs[i]) || SCIPisFeasNegative(scip, matrix->rhs[i])) )
606  {
607  *infeasible = TRUE;
608  SCIPdebugMessage(" Matrix initialization stopped because of row infeasibility! \n");
609  break;
610  }
611 
612  /* row coefficients are normalized and copied to heuristic matrix */
613  for( j = 0; j < nrowlpnonz; ++j )
614  {
615  if( !colIsDiscrete(cols[j], impliscontinuous) )
616  continue;
617  assert(SCIPcolGetLPPos(cols[j]) >= 0);
618  assert(currentpointer < matrix->nnonzs);
619 
620  matrix->rowmatvals[currentpointer] = rowvals[j];
621  if( normalize && SCIPisFeasGT(scip, maxval, 0.0) )
622  matrix->rowmatvals[currentpointer] /= maxval;
623 
624  matrix->rowmatind[currentpointer] = SCIPcolGetLPPos(cols[j]);
625 
626  ++currentpointer;
627  }
628  }
629 
630  matrix->normalized = TRUE;
631 
632  if( *infeasible )
633  return SCIP_OKAY;
634 
635  assert(currentpointer == matrix->nnonzs);
636 
637  currentpointer = 0;
638 
639  /* copy the nonzero coefficient data column by column to heuristic matrix */
640  for( j = 0; j < matrix->ncols; ++j )
641  {
642  SCIP_COL* currentcol;
643  SCIP_ROW** rows;
644  SCIP_Real* colvals;
645  int ncolnonz;
646 
647 
648  assert(SCIPcolGetLPPos(lpcols[j]) >= 0);
649 
650  currentcol = lpcols[j];
651  assert(colIsDiscrete(currentcol, impliscontinuous));
652 
653  colvals = SCIPcolGetVals(currentcol);
654  rows = SCIPcolGetRows(currentcol);
655  ncolnonz = SCIPcolGetNLPNonz(currentcol);
656  matrix->colnorms[j] = ncolnonz;
657 
658  *nmaxrows = MAX(*nmaxrows, ncolnonz);
659 
660  /* loop over all rows with nonzero coefficients in the column, transform them and add them to the heuristic matrix */
661  matrix->colmatbegin[j] = currentpointer;
662 
663  for( i = 0; i < ncolnonz; ++i )
664  {
665  SCIP_Real maxval;
666 
667  assert(rows[i] != NULL);
668  assert(0 <= SCIProwGetLPPos(rows[i]));
669  assert(SCIProwGetLPPos(rows[i]) < nrows);
670  assert(currentpointer < matrix->nnonzs);
671 
672  /* rows are normalized by maximum norm */
673  maxval = SCIPgetRowMaxCoef(scip, rows[i]);
674 
675  assert(maxval > 0);
676 
677  matrix->colmatvals[currentpointer] = colvals[i];
678  if( normalize && SCIPisFeasGT(scip, maxval, 0.0) )
679  matrix->colmatvals[currentpointer] /= maxval;
680 
681  matrix->colmatind[currentpointer] = SCIProwGetLPPos(rows[i]);
682 
683  /* update the column norm */
684  matrix->colnorms[j] += ABS(matrix->colmatvals[currentpointer]);
685  ++currentpointer;
686  }
687  }
688  assert(currentpointer == matrix->nnonzs);
689 
690  /* each variable is either transformed, if it supposed to be integral, or relaxed */
691  for( j = 0; j < (relax ? ncols : matrix->ndiscvars); ++j )
692  {
693  SCIP_COL* col;
694 
695  col = lpcols[j];
696  if( colIsDiscrete(col, impliscontinuous) )
697  {
698  matrix->transformshiftvals[j] = 0.0;
699  transformVariable(scip, matrix, heurdata, j);
700  }
701  else
702  {
703  SCIP_VAR* var;
704  var = SCIPcolGetVar(col);
705  assert(!varIsDiscrete(var, impliscontinuous));
706  relaxVar(scip, var, matrix, normalize);
707  }
708  }
709  *initialized = TRUE;
710 
711  SCIPdebugMessage("Matrix initialized for %d discrete variables with %d cols, %d rows and %d nonzero entries\n",
712  matrix->ndiscvars, matrix->ncols, matrix->nrows, matrix->nnonzs);
713  return SCIP_OKAY;
714 }
715 
716 /** frees all members of the heuristic matrix */
717 static
718 void freeMatrix(
719  SCIP* scip, /**< current SCIP instance */
720  CONSTRAINTMATRIX** matrix /**< constraint matrix object */
721  )
722 {
723  assert(scip != NULL);
724  assert(matrix != NULL);
725 
726  /* all fields are only allocated, if problem is not empty */
727  if( (*matrix)->nnonzs > 0 )
728  {
729  assert((*matrix) != NULL);
730  assert((*matrix)->rowmatbegin != NULL);
731  assert((*matrix)->rowmatvals != NULL);
732  assert((*matrix)->rowmatind != NULL);
733  assert((*matrix)->colmatbegin != NULL);
734  assert((*matrix)->colmatvals!= NULL);
735  assert((*matrix)->colmatind != NULL);
736  assert((*matrix)->lhs != NULL);
737  assert((*matrix)->rhs != NULL);
738  assert((*matrix)->transformstatus != NULL);
739  assert((*matrix)->transformshiftvals != NULL);
740 
741  /* free all fields */
742  SCIPfreeMemoryArray(scip, &((*matrix)->rowmatbegin));
743  SCIPfreeMemoryArray(scip, &((*matrix)->rowmatvals));
744  SCIPfreeMemoryArray(scip, &((*matrix)->rowmatind));
745  SCIPfreeMemoryArray(scip, &((*matrix)->colmatvals));
746  SCIPfreeMemoryArray(scip, &((*matrix)->colmatind));
747  SCIPfreeMemoryArray(scip, &((*matrix)->colmatbegin));
748  SCIPfreeMemoryArray(scip, &((*matrix)->lhs));
749  SCIPfreeMemoryArray(scip, &((*matrix)->rhs));
750  SCIPfreeMemoryArray(scip, &((*matrix)->colnorms));
751  SCIPfreeMemoryArray(scip, &((*matrix)->violrows));
752  SCIPfreeMemoryArray(scip, &((*matrix)->transformstatus));
753  SCIPfreeMemoryArray(scip, &((*matrix)->upperbounds));
754  SCIPfreeMemoryArray(scip, &((*matrix)->transformshiftvals));
755 
756  (*matrix)->nrows = 0;
757  (*matrix)->ncols = 0;
758  }
759 
760  /* free matrix */
761  SCIPfreeBuffer(scip, matrix);
762 }
763 
764 /** updates the information about a row whenever violation status changes */
765 static
766 void checkRowViolation(
767  SCIP* scip, /**< current SCIP instance */
768  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
769  int rowindex, /**< index of the row */
770  int* violatedrows, /**< contains all violated rows */
771  int* violatedrowpos, /**< positions of rows in the violatedrows array */
772  int* nviolatedrows, /**< pointer to update total number of violated rows */
773  int* rowweights, /**< row weight storage */
774  SCIP_Bool updateweights /**< should row weight be increased every time the row is violated? */
775  )
776 {
777  int* cols;
778  int ncols;
779  int c;
780  int violadd;
781  assert(matrix != NULL);
782  assert(violatedrows != NULL);
783  assert(violatedrowpos != NULL);
784  assert(nviolatedrows != NULL);
785 
786  getRowData(matrix, rowindex, NULL, NULL, NULL, &cols, &ncols);
787  violadd = 0;
788 
789  /* row is now violated. Enqueue it in the set of violated rows. */
790  if( violatedrowpos[rowindex] == -1 && (SCIPisFeasGT(scip, matrix->lhs[rowindex], 0.0) || SCIPisFeasLT(scip, matrix->rhs[rowindex], 0.0)) )
791  {
792  assert(*nviolatedrows < matrix->nrows);
793 
794  violatedrows[*nviolatedrows] = rowindex;
795  violatedrowpos[rowindex] = *nviolatedrows;
796  ++(*nviolatedrows);
797  if( updateweights )
798  ++rowweights[rowindex];
799 
800  violadd = 1;
801  }
802  /* row is now feasible. Remove it from the set of violated rows. */
803  else if( violatedrowpos[rowindex] >= 0 && SCIPisFeasLE(scip, matrix->lhs[rowindex], 0.0) && SCIPisFeasGE(scip, matrix->rhs[rowindex], 0.0) )
804  {
805  /* swap the row with last violated row */
806  if( violatedrowpos[rowindex] != *nviolatedrows - 1 )
807  {
808  assert(*nviolatedrows - 1 >= 0);
809  violatedrows[violatedrowpos[rowindex]] = violatedrows[*nviolatedrows - 1];
810  violatedrowpos[violatedrows[*nviolatedrows - 1]] = violatedrowpos[rowindex];
811  }
812 
813  /* unlink the row from its position in the array and decrease number of violated rows */
814  violatedrowpos[rowindex] = -1;
815  --(*nviolatedrows);
816  violadd = -1;
817  }
818 
819  /* increase or decrease the column violation counter */
820  for( c = 0; c < ncols; ++c )
821  {
822  matrix->violrows[cols[c]] += violadd;
823  assert(matrix->violrows[cols[c]] >= 0);
824  }
825 }
826 
827 /** collects the necessary information about row violations for the zero-solution. That is,
828  * all solution values in heuristic transformation are zero.
829  */
830 static
831 void checkViolations(
832  SCIP* scip, /**< current scip instance */
833  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
834  int colidx, /**< column index for specific column, or -1 for all rows */
835  int* violatedrows, /**< violated rows */
836  int* violatedrowpos, /**< row positions of violated rows */
837  int* nviolatedrows, /**< pointer to store the number of violated rows */
838  int* rowweights, /**< weight array for every row */
839  SCIP_Bool updateweights /**< should row weight be increased every time the row is violated? */
840  )
841 {
842  int nrows;
843  int* rowindices;
844  int i;
845 
846  assert(matrix != NULL);
847  assert(violatedrows != NULL);
848  assert(violatedrowpos != NULL);
849  assert(nviolatedrows != NULL);
850  assert(-1 <= colidx && colidx < matrix->ncols);
851 
852  /* check if we requested an update for a single variable, or if we want to (re)-initialize the whole violation info */
853  if( colidx >= 0 )
854  getColumnData(matrix, colidx, NULL, &rowindices, &nrows);
855  else
856  {
857  nrows = matrix->nrows;
858  rowindices = NULL;
859  *nviolatedrows = 0;
860 
861  /* reinitialize the violated rows */
862  for( i = 0; i < nrows; ++i )
863  violatedrowpos[i] = -1;
864 
865  /* clear the violated row counters for all variables */
866  BMSclearMemoryArray(matrix->violrows, matrix->ndiscvars);
867  }
868 
869  assert(colidx < 0 || *nviolatedrows >= 0);
870  SCIPdebugMessage("Entering violation check for %d rows! \n", nrows);
871  /* loop over rows and check if it is violated */
872  for( i = 0; i < nrows; ++i )
873  {
874  int rowpos;
875  if( colidx >= 0 )
876  {
877  assert(rowindices != NULL);
878  rowpos = rowindices[i];
879  }
880  else
881  rowpos = i;
882  /* check, if zero solution violates this row */
883  checkRowViolation(scip, matrix, rowpos, violatedrows, violatedrowpos, nviolatedrows, rowweights, updateweights);
884 
885  assert((violatedrowpos[rowpos] == -1 && SCIPisFeasGE(scip, matrix->rhs[rowpos], 0.0) && SCIPisFeasLE(scip, matrix->lhs[rowpos], 0.0))
886  || (violatedrowpos[rowpos] >= 0 &&(SCIPisFeasLT(scip, matrix->rhs[rowpos], 0.0) || SCIPisFeasGT(scip, matrix->lhs[rowpos], 0.0))));
887  }
888 }
889 
890 /** retransforms solution values of variables according to their transformation status */
891 static
893  SCIP* scip, /**< current scip instance */
894  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
895  SCIP_VAR* var, /**< variable whose solution value has to be retransformed */
896  int varindex, /**< permutation of variable indices according to sorting */
897  SCIP_Real solvalue /**< solution value of the variable */
898  )
899 {
900  TRANSFORMSTATUS status;
901 
902  assert(matrix != NULL);
903  assert(var != NULL);
904 
905  status = matrix->transformstatus[varindex];
906  assert(status != TRANSFORMSTATUS_NONE);
907 
908  /* check if original variable has different bounds and transform solution value correspondingly */
909  if( status == TRANSFORMSTATUS_LB )
910  {
911  assert(!SCIPisInfinity(scip, -SCIPvarGetLbLocal(var)));
912 
913  return solvalue + matrix->transformshiftvals[varindex];
914  }
915  else if( status == TRANSFORMSTATUS_NEG )
916  {
917  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
918  return matrix->transformshiftvals[varindex] - solvalue;
919  }
920  return solvalue;
921 }
922 
923 /** determines the best shifting value of a variable
924  * @todo if there is already an incumbent solution, try considering the objective cutoff as additional constraint */
925 static
927  SCIP* scip, /**< current scip instance */
928  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
929  int varindex, /**< index of variable which should be shifted */
930  int direction, /**< the direction for this variable */
931  int* rowweights, /**< weighting of rows for best shift calculation */
932  SCIP_Real* steps, /**< buffer array to store the individual steps for individual rows */
933  int* violationchange, /**< buffer array to store the individual change of feasibility of row */
934  SCIP_Real* beststep, /**< pointer to store optimal shifting step */
935  int* rowviolations /**< pointer to store new weighted sum of row violations, i.e, v - f */
936  )
937 {
938  SCIP_Real* vals;
939  int* rows;
940 
941  SCIP_Real slacksurplus;
942  SCIP_Real upperbound;
943 
944  int nrows;
945  int sum;
946  int i;
947 
948  SCIP_Bool allzero;
949 
950  assert(beststep != NULL);
951  assert(rowviolations != NULL);
952  assert(rowweights != NULL);
953  assert(steps != NULL);
954  assert(violationchange != NULL);
955  assert(direction == 1 || direction == -1);
956 
957  upperbound = matrix->upperbounds[varindex];
958 
959  /* get nonzero values and corresponding rows of variable */
960  getColumnData(matrix, varindex, &vals, &rows, &nrows);
961 
962  /* loop over rows and calculate, which is the minimum shift to make this row feasible
963  * or the minimum shift to violate this row
964  */
965  allzero = TRUE;
966  slacksurplus = 0.0;
967  for( i = 0; i < nrows; ++i )
968  {
969  SCIP_Real lhs;
970  SCIP_Real rhs;
971  SCIP_Real val;
972  int rowpos;
973  SCIP_Bool rowisviolated;
974  int rowweight;
975 
976  /* get the row data */
977  rowpos = rows[i];
978  assert(rowpos >= 0);
979  lhs = matrix->lhs[rowpos];
980  rhs = matrix->rhs[rowpos];
981  rowweight = rowweights[rowpos];
982  val = direction * vals[i];
983 
984  /* determine if current row is violated or not */
985  rowisviolated =(SCIPisFeasLT(scip, rhs, 0.0) || SCIPisFeasLT(scip, -lhs, 0.0));
986 
987  /* for a feasible row, determine the minimum integer value within the bounds of the variable by which it has to be
988  * shifted to make row infeasible.
989  */
990  if( !rowisviolated )
991  {
992  SCIP_Real maxfeasshift;
993 
994  maxfeasshift = SCIPinfinity(scip);
995 
996  /* feasibility can only be violated if the variable has a lock in the corresponding direction,
997  * i.e. a positive coefficient for a "<="-constraint, a negative coefficient for a ">="-constraint.
998  */
999  if( SCIPisFeasGT(scip, val, 0.0) && !SCIPisInfinity(scip, rhs) )
1000  maxfeasshift = SCIPfeasFloor(scip, rhs/val);
1001  else if( SCIPisFeasLT(scip, val, 0.0) && !SCIPisInfinity(scip, -lhs) )
1002  maxfeasshift = SCIPfeasFloor(scip, lhs/val);
1003 
1004  /* if the variable has no lock in the current row, it can still help to increase the slack of this row;
1005  * we measure slack increase for shifting by one
1006  */
1007  if( SCIPisFeasGT(scip, val, 0.0) && SCIPisInfinity(scip, rhs) )
1008  slacksurplus += val;
1009  if( SCIPisFeasLT(scip, val, 0.0) && SCIPisInfinity(scip, -lhs) )
1010  slacksurplus -= val;
1011 
1012  /* check if the least violating shift lies within variable bounds and set corresponding array values */
1013  if( SCIPisFeasLE(scip, maxfeasshift + 1.0, upperbound) )
1014  {
1015  steps[i] = maxfeasshift + 1.0;
1016  violationchange[i] = rowweight;
1017  allzero = FALSE;
1018  }
1019  else
1020  {
1021  steps[i] = upperbound;
1022  violationchange[i] = 0;
1023  }
1024  }
1025  /* for a violated row, determine the minimum integral value within the bounds of the variable by which it has to be
1026  * shifted to make row feasible.
1027  */
1028  else
1029  {
1030  SCIP_Real minfeasshift;
1031 
1032  minfeasshift = SCIPinfinity(scip);
1033 
1034  /* if coefficient has the right sign to make row feasible, determine the minimum integer to shift variable
1035  * to obtain feasibility
1036  */
1037  if( SCIPisFeasLT(scip, -lhs, 0.0) && SCIPisFeasGT(scip, val, 0.0) )
1038  minfeasshift = SCIPfeasCeil(scip, lhs/val);
1039  else if( SCIPisFeasLT(scip, rhs,0.0) && SCIPisFeasLT(scip, val, 0.0) )
1040  minfeasshift = SCIPfeasCeil(scip, rhs/val);
1041 
1042  /* check if the minimum feasibility recovery shift lies within variable bounds and set corresponding array
1043  * values
1044  */
1045  if( !SCIPisInfinity(scip, minfeasshift) && SCIPisFeasLE(scip, minfeasshift, upperbound) )
1046  {
1047  steps[i] = minfeasshift;
1048  violationchange[i] = -rowweight;
1049  allzero = FALSE;
1050  }
1051  else
1052  {
1053  steps[i] = upperbound;
1054  violationchange[i] = 0;
1055  }
1056  }
1057  }
1058 
1059  /* in case that the variable cannot affect the feasibility of any row, in particular it cannot violate
1060  * a single row, but we can add slack to already feasible rows, we will do this
1061  */
1062  if( allzero )
1063  {
1064  *beststep = SCIPisFeasGT(scip, slacksurplus, 0.0) ? direction * upperbound : 0.0;
1065  return SCIP_OKAY;
1066  }
1067 
1068  /* sorts rows by increasing value of steps */
1069  SCIPsortRealInt(steps, violationchange, nrows);
1070 
1071  *beststep = 0.0;
1072  *rowviolations = 0;
1073  sum = 0;
1074 
1075  /* best shifting step is calculated by summing up the violation changes for each relevant step and
1076  * taking the one which leads to the minimum sum. This sum measures the balance of feasibility recovering and
1077  * violating changes which will be obtained by shifting the variable by this step
1078  * note, the sums for smaller steps have to be taken into account for all bigger steps, i.e., the sums can be
1079  * computed iteratively
1080  */
1081  for( i = 0; i < nrows && !SCIPisInfinity(scip, steps[i]); ++i )
1082  {
1083  sum += violationchange[i];
1084 
1085  /* if we reached the last entry for the current step value, we have finished computing its sum and
1086  * update the step defining the minimum sum
1087  */
1088  if( (i == nrows-1 || steps[i+1] > steps[i]) && sum < *rowviolations ) /*lint !e679*/
1089  {
1090  *rowviolations = sum;
1091  *beststep = direction * steps[i];
1092  }
1093  }
1094  assert(*rowviolations <= 0);
1095  assert(!SCIPisInfinity(scip, *beststep));
1096 
1097  return SCIP_OKAY;
1098 }
1099 
1100 /** updates transformation of a given variable by taking into account current local bounds. if the bounds have changed
1101  * since last update, updating the heuristic specific upper bound of the variable, its current transformed solution value
1102  * and all affected rows is necessary.
1103  */
1104 static
1106  SCIP* scip, /**< current scip */
1107  CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
1108  SCIP_HEURDATA* heurdata, /**< heuristic data */
1109  int varindex, /**< index of variable in matrix */
1110  SCIP_Real lb, /**< local lower bound of the variable */
1111  SCIP_Real ub, /**< local upper bound of the variable */
1112  int* violatedrows, /**< violated rows */
1113  int* violatedrowpos, /**< violated row positions */
1114  int* nviolatedrows /**< pointer to store number of violated rows */
1115  )
1116 {
1117  TRANSFORMSTATUS status;
1118  SCIP_Real deltashift;
1119  SCIP_Bool checkviolations;
1120 
1121  assert(scip != NULL);
1122  assert(matrix != NULL);
1123  assert(0 <= varindex && varindex < matrix->ndiscvars);
1124 
1125  /* deltashift is the difference between the old and new transformation value. */
1126  deltashift = 0.0;
1127  status = matrix->transformstatus[varindex];
1128 
1129  SCIPdebugMessage(" Variable <%d> [%g,%g], status %d(%g), ub %g \n", varindex, lb, ub, status,
1130  matrix->transformshiftvals[varindex], matrix->upperbounds[varindex]);
1131 
1132  checkviolations = FALSE;
1133  /* depending on the variable status, deltashift is calculated differently. */
1134  switch( status )
1135  {
1136  case TRANSFORMSTATUS_LB:
1137  if( SCIPisInfinity(scip, -lb) )
1138  {
1139  transformVariable(scip, matrix, heurdata, varindex);
1140  checkviolations = TRUE;
1141  }
1142  else
1143  {
1144  deltashift = lb - (matrix->transformshiftvals[varindex]);
1145  matrix->transformshiftvals[varindex] = lb;
1146  if( !SCIPisInfinity(scip, ub) )
1147  matrix->upperbounds[varindex] = ub - lb;
1148  else
1149  matrix->upperbounds[varindex] = SCIPinfinity(scip);
1150  }
1151  break;
1152  case TRANSFORMSTATUS_NEG:
1153  if( SCIPisInfinity(scip, ub) )
1154  {
1155  transformVariable(scip, matrix, heurdata, varindex);
1156  checkviolations = TRUE;
1157  }
1158  else
1159  {
1160  deltashift = (matrix->transformshiftvals[varindex]) - ub;
1161  matrix->transformshiftvals[varindex] = ub;
1162 
1163  if( !SCIPisInfinity(scip, -lb) )
1164  matrix->upperbounds[varindex] = ub - lb;
1165  }
1166  break;
1167  case TRANSFORMSTATUS_FREE:
1168  /* in case of a free transform status, if one of the bounds has become finite, we want
1169  * to transform this variable to a variable with a lowerbound or a negated transform status */
1170  if( !SCIPisInfinity(scip, -lb) || !SCIPisInfinity(scip, ub) )
1171  {
1172  transformVariable(scip, matrix, heurdata, varindex);
1173 
1174  /* violations have to be rechecked for rows in which variable appears */
1175  checkviolations = TRUE;
1176 
1177  assert(matrix->transformstatus[varindex] == TRANSFORMSTATUS_LB || TRANSFORMSTATUS_NEG);
1178  assert(SCIPisFeasLE(scip, ABS(lb), ABS(ub)) || matrix->transformstatus[varindex] == TRANSFORMSTATUS_NEG);
1179  }
1180  break;
1181 
1182  case TRANSFORMSTATUS_NONE:
1183  default:
1184  SCIPerrorMessage("Error: Invalid variable status <%d> in shift and propagagate heuristic, aborting!\n");
1185  SCIPABORT();
1186  return SCIP_INVALIDDATA; /*lint !e527*/
1187  }
1188  /* if the bound, by which the variable was shifted, has changed, deltashift is different from zero, which requires
1189  * an update of all affected rows
1190  */
1191  if( !SCIPisFeasZero(scip, deltashift) )
1192  {
1193  int i;
1194  int* rows;
1195  SCIP_Real* vals;
1196  int nrows;
1197 
1198  /* get nonzero values and corresponding rows of variable */
1199  getColumnData(matrix, varindex, &vals, &rows, &nrows);
1200 
1201  /* go through rows, update the rows w.r.t. the influence of the changed transformation of the variable */
1202  for( i = 0; i < nrows; ++i )
1203  {
1204  SCIPdebugMessage(" update slacks of row<%d>: coefficient <%g>, %g <= 0 <= %g \n",
1205  rows[i], vals[i], matrix->lhs[rows[i]], matrix->rhs[rows[i]]);
1206 
1207  if( !SCIPisInfinity(scip, -(matrix->lhs[rows[i]])) )
1208  matrix->lhs[rows[i]] -= (vals[i]) * deltashift;
1209 
1210  if( !SCIPisInfinity(scip, matrix->rhs[rows[i]]) )
1211  matrix->rhs[rows[i]] -= (vals[i]) * deltashift;
1212  }
1213  checkviolations = TRUE;
1214  }
1215 
1216  /* check and update information about violated rows, if necessary */
1217  if( checkviolations )
1218  checkViolations(scip, matrix, varindex, violatedrows, violatedrowpos, nviolatedrows, heurdata->rowweights, heurdata->updateweights);
1219 
1220  SCIPdebugMessage(" Variable <%d> [%g,%g], status %d(%g), ub %g \n", varindex, lb, ub, status,
1221  matrix->transformshiftvals[varindex], matrix->upperbounds[varindex]);
1222 
1223  return SCIP_OKAY;
1224 }
1225 
1226 /** comparison method for columns; binary < integer < implicit < continuous variables */
1227 static
1228 SCIP_DECL_SORTPTRCOMP(heurSortColsShiftandpropagate)
1230  SCIP_COL* col1;
1231  SCIP_COL* col2;
1232  SCIP_VAR* var1;
1233  SCIP_VAR* var2;
1234  SCIP_VARTYPE vartype1;
1235  SCIP_VARTYPE vartype2;
1236  int key1;
1237  int key2;
1238 
1239  col1 = (SCIP_COL*)elem1;
1240  col2 = (SCIP_COL*)elem2;
1241  var1 = SCIPcolGetVar(col1);
1242  var2 = SCIPcolGetVar(col2);
1243  assert(var1 != NULL && var2 != NULL);
1244 
1245  vartype1 = SCIPvarGetType(var1);
1246  vartype2 = SCIPvarGetType(var2);
1247 
1248  switch (vartype1)
1249  {
1250  case SCIP_VARTYPE_BINARY:
1251  key1 = 1;
1252  break;
1253  case SCIP_VARTYPE_INTEGER:
1254  key1 = 2;
1255  break;
1256  case SCIP_VARTYPE_IMPLINT:
1257  key1 = 3;
1258  break;
1260  key1 = 4;
1261  break;
1262  default:
1263  key1 = -1;
1264  SCIPerrorMessage("unknown variable type\n");
1265  SCIPABORT();
1266  break;
1267  }
1268  switch (vartype2)
1269  {
1270  case SCIP_VARTYPE_BINARY:
1271  key2 = 1;
1272  break;
1273  case SCIP_VARTYPE_INTEGER:
1274  key2 = 2;
1275  break;
1276  case SCIP_VARTYPE_IMPLINT:
1277  key2 = 3;
1278  break;
1280  key2 = 4;
1281  break;
1282  default:
1283  key2 = -1;
1284  SCIPerrorMessage("unknown variable type\n");
1285  SCIPABORT();
1286  break;
1287  }
1288  return key1 - key2;
1289 }
1290 
1291 /*
1292  * Callback methods of primal heuristic
1293  */
1294 
1295 /** deinitialization method of primal heuristic(called before transformed problem is freed) */
1296 static
1297 SCIP_DECL_HEUREXIT(heurExitShiftandpropagate)
1298 { /*lint --e{715}*/
1299  /* if statistic mode is enabled, statistics are printed to console */
1300  SCIPstatistic(
1301  SCIP_HEURDATA* heurdata;
1302 
1303  heurdata = SCIPheurGetData(heur);
1304 
1305  assert(heurdata != NULL);
1306 
1308  " DETAILS : %d violations left, %d probing status, %d redundant rows\n",
1309  heurdata->nremainingviols,
1310  heurdata->lpsolstat
1311  );
1313  " SHIFTANDPROPAGATE PROBING : %d probings, %" SCIP_LONGINT_FORMAT " domain reductions, ncutoffs: %d , LP iterations: %" SCIP_LONGINT_FORMAT " \n ",
1314  heurdata->nprobings,
1315  heurdata->ntotaldomredsfound,
1316  heurdata->ncutoffs,
1317  heurdata->nlpiters);
1318  );
1319 
1320  return SCIP_OKAY;
1321 }
1322 
1323 /** initialization method of primal heuristic(called after problem was transformed). We only need this method for
1324  * statistic mode of heuristic.
1325  */
1326 static
1327 SCIP_DECL_HEURINIT(heurInitShiftandpropagate)
1328 { /*lint --e{715}*/
1329 
1330  SCIP_HEURDATA* heurdata;
1331 
1332  heurdata = SCIPheurGetData(heur);
1333 
1334  assert(heurdata != NULL);
1335 
1336  heurdata->randseed = DEFAULT_RANDSEED;
1337 
1338  SCIPstatistic(
1339  heurdata->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
1340  heurdata->nremainingviols = 0;
1341  heurdata->nprobings = 0;
1342  heurdata->ntotaldomredsfound = 0;
1343  heurdata->ncutoffs = 0;
1344  heurdata->nlpiters = 0;
1345  )
1346  return SCIP_OKAY;
1347 }
1348 
1349 /** destructor of primal heuristic to free user data(called when SCIP is exiting) */
1350 static
1351 SCIP_DECL_HEURFREE(heurFreeShiftandpropagate)
1352 { /*lint --e{715}*/
1353  SCIP_HEURDATA* heurdata;
1354  SCIP_EVENTHDLR* eventhdlr;
1355  SCIP_EVENTHDLRDATA* eventhdlrdata;
1356 
1357  heurdata = SCIPheurGetData(heur);
1358  eventhdlr = heurdata->eventhdlr;
1359  assert(eventhdlr != NULL);
1360  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1361 
1362  SCIPfreeMemory(scip, &eventhdlrdata);
1363 
1364  /* free heuristic data */
1365  if( heurdata != NULL )
1366  SCIPfreeMemory(scip, &heurdata);
1367 
1368  SCIPheurSetData(heur, NULL);
1369 
1370  return SCIP_OKAY;
1371 }
1372 
1373 
1374 /** copy method for primal heuristic plugins(called when SCIP copies plugins) */
1375 static
1376 SCIP_DECL_HEURCOPY(heurCopyShiftandpropagate)
1377 { /*lint --e{715}*/
1378  assert(scip != NULL);
1379  assert(heur != NULL);
1380  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1381 
1382  /* call inclusion method of primal heuristic */
1384 
1385  return SCIP_OKAY;
1386 }
1387 
1388 /** execution method of primal heuristic */
1389 static
1390 SCIP_DECL_HEUREXEC(heurExecShiftandpropagate)
1391 { /*lint --e{715}*/
1392  SCIP_HEURDATA* heurdata; /* heuristic data */
1393  SCIP_EVENTHDLR* eventhdlr; /* shiftandpropagate event handler */
1394  SCIP_EVENTHDLRDATA* eventhdlrdata; /* event handler data */
1395  SCIP_EVENTDATA** eventdatas; /* event data for every variable */
1396 
1397  CONSTRAINTMATRIX* matrix; /* constraint matrix object */
1398  SCIP_COL** lpcols; /* lp columns */
1399  SCIP_SOL* sol; /* solution pointer */
1400  SCIP_Real* colnorms; /* contains Euclidean norms of column vectors */
1401 
1402  SCIP_Real* steps; /* buffer arrays for best shift selection in main loop */
1403  int* violationchange;
1404 
1405  int* violatedrows; /* the violated rows */
1406  int* violatedrowpos; /* the array position of a violated row, or -1 */
1407  int* permutation; /* reflects the position of the variables after sorting */
1408  int* violatedvarrows; /* number of violated rows for each variable */
1409  int nlpcols; /* number of lp columns */
1410  int nviolatedrows; /* number of violated rows */
1411  int ndiscvars; /* number of non-continuous variables of the problem */
1412  int lastindexofsusp; /* last variable which has been swapped due to a cutoff */
1413  int nbinvars; /* number of binary variables */
1414  int nintvars; /* number of integer variables */
1415  int i;
1416  int r;
1417  int v;
1418  int c;
1419  int ncutoffs; /* counts the number of cutoffs for this execution */
1420  int nprobings; /* counts the number of probings */
1421  int nlprows; /* the number LP rows */
1422  int nmaxrows; /* maximum number of LP rows of a variable */
1423 
1424  SCIP_Bool initialized; /* has the matrix been initialized? */
1425  SCIP_Bool cutoff; /* has current probing node been cutoff? */
1426  SCIP_Bool probing; /* should probing be applied or not? */
1427  SCIP_Bool infeasible; /* FALSE as long as currently infeasible rows have variables left */
1428  SCIP_Bool impliscontinuous;
1429 
1430  heurdata = SCIPheurGetData(heur);
1431  assert(heurdata != NULL);
1432 
1433  eventhdlr = heurdata->eventhdlr;
1434  assert(eventhdlr != NULL);
1435 
1436  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1437  assert(eventhdlrdata != NULL);
1438 
1439  *result = SCIP_DIDNOTRUN;
1440  SCIPdebugMessage("entering execution method of shift and propagate heuristic\n");
1441 
1442  /* heuristic is obsolete if there are only continuous variables */
1443  if( SCIPgetNVars(scip) - SCIPgetNContVars(scip) == 0 )
1444  return SCIP_OKAY;
1445 
1446  /* stop execution method if there is already a primarily feasible solution at hand */
1447  if( SCIPgetBestSol(scip) != NULL && heurdata->onlywithoutsol )
1448  return SCIP_OKAY;
1449 
1450  /* stop if there is no LP available */
1451  if ( ! SCIPhasCurrentNodeLP(scip) )
1452  return SCIP_OKAY;
1453 
1454  if( !SCIPisLPConstructed(scip) )
1455  {
1456  SCIP_Bool nodecutoff;
1457 
1458  nodecutoff = FALSE;
1459  /* @note this call can have the side effect that variables are created */
1460  SCIP_CALL( SCIPconstructLP(scip, &nodecutoff) );
1461  SCIP_CALL( SCIPflushLP(scip) );
1462  }
1463 
1464  SCIPstatistic( heurdata->nlpiters = SCIPgetNLPIterations(scip) );
1465 
1466  nlprows = SCIPgetNLPRows(scip);
1467 
1468  SCIP_CALL( SCIPgetLPColsData(scip, &lpcols, &nlpcols) );
1469  assert(nlpcols == 0 || lpcols != NULL);
1470 
1471  /* we need an LP */
1472  if( nlprows == 0 || nlpcols == 0 )
1473  return SCIP_OKAY;
1474 
1475 
1476  *result = SCIP_DIDNOTFIND;
1477  initialized = FALSE;
1478 
1479  /* allocate lp column array */
1480  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->lpcols, nlpcols) );
1481  heurdata->nlpcols = nlpcols;
1482 
1483  impliscontinuous = heurdata->impliscontinuous;
1484 
1485 #ifndef NDEBUG
1486  BMSclearMemoryArray(heurdata->lpcols, nlpcols);
1487 #endif
1488 
1489  BMScopyMemoryArray(heurdata->lpcols, lpcols, nlpcols);
1490 
1491  SCIPsortPtr((void**)heurdata->lpcols, heurSortColsShiftandpropagate, nlpcols);
1492 
1493  /* we have to collect the number of different variable types before we start probing since during probing variable
1494  * can be created (e.g., cons_xor.c)
1495  */
1496  ndiscvars = 0;
1497  nbinvars = 0;
1498  nintvars = 0;
1499  for( c = 0; c < nlpcols; ++c )
1500  {
1501  SCIP_COL* col;
1502  SCIP_VAR* colvar;
1503 
1504  col = heurdata->lpcols[c];
1505  assert(col != NULL);
1506  colvar = SCIPcolGetVar(col);
1507  assert(colvar != NULL);
1508 
1509  if( varIsDiscrete(colvar, impliscontinuous) )
1510  ++ndiscvars;
1511  if( SCIPvarGetType(colvar) == SCIP_VARTYPE_BINARY )
1512  ++nbinvars;
1513  else if( SCIPvarGetType(colvar) == SCIP_VARTYPE_INTEGER )
1514  ++nintvars;
1515  }
1516  assert(nbinvars + nintvars <= ndiscvars);
1517 
1518  /* start probing mode */
1519  SCIP_CALL( SCIPstartProbing(scip) );
1520 
1521  /* enables collection of variable statistics during probing */
1522  if( heurdata->collectstats )
1523  SCIPenableVarHistory(scip);
1524  else
1525  SCIPdisableVarHistory(scip);
1526 
1527  /* @todo check if this node is necessary (I don't think so) */
1528  SCIP_CALL( SCIPnewProbingNode(scip) );
1529  ncutoffs = 0;
1530  nprobings = 0;
1531  nmaxrows = 0;
1532  infeasible = FALSE;
1533 
1534  /* initialize heuristic matrix and working solution */
1535  SCIP_CALL( SCIPallocBuffer(scip, &matrix) );
1536  SCIP_CALL( initMatrix(scip, matrix, heurdata, heurdata->normalize, &nmaxrows, heurdata->relax, &initialized, &infeasible) );
1537 
1538  /* could not initialize matrix */
1539  if( !initialized || infeasible )
1540  {
1541  SCIPdebugMessage(" MATRIX not initialized -> Execution of heuristic stopped! \n");
1542  goto TERMINATE;
1543  }
1544 
1545  /* the number of discrete LP column variables can be less than the actual number of variables, if, e.g., there
1546  * are nonlinearities in the problem. The heuristic execution can be terminated in that case.
1547  */
1548  if( matrix->ndiscvars < ndiscvars )
1549  {
1550  SCIPdebugMessage(" Not all discrete variables are in the current LP. Shiftandpropagate execution terminated\n");
1551  goto TERMINATE;
1552  }
1553 
1554  assert(nmaxrows > 0);
1555 
1556  eventhdlrdata->matrix = matrix;
1557  eventhdlrdata->heurdata = heurdata;
1558 
1559  SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
1560  SCIPsolSetHeur(sol, heur);
1561 
1562  /* allocate arrays for execution method */
1563  SCIP_CALL( SCIPallocBufferArray(scip, &permutation, ndiscvars) );
1564  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowweights, matrix->nrows) );
1565 
1566  /* allocate necessary memory for best shift search */
1567  SCIP_CALL( SCIPallocBufferArray(scip, &steps, nmaxrows) );
1568  SCIP_CALL( SCIPallocBufferArray(scip, &violationchange, nmaxrows) );
1569 
1570  /* allocate arrays to store information about infeasible rows */
1571  SCIP_CALL( SCIPallocBufferArray(scip, &violatedrows, matrix->nrows) );
1572  SCIP_CALL( SCIPallocBufferArray(scip, &violatedrowpos, matrix->nrows) );
1573 
1574  eventhdlrdata->violatedrows = violatedrows;
1575  eventhdlrdata->violatedrowpos = violatedrowpos;
1576  eventhdlrdata->nviolatedrows = &nviolatedrows;
1577 
1578 
1579 
1580  /* initialize arrays. Before sorting, permutation is the identity permutation */
1581  for( i = 0; i < ndiscvars; ++i )
1582  permutation[i] = i;
1583 
1584  /* initialize row weights */
1585  for( r = 0; r < matrix->nrows; ++r )
1586  {
1587  if( !SCIPisInfinity(scip, -(matrix->lhs[r])) && !SCIPisInfinity(scip, matrix->rhs[r]) )
1588  heurdata->rowweights[r] = DEFAULT_WEIGHT_EQUALITY;
1589  else
1590  heurdata->rowweights[r] = DEFAULT_WEIGHT_INEQUALITY;
1591 
1592  }
1593  colnorms = matrix->colnorms;
1594 
1595  assert(nbinvars >= 0);
1596  assert(nintvars >= 0);
1597 
1598  /* check rows for infeasibility */
1599  checkViolations(scip, matrix, -1, violatedrows, violatedrowpos, &nviolatedrows, heurdata->rowweights, heurdata->updateweights);
1600 
1601  /* allocate memory for violatedvarrows array only if variable ordering relies on it */
1602  if( heurdata->sortvars && (heurdata->sortkey == 't' || heurdata->sortkey == 'v') )
1603  {
1604  SCIP_CALL( SCIPallocBufferArray(scip, &violatedvarrows, ndiscvars) );
1605  BMScopyMemoryArray(violatedvarrows, matrix->violrows, ndiscvars);
1606  }
1607  else
1608  violatedvarrows = NULL;
1609 
1610  /* sort variables w.r.t. the sorting key parameter. Sorting is indirect, all matrix column data
1611  * stays in place, but permutation array gives access to the sorted order of variables
1612  */
1613  if( heurdata->sortvars )
1614  {
1615  switch (heurdata->sortkey)
1616  {
1617  case 'n':
1618  /* variable ordering w.r.t. column norms nonincreasing */
1619  if( heurdata->preferbinaries )
1620  {
1621  if( nbinvars > 0 )
1622  SCIPsortDownRealInt(colnorms, permutation, nbinvars);
1623  if( nbinvars < ndiscvars )
1624  SCIPsortDownRealInt(&colnorms[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1625  }
1626  else
1627  {
1628  SCIPsortDownRealInt(colnorms, permutation, ndiscvars);
1629  }
1630  SCIPdebugMessage("Variables sorted down w.r.t their normalized columns!\n");
1631  break;
1632  case 'u':
1633  /* variable ordering w.r.t. column norms nondecreasing */
1634  if( heurdata->preferbinaries )
1635  {
1636  if( nbinvars > 0 )
1637  SCIPsortRealInt(colnorms, permutation, nbinvars);
1638  if( nbinvars < ndiscvars )
1639  SCIPsortRealInt(&colnorms[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1640  }
1641  else
1642  {
1643  SCIPsortRealInt(colnorms, permutation, ndiscvars);
1644  }
1645  SCIPdebugMessage("Variables sorted w.r.t their normalized columns!\n");
1646  break;
1647  case 'v':
1648  /* variable ordering w.r.t. nonincreasing number of violated rows */
1649  assert(violatedvarrows != NULL);
1650  if( heurdata->preferbinaries )
1651  {
1652  if( nbinvars > 0 )
1653  SCIPsortDownIntInt(violatedvarrows, permutation, nbinvars);
1654  if( nbinvars < ndiscvars )
1655  SCIPsortDownIntInt(&violatedvarrows[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1656  }
1657  else
1658  {
1659  SCIPsortDownIntInt(violatedvarrows, permutation, ndiscvars);
1660  }
1661 
1662  SCIPdebugMessage("Variables sorted down w.r.t their number of currently infeasible rows!\n");
1663  break;
1664  case 't':
1665  /* variable ordering w.r.t. nondecreasing number of violated rows */
1666  assert(violatedvarrows != NULL);
1667  if( heurdata->preferbinaries )
1668  {
1669  if( nbinvars > 0 )
1670  SCIPsortIntInt(violatedvarrows, permutation, nbinvars);
1671  if( nbinvars < ndiscvars )
1672  SCIPsortIntInt(&violatedvarrows[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
1673  }
1674  else
1675  {
1676  SCIPsortIntInt(violatedvarrows, permutation, ndiscvars);
1677  }
1678 
1679  SCIPdebugMessage("Variables sorted (upwards) w.r.t their number of currently infeasible rows!\n");
1680  break;
1681  case 'r':
1682  /* random sorting */
1683  if( heurdata->preferbinaries )
1684  {
1685  if( nbinvars > 0 )
1686  SCIPpermuteIntArray(permutation, 0, nbinvars - 1, &heurdata->randseed);
1687  if( nbinvars < ndiscvars )
1688  SCIPpermuteIntArray(&permutation[nbinvars], nbinvars - 1, ndiscvars - nbinvars - 1, &heurdata->randseed);
1689  }
1690  else
1691  {
1692  SCIPpermuteIntArray(permutation, 0, ndiscvars - 1, &heurdata->randseed);
1693  }
1694  SCIPdebugMessage("Variables permuted randomly!\n");
1695  break;
1696  default:
1697  SCIPdebugMessage("No variable permutation applied\n");
1698  break;
1699  }
1700  }
1701 
1702  /* should binary variables without locks be treated first? */
1703  if( heurdata->binlocksfirst )
1704  {
1705  SCIP_VAR* var;
1706  int nbinwithoutlocks = 0;
1707 
1708  /* count number of binaries without locks */
1709  if( heurdata->preferbinaries )
1710  {
1711  for( c = 0; c < nbinvars; ++c )
1712  {
1713  var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1714  if( SCIPvarGetNLocksUp(var) == 0 || SCIPvarGetNLocksDown(var) == 0 )
1715  ++nbinwithoutlocks;
1716  }
1717  }
1718  else
1719  {
1720  for( c = 0; c < ndiscvars; ++c )
1721  {
1722  var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1723  if( SCIPvarIsBinary(var) )
1724  {
1725  if( SCIPvarGetNLocksUp(var) == 0 || SCIPvarGetNLocksDown(var) == 0 )
1726  ++nbinwithoutlocks;
1727  }
1728  }
1729  }
1730 
1731  if( nbinwithoutlocks > 0 )
1732  {
1733  SCIP_VAR* binvar;
1734  int b = 1;
1735  int tmp;
1736  c = 0;
1737 
1738  /* if c reaches nbinwithoutlocks, then all binary variables without locks were sorted to the beginning of the array */
1739  while( c < nbinwithoutlocks && b < ndiscvars )
1740  {
1741  assert(c < b);
1742  assert(c < ndiscvars);
1743  assert(b < ndiscvars);
1744  var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1745  binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
1746 
1747  /* search for next variable which is not a binary variable without locks */
1748  while( SCIPvarIsBinary(var) && (SCIPvarGetNLocksUp(var) == 0 || SCIPvarGetNLocksDown(var) == 0) )
1749  {
1750  ++c;
1751  if( c >= nbinwithoutlocks )
1752  break;
1753  var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
1754  }
1755  if( c >= nbinwithoutlocks )
1756  break;
1757 
1758  /* search for next binary variable without locks (with position > c) */
1759  if( b <= c )
1760  {
1761  b = c + 1;
1762  binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
1763  }
1764  while( !SCIPvarIsBinary(binvar) || (SCIPvarGetNLocksUp(binvar) > 0 && SCIPvarGetNLocksDown(binvar) > 0) )
1765  {
1766  ++b;
1767  assert(b < ndiscvars);
1768  binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
1769  }
1770 
1771  /* swap the two variables */
1772  tmp = permutation[b];
1773  permutation[b] = permutation[c];
1774  permutation[c] = tmp;
1775 
1776  /* increase counters */
1777  ++c;
1778  ++b;
1779  }
1780  }
1781 
1782 #ifndef NDEBUG
1783  for( c = 0; c < ndiscvars; ++c )
1784  {
1785  assert((c < nbinwithoutlocks) == (SCIPvarIsBinary(SCIPcolGetVar(heurdata->lpcols[permutation[c]]))
1786  && (SCIPvarGetNLocksUp(SCIPcolGetVar(heurdata->lpcols[permutation[c]])) == 0
1787  || SCIPvarGetNLocksDown(SCIPcolGetVar(heurdata->lpcols[permutation[c]])) == 0)));
1788  }
1789 #endif
1790  }
1791 
1792  SCIP_CALL( SCIPallocBufferArray(scip, &eventdatas, matrix->ndiscvars) );
1793  BMSclearMemoryArray(eventdatas, matrix->ndiscvars);
1794 
1795  /* initialize variable events to catch bound changes during propagation */
1796  for( c = 0; c < matrix->ndiscvars; ++c )
1797  {
1798  SCIP_VAR* var;
1799 
1800  var = SCIPcolGetVar(heurdata->lpcols[c]);
1801  assert(var != NULL);
1802  assert(SCIPvarIsIntegral(var));
1803  assert(eventdatas[c] == NULL);
1804 
1805  SCIP_CALL( SCIPallocBuffer(scip, &(eventdatas[c])) ); /*lint !e866*/
1806 
1807  eventdatas[c]->colpos = c;
1808 
1809  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, eventdatas[c], NULL) );
1810  }
1811 
1812  cutoff = FALSE;
1813  lastindexofsusp = -1;
1814  probing = heurdata->probing;
1815  infeasible = FALSE;
1816 
1817  SCIPdebugMessage("SHIFT_AND_PROPAGATE heuristic starts main loop with %d violations and %d remaining variables!\n",
1818  nviolatedrows, ndiscvars);
1819 
1820  assert(matrix->ndiscvars == ndiscvars);
1821 
1822  /* loop over variables, shift them according to shifting criteria and try to reduce the global infeasibility */
1823  for( c = 0; c < ndiscvars; ++c )
1824  {
1825  SCIP_VAR* var;
1826  SCIP_Longint ndomredsfound;
1827  SCIP_Real optimalshiftvalue;
1828  SCIP_Real origsolval;
1829  SCIP_Real lb;
1830  SCIP_Real ub;
1831  TRANSFORMSTATUS status;
1832  int nviolations;
1833  int permutedvarindex;
1834  int j;
1835  SCIP_Bool marksuspicious;
1836 
1837  if( heurdata->selectbest )
1838  { /* search for best candidate */
1839  j = c + 1;
1840  while( j < ndiscvars )
1841  {
1842  /* run through remaining variables and search for best candidate */
1843  if( matrix->violrows[permutation[c]] < matrix->violrows[permutation[j]] )
1844  {
1845  int tmp;
1846  tmp = permutation[c];
1847  permutation[c] = permutation[j];
1848  permutation[j] = tmp;
1849  }
1850  ++j;
1851  }
1852  }
1853  permutedvarindex = permutation[c];
1854  optimalshiftvalue = 0.0;
1855  nviolations = 0;
1856  var = SCIPcolGetVar(heurdata->lpcols[permutedvarindex]);
1857  lb = SCIPvarGetLbLocal(var);
1858  ub = SCIPvarGetUbLocal(var);
1859  assert(SCIPcolGetLPPos(SCIPvarGetCol(var)) >= 0);
1860  assert(SCIPvarIsIntegral(var));
1861 
1862  /* check whether we hit some limit, e.g. the time limit, in between
1863  * since the check itself consumes some time, we only do it every tenth iteration
1864  */
1865  if( c % 10 == 0 && SCIPisStopped(scip) )
1866  goto TERMINATE2;
1867 
1868  /* if propagation is enabled, check if propagation has changed the variables bounds
1869  * and update the transformed upper bound correspondingly
1870  * @todo this should not be necessary
1871  */
1872  if( heurdata->probing )
1873  SCIP_CALL( updateTransformation(scip, matrix, heurdata, permutedvarindex,lb, ub, violatedrows, violatedrowpos,
1874  &nviolatedrows) );
1875 
1876  status = matrix->transformstatus[permutedvarindex];
1877 
1878  SCIPdebugMessage("Variable %s with local bounds [%g,%g], status <%d>, matrix bound <%g>\n",
1879  SCIPvarGetName(var), lb, ub, status, matrix->upperbounds[permutedvarindex]);
1880 
1881  /* ignore variable if propagation fixed it (lb and ub will be zero) */
1882  if( SCIPisFeasZero(scip, matrix->upperbounds[permutedvarindex]) )
1883  {
1884  assert(!SCIPisInfinity(scip, ub));
1885  assert(SCIPisFeasEQ(scip, lb, ub));
1886 
1887  SCIP_CALL( SCIPsetSolVal(scip, sol, var, ub) );
1888 
1889  continue;
1890  }
1891 
1892  marksuspicious = FALSE;
1893 
1894  /* check whether the variable is binary and has no locks in one direction, so that we want to fix it to the
1895  * respective bound (only enabled by parameter)
1896  */
1897  if( heurdata->fixbinlocks && SCIPvarIsBinary(var) && (SCIPvarGetNLocksUp(var) == 0 || SCIPvarGetNLocksDown(var) == 0) )
1898  {
1899  if( SCIPvarGetNLocksUp(var) == 0 )
1900  origsolval = SCIPvarGetUbLocal(var);
1901  else
1902  {
1903  assert(SCIPvarGetNLocksDown(var) == 0);
1904  origsolval = SCIPvarGetLbLocal(var);
1905  }
1906  }
1907  else
1908  {
1909  /* only apply the computationally expensive best shift selection, if there is a violated row left */
1910  if( !heurdata->stopafterfeasible || nviolatedrows > 0 )
1911  {
1912  /* compute optimal shift value for variable */
1913  SCIP_CALL( getOptimalShiftingValue(scip, matrix, permutedvarindex, 1, heurdata->rowweights, steps, violationchange,
1914  &optimalshiftvalue, &nviolations) );
1915  assert(SCIPisFeasGE(scip, optimalshiftvalue, 0.0));
1916 
1917  /* Variables with FREE transform have to be dealt with twice */
1918  if( matrix->transformstatus[permutedvarindex] == TRANSFORMSTATUS_FREE )
1919  {
1920  SCIP_Real downshiftvalue;
1921  int ndownviolations;
1922 
1923  downshiftvalue = 0.0;
1924  ndownviolations = 0;
1925  SCIP_CALL( getOptimalShiftingValue(scip, matrix, permutedvarindex, -1, heurdata->rowweights, steps, violationchange,
1926  &downshiftvalue, &ndownviolations) );
1927 
1928  assert(SCIPisLE(scip, downshiftvalue, 0.0));
1929 
1930  /* compare to positive direction and select the direction which makes more rows feasible */
1931  if( ndownviolations < nviolations )
1932  {
1933  optimalshiftvalue = downshiftvalue;
1934  }
1935  }
1936  }
1937  else
1938  optimalshiftvalue = 0.0;
1939 
1940  /* if zero optimal shift values are forbidden by the user parameter, delay the variable by marking it suspicious */
1941  if( heurdata->nozerofixing && nviolations > 0 && SCIPisFeasZero(scip, optimalshiftvalue) )
1942  marksuspicious = TRUE;
1943 
1944  /* retransform the solution value from the heuristic transformation space */
1945  assert(varIsDiscrete(var, impliscontinuous));
1946  origsolval = retransformVariable(scip, matrix, var, permutedvarindex, optimalshiftvalue);
1947  }
1948  assert(SCIPisFeasGE(scip, origsolval, lb) && SCIPisFeasLE(scip, origsolval, ub));
1949 
1950  /* check if propagation should still be performed */
1951  if( nprobings > DEFAULT_PROPBREAKER )
1952  probing = FALSE;
1953 
1954  /* if propagation is enabled, fix the variable to the new solution value and propagate the fixation
1955  * (to fix other variables and to find out early whether solution is already infeasible)
1956  */
1957  if( !marksuspicious && probing )
1958  {
1959  SCIP_CALL( SCIPnewProbingNode(scip) );
1960  SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) );
1961  ndomredsfound = 0;
1962 
1963  SCIPdebugMessage(" Shift %g(%g originally) is optimal, propagate solution\n", optimalshiftvalue, origsolval);
1964  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
1965 
1966  ++nprobings;
1967  SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
1968  SCIPdebugMessage("Propagation finished! <%" SCIP_LONGINT_FORMAT "> domain reductions %s, <%d> probing depth\n", ndomredsfound, cutoff ? "CUTOFF" : "",
1969  SCIPgetProbingDepth(scip));
1970  }
1971  assert(!cutoff || probing);
1972 
1973  /* propagation led to an empty domain, hence we backtrack and postpone the variable */
1974  if( cutoff )
1975  {
1976  assert(probing);
1977 
1978  ++ncutoffs;
1979 
1980  /* only continue heuristic if number of cutoffs occured so far is reasonably small */
1981  if( heurdata->cutoffbreaker >= 0 && ncutoffs >= ((heurdata->maxcutoffquot * SCIPgetProbingDepth(scip)) + heurdata->cutoffbreaker) )
1982  break;
1983 
1984  cutoff = FALSE;
1985 
1986  /* backtrack to the parent of the current node */
1987  assert(SCIPgetProbingDepth(scip) >= 1);
1989  marksuspicious = TRUE;
1990 
1991  /* if the variable were to be set to one of its bounds, repropagate by tightening this bound by 1.0
1992  * into the direction of the other bound, if possible */
1993  if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), origsolval) )
1994  {
1995  assert(SCIPisFeasGE(scip, SCIPvarGetUbLocal(var), origsolval + 1.0));
1996 
1997  ndomredsfound = 0;
1998  SCIP_CALL( SCIPnewProbingNode(scip) );
1999  SCIP_CALL( SCIPchgVarLbProbing(scip, var, origsolval + 1.0) );
2000  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
2001 
2002  SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
2003 
2004  /* if the tightened bound again leads to a cutoff, both subproblems are proven infeasible and the heuristic
2005  * can be stopped */
2006  if( cutoff )
2007  break;
2008  }
2009  else if( SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), origsolval) )
2010  {
2011  assert(SCIPisFeasLE(scip, SCIPvarGetLbLocal(var), origsolval - 1.0));
2012 
2013  ndomredsfound = 0;
2014 
2015  SCIP_CALL( SCIPnewProbingNode(scip) );
2016  SCIP_CALL( SCIPchgVarUbProbing(scip, var, origsolval - 1.0) );
2017  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
2018 
2019  SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
2020 
2021  /* if the tightened bound again leads to a cutoff, both subproblems are proven infeasible and the heuristic
2022  * can be stopped */
2023  if( cutoff )
2024  break;
2025  }
2026  }
2027 
2028  if( marksuspicious )
2029  {
2030  /* mark the variable as suspicious */
2031  assert(permutedvarindex == permutation[c]);
2032 
2033  ++lastindexofsusp;
2034  assert(lastindexofsusp >= 0 && lastindexofsusp <= c);
2035 
2036  permutation[c] = permutation[lastindexofsusp];
2037  permutation[lastindexofsusp] = permutedvarindex;
2038 
2039  SCIPdebugMessage(" Suspicious variable! Postponed from pos <%d> to position <%d>\n", c, lastindexofsusp);
2040  }
2041  else
2042  {
2043  SCIPdebugMessage("Variable <%d><%s> successfully shifted by value <%g>!\n", permutedvarindex,
2044  SCIPvarGetName(var), optimalshiftvalue);
2045 
2046  /* update solution */
2047  SCIP_CALL( SCIPsetSolVal(scip, sol, var, origsolval) );
2048 
2049  /* only to ensure that some assertions can be made later on */
2050  if( !probing )
2051  {
2052  SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) );
2053  }
2054  }
2055  }
2056  SCIPdebugMessage("Heuristic finished with %d remaining violations and %d remaining variables!\n",
2057  nviolatedrows, lastindexofsusp + 1);
2058 
2059  /* if constructed solution might be feasible, go through the queue of suspicious variables and set the solution
2060  * values
2061  */
2062  if( nviolatedrows == 0 && !cutoff )
2063  {
2064  SCIP_Bool stored;
2065 
2066  for( v = 0; v <= lastindexofsusp; ++v )
2067  {
2068  SCIP_VAR* var;
2069  SCIP_Real origsolval;
2070  int permutedvarindex;
2071 
2072  /* get the column position of the variable */
2073  permutedvarindex = permutation[v];
2074  var = SCIPcolGetVar(heurdata->lpcols[permutedvarindex]);
2075  assert(varIsDiscrete(var, impliscontinuous));
2076 
2077  /* update the transformation of the variable, since the bound might have changed after the last update. */
2078  if( heurdata->probing )
2079  SCIP_CALL( updateTransformation(scip, matrix, heurdata, permutedvarindex, SCIPvarGetLbLocal(var),
2080  SCIPvarGetUbLocal(var), violatedrows, violatedrowpos, &nviolatedrows) );
2081 
2082  /* retransform the solution value from the heuristic transformed space, set the solution value accordingly */
2083  assert(varIsDiscrete(var, impliscontinuous));
2084  origsolval = retransformVariable(scip, matrix, var, permutedvarindex, 0.0);
2085  assert(SCIPisFeasGE(scip, origsolval, SCIPvarGetLbLocal(var))
2086  && SCIPisFeasLE(scip, origsolval, SCIPvarGetUbLocal(var)));
2087  SCIP_CALL( SCIPsetSolVal(scip, sol, var, origsolval) );
2088  SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) ); /* only to ensure that some assertions can be made later */
2089 
2090  SCIPdebugMessage(" Remaining variable <%s> set to <%g>; %d Violations\n", SCIPvarGetName(var), origsolval,
2091  nviolatedrows);
2092  }
2093  /* Fixing of remaining variables led to infeasibility */
2094  if( nviolatedrows > 0 )
2095  goto TERMINATE2;
2096 
2097  stored = TRUE;
2098  /* if the constructed solution might still be extendable to a feasible solution, try this by
2099  * solving the remaining LP
2100  */
2101  if( nlpcols != matrix->ndiscvars )
2102  {
2103  /* case that remaining LP has to be solved */
2104  SCIP_Bool lperror;
2105 
2106 #ifndef NDEBUG
2107  {
2108  SCIP_VAR** vars;
2109 
2110  vars = SCIPgetVars(scip);
2111  assert(vars != NULL);
2112  /* ensure that all discrete variables in the remaining LP are fixed */
2113  for( v = 0; v < ndiscvars; ++v )
2114  {
2115  if( SCIPvarIsInLP(vars[v]) )
2116  assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v])));
2117 
2118  }
2119  }
2120 #endif
2121 
2122  SCIPdebugMessage(" -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
2123 
2124  /* solve LP;
2125  * errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
2126  * hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
2127  */
2128 #ifdef NDEBUG
2129  {
2130  SCIP_RETCODE retstat;
2131  retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
2132  if( retstat != SCIP_OKAY )
2133  {
2134  SCIPwarningMessage(scip, "Error while solving LP in SHIFTANDPROPAGATE heuristic; LP solve terminated with code <%d>\n",
2135  retstat);
2136  }
2137  }
2138 #else
2139  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, NULL) );
2140 #endif
2141 
2142  SCIPdebugMessage(" -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
2143  SCIPdebugMessage(" -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
2144 
2145  /* check if this is a feasible solution */
2146  if( !lperror && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
2147  {
2148  /* copy the current LP solution to the working solution */
2149  SCIP_CALL( SCIPlinkLPSol(scip, sol) );
2150  }
2151  else
2152  stored = FALSE;
2153 
2154  SCIPstatistic( heurdata->lpsolstat = SCIPgetLPSolstat(scip) );
2155  }
2156  /* check solution for feasibility, and add it to solution store if possible.
2157  * Neither integrality nor feasibility of LP rows have to be checked, because they
2158  * are guaranteed by the heuristic at this stage.
2159  */
2160  if( stored )
2161  {
2162 #ifndef NDEBUG
2163  SCIP_CALL( SCIPtrySol(scip, sol, FALSE, TRUE, TRUE, TRUE, &stored) );
2164 #else
2165  /* @todo: maybe bounds don't need to be checked, in this case put an assert concerning stored ?????????? */
2166  SCIP_CALL( SCIPtrySol(scip, sol, FALSE, TRUE, FALSE, FALSE, &stored) );
2167 #endif
2168  if( stored )
2169  {
2170  SCIPdebugMessage("found feasible shifted solution:\n");
2171  SCIPdebug( SCIP_CALL( SCIPprintSol(scip, sol, NULL, FALSE) ) );
2172  *result = SCIP_FOUNDSOL;
2173  SCIPstatisticMessage(" Shiftandpropagate solution value: %16.9g \n", SCIPgetSolOrigObj(scip, sol));
2174  }
2175  }
2176  }
2177  else
2178  {
2179  SCIPdebugMessage("Solution constructed by heuristic is already known to be infeasible\n");
2180  }
2181 
2182  SCIPstatistic( heurdata->nremainingviols = nviolatedrows; );
2183 
2184  TERMINATE2:
2185  /* free allocated memory in reverse order of allocation */
2186  for( c = matrix->ndiscvars - 1; c >= 0; --c )
2187  {
2188  SCIP_VAR* var;
2189 
2190  var = SCIPcolGetVar(heurdata->lpcols[c]);
2191  assert(var != NULL);
2192  assert(eventdatas[c] != NULL);
2193 
2194  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, eventdatas[c], -1) );
2195  SCIPfreeBuffer(scip, &(eventdatas[c]));
2196  }
2197  SCIPfreeBufferArray(scip, &eventdatas);
2198 
2199  if( violatedvarrows != NULL )
2200  {
2201  assert(heurdata->sortkey == 'v' || heurdata->sortkey == 't');
2202  SCIPfreeBufferArray(scip, &violatedvarrows);
2203  }
2204  /* free all allocated memory */
2205  SCIPfreeBufferArray(scip, &violatedrowpos);
2206  SCIPfreeBufferArray(scip, &violatedrows);
2207  SCIPfreeBufferArray(scip, &violationchange);
2208  SCIPfreeBufferArray(scip, &steps);
2209  SCIPfreeBufferArray(scip, &heurdata->rowweights);
2210  SCIPfreeBufferArray(scip, &permutation);
2211  SCIP_CALL( SCIPfreeSol(scip, &sol) );
2212 
2213  eventhdlrdata->nviolatedrows = NULL;
2214  eventhdlrdata->violatedrowpos = NULL;
2215  eventhdlrdata->violatedrows = NULL;
2216 
2217  TERMINATE:
2218  /* terminate probing mode and free the remaining memory */
2219  SCIPstatistic(
2220  heurdata->ncutoffs += ncutoffs;
2221  heurdata->nprobings += nprobings;
2222  heurdata->nlpiters = SCIPgetNLPIterations(scip) - heurdata->nlpiters;
2223  );
2224 
2225  SCIP_CALL( SCIPendProbing(scip) );
2226  SCIPfreeBufferArray(scip, &heurdata->lpcols);
2227  freeMatrix(scip, &matrix);
2228  eventhdlrdata->matrix = NULL;
2229 
2230  return SCIP_OKAY;
2231 }
2232 
2233 /** event handler execution method for the heuristic which catches all
2234  * events in which a lower or upper bound were tightened */
2235 static
2236 SCIP_DECL_EVENTEXEC(eventExecShiftandpropagate)
2237 { /*lint --e{715}*/
2238  SCIP_EVENTHDLRDATA* eventhdlrdata;
2239  SCIP_VAR* var;
2240  SCIP_COL* col;
2241  SCIP_Real lb;
2242  SCIP_Real ub;
2243  int colpos;
2244  CONSTRAINTMATRIX* matrix;
2245  SCIP_HEURDATA* heurdata;
2246 
2247  assert(scip != NULL);
2248  assert(eventhdlr != NULL);
2249  assert(strcmp(EVENTHDLR_NAME, SCIPeventhdlrGetName(eventhdlr)) == 0);
2250 
2251  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2252  assert(eventhdlrdata != NULL);
2253 
2254  matrix = eventhdlrdata->matrix;
2255 
2256  heurdata = eventhdlrdata->heurdata;
2257  assert(heurdata != NULL && heurdata->lpcols != NULL);
2258 
2259  colpos = eventdata->colpos;
2260 
2261  assert(0 <= colpos && colpos < matrix->ndiscvars);
2262 
2263  col = heurdata->lpcols[colpos];
2264  var = SCIPcolGetVar(col);
2265 
2266  lb = SCIPvarGetLbLocal(var);
2267  ub = SCIPvarGetUbLocal(var);
2268 
2269  SCIP_CALL( updateTransformation(scip, matrix, eventhdlrdata->heurdata, colpos, lb, ub, eventhdlrdata->violatedrows,
2270  eventhdlrdata->violatedrowpos, eventhdlrdata->nviolatedrows) );
2271 
2272  return SCIP_OKAY;
2273 }
2274 
2275 /*
2276  * primal heuristic specific interface methods
2277  */
2278 
2279 /** creates the shiftandpropagate primal heuristic and includes it in SCIP */
2281  SCIP* scip /**< SCIP data structure */
2282  )
2283 {
2284  SCIP_HEURDATA* heurdata;
2285  SCIP_HEUR* heur;
2286  SCIP_EVENTHDLRDATA* eventhandlerdata;
2287  SCIP_EVENTHDLR* eventhdlr;
2288 
2289 
2290  SCIP_CALL( SCIPallocMemory(scip, &eventhandlerdata) );
2291  eventhandlerdata->matrix = NULL;
2292 
2293  eventhdlr = NULL;
2295  eventExecShiftandpropagate, eventhandlerdata) );
2296  assert(eventhdlr != NULL);
2297 
2298  /* create Shiftandpropagate primal heuristic data */
2299  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
2300  heurdata->rowweights = NULL;
2301  heurdata->nlpcols = 0;
2302  heurdata->eventhdlr = eventhdlr;
2303 
2304  /* include primal heuristic */
2305  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
2307  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecShiftandpropagate, heurdata) );
2308 
2309  assert(heur != NULL);
2310 
2311  /* set non-NULL pointers to callback methods */
2312  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyShiftandpropagate) );
2313  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeShiftandpropagate) );
2314  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitShiftandpropagate) );
2315  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitShiftandpropagate) );
2316 
2317 
2318  /* add shiftandpropagate primal heuristic parameters */
2319  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nproprounds", "The number of propagation rounds used for each propagation",
2320  &heurdata->nproprounds, TRUE, DEFAULT_NPROPROUNDS, -1, 1000, NULL, NULL) );
2321  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/relax", "Should continuous variables be relaxed?",
2322  &heurdata->relax, TRUE, DEFAULT_RELAX, NULL, NULL) );
2323  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/probing", "Should domains be reduced by probing?",
2324  &heurdata->probing, TRUE, DEFAULT_PROBING, NULL, NULL) );
2325  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/onlywithoutsol", "Should heuristic only be executed if no primal solution was found, yet?",
2326  &heurdata->onlywithoutsol, TRUE, DEFAULT_ONLYWITHOUTSOL, NULL, NULL) );
2327  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/cutoffbreaker", "The number of cutoffs before heuristic stops",
2328  &heurdata->cutoffbreaker, TRUE, DEFAULT_CUTOFFBREAKER, -1, 1000000, NULL, NULL) );
2329  SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/sortkey", "the key for variable sorting: (n)orms down, norms (u)p, (v)iolations down, viola(t)ions up, or (r)andom",
2330  &heurdata->sortkey, TRUE, DEFAULT_SORTKEY, SORTKEYS, NULL, NULL) );
2331  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/sortvars", "Should variables be sorted for the heuristic?",
2332  &heurdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL));
2333  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/collectstats", "should variable statistics be collected during probing?",
2334  &heurdata->collectstats, TRUE, DEFAULT_COLLECTSTATS, NULL, NULL) );
2335  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/stopafterfeasible", "Should the heuristic stop calculating optimal shift values when no more rows are violated?",
2336  &heurdata->stopafterfeasible, TRUE, DEFAULT_STOPAFTERFEASIBLE, NULL, NULL) );
2337  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/preferbinaries", "Should binary variables be shifted first?",
2338  &heurdata->preferbinaries, TRUE, DEFAULT_PREFERBINARIES, NULL, NULL) );
2339  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/nozerofixing", "should variables with a zero shifting value be delayed instead of being fixed?",
2340  &heurdata->nozerofixing, TRUE, DEFAULT_NOZEROFIXING, NULL, NULL) );
2341  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/fixbinlocks", "should binary variables with no locks in one direction be fixed to that direction?",
2342  &heurdata->fixbinlocks, TRUE, DEFAULT_FIXBINLOCKS, NULL, NULL) );
2343  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/binlocksfirst", "should binary variables with no locks be preferred in the ordering?",
2344  &heurdata->binlocksfirst, TRUE, DEFAULT_BINLOCKSFIRST, NULL, NULL) );
2345  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/normalize", "should coefficients and left/right hand sides be normalized by max row coeff?",
2346  &heurdata->normalize, TRUE, DEFAULT_NORMALIZE, NULL, NULL) );
2347  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/updateweights", "should row weight be increased every time the row is violated?",
2348  &heurdata->updateweights, TRUE, DEFAULT_UPDATEWEIGHTS, NULL, NULL) );
2349  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/impliscontinuous", "should implicit integer variables be treated as continuous variables?",
2350  &heurdata->impliscontinuous, TRUE, DEFAULT_IMPLISCONTINUOUS, NULL, NULL) );
2351  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/selectbest", "should the heuristic choose the best candidate in every round? (set to FALSE for static order)?",
2352  &heurdata->selectbest, TRUE, DEFAULT_SELECTBEST, NULL, NULL) );
2353  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxcutoffquot", "maximum percentage of allowed cutoffs before stopping the heuristic",
2354  &heurdata->maxcutoffquot, TRUE, DEFAULT_MAXCUTOFFQUOT, 0.0, 2.0, NULL, NULL) );
2355 
2356  return SCIP_OKAY;
2357 }
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:32398
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10735
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
#define DEFAULT_FIXBINLOCKS
preroot heuristic that alternatingly fixes variables and propagates domains
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41256
void SCIPdisableVarHistory(SCIP *scip)
Definition: scip.c:23151
static void relaxVar(SCIP *scip, SCIP_VAR *var, CONSTRAINTMATRIX *matrix, SCIP_Bool normalize)
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
#define HEUR_USESSUBSCIP
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7266
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:31860
#define DEFAULT_SORTKEY
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16521
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1220
#define HEUR_DESC
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41528
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:37064
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10690
static SCIP_DECL_HEUREXEC(heurExecShiftandpropagate)
void SCIPenableVarHistory(SCIP *scip)
Definition: scip.c:23132
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17011
#define HEUR_NAME
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41640
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18914
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18860
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16965
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:34453
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:129
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:18747
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:7221
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:18849
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:32162
#define FALSE
Definition: def.h:53
#define DEFAULT_CUTOFFBREAKER
static SCIP_DECL_EVENTEXEC(eventExecShiftandpropagate)
#define DEFAULT_RELAX
static void freeMatrix(SCIP *scip, CONSTRAINTMATRIX **matrix)
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7747
#define TRUE
Definition: def.h:52
#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
#define HEUR_DISPCHAR
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41580
#define DEFAULT_SORTVARS
#define DEFAULT_UPDATEWEIGHTS
#define DEFAULT_BINLOCKSFIRST
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
void SCIPsortDownIntInt(int *intarray1, int *intarray2, int len)
#define SCIPfreeBuffer(scip, ptr)
Definition: scip.h:20424
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26426
#define SCIPdebugMessage
Definition: pub_message.h:77
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20414
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:16680
#define DEFAULT_WEIGHT_INEQUALITY
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18880
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:10915
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
#define DEFAULT_RANDSEED
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:99
#define HEUR_TIMING
SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28050
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41652
#define DEFAULT_ONLYWITHOUTSOL
#define HEUR_PRIORITY
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
Definition: scip.c:26659
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34676
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.c:3516
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16460
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.c:3542
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16532
static SCIP_DECL_HEUREXIT(heurExitShiftandpropagate)
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36232
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition: scip.c:26359
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:18725
#define DEFAULT_NORMALIZE
SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
Definition: scip.c:26382
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:18783
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41592
static SCIP_Bool varIsDiscrete(SCIP_VAR *var, SCIP_Bool impliscontinuous)
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20355
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition: lp.c:18704
#define SCIPallocBuffer(scip, ptr)
Definition: scip.h:20412
#define DEFAULT_STOPAFTERFEASIBLE
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20426
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18924
#define DEFAULT_SELECTBEST
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
static void transformVariable(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int colpos)
static SCIP_Bool colIsDiscrete(SCIP_COL *col, SCIP_Bool impliscontinuous)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41604
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:31833
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41206
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:33612
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition: sol.c:2234
#define SORTKEYS
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41515
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
#define DEFAULT_PREFERBINARIES
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16669
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition: scip.c:26737
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41245
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define SCIP_CALL(x)
Definition: def.h:263
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:288
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:26341
#define DEFAULT_NOZEROFIXING
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:18772
static SCIP_DECL_HEURINIT(heurInitShiftandpropagate)
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18973
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41554
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
struct ConstraintMatrix CONSTRAINTMATRIX
#define EVENTHDLR_NAME
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17021
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:50
#define HEUR_MAXDEPTH
#define HEUR_FREQOFS
SCIP_RETCODE SCIPincludeHeurShiftandpropagate(SCIP *scip)
#define DEFAULT_NPROPROUNDS
#define MAX(x, y)
Definition: tclique_def.h:75
enum TransformStatus TRANSFORMSTATUS
#define DEFAULT_MAXCUTOFFQUOT
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
Definition: scip.c:32025
#define DEFAULT_IMPLISCONTINUOUS
static SCIP_RETCODE initMatrix(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, SCIP_Bool normalize, int *nmaxrows, SCIP_Bool relax, SCIP_Bool *initialized, SCIP_Bool *infeasible)
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20373
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:31763
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
#define DEFAULT_WEIGHT_EQUALITY
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:31895
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20357
#define HEUR_FREQ
static void getColumnData(CONSTRAINTMATRIX *matrix, int colindex, SCIP_Real **valpointer, int **indexpointer, int *ncolvals)
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34258
static void checkRowViolation(SCIP *scip, CONSTRAINTMATRIX *matrix, int rowindex, int *violatedrows, int *violatedrowpos, int *nviolatedrows, int *rowweights, SCIP_Bool updateweights)
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:7314
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:7298
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36278
static void checkViolations(SCIP *scip, CONSTRAINTMATRIX *matrix, int colidx, int *violatedrows, int *violatedrowpos, int *nviolatedrows, int *rowweights, SCIP_Bool updateweights)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16506
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20371
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16955
static SCIP_DECL_HEURCOPY(heurCopyShiftandpropagate)
static SCIP_Real retransformVariable(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_VAR *var, int varindex, SCIP_Real solvalue)
static SCIP_RETCODE updateTransformation(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int varindex, SCIP_Real lb, SCIP_Real ub, int *violatedrows, int *violatedrowpos, int *nviolatedrows)
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18870
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
static void getRowData(CONSTRAINTMATRIX *matrix, int rowindex, SCIP_Real **valpointer, SCIP_Real *lhs, SCIP_Real *rhs, int **indexpointer, int *nrowvals)
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:31962
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41541
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:7282
#define SCIPstatistic(x)
Definition: pub_message.h:101
#define SCIP_Real
Definition: def.h:124
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:31800
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3626
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:31928
SCIP_RETCODE SCIPflushLP(SCIP *scip)
Definition: scip.c:26406
void SCIPpermuteIntArray(int *array, int begin, int end, unsigned int *randseed)
Definition: misc.c:7850
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:28321
static SCIP_DECL_SORTPTRCOMP(heurSortColsShiftandpropagate)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41567
#define SCIP_Longint
Definition: def.h:109
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:19103
#define EVENTHDLR_DESC
#define DEFAULT_PROBING
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1058
#define DEFAULT_PROPBREAKER
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:58
#define DEFAULT_COLLECTSTATS
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18684
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:35377
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:18793
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.c:3598
#define SCIPABORT()
Definition: def.h:235
static SCIP_DECL_HEURFREE(heurFreeShiftandpropagate)
int SCIPgetNLPRows(SCIP *scip)
Definition: scip.c:26793
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:35827
static SCIP_RETCODE getOptimalShiftingValue(SCIP *scip, CONSTRAINTMATRIX *matrix, int varindex, int direction, int *rowweights, SCIP_Real *steps, int *violationchange, SCIP_Real *beststep, int *rowviolations)
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:35007
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:34217