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