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