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-2025 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 assert(scip != NULL);
391 assert(var != NULL);
392 assert(upscore != NULL);
393 assert(downscore != NULL);
394 assert(!SCIPisIntegral(scip, lpsolval) || SCIPvarIsBinary(var));
396
397 varcol = SCIPvarGetCol(var);
398 assert(varcol != NULL);
399
400 colrows = SCIPcolGetRows(varcol);
401 rowvals = SCIPcolGetVals(varcol);
402 ncolrows = SCIPcolGetNNonz(varcol);
403 varlb = SCIPvarGetLbLocal(var);
404 varub = SCIPvarGetUbLocal(var);
405 assert(varub - varlb > 0.5);
406 vartype = SCIPvarGetType(var);
407
408 /* calculate mean and variance of variable uniform distribution before and after branching */
409 currentmean = 0.0;
410 squaredbounddiff = 0.0;
411 SCIPvarCalcDistributionParameters(scip, varlb, varub, vartype, &currentmean, &squaredbounddiff);
412
413 /* unfixed binary variables may have an integer solution value in the LP solution, eg, at the presence of indicator constraints */
414 if( !SCIPvarIsBinary(var) )
415 {
416 newlb = SCIPfeasCeil(scip, lpsolval);
417 newub = SCIPfeasFloor(scip, lpsolval);
418 }
419 else
420 {
421 newlb = 1.0;
422 newub = 0.0;
423 }
424
425 /* calculate the variable's uniform distribution after branching up and down, respectively. */
426 squaredbounddiffup = 0.0;
427 meanup = 0.0;
428 SCIPvarCalcDistributionParameters(scip, newlb, varub, vartype, &meanup, &squaredbounddiffup);
429
430 /* calculate the distribution mean and variance for a variable with finite lower bound */
431 squaredbounddiffdown = 0.0;
432 meandown = 0.0;
433 SCIPvarCalcDistributionParameters(scip, varlb, newub, vartype, &meandown, &squaredbounddiffdown);
434
435 /* initialize the variable's up and down score */
436 *upscore = 0.0;
437 *downscore = 0.0;
438
439 /* loop over the variable rows and calculate the up and down score */
440 for( i = 0; i < ncolrows; ++i )
441 {
442 SCIP_ROW* row;
443 SCIP_Real changedrowmean;
444 SCIP_Real rowmean;
445 SCIP_Real rowvariance;
446 SCIP_Real changedrowvariance;
447 SCIP_Real currentrowprob;
448 SCIP_Real newrowprobup;
449 SCIP_Real newrowprobdown;
450 SCIP_Real squaredcoeff;
451 SCIP_Real rowval;
452 int rowinfinitiesdown;
453 int rowinfinitiesup;
454 int rowpos;
455
456 row = colrows[i];
457 rowval = rowvals[i];
458 assert(row != NULL);
459
460 /* we access the rows by their index */
461 rowpos = SCIProwGetIndex(row);
462
463 /* TODO add possibility to skip non-active rows by setting a user parameter */
464 /* if( SCIPisSumPositive(scip, SCIPgetRowLPFeasibility(scip, row)) )
465 continue;
466 */
467
468 /* call method to ensure sufficient data capacity */
469 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, rowpos) );
470
471 /* calculate row activity distribution if this is the first candidate to appear in this row */
472 if( heurdata->rowmeans[rowpos] == SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
473 {
474 rowCalculateGauss(scip, heurdata, row, &heurdata->rowmeans[rowpos], &heurdata->rowvariances[rowpos],
475 &heurdata->rowinfinitiesdown[rowpos], &heurdata->rowinfinitiesup[rowpos]);
476 }
477
478 /* retrieve the row distribution parameters from the branch rule data */
479 rowmean = heurdata->rowmeans[rowpos];
480 rowvariance = heurdata->rowvariances[rowpos];
481 rowinfinitiesdown = heurdata->rowinfinitiesdown[rowpos];
482 rowinfinitiesup = heurdata->rowinfinitiesup[rowpos];
483 assert(!SCIPisNegative(scip, rowvariance));
484
485 currentrowprob = SCIProwCalcProbability(scip, row, rowmean, rowvariance,
486 rowinfinitiesdown, rowinfinitiesup);
487
488 /* get variable's current expected contribution to row activity */
489 squaredcoeff = SQR(rowval);
490
491 /* first, get the probability change for the row if the variable is branched on upwards. The probability
492 * can only be affected if the variable upper bound is finite
493 */
494 if( !SCIPisInfinity(scip, varub) )
495 {
496 int rowinftiesdownafterbranch;
497 int rowinftiesupafterbranch;
498
499 /* calculate how branching would affect the row parameters */
500 changedrowmean = rowmean + rowval * (meanup - currentmean);
501 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffup - squaredbounddiff);
502 changedrowvariance = MAX(0.0, changedrowvariance);
503
504 rowinftiesdownafterbranch = rowinfinitiesdown;
505 rowinftiesupafterbranch = rowinfinitiesup;
506
507 /* account for changes of the row's infinite bound contributions */
508 if( SCIPisInfinity(scip, -varlb) && rowval < 0.0 )
509 rowinftiesupafterbranch--;
510 if( SCIPisInfinity(scip, -varlb) && rowval > 0.0 )
511 rowinftiesdownafterbranch--;
512
513 assert(rowinftiesupafterbranch >= 0);
514 assert(rowinftiesdownafterbranch >= 0);
515 newrowprobup = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
516 rowinftiesupafterbranch);
517 }
518 else
519 newrowprobup = currentrowprob;
520
521 /* do the same for the other branching direction */
522 if( !SCIPisInfinity(scip, varlb) )
523 {
524 int rowinftiesdownafterbranch;
525 int rowinftiesupafterbranch;
526
527 changedrowmean = rowmean + rowval * (meandown - currentmean);
528 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffdown - squaredbounddiff);
529 changedrowvariance = MAX(0.0, changedrowvariance);
530
531 rowinftiesdownafterbranch = rowinfinitiesdown;
532 rowinftiesupafterbranch = rowinfinitiesup;
533
534 /* account for changes of the row's infinite bound contributions */
535 if( SCIPisInfinity(scip, varub) && rowval > 0.0 )
536 rowinftiesupafterbranch -= 1;
537 if( SCIPisInfinity(scip, varub) && rowval < 0.0 )
538 rowinftiesdownafterbranch -= 1;
539
540 assert(rowinftiesdownafterbranch >= 0);
541 assert(rowinftiesupafterbranch >= 0);
542 newrowprobdown = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
543 rowinftiesupafterbranch);
544 }
545 else
546 newrowprobdown = currentrowprob;
547
548 /* update the up and down score depending on the chosen scoring parameter */
549 SCIP_CALL( SCIPupdateDistributionScore(scip, currentrowprob, newrowprobup, newrowprobdown, upscore, downscore, scoreparam) );
550
551 SCIPdebugMsg(scip, " Variable %s changes probability of row %s from %g to %g (branch up) or %g;\n",
552 SCIPvarGetName(var), SCIProwGetName(row), currentrowprob, newrowprobup, newrowprobdown);
553 SCIPdebugMsg(scip, " --> new variable score: %g (for branching up), %g (for branching down)\n",
554 *upscore, *downscore);
555 }
556
557 return SCIP_OKAY;
558}
559
560/** free heuristic data */
561static
563 SCIP* scip, /**< SCIP data structure */
564 SCIP_HEURDATA* heurdata /**< heuristic data */
565 )
566{
567 assert(heurdata->memsize == 0 || heurdata->rowmeans != NULL);
568 assert(heurdata->memsize >= 0);
569
570 if( heurdata->varpossmemsize > 0 )
571 {
572 SCIP_VAR** vars;
573 int v;
574
575 assert(heurdata->varpossmemsize == SCIPgetNVars(scip));
576
577 vars = SCIPgetVars(scip);
578 for( v = heurdata->varpossmemsize - 1; v >= 0; --v )
579 {
580 SCIP_VAR* var;
581
582 var = vars[v];
583
584 assert(var != NULL);
585 assert(v == SCIPvarGetProbindex(var));
586 SCIP_CALL( SCIPdropVarEvent(scip, var, EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, heurdata->varfilterposs[v]) );
587 }
588 SCIPfreeBufferArray(scip, &heurdata->currentlbs);
589 SCIPfreeBufferArray(scip, &heurdata->currentubs);
590 SCIPfreeBufferArray(scip, &heurdata->updatedvars);
591 SCIPfreeBufferArray(scip, &heurdata->varposs);
592 SCIPfreeBufferArray(scip, &heurdata->varfilterposs);
593 }
594
595 if( heurdata->memsize > 0 )
596 {
597 SCIPfreeBufferArray(scip, &heurdata->rowvariances);
598 SCIPfreeBufferArray(scip, &heurdata->rowmeans);
599 SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesup);
600 SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesdown);
601
602 heurdata->memsize = 0;
603 }
604
605 heurdata->varpossmemsize = 0;
606 heurdata->nupdatedvars = 0;
607
608 return SCIP_OKAY;
609}
610
611/** add variable to the bound change event queue; skipped if variable is already in there, or if variable has
612 * no row currently watched
613 */
614static
616 SCIP_HEURDATA* heurdata, /**< heuristic data */
617 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
618 )
619{
620 int varindex;
621 int varpos;
622
623 assert(var != NULL);
624
625 varindex = SCIPvarGetProbindex(var);
626 assert(-1 <= varindex && varindex < heurdata->varpossmemsize);
627
628 /* if variable is not active, it should not be watched */
629 if( varindex == -1 )
630 return;
631 varpos = heurdata->varposs[varindex];
632 assert(varpos < heurdata->nupdatedvars);
633
634 /* nothing to do if variable is already in the queue */
635 if( varpos >= 0 )
636 {
637 assert(heurdata->updatedvars[varpos] == var);
638
639 return;
640 }
641
642 /* if none of the variables rows was calculated yet, variable needs not to be watched */
643 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) == (heurdata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
644
645 /* we don't need to enqueue the variable if it hasn't been watched so far */
646 if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 see above */
647 return;
648
649 /* add the variable to the heuristic data of variables to process updates for */
650 assert(heurdata->varpossmemsize > heurdata->nupdatedvars);
651 varpos = heurdata->nupdatedvars;
652 heurdata->updatedvars[varpos] = var;
653 heurdata->varposs[varindex] = varpos;
654 ++heurdata->nupdatedvars;
655}
656
657/** returns the next unprocessed variable (last in, first out) with pending bound changes, or NULL */
658static
660 SCIP_HEURDATA* heurdata /**< heuristic data */
661 )
662{
663 SCIP_VAR* var;
664 int varpos;
665 int varindex;
666
667 assert(heurdata->nupdatedvars >= 0);
668
669 /* return if no variable is currently pending */
670 if( heurdata->nupdatedvars == 0 )
671 return NULL;
672
673 varpos = heurdata->nupdatedvars - 1;
674 var = heurdata->updatedvars[varpos];
675 assert(var != NULL);
676 varindex = SCIPvarGetProbindex(var);
677 assert(0 <= varindex && varindex < heurdata->varpossmemsize);
678 assert(varpos == heurdata->varposs[varindex]);
679
680 heurdata->varposs[varindex] = -1;
681 heurdata->nupdatedvars--;
682
683 return var;
684}
685
686/** process a variable from the queue of changed variables */
687static
689 SCIP* scip, /**< SCIP data structure */
690 SCIP_HEURDATA* heurdata, /**< heuristic data */
691 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
692 )
693{
694 SCIP_ROW** colrows;
695 SCIP_COL* varcol;
696 SCIP_Real* colvals;
697 SCIP_Real oldmean;
698 SCIP_Real newmean;
699 SCIP_Real oldvariance;
700 SCIP_Real newvariance;
701 SCIP_Real oldlb;
702 SCIP_Real newlb;
703 SCIP_Real oldub;
704 SCIP_Real newub;
705 SCIP_VARTYPE vartype;
706 int ncolrows;
707 int r;
708 int varindex;
709
710 /* ensure that this is a probing bound change */
711 assert(SCIPinProbing(scip));
712
713 assert(var != NULL);
714 varcol = SCIPvarGetCol(var);
715 assert(varcol != NULL);
716 colrows = SCIPcolGetRows(varcol);
717 colvals = SCIPcolGetVals(varcol);
718 ncolrows = SCIPcolGetNNonz(varcol);
719
720 varindex = SCIPvarGetProbindex(var);
721
722 oldlb = heurdata->currentlbs[varindex];
723 oldub = heurdata->currentubs[varindex];
724
725 /* skip update if the variable has never been subject of previously calculated row activities */
726 assert((oldlb == SCIP_INVALID) == (oldub == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
727 if( oldlb == SCIP_INVALID ) /*lint !e777 */
728 return SCIP_OKAY;
729
730 newlb = SCIPvarGetLbLocal(var);
731 newub = SCIPvarGetUbLocal(var);
732
733 /* skip update if the bound change events have cancelled out */
734 if( SCIPisFeasEQ(scip, oldlb, newlb) && SCIPisFeasEQ(scip, oldub, newub) )
735 return SCIP_OKAY;
736
737 /* calculate old and new variable distribution mean and variance */
738 oldvariance = 0.0;
739 newvariance = 0.0;
740 oldmean = 0.0;
741 newmean = 0.0;
742 vartype = SCIPvarGetType(var);
743 SCIPvarCalcDistributionParameters(scip, oldlb, oldub, vartype, &oldmean, &oldvariance);
744 SCIPvarCalcDistributionParameters(scip, newlb, newub, vartype, &newmean, &newvariance);
745
746 /* loop over all rows of this variable and update activity distribution */
747 for( r = 0; r < ncolrows; ++r )
748 {
749 int rowpos;
750
751 assert(colrows[r] != NULL);
752 rowpos = SCIProwGetIndex(colrows[r]);
753 assert(rowpos >= 0);
754
755 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, rowpos) );
756
757 /* only consider rows for which activity distribution was already calculated */
758 if( heurdata->rowmeans[rowpos] != SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
759 {
760 SCIP_Real coeff;
761 SCIP_Real coeffsquared;
762 assert(heurdata->rowvariances[rowpos] != SCIP_INVALID && SCIPisFeasGE(scip, heurdata->rowvariances[rowpos], 0.0)); /*lint !e777 */
763
764 coeff = colvals[r];
765 coeffsquared = SQR(coeff);
766
767 /* update variable contribution to row activity distribution */
768 heurdata->rowmeans[rowpos] += coeff * (newmean - oldmean);
769 heurdata->rowvariances[rowpos] += coeffsquared * (newvariance - oldvariance);
770 heurdata->rowvariances[rowpos] = MAX(0.0, heurdata->rowvariances[rowpos]);
771
772 /* account for changes of the infinite contributions to row activities */
773 if( coeff > 0.0 )
774 {
775 /* if the coefficient is positive, upper bounds affect activity up */
776 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
777 ++heurdata->rowinfinitiesup[rowpos];
778 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
779 --heurdata->rowinfinitiesup[rowpos];
780
781 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
782 ++heurdata->rowinfinitiesdown[rowpos];
783 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
784 --heurdata->rowinfinitiesdown[rowpos];
785 }
786 else if( coeff < 0.0 )
787 {
788 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
789 ++heurdata->rowinfinitiesdown[rowpos];
790 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
791 --heurdata->rowinfinitiesdown[rowpos];
792
793 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
794 ++heurdata->rowinfinitiesup[rowpos];
795 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
796 --heurdata->rowinfinitiesup[rowpos];
797 }
798 assert(heurdata->rowinfinitiesdown[rowpos] >= 0);
799 assert(heurdata->rowinfinitiesup[rowpos] >= 0);
800 }
801 }
802
803 /* store the new local bounds in the data */
804 heurdataUpdateCurrentBounds(scip, heurdata, var);
805
806 return SCIP_OKAY;
807}
808
809/** destructor of event handler to free user data (called when SCIP is exiting) */
810static
811SCIP_DECL_EVENTFREE(eventFreeDistributiondiving)
812{
813 SCIP_EVENTHDLRDATA* eventhdlrdata;
814
815 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
816 assert(eventhdlrdata != NULL);
817
818 SCIPfreeBlockMemory(scip, &eventhdlrdata);
819 SCIPeventhdlrSetData(eventhdlr, NULL);
820
821 return SCIP_OKAY;
822}
823
824/*
825 * Callback methods
826 */
827
828/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
829static
830SCIP_DECL_HEURCOPY(heurCopyDistributiondiving)
831{ /*lint --e{715}*/
832 assert(scip != NULL);
833 assert(heur != NULL);
834 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
835
836 /* call inclusion method of primal heuristic */
838
839 return SCIP_OKAY;
840}
841
842/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
843static
844SCIP_DECL_HEURFREE(heurFreeDistributiondiving) /*lint --e{715}*/
845{ /*lint --e{715}*/
846 SCIP_HEURDATA* heurdata;
847
848 assert(heur != NULL);
849 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
850 assert(scip != NULL);
851
852 /* free heuristic data */
853 heurdata = SCIPheurGetData(heur);
854 assert(heurdata != NULL);
855 SCIPfreeBlockMemory(scip, &heurdata);
856 SCIPheurSetData(heur, NULL);
857
858 return SCIP_OKAY;
859}
860
861
862/** initialization method of primal heuristic (called after problem was transformed) */
863static
864SCIP_DECL_HEURINIT(heurInitDistributiondiving) /*lint --e{715}*/
865{ /*lint --e{715}*/
866 SCIP_HEURDATA* heurdata;
867
868 assert(heur != NULL);
869 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
870
871 /* get heuristic data */
872 heurdata = SCIPheurGetData(heur);
873 assert(heurdata != NULL);
874
875 /* create working solution */
876 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
877
878 return SCIP_OKAY;
879}
880
881
882/** deinitialization method of primal heuristic (called before transformed problem is freed) */
883static
884SCIP_DECL_HEUREXIT(heurExitDistributiondiving) /*lint --e{715}*/
885{ /*lint --e{715}*/
886 SCIP_HEURDATA* heurdata;
887
888 assert(heur != NULL);
889 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
890
891 /* get heuristic data */
892 heurdata = SCIPheurGetData(heur);
893 assert(heurdata != NULL);
894
895 /* free working solution */
896 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
897
898 return SCIP_OKAY;
899}
900
901/** scoring callback for distribution diving. best candidate maximizes the distribution score */
902static
903SCIP_DECL_DIVESETGETSCORE(divesetGetScoreDistributiondiving)
904{ /*lint --e{715}*/
905 SCIP_HEURDATA* heurdata;
906 SCIP_Real upscore;
907 SCIP_Real downscore;
908 int varindex;
909
910 heurdata = SCIPheurGetData(SCIPdivesetGetHeur(diveset));
911 assert(heurdata != NULL);
912
913 /* process pending bound change events */
914 while( heurdata->nupdatedvars > 0 )
915 {
916 SCIP_VAR* nextvar;
917
918 /* pop the next variable from the queue and process its bound changes */
919 nextvar = heurdataPopBoundChangeVar(heurdata);
920 assert(nextvar != NULL);
921 SCIP_CALL( varProcessBoundChanges(scip, heurdata, nextvar) );
922 }
923
924 assert(cand != NULL);
925
926 varindex = SCIPvarGetProbindex(cand);
927
928 /* terminate with a penalty for inactive variables, which the plugin can currently not score
929 * this should never happen with default settings where only LP branching candidates are iterated, but might occur
930 * if other constraint handlers try to score an inactive variable that was (multi-)aggregated or negated
931 */
932 if( varindex == - 1 )
933 {
934 *score = -1.0;
935 *roundup = FALSE;
936
937 return SCIP_OKAY;
938 }
939
940 /* in debug mode, ensure that all bound process events which occurred in the mean time have been captured
941 * by the heuristic event system
942 */
944 assert(0 <= varindex && varindex < heurdata->varpossmemsize);
945
946 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) == (heurdata->currentubs[varindex] == SCIP_INVALID));/*lint !e777 doesn't like comparing floats for equality */
947 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(cand), heurdata->currentlbs[varindex])); /*lint !e777 */
948 assert((heurdata->currentubs[varindex] == SCIP_INVALID) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(cand), heurdata->currentubs[varindex])); /*lint !e777 */
949
950 /* if the heuristic has not captured the variable bounds yet, this can be done now */
951 if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 */
952 heurdataUpdateCurrentBounds(scip, heurdata, cand);
953
954 upscore = 0.0;
955 downscore = 0.0;
956
957 /* loop over candidate rows and determine the candidate up- and down- branching score w.r.t. the score parameter */
958 SCIP_CALL( calcBranchScore(scip, heurdata, cand, candsol, &upscore, &downscore, heurdata->score) );
959
960 /* score is simply the maximum of the two individual scores */
961 *roundup = (upscore > downscore);
962 *score = MAX(upscore, downscore);
963
964 return SCIP_OKAY;
965}
966
967
968/** execution method of primal heuristic */
969static
970SCIP_DECL_HEUREXEC(heurExecDistributiondiving)
971{ /*lint --e{715}*/
972 SCIP_HEURDATA* heurdata;
973 SCIP_DIVESET* diveset;
974 int nlprows;
975
976 assert(heur != NULL);
977 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
978 assert(scip != NULL);
979 assert(result != NULL);
980 assert(SCIPhasCurrentNodeLP(scip));
981
982 *result = SCIP_DIDNOTRUN;
983
984 /* get heuristic's data */
985 heurdata = SCIPheurGetData(heur);
986 assert(heurdata != NULL);
987 nlprows = SCIPgetNLPRows(scip);
988 if( nlprows == 0 )
989 return SCIP_OKAY;
990
991 /* terminate if there are no integer variables (note that, e.g., SOS1 variables may be present) */
993 return SCIP_OKAY;
994
995 /* select and store the scoring parameter for this call of the heuristic */
996 if( heurdata->scoreparam == 'r' )
998 else
999 heurdata->score = heurdata->scoreparam;
1000
1001 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, nlprows) );
1002 assert(SCIPheurGetNDivesets(heur) > 0);
1003 assert(SCIPheurGetDivesets(heur) != NULL);
1004 diveset = SCIPheurGetDivesets(heur)[0];
1005 assert(diveset != NULL);
1006
1007 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible, -1L, -1, -1.0, SCIP_DIVECONTEXT_SINGLE) );
1008
1009 SCIP_CALL( heurdataFreeArrays(scip, heurdata) );
1010
1011 return SCIP_OKAY;
1012}
1013
1014/** event execution method of distribution branching which handles bound change events of variables */
1015static
1016SCIP_DECL_EVENTEXEC(eventExecDistribution)
1017{
1018 SCIP_HEURDATA* heurdata;
1019 SCIP_EVENTHDLRDATA* eventhdlrdata;
1020 SCIP_VAR* var;
1021
1022 assert(eventhdlr != NULL);
1023 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1024 assert(eventhdlrdata != NULL);
1025
1026 heurdata = eventhdlrdata->heurdata;
1027 var = SCIPeventGetVar(event);
1028
1029 /* add the variable to the queue of unprocessed variables; method itself ensures that every variable is added at most once */
1030 heurdataAddBoundChangeVar(heurdata, var);
1031
1032 return SCIP_OKAY;
1033}
1034
1035/*
1036 * heuristic specific interface methods
1037 */
1038
1039#define divesetAvailableDistributiondiving NULL
1040
1041/** creates the distributiondiving heuristic and includes it in SCIP */
1043 SCIP* scip /**< SCIP data structure */
1044 )
1045{
1046 SCIP_HEURDATA* heurdata;
1047 SCIP_HEUR* heur;
1048 SCIP_EVENTHDLRDATA* eventhdlrdata;
1049
1050 /* create distributiondiving data */
1051 heurdata = NULL;
1052 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1053
1054 heurdata->memsize = 0;
1055 heurdata->rowmeans = NULL;
1056 heurdata->rowvariances = NULL;
1057 heurdata->rowinfinitiesdown = NULL;
1058 heurdata->rowinfinitiesup = NULL;
1059 heurdata->varfilterposs = NULL;
1060 heurdata->currentlbs = NULL;
1061 heurdata->currentubs = NULL;
1062
1063 /* create event handler first to finish heuristic data */
1064 eventhdlrdata = NULL;
1065 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
1066 eventhdlrdata->heurdata = heurdata;
1067
1068 heurdata->eventhdlr = NULL;
1070 "event handler for dynamic acitivity distribution updating",
1071 eventExecDistribution, eventhdlrdata) );
1072 assert( heurdata->eventhdlr != NULL);
1073 SCIP_CALL( SCIPsetEventhdlrFree(scip, heurdata->eventhdlr, eventFreeDistributiondiving) );
1074
1075 /* include primal heuristic */
1078 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecDistributiondiving, heurdata) );
1079
1080 assert(heur != NULL);
1081
1082 /* set non-NULL pointers to callback methods */
1083 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDistributiondiving) );
1084 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDistributiondiving) );
1085 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitDistributiondiving) );
1086 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitDistributiondiving) );
1087
1088 /* add diveset with the defined scoring function */
1094 divesetGetScoreDistributiondiving, divesetAvailableDistributiondiving) );
1095
1096 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/scoreparam",
1097 "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",
1098 &heurdata->scoreparam, TRUE, DEFAULT_SCOREPARAM, "lvdhwr", NULL, NULL) );
1099
1100 return SCIP_OKAY;
1101}
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:262
#define SCIP_INVALID
Definition: def.h:192
#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:234
#define SCIP_CALL(x)
Definition: def.h:369
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:17071
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:17155
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:17190
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:17180
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:323
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:111
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:157
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:361
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:407
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:167
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:122
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:183
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:215
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:199
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:84
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:627
#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:17242
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17267
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2216
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17380
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:17390
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17287
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17277
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 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:17807
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17766
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17617
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17556
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18162
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17602
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17786
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17437
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18152
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