Scippy

SCIP

Solving Constraint Integer Programs

heur_zirounding.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_zirounding.c
17  * @brief zirounding primal heuristic
18  * @author Gregor Hendel
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 
26 #include "scip/heur_zirounding.h"
27 #include "scip.h"
28 
29 #define HEUR_NAME "zirounding"
30 #define HEUR_DESC "LP rounding heuristic as suggested by C. Wallace taking row slacks and bounds into account"
31 #define HEUR_DISPCHAR 'z'
32 #define HEUR_PRIORITY -500
33 #define HEUR_FREQ 1
34 #define HEUR_FREQOFS 0
35 #define HEUR_MAXDEPTH -1
36 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
37 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
38 
39 #define DEFAULT_MAXROUNDINGLOOPS 2 /**< delimits the number of main loops, can be set to -1 for no limit */
40 #define DEFAULT_STOPZIROUND TRUE /**< deactivation check is enabled by default */
41 #define DEFAULT_STOPPERCENTAGE 0.02 /**< the tolerance percentage after which zirounding will not be executed anymore */
42 #define DEFAULT_MINSTOPNCALLS 1000 /**< number of heuristic calls before deactivation check */
43 
44 
45 /*
46  * Data structures
47  */
48 
49 /** primal heuristic data */
50 struct SCIP_HeurData
51 {
52  SCIP_SOL* sol; /**< working solution */
53  SCIP_Longint lastlp; /**< the number of the last LP for which ZIRounding was called */
54  int maxroundingloops; /**< limits rounding loops in execution */
55  SCIP_Bool stopziround; /**< sets deactivation check */
56  SCIP_Real stoppercentage; /**< threshold for deactivation check */
57  int minstopncalls; /**< number of heuristic calls before deactivation check */
58 };
59 
61 {
64 };
65 typedef enum Direction DIRECTION;
66 
67 /*
68  * Local methods
69  */
70 
71 /** returns the fractionality of a value x, which is calculated as zivalue(x) = min(x-floor(x), ceil(x)-x) */
72 static
74  SCIP* scip, /**< pointer to current SCIP data structure */
75  SCIP_Real val /**< the value for which the fractionality should be computed */
76  )
77 {
78  SCIP_Real upgap; /* the gap between val and ceil(val) */
79  SCIP_Real downgap; /* the gap between val and floor(val) */
80 
81  assert(scip != NULL);
82 
83  upgap = SCIPfeasCeil(scip, val) - val;
84  downgap = val - SCIPfeasFloor(scip, val);
85 
86  return MIN(upgap, downgap);
87 }
88 
89 /** determines shifting bounds for variable */
90 static
92  SCIP* scip, /**< pointer to current SCIP data structure */
93  SCIP_VAR* var, /**< the variable for which lb and ub have to be calculated */
94  SCIP_Real currentvalue, /**< the current value of var in the working solution */
95  SCIP_Real* upperbound, /**< pointer to store the calculated upper bound on the variable shift */
96  SCIP_Real* lowerbound, /**< pointer to store the calculated lower bound on the variable shift */
97  SCIP_Real* upslacks, /**< array that contains the slacks between row activities and the right hand sides of the rows */
98  SCIP_Real* downslacks, /**< array that contains lhs slacks */
99  int nslacks, /**< current number of slacks */
100  SCIP_Bool* numericalerror /**< flag to determine whether a numerical error occurred */
101  )
102 {
103  SCIP_COL* col;
104  SCIP_ROW** colrows;
105  SCIP_Real* colvals;
106  int ncolvals;
107  int i;
108 
109  assert(scip != NULL);
110  assert(var != NULL);
111  assert(upslacks != NULL);
112  assert(downslacks != NULL);
113  assert(upperbound != NULL);
114  assert(lowerbound != NULL);
115 
116  /* get the column associated to the variable, the nonzero rows and the nonzero coefficients */
117  col = SCIPvarGetCol(var);
118  colrows = SCIPcolGetRows(col);
119  colvals = SCIPcolGetVals(col);
120  ncolvals = SCIPcolGetNLPNonz(col);
121 
122  /* only proceed, when variable has nonzero coefficients */
123  if( ncolvals == 0 )
124  return;
125 
126  assert(colvals != NULL);
127  assert(colrows != NULL);
128 
129  /* initialize the bounds on the shift to be the gap of the current solution value to the bounds of the variable */
130  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) )
131  *upperbound = SCIPinfinity(scip);
132  else
133  *upperbound = SCIPvarGetUbGlobal(var) - currentvalue;
134 
135  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)) )
136  *lowerbound = SCIPinfinity(scip);
137  else
138  *lowerbound = currentvalue - SCIPvarGetLbGlobal(var);
139 
140  /* go through every nonzero row coefficient corresponding to var to determine bounds for shifting
141  * in such a way that shifting maintains feasibility in every LP row.
142  * a lower or upper bound as it is calculated in zirounding always has to be >= 0.0.
143  * if one of these values is significantly < 0.0, this will cause the abort of execution of the heuristic so that
144  * infeasible solutions are avoided
145  */
146  for( i = 0; i < ncolvals && (*lowerbound > 0.0 || *upperbound > 0.0); ++i )
147  {
148  SCIP_ROW* row;
149  int rowpos;
150 
151  row = colrows[i];
152  rowpos = SCIProwGetLPPos(row);
153 
154  /* the row might currently not be in the LP, ignore it! */
155  if( rowpos == -1 )
156  continue;
157 
158  assert(0 <= rowpos && rowpos < nslacks);
159 
160  /* all bounds and slacks as they are calculated in zirounding always have to be greater equal zero.
161  * It might however be due to numerical issues, e.g. with scaling, that they are not. Better abort in this case.
162  */
163  if( SCIPisFeasLT(scip, *lowerbound, 0.0) || SCIPisFeasLT(scip, *upperbound, 0.0)
164  || SCIPisFeasLT(scip, upslacks[rowpos], 0.0) || SCIPisFeasLT(scip, downslacks[rowpos] , 0.0) )
165  {
166  *numericalerror = TRUE;
167  return;
168  }
169 
170  SCIPdebugMessage("colval: %15.8g, downslack: %15.8g, upslack: %5.2g, lb: %5.2g, ub: %5.2g\n", colvals[i], downslacks[rowpos], upslacks[rowpos],
171  *lowerbound, *upperbound);
172 
173  /* if coefficient > 0, rounding up might violate up slack and rounding down might violate down slack
174  * thus search for the minimum so that no constraint is violated; vice versa for coefficient < 0
175  */
176  if( colvals[i] > 0 )
177  {
178  if( !SCIPisInfinity(scip, upslacks[rowpos]) )
179  {
180  SCIP_Real upslack;
181  upslack = MAX(upslacks[rowpos], 0.0); /* avoid errors due to numerically slightly infeasible rows */
182  *upperbound = MIN(*upperbound, upslack/colvals[i]);
183  }
184 
185  if( !SCIPisInfinity(scip, downslacks[rowpos]) )
186  {
187  SCIP_Real downslack;
188  downslack = MAX(downslacks[rowpos], 0.0); /* avoid errors due to numerically slightly infeasible rows */
189  *lowerbound = MIN(*lowerbound, downslack/colvals[i]);
190  }
191  }
192  else
193  {
194  assert(colvals[i] != 0.0);
195 
196  if( !SCIPisInfinity(scip, upslacks[rowpos]) )
197  {
198  SCIP_Real upslack;
199  upslack = MAX(upslacks[rowpos], 0.0); /* avoid errors due to numerically slightly infeasible rows */
200  *lowerbound = MIN(*lowerbound, -upslack/colvals[i]);
201  }
202 
203  if( !SCIPisInfinity(scip, downslacks[rowpos]) )
204  {
205  SCIP_Real downslack;
206  downslack = MAX(downslacks[rowpos], 0.0); /* avoid errors due to numerically slightly infeasible rows */
207  *upperbound = MIN(*upperbound, -downslack/colvals[i]);
208  }
209  }
210  }
211 }
212 
213 /** when a variable is shifted, the activities and slacks of all rows it appears in have to be updated */
214 static
216  SCIP* scip, /**< pointer to current SCIP data structure */
217  SCIP_SOL* sol, /**< working solution */
218  SCIP_VAR* var, /**< pointer to variable to be modified */
219  SCIP_Real shiftvalue, /**< the value by which the variable is shifted */
220  SCIP_Real* upslacks, /**< upslacks of all rows the variable appears in */
221  SCIP_Real* downslacks, /**< downslacks of all rows the variable appears in */
222  SCIP_Real* activities, /**< activities of the LP rows */
223  SCIP_VAR** slackvars, /**< the slack variables for equality rows */
224  SCIP_Real* slackcoeffs, /**< the slack variable coefficients */
225  int nslacks /**< size of the arrays */
226  )
227 {
228  SCIP_COL* col; /* the corresponding column of variable var */
229  SCIP_ROW** rows; /* pointer to the nonzero coefficient rows for variable var */
230  int nrows; /* the number of nonzeros */
231  SCIP_Real* colvals; /* array to store the nonzero coefficients */
232  int i;
233 
234  assert(scip != NULL);
235  assert(sol != NULL);
236  assert(var != NULL);
237  assert(upslacks != NULL);
238  assert(downslacks != NULL);
239  assert(activities != NULL);
240  assert(nslacks >= 0);
241 
242  col = SCIPvarGetCol(var);
243  assert(col != NULL);
244 
245  rows = SCIPcolGetRows(col);
246  nrows = SCIPcolGetNLPNonz(col);
247  colvals = SCIPcolGetVals(col);
248  assert(nrows == 0 || (rows != NULL && colvals != NULL));
249 
250  /* go through all rows the shifted variable appears in */
251  for( i = 0; i < nrows; ++i )
252  {
253  int rowpos;
254 
255  rowpos = SCIProwGetLPPos(rows[i]);
256  assert(-1 <= rowpos && rowpos < nslacks);
257 
258  /* if the row is in the LP, update its activity, up and down slack */
259  if( rowpos >= 0 )
260  {
261  SCIP_Real val;
262 
263  val = colvals[i] * shiftvalue;
264 
265  /* if the row is an equation, we update its slack variable instead of its activities */
266  if( SCIPisFeasEQ(scip, SCIProwGetLhs(rows[i]), SCIProwGetRhs(rows[i])) )
267  {
268  SCIP_Real slackvarshiftval;
269  SCIP_Real slackvarsolval;
270 
271  assert(slackvars[rowpos] != NULL);
272  assert(!SCIPisFeasZero(scip, slackcoeffs[rowpos]));
273 
274  slackvarsolval = SCIPgetSolVal(scip, sol, slackvars[rowpos]);
275  slackvarshiftval = -val / slackcoeffs[rowpos];
276 
277  assert(SCIPisFeasGE(scip, slackvarsolval + slackvarshiftval, SCIPvarGetLbGlobal(slackvars[rowpos])));
278  assert(SCIPisFeasLE(scip, slackvarsolval + slackvarshiftval, SCIPvarGetUbGlobal(slackvars[rowpos])));
279 
280  SCIP_CALL( SCIPsetSolVal(scip, sol, slackvars[rowpos], slackvarsolval + slackvarshiftval) );
281  }
282  else if( !SCIPisInfinity(scip, -activities[rowpos]) && !SCIPisInfinity(scip, activities[rowpos]) )
283  activities[rowpos] += val;
284 
285  /* the slacks of the row now can be updated independently of its type */
286  if( !SCIPisInfinity(scip, upslacks[rowpos]) )
287  upslacks[rowpos] -= val;
288  if( !SCIPisInfinity(scip, -downslacks[rowpos]) )
289  downslacks[rowpos] += val;
290 
291  assert(!SCIPisFeasNegative(scip, upslacks[rowpos]));
292  assert(!SCIPisFeasNegative(scip, downslacks[rowpos]));
293  }
294  }
295  return SCIP_OKAY;
296 }
297 
298 /** finds a continuous slack variable for an equation row, NULL if none exists */
299 static
301  SCIP* scip, /**< pointer to current SCIP data structure */
302  SCIP_ROW* row, /**< the row for which a slack variable is searched */
303  SCIP_VAR** varpointer, /**< pointer to store the slack variable */
304  SCIP_Real* coeffpointer /**< pointer to store the coefficient of the slack variable */
305  )
306 {
307  int v;
308  SCIP_COL** rowcols;
309  SCIP_Real* rowvals;
310  int nrowvals;
311 
312  assert(row != NULL);
313  assert(varpointer != NULL);
314  assert(coeffpointer != NULL);
315 
316  rowcols = SCIProwGetCols(row);
317  rowvals = SCIProwGetVals(row);
318  nrowvals = SCIProwGetNNonz(row);
319 
320  assert(nrowvals == 0 || rowvals != NULL);
321  assert(nrowvals == 0 || rowcols != NULL);
322 
323  /* iterate over the row variables. Stop after the first unfixed continuous variable was found. */
324  for( v = nrowvals - 1; v >= 0; --v )
325  {
326  SCIP_VAR* colvar;
327 
328  assert(rowcols[v] != NULL);
329  if( SCIPcolGetLPPos(rowcols[v]) == -1 )
330  continue;
331 
332  colvar = SCIPcolGetVar(rowcols[v]);
333 
335  && !SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(colvar), SCIPvarGetUbGlobal(colvar))
336  && SCIPcolGetNLPNonz(rowcols[v]) == 1 )
337  {
338  SCIPdebugMessage(" slack variable for row %s found: %s\n", SCIProwGetName(row), SCIPvarGetName(colvar));
339 
340  *coeffpointer = rowvals[v];
341  *varpointer = colvar;
342 
343  return;
344  }
345  }
346 
347  *varpointer = NULL;
348  *coeffpointer = 0.0;
349 
350  SCIPdebugMessage("No slack variable for row %s found. \n", SCIProwGetName(row));
351 }
352 
353 /*
354  * Callback methods of primal heuristic
355  */
356 
357 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
358 static
359 SCIP_DECL_HEURCOPY(heurCopyZirounding)
360 { /*lint --e{715}*/
361  assert(scip != NULL);
362  assert(heur != NULL);
363  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
364 
365  /* call inclusion method of primal heuristic */
367 
368  return SCIP_OKAY;
369 }
370 
371 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
372 static
373 SCIP_DECL_HEURFREE(heurFreeZirounding)
374 { /*lint --e{715}*/
375  SCIP_HEURDATA* heurdata;
376 
377  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
378 
379  heurdata = SCIPheurGetData(heur);
380  assert(heurdata != NULL);
381 
382  /* free heuristic data */
383  SCIPfreeMemory(scip, &heurdata);
384  SCIPheurSetData(heur, NULL);
385 
386  return SCIP_OKAY;
387 }
388 
389 /** initialization method of primal heuristic (called after problem was transformed) */
390 static
391 SCIP_DECL_HEURINIT(heurInitZirounding)
392 { /*lint --e{715}*/
393  SCIP_HEURDATA* heurdata;
394 
395  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
396 
397  heurdata = SCIPheurGetData(heur);
398  assert(heurdata != NULL);
399 
400  /* create working solution */
401  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
402 
403  return SCIP_OKAY;
404 }
405 
406 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
407 static
408 SCIP_DECL_HEUREXIT(heurExitZirounding) /*lint --e{715}*/
409 { /*lint --e{715}*/
410  SCIP_HEURDATA* heurdata;
411 
412  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
413 
414  heurdata = SCIPheurGetData(heur);
415  assert(heurdata != NULL);
416 
417  /* free working solution */
418  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
419 
420  return SCIP_OKAY;
421 }
422 
423 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
424 static
425 SCIP_DECL_HEURINITSOL(heurInitsolZirounding)
426 { /*lint --e{715}*/
427  SCIP_HEURDATA* heurdata;
428 
429  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
430 
431  heurdata = SCIPheurGetData(heur);
432  assert(heurdata != NULL);
433 
434  heurdata->lastlp = -1;
435 
436  return SCIP_OKAY;
437 }
438 
439 
440 /** execution method of primal heuristic */
441 static
442 SCIP_DECL_HEUREXEC(heurExecZirounding)
443 { /*lint --e{715}*/
444  SCIP_HEURDATA* heurdata;
445  SCIP_SOL* sol;
446  SCIP_VAR** lpcands;
447  SCIP_VAR** zilpcands;
448 
449  SCIP_VAR** slackvars;
450  SCIP_Real* upslacks;
451  SCIP_Real* downslacks;
452  SCIP_Real* activities;
453  SCIP_Real* slackvarcoeffs;
454  SCIP_Bool* rowneedsslackvar;
455 
456  SCIP_ROW** rows;
457  SCIP_Real* lpcandssol;
458  SCIP_Real* solarray;
459 
460  SCIP_Longint nlps;
461  int currentlpcands;
462  int nlpcands;
463  int nimplfracs;
464  int i;
465  int c;
466  int nslacks;
467  int nroundings;
468 
469  SCIP_RETCODE retcode;
470 
471  SCIP_Bool improvementfound;
472  SCIP_Bool numericalerror;
473 
474  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
475  assert(result != NULL);
476  assert(SCIPhasCurrentNodeLP(scip));
477 
478  *result = SCIP_DIDNOTRUN;
479 
480  /* do not call heuristic of node was already detected to be infeasible */
481  if( nodeinfeasible )
482  return SCIP_OKAY;
483 
484  /* only call heuristic if an optimal LP-solution is at hand */
486  return SCIP_OKAY;
487 
488  /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
490  return SCIP_OKAY;
491 
492  /* get heuristic data */
493  heurdata = SCIPheurGetData(heur);
494  assert(heurdata != NULL);
495 
496  /* Do not call heuristic if deactivation check is enabled and percentage of found solutions in relation
497  * to number of calls falls below heurdata->stoppercentage */
498  if( heurdata->stopziround && SCIPheurGetNCalls(heur) >= heurdata->minstopncalls
499  && SCIPheurGetNSolsFound(heur)/(SCIP_Real)SCIPheurGetNCalls(heur) < heurdata->stoppercentage )
500  return SCIP_OKAY;
501 
502  /* assure that heuristic has not already been called after the last LP had been solved */
503  nlps = SCIPgetNLPs(scip);
504  if( nlps == heurdata->lastlp )
505  return SCIP_OKAY;
506 
507  heurdata->lastlp = nlps;
508 
509  /* get fractional variables */
510  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL, &nimplfracs) );
511  nlpcands = nlpcands + nimplfracs;
512  /* make sure that there is at least one fractional variable that should be integral */
513  if( nlpcands == 0 )
514  return SCIP_OKAY;
515 
516  assert(nlpcands > 0);
517  assert(lpcands != NULL);
518  assert(lpcandssol != NULL);
519 
520  /* get LP rows data */
521  rows = SCIPgetLPRows(scip);
522  nslacks = SCIPgetNLPRows(scip);
523 
524  /* cannot do anything if LP is empty */
525  if( nslacks == 0 )
526  return SCIP_OKAY;
527 
528  assert(rows != NULL);
529  assert(nslacks > 0);
530 
531  /* get the working solution from heuristic's local data */
532  sol = heurdata->sol;
533  assert(sol != NULL);
534 
535  *result = SCIP_DIDNOTFIND;
536 
537  solarray = NULL;
538  zilpcands = NULL;
539 
540  retcode = SCIP_OKAY;
541  /* copy the current LP solution to the working solution and allocate memory for local data */
542  SCIP_CALL( SCIPlinkLPSol(scip, sol) );
543  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &solarray, nlpcands), TERMINATE);
544  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &zilpcands, nlpcands), TERMINATE);
545 
546  /* copy necessary data to local arrays */
547  BMScopyMemoryArray(solarray, lpcandssol, nlpcands);
548  BMScopyMemoryArray(zilpcands, lpcands, nlpcands);
549 
550  /* allocate buffer data arrays */
551  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &slackvars, nslacks), TERMINATE);
552  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &upslacks, nslacks), TERMINATE);
553  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &downslacks, nslacks), TERMINATE);
554  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &slackvarcoeffs, nslacks), TERMINATE);
555  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &rowneedsslackvar, nslacks), TERMINATE);
556  SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &activities, nslacks), TERMINATE);
557 
558  BMSclearMemoryArray(slackvars, nslacks);
559  BMSclearMemoryArray(slackvarcoeffs, nslacks);
560  BMSclearMemoryArray(rowneedsslackvar, nslacks);
561 
562  numericalerror = FALSE;
563  nroundings = 0;
564 
565  /* loop over fractional variables and involved LP rows to find all rows which require a slack variable */
566  for( c = 0; c < nlpcands; ++c )
567  {
568  SCIP_VAR* cand;
569  SCIP_ROW** candrows;
570  int r;
571  int ncandrows;
572 
573  cand = zilpcands[c];
574  assert(cand != NULL);
575  assert(SCIPcolGetLPPos(SCIPvarGetCol(cand)) >= 0);
576 
577  candrows = SCIPcolGetRows(SCIPvarGetCol(cand));
578  ncandrows = SCIPcolGetNLPNonz(SCIPvarGetCol(cand));
579 
580  assert(candrows == NULL || ncandrows > 0);
581 
582  for( r = 0; r < ncandrows; ++r )
583  {
584  int rowpos;
585 
586  assert(candrows != NULL); /* to please flexelint */
587  assert(candrows[r] != NULL);
588  rowpos = SCIProwGetLPPos(candrows[r]);
589 
590  if( rowpos >= 0 && SCIPisFeasEQ(scip, SCIProwGetLhs(candrows[r]), SCIProwGetRhs(candrows[r])) )
591  {
592  rowneedsslackvar[rowpos] = TRUE;
593  SCIPdebugMessage(" Row %s needs slack variable for variable %s\n", SCIProwGetName(candrows[r]), SCIPvarGetName(cand));
594  }
595  }
596  }
597 
598  /* calculate row slacks for every every row that belongs to the current LP and ensure, that the current solution
599  * has no violated constraint -- if any constraint is violated, i.e. a slack is significantly smaller than zero,
600  * this will cause the termination of the heuristic because Zirounding does not provide feasibility recovering
601  */
602  for( i = 0; i < nslacks; ++i )
603  {
604  SCIP_ROW* row;
605  SCIP_Real lhs;
606  SCIP_Real rhs;
607 
608  row = rows[i];
609 
610  assert(row != NULL);
611 
612  lhs = SCIProwGetLhs(row);
613  rhs = SCIProwGetRhs(row);
614 
615  /* get row activity */
616  activities[i] = SCIPgetRowActivity(scip, row);
617  assert(SCIPisFeasLE(scip, lhs, activities[i]) && SCIPisFeasLE(scip, activities[i], rhs));
618 
619  /* in special case if LHS or RHS is (-)infinity slacks have to be initialized as infinity */
620  if( SCIPisInfinity(scip, -lhs) )
621  downslacks[i] = SCIPinfinity(scip);
622  else
623  downslacks[i] = activities[i] - lhs;
624 
625  if( SCIPisInfinity(scip, rhs) )
626  upslacks[i] = SCIPinfinity(scip);
627  else
628  upslacks[i] = rhs - activities[i];
629 
630  SCIPdebugMessage("lhs:%5.2f <= act:%5.2g <= rhs:%5.2g --> down: %5.2g, up:%5.2g\n", lhs, activities[i], rhs, downslacks[i], upslacks[i]);
631 
632  /* row is an equation. Try to find a slack variable in the row, i.e.,
633  * a continuous variable which occurs only in this row. If no such variable exists,
634  * there is no hope for an IP-feasible solution in this round
635  */
636  if( SCIPisFeasEQ(scip, lhs, rhs) && rowneedsslackvar[i] )
637  {
638  /* @todo: This is only necessary for rows containing fractional variables. */
639  rowFindSlackVar(scip, row, &(slackvars[i]), &(slackvarcoeffs[i]));
640 
641  if( slackvars[i] == NULL )
642  {
643  SCIPdebugMessage("No slack variable found for equation %s, terminating ZI Round heuristic\n", SCIProwGetName(row));
644  goto TERMINATE;
645  }
646  else
647  {
648  SCIP_Real ubslackvar;
649  SCIP_Real lbslackvar;
650  SCIP_Real solvalslackvar;
651  SCIP_Real coeffslackvar;
652  SCIP_Real ubgap;
653  SCIP_Real lbgap;
654 
655  assert(SCIPvarGetType(slackvars[i]) == SCIP_VARTYPE_CONTINUOUS);
656  solvalslackvar = SCIPgetSolVal(scip, sol, slackvars[i]);
657  ubslackvar = SCIPvarGetUbGlobal(slackvars[i]);
658  lbslackvar = SCIPvarGetLbGlobal(slackvars[i]);
659 
660  coeffslackvar = slackvarcoeffs[i];
661  assert(!SCIPisFeasZero(scip, coeffslackvar));
662 
663  ubgap = ubslackvar - solvalslackvar;
664  lbgap = solvalslackvar - lbslackvar;
665 
666  if( SCIPisFeasZero(scip, ubgap) )
667  ubgap = 0.0;
668  if( SCIPisFeasZero(scip, lbgap) )
669  lbgap = 0.0;
670 
671  if( SCIPisFeasPositive(scip, coeffslackvar) )
672  {
673  if( !SCIPisInfinity(scip, lbslackvar) )
674  upslacks[i] += coeffslackvar * lbgap;
675  else
676  upslacks[i] = SCIPinfinity(scip);
677  if( !SCIPisInfinity(scip, ubslackvar) )
678  downslacks[i] += coeffslackvar * ubgap;
679  else
680  downslacks[i] = SCIPinfinity(scip);
681  }
682  else
683  {
684  if( !SCIPisInfinity(scip, ubslackvar) )
685  upslacks[i] -= coeffslackvar * ubgap;
686  else
687  upslacks[i] = SCIPinfinity(scip);
688  if( !SCIPisInfinity(scip, lbslackvar) )
689  downslacks[i] -= coeffslackvar * lbgap;
690  else
691  downslacks[i] = SCIPinfinity(scip);
692  }
693  SCIPdebugMessage(" Slack variable for row %s at pos %d: %g <= %s = %g <= %g; Coeff %g, upslack = %g, downslack = %g \n",
694  SCIProwGetName(row), SCIProwGetLPPos(row), lbslackvar, SCIPvarGetName(slackvars[i]), solvalslackvar, ubslackvar, coeffslackvar,
695  upslacks[i], downslacks[i]);
696  }
697  }
698  /* due to numerical inaccuracies, the rows might be feasible, even if the slacks are
699  * significantly smaller than zero -> terminate
700  */
701  if( SCIPisFeasLT(scip, upslacks[i], 0.0) || SCIPisFeasLT(scip, downslacks[i], 0.0) )
702  goto TERMINATE;
703  }
704 
705  assert(nslacks == 0 || (upslacks != NULL && downslacks != NULL && activities != NULL));
706 
707  /* initialize number of remaining variables and flag to enter the main loop */
708  currentlpcands = nlpcands;
709  improvementfound = TRUE;
710 
711  /* iterate over variables as long as there are fractional variables left */
712  while( currentlpcands > 0 && improvementfound && (heurdata->maxroundingloops == -1 || nroundings < heurdata->maxroundingloops) )
713  { /*lint --e{850}*/
714  improvementfound = FALSE;
715  nroundings++;
716  SCIPdebugMessage("zirounding enters while loop for %d time with %d candidates left. \n", nroundings, currentlpcands);
717 
718  /* check for every remaining fractional variable if a shifting decreases ZI-value of the variable */
719  for( c = 0; c < currentlpcands; ++c )
720  {
721  SCIP_VAR* var;
722  SCIP_Real oldsolval;
723  SCIP_Real upperbound;
724  SCIP_Real lowerbound;
725  SCIP_Real up;
726  SCIP_Real down;
727  SCIP_Real ziup;
728  SCIP_Real zidown;
729  SCIP_Real zicurrent;
730  SCIP_Real shiftval;
731 
732  DIRECTION direction;
733 
734  /* get values from local data */
735  oldsolval = solarray[c];
736  var = zilpcands[c];
737 
738  assert(!SCIPisFeasIntegral(scip, oldsolval));
739  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
740 
741  /* calculate bounds for variable and make sure that there are no numerical inconsistencies */
742  upperbound = SCIPinfinity(scip);
743  lowerbound = SCIPinfinity(scip);
744  calculateBounds(scip, var, oldsolval, &upperbound, &lowerbound, upslacks, downslacks, nslacks, &numericalerror);
745 
746  if( numericalerror )
747  goto TERMINATE;
748 
749  /* calculate the possible values after shifting */
750  up = oldsolval + upperbound;
751  down = oldsolval - lowerbound;
752 
753  /* if the variable is integer or implicit binary, do not shift further than the nearest integer */
755  {
756  SCIP_Real ceilx;
757  SCIP_Real floorx;
758 
759  ceilx = SCIPfeasCeil(scip, oldsolval);
760  floorx = SCIPfeasFloor(scip, oldsolval);
761  up = MIN(up, ceilx);
762  down = MAX(down, floorx);
763  }
764 
765  /* calculate necessary values */
766  ziup = getZiValue(scip, up);
767  zidown = getZiValue(scip, down);
768  zicurrent = getZiValue(scip, oldsolval);
769 
770  /* calculate the shifting direction that reduces ZI-value the most,
771  * if both directions improve ZI-value equally, take the direction which improves the objective
772  */
773  if( SCIPisFeasLT(scip, zidown, zicurrent) || SCIPisFeasLT(scip, ziup, zicurrent) )
774  {
775  if( SCIPisFeasEQ(scip,ziup, zidown) )
776  direction = SCIPisFeasGE(scip, SCIPvarGetObj(var), 0.0) ? DIRECTION_DOWN : DIRECTION_UP;
777  else if( SCIPisFeasLT(scip, zidown, ziup) )
778  direction = DIRECTION_DOWN;
779  else
780  direction = DIRECTION_UP;
781 
782  /* once a possible shifting direction and value have been found, variable value is updated */
783  shiftval = (direction == DIRECTION_UP ? up - oldsolval : down - oldsolval);
784 
785  /* this improves numerical stability in some cases */
786  if( direction == DIRECTION_UP )
787  shiftval = MIN(shiftval, upperbound);
788  else
789  shiftval = MIN(shiftval, lowerbound);
790  /* update the solution */
791  solarray[c] = direction == DIRECTION_UP ? up : down;
792  SCIP_CALL( SCIPsetSolVal(scip, sol, var, solarray[c]) );
793 
794  /* update the rows activities and slacks */
795  SCIP_CALL( updateSlacks(scip, sol, var, shiftval, upslacks,
796  downslacks, activities, slackvars, slackvarcoeffs, nslacks) );
797 
798  SCIPdebugMessage("zirounding update step : %d var index, oldsolval=%g, shiftval=%g\n",
799  SCIPvarGetIndex(var), oldsolval, shiftval);
800  /* since at least one improvement has been found, heuristic will enter main loop for another time because the improvement
801  * might affect many LP rows and their current slacks and thus make further rounding steps possible */
802  improvementfound = TRUE;
803  }
804 
805  /* if solution value of variable has become feasibly integral due to rounding step,
806  * variable is put at the end of remaining candidates array so as not to be considered in future loops
807  */
808  if( SCIPisFeasIntegral(scip, solarray[c]) )
809  {
810  zilpcands[c] = zilpcands[currentlpcands - 1];
811  solarray[c] = solarray[currentlpcands - 1];
812  currentlpcands--;
813 
814  /* counter is decreased if end of candidates array has not been reached yet */
815  if( c < currentlpcands )
816  c--;
817  }
818  else if( nroundings == heurdata->maxroundingloops - 1 )
819  goto TERMINATE;
820  }
821  }
822 
823  /* in case that no candidate is left for rounding after the final main loop
824  * the found solution has to be checked for feasibility in the original problem
825  */
826  if( currentlpcands == 0 )
827  {
828  SCIP_Bool stored;
829  SCIP_CALL(SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, FALSE, &stored));
830  if( stored )
831  {
832 #ifdef SCIP_DEBUG
833  SCIPdebugMessage("found feasible rounded solution:\n");
834  SCIP_CALL( SCIPprintSol(scip, sol, NULL, FALSE) );
835 #endif
836  SCIPstatisticMessage(" ZI Round solution value: %g \n", SCIPgetSolOrigObj(scip, sol));
837 
838  *result = SCIP_FOUNDSOL;
839  }
840  }
841 
842  /* free memory for all locally allocated data */
843  TERMINATE:
844  SCIPfreeBufferArrayNull(scip, &activities);
845  SCIPfreeBufferArrayNull(scip, &rowneedsslackvar);
846  SCIPfreeBufferArrayNull(scip, &slackvarcoeffs);
847  SCIPfreeBufferArrayNull(scip, &downslacks);
848  SCIPfreeBufferArrayNull(scip, &upslacks);
849  SCIPfreeBufferArrayNull(scip, &slackvars);
850  SCIPfreeBufferArrayNull(scip, &zilpcands);
851  SCIPfreeBufferArrayNull(scip, &solarray);
852 
853  return retcode;
854 }
855 
856 /*
857  * primal heuristic specific interface methods
858  */
859 
860 /** creates the zirounding primal heuristic and includes it in SCIP */
862  SCIP* scip /**< SCIP data structure */
863  )
864 {
865  SCIP_HEURDATA* heurdata;
866  SCIP_HEUR* heur;
867 
868  /* create zirounding primal heuristic data */
869  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
870 
871  /* include primal heuristic */
872  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
874  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecZirounding, heurdata) );
875 
876  assert(heur != NULL);
877 
878  /* set non-NULL pointers to callback methods */
879  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyZirounding) );
880  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeZirounding) );
881  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitZirounding) );
882  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitZirounding) );
883  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolZirounding) );
884 
885  /* add zirounding primal heuristic parameters */
886  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/zirounding/maxroundingloops",
887  "determines maximum number of rounding loops",
888  &heurdata->maxroundingloops, TRUE, DEFAULT_MAXROUNDINGLOOPS, -1, INT_MAX, NULL, NULL) );
889  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/zirounding/stopziround",
890  "flag to determine if Zirounding is deactivated after a certain percentage of unsuccessful calls",
891  &heurdata->stopziround, TRUE, DEFAULT_STOPZIROUND, NULL, NULL) );
892  SCIP_CALL( SCIPaddRealParam(scip,"heuristics/zirounding/stoppercentage",
893  "if percentage of found solutions falls below this parameter, Zirounding will be deactivated",
894  &heurdata->stoppercentage, TRUE, DEFAULT_STOPPERCENTAGE, 0.0, 1.0, NULL, NULL) );
895  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/zirounding/minstopncalls",
896  "determines the minimum number of calls before percentage-based deactivation of Zirounding is applied",
897  &heurdata->minstopncalls, TRUE, DEFAULT_MINSTOPNCALLS, 1, INT_MAX, NULL, NULL) );
898 
899  return SCIP_OKAY;
900 }
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip.c:7361
static void calculateBounds(SCIP *scip, SCIP_VAR *var, SCIP_Real currentvalue, SCIP_Real *upperbound, SCIP_Real *lowerbound, SCIP_Real *upslacks, SCIP_Real *downslacks, int nslacks, SCIP_Bool *numericalerror)
static SCIP_Real getZiValue(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:33125
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
enum Direction DIRECTION
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
#define HEUR_DESC
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1273
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7297
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1283
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41920
#define HEUR_FREQ
#define NULL
Definition: lpi_spx.cpp:130
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
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
#define DEFAULT_MAXROUNDINGLOOPS
#define FALSE
Definition: def.h:56
#define HEUR_NAME
#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
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition: scip.c:26785
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
#define HEUR_FREQOFS
#define HEUR_DISPCHAR
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:26482
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:42044
Direction
Definition: heur_twoopt.c:110
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
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:18726
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:18784
static SCIP_DECL_HEUREXIT(heurExitZirounding)
#define DEFAULT_STOPZIROUND
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41984
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41996
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:287
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:34002
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
static SCIP_DECL_HEURCOPY(heurCopyZirounding)
SCIP_RETCODE SCIPincludeHeurZirounding(SCIP *scip)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:26354
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:18773
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:37435
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18974
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20598
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
#define HEUR_TIMING
#define DEFAULT_MINSTOPNCALLS
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16740
#define SCIP_Bool
Definition: def.h:53
#define HEUR_USESSUBSCIP
#define MAX(x, y)
Definition: tclique_def.h:75
enum Direction DIRECTION
Definition: heur_twoopt.c:116
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34648
ZI Round primal heuristic.
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:7345
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:7329
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
#define DEFAULT_STOPPERCENTAGE
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
static SCIP_DECL_HEUREXEC(heurExecZirounding)
static SCIP_DECL_HEURINITSOL(heurInitsolZirounding)
static SCIP_RETCODE updateSlacks(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real shiftvalue, SCIP_Real *upslacks, SCIP_Real *downslacks, SCIP_Real *activities, SCIP_VAR **slackvars, SCIP_Real *slackcoeffs, int nslacks)
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18871
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
static SCIP_DECL_HEURFREE(heurFreeZirounding)
#define MIN(x, y)
Definition: memory.c:67
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41959
#define SCIP_Longint
Definition: def.h:112
#define HEUR_PRIORITY
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:19104
SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28245
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18836
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1058
static void rowFindSlackVar(SCIP *scip, SCIP_ROW *row, SCIP_VAR **varpointer, SCIP_Real *coeffpointer)
static SCIP_DECL_HEURINIT(heurInitZirounding)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
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 HEUR_MAXDEPTH
int SCIPgetNLPRows(SCIP *scip)
Definition: scip.c:26806
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
SCIP callable library.
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