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), SCIPvarGetImplType(colvar),
346 &varmean, &varvariance);
347
348 /* actual values are updated; the contribution of the variable to mu is the arithmetic mean of its bounds */
349 *mu += colval * varmean;
350
351 /* 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 */
352 squarecoeff = SQR(colval);
353 *sigma2 += squarecoeff * varvariance;
354
355 assert(!SCIPisFeasNegative(scip, *sigma2));
356 }
357
359 SCIPdebugMsg(scip, " Row %s has a mean value of %g at a sigma2 of %g \n", SCIProwGetName(row), *mu, *sigma2);
360}
361
362/** calculate the branching score of a variable, depending on the chosen score parameter */
363static
365 SCIP* scip, /**< current SCIP */
366 SCIP_HEURDATA* heurdata, /**< branch rule data */
367 SCIP_VAR* var, /**< candidate variable */
368 SCIP_Real lpsolval, /**< current fractional LP-relaxation solution value */
369 SCIP_Real* upscore, /**< pointer to store the variable score when branching on it in upward direction */
370 SCIP_Real* downscore, /**< pointer to store the variable score when branching on it in downward direction */
371 char scoreparam /**< the score parameter of this heuristic */
372 )
373{
374 SCIP_COL* varcol;
375 SCIP_ROW** colrows;
376 SCIP_Real* rowvals;
377 SCIP_Real varlb;
378 SCIP_Real varub;
379 SCIP_Real squaredbounddiff; /* current squared difference of variable bounds (ub - lb)^2 */
380 SCIP_Real newub; /* new upper bound if branching downwards */
381 SCIP_Real newlb; /* new lower bound if branching upwards */
382 SCIP_Real squaredbounddiffup; /* squared difference after branching upwards (ub - lb')^2 */
383 SCIP_Real squaredbounddiffdown; /* squared difference after branching downwards (ub' - lb)^2 */
384 SCIP_Real currentmean; /* current mean value of variable uniform distribution */
385 SCIP_Real meanup; /* mean value of variable uniform distribution after branching up */
386 SCIP_Real meandown; /* mean value of variable uniform distribution after branching down*/
387 SCIP_VARTYPE vartype;
388 SCIP_IMPLINTTYPE impltype;
389 int ncolrows;
390 int i;
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 impltype = SCIPvarGetImplType(var);
410
411 /* calculate mean and variance of variable uniform distribution before and after branching */
412 currentmean = 0.0;
413 squaredbounddiff = 0.0;
414 SCIPvarCalcDistributionParameters(scip, varlb, varub, vartype, impltype, &currentmean, &squaredbounddiff);
415
416 /* unfixed binary variables may have an integer solution value in the LP solution, eg, at the presence of indicator constraints */
417 if( !SCIPvarIsBinary(var) )
418 {
419 newlb = SCIPfeasCeil(scip, lpsolval);
420 newub = SCIPfeasFloor(scip, lpsolval);
421 }
422 else
423 {
424 newlb = 1.0;
425 newub = 0.0;
426 }
427
428 /* calculate the variable's uniform distribution after branching up and down, respectively. */
429 squaredbounddiffup = 0.0;
430 meanup = 0.0;
431 SCIPvarCalcDistributionParameters(scip, newlb, varub, vartype, impltype, &meanup, &squaredbounddiffup);
432
433 /* calculate the distribution mean and variance for a variable with finite lower bound */
434 squaredbounddiffdown = 0.0;
435 meandown = 0.0;
436 SCIPvarCalcDistributionParameters(scip, varlb, newub, vartype, impltype, &meandown, &squaredbounddiffdown);
437
438 /* initialize the variable's up and down score */
439 *upscore = 0.0;
440 *downscore = 0.0;
441
442 /* loop over the variable rows and calculate the up and down score */
443 for( i = 0; i < ncolrows; ++i )
444 {
445 SCIP_ROW* row;
446 SCIP_Real changedrowmean;
447 SCIP_Real rowmean;
448 SCIP_Real rowvariance;
449 SCIP_Real changedrowvariance;
450 SCIP_Real currentrowprob;
451 SCIP_Real newrowprobup;
452 SCIP_Real newrowprobdown;
453 SCIP_Real squaredcoeff;
454 SCIP_Real rowval;
455 int rowinfinitiesdown;
456 int rowinfinitiesup;
457 int rowpos;
458
459 row = colrows[i];
460 rowval = rowvals[i];
461 assert(row != NULL);
462
463 /* we access the rows by their index */
464 rowpos = SCIProwGetIndex(row);
465
466 /* TODO add possibility to skip non-active rows by setting a user parameter */
467 /* if( SCIPisSumPositive(scip, SCIPgetRowLPFeasibility(scip, row)) )
468 continue;
469 */
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 SCIP_IMPLINTTYPE impltype;
710 int ncolrows;
711 int r;
712 int varindex;
713
714 /* ensure that this is a probing bound change */
715 assert(SCIPinProbing(scip));
716
717 assert(var != NULL);
718 varcol = SCIPvarGetCol(var);
719 assert(varcol != NULL);
720 colrows = SCIPcolGetRows(varcol);
721 colvals = SCIPcolGetVals(varcol);
722 ncolrows = SCIPcolGetNNonz(varcol);
723
724 varindex = SCIPvarGetProbindex(var);
725
726 oldlb = heurdata->currentlbs[varindex];
727 oldub = heurdata->currentubs[varindex];
728
729 /* skip update if the variable has never been subject of previously calculated row activities */
730 assert((oldlb == SCIP_INVALID) == (oldub == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
731 if( oldlb == SCIP_INVALID ) /*lint !e777 */
732 return SCIP_OKAY;
733
734 newlb = SCIPvarGetLbLocal(var);
735 newub = SCIPvarGetUbLocal(var);
736
737 /* skip update if the bound change events have cancelled out */
738 if( SCIPisFeasEQ(scip, oldlb, newlb) && SCIPisFeasEQ(scip, oldub, newub) )
739 return SCIP_OKAY;
740
741 /* calculate old and new variable distribution mean and variance */
742 oldvariance = 0.0;
743 newvariance = 0.0;
744 oldmean = 0.0;
745 newmean = 0.0;
746 vartype = SCIPvarGetType(var);
747 impltype = SCIPvarGetImplType(var);
748 SCIPvarCalcDistributionParameters(scip, oldlb, oldub, vartype, impltype, &oldmean, &oldvariance);
749 SCIPvarCalcDistributionParameters(scip, newlb, newub, vartype, impltype, &newmean, &newvariance);
750
751 /* loop over all rows of this variable and update activity distribution */
752 for( r = 0; r < ncolrows; ++r )
753 {
754 int rowpos;
755
756 assert(colrows[r] != NULL);
757 rowpos = SCIProwGetIndex(colrows[r]);
758 assert(rowpos >= 0);
759
760 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, rowpos) );
761
762 /* only consider rows for which activity distribution was already calculated */
763 if( heurdata->rowmeans[rowpos] != SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
764 {
765 SCIP_Real coeff;
766 SCIP_Real coeffsquared;
767 assert(heurdata->rowvariances[rowpos] != SCIP_INVALID && SCIPisFeasGE(scip, heurdata->rowvariances[rowpos], 0.0)); /*lint !e777 */
768
769 coeff = colvals[r];
770 coeffsquared = SQR(coeff);
771
772 /* update variable contribution to row activity distribution */
773 heurdata->rowmeans[rowpos] += coeff * (newmean - oldmean);
774 heurdata->rowvariances[rowpos] += coeffsquared * (newvariance - oldvariance);
775 heurdata->rowvariances[rowpos] = MAX(0.0, heurdata->rowvariances[rowpos]);
776
777 /* account for changes of the infinite contributions to row activities */
778 if( coeff > 0.0 )
779 {
780 /* if the coefficient is positive, upper bounds affect activity up */
781 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
782 ++heurdata->rowinfinitiesup[rowpos];
783 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
784 --heurdata->rowinfinitiesup[rowpos];
785
786 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
787 ++heurdata->rowinfinitiesdown[rowpos];
788 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
789 --heurdata->rowinfinitiesdown[rowpos];
790 }
791 else if( coeff < 0.0 )
792 {
793 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
794 ++heurdata->rowinfinitiesdown[rowpos];
795 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
796 --heurdata->rowinfinitiesdown[rowpos];
797
798 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
799 ++heurdata->rowinfinitiesup[rowpos];
800 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
801 --heurdata->rowinfinitiesup[rowpos];
802 }
803 assert(heurdata->rowinfinitiesdown[rowpos] >= 0);
804 assert(heurdata->rowinfinitiesup[rowpos] >= 0);
805 }
806 }
807
808 /* store the new local bounds in the data */
809 heurdataUpdateCurrentBounds(scip, heurdata, var);
810
811 return SCIP_OKAY;
812}
813
814/** destructor of event handler to free user data (called when SCIP is exiting) */
815static
816SCIP_DECL_EVENTFREE(eventFreeDistributiondiving)
817{
818 SCIP_EVENTHDLRDATA* eventhdlrdata;
819
820 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
821 assert(eventhdlrdata != NULL);
822
823 SCIPfreeBlockMemory(scip, &eventhdlrdata);
824 SCIPeventhdlrSetData(eventhdlr, NULL);
825
826 return SCIP_OKAY;
827}
828
829/*
830 * Callback methods
831 */
832
833/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
834static
835SCIP_DECL_HEURCOPY(heurCopyDistributiondiving)
836{ /*lint --e{715}*/
837 assert(scip != NULL);
838 assert(heur != NULL);
839 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
840
841 /* call inclusion method of primal heuristic */
843
844 return SCIP_OKAY;
845}
846
847/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
848static
849SCIP_DECL_HEURFREE(heurFreeDistributiondiving) /*lint --e{715}*/
850{ /*lint --e{715}*/
851 SCIP_HEURDATA* heurdata;
852
853 assert(heur != NULL);
854 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
855 assert(scip != NULL);
856
857 /* free heuristic data */
858 heurdata = SCIPheurGetData(heur);
859 assert(heurdata != NULL);
860 SCIPfreeBlockMemory(scip, &heurdata);
861 SCIPheurSetData(heur, NULL);
862
863 return SCIP_OKAY;
864}
865
866
867/** initialization method of primal heuristic (called after problem was transformed) */
868static
869SCIP_DECL_HEURINIT(heurInitDistributiondiving) /*lint --e{715}*/
870{ /*lint --e{715}*/
871 SCIP_HEURDATA* heurdata;
872
873 assert(heur != NULL);
874 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
875
876 /* get heuristic data */
877 heurdata = SCIPheurGetData(heur);
878 assert(heurdata != NULL);
879
880 /* create working solution */
881 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
882
883 return SCIP_OKAY;
884}
885
886
887/** deinitialization method of primal heuristic (called before transformed problem is freed) */
888static
889SCIP_DECL_HEUREXIT(heurExitDistributiondiving) /*lint --e{715}*/
890{ /*lint --e{715}*/
891 SCIP_HEURDATA* heurdata;
892
893 assert(heur != NULL);
894 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
895
896 /* get heuristic data */
897 heurdata = SCIPheurGetData(heur);
898 assert(heurdata != NULL);
899
900 /* free working solution */
901 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
902
903 return SCIP_OKAY;
904}
905
906/** scoring callback for distribution diving. best candidate maximizes the distribution score */
907static
908SCIP_DECL_DIVESETGETSCORE(divesetGetScoreDistributiondiving)
909{ /*lint --e{715}*/
910 SCIP_HEURDATA* heurdata;
911 SCIP_Real upscore;
912 SCIP_Real downscore;
913 int varindex;
914
915 heurdata = SCIPheurGetData(SCIPdivesetGetHeur(diveset));
916 assert(heurdata != NULL);
917
918 /* process pending bound change events */
919 while( heurdata->nupdatedvars > 0 )
920 {
921 SCIP_VAR* nextvar;
922
923 /* pop the next variable from the queue and process its bound changes */
924 nextvar = heurdataPopBoundChangeVar(heurdata);
925 assert(nextvar != NULL);
926 SCIP_CALL( varProcessBoundChanges(scip, heurdata, nextvar) );
927 }
928
929 assert(cand != NULL);
930
931 varindex = SCIPvarGetProbindex(cand);
932
933 /* terminate with a penalty for inactive variables, which the plugin can currently not score
934 * this should never happen with default settings where only LP branching candidates are iterated, but might occur
935 * if other constraint handlers try to score an inactive variable that was (multi-)aggregated or negated
936 */
937 if( varindex == - 1 )
938 {
939 *score = -1.0;
940 *roundup = FALSE;
941
942 return SCIP_OKAY;
943 }
944
945 /* in debug mode, ensure that all bound process events which occurred in the mean time have been captured
946 * by the heuristic event system
947 */
949 assert(0 <= varindex && varindex < heurdata->varpossmemsize);
950
951 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) == (heurdata->currentubs[varindex] == SCIP_INVALID));/*lint !e777 doesn't like comparing floats for equality */
952 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(cand), heurdata->currentlbs[varindex])); /*lint !e777 */
953 assert((heurdata->currentubs[varindex] == SCIP_INVALID) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(cand), heurdata->currentubs[varindex])); /*lint !e777 */
954
955 /* if the heuristic has not captured the variable bounds yet, this can be done now */
956 if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 */
957 heurdataUpdateCurrentBounds(scip, heurdata, cand);
958
959 upscore = 0.0;
960 downscore = 0.0;
961
962 /* loop over candidate rows and determine the candidate up- and down- branching score w.r.t. the score parameter */
963 SCIP_CALL( calcBranchScore(scip, heurdata, cand, candsol, &upscore, &downscore, heurdata->score) );
964
965 /* score is simply the maximum of the two individual scores */
966 *roundup = (upscore > downscore);
967 *score = MAX(upscore, downscore);
968
969 return SCIP_OKAY;
970}
971
972
973/** execution method of primal heuristic */
974static
975SCIP_DECL_HEUREXEC(heurExecDistributiondiving)
976{ /*lint --e{715}*/
977 SCIP_HEURDATA* heurdata;
978 SCIP_DIVESET* diveset;
979 int nlprows;
980
981 assert(heur != NULL);
982 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
983 assert(scip != NULL);
984 assert(result != NULL);
985 assert(SCIPhasCurrentNodeLP(scip));
986
987 *result = SCIP_DIDNOTRUN;
988
989 /* get heuristic's data */
990 heurdata = SCIPheurGetData(heur);
991 assert(heurdata != NULL);
992 nlprows = SCIPgetNLPRows(scip);
993 if( nlprows == 0 )
994 return SCIP_OKAY;
995
996 /* terminate if there are no integer variables (note that, e.g., SOS1 variables may be present) */
998 return SCIP_OKAY;
999
1000 /* select and store the scoring parameter for this call of the heuristic */
1001 if( heurdata->scoreparam == 'r' )
1002 heurdata->score = SCOREPARAM_VALUES[SCIPheurGetNCalls(heur) % SCOREPARAM_VALUESLEN];
1003 else
1004 heurdata->score = heurdata->scoreparam;
1005
1006 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, nlprows) );
1007 assert(SCIPheurGetNDivesets(heur) > 0);
1008 assert(SCIPheurGetDivesets(heur) != NULL);
1009 diveset = SCIPheurGetDivesets(heur)[0];
1010 assert(diveset != NULL);
1011
1012 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible, -1L, -1, -1.0, SCIP_DIVECONTEXT_SINGLE) );
1013
1014 SCIP_CALL( heurdataFreeArrays(scip, heurdata) );
1015
1016 return SCIP_OKAY;
1017}
1018
1019/** event execution method of distribution branching which handles bound change events of variables */
1020static
1021SCIP_DECL_EVENTEXEC(eventExecDistribution)
1022{
1023 SCIP_HEURDATA* heurdata;
1024 SCIP_EVENTHDLRDATA* eventhdlrdata;
1025 SCIP_VAR* var;
1026
1027 assert(eventhdlr != NULL);
1028 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1029 assert(eventhdlrdata != NULL);
1030
1031 heurdata = eventhdlrdata->heurdata;
1032 var = SCIPeventGetVar(event);
1033
1034 /* add the variable to the queue of unprocessed variables; method itself ensures that every variable is added at most once */
1035 heurdataAddBoundChangeVar(heurdata, var);
1036
1037 return SCIP_OKAY;
1038}
1039
1040/*
1041 * heuristic specific interface methods
1042 */
1043
1044#define divesetAvailableDistributiondiving NULL
1045
1046/** creates the distributiondiving heuristic and includes it in SCIP */
1048 SCIP* scip /**< SCIP data structure */
1049 )
1050{
1051 SCIP_HEURDATA* heurdata;
1052 SCIP_HEUR* heur;
1053 SCIP_EVENTHDLRDATA* eventhdlrdata;
1054
1055 /* create distributiondiving data */
1056 heurdata = NULL;
1057 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1058
1059 heurdata->memsize = 0;
1060 heurdata->rowmeans = NULL;
1061 heurdata->rowvariances = NULL;
1062 heurdata->rowinfinitiesdown = NULL;
1063 heurdata->rowinfinitiesup = NULL;
1064 heurdata->varfilterposs = NULL;
1065 heurdata->currentlbs = NULL;
1066 heurdata->currentubs = NULL;
1067
1068 /* create event handler first to finish heuristic data */
1069 eventhdlrdata = NULL;
1070 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
1071 eventhdlrdata->heurdata = heurdata;
1072
1073 heurdata->eventhdlr = NULL;
1075 "event handler for dynamic acitivity distribution updating",
1076 eventExecDistribution, eventhdlrdata) );
1077 assert( heurdata->eventhdlr != NULL);
1078 SCIP_CALL( SCIPsetEventhdlrFree(scip, heurdata->eventhdlr, eventFreeDistributiondiving) );
1079
1080 /* include primal heuristic */
1083 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecDistributiondiving, heurdata) );
1084
1085 assert(heur != NULL);
1086
1087 /* primal heuristic is safe to use in exact solving mode */
1088 SCIPheurMarkExact(heur);
1089
1090 /* set non-NULL pointers to callback methods */
1091 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDistributiondiving) );
1092 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDistributiondiving) );
1093 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitDistributiondiving) );
1094 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitDistributiondiving) );
1095
1096 /* add diveset with the defined scoring function */
1102 divesetGetScoreDistributiondiving, divesetAvailableDistributiondiving) );
1103
1104 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/scoreparam",
1105 "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",
1106 &heurdata->scoreparam, TRUE, DEFAULT_SCOREPARAM, "lvdhwr", NULL, NULL) );
1107
1108 return SCIP_OKAY;
1109}
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:248
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Real
Definition: def.h:156
#define SQR(x)
Definition: def.h:199
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL(x)
Definition: def.h:355
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_IMPLINTTYPE impltype, SCIP_Real *mean, SCIP_Real *variance)
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2569
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
int SCIPgetNContImplVars(SCIP *scip)
Definition: scip_prob.c:2522
#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:17425
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:17520
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:17555
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:17545
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:406
void SCIPeventhdlrSetData(SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event.c:416
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:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:413
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1217
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:1368
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:1593
int SCIPheurGetNDivesets(SCIP_HEUR *heur)
Definition: heur.c:1675
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition: heur.c:1457
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:1467
SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
Definition: heur.c:1665
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1378
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:87
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:632
#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:98
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17607
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17632
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2176
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17745
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:17755
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17652
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17642
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:516
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1252
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:221
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:23683
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition: var.c:23463
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:160
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
enum SCIP_ImplintType SCIP_IMPLINTTYPE
Definition: type_var.h:117
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:53
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73