Scippy

SCIP

Solving Constraint Integer Programs

heur_distributiondiving.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_distributiondiving.c
17  * @brief Diving heuristic that chooses fixings w.r.t. changes in the solution density after Pryor and Chinneck.
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 
28 #include "pub_dive.h"
29 
30 #define HEUR_NAME "distributiondiving"
31 #define HEUR_DESC "Diving heuristic that chooses fixings w.r.t. changes in the solution density"
32 #define HEUR_DISPCHAR 'e'
33 #define HEUR_PRIORITY -1003300
34 #define HEUR_FREQ 10
35 #define HEUR_FREQOFS 3
36 #define HEUR_MAXDEPTH -1
37 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
38 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
39 #define EVENT_DISTRIBUTION SCIP_EVENTTYPE_BOUNDCHANGED /**< the event type to be handled by this event handler */
40 #define EVENTHDLR_NAME "eventhdlr_distributiondiving"
41 #define DIVESET_DIVETYPES SCIP_DIVETYPE_INTEGRALITY /**< bit mask that represents all supported dive types */
42 
43 #define SQUARED(x) ((x) * (x))
44 /*
45  * Default parameter settings
46  */
47 
48 #define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
49 #define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
50 #define DEFAULT_MAXLPITERQUOT 0.05 /**< maximal fraction of diving LP iterations compared to node LP iterations */
51 #define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
52 #define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
53  * where diving is performed (0.0: no limit) */
54 #define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
55  * where diving is performed (0.0: no limit) */
56 #define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
57 #define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
58 #define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
59 #define DEFAULT_LPRESOLVEDOMCHGQUOT 0.15 /**< percentage of immediate domain changes during probing to trigger LP resolve */
60 #define DEFAULT_LPSOLVEFREQ 0 /**< LP solve frequency for diving heuristics */
61 #define DEFAULT_ONLYLPBRANCHCANDS TRUE /**< should only LP branching candidates be considered instead of the slower but
62  * more general constraint handler diving variable selection? */
63 
64 #define SCOREPARAM_VALUES "lhwvd" /**< the score;largest 'd'ifference, 'l'owest cumulative probability,'h'ighest c.p.,
65  * 'v'otes lowest c.p., votes highest c.p.('w'), 'r'evolving */
66 #define SCOREPARAM_VALUESLEN 5
67 #define DEFAULT_SCOREPARAM 'r' /**< default scoring parameter to guide the diving */
68 
69 /* locally defined heuristic data */
70 struct SCIP_HeurData
71 {
72  SCIP_SOL* sol; /**< working solution */
73 
74  SCIP_EVENTHDLR* eventhdlr; /**< event handler pointer */
75  SCIP_VAR** updatedvars; /**< variables to process bound change events for */
76  SCIP_Real* rowmeans; /**< row activity mean values for all rows */
77  SCIP_Real* rowvariances; /**< row activity variances for all rows */
78  SCIP_Real* currentubs; /**< variable upper bounds as currently saved in the row activities */
79  SCIP_Real* currentlbs; /**< variable lower bounds as currently saved in the row activities */
80  int* rowinfinitiesdown; /**< count the number of variables with infinite bounds which allow for always
81  * repairing the constraint right hand side */
82  int* rowinfinitiesup; /**< count the number of variables with infinite bounds which allow for always
83  * repairing the constraint left hand side */
84  int* varposs; /**< array of variable positions in the updated variables array */
85  int* varfilterposs; /**< array of event filter positions for variable events */
86  int nupdatedvars; /**< the current number of variables with pending bound changes */
87  int memsize; /**< memory size of current arrays, needed for dynamic reallocation */
88  int varpossmemsize; /**< memory size of updated vars and varposs array */
89 
90  char scoreparam; /**< score user parameter */
91  char score; /**< score to be used depending on user parameter to use fixed score or revolve */
92 };
93 
94 struct SCIP_EventhdlrData
95 {
96  SCIP_HEURDATA* heurdata; /**< the heuristic data to access distribution arrays */
97 };
98 /*
99  * local methods
100  */
101 
102 /** ensure that maxindex + 1 rows can be represented in data arrays; memory gets reallocated with 10% extra space
103  * to save some time for future allocations */
104 static
106  SCIP* scip, /**< SCIP data structure */
107  SCIP_HEURDATA* heurdata, /**< heuristic data */
108  int maxindex /**< row index at hand (size must be at least this large) */
109  )
110 {
111  int newsize;
112  int r;
113 
114  /* maxindex fits in current array -> nothing to do */
115  if( maxindex < heurdata->memsize )
116  return SCIP_OKAY;
117 
118  /* new memory size is the max index + 1 plus 10% additional space */
119  newsize = (int)SCIPfeasCeil(scip, (maxindex + 1) * 1.1);
120  assert(newsize > heurdata->memsize);
121  assert(heurdata->memsize >= 0);
122 
123  /* alloc memory arrays for row information */
124  if( heurdata->memsize == 0 )
125  {
126  SCIP_VAR** vars;
127  int v;
128  int nvars;
129 
130  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) );
131  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) );
132  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowmeans, newsize) );
133  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowvariances, newsize) );
134 
135  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING);
136 
137  vars = SCIPgetVars(scip);
138  nvars = SCIPgetNVars(scip);
139 
140  assert(nvars > 0);
141 
142  /* allocate variable update event processing array storage */
143  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varfilterposs, nvars) );
144  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varposs, nvars) );
145  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->updatedvars, nvars) );
146  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentubs, nvars) );
147  SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentlbs, nvars) );
148 
149  heurdata->varpossmemsize = nvars;
150  heurdata->nupdatedvars = 0;
151 
152  /* init variable event processing data */
153  for( v = 0; v < nvars; ++v )
154  {
155  assert(SCIPvarIsActive(vars[v]));
156  assert(SCIPvarGetProbindex(vars[v]) == v);
157 
158  /* set up variable events to catch bound changes */
159  SCIP_CALL( SCIPcatchVarEvent(scip, vars[v], EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, &(heurdata->varfilterposs[v])) );
160  assert(heurdata->varfilterposs[v] >= 0);
161 
162  heurdata->varposs[v] = -1;
163  heurdata->updatedvars[v] = NULL;
164  heurdata->currentlbs[v] = SCIP_INVALID;
165  heurdata->currentubs[v] = SCIP_INVALID;
166  }
167 
168  }
169  else
170  {
171  SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) );
172  SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) );
173  SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowmeans, newsize) );
174  SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowvariances, newsize) );
175  }
176 
177  /* loop over extended arrays and invalidate data to trigger initialization of this row when necessary */
178  for( r = heurdata->memsize; r < newsize; ++r )
179  {
180  heurdata->rowmeans[r] = SCIP_INVALID;
181  heurdata->rowvariances[r] = SCIP_INVALID;
182  heurdata->rowinfinitiesdown[r] = 0;
183  heurdata->rowinfinitiesup[r] = 0;
184  }
185 
186  /* adjust memsize */
187  heurdata->memsize = newsize;
188 
189  return SCIP_OKAY;
190 }
191 
192 /** update the variables current lower and upper bound */
193 static
195  SCIP* scip, /**< SCIP data structure */
196  SCIP_HEURDATA* heurdata, /**< heuristic data */
197  SCIP_VAR* var /**< the variable to update current bounds */
198  )
199 {
200  int varindex;
201  SCIP_Real lblocal;
202  SCIP_Real ublocal;
203 
204  assert(var != NULL);
205 
206  varindex = SCIPvarGetProbindex(var);
207  assert(0 <= varindex && varindex < heurdata->varpossmemsize);
208  lblocal = SCIPvarGetLbLocal(var);
209  ublocal = SCIPvarGetUbLocal(var);
210 
211  assert(SCIPisFeasLE(scip, lblocal, ublocal));
212 
213  heurdata->currentlbs[varindex] = lblocal;
214  heurdata->currentubs[varindex] = ublocal;
215 }
216 
217 /** calculates the initial mean and variance of the row activity normal distribution.
218  *
219  * The mean value \f$ \mu \f$ is given by \f$ \mu = \sum_i=1^n c_i * (lb_i +ub_i) / 2 \f$ where
220  * \f$n \f$ is the number of variables, and \f$ c_i, lb_i, ub_i \f$ are the variable coefficient and
221  * bounds, respectively. With the same notation, the variance \f$ \sigma^2 \f$ is given by
222  * \f$ \sigma^2 = \sum_i=1^n c_i^2 * \sigma^2_i \f$, with the variance being
223  * \f$ \sigma^2_i = ((ub_i - lb_i + 1)^2 - 1) / 12 \f$ for integer variables and
224  * \f$ \sigma^2_i = (ub_i - lb_i)^2 / 12 \f$ for continuous variables.
225  */
226 static
227 void rowCalculateGauss(
228  SCIP* scip, /**< SCIP data structure */
229  SCIP_HEURDATA* heurdata, /**< the heuristic rule data */
230  SCIP_ROW* row, /**< the row for which the gaussian normal distribution has to be calculated */
231  SCIP_Real* mu, /**< pointer to store the mean value of the gaussian normal distribution */
232  SCIP_Real* sigma2, /**< pointer to store the variance value of the gaussian normal distribution */
233  int* rowinfinitiesdown, /**< pointer to store the number of variables with infinite bounds to DECREASE activity */
234  int* rowinfinitiesup /**< pointer to store the number of variables with infinite bounds to INCREASE activity */
235  )
236 {
237  SCIP_COL** rowcols;
238  SCIP_Real* rowvals;
239  int nrowvals;
240  int c;
241 
242  assert(scip != NULL);
243  assert(row != NULL);
244  assert(mu != NULL);
245  assert(sigma2 != NULL);
246  assert(rowinfinitiesup != NULL);
247  assert(rowinfinitiesdown != NULL);
248 
249  rowcols = SCIProwGetCols(row);
250  rowvals = SCIProwGetVals(row);
251  nrowvals = SCIProwGetNNonz(row);
252 
253  assert(nrowvals == 0 || rowcols != NULL);
254  assert(nrowvals == 0 || rowvals != NULL);
255 
256  *mu = SCIProwGetConstant(row);
257  *sigma2 = 0.0;
258  *rowinfinitiesdown = 0;
259  *rowinfinitiesup = 0;
260 
261  /* loop over nonzero row coefficients and sum up the variable contributions to mu and sigma2 */
262  for( c = 0; c < nrowvals; ++c )
263  {
264  SCIP_VAR* colvar;
265  SCIP_Real colval;
266  SCIP_Real colvarlb;
267  SCIP_Real colvarub;
268  SCIP_Real squarecoeff;
269  SCIP_Real varvariance;
270  SCIP_Real varmean;
271  int varindex;
272 
273  assert(rowcols[c] != NULL);
274  colvar = SCIPcolGetVar(rowcols[c]);
275  assert(colvar != NULL);
276 
277  colval = rowvals[c];
278  colvarlb = SCIPvarGetLbLocal(colvar);
279  colvarub = SCIPvarGetUbLocal(colvar);
280 
281  varmean = 0.0;
282  varvariance = 0.0;
283  varindex = SCIPvarGetProbindex(colvar);
284  assert((heurdata->currentlbs[varindex] == SCIP_INVALID)
285  == (heurdata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
286 
287  /* variable bounds need to be watched from now on */
288  if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
289  heurdataUpdateCurrentBounds(scip, heurdata, colvar);
290 
291  assert(!SCIPisInfinity(scip, colvarlb));
292  assert(!SCIPisInfinity(scip, -colvarub));
293  assert(SCIPisFeasLE(scip, colvarlb, colvarub));
294 
295  /* variables with infinite bounds are skipped for the calculation of the variance; they need to
296  * be accounted for by the counters for infinite row activity decrease and increase and they
297  * are used to shift the row activity mean in case they have one nonzero, but finite bound */
298  if( SCIPisInfinity(scip, -colvarlb) || SCIPisInfinity(scip, colvarub) )
299  {
300  if( SCIPisInfinity(scip, colvarub) )
301  {
302  /* an infinite upper bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
303  * positive or negative, resp.
304  */
305  if( colval < 0.0 )
306  ++(*rowinfinitiesdown);
307  else
308  ++(*rowinfinitiesup);
309  }
310 
311  /* an infinite lower bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
312  * negative or positive, resp.
313  */
314  if( SCIPisInfinity(scip, -colvarlb) )
315  {
316  if( colval > 0.0 )
317  ++(*rowinfinitiesdown);
318  else
319  ++(*rowinfinitiesup);
320  }
321  }
322  SCIPvarCalcDistributionParameters(scip, colvarlb, colvarub, SCIPvarGetType(colvar), &varmean, &varvariance);
323 
324  /* actual values are updated; the contribution of the variable to mu is the arithmetic mean of its bounds */
325  *mu += colval * varmean;
326 
327  /* the variance contribution of a variable is c^2 * (u - l)^2 / 12.0 for continuous and c^2 * ((u - l + 1)^2 - 1) / 12.0 for integer */
328  squarecoeff = SQUARED(colval);
329  *sigma2 += squarecoeff * varvariance;
330 
331  assert(!SCIPisFeasNegative(scip, *sigma2));
332  }
333 
334  SCIPdebug( SCIPprintRow(scip, row, NULL) );
335  SCIPdebugMessage(" Row %s has a mean value of %g at a sigma2 of %g \n", SCIProwGetName(row), *mu, *sigma2);
336 }
337 
338 /** calculate the branching score of a variable, depending on the chosen score parameter */
339 static
341  SCIP* scip, /**< current SCIP */
342  SCIP_HEURDATA* heurdata, /**< branch rule data */
343  SCIP_VAR* var, /**< candidate variable */
344  SCIP_Real lpsolval, /**< current fractional LP-relaxation solution value */
345  SCIP_Real* upscore, /**< pointer to store the variable score when branching on it in upward direction */
346  SCIP_Real* downscore, /**< pointer to store the variable score when branching on it in downward direction */
347  char scoreparam /**< the score parameter of this heuristic */
348  )
349 {
350  SCIP_COL* varcol;
351  SCIP_ROW** colrows;
352  SCIP_Real* rowvals;
353  SCIP_Real varlb;
354  SCIP_Real varub;
355  SCIP_Real squaredbounddiff; /* current squared difference of variable bounds (ub - lb)^2 */
356  SCIP_Real newub; /* new upper bound if branching downwards */
357  SCIP_Real newlb; /* new lower bound if branching upwards */
358  SCIP_Real squaredbounddiffup; /* squared difference after branching upwards (ub - lb')^2 */
359  SCIP_Real squaredbounddiffdown; /* squared difference after branching downwards (ub' - lb)^2 */
360  SCIP_Real currentmean; /* current mean value of variable uniform distribution */
361  SCIP_Real meanup; /* mean value of variable uniform distribution after branching up */
362  SCIP_Real meandown; /* mean value of variable uniform distribution after branching down*/
363  SCIP_VARTYPE vartype;
364  int ncolrows;
365  int i;
366 
367  SCIP_Bool onlyactiverows; /* should only rows which are active at the current node be considered? */
368 
369  assert(scip != NULL);
370  assert(var != NULL);
371  assert(upscore != NULL);
372  assert(downscore != NULL);
373  assert(!SCIPisIntegral(scip, lpsolval) || SCIPvarIsBinary(var));
374  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
375 
376  varcol = SCIPvarGetCol(var);
377  assert(varcol != NULL);
378 
379  colrows = SCIPcolGetRows(varcol);
380  rowvals = SCIPcolGetVals(varcol);
381  ncolrows = SCIPcolGetNNonz(varcol);
382  varlb = SCIPvarGetLbLocal(var);
383  varub = SCIPvarGetUbLocal(var);
384  assert(SCIPisFeasLT(scip, varlb, varub));
385  vartype = SCIPvarGetType(var);
386 
387  /* calculate mean and variance of variable uniform distribution before and after branching */
388  currentmean = 0.0;
389  squaredbounddiff = 0.0;
390  SCIPvarCalcDistributionParameters(scip, varlb, varub, vartype, &currentmean, &squaredbounddiff);
391 
392  /* unfixed binary variables may have an integer solution value in the LP solution, eg, at the presence of indicator constraints */
393  if( !SCIPvarIsBinary(var) )
394  {
395  newlb = SCIPfeasCeil(scip, lpsolval);
396  newub = SCIPfeasFloor(scip, lpsolval);
397  }
398  else
399  {
400  newlb = 1.0;
401  newub = 0.0;
402  }
403 
404 
405  /* calculate the variable's uniform distribution after branching up and down, respectively. */
406  squaredbounddiffup = 0.0;
407  meanup = 0.0;
408  SCIPvarCalcDistributionParameters(scip, newlb, varub, vartype, &meanup, &squaredbounddiffup);
409 
410  /* calculate the distribution mean and variance for a variable with finite lower bound */
411  squaredbounddiffdown = 0.0;
412  meandown = 0.0;
413  SCIPvarCalcDistributionParameters(scip, varlb, newub, vartype, &meandown, &squaredbounddiffdown);
414 
415  /* initialize the variable's up and down score */
416  *upscore = 0.0;
417  *downscore = 0.0;
418 
419  onlyactiverows = FALSE;
420 
421  /* loop over the variable rows and calculate the up and down score */
422  for( i = 0; i < ncolrows; ++i )
423  {
424  SCIP_ROW* row;
425  SCIP_Real changedrowmean;
426  SCIP_Real rowmean;
427  SCIP_Real rowvariance;
428  SCIP_Real changedrowvariance;
429  SCIP_Real currentrowprob;
430  SCIP_Real newrowprobup;
431  SCIP_Real newrowprobdown;
432  SCIP_Real squaredcoeff;
433  SCIP_Real rowval;
434  int rowinfinitiesdown;
435  int rowinfinitiesup;
436  int rowpos;
437 
438  row = colrows[i];
439  rowval = rowvals[i];
440  assert(row != NULL);
441 
442  /* we access the rows by their index */
443  rowpos = SCIProwGetIndex(row);
444 
445  /* skip non-active rows if the user parameter was set this way */
446  if( onlyactiverows && SCIPisSumPositive(scip, SCIPgetRowLPFeasibility(scip, row)) )
447  continue;
448 
449  /* call method to ensure sufficient data capacity */
450  SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, rowpos) );
451 
452  /* calculate row activity distribution if this is the first candidate to appear in this row */
453  if( heurdata->rowmeans[rowpos] == SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
454  {
455  rowCalculateGauss(scip, heurdata, row, &heurdata->rowmeans[rowpos], &heurdata->rowvariances[rowpos],
456  &heurdata->rowinfinitiesdown[rowpos], &heurdata->rowinfinitiesup[rowpos]);
457  }
458 
459  /* retrieve the row distribution parameters from the branch rule data */
460  rowmean = heurdata->rowmeans[rowpos];
461  rowvariance = heurdata->rowvariances[rowpos];
462  rowinfinitiesdown = heurdata->rowinfinitiesdown[rowpos];
463  rowinfinitiesup = heurdata->rowinfinitiesup[rowpos];
464  assert(!SCIPisNegative(scip, rowvariance));
465 
466  currentrowprob = SCIProwCalcProbability(scip, row, rowmean, rowvariance,
467  rowinfinitiesdown, rowinfinitiesup);
468 
469  /* get variable's current expected contribution to row activity */
470  squaredcoeff = SQUARED(rowval);
471 
472  /* first, get the probability change for the row if the variable is branched on upwards. The probability
473  * can only be affected if the variable upper bound is finite
474  */
475  if( !SCIPisInfinity(scip, varub) )
476  {
477  int rowinftiesdownafterbranch;
478  int rowinftiesupafterbranch;
479 
480  /* calculate how branching would affect the row parameters */
481  changedrowmean = rowmean + rowval * (meanup - currentmean);
482  changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffup - squaredbounddiff);
483  changedrowvariance = MAX(0.0, changedrowvariance);
484 
485  rowinftiesdownafterbranch = rowinfinitiesdown;
486  rowinftiesupafterbranch = rowinfinitiesup;
487 
488  /* account for changes of the row's infinite bound contributions */
489  if( SCIPisInfinity(scip, -varlb) && rowval < 0.0 )
490  rowinftiesupafterbranch--;
491  if( SCIPisInfinity(scip, -varlb) && rowval > 0.0 )
492  rowinftiesdownafterbranch--;
493 
494  assert(rowinftiesupafterbranch >= 0);
495  assert(rowinftiesdownafterbranch >= 0);
496  newrowprobup = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
497  rowinftiesupafterbranch);
498  }
499  else
500  newrowprobup = currentrowprob;
501 
502  /* do the same for the other branching direction */
503  if( !SCIPisInfinity(scip, varlb) )
504  {
505  int rowinftiesdownafterbranch;
506  int rowinftiesupafterbranch;
507 
508  changedrowmean = rowmean + rowval * (meandown - currentmean);
509  changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffdown - squaredbounddiff);
510  changedrowvariance = MAX(0.0, changedrowvariance);
511 
512  rowinftiesdownafterbranch = rowinfinitiesdown;
513  rowinftiesupafterbranch = rowinfinitiesup;
514 
515  /* account for changes of the row's infinite bound contributions */
516  if( SCIPisInfinity(scip, varub) && rowval > 0.0 )
517  rowinftiesupafterbranch -= 1;
518  if( SCIPisInfinity(scip, varub) && rowval < 0.0 )
519  rowinftiesdownafterbranch -= 1;
520 
521  assert(rowinftiesdownafterbranch >= 0);
522  assert(rowinftiesupafterbranch >= 0);
523  newrowprobdown = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
524  rowinftiesupafterbranch);
525  }
526  else
527  newrowprobdown = currentrowprob;
528 
529  /* update the up and down score depending on the chosen scoring parameter */
530  SCIP_CALL( SCIPupdateDistributionScore(scip, currentrowprob, newrowprobup, newrowprobdown, upscore, downscore, scoreparam) );
531 
532  SCIPdebugMessage(" Variable %s changes probability of row %s from %g to %g (branch up) or %g;\n",
533  SCIPvarGetName(var), SCIProwGetName(row), currentrowprob, newrowprobup, newrowprobdown);
534  SCIPdebugMessage(" --> new variable score: %g (for branching up), %g (for branching down)\n",
535  *upscore, *downscore);
536  }
537 
538  return SCIP_OKAY;
539 }
540 
541 /** free heuristic data */
542 static
544  SCIP* scip, /**< SCIP data structure */
545  SCIP_HEURDATA* heurdata /**< heuristic data */
546  )
547 {
548  assert(heurdata->memsize == 0 || heurdata->rowmeans != NULL);
549  assert(heurdata->memsize >= 0);
550 
551  if( heurdata->memsize > 0 )
552  {
553  SCIPfreeBufferArray(scip, &heurdata->rowmeans);
554  SCIPfreeBufferArray(scip, &heurdata->rowvariances);
555  SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesup);
556  SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesdown);
557 
558  heurdata->memsize = 0;
559  }
560 
561  if( heurdata->varpossmemsize > 0 )
562  {
563  SCIP_VAR** vars;
564  int v;
565 
566  assert(heurdata->varpossmemsize == SCIPgetNVars(scip));
567 
568  vars = SCIPgetVars(scip);
569  for( v = heurdata->varpossmemsize - 1; v >= 0; --v )
570  {
571  SCIP_VAR* var;
572 
573  var = vars[v];
574 
575  assert(var != NULL);
576  assert(v == SCIPvarGetProbindex(var));
577  SCIP_CALL( SCIPdropVarEvent(scip, var, EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, heurdata->varfilterposs[v]) );
578  }
579  SCIPfreeBufferArray(scip, &heurdata->currentlbs);
580  SCIPfreeBufferArray(scip, &heurdata->currentubs);
581  SCIPfreeBufferArray(scip, &heurdata->updatedvars);
582  SCIPfreeBufferArray(scip, &heurdata->varposs);
583  SCIPfreeBufferArray(scip, &heurdata->varfilterposs);
584  }
585  /* allocate variable update event processing array storage */
586 
587  heurdata->varpossmemsize = 0;
588  heurdata->nupdatedvars = 0;
589 
590  return SCIP_OKAY;
591 }
592 
593 /** add variable to the bound change event queue; skipped if variable is already in there, or if variable has
594  * no row currently watched
595  */
596 static
598  SCIP* scip, /**< SCIP data structure */
599  SCIP_HEURDATA* heurdata, /**< heuristic data */
600  SCIP_VAR* var /**< the variable whose bound changes need to be processed */
601  )
602 {
603  int varindex;
604  int varpos;
605 
606  assert(var != NULL);
607 
608  varindex = SCIPvarGetProbindex(var);
609  assert(-1 <= varindex && varindex < heurdata->varpossmemsize);
610 
611  /* if variable is not active, it should not be watched */
612  if( varindex == -1 )
613  return;
614  varpos = heurdata->varposs[varindex];
615  assert(varpos < heurdata->nupdatedvars);
616 
617  /* nothing to do if variable is already in the queue */
618  if( varpos >= 0 )
619  {
620  assert(heurdata->updatedvars[varpos] == var);
621 
622  return;
623  }
624 
625  /* if none of the variables rows was calculated yet, variable needs not to be watched */
626  assert((heurdata->currentlbs[varindex] == SCIP_INVALID)
627  == (heurdata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
628 
629  /* we don't need to enqueue the variable if it hasn't been watched so far */
630  if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 see above */
631  return;
632 
633  /* add the variable to the heuristic data of variables to process updates for */
634  assert(heurdata->varpossmemsize > heurdata->nupdatedvars);
635  varpos = heurdata->nupdatedvars;
636  heurdata->updatedvars[varpos] = var;
637  heurdata->varposs[varindex] = varpos;
638  ++heurdata->nupdatedvars;
639 }
640 
641 /** returns the next unprocessed variable (last in, first out) with pending bound changes, or NULL */
642 static
644  SCIP* scip, /**< SCIP data structure */
645  SCIP_HEURDATA* heurdata /**< heuristic data */
646  )
647 {
648  SCIP_VAR* var;
649  int varpos;
650  int varindex;
651 
652  assert(heurdata->nupdatedvars >= 0);
653 
654  /* return if no variable is currently pending */
655  if( heurdata->nupdatedvars == 0 )
656  return NULL;
657 
658  varpos = heurdata->nupdatedvars - 1;
659  var = heurdata->updatedvars[varpos];
660  assert(var != NULL);
661  varindex = SCIPvarGetProbindex(var);
662  assert(0 <= varindex && varindex < heurdata->varpossmemsize);
663  assert(varpos == heurdata->varposs[varindex]);
664 
665  heurdata->varposs[varindex] = -1;
666  heurdata->nupdatedvars--;
667 
668  return var;
669 }
670 
671 /** process a variable from the queue of changed variables */
672 static
674  SCIP* scip, /**< SCIP data structure */
675  SCIP_HEURDATA* heurdata, /**< heuristic data */
676  SCIP_VAR* var /**< the variable whose bound changes need to be processed */
677  )
678 {
679  SCIP_ROW** colrows;
680  SCIP_COL* varcol;
681  SCIP_Real* colvals;
682  SCIP_Real oldmean;
683  SCIP_Real newmean;
684  SCIP_Real oldvariance;
685  SCIP_Real newvariance;
686  SCIP_Real oldlb;
687  SCIP_Real newlb;
688  SCIP_Real oldub;
689  SCIP_Real newub;
690  SCIP_VARTYPE vartype;
691  int ncolrows;
692  int r;
693  int varindex;
694 
695  /* ensure that this is a probing bound change */
696  assert(SCIPinProbing(scip));
697 
698  assert(var != NULL);
699  varcol = SCIPvarGetCol(var);
700  assert(varcol != NULL);
701  colrows = SCIPcolGetRows(varcol);
702  colvals = SCIPcolGetVals(varcol);
703  ncolrows = SCIPcolGetNNonz(varcol);
704 
705  varindex = SCIPvarGetProbindex(var);
706 
707  oldlb = heurdata->currentlbs[varindex];
708  oldub = heurdata->currentubs[varindex];
709 
710  /* skip update if the variable has never been subject of previously calculated row activities */
711  assert((oldlb == SCIP_INVALID) == (oldub == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
712  if( oldlb == SCIP_INVALID ) /*lint !e777 */
713  return SCIP_OKAY;
714 
715  newlb = SCIPvarGetLbLocal(var);
716  newub = SCIPvarGetUbLocal(var);
717 
718  /* skip update if the bound change events have cancelled out */
719  if( SCIPisFeasEQ(scip, oldlb, newlb) && SCIPisFeasEQ(scip, oldub, newub) )
720  return SCIP_OKAY;
721 
722  /* calculate old and new variable distribution mean and variance */
723  oldvariance = 0.0;
724  newvariance = 0.0;
725  oldmean = 0.0;
726  newmean = 0.0;
727  vartype = SCIPvarGetType(var);
728  SCIPvarCalcDistributionParameters(scip, oldlb, oldub, vartype, &oldmean, &oldvariance);
729  SCIPvarCalcDistributionParameters(scip, newlb, newub, vartype, &newmean, &newvariance);
730 
731  /* loop over all rows of this variable and update activity distribution */
732  for( r = 0; r < ncolrows; ++r )
733  {
734  int rowpos;
735 
736  assert(colrows[r] != NULL);
737  rowpos = SCIProwGetIndex(colrows[r]);
738  assert(rowpos >= 0);
739 
740  SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, rowpos) );
741 
742  /* only consider rows for which activity distribution was already calculated */
743  if( heurdata->rowmeans[rowpos] != SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
744  {
745  SCIP_Real coeff;
746  SCIP_Real coeffsquared;
747  assert(heurdata->rowvariances[rowpos] != SCIP_INVALID
748  && SCIPisFeasGE(scip, heurdata->rowvariances[rowpos], 0.0)); /*lint !e777 */
749 
750  coeff = colvals[r];
751  coeffsquared = SQUARED(coeff);
752 
753  /* update variable contribution to row activity distribution */
754  heurdata->rowmeans[rowpos] += coeff * (newmean - oldmean);
755  heurdata->rowvariances[rowpos] += coeffsquared * (newvariance - oldvariance);
756  heurdata->rowvariances[rowpos] = MAX(0.0, heurdata->rowvariances[rowpos]);
757 
758  /* account for changes of the infinite contributions to row activities */
759  if( coeff > 0.0 )
760  {
761  /* if the coefficient is positive, upper bounds affect activity up */
762  if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
763  ++heurdata->rowinfinitiesup[rowpos];
764  else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
765  --heurdata->rowinfinitiesup[rowpos];
766 
767  if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
768  ++heurdata->rowinfinitiesdown[rowpos];
769  else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
770  --heurdata->rowinfinitiesdown[rowpos];
771  }
772  else if( coeff < 0.0 )
773  {
774  if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
775  ++heurdata->rowinfinitiesdown[rowpos];
776  else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
777  --heurdata->rowinfinitiesdown[rowpos];
778 
779  if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
780  ++heurdata->rowinfinitiesup[rowpos];
781  else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
782  --heurdata->rowinfinitiesup[rowpos];
783  }
784  assert(heurdata->rowinfinitiesdown[rowpos] >= 0);
785  assert(heurdata->rowinfinitiesup[rowpos] >= 0);
786  }
787  }
788 
789  /* store the new local bounds in the data */
790  heurdataUpdateCurrentBounds(scip, heurdata, var);
791 
792  return SCIP_OKAY;
793 }
794 
795 /** destructor of event handler to free user data (called when SCIP is exiting) */
796 static
797 SCIP_DECL_EVENTFREE(eventFreeDistributiondiving)
798 {
799  SCIP_EVENTHDLRDATA* eventhdlrdata;
800 
801  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
802  assert(eventhdlrdata != NULL);
803 
804  SCIPfreeMemory(scip, &eventhdlrdata);
805  SCIPeventhdlrSetData(eventhdlr, NULL);
806 
807  return SCIP_OKAY;
808 }
809 
810 /*
811  * Callback methods
812  */
813 
814 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
815 static
816 SCIP_DECL_HEURCOPY(heurCopyDistributiondiving)
817 { /*lint --e{715}*/
818  assert(scip != NULL);
819  assert(heur != NULL);
820  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
821 
822  /* call inclusion method of primal heuristic */
824 
825  return SCIP_OKAY;
826 }
827 
828 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
829 static
830 SCIP_DECL_HEURFREE(heurFreeDistributiondiving) /*lint --e{715}*/
831 { /*lint --e{715}*/
832  SCIP_HEURDATA* heurdata;
833 
834  assert(heur != NULL);
835  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
836  assert(scip != NULL);
837 
838  /* free heuristic data */
839  heurdata = SCIPheurGetData(heur);
840  assert(heurdata != NULL);
841  SCIPfreeMemory(scip, &heurdata);
842  SCIPheurSetData(heur, NULL);
843 
844  return SCIP_OKAY;
845 }
846 
847 
848 /** initialization method of primal heuristic (called after problem was transformed) */
849 static
850 SCIP_DECL_HEURINIT(heurInitDistributiondiving) /*lint --e{715}*/
851 { /*lint --e{715}*/
852  SCIP_HEURDATA* heurdata;
853 
854  assert(heur != NULL);
855  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
856 
857  /* get heuristic data */
858  heurdata = SCIPheurGetData(heur);
859  assert(heurdata != NULL);
860 
861  /* create working solution */
862  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
863 
864  return SCIP_OKAY;
865 }
866 
867 
868 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
869 static
870 SCIP_DECL_HEUREXIT(heurExitDistributiondiving) /*lint --e{715}*/
871 { /*lint --e{715}*/
872  SCIP_HEURDATA* heurdata;
873 
874  assert(heur != NULL);
875  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
876 
877  /* get heuristic data */
878  heurdata = SCIPheurGetData(heur);
879  assert(heurdata != NULL);
880 
881  /* free working solution */
882  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
883 
884  return SCIP_OKAY;
885 }
886 
887 /** scoring callback for distribution diving. best candidate maximizes the distribution score */
888 static
889 SCIP_DECL_DIVESETGETSCORE(divesetGetScoreDistributiondiving)
890 { /*lint --e{715}*/
891  SCIP_HEURDATA* heurdata;
892  SCIP_Real upscore;
893  SCIP_Real downscore;
894  int varindex;
895 
896  heurdata = SCIPheurGetData(SCIPdivesetGetHeur(diveset));
897  assert(heurdata != NULL);
898 
899  /* process pending bound change events */
900  while( heurdata->nupdatedvars > 0 )
901  {
902  SCIP_VAR* nextvar;
903 
904  /* pop the next variable from the queue and process its bound changes */
905  nextvar = heurdataPopBoundChangeVar(scip, heurdata);
906  assert(nextvar != NULL);
907  SCIP_CALL( varProcessBoundChanges(scip, heurdata, nextvar) );
908  }
909 
910  assert(cand != NULL);
911 
912  varindex = SCIPvarGetProbindex(cand);
913 
914  /* terminate with a penalty for inactive variables, which the plugin can currently not score
915  * this should never happen with default settings where only LP branching candidates are iterated, but might occur
916  * if other constraint handlers try to score an inactive variable that was (multi-)aggregated or negated
917  */
918  if( varindex == - 1 )
919  {
920  *score = -1.0;
921  *roundup = FALSE;
922 
923  return SCIP_OKAY;
924  }
925 
926 
927  /* in debug mode, ensure that all bound process events which occurred in the mean time have been captured
928  * by the heuristic event system
929  */
930  assert(SCIPisFeasLE(scip, SCIPvarGetLbLocal(cand), SCIPvarGetUbLocal(cand)));
931  assert(0 <= varindex && varindex < heurdata->varpossmemsize);
932 
933  assert((heurdata->currentlbs[varindex] == SCIP_INVALID)
934  == (heurdata->currentubs[varindex] == SCIP_INVALID));/*lint !e777 doesn't like comparing floats for equality */
935  assert((heurdata->currentlbs[varindex] == SCIP_INVALID)
936  || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(cand), heurdata->currentlbs[varindex])); /*lint !e777 */
937  assert((heurdata->currentubs[varindex] == SCIP_INVALID)
938  || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(cand), heurdata->currentubs[varindex])); /*lint !e777 */
939 
940  /* if the heuristic has not captured the variable bounds yet, this can be done now */
941  if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 */
942  heurdataUpdateCurrentBounds(scip, heurdata, cand);
943 
944  upscore = 0.0;
945  downscore = 0.0;
946 
947  /* loop over candidate rows and determine the candidate up- and down- branching score w.r.t. the score parameter */
948  SCIP_CALL( calcBranchScore(scip, heurdata, cand, candsol, &upscore, &downscore, heurdata->score) );
949 
950  /* score is simply the maximum of the two individual scores */
951  *roundup = (upscore > downscore);
952  *score = MAX(upscore, downscore);
953 
954  return SCIP_OKAY;
955 }
956 
957 
958 /** execution method of primal heuristic */
959 static
960 SCIP_DECL_HEUREXEC(heurExecDistributiondiving)
961 { /*lint --e{715}*/
962  SCIP_HEURDATA* heurdata;
963  SCIP_DIVESET* diveset;
964  int nlprows;
965 
966  assert(heur != NULL);
967  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
968  assert(scip != NULL);
969  assert(result != NULL);
970  assert(SCIPhasCurrentNodeLP(scip));
971 
972  *result = SCIP_DIDNOTRUN;
973 
974  /* get heuristic's data */
975  heurdata = SCIPheurGetData(heur);
976  assert(heurdata != NULL);
977  nlprows = SCIPgetNLPRows(scip);
978  if( nlprows == 0 )
979  return SCIP_OKAY;
980 
981  /* terminate if there are no integer variables (note that, e.g., SOS1 variables may be present) */
982  if( SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) == 0 )
983  return SCIP_OKAY;
984 
985  /* select and store the scoring parameter for this call of the heuristic */
986  if( heurdata->scoreparam == 'r' )
987  heurdata->score = SCOREPARAM_VALUES[SCIPheurGetNCalls(heur) % SCOREPARAM_VALUESLEN];
988  else
989  heurdata->score = heurdata->scoreparam;
990 
991  SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, nlprows) );
992  assert(SCIPheurGetNDivesets(heur) > 0);
993  assert(SCIPheurGetDivesets(heur) != NULL);
994  diveset = SCIPheurGetDivesets(heur)[0];
995  assert(diveset != NULL);
996 
997  SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible) );
998 
999  SCIP_CALL( heurdataFreeArrays(scip, heurdata) );
1000 
1001  return SCIP_OKAY;
1002 }
1003 
1004 /** event execution method of distribution branching which handles bound change events of variables */
1005 static
1006 SCIP_DECL_EVENTEXEC(eventExecDistribution)
1007 {
1008  SCIP_HEURDATA* heurdata;
1009  SCIP_EVENTHDLRDATA* eventhdlrdata;
1010  SCIP_VAR* var;
1011 
1012  assert(eventhdlr != NULL);
1013  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1014  assert(eventhdlrdata != NULL);
1015 
1016  heurdata = eventhdlrdata->heurdata;
1017  var = SCIPeventGetVar(event);
1018 
1019  /* add the variable to the queue of unprocessed variables; method itself ensures that every variable is added at most once */
1020  heurdataAddBoundChangeVar(scip, heurdata, var);
1021 
1022  return SCIP_OKAY;
1023 }
1024 
1025 /*
1026  * heuristic specific interface methods
1027  */
1028 
1029 /** creates the distributiondiving heuristic and includes it in SCIP */
1031  SCIP* scip /**< SCIP data structure */
1032  )
1033 {
1034  SCIP_HEURDATA* heurdata;
1035  SCIP_HEUR* heur;
1036  SCIP_EVENTHDLRDATA* eventhdlrdata;
1037 
1038  /* create distributiondiving data */
1039  heurdata = NULL;
1040  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
1041 
1042  heurdata->memsize = 0;
1043  heurdata->rowmeans = NULL;
1044  heurdata->rowvariances = NULL;
1045  heurdata->rowinfinitiesdown = NULL;
1046  heurdata->rowinfinitiesup = NULL;
1047  heurdata->varfilterposs = NULL;
1048  heurdata->currentlbs = NULL;
1049  heurdata->currentubs = NULL;
1050 
1051  /* create event handler first to finish heuristic data */
1052  eventhdlrdata = NULL;
1053  SCIP_CALL( SCIPallocMemory(scip, &eventhdlrdata) );
1054  eventhdlrdata->heurdata = heurdata;
1055 
1056  heurdata->eventhdlr = NULL;
1057  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &heurdata->eventhdlr, EVENTHDLR_NAME,
1058  "event handler for dynamic acitivity distribution updating",
1059  eventExecDistribution, eventhdlrdata) );
1060  assert( heurdata->eventhdlr != NULL);
1061  SCIP_CALL( SCIPsetEventhdlrFree(scip, heurdata->eventhdlr, eventFreeDistributiondiving) );
1062 
1063  /* include primal heuristic */
1064  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1066  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecDistributiondiving, heurdata) );
1067 
1068  assert(heur != NULL);
1069 
1070  /* set non-NULL pointers to callback methods */
1071  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDistributiondiving) );
1072  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDistributiondiving) );
1073  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitDistributiondiving) );
1074  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitDistributiondiving) );
1075 
1081  divesetGetScoreDistributiondiving) );
1082 
1083  SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/scoreparam",
1084  "the score;largest 'd'ifference, 'l'owest cumulative probability,'h'ighest c.p., 'v'otes lowest c.p., votes highest c.p.('w'), 'r'evolving",
1085  &heurdata->scoreparam, TRUE, DEFAULT_SCOREPARAM, "lvdhwr", NULL, NULL) );
1086 
1087  return SCIP_OKAY;
1088 }
#define DIVESET_DIVETYPES
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
probability based branching rule based on an article by J. Pryor and J.W. Chinneck ...
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:20589
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
#define SQUARED(x)
SCIP_RETCODE SCIPincludeHeurDistributiondiving(SCIP *scip)
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
static SCIP_DECL_DIVESETGETSCORE(divesetGetScoreDistributiondiving)
#define SCOREPARAM_VALUESLEN
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16623
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41920
static SCIP_RETCODE heurdataEnsureArraySize(SCIP *scip, SCIP_HEURDATA *heurdata, int maxindex)
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
library methods for diving heuristics
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:42032
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:940
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18861
#define SCOREPARAM_VALUES
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:129
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, unsigned int timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:7252
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:18984
#define FALSE
Definition: def.h:56
#define HEUR_NAME
#define HEUR_PRIORITY
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10743
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7778
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIP_CALL(x)
Definition: def.h:266
int SCIPheurGetNDivesets(SCIP_HEUR *heur)
Definition: heur.c:1355
#define HEUR_FREQ
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
SCIP_RETCODE SCIPcreateDiveset(SCIP *scip, SCIP_DIVESET **diveset, SCIP_HEUR *heur, const char *name, SCIP_Real minreldepth, SCIP_Real maxreldepth, SCIP_Real maxlpiterquot, SCIP_Real maxdiveubquot, SCIP_Real maxdiveavgquot, SCIP_Real maxdiveubquotnosol, SCIP_Real maxdiveavgquotnosol, SCIP_Real lpresolvedomchgquot, int lpsolvefreq, int maxlpiterofs, SCIP_Bool backtrack, SCIP_Bool onlylpbranchcands, SCIP_Bool specificsos1score, SCIP_DECL_DIVESETGETSCORE((*divesetgetscore)))
Definition: scip.c:7689
#define HEUR_USESSUBSCIP
static SCIP_RETCODE calcBranchScore(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var, SCIP_Real lpsolval, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
#define EVENT_DISTRIBUTION
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18881
SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
Definition: heur.c:1345
static SCIP_DECL_EVENTFREE(eventFreeDistributiondiving)
#define HEUR_FREQOFS
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:42044
void SCIPeventhdlrSetData(SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event.c:298
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_HEUR * SCIPdivesetGetHeur(SCIP_DIVESET *diveset)
Definition: heur.c:302
#define DEFAULT_MINRELDEPTH
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36622
#define EVENTHDLR_NAME
#define DEFAULT_MAXDIVEUBQUOTNOSOL
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:18784
#define DEFAULT_SCOREPARAM
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
#define DEFAULT_LPSOLVEFREQ
SCIP_Bool SCIPisSumPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41883
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41996
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28151
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
SCIP_SOL * sol
Definition: struct_heur.h:40
static SCIP_DECL_HEURCOPY(heurCopyDistributiondiving)
static SCIP_DECL_EVENTEXEC(eventExecDistribution)
#define HEUR_TIMING
static void rowCalculateGauss(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_ROW *row, SCIP_Real *mu, SCIP_Real *sigma2, int *rowinfinitiesdown, int *rowinfinitiesup)
#define DEFAULT_MAXLPITEROFS
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
void SCIPvarCalcDistributionParameters(SCIP *scip, SCIP_Real varlb, SCIP_Real varub, SCIP_VARTYPE vartype, SCIP_Real *mean, SCIP_Real *variance)
#define DEFAULT_MAXLPITERQUOT
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:288
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:26354
static SCIP_DECL_HEUREXIT(heurExitDistributiondiving)
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18974
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:32131
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
SCIP_RETCODE SCIPupdateDistributionScore(SCIP *scip, SCIP_Real currentprob, SCIP_Real newprobup, SCIP_Real newprobdown, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
#define SCIP_Bool
Definition: def.h:53
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_DECL_HEUREXEC(heurExecDistributiondiving)
#define HEUR_MAXDEPTH
static void heurdataUpdateCurrentBounds(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var)
static SCIP_RETCODE heurdataFreeArrays(SCIP *scip, SCIP_HEURDATA *heurdata)
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:7345
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:7329
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36668
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_RETCODE SCIPperformGenericDivingAlgorithm(SCIP *scip, SCIP_DIVESET *diveset, SCIP_SOL *worksol, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Bool nodeinfeasible)
Definition: dive.c:188
Diving heuristic that chooses fixings w.r.t. changes in the solution density after Pryor and Chinneck...
#define DEFAULT_BACKTRACK
static void heurdataAddBoundChangeVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var)
#define DEFAULT_MAXDIVEAVGQUOTNOSOL
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:10788
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
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
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
#define SCIP_Real
Definition: def.h:127
#define DEFAULT_ONLYLPBRANCHCANDS
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3657
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:28334
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41959
#define SCIP_INVALID
Definition: def.h:147
static SCIP_DECL_HEURFREE(heurFreeDistributiondiving)
SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
Definition: scip.c:7824
static SCIP_VAR * heurdataPopBoundChangeVar(SCIP *scip, SCIP_HEURDATA *heurdata)
#define HEUR_DESC
#define HEUR_DISPCHAR
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18836
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1058
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:58
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_Real SCIProwCalcProbability(SCIP *scip, SCIP_ROW *row, SCIP_Real mu, SCIP_Real sigma2, int rowinfinitiesdown, int rowinfinitiesup)
#define DEFAULT_LPRESOLVEDOMCHGQUOT
#define DEFAULT_MAXDIVEUBQUOT
static SCIP_DECL_HEURINIT(heurInitDistributiondiving)
static SCIP_RETCODE varProcessBoundChanges(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:18794
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:18759
int SCIPgetNLPRows(SCIP *scip)
Definition: scip.c:26806
#define DEFAULT_MAXRELDEPTH
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:34607
#define DEFAULT_MAXDIVEAVGQUOT