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