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