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
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 */
96struct 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
119struct 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 */
129static
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
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 */
217static
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 */
250static
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
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 */
362static
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));
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 */
564static
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 */
617static
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 */
661static
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 */
690static
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) */
813static
814SCIP_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) */
832static
833SCIP_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) */
846static
847SCIP_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) */
866static
867SCIP_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) */
886static
887SCIP_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 */
905static
906SCIP_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 */
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 */
972static
973SCIP_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) */
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 */
1018static
1019SCIP_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;
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 */
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}
probability based branching rule based on an article by J. Pryor and J.W. Chinneck
SCIP_Real * r
Definition: circlepacking.c:59
#define NULL
Definition: def.h:266
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:172
#define SQR(x)
Definition: def.h:213
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_RETCODE SCIPupdateDistributionScore(SCIP *scip, SCIP_Real currentprob, SCIP_Real newprobup, SCIP_Real newprobdown, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
SCIP_Real SCIProwCalcProbability(SCIP *scip, SCIP_ROW *row, SCIP_Real mu, SCIP_Real sigma2, int rowinfinitiesdown, int rowinfinitiesup)
void SCIPvarCalcDistributionParameters(SCIP *scip, SCIP_Real varlb, SCIP_Real varub, SCIP_VARTYPE vartype, SCIP_Real *mean, SCIP_Real *variance)
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2082
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
#define SCIPdebugMsg
Definition: scip_message.h:78
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_RETCODE SCIPincludeHeurDistributiondiving(SCIP *scip)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17042
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:17126
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:17161
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:17151
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
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
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:334
void SCIPeventhdlrSetData(SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event.c:344
SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
Definition: scip_event.c:150
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:354
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_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1053
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:162
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1364
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
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:178
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:210
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1579
int SCIPheurGetNDivesets(SCIP_HEUR *heur)
Definition: heur.c:1661
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:194
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1453
SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
Definition: heur.c:1651
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1374
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:626
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:97
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17213
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17238
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17351
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:17361
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:2010
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17258
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17248
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:180
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:837
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
SCIP_Bool SCIPisSumPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17788
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17747
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17598
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17537
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18143
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17583
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17767
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17418
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18133
SCIP_HEUR * SCIPdivesetGetHeur(SCIP_DIVESET *diveset)
Definition: heur.c:416
#define DEFAULT_ONLYLPBRANCHCANDS
#define DEFAULT_MAXDIVEUBQUOT
#define divesetAvailableDistributiondiving
#define DEFAULT_SCOREPARAM
#define DEFAULT_LPRESOLVEDOMCHGQUOT
static SCIP_DECL_EVENTFREE(eventFreeDistributiondiving)
#define EVENT_DISTRIBUTION
#define HEUR_TIMING
#define SCOREPARAM_VALUES
static SCIP_DECL_EVENTEXEC(eventExecDistribution)
#define DEFAULT_MAXLPITERQUOT
#define HEUR_FREQOFS
static SCIP_RETCODE calcBranchScore(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var, SCIP_Real lpsolval, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
static void rowCalculateGauss(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_ROW *row, SCIP_Real *mu, SCIP_Real *sigma2, int *rowinfinitiesdown, int *rowinfinitiesup)
#define HEUR_DESC
#define SCOREPARAM_VALUESLEN
static SCIP_DECL_HEURCOPY(heurCopyDistributiondiving)
static void heurdataUpdateCurrentBounds(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var)
#define DEFAULT_MAXDIVEAVGQUOT
#define DEFAULT_LPSOLVEFREQ
static SCIP_RETCODE varProcessBoundChanges(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var)
static SCIP_VAR * heurdataPopBoundChangeVar(SCIP_HEURDATA *heurdata)
#define DEFAULT_BACKTRACK
#define DEFAULT_MAXDIVEUBQUOTNOSOL
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define DEFAULT_MAXRELDEPTH
#define DEFAULT_MAXLPITEROFS
static SCIP_RETCODE heurdataEnsureArraySize(SCIP *scip, SCIP_HEURDATA *heurdata, int maxindex)
#define DEFAULT_MAXDIVEAVGQUOTNOSOL
#define HEUR_NAME
static SCIP_DECL_DIVESETGETSCORE(divesetGetScoreDistributiondiving)
static SCIP_RETCODE heurdataFreeArrays(SCIP *scip, SCIP_HEURDATA *heurdata)
static SCIP_DECL_HEURINIT(heurInitDistributiondiving)
static SCIP_DECL_HEUREXIT(heurExitDistributiondiving)
#define DEFAULT_RANDSEED
#define DIVESET_DIVETYPES
static SCIP_DECL_HEURFREE(heurFreeDistributiondiving)
static void heurdataAddBoundChangeVar(SCIP_HEURDATA *heurdata, SCIP_VAR *var)
#define DIVESET_ISPUBLIC
#define HEUR_FREQ
#define DEFAULT_MINRELDEPTH
#define HEUR_USESSUBSCIP
#define EVENTHDLR_NAME
static SCIP_DECL_HEUREXEC(heurExecDistributiondiving)
Diving heuristic that chooses fixings w.r.t. changes in the solution density after Pryor and Chinneck...
methods commonly used by primal heuristics
memory allocation routines
public methods for managing events
public methods for primal heuristics
public methods for LP management
public methods for message output
#define SCIPdebug(x)
Definition: pub_message.h:93
public methods for problem variables
public methods for event handler plugins and event handlers
general public methods
public methods for primal heuristic plugins and divesets
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
SCIP_SOL * sol
Definition: struct_heur.h:71
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:155
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
@ SCIP_DIVECONTEXT_SINGLE
Definition: type_heur.h:69
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:51
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73