Scippy

SCIP

Solving Constraint Integer Programs

branch_distribution.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 branch_distribution.c
26 * @ingroup DEFPLUGINS_BRANCH
27 * @ingroup BRANCHINGRULES
28 * @brief probability based branching rule based on an article by J. Pryor and J.W. Chinneck
29 * @author Gregor Hendel
30 *
31 * The distribution branching rule selects a variable based on its impact on row activity distributions. More formally,
32 * let \f$ a(x) = a_1 x_1 + \dots + a_n x_n \leq b \f$ be a row of the LP. Let further \f$ l_i, u_i \in R\f$ denote the
33 * (finite) lower and upper bound, respectively, of the \f$ i \f$-th variable \f$x_i\f$.
34 * Viewing every variable \f$x_i \f$ as (continuously) uniformly distributed within its bounds, we can approximately
35 * understand the row activity \f$a(x)\f$ as a Gaussian random variate with mean value \f$ \mu = E[a(x)] = \sum_i a_i\frac{l_i + u_i}{2}\f$
36 * and variance \f$ \sigma^2 = \sum_i a_i^2 \sigma_i^2 \f$, with \f$ \sigma_i^2 = \frac{(u_i - l_i)^2}{12}\f$ for
37 * continuous and \f$ \sigma_i^2 = \frac{(u_i - l_i + 1)^2 - 1}{12}\f$ for discrete variables.
38 * With these two parameters, we can calculate the probability to satisfy the row in terms of the cumulative distribution
39 * of the standard normal distribution: \f$ P(a(x) \leq b) = \Phi(\frac{b - \mu}{\sigma})\f$.
40 *
41 * The impact of a variable on the probability to satisfy a constraint after branching can be estimated by altering
42 * the variable contribution to the sums described above. In order to keep the tree size small,
43 * variables are preferred which decrease the probability
44 * to satisfy a row because it is more likely to create infeasible subproblems.
45 *
46 * The selection of the branching variable is subject to the parameter @p scoreparam. For both branching directions,
47 * an individual score is calculated. Available options for scoring methods are:
48 * - @b d: select a branching variable with largest difference in satisfaction probability after branching
49 * - @b l: lowest cumulative probability amongst all variables on all rows (after branching).
50 * - @b h: highest cumulative probability amongst all variables on all rows (after branching).
51 * - @b v: highest number of votes for lowering row probability for all rows a variable appears in.
52 * - @b w: highest number of votes for increasing row probability for all rows a variable appears in.
53 *
54 * If the parameter @p usescipscore is set to @a TRUE, a single branching score is calculated from the respective
55 * up and down scores as defined by the SCIP branching score function (see advanced branching parameter @p scorefunc),
56 * otherwise, the variable with the single highest score is selected, and the maximizing direction is assigned
57 * higher branching priority.
58 *
59 * The original idea of probability based branching schemes appeared in:
60 *
61 * J. Pryor and J.W. Chinneck:@n
62 * Faster Integer-Feasibility in Mixed-Integer Linear Programs by Branching to Force Change@n
63 * Computers and Operations Research, vol. 38, 2011, p. 1143–1152@n
64 * (Paper: <a href="http://www.sce.carleton.ca/faculty/chinneck/docs/PryorChinneck.pdf">PDF</a>).
65 */
66
67/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
68
69#define _USE_MATH_DEFINES /* to get M_SQRT2 on Windows */ /*lint !750 */
70
72#include "scip/pub_branch.h"
73#include "scip/pub_event.h"
74#include "scip/pub_lp.h"
75#include "scip/pub_message.h"
76#include "scip/pub_misc.h"
77#include "scip/pub_var.h"
78#include "scip/scip_branch.h"
79#include "scip/scip_event.h"
80#include "scip/scip_general.h"
81#include "scip/scip_lp.h"
82#include "scip/scip_message.h"
83#include "scip/scip_mem.h"
84#include "scip/scip_numerics.h"
85#include "scip/scip_param.h"
86#include "scip/scip_pricer.h"
87#include "scip/scip_prob.h"
88#include "scip/scip_probing.h"
89#include <string.h>
90#include <math.h>
91
92
93#define BRANCHRULE_NAME "distribution"
94#define BRANCHRULE_DESC "branching rule based on variable influence on cumulative normal distribution of row activities"
95#define BRANCHRULE_PRIORITY 0
96#define BRANCHRULE_MAXDEPTH -1
97#define BRANCHRULE_MAXBOUNDDIST 1.0
98
99#define SCOREPARAM_VALUES "dhlvw"
100#define DEFAULT_SCOREPARAM 'v'
101#define DEFAULT_PRIORITY 2.0
102#define DEFAULT_ONLYACTIVEROWS FALSE /**< should only rows which are active at the current node be considered? */
103#define DEFAULT_USEWEIGHTEDSCORE FALSE /**< should the branching score weigh up- and down-scores of a variable */
104
105/* branching rule event handler to catch variable bound changes */
106#define EVENTHDLR_NAME "eventhdlr_distribution" /**< event handler name */
107#define EVENT_DISTRIBUTION SCIP_EVENTTYPE_BOUNDCHANGED /**< the event tyoe to be handled by this event handler */
108
109/*
110 * Data structures
111 */
112
113/** branching rule data */
114struct SCIP_BranchruleData
115{
116 SCIP_EVENTHDLR* eventhdlr; /**< event handler pointer */
117 SCIP_VAR** updatedvars; /**< variables to process bound change events for */
118 SCIP_Real* rowmeans; /**< row activity mean values for all rows */
119 SCIP_Real* rowvariances; /**< row activity variances for all rows */
120 SCIP_Real* currentubs; /**< variable upper bounds as currently saved in the row activities */
121 SCIP_Real* currentlbs; /**< variable lower bounds as currently saved in the row activities */
122 int* rowinfinitiesdown; /**< count the number of variables with infinite bounds which allow for always
123 * repairing the constraint right hand side */
124 int* rowinfinitiesup; /**< count the number of variables with infinite bounds which allow for always
125 * repairing the constraint left hand side */
126 int* varposs; /**< array of variable positions in the updated variables array */
127 int* varfilterposs; /**< array of event filter positions for variable events */
128 int nupdatedvars; /**< the current number of variables with pending bound changes */
129 int memsize; /**< memory size of current arrays, needed for dynamic reallocation */
130 int varpossmemsize; /**< memory size of updated vars and varposs array */
131 char scoreparam; /**< parameter how the branch score is calculated */
132 SCIP_Bool onlyactiverows; /**< should only rows which are active at the current node be considered? */
133 SCIP_Bool usescipscore; /**< should the branching use SCIP's branching score function */
134};
135
136struct SCIP_EventhdlrData
137{
138 SCIP_BRANCHRULEDATA* branchruledata; /**< the branching rule data to access distribution arrays */
139};
140
141/*
142 * Local methods
143 */
144
145/** ensure that maxindex + 1 rows can be represented in data arrays; memory gets reallocated with 10% extra space
146 * to save some time for future allocations */
147static
149 SCIP* scip, /**< SCIP data structure */
150 SCIP_BRANCHRULEDATA* branchruledata, /**< branchruledata */
151 int maxindex /**< row index at hand (size must be at least this large) */
152 )
153{
154 int newsize;
155 int r;
156
157 /* maxindex fits in current array -> nothing to do */
158 if( maxindex < branchruledata->memsize )
159 return SCIP_OKAY;
160
161 /* new memory size is the max index + 1 plus 10% additional space */
162 newsize = (int)SCIPfeasCeil(scip, (maxindex + 1) * 1.1);
163 assert(newsize > branchruledata->memsize);
164 assert(branchruledata->memsize >= 0);
165
166 /* alloc memory arrays for row information */
167 if( branchruledata->memsize == 0 )
168 {
169 SCIP_VAR** vars;
170 int v;
171 int nvars;
172
173 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesdown, newsize) );
174 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesup, newsize) );
175 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowmeans, newsize) );
176 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowvariances, newsize) );
177
179
180 vars = SCIPgetVars(scip);
181 nvars = SCIPgetNVars(scip);
182
183 assert(nvars > 0);
184
185 /* allocate variable update event processing array storage */
186 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->varfilterposs, nvars) );
187 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->varposs, nvars) );
188 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->updatedvars, nvars) );
189 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->currentubs, nvars) );
190 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->currentlbs, nvars) );
191
192 branchruledata->varpossmemsize = nvars;
193 branchruledata->nupdatedvars = 0;
194
195 /* init variable event processing data */
196 for( v = 0; v < nvars; ++v )
197 {
198 assert(SCIPvarIsActive(vars[v]));
199 assert(SCIPvarGetProbindex(vars[v]) == v);
200
201 /* set up variable events to catch bound changes */
202 SCIP_CALL( SCIPcatchVarEvent(scip, vars[v], EVENT_DISTRIBUTION, branchruledata->eventhdlr, NULL, &(branchruledata->varfilterposs[v])) );
203 assert(branchruledata->varfilterposs[v] >= 0);
204
205 branchruledata->varposs[v] = -1;
206 branchruledata->updatedvars[v] = NULL;
207 branchruledata->currentlbs[v] = SCIP_INVALID;
208 branchruledata->currentubs[v] = SCIP_INVALID;
209 }
210 }
211 else
212 {
213 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesdown, branchruledata->memsize, newsize) );
214 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesup, branchruledata->memsize, newsize) );
215 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowmeans, branchruledata->memsize, newsize) );
216 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowvariances, branchruledata->memsize, newsize) );
217 }
218
219 /* loop over extended arrays and invalidate data to trigger initialization of this row when necessary */
220 for( r = branchruledata->memsize; r < newsize; ++r )
221 {
222 branchruledata->rowmeans[r] = SCIP_INVALID;
223 branchruledata->rowvariances[r] = SCIP_INVALID;
224 branchruledata->rowinfinitiesdown[r] = 0;
225 branchruledata->rowinfinitiesup[r] = 0;
226 }
227
228 /* adjust memsize */
229 branchruledata->memsize = newsize;
230
231 return SCIP_OKAY;
232}
233
234/* update the variables current lower and upper bound */
235static
237 SCIP* scip, /**< SCIP data structure */
238 SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
239 SCIP_VAR* var /**< the variable to update current bounds */
240 )
241{
242 int varindex;
243 SCIP_Real lblocal;
244 SCIP_Real ublocal;
245
246 assert(var != NULL);
247
248 varindex = SCIPvarGetProbindex(var);
249 assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
250 lblocal = SCIPvarGetLbLocal(var);
251 ublocal = SCIPvarGetUbLocal(var);
252
253 assert(SCIPisFeasLE(scip, lblocal, ublocal));
254
255 branchruledata->currentlbs[varindex] = lblocal;
256 branchruledata->currentubs[varindex] = ublocal;
257}
258
259/** calculate the variable's distribution parameters (mean and variance) for the bounds specified in the arguments.
260 * special treatment of infinite bounds necessary */
262 SCIP* scip, /**< SCIP data structure */
263 SCIP_Real varlb, /**< variable lower bound */
264 SCIP_Real varub, /**< variable upper bound */
265 SCIP_VARTYPE vartype, /**< type of the variable */
266 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
267 SCIP_Real* mean, /**< pointer to store mean value */
268 SCIP_Real* variance /**< pointer to store the variance of the variable uniform distribution */
269 )
270{
271 assert(mean != NULL);
272 assert(variance != NULL);
273
274 /* calculate mean and variance of variable uniform distribution before and after branching */
275 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
276 {
277 /* variables with infinite bounds are not kept in the row activity variance */
278 *variance = 0.0;
279
280 if( !SCIPisInfinity(scip, varub) )
281 *mean = varub;
282 else if( !SCIPisInfinity(scip, -varlb) )
283 *mean = varlb;
284 else
285 *mean = 0.0;
286 }
287 else
288 {
289 /* if the variable is continuous, we assume a continuous uniform distribution, otherwise a discrete one */
290 if( vartype == SCIP_VARTYPE_CONTINUOUS && impltype == SCIP_IMPLINTTYPE_NONE )
291 *variance = SQR(varub - varlb);
292 else
293 *variance = SQR(varub - varlb + 1.0) - 1.0;
294 *variance /= 12.0;
295 *mean = (varub + varlb) * .5;
296 }
297
298 assert(!SCIPisNegative(scip, *variance));
299}
300
301/** calculates the cumulative distribution P(-infinity <= x <= value) that a normally distributed
302 * random variable x takes a value between -infinity and parameter \p value.
303 *
304 * The distribution is given by the respective mean and deviation. This implementation
305 * uses the error function SCIPerf().
306 */
308 SCIP* scip, /**< current SCIP */
309 SCIP_Real mean, /**< the mean value of the distribution */
310 SCIP_Real variance, /**< the square of the deviation of the distribution */
311 SCIP_Real value /**< the upper limit of the calculated distribution integral */
312 )
313{
314 SCIP_Real normvalue;
316
317 /* we need to calculate the standard deviation from the variance */
318 assert(!SCIPisNegative(scip, variance));
319 if( SCIPisFeasZero(scip, variance) )
320 std = 0.0;
321 else
322 std = sqrt(variance);
323
324 /* special treatment for zero variance */
325 if( SCIPisFeasZero(scip, std) )
326 {
327 if( SCIPisFeasLE(scip, value, mean) )
328 return 1.0;
329 else
330 return 0.0;
331 }
332 assert( std != 0.0 ); /* for lint */
333
334 /* scale and translate to standard normal distribution. Factor sqrt(2) is needed for SCIPerf() function */
335 normvalue = (value - mean)/(std * M_SQRT2);
336
337 SCIPdebugMsg(scip, " Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean, std);
338
339 /* calculate the cumulative distribution function for normvalue. For negative normvalues, we negate
340 * the normvalue and use the oddness of the SCIPerf()-function; special treatment for values close to zero.
341 */
342 if( SCIPisFeasZero(scip, normvalue) )
343 return .5;
344 else if( normvalue > 0 )
345 {
346 SCIP_Real erfresult;
347
348 erfresult = SCIPerf(normvalue);
349 return erfresult / 2.0 + 0.5;
350 }
351 else
352 {
353 SCIP_Real erfresult;
354
355 erfresult = SCIPerf(-normvalue);
356
357 return 0.5 - erfresult / 2.0;
358 }
359}
360
361/** calculates the probability of satisfying an LP-row under the assumption
362 * of uniformly distributed variable values.
363 *
364 * For inequalities, we use the cumulative distribution function of the standard normal
365 * distribution PHI(rhs - mu/sqrt(sigma2)) to calculate the probability
366 * for a right hand side row with mean activity mu and variance sigma2 to be satisfied.
367 * Similarly, 1 - PHI(lhs - mu/sqrt(sigma2)) is the probability to satisfy a left hand side row.
368 * For equations (lhs==rhs), we use the centeredness measure p = min(PHI(lhs'), 1-PHI(lhs'))/max(PHI(lhs'), 1 - PHI(lhs')),
369 * where lhs' = lhs - mu / sqrt(sigma2).
370 */
372 SCIP* scip, /**< current scip */
373 SCIP_ROW* row, /**< the row */
374 SCIP_Real mu, /**< the mean value of the row distribution */
375 SCIP_Real sigma2, /**< the variance of the row distribution */
376 int rowinfinitiesdown, /**< the number of variables with infinite bounds to DECREASE activity */
377 int rowinfinitiesup /**< the number of variables with infinite bounds to INCREASE activity */
378 )
379{
380 SCIP_Real rowprobability;
381 SCIP_Real lhs;
382 SCIP_Real rhs;
383 SCIP_Real lhsprob;
384 SCIP_Real rhsprob;
385
386 lhs = SCIProwGetLhs(row);
387 rhs = SCIProwGetRhs(row);
388
389 lhsprob = 1.0;
390 rhsprob = 1.0;
391
392 /* use the cumulative distribution if the row contains no variable to repair every infeasibility */
393 if( !SCIPisInfinity(scip, rhs) && rowinfinitiesdown == 0 )
394 rhsprob = SCIPcalcCumulativeDistribution(scip, mu, sigma2, rhs);
395
396 /* use the cumulative distribution if the row contains no variable to repair every infeasibility
397 * otherwise the row can always be made feasible by increasing activity far enough
398 */
399 if( !SCIPisInfinity(scip, -lhs) && rowinfinitiesup == 0 )
400 lhsprob = 1.0 - SCIPcalcCumulativeDistribution(scip, mu, sigma2, lhs);
401
402 assert(SCIPisFeasLE(scip, lhsprob, 1.0) && SCIPisFeasGE(scip, lhsprob, 0.0));
403 assert(SCIPisFeasLE(scip, rhsprob, 1.0) && SCIPisFeasGE(scip, rhsprob, 0.0));
404
405 /* use centeredness measure for equations; for inequalities, the minimum of the two probabilities is the
406 * probability to satisfy the row */
407 if( SCIPisFeasEQ(scip, lhs, rhs) )
408 {
409 SCIP_Real minprobability;
410 SCIP_Real maxprobability;
411
412 minprobability = MIN(rhsprob, lhsprob);
413 maxprobability = MAX(lhsprob, rhsprob);
414 rowprobability = minprobability / maxprobability;
415 }
416 else
417 rowprobability = MIN(rhsprob, lhsprob);
418
420 SCIPdebugMsg(scip, " Row %s, mean %g, sigma2 %g, LHS %g, RHS %g has probability %g to be satisfied\n",
421 SCIProwGetName(row), mu, sigma2, lhs, rhs, rowprobability);
422
423 assert(SCIPisFeasGE(scip, rowprobability, 0.0) && SCIPisFeasLE(scip, rowprobability, 1.0));
424
425 return rowprobability;
426}
427
428/** calculates the initial mean and variance of the row activity normal distribution.
429 *
430 * The mean value \f$ \mu \f$ is given by \f$ \mu = \sum_i=1^n c_i * (lb_i +ub_i) / 2 \f$ where
431 * \f$n \f$ is the number of variables, and \f$ c_i, lb_i, ub_i \f$ are the variable coefficient and
432 * bounds, respectively. With the same notation, the variance \f$ \sigma^2 \f$ is given by
433 * \f$ \sigma^2 = \sum_i=1^n c_i^2 * \sigma^2_i \f$, with the variance being
434 * \f$ \sigma^2_i = ((ub_i - lb_i + 1)^2 - 1) / 12 \f$ for integer variables and
435 * \f$ \sigma^2_i = (ub_i - lb_i)^2 / 12 \f$ for continuous variables.
436 */
437static
439 SCIP* scip, /**< SCIP data structure */
440 SCIP_BRANCHRULEDATA* branchruledata, /**< the branching rule data */
441 SCIP_ROW* row, /**< the row for which the gaussian normal distribution has to be calculated */
442 SCIP_Real* mu, /**< pointer to store the mean value of the gaussian normal distribution */
443 SCIP_Real* sigma2, /**< pointer to store the variance value of the gaussian normal distribution */
444 int* rowinfinitiesdown, /**< pointer to store the number of variables with infinite bounds to DECREASE activity */
445 int* rowinfinitiesup /**< pointer to store the number of variables with infinite bounds to INCREASE activity */
446 )
447{
448 SCIP_COL** rowcols;
449 SCIP_Real* rowvals;
450 int nrowvals;
451 int c;
452
453 assert(scip != NULL);
454 assert(row != NULL);
455 assert(mu != NULL);
456 assert(sigma2 != NULL);
457 assert(rowinfinitiesup != NULL);
458 assert(rowinfinitiesdown != NULL);
459
460 rowcols = SCIProwGetCols(row);
461 rowvals = SCIProwGetVals(row);
462 nrowvals = SCIProwGetNNonz(row);
463
464 assert(nrowvals == 0 || rowcols != NULL);
465 assert(nrowvals == 0 || rowvals != NULL);
466
467 *mu = SCIProwGetConstant(row);
468 *sigma2 = 0.0;
469 *rowinfinitiesdown = 0;
470 *rowinfinitiesup = 0;
471
472 /* loop over nonzero row coefficients and sum up the variable contributions to mu and sigma2 */
473 for( c = 0; c < nrowvals; ++c )
474 {
475 SCIP_VAR* colvar;
476 SCIP_Real colval;
477 SCIP_Real colvarlb;
478 SCIP_Real colvarub;
479 SCIP_Real squarecoeff;
480 SCIP_Real varvariance;
481 SCIP_Real varmean;
482 int varindex;
483
484 assert(rowcols[c] != NULL);
485 colvar = SCIPcolGetVar(rowcols[c]);
486 assert(colvar != NULL);
487
488 colval = rowvals[c];
489 colvarlb = SCIPvarGetLbLocal(colvar);
490 colvarub = SCIPvarGetUbLocal(colvar);
491
492 varmean = 0.0;
493 varvariance = 0.0;
494 varindex = SCIPvarGetProbindex(colvar);
495 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID) == (branchruledata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777*/
496
497 /* variable bounds need to be watched from now on */
498 if( branchruledata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777*/
499 branchruledataUpdateCurrentBounds(scip, branchruledata, colvar);
500
501 assert(!SCIPisInfinity(scip, colvarlb));
502 assert(!SCIPisInfinity(scip, -colvarub));
503 assert(SCIPisFeasLE(scip, colvarlb, colvarub));
504
505 /* variables with infinite bounds are skipped for the calculation of the variance; they need to
506 * be accounted for by the counters for infinite row activity decrease and increase and they
507 * are used to shift the row activity mean in case they have one nonzero, but finite bound */
508 if( SCIPisInfinity(scip, -colvarlb) || SCIPisInfinity(scip, colvarub) )
509 {
510 if( SCIPisInfinity(scip, colvarub) )
511 {
512 /* an infinite upper bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
513 * positive or negative, resp.
514 */
515 if( colval < 0.0 )
516 ++(*rowinfinitiesdown);
517 else
518 ++(*rowinfinitiesup);
519 }
520
521 /* an infinite lower bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
522 * negative or positive, resp.
523 */
524 if( SCIPisInfinity(scip, -colvarlb) )
525 {
526 if( colval > 0.0 )
527 ++(*rowinfinitiesdown);
528 else
529 ++(*rowinfinitiesup);
530 }
531 }
532 SCIPvarCalcDistributionParameters(scip, colvarlb, colvarub, SCIPvarGetType(colvar), SCIPvarGetImplType(colvar),
533 &varmean, &varvariance);
534
535 /* actual values are updated; the contribution of the variable to mu is the arithmetic mean of its bounds */
536 *mu += colval * varmean;
537
538 /* 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 */
539 squarecoeff = SQR(colval);
540 *sigma2 += squarecoeff * varvariance;
541
542 assert(!SCIPisFeasNegative(scip, *sigma2));
543 }
544
546 SCIPdebugMsg(scip, " Row %s has a mean value of %g at a sigma2 of %g \n", SCIProwGetName(row), *mu, *sigma2);
547}
548
549/** update the up- and downscore of a single variable after calculating the impact of branching on a
550 * particular row, depending on the chosen score parameter
551 */
553 SCIP* scip, /**< current SCIP pointer */
554 SCIP_Real currentprob, /**< the current probability */
555 SCIP_Real newprobup, /**< the new probability if branched upwards */
556 SCIP_Real newprobdown, /**< the new probability if branched downwards */
557 SCIP_Real* upscore, /**< pointer to store the new score for branching up */
558 SCIP_Real* downscore, /**< pointer to store the new score for branching down */
559 char scoreparam /**< parameter to determine the way the score is calculated */
560 )
561{
562 assert(scip != NULL);
563 assert(SCIPisFeasGE(scip, currentprob, 0.0) && SCIPisFeasLE(scip, currentprob, 1.0));
564 assert(SCIPisFeasGE(scip, newprobup, 0.0) && SCIPisFeasLE(scip, newprobup, 1.0));
565 assert(SCIPisFeasGE(scip, newprobdown, 0.0) && SCIPisFeasLE(scip, newprobdown, 1.0));
566 assert(upscore != NULL);
567 assert(downscore != NULL);
568
569 /* update up and downscore depending on score parameter */
570 switch( scoreparam )
571 {
572 case 'l' :
573 /* 'l'owest cumulative probability */
574 if( SCIPisGT(scip, 1.0 - newprobup, *upscore) )
575 *upscore = 1.0 - newprobup;
576 if( SCIPisGT(scip, 1.0 - newprobdown, *downscore) )
577 *downscore = 1.0 - newprobdown;
578 break;
579
580 case 'd' :
581 /* biggest 'd'ifference currentprob - newprob */
582 if( SCIPisGT(scip, currentprob - newprobup, *upscore) )
583 *upscore = currentprob - newprobup;
584 if( SCIPisGT(scip, currentprob - newprobdown, *downscore) )
585 *downscore = currentprob - newprobdown;
586 break;
587
588 case 'h' :
589 /* 'h'ighest cumulative probability */
590 if( SCIPisGT(scip, newprobup, *upscore) )
591 *upscore = newprobup;
592 if( SCIPisGT(scip, newprobdown, *downscore) )
593 *downscore = newprobdown;
594 break;
595
596 case 'v' :
597 /* 'v'otes lowest cumulative probability */
598 if( SCIPisLT(scip, newprobup, newprobdown) )
599 *upscore += 1.0;
600 else if( SCIPisGT(scip, newprobup, newprobdown) )
601 *downscore += 1.0;
602 break;
603
604 case 'w' :
605 /* votes highest cumulative probability */
606 if( SCIPisGT(scip, newprobup, newprobdown) )
607 *upscore += 1.0;
608 else if( SCIPisLT(scip, newprobup, newprobdown) )
609 *downscore += 1.0;
610 break;
611
612 default :
613 SCIPerrorMessage(" ERROR! No branching scheme selected! Exiting method.\n");
614 return SCIP_INVALIDCALL;
615 }
616
617 return SCIP_OKAY;
618}
619
620/** calculate the branching score of a variable, depending on the chosen score parameter */
621static
623 SCIP* scip, /**< current SCIP */
624 SCIP_BRANCHRULEDATA* branchruledata, /**< branch rule data */
625 SCIP_VAR* var, /**< candidate variable */
626 SCIP_Real lpsolval, /**< current fractional LP-relaxation solution value */
627 SCIP_Real* upscore, /**< pointer to store the variable score when branching on it in upward direction */
628 SCIP_Real* downscore, /**< pointer to store the variable score when branching on it in downward direction */
629 char scoreparam /**< the score parameter of this branching rule */
630 )
631{
632 SCIP_COL* varcol;
633 SCIP_ROW** colrows;
634 SCIP_Real* rowvals;
635 SCIP_Real varlb;
636 SCIP_Real varub;
637 SCIP_Real squaredbounddiff; /* current squared difference of variable bounds (ub - lb)^2 */
638 SCIP_Real newub; /* new upper bound if branching downwards */
639 SCIP_Real newlb; /* new lower bound if branching upwards */
640 SCIP_Real squaredbounddiffup; /* squared difference after branching upwards (ub - lb')^2 */
641 SCIP_Real squaredbounddiffdown; /* squared difference after branching downwards (ub' - lb)^2 */
642 SCIP_Real currentmean; /* current mean value of variable uniform distribution */
643 SCIP_Real meanup; /* mean value of variable uniform distribution after branching up */
644 SCIP_Real meandown; /* mean value of variable uniform distribution after branching down*/
645 SCIP_VARTYPE vartype;
646 SCIP_IMPLINTTYPE impltype;
647 int ncolrows;
648 int i;
649
650 SCIP_Bool onlyactiverows; /* should only rows which are active at the current node be considered? */
651
652 assert(scip != NULL);
653 assert(var != NULL);
654 assert(upscore != NULL);
655 assert(downscore != NULL);
656 assert(!SCIPisIntegral(scip, lpsolval));
658
659 varcol = SCIPvarGetCol(var);
660 assert(varcol != NULL);
661
662 colrows = SCIPcolGetRows(varcol);
663 rowvals = SCIPcolGetVals(varcol);
664 ncolrows = SCIPcolGetNNonz(varcol);
665 varlb = SCIPvarGetLbLocal(var);
666 varub = SCIPvarGetUbLocal(var);
667 assert(SCIPisFeasLT(scip, varlb, varub));
668 vartype = SCIPvarGetType(var);
669 impltype = SCIPvarGetImplType(var);
670
671 /* calculate mean and variance of variable uniform distribution before and after branching */
672 currentmean = 0.0;
673 squaredbounddiff = 0.0;
674 SCIPvarCalcDistributionParameters(scip, varlb, varub, vartype, impltype, &currentmean, &squaredbounddiff);
675
676 newlb = SCIPfeasCeil(scip, lpsolval);
677 newub = SCIPfeasFloor(scip, lpsolval);
678
679 /* calculate the variable's uniform distribution after branching up and down, respectively. */
680 squaredbounddiffup = 0.0;
681 meanup = 0.0;
682 SCIPvarCalcDistributionParameters(scip, newlb, varub, vartype, impltype, &meanup, &squaredbounddiffup);
683
684 /* calculate the distribution mean and variance for a variable with finite lower bound */
685 squaredbounddiffdown = 0.0;
686 meandown = 0.0;
687 SCIPvarCalcDistributionParameters(scip, varlb, newub, vartype, impltype, &meandown, &squaredbounddiffdown);
688
689 /* initialize the variable's up and down score */
690 *upscore = 0.0;
691 *downscore = 0.0;
692
693 onlyactiverows = branchruledata->onlyactiverows;
694
695 /* loop over the variable rows and calculate the up and down score */
696 for( i = 0; i < ncolrows; ++i )
697 {
698 SCIP_ROW* row;
699 SCIP_Real changedrowmean;
700 SCIP_Real rowmean;
701 SCIP_Real rowvariance;
702 SCIP_Real changedrowvariance;
703 SCIP_Real currentrowprob;
704 SCIP_Real newrowprobup;
705 SCIP_Real newrowprobdown;
706 SCIP_Real squaredcoeff;
707 SCIP_Real rowval;
708 int rowinfinitiesdown;
709 int rowinfinitiesup;
710 int rowpos;
711
712 row = colrows[i];
713 rowval = rowvals[i];
714 assert(row != NULL);
715
716 /* we access the rows by their index */
717 rowpos = SCIProwGetIndex(row);
718
719 /* skip non-active rows if the user parameter was set this way */
720 if( onlyactiverows && SCIPisSumPositive(scip, SCIPgetRowLPFeasibility(scip, row)) )
721 continue;
722
723 /* call method to ensure sufficient data capacity */
724 SCIP_CALL( branchruledataEnsureArraySize(scip, branchruledata, rowpos) );
725
726 /* calculate row activity distribution if this is the first candidate to appear in this row */
727 if( branchruledata->rowmeans[rowpos] == SCIP_INVALID ) /*lint !e777*/
728 {
729 rowCalculateGauss(scip, branchruledata, row, &branchruledata->rowmeans[rowpos], &branchruledata->rowvariances[rowpos],
730 &branchruledata->rowinfinitiesdown[rowpos], &branchruledata->rowinfinitiesup[rowpos]);
731 }
732
733 /* retrieve the row distribution parameters from the branch rule data */
734 rowmean = branchruledata->rowmeans[rowpos];
735 rowvariance = branchruledata->rowvariances[rowpos];
736 rowinfinitiesdown = branchruledata->rowinfinitiesdown[rowpos];
737 rowinfinitiesup = branchruledata->rowinfinitiesdown[rowpos];
738 assert(!SCIPisNegative(scip, rowvariance));
739
740 currentrowprob = SCIProwCalcProbability(scip, row, rowmean, rowvariance,
741 rowinfinitiesdown, rowinfinitiesup);
742
743 /* get variable's current expected contribution to row activity */
744 squaredcoeff = SQR(rowval);
745
746 /* first, get the probability change for the row if the variable is branched on upwards. The probability
747 * can only be affected if the variable upper bound is finite
748 */
749 if( !SCIPisInfinity(scip, varub) )
750 {
751 int rowinftiesdownafterbranch;
752 int rowinftiesupafterbranch;
753
754 /* calculate how branching would affect the row parameters */
755 changedrowmean = rowmean + rowval * (meanup - currentmean);
756 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffup - squaredbounddiff);
757 changedrowvariance = MAX(0.0, changedrowvariance);
758
759 rowinftiesdownafterbranch = rowinfinitiesdown;
760 rowinftiesupafterbranch = rowinfinitiesup;
761
762 /* account for changes of the row's infinite bound contributions */
763 if( SCIPisInfinity(scip, -varlb) && rowval < 0.0 )
764 rowinftiesupafterbranch--;
765 if( SCIPisInfinity(scip, -varlb) && rowval > 0.0 )
766 rowinftiesdownafterbranch--;
767
768 assert(rowinftiesupafterbranch >= 0);
769 assert(rowinftiesdownafterbranch >= 0);
770 newrowprobup = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
771 rowinftiesupafterbranch);
772 }
773 else
774 newrowprobup = currentrowprob;
775
776 /* do the same for the other branching direction */
777 if( !SCIPisInfinity(scip, varlb) )
778 {
779 int rowinftiesdownafterbranch;
780 int rowinftiesupafterbranch;
781
782 changedrowmean = rowmean + rowval * (meandown - currentmean);
783 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffdown - squaredbounddiff);
784 changedrowvariance = MAX(0.0, changedrowvariance);
785
786 rowinftiesdownafterbranch = rowinfinitiesdown;
787 rowinftiesupafterbranch = rowinfinitiesup;
788
789 /* account for changes of the row's infinite bound contributions */
790 if( SCIPisInfinity(scip, varub) && rowval > 0.0 )
791 rowinftiesupafterbranch -= 1;
792 if( SCIPisInfinity(scip, varub) && rowval < 0.0 )
793 rowinftiesdownafterbranch -= 1;
794
795 assert(rowinftiesdownafterbranch >= 0);
796 assert(rowinftiesupafterbranch >= 0);
797 newrowprobdown = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
798 rowinftiesupafterbranch);
799 }
800 else
801 newrowprobdown = currentrowprob;
802
803 /* update the up and down score depending on the chosen scoring parameter */
804 SCIP_CALL( SCIPupdateDistributionScore(scip, currentrowprob, newrowprobup, newrowprobdown, upscore, downscore, scoreparam) );
805
806 SCIPdebugMsg(scip, " Variable %s changes probability of row %s from %g to %g (branch up) or %g;\n",
807 SCIPvarGetName(var), SCIProwGetName(row), currentrowprob, newrowprobup, newrowprobdown);
808 SCIPdebugMsg(scip, " --> new variable score: %g (for branching up), %g (for branching down)\n",
809 *upscore, *downscore);
810 }
811
812 return SCIP_OKAY;
813}
814
815/** free branchrule data */
816static
818 SCIP* scip, /**< SCIP data structure */
819 SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
820 )
821{
822 assert(branchruledata->memsize == 0 || branchruledata->rowmeans != NULL);
823 assert(branchruledata->memsize >= 0);
824
825 if( branchruledata->memsize > 0 )
826 {
827 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowmeans, branchruledata->memsize);
828 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowvariances, branchruledata->memsize);
829 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowinfinitiesup, branchruledata->memsize);
830 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowinfinitiesdown, branchruledata->memsize);
831
832 SCIPfreeBlockMemoryArray(scip, &branchruledata->varfilterposs, branchruledata->varpossmemsize);
833 SCIPfreeBlockMemoryArray(scip, &branchruledata->varposs, branchruledata->varpossmemsize);
834 SCIPfreeBlockMemoryArray(scip, &branchruledata->updatedvars, branchruledata->varpossmemsize);
835 SCIPfreeBlockMemoryArray(scip, &branchruledata->currentubs, branchruledata->varpossmemsize);
836 SCIPfreeBlockMemoryArray(scip, &branchruledata->currentlbs, branchruledata->varpossmemsize);
837
838 branchruledata->memsize = 0;
839 }
840}
841
842/** add variable to the bound change event queue; skipped if variable is already in there, or if variable has
843 * no row currently watched
844 */
845static
847 SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
848 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
849 )
850{
851 int varindex;
852 int varpos;
853
854 assert(var != NULL);
855
856 varindex = SCIPvarGetProbindex(var);
857 assert(-1 <= varindex && varindex < branchruledata->varpossmemsize);
858
859 /* if variable is not active, it should not be watched */
860 if( varindex == -1 )
861 return;
862 varpos = branchruledata->varposs[varindex];
863 assert(varpos < branchruledata->nupdatedvars);
864
865 /* nothing to do if variable is already in the queue */
866 if( varpos >= 0 )
867 {
868 assert(branchruledata->updatedvars[varpos] == var);
869
870 return;
871 }
872
873 /* if none of the variables rows was calculated yet, variable needs not to be watched */
874 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID) == (branchruledata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777*/
875 if( branchruledata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777*/
876 return;
877
878 /* add the variable to the branch rule data of variables to process updates for */
879 assert(branchruledata->varpossmemsize > branchruledata->nupdatedvars);
880 varpos = branchruledata->nupdatedvars;
881 branchruledata->updatedvars[varpos] = var;
882 branchruledata->varposs[varindex] = varpos;
883 ++branchruledata->nupdatedvars;
884}
885
886/** returns the next unprocessed variable (last in, first out) with pending bound changes, or NULL */
887static
889 SCIP_BRANCHRULEDATA* branchruledata /**< branchrule data */
890 )
891{
892 SCIP_VAR* var;
893 int varpos;
894 int varindex;
895
896 assert(branchruledata->nupdatedvars >= 0);
897
898 /* return if no variable is currently pending */
899 if( branchruledata->nupdatedvars == 0 )
900 return NULL;
901
902 varpos = branchruledata->nupdatedvars - 1;
903 var = branchruledata->updatedvars[varpos];
904 assert(var != NULL);
905 varindex = SCIPvarGetProbindex(var);
906 assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
907 assert(varpos == branchruledata->varposs[varindex]);
908
909 branchruledata->varposs[varindex] = -1;
910 branchruledata->nupdatedvars--;
911
912 return var;
913}
914
915/** process a variable from the queue of changed variables */
916static
918 SCIP* scip, /**< SCIP data structure */
919 SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
920 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
921 )
922{
923 SCIP_ROW** colrows;
924 SCIP_COL* varcol;
925 SCIP_Real* colvals;
926 SCIP_Real oldmean;
927 SCIP_Real newmean;
928 SCIP_Real oldvariance;
929 SCIP_Real newvariance;
930 SCIP_Real oldlb;
931 SCIP_Real newlb;
932 SCIP_Real oldub;
933 SCIP_Real newub;
934 SCIP_VARTYPE vartype;
935 SCIP_IMPLINTTYPE impltype;
936 int ncolrows;
937 int r;
938 int varindex;
939
940 /* skip event execution if SCIP is in Probing mode because these bound changes will be undone anyway before branching
941 * rule is called again
942 */
943 assert(!SCIPinProbing(scip));
944
945 assert(var != NULL);
946 varcol = SCIPvarGetCol(var);
947 assert(varcol != NULL);
948 colrows = SCIPcolGetRows(varcol);
949 colvals = SCIPcolGetVals(varcol);
950 ncolrows = SCIPcolGetNNonz(varcol);
951
952 varindex = SCIPvarGetProbindex(var);
953
954 oldlb = branchruledata->currentlbs[varindex];
955 oldub = branchruledata->currentubs[varindex];
956
957 /* skip update if the variable has never been subject of previously calculated row activities */
958 assert((oldlb == SCIP_INVALID) == (oldub == SCIP_INVALID)); /*lint !e777*/
959 if( oldlb == SCIP_INVALID ) /*lint !e777*/
960 return SCIP_OKAY;
961
962 newlb = SCIPvarGetLbLocal(var);
963 newub = SCIPvarGetUbLocal(var);
964
965 /* skip update if the bound change events have cancelled out */
966 if( SCIPisFeasEQ(scip, oldlb, newlb) && SCIPisFeasEQ(scip, oldub, newub) )
967 return SCIP_OKAY;
968
969 /* calculate old and new variable distribution mean and variance */
970 oldvariance = 0.0;
971 newvariance = 0.0;
972 oldmean = 0.0;
973 newmean = 0.0;
974 vartype = SCIPvarGetType(var);
975 impltype = SCIPvarGetImplType(var);
976 SCIPvarCalcDistributionParameters(scip, oldlb, oldub, vartype, impltype, &oldmean, &oldvariance);
977 SCIPvarCalcDistributionParameters(scip, newlb, newub, vartype, impltype, &newmean, &newvariance);
978
979 /* loop over all rows of this variable and update activity distribution */
980 for( r = 0; r < ncolrows; ++r )
981 {
982 int rowpos;
983
984 assert(colrows[r] != NULL);
985 rowpos = SCIProwGetIndex(colrows[r]);
986 assert(rowpos >= 0);
987
988 SCIP_CALL( branchruledataEnsureArraySize(scip, branchruledata, rowpos) );
989
990 /* only consider rows for which activity distribution was already calculated */
991 if( branchruledata->rowmeans[rowpos] != SCIP_INVALID ) /*lint !e777*/
992 {
993 SCIP_Real coeff;
994 SCIP_Real coeffsquared;
995 /*lint -e777*/
996 assert(branchruledata->rowvariances[rowpos] != SCIP_INVALID
997 && SCIPisFeasGE(scip, branchruledata->rowvariances[rowpos], 0.0));
998
999 coeff = colvals[r];
1000 coeffsquared = SQR(coeff);
1001
1002 /* update variable contribution to row activity distribution */
1003 branchruledata->rowmeans[rowpos] += coeff * (newmean - oldmean);
1004 branchruledata->rowvariances[rowpos] += coeffsquared * (newvariance - oldvariance);
1005 branchruledata->rowvariances[rowpos] = MAX(0.0, branchruledata->rowvariances[rowpos]);
1006
1007 /* account for changes of the infinite contributions to row activities */
1008 if( coeff > 0.0 )
1009 {
1010 /* if the coefficient is positive, upper bounds affect activity up */
1011 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
1012 ++branchruledata->rowinfinitiesup[rowpos];
1013 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
1014 --branchruledata->rowinfinitiesup[rowpos];
1015
1016 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
1017 ++branchruledata->rowinfinitiesdown[rowpos];
1018 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
1019 --branchruledata->rowinfinitiesdown[rowpos];
1020 }
1021 else if( coeff < 0.0 )
1022 {
1023 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
1024 ++branchruledata->rowinfinitiesdown[rowpos];
1025 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
1026 --branchruledata->rowinfinitiesdown[rowpos];
1027
1028 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
1029 ++branchruledata->rowinfinitiesup[rowpos];
1030 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
1031 --branchruledata->rowinfinitiesup[rowpos];
1032 }
1033 assert(branchruledata->rowinfinitiesdown[rowpos] >= 0);
1034 assert(branchruledata->rowinfinitiesup[rowpos] >= 0);
1035 }
1036 }
1037
1038 /* store the new local bounds in the data */
1039 branchruledataUpdateCurrentBounds(scip, branchruledata, var);
1040
1041 return SCIP_OKAY;
1042}
1043
1044/** destructor of event handler to free user data (called when SCIP is exiting) */
1045static
1046SCIP_DECL_EVENTFREE(eventFreeDistribution)
1047{
1048 SCIP_EVENTHDLRDATA* eventhdlrdata;
1049
1050 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1051 assert(eventhdlrdata != NULL);
1052
1053 SCIPfreeBlockMemory(scip, &eventhdlrdata);
1054 SCIPeventhdlrSetData(eventhdlr, NULL);
1055
1056 return SCIP_OKAY;
1057}
1058
1059/*
1060 * Callback methods of branching rule
1061 */
1062
1063/** copy method for branchrule plugins (called when SCIP copies plugins) */
1064static
1065SCIP_DECL_BRANCHCOPY(branchCopyDistribution)
1066{ /*lint --e{715}*/
1067 assert(scip != NULL);
1068
1070
1071 return SCIP_OKAY;
1072}
1073
1074/** solving process deinitialization method of branching rule (called before branch and bound process data is freed) */
1075static
1076SCIP_DECL_BRANCHEXITSOL(branchExitsolDistribution)
1077{
1078 SCIP_BRANCHRULEDATA* branchruledata;
1079
1080 assert(branchrule != NULL);
1081 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
1082
1083 branchruledata = SCIPbranchruleGetData(branchrule);
1084 assert(branchruledata != NULL);
1085
1086 /* drop variable events at the end of branch and bound process (cannot be used after restarts, anyway) */
1087 if( branchruledata->varfilterposs != NULL)
1088 {
1089 SCIP_VAR** vars;
1090 int nvars;
1091 int v;
1092
1093 vars = SCIPgetVars(scip);
1094 nvars = SCIPgetNVars(scip);
1095
1096 assert(nvars > 0);
1097 for( v = 0; v < nvars; ++v )
1098 {
1099 SCIP_CALL( SCIPdropVarEvent(scip, vars[v], EVENT_DISTRIBUTION, branchruledata->eventhdlr, NULL, branchruledata->varfilterposs[v]) );
1100 }
1101 }
1102
1103 /* free row arrays when branch-and-bound data is freed */
1104 branchruledataFreeArrays(scip, branchruledata);
1105
1106 return SCIP_OKAY;
1107}
1108
1109/** destructor of branching rule to free user data (called when SCIP is exiting) */
1110static
1111SCIP_DECL_BRANCHFREE(branchFreeDistribution)
1112{
1113 SCIP_BRANCHRULEDATA* branchruledata;
1114
1115 assert(branchrule != NULL);
1116 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
1117
1118 branchruledata = SCIPbranchruleGetData(branchrule);
1119 assert(branchruledata != NULL);
1120
1121 /* free internal arrays first */
1122 branchruledataFreeArrays(scip, branchruledata);
1123 SCIPfreeBlockMemory(scip, &branchruledata);
1124 SCIPbranchruleSetData(branchrule, NULL);
1125
1126 return SCIP_OKAY;
1127}
1128
1129/** branching execution method for fractional LP solutions */
1130static
1131SCIP_DECL_BRANCHEXECLP(branchExeclpDistribution)
1132{ /*lint --e{715}*/
1133 SCIP_BRANCHRULEDATA* branchruledata;
1134 SCIP_VAR** lpcands;
1135 SCIP_VAR* bestcand;
1136 SCIP_NODE* downchild;
1137 SCIP_NODE* upchild;
1138
1139 SCIP_Real* lpcandssol;
1140
1141 SCIP_Real bestscore;
1142 SCIP_BRANCHDIR bestbranchdir;
1143 int nlpcands;
1144 int c;
1145
1146 assert(branchrule != NULL);
1147 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
1148 assert(scip != NULL);
1149 assert(result != NULL);
1150
1151 *result = SCIP_DIDNOTRUN;
1152
1153 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, NULL, &nlpcands, NULL) );
1154
1155 if( nlpcands == 0 )
1156 return SCIP_OKAY;
1157
1158 if( SCIPgetNActivePricers(scip) > 0 )
1159 return SCIP_OKAY;
1160
1161 branchruledata = SCIPbranchruleGetData(branchrule);
1162
1163 /* if branching rule data arrays were not initialized before (usually the first call of the branching execution),
1164 * allocate arrays with an initial capacity of the number of LP rows */
1165 if( branchruledata->memsize == 0 )
1166 {
1167 int nlprows;
1168
1169 /* get LP rows data */
1170 nlprows = SCIPgetNLPRows(scip);
1171
1172 /* initialize arrays only if there are actual LP rows to operate on */
1173 if( nlprows > 0 )
1174 {
1175 SCIP_CALL( branchruledataEnsureArraySize(scip, branchruledata, nlprows) );
1176 }
1177 else /* if there are no LP rows, branching rule cannot be used */
1178 return SCIP_OKAY;
1179 }
1180
1181 /* process pending bound change events */
1182 while( branchruledata->nupdatedvars > 0 )
1183 {
1184 SCIP_VAR* nextvar;
1185
1186 /* pop the next variable from the queue and process its bound changes */
1187 nextvar = branchruledataPopBoundChangeVar(branchruledata);
1188 assert(nextvar != NULL);
1189 SCIP_CALL( varProcessBoundChanges(scip, branchruledata, nextvar) );
1190 }
1191
1192 bestscore = -1;
1193 bestbranchdir = SCIP_BRANCHDIR_AUTO;
1194 bestcand = NULL;
1195
1196 /* invalidate the current row distribution data which is initialized on the fly when looping over the candidates */
1197
1198 /* loop over candidate variables and calculate their score in changing the cumulative
1199 * probability of fulfilling each of their constraints */
1200 for( c = 0; c < nlpcands; ++c )
1201 {
1202 SCIP_Real upscore;
1203 SCIP_Real downscore;
1204 SCIP_VAR* lpcand;
1205 int varindex;
1206
1207 lpcand = lpcands[c];
1208 assert(lpcand != NULL);
1209
1210 varindex = SCIPvarGetProbindex(lpcand);
1211
1212 /* in debug mode, ensure that all bound process events which occurred in the mean time have been captured
1213 * by the branching rule event system
1214 */
1215 assert(SCIPisFeasLE(scip, SCIPvarGetLbLocal(lpcand), SCIPvarGetUbLocal(lpcand)));
1216 assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
1217
1218 /*lint -e777*/
1219 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID) == (branchruledata->currentubs[varindex] == SCIP_INVALID));
1220 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID)
1221 || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(lpcand), branchruledata->currentlbs[varindex]));
1222 assert((branchruledata->currentubs[varindex] == SCIP_INVALID)
1223 || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(lpcand), branchruledata->currentubs[varindex]));
1224
1225 /* if the branching rule has not captured the variable bounds yet, this can be done now */
1226 if( branchruledata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777*/
1227 {
1228 branchruledataUpdateCurrentBounds(scip, branchruledata, lpcand);
1229 }
1230
1231 upscore = 0.0;
1232 downscore = 0.0;
1233
1234 /* loop over candidate rows and determine the candidate up- and down- branching score w.r.t. the score parameter */
1235 SCIP_CALL( calcBranchScore(scip, branchruledata, lpcand, lpcandssol[c],
1236 &upscore, &downscore, branchruledata->scoreparam) );
1237
1238 /* if weighted scoring is enabled, use the branching score method of SCIP to weigh up and down score */
1239 if( branchruledata->usescipscore )
1240 {
1241 SCIP_Real score;
1242
1243 score = SCIPgetBranchScore(scip, lpcand, downscore, upscore);
1244
1245 /* select the candidate with the highest branching score */
1246 if( score > bestscore )
1247 {
1248 bestscore = score;
1249 bestcand = lpcand;
1250 /* prioritize branching direction with the higher score */
1251 if( upscore > downscore )
1252 bestbranchdir = SCIP_BRANCHDIR_UPWARDS;
1253 else
1254 bestbranchdir = SCIP_BRANCHDIR_DOWNWARDS;
1255 }
1256 }
1257 else
1258 {
1259 /* no weighted score; keep candidate which has the single highest score in one direction */
1260 if( upscore > bestscore && upscore > downscore )
1261 {
1262 bestscore = upscore;
1263 bestbranchdir = SCIP_BRANCHDIR_UPWARDS;
1264 bestcand = lpcand;
1265 }
1266 else if( downscore > bestscore )
1267 {
1268 bestscore = downscore;
1269 bestbranchdir = SCIP_BRANCHDIR_DOWNWARDS;
1270 bestcand = lpcand;
1271 }
1272 }
1273
1274 SCIPdebugMsg(scip, " Candidate %s has score down %g and up %g \n", SCIPvarGetName(lpcand), downscore, upscore);
1275 SCIPdebugMsg(scip, " Best candidate: %s, score %g, direction %d\n", SCIPvarGetName(bestcand), bestscore, bestbranchdir);
1276 }
1277 assert(!SCIPisFeasIntegral(scip, SCIPvarGetSol(bestcand, TRUE)));
1278 assert(bestbranchdir == SCIP_BRANCHDIR_DOWNWARDS || bestbranchdir == SCIP_BRANCHDIR_UPWARDS);
1279 assert(bestcand != NULL);
1280
1281 SCIPdebugMsg(scip, " Branching on variable %s with bounds [%g, %g] and solution value <%g>\n", SCIPvarGetName(bestcand),
1282 SCIPvarGetLbLocal(bestcand), SCIPvarGetUbLocal(bestcand), SCIPvarGetLPSol(bestcand));
1283
1284 /* branch on the best candidate variable */
1285 SCIP_CALL( SCIPbranchVar(scip, bestcand, &downchild, NULL, &upchild) );
1286
1287 assert(downchild != NULL);
1288 assert(upchild != NULL);
1289
1290 if( bestbranchdir == SCIP_BRANCHDIR_UPWARDS )
1291 {
1293 SCIPdebugMsg(scip, " Changing node priority of up-child.\n");
1294 }
1295 else
1296 {
1297 assert(bestbranchdir == SCIP_BRANCHDIR_DOWNWARDS);
1299 SCIPdebugMsg(scip, " Changing node priority of down-child.\n");
1300 }
1301
1302 *result = SCIP_BRANCHED;
1303
1304 return SCIP_OKAY;
1305}
1306
1307/** event execution method of distribution branching which handles bound change events of variables */
1308static
1309SCIP_DECL_EVENTEXEC(eventExecDistribution)
1310{ /*lint --e{715}*/
1311 SCIP_BRANCHRULEDATA* branchruledata;
1312 SCIP_EVENTHDLRDATA* eventhdlrdata;
1313 SCIP_VAR* var;
1314
1315 assert(eventhdlr != NULL);
1316 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1317 assert(eventhdlrdata != NULL);
1318
1319 branchruledata = eventhdlrdata->branchruledata;
1320 var = SCIPeventGetVar(event);
1321
1322 /* add the variable to the queue of unprocessed variables; method itself ensures that every variable is added at most once */
1323 branchruledataAddBoundChangeVar(branchruledata, var);
1324
1325 return SCIP_OKAY;
1326}
1327
1328
1329/*
1330 * branching rule specific interface methods
1331 */
1332
1333/** creates the distribution branching rule and includes it in SCIP */
1335 SCIP* scip /**< SCIP data structure */
1336 )
1337{
1338 SCIP_BRANCHRULE* branchrule = NULL;
1339 SCIP_BRANCHRULEDATA* branchruledata;
1340 SCIP_EVENTHDLRDATA* eventhdlrdata;
1341
1342 /* create distribution branching rule data */
1343 branchruledata = NULL;
1344 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
1345
1346 branchruledata->memsize = 0;
1347 branchruledata->rowmeans = NULL;
1348 branchruledata->rowvariances = NULL;
1349 branchruledata->rowinfinitiesdown = NULL;
1350 branchruledata->rowinfinitiesup = NULL;
1351 branchruledata->varfilterposs = NULL;
1352 branchruledata->currentlbs = NULL;
1353 branchruledata->currentubs = NULL;
1354
1355 /* create event handler first to finish branch rule data */
1356 eventhdlrdata = NULL;
1357 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
1358 eventhdlrdata->branchruledata = branchruledata;
1359
1360 branchruledata->eventhdlr = NULL;
1361 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &branchruledata->eventhdlr, EVENTHDLR_NAME,
1362 "event handler for dynamic acitivity distribution updating",
1363 eventExecDistribution, eventhdlrdata) );
1364 assert( branchruledata->eventhdlr != NULL);
1365 SCIP_CALL( SCIPsetEventhdlrFree(scip, branchruledata->eventhdlr, eventFreeDistribution) );
1366
1367 /* include branching rule */
1369 BRANCHRULE_MAXBOUNDDIST, branchruledata) );
1370
1371 assert(branchrule != NULL);
1372 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyDistribution) );
1373 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeDistribution) );
1374 SCIP_CALL( SCIPsetBranchruleExitsol(scip, branchrule, branchExitsolDistribution) );
1375 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpDistribution) );
1376
1377 /* add distribution branching rule parameters */
1378 SCIP_CALL( SCIPaddCharParam(scip, "branching/" BRANCHRULE_NAME "/scoreparam",
1379 "the score;largest 'd'ifference, 'l'owest cumulative probability,'h'ighest c.p., 'v'otes lowest c.p., votes highest c.p.('w') ",
1380 &branchruledata->scoreparam, TRUE, DEFAULT_SCOREPARAM, SCOREPARAM_VALUES, NULL, NULL) );
1381
1382 SCIP_CALL( SCIPaddBoolParam(scip, "branching/" BRANCHRULE_NAME "/onlyactiverows",
1383 "should only rows which are active at the current node be considered?",
1384 &branchruledata->onlyactiverows, TRUE, DEFAULT_ONLYACTIVEROWS, NULL, NULL) );
1385
1386 SCIP_CALL( SCIPaddBoolParam(scip, "branching/" BRANCHRULE_NAME "/weightedscore",
1387 "should the branching score weigh up- and down-scores of a variable",
1388 &branchruledata->usescipscore, TRUE, DEFAULT_USEWEIGHTEDSCORE, NULL, NULL) );
1389
1390 return SCIP_OKAY;
1391}
#define BRANCHRULE_DESC
#define DEFAULT_PRIORITY
#define DEFAULT_SCOREPARAM
#define BRANCHRULE_PRIORITY
#define EVENT_DISTRIBUTION
static SCIP_DECL_BRANCHCOPY(branchCopyDistribution)
static SCIP_DECL_BRANCHEXECLP(branchExeclpDistribution)
static SCIP_RETCODE calcBranchScore(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var, SCIP_Real lpsolval, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
#define SCOREPARAM_VALUES
static SCIP_DECL_EVENTEXEC(eventExecDistribution)
static SCIP_DECL_BRANCHFREE(branchFreeDistribution)
#define BRANCHRULE_NAME
static void rowCalculateGauss(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_ROW *row, SCIP_Real *mu, SCIP_Real *sigma2, int *rowinfinitiesdown, int *rowinfinitiesup)
static SCIP_VAR * branchruledataPopBoundChangeVar(SCIP_BRANCHRULEDATA *branchruledata)
static SCIP_RETCODE branchruledataEnsureArraySize(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, int maxindex)
static void branchruledataFreeArrays(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata)
static SCIP_DECL_EVENTFREE(eventFreeDistribution)
static SCIP_RETCODE varProcessBoundChanges(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
static SCIP_DECL_BRANCHEXITSOL(branchExitsolDistribution)
static void branchruledataUpdateCurrentBounds(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
#define DEFAULT_ONLYACTIVEROWS
static void branchruledataAddBoundChangeVar(SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
#define EVENTHDLR_NAME
#define BRANCHRULE_MAXDEPTH
#define BRANCHRULE_MAXBOUNDDIST
#define DEFAULT_USEWEIGHTEDSCORE
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_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define SQR(x)
Definition: def.h:199
#define TRUE
Definition: def.h:93
#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_Real SCIPcalcCumulativeDistribution(SCIP *scip, SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
SCIP_RETCODE SCIPincludeBranchruleDistribution(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
SCIP_RETCODE SCIPchgChildPrio(SCIP *scip, SCIP_NODE *child, SCIP_Real priority)
Definition: scip_prob.c:4388
#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 SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip_branch.c:256
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip_branch.c:160
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
Definition: scip_branch.c:123
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2018
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1886
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip_branch.c:176
SCIP_RETCODE SCIPsetBranchruleExitsol(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXITSOL((*branchexitsol)))
Definition: scip_branch.c:240
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1896
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip_branch.c:402
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip_branch.c:1058
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: scip_branch.c:857
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 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
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:632
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip_pricer.c:348
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17686
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17607
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17632
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17696
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 SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1974
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17652
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17642
SCIP_Bool SCIPisSumPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:23683
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:19007
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
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 SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:24664
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition: var.c:23463
SCIP_Real SCIPerf(SCIP_Real x)
Definition: misc.c:160
#define M_SQRT2
Definition: misc_rowprep.c:59
Definition: pqueue.h:38
public methods for branching rules
public methods for managing events
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
public data structures and miscellaneous methods
public methods for problem variables
public methods for branching rule plugins and branching
public methods for event handler plugins and event handlers
general public methods
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 variable pricer plugins
public methods for global and local (sub)problems
public methods for the probing mode
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:57
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:160
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_AUTO
Definition: type_history.h:46
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:48
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_BRANCHED
Definition: type_result.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
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_IMPLINTTYPE_NONE
Definition: type_var.h:90
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:53
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73