Scippy

SCIP

Solving Constraint Integer Programs

branch.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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file branch.c
17  * @brief methods for branching rules and branching candidate storage
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  * @author Stefan Heinz
22  * @author Michael Winkler
23  * @author Stefan Vigerske
24  */
25 
26 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
27 
28 #include <assert.h>
29 #include <string.h>
30 
31 #include "scip/def.h"
32 #include "blockmemshell/memory.h"
33 #include "scip/set.h"
34 #include "scip/stat.h"
35 #include "scip/clock.h"
36 #include "scip/paramset.h"
37 #include "scip/event.h"
38 #include "scip/lp.h"
39 #include "scip/var.h"
40 #include "scip/prob.h"
41 #include "scip/tree.h"
42 #include "scip/sepastore.h"
43 #include "scip/scip.h"
44 #include "scip/branch.h"
45 #include "scip/solve.h"
46 
47 #include "scip/struct_branch.h"
48 
49 /*
50  * memory growing methods for dynamically allocated arrays
51  */
52 
53 /** ensures, that lpcands array can store at least num entries */
54 static
56  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
57  SCIP_SET* set, /**< global SCIP settings */
58  int num /**< minimum number of entries to store */
59  )
60 {
61  assert(branchcand->nlpcands <= branchcand->lpcandssize);
62 
63  if( num > branchcand->lpcandssize )
64  {
65  int newsize;
66 
67  newsize = SCIPsetCalcMemGrowSize(set, num);
68  SCIP_ALLOC( BMSreallocMemoryArray(&branchcand->lpcands, newsize) );
69  SCIP_ALLOC( BMSreallocMemoryArray(&branchcand->lpcandssol, newsize) );
70  SCIP_ALLOC( BMSreallocMemoryArray(&branchcand->lpcandsfrac, newsize) );
71  branchcand->lpcandssize = newsize;
72  }
73  assert(num <= branchcand->lpcandssize);
74 
75  return SCIP_OKAY;
76 }
77 
78 /** ensures, that pseudocands array can store at least num entries */
79 static
81  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
82  SCIP_SET* set, /**< global SCIP settings */
83  int num /**< minimum number of entries to store */
84  )
85 {
86  assert(branchcand->npseudocands <= branchcand->pseudocandssize);
87 
88  if( num > branchcand->pseudocandssize )
89  {
90  int newsize;
91 
92  newsize = SCIPsetCalcMemGrowSize(set, num);
93  SCIP_ALLOC( BMSreallocMemoryArray(&branchcand->pseudocands, newsize) );
94  branchcand->pseudocandssize = newsize;
95  }
96  assert(num <= branchcand->pseudocandssize);
97 
98  return SCIP_OKAY;
99 }
100 
101 /** ensures, that externcands array can store at least num entries */
102 static
104  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
105  SCIP_SET* set, /**< global SCIP settings */
106  int num /**< minimum number of entries to store */
107  )
108 {
109  assert(branchcand->nexterncands <= branchcand->externcandssize);
110 
111  if( num > branchcand->externcandssize )
112  {
113  int newsize;
114 
115  newsize = SCIPsetCalcMemGrowSize(set, num);
116  SCIP_ALLOC( BMSreallocMemoryArray(&branchcand->externcands, newsize) );
117  SCIP_ALLOC( BMSreallocMemoryArray(&branchcand->externcandsscore, newsize) );
118  SCIP_ALLOC( BMSreallocMemoryArray(&branchcand->externcandssol, newsize) );
119  branchcand->externcandssize = newsize;
120  }
121  assert(num <= branchcand->externcandssize);
122 
123  return SCIP_OKAY;
124 }
125 
126 
127 
128 /*
129  * branching candidate storage methods
130  */
131 
132 /** creates a branching candidate storage */
134  SCIP_BRANCHCAND** branchcand /**< pointer to store branching candidate storage */
135  )
136 {
137  assert(branchcand != NULL);
138 
139  SCIP_ALLOC( BMSallocMemory(branchcand) );
140  (*branchcand)->lpcands = NULL;
141  (*branchcand)->lpcandssol = NULL;
142  (*branchcand)->lpcandsfrac = NULL;
143  (*branchcand)->externcands = NULL;
144  (*branchcand)->externcandssol = NULL;
145  (*branchcand)->externcandsscore = NULL;
146  (*branchcand)->pseudocands = NULL;
147  (*branchcand)->lpcandssize = 0;
148  (*branchcand)->nlpcands = 0;
149  (*branchcand)->nimpllpfracs = 0;
150  (*branchcand)->npriolpcands = 0;
151  (*branchcand)->npriolpbins = 0;
152  (*branchcand)->lpmaxpriority = INT_MIN;
153  (*branchcand)->externcandssize = 0;
154  (*branchcand)->nexterncands = 0;
155  (*branchcand)->nprioexterncands = 0;
156  (*branchcand)->nprioexternbins = 0;
157  (*branchcand)->nprioexternints = 0;
158  (*branchcand)->nprioexternimpls = 0;
159  (*branchcand)->externmaxpriority = INT_MIN;
160  (*branchcand)->pseudocandssize = 0;
161  (*branchcand)->npseudocands = 0;
162  (*branchcand)->npriopseudocands = 0;
163  (*branchcand)->npriopseudobins = 0;
164  (*branchcand)->npriopseudoints = 0;
165  (*branchcand)->pseudomaxpriority = INT_MIN;
166 
167  SCIPbranchcandInvalidate(*branchcand);
168 
169  return SCIP_OKAY;
170 }
171 
172 /** frees branching candidate storage */
174  SCIP_BRANCHCAND** branchcand /**< pointer to store branching candidate storage */
175  )
176 {
177  assert(branchcand != NULL);
178 
179  BMSfreeMemoryArrayNull(&(*branchcand)->lpcands);
180  BMSfreeMemoryArrayNull(&(*branchcand)->lpcandssol);
181  BMSfreeMemoryArrayNull(&(*branchcand)->lpcandsfrac);
182  BMSfreeMemoryArrayNull(&(*branchcand)->pseudocands);
183  BMSfreeMemoryArrayNull(&(*branchcand)->externcands);
184  BMSfreeMemoryArrayNull(&(*branchcand)->externcandsscore);
185  BMSfreeMemoryArrayNull(&(*branchcand)->externcandssol);
186  BMSfreeMemory(branchcand);
187 
188  return SCIP_OKAY;
189 }
190 
191 /** resets branching candidates storage */
193  SCIP_BRANCHCAND* branchcand /**< pointer to store branching candidate storage */
194  )
195 {
196  assert(branchcand != NULL);
197 
198  branchcand->validlpcandslp = -1;
199 }
200 
201 /** calculates branching candidates for LP solution branching (fractional variables) */
202 static
204  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
205  SCIP_SET* set, /**< global SCIP settings */
206  SCIP_STAT* stat, /**< problem statistics */
207  SCIP_LP* lp /**< current LP data */
208  )
209 {
210  assert(branchcand != NULL);
211  assert(stat != NULL);
212  assert(branchcand->validlpcandslp <= stat->lpcount);
213  assert(lp != NULL);
214  assert(lp->solved);
216 
217  SCIPsetDebugMsg(set, "calculating LP branching candidates: validlp=%" SCIP_LONGINT_FORMAT ", lpcount=%" SCIP_LONGINT_FORMAT "\n",
218  branchcand->validlpcandslp, stat->lpcount);
219 
221  {
222  branchcand->lpmaxpriority = INT_MIN / 2;
223  branchcand->nlpcands = 0;
224  branchcand->npriolpcands = 0;
225  branchcand->npriolpbins = 0;
226  branchcand->nimpllpfracs = 0;
227  branchcand->validlpcandslp = stat->lpcount;
228 
229  SCIPsetDebugMsg(set, " LP is unbounded -> no branching candidates\n");
230  return SCIP_OKAY;
231  }
232 
233  /* check, if the current LP branching candidate array is invalid */
234  if( branchcand->validlpcandslp < stat->lpcount )
235  {
236  SCIP_COL** cols;
237  SCIP_VAR* var;
238  SCIP_COL* col;
239  SCIP_Real primsol;
240  SCIP_Real frac;
241  SCIP_VARTYPE vartype;
242  int branchpriority;
243  int ncols;
244  int c;
245  int insertpos;
246 
247  SCIPsetDebugMsg(set, " -> recalculating LP branching candidates\n");
248 
249  cols = SCIPlpGetCols(lp);
250  ncols = SCIPlpGetNCols(lp);
251 
252  /* construct the LP branching candidate set, moving the candidates with maximal priority to the front */
253  SCIP_CALL( ensureLpcandsSize(branchcand, set, ncols) );
254 
255  branchcand->lpmaxpriority = INT_MIN / 2;
256  branchcand->nlpcands = 0;
257  branchcand->nimpllpfracs = 0;
258  branchcand->npriolpcands = 0;
259  branchcand->npriolpbins = 0;
260  for( c = 0; c < ncols; ++c )
261  {
262  col = cols[c];
263  assert(col != NULL);
264  assert(col->lppos == c);
265  assert(col->lpipos >= 0);
266 
267  primsol = SCIPcolGetPrimsol(col);
268  assert(primsol < SCIP_INVALID);
269  assert(SCIPsetIsInfinity(set, -col->lb) || SCIPsetIsFeasGE(set, primsol, col->lb));
270  assert(SCIPsetIsInfinity(set, col->ub) || SCIPsetIsFeasLE(set, primsol, col->ub));
271 
272  var = col->var;
273  assert(var != NULL);
274  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
275  assert(SCIPvarGetCol(var) == col);
276 
277  /* LP branching candidates are fractional binary and integer variables; implicit variables are kept at the end
278  * of the candidates array for some rounding heuristics
279  */
280  vartype = SCIPvarGetType(var);
281  if( vartype == SCIP_VARTYPE_CONTINUOUS )
282  continue;
283 
284  /* ignore fixed variables (due to numerics, it is possible, that the LP solution of a fixed integer variable
285  * (with large fixed value) is fractional in terms of absolute feasibility measure)
286  */
287  if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
288  continue;
289 
290  /* check, if the LP solution value is fractional */
291  frac = SCIPsetFeasFrac(set, primsol);
292 
293  /* The fractionality should not be smaller than -feastol, however, if the primsol is large enough
294  * and close to an integer, fixed precision floating point arithmetic might give us values slightly
295  * smaller than -feastol. Originally, the "frac >= -feastol"-check was within SCIPsetIsFeasFracIntegral(),
296  * however, we relaxed it to "frac >= -2*feastol" and have the stricter check here for small-enough primsols.
297  */
298  assert(SCIPsetIsGE(set, frac, -SCIPsetFeastol(set)) || (primsol > 1e14 * SCIPsetFeastol(set)));
299 
300  if( SCIPsetIsFeasFracIntegral(set, frac) )
301  continue;
302 
303  /* insert candidate in candidate list */
304  branchpriority = SCIPvarGetBranchPriority(var);
305  insertpos = branchcand->nlpcands + branchcand->nimpllpfracs;
306  assert(insertpos < branchcand->lpcandssize);
307 
308  if( vartype == SCIP_VARTYPE_IMPLINT )
309  branchpriority = INT_MIN;
310 
311  assert(vartype == SCIP_VARTYPE_IMPLINT || branchpriority >= INT_MIN/2);
312  /* ensure that implicit variables are stored at the end of the array */
313  if( vartype != SCIP_VARTYPE_IMPLINT && branchcand->nimpllpfracs > 0 )
314  {
315  assert(branchcand->lpcands[branchcand->nlpcands] != NULL
316  && SCIPvarGetType(branchcand->lpcands[branchcand->nlpcands]) == SCIP_VARTYPE_IMPLINT );
317 
318  branchcand->lpcands[insertpos] = branchcand->lpcands[branchcand->nlpcands];
319  branchcand->lpcandssol[insertpos] = branchcand->lpcandssol[branchcand->nlpcands];
320  branchcand->lpcandsfrac[insertpos] = branchcand->lpcandsfrac[branchcand->nlpcands];
321 
322  insertpos = branchcand->nlpcands;
323  }
324 
325  if( branchpriority > branchcand->lpmaxpriority )
326  {
327  /* candidate has higher priority than the current maximum:
328  * move it to the front and declare it to be the single best candidate
329  */
330  if( insertpos != 0 )
331  {
332  branchcand->lpcands[insertpos] = branchcand->lpcands[0];
333  branchcand->lpcandssol[insertpos] = branchcand->lpcandssol[0];
334  branchcand->lpcandsfrac[insertpos] = branchcand->lpcandsfrac[0];
335  insertpos = 0;
336  }
337  branchcand->npriolpcands = 1;
338  branchcand->npriolpbins = (vartype == SCIP_VARTYPE_BINARY ? 1 : 0);
339  branchcand->lpmaxpriority = branchpriority;
340  }
341  else if( branchpriority == branchcand->lpmaxpriority )
342  {
343  /* candidate has equal priority as the current maximum:
344  * move away the first non-maximal priority candidate, move the current candidate to the correct
345  * slot (binaries first) and increase the number of maximal priority candidates
346  */
347  if( insertpos != branchcand->npriolpcands )
348  {
349  branchcand->lpcands[insertpos] = branchcand->lpcands[branchcand->npriolpcands];
350  branchcand->lpcandssol[insertpos] = branchcand->lpcandssol[branchcand->npriolpcands];
351  branchcand->lpcandsfrac[insertpos] = branchcand->lpcandsfrac[branchcand->npriolpcands];
352  insertpos = branchcand->npriolpcands;
353  }
354  branchcand->npriolpcands++;
355  if( vartype == SCIP_VARTYPE_BINARY )
356  {
357  if( insertpos != branchcand->npriolpbins )
358  {
359  branchcand->lpcands[insertpos] = branchcand->lpcands[branchcand->npriolpbins];
360  branchcand->lpcandssol[insertpos] = branchcand->lpcandssol[branchcand->npriolpbins];
361  branchcand->lpcandsfrac[insertpos] = branchcand->lpcandsfrac[branchcand->npriolpbins];
362  insertpos = branchcand->npriolpbins;
363  }
364  branchcand->npriolpbins++;
365  }
366  }
367  /* insert variable at the correct position of the candidates storage */
368  branchcand->lpcands[insertpos] = var;
369  branchcand->lpcandssol[insertpos] = primsol;
370  branchcand->lpcandsfrac[insertpos] = frac;
371 
372  /* increase the counter depending on the variable type */
373  if( vartype != SCIP_VARTYPE_IMPLINT )
374  branchcand->nlpcands++;
375  else
376  branchcand->nimpllpfracs++;
377 
378  SCIPsetDebugMsg(set, " -> candidate %d: var=<%s>, sol=%g, frac=%g, prio=%d (max: %d) -> pos %d\n",
379  branchcand->nlpcands, SCIPvarGetName(var), primsol, frac, branchpriority, branchcand->lpmaxpriority,
380  insertpos);
381  }
382 
383 #ifndef NDEBUG
384  /* in debug mode we assert that the variables are positioned correctly (binaries and integers first,
385  * implicit integers last)
386  */
387  for( c = 0; c < branchcand->nlpcands + branchcand->nimpllpfracs; ++c )
388  {
389  assert(c >= branchcand->nlpcands || SCIPvarGetType(branchcand->lpcands[c]) != SCIP_VARTYPE_IMPLINT);
390  assert(c < branchcand->nlpcands || SCIPvarGetType(branchcand->lpcands[c]) == SCIP_VARTYPE_IMPLINT);
391  }
392 #endif
393 
394  branchcand->validlpcandslp = stat->lpcount;
395  }
396  assert(0 <= branchcand->npriolpcands && branchcand->npriolpcands <= branchcand->nlpcands);
397 
398  SCIPsetDebugMsg(set, " -> %d fractional variables (%d of maximal priority)\n", branchcand->nlpcands, branchcand->npriolpcands);
399 
400  return SCIP_OKAY;
401 }
402 
403 /** gets branching candidates for LP solution branching (fractional variables) */
405  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
406  SCIP_SET* set, /**< global SCIP settings */
407  SCIP_STAT* stat, /**< problem statistics */
408  SCIP_LP* lp, /**< current LP data */
409  SCIP_VAR*** lpcands, /**< pointer to store the array of LP branching candidates, or NULL */
410  SCIP_Real** lpcandssol, /**< pointer to store the array of LP candidate solution values, or NULL */
411  SCIP_Real** lpcandsfrac, /**< pointer to store the array of LP candidate fractionalities, or NULL */
412  int* nlpcands, /**< pointer to store the number of LP branching candidates, or NULL */
413  int* npriolpcands, /**< pointer to store the number of candidates with maximal priority, or NULL */
414  int* nfracimplvars /**< pointer to store the number of implicit fractional variables, or NULL */
415  )
416 {
417  /* calculate branching candidates */
418  SCIP_CALL( branchcandCalcLPCands(branchcand, set, stat, lp) );
419 
420  /* assign return values */
421  if( lpcands != NULL )
422  *lpcands = branchcand->lpcands;
423  if( lpcandssol != NULL )
424  *lpcandssol = branchcand->lpcandssol;
425  if( lpcandsfrac != NULL )
426  *lpcandsfrac = branchcand->lpcandsfrac;
427  if( nlpcands != NULL )
428  *nlpcands = branchcand->nlpcands;
429  if( npriolpcands != NULL )
430  *npriolpcands = (set->branch_preferbinary && branchcand->npriolpbins > 0 ? branchcand->npriolpbins
431  : branchcand->npriolpcands);
432  if( nfracimplvars != NULL )
433  *nfracimplvars = branchcand->nimpllpfracs;
434 
435  return SCIP_OKAY;
436 }
437 
438 /** gets external branching candidates */
440  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
441  SCIP_VAR*** externcands, /**< pointer to store the array of external branching candidates, or NULL */
442  SCIP_Real** externcandssol, /**< pointer to store the array of external candidate solution values, or NULL */
443  SCIP_Real** externcandsscore, /**< pointer to store the array of external candidate scores, or NULL */
444  int* nexterncands, /**< pointer to store the number of external branching candidates, or NULL */
445  int* nprioexterncands, /**< pointer to store the number of candidates with maximal priority, or NULL */
446  int* nprioexternbins, /**< pointer to store the number of binary candidates with maximal priority, or NULL */
447  int* nprioexternints, /**< pointer to store the number of integer candidates with maximal priority, or NULL */
448  int* nprioexternimpls /**< pointer to store the number of implicit integer candidates with maximal priority,
449  * or NULL */
450  )
451 {
452  assert(branchcand != NULL);
453 
454  /* assign return values */
455  if( externcands != NULL )
456  *externcands = branchcand->externcands;
457  if( externcandssol != NULL )
458  *externcandssol = branchcand->externcandssol;
459  if( externcandsscore != NULL )
460  *externcandsscore = branchcand->externcandsscore;
461  if( nexterncands != NULL )
462  *nexterncands = branchcand->nexterncands;
463  if( nprioexterncands != NULL )
464  *nprioexterncands = branchcand->nprioexterncands;
465  if( nprioexternbins != NULL )
466  *nprioexternbins = branchcand->nprioexternbins;
467  if( nprioexternints != NULL )
468  *nprioexternints = branchcand->nprioexternints;
469  if( nprioexternimpls != NULL )
470  *nprioexternimpls = branchcand->nprioexternimpls;
471 
472  return SCIP_OKAY;
473 }
474 
475 /** gets number of external branching candidates */
477  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
478  )
479 {
480  assert(branchcand != NULL);
481 
482  return branchcand->nexterncands;
483 }
484 
485 /** gets number of external branching candidates with maximal branch priority */
487  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
488  )
489 {
490  assert(branchcand != NULL);
491 
492  return branchcand->nprioexterncands;
493 }
494 
495 /** gets number of binary external branching candidates with maximal branch priority */
497  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
498  )
499 {
500  assert(branchcand != NULL);
501 
502  return branchcand->nprioexternbins;
503 }
504 
505 /** gets number of integer external branching candidates with maximal branch priority */
507  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
508  )
509 {
510  assert(branchcand != NULL);
511 
512  return branchcand->nprioexternints;
513 }
514 
515 /** gets number of implicit integer external branching candidates with maximal branch priority */
517  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
518  )
519 {
520  assert(branchcand != NULL);
521 
522  return branchcand->nprioexternimpls;
523 }
524 
525 /** gets number of continuous external branching candidates with maximal branch priority */
527  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
528  )
529 {
530  assert(branchcand != NULL);
531 
532  return branchcand->nprioexterncands - branchcand->nprioexternbins - branchcand->nprioexternints - branchcand->nprioexternimpls;
533 }
534 
535 /** insert variable, its score and its solution value into the external branching candidate storage
536  * the absolute difference of the current lower and upper bounds of the variable must be at least epsilon
537  */
539  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
540  SCIP_SET* set, /**< global SCIP settings */
541  SCIP_VAR* var, /**< variable to insert */
542  SCIP_Real score, /**< score of external candidate, e.g. infeasibility */
543  SCIP_Real solval /**< value of the variable in the current solution */
544  )
545 {
546  SCIP_VARTYPE vartype;
547  int branchpriority;
548  int insertpos;
549 
550  assert(branchcand != NULL);
551  assert(var != NULL);
552  assert(!SCIPsetIsEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))); /* the variable should not be fixed yet */
553  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || !SCIPsetIsEQ(set, SCIPsetCeil(set, SCIPvarGetLbLocal(var)), SCIPsetFloor(set, SCIPvarGetUbLocal(var)))); /* a discrete variable should also not be fixed, even after rounding bounds to integral values */
554  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR || !SCIPsetIsEQ(set, SCIPvarGetMultaggrLbLocal(var, set), SCIPvarGetMultaggrUbLocal(var, set))); /* also the current bounds of a multi-aggregated variable should not be fixed yet */
555  assert(branchcand->nprioexterncands <= branchcand->nexterncands);
556  assert(branchcand->nexterncands <= branchcand->externcandssize);
557 
558  vartype = SCIPvarGetType(var);
559  branchpriority = SCIPvarGetBranchPriority(var);
560  insertpos = branchcand->nexterncands;
561 
562  SCIP_CALL( ensureExterncandsSize(branchcand, set, branchcand->nexterncands+1) );
563 
564  SCIPsetDebugMsg(set, "inserting external candidate <%s> of type %d and priority %d into candidate set (maxprio: %d), score = %g, solval = %g\n",
565  SCIPvarGetName(var), vartype, branchpriority, branchcand->externmaxpriority, score, solval);
566 
567  /* insert the variable into externcands, making sure, that the highest priority candidates are at the front
568  * and ordered binaries, integers, implicit integers, continuous
569  */
570  if( branchpriority > branchcand->externmaxpriority )
571  {
572  /* candidate has higher priority than the current maximum:
573  * move it to the front and declare it to be the single best candidate
574  */
575  branchcand->externcands[insertpos] = branchcand->externcands[0];
576  branchcand->externcandsscore[insertpos] = branchcand->externcandsscore[0];
577  branchcand->externcandssol[insertpos] = branchcand->externcandssol[0];
578 
579  insertpos = 0;
580 
581  branchcand->nprioexterncands = 1;
582  branchcand->nprioexternbins = (vartype == SCIP_VARTYPE_BINARY ? 1 : 0);
583  branchcand->nprioexternints = (vartype == SCIP_VARTYPE_INTEGER ? 1 : 0);
584  branchcand->nprioexternimpls = (vartype == SCIP_VARTYPE_IMPLINT ? 1 : 0);
585  branchcand->externmaxpriority = branchpriority;
586  }
587  else if( branchpriority == branchcand->externmaxpriority )
588  {
589  /* candidate has equal priority as the current maximum:
590  * move away the first non-maximal priority candidate, move the current candidate to the correct
591  * slot (binaries first, integers next, implicit integers next, continuous last) and increase the number
592  * of maximal priority candidates
593  */
594  if( insertpos != branchcand->nprioexterncands )
595  {
596  branchcand->externcands[insertpos] = branchcand->externcands[branchcand->nprioexterncands];
597  branchcand->externcandsscore[insertpos] = branchcand->externcandsscore[branchcand->nprioexterncands];
598  branchcand->externcandssol[insertpos] = branchcand->externcandssol[branchcand->nprioexterncands];
599 
600  insertpos = branchcand->nprioexterncands;
601  }
602  branchcand->nprioexterncands++;
603  if( vartype == SCIP_VARTYPE_BINARY || vartype == SCIP_VARTYPE_INTEGER || vartype == SCIP_VARTYPE_IMPLINT )
604  {
605  if( insertpos != branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls )
606  {
607  branchcand->externcands[insertpos] =
608  branchcand->externcands[branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls];
609  branchcand->externcandsscore[insertpos] =
610  branchcand->externcandsscore[branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls];
611  branchcand->externcandssol[insertpos] =
612  branchcand->externcandssol[branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls];
613 
614  insertpos = branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls;
615  }
616  branchcand->nprioexternimpls++;
617 
618 
619  if( vartype == SCIP_VARTYPE_BINARY || vartype == SCIP_VARTYPE_INTEGER )
620  {
621  if( insertpos != branchcand->nprioexternbins + branchcand->nprioexternints )
622  {
623  branchcand->externcands[insertpos] =
624  branchcand->externcands[branchcand->nprioexternbins + branchcand->nprioexternints];
625  branchcand->externcandsscore[insertpos] =
626  branchcand->externcandsscore[branchcand->nprioexternbins + branchcand->nprioexternints];
627  branchcand->externcandssol[insertpos] =
628  branchcand->externcandssol[branchcand->nprioexternbins + branchcand->nprioexternints];
629 
630  insertpos = branchcand->nprioexternbins + branchcand->nprioexternints;
631  }
632  branchcand->nprioexternints++;
633  branchcand->nprioexternimpls--;
634 
635 
636  if( vartype == SCIP_VARTYPE_BINARY )
637  {
638  if( insertpos != branchcand->nprioexternbins )
639  {
640  branchcand->externcands[insertpos] = branchcand->externcands[branchcand->nprioexternbins];
641  branchcand->externcandsscore[insertpos] = branchcand->externcandsscore[branchcand->nprioexternbins];
642  branchcand->externcandssol[insertpos] = branchcand->externcandssol[branchcand->nprioexternbins];
643 
644  insertpos = branchcand->nprioexternbins;
645  }
646  branchcand->nprioexternbins++;
647  branchcand->nprioexternints--;
648  }
649  }
650  }
651  }
652  branchcand->externcands[insertpos] = var;
653  branchcand->externcandsscore[insertpos] = score;
654  branchcand->externcandssol[insertpos] = solval;
655  branchcand->nexterncands++;
656 
657  SCIPsetDebugMsg(set, " -> inserted at position %d (nprioexterncands=%d)\n", insertpos, branchcand->nprioexterncands);
658 
659  assert(0 <= branchcand->nprioexterncands && branchcand->nprioexterncands <= branchcand->nexterncands);
660  assert(0 <= branchcand->nprioexternbins && branchcand->nprioexternbins <= branchcand->nprioexterncands);
661  assert(0 <= branchcand->nprioexternints && branchcand->nprioexternints <= branchcand->nprioexterncands);
662  assert(0 <= branchcand->nprioexternimpls && branchcand->nprioexternimpls <= branchcand->nprioexterncands);
663 
664  return SCIP_OKAY;
665 }
666 
667 /** removes all external candidates from the storage for external branching */
669  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
670  )
671 {
672  assert(branchcand != NULL);
673 
674  branchcand->nexterncands = 0;
675  branchcand->nprioexterncands = 0;
676  branchcand->nprioexternbins = 0;
677  branchcand->nprioexternints = 0;
678  branchcand->nprioexternimpls = 0;
679  branchcand->externmaxpriority = INT_MIN;
680 }
681 
682 /** checks whether the given variable is contained in the candidate storage for external branching */
684  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
685  SCIP_VAR* var /**< variable to look for */
686  )
687 {
688  int branchpriority;
689  int i;
690 
691  assert(branchcand != NULL);
692  assert(var != NULL);
693  assert(branchcand->nprioexterncands <= branchcand->nexterncands);
694  assert(branchcand->nexterncands <= branchcand->externcandssize);
695 
696  branchpriority = SCIPvarGetBranchPriority(var);
697 
698  /* look for the variable in the externcands, using the fact, that the highest priority candidates are at the front
699  * and ordered binaries, integers, implicit integers, continuous
700  */
701  if( branchpriority > branchcand->externmaxpriority )
702  {
703  /* the branching priority of the variable is higher than the maximal priority contained in the array;
704  * the variable can thus not be contained */
705  return FALSE;
706  }
707  if( branchpriority == branchcand->externmaxpriority )
708  {
709  SCIP_VARTYPE vartype;
710 
711  vartype = SCIPvarGetType(var);
712 
713  /* variable has equal priority as the current maximum:
714  * look for it in the correct slot (binaries first, integers next, implicit integers next, continuous last)
715  */
716  if( vartype == SCIP_VARTYPE_BINARY )
717  {
718  /* the variable is binary, look at the first branchcand->nprioexternbins slots */
719  for( i = 0; i < branchcand->nprioexternbins; i++ )
720  if( branchcand->externcands[i] == var )
721  return TRUE;
722  return FALSE;
723  }
724  if( vartype == SCIP_VARTYPE_INTEGER )
725  {
726  /* the variable is integer, look at the slots containing integers */
727  for( i = 0; i < branchcand->nprioexternints; i++ )
728  if( branchcand->externcands[branchcand->nprioexternbins + i] == var )
729  return TRUE;
730  return FALSE;
731  }
732  if( vartype == SCIP_VARTYPE_IMPLINT )
733  {
734  /* the variable is implicit integer, look at the slots containing implicit integers */
735  for( i = 0; i < branchcand->nprioexternimpls; i++ )
736  if( branchcand->externcands[branchcand->nprioexternbins + branchcand->nprioexternints + i] == var )
737  return TRUE;
738  return FALSE;
739  }
740  /* the variable is continuous, look at the slots containing continuous variables */
741  assert(vartype == SCIP_VARTYPE_CONTINUOUS);
742  for( i = branchcand->nprioexternbins + branchcand->nprioexternints + branchcand->nprioexternimpls;
743  i < branchcand->nprioexterncands; i++ )
744  if( branchcand->externcands[i] == var )
745  return TRUE;
746  return FALSE;
747  }
748  /* the branching priority of the variable is lower than the maximal priority contained in the array;
749  * look for the variable in the candidates which do not have maximal priority */
750  assert(branchpriority < branchcand->externmaxpriority);
751 
752  for( i = branchcand->nprioexterncands; i < branchcand->nexterncands; i++ )
753  if( branchcand->externcands[i] == var )
754  return TRUE;
755  return FALSE;
756 }
757 
758 /** gets branching candidates for pseudo solution branching (non-fixed variables) */
760  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
761  SCIP_SET* set, /**< global SCIP settings */
762  SCIP_PROB* prob, /**< problem data */
763  SCIP_VAR*** pseudocands, /**< pointer to store the array of pseudo branching candidates, or NULL */
764  int* npseudocands, /**< pointer to store the number of pseudo branching candidates, or NULL */
765  int* npriopseudocands /**< pointer to store the number of candidates with maximal priority, or NULL */
766  )
767 {
768  assert(branchcand != NULL);
769 
770 #ifndef NDEBUG
771  /* check, if the current pseudo branching candidate array is correct */
772  {
773  SCIP_VAR* var;
774  int npcs;
775  int v;
776 
777  assert(prob != NULL);
778 
779  /* pseudo branching candidates are non-fixed binary, integer, and implicit integer variables */
780  npcs = 0;
781  for( v = 0; v < prob->nbinvars + prob->nintvars + prob->nimplvars; ++v )
782  {
783  var = prob->vars[v];
784  assert(var != NULL);
786  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY
789  assert(SCIPsetIsFeasIntegral(set, SCIPvarGetLbLocal(var)));
790  assert(SCIPsetIsFeasIntegral(set, SCIPvarGetUbLocal(var)));
791  assert(SCIPsetIsLE(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
792 
793  if( SCIPsetIsLT(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
794  {
795  assert(0 <= var->pseudocandindex && var->pseudocandindex < branchcand->npseudocands);
796  assert(branchcand->pseudocands[var->pseudocandindex] == var);
797  npcs++;
798  }
799  else
800  {
801  assert(var->pseudocandindex == -1);
802  }
803  }
804  assert(branchcand->npseudocands == npcs);
805  for (v = 0; v < branchcand->npriopseudocands; ++v)
806  assert( branchcand->pseudocands[v]->branchpriority == branchcand->pseudomaxpriority );
807  }
808 #endif
809 
810  /* assign return values */
811  if( pseudocands != NULL )
812  *pseudocands = branchcand->pseudocands;
813  if( npseudocands != NULL )
814  *npseudocands = branchcand->npseudocands;
815  if( npriopseudocands != NULL )
816  *npriopseudocands = (set->branch_preferbinary && branchcand->npriopseudobins > 0 ? branchcand->npriopseudobins
817  : branchcand->npriopseudocands);
818 
819  return SCIP_OKAY;
820 }
821 
822 /** gets number of branching candidates for pseudo solution branching (non-fixed variables) */
824  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
825  )
826 {
827  assert(branchcand != NULL);
828 
829  return branchcand->npseudocands;
830 }
831 
832 /** gets number of branching candidates with maximal branch priority for pseudo solution branching */
834  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
835  )
836 {
837  assert(branchcand != NULL);
838 
839  return branchcand->npriopseudocands;
840 }
841 
842 /** gets number of binary branching candidates with maximal branch priority for pseudo solution branching */
844  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
845  )
846 {
847  assert(branchcand != NULL);
848 
849  return branchcand->npriopseudobins;
850 }
851 
852 /** gets number of integer branching candidates with maximal branch priority for pseudo solution branching */
854  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
855  )
856 {
857  assert(branchcand != NULL);
858 
859  return branchcand->npriopseudoints;
860 }
861 
862 /** gets number of implicit integer branching candidates with maximal branch priority for pseudo solution branching */
864  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
865  )
866 {
867  assert(branchcand != NULL);
868 
869  return branchcand->npriopseudocands - branchcand->npriopseudobins - branchcand->npriopseudoints;
870 }
871 
872 /** insert pseudocand at given position, or to the first positions of the maximal priority candidates, using the
873  * given position as free slot for the other candidates
874  */
875 static
877  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
878  SCIP_VAR* var, /**< variable to insert */
879  int insertpos /**< free position to insert the variable */
880  )
881 {
882  SCIP_VARTYPE vartype;
883  int branchpriority;
884 
885  assert(branchcand != NULL);
886  assert(var != NULL);
887  assert(branchcand->npriopseudocands <= insertpos && insertpos < branchcand->npseudocands);
888  assert(branchcand->npseudocands <= branchcand->pseudocandssize);
889 
890  vartype = SCIPvarGetType(var);
891  branchpriority = SCIPvarGetBranchPriority(var);
892 
893  SCIPdebugMessage("inserting pseudo candidate <%s> of type %d and priority %d into candidate set at position %d (maxprio: %d)\n",
894  SCIPvarGetName(var), vartype, branchpriority, insertpos, branchcand->pseudomaxpriority);
895 
896  /* insert the variable into pseudocands, making sure, that the highest priority candidates are at the front
897  * and ordered binaries, integers, implicit integers
898  */
899  if( branchpriority > branchcand->pseudomaxpriority )
900  {
901  /* candidate has higher priority than the current maximum:
902  * move it to the front and declare it to be the single best candidate
903  */
904  if( insertpos != 0 )
905  {
906  branchcand->pseudocands[insertpos] = branchcand->pseudocands[0];
907  branchcand->pseudocands[insertpos]->pseudocandindex = insertpos;
908  insertpos = 0;
909  }
910  branchcand->npriopseudocands = 1;
911  branchcand->npriopseudobins = (vartype == SCIP_VARTYPE_BINARY ? 1 : 0);
912  branchcand->npriopseudoints = (vartype == SCIP_VARTYPE_INTEGER ? 1 : 0);
913  branchcand->pseudomaxpriority = branchpriority;
914  }
915  else if( branchpriority == branchcand->pseudomaxpriority )
916  {
917  /* candidate has equal priority as the current maximum:
918  * move away the first non-maximal priority candidate, move the current candidate to the correct
919  * slot (binaries first, integers next, implicit integers last) and increase the number of maximal priority candidates
920  */
921  if( insertpos != branchcand->npriopseudocands )
922  {
923  branchcand->pseudocands[insertpos] = branchcand->pseudocands[branchcand->npriopseudocands];
924  branchcand->pseudocands[insertpos]->pseudocandindex = insertpos;
925  insertpos = branchcand->npriopseudocands;
926  }
927  branchcand->npriopseudocands++;
928  if( vartype == SCIP_VARTYPE_BINARY || vartype == SCIP_VARTYPE_INTEGER )
929  {
930  if( insertpos != branchcand->npriopseudobins + branchcand->npriopseudoints )
931  {
932  branchcand->pseudocands[insertpos] =
933  branchcand->pseudocands[branchcand->npriopseudobins + branchcand->npriopseudoints];
934  branchcand->pseudocands[insertpos]->pseudocandindex = insertpos;
935  insertpos = branchcand->npriopseudobins + branchcand->npriopseudoints;
936  }
937  branchcand->npriopseudoints++;
938 
939  if( vartype == SCIP_VARTYPE_BINARY )
940  {
941  if( insertpos != branchcand->npriopseudobins )
942  {
943  branchcand->pseudocands[insertpos] = branchcand->pseudocands[branchcand->npriopseudobins];
944  branchcand->pseudocands[insertpos]->pseudocandindex = insertpos;
945  insertpos = branchcand->npriopseudobins;
946  }
947  branchcand->npriopseudobins++;
948  branchcand->npriopseudoints--;
949  }
950  }
951  }
952  branchcand->pseudocands[insertpos] = var;
953  var->pseudocandindex = insertpos;
954 
955  SCIPdebugMessage(" -> inserted at position %d (npriopseudocands=%d)\n", insertpos, branchcand->npriopseudocands);
956 
957  assert(0 <= branchcand->npriopseudocands && branchcand->npriopseudocands <= branchcand->npseudocands);
958  assert(0 <= branchcand->npriopseudobins && branchcand->npriopseudobins <= branchcand->npriopseudocands);
959  assert(0 <= branchcand->npriopseudoints && branchcand->npriopseudoints <= branchcand->npriopseudocands);
960 }
961 
962 /** sorts the pseudo branching candidates, such that the candidates of maximal priority are at the front,
963  * ordered by binaries, integers, implicit integers
964  */
965 static
967  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
968  )
969 {
970  SCIP_VAR* var;
971  int i;
972 
973  assert(branchcand != NULL);
974  assert(branchcand->npriopseudocands == 0); /* is only be called after removal of last maximal candidate */
975  assert(branchcand->npriopseudobins == 0);
976  assert(branchcand->npriopseudoints == 0);
977 
978  SCIPdebugMessage("resorting pseudo candidates\n");
979 
980  branchcand->pseudomaxpriority = INT_MIN;
981 
982  for( i = 0; i < branchcand->npseudocands; ++i )
983  {
984  var = branchcand->pseudocands[i];
985  assert(var->pseudocandindex == i);
986 
987  if( SCIPvarGetBranchPriority(var) >= branchcand->pseudomaxpriority )
988  branchcandInsertPseudoCand(branchcand, var, i);
989  }
990 
991  assert(0 <= branchcand->npriopseudocands && branchcand->npriopseudocands <= branchcand->npseudocands);
992  assert(0 <= branchcand->npriopseudobins && branchcand->npriopseudobins <= branchcand->npriopseudocands);
993  assert(0 <= branchcand->npriopseudoints && branchcand->npriopseudoints <= branchcand->npriopseudocands);
994 #ifndef NDEBUG
995  {
996  for (i = 0; i < branchcand->npriopseudocands; ++i)
997  assert( branchcand->pseudocands[i]->branchpriority == branchcand->pseudomaxpriority );
998  }
999 #endif
1000 }
1001 
1002 /** removes pseudo candidate from pseudocands array
1003  */
1004 static
1006  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1007  SCIP_VAR* var /**< variable to remove */
1008  )
1009 {
1010  int freepos;
1011 
1012  assert(branchcand != NULL);
1013  assert(var != NULL);
1014  assert(var->pseudocandindex < branchcand->npseudocands);
1015  assert(branchcand->pseudocands[var->pseudocandindex] == var);
1016  assert(branchcand->pseudocands[branchcand->npseudocands-1] != NULL);
1017 
1018  /* Note that the branching priority of the variable to be removed is not necessarily equal to pseudomaxpriority, since
1019  * the status of the variable might have changed, leading to a change in the branching priority. Moreover, if the
1020  * variable was part of an aggregation, even other variables might at this point have different priorities. */
1021  SCIPdebugMessage("removing pseudo candidate <%s> of type %d and priority %d at %d from candidate set (maxprio: %d)\n",
1023  branchcand->pseudomaxpriority);
1024 
1025  /* delete the variable from pseudocands, making sure, that the highest priority candidates are at the front
1026  * and ordered binaries, integers, implicit integers
1027  */
1028  freepos = var->pseudocandindex;
1029  var->pseudocandindex = -1;
1030  assert(0 <= freepos && freepos < branchcand->npseudocands);
1031 
1032  if( freepos < branchcand->npriopseudobins )
1033  {
1034  /* a binary candidate of maximal priority was removed */
1035  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
1036  if( freepos != branchcand->npriopseudobins - 1 )
1037  {
1038  branchcand->pseudocands[freepos] = branchcand->pseudocands[branchcand->npriopseudobins - 1];
1039  branchcand->pseudocands[freepos]->pseudocandindex = freepos;
1040  freepos = branchcand->npriopseudobins - 1;
1041  }
1042  branchcand->npriopseudobins--;
1043  branchcand->npriopseudoints++;
1044  }
1045 
1046  if( freepos < branchcand->npriopseudobins + branchcand->npriopseudoints )
1047  {
1048  /* a binary or integer candidate of maximal priority was removed */
1050  if( freepos != branchcand->npriopseudobins + branchcand->npriopseudoints - 1 )
1051  {
1052  branchcand->pseudocands[freepos] =
1053  branchcand->pseudocands[branchcand->npriopseudobins + branchcand->npriopseudoints - 1];
1054  branchcand->pseudocands[freepos]->pseudocandindex = freepos;
1055  freepos = branchcand->npriopseudobins + branchcand->npriopseudoints - 1;
1056  }
1057  branchcand->npriopseudoints--;
1058  }
1059 
1060  if( freepos < branchcand->npriopseudocands )
1061  {
1062  /* a candidate of maximal priority was removed */
1063  if( freepos != branchcand->npriopseudocands - 1 )
1064  {
1065  branchcand->pseudocands[freepos] = branchcand->pseudocands[branchcand->npriopseudocands - 1];
1066  branchcand->pseudocands[freepos]->pseudocandindex = freepos;
1067  freepos = branchcand->npriopseudocands - 1;
1068  }
1069  branchcand->npriopseudocands--;
1070  }
1071  if( freepos != branchcand->npseudocands - 1 )
1072  {
1073  branchcand->pseudocands[freepos] = branchcand->pseudocands[branchcand->npseudocands - 1];
1074  branchcand->pseudocands[freepos]->pseudocandindex = freepos;
1075  }
1076  branchcand->npseudocands--;
1077 
1078  assert(0 <= branchcand->npriopseudocands && branchcand->npriopseudocands <= branchcand->npseudocands);
1079  assert(0 <= branchcand->npriopseudobins && branchcand->npriopseudobins <= branchcand->npriopseudocands);
1080  assert(0 <= branchcand->npriopseudoints && branchcand->npriopseudoints <= branchcand->npriopseudocands);
1081 
1082  /* if all maximal priority candidates were removed, resort the array s.t. the new maximal priority candidates
1083  * are at the front
1084  */
1085  if( branchcand->npriopseudocands == 0 )
1086  branchcandSortPseudoCands(branchcand);
1087 }
1088 
1089 /** removes variable from branching candidate list */
1091  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1092  SCIP_VAR* var /**< variable that changed its bounds */
1093  )
1094 {
1095  assert(var != NULL);
1096 
1097  /* make sure, variable is not member of the pseudo branching candidate list */
1098  if( var->pseudocandindex >= 0 )
1099  {
1100  branchcandRemovePseudoCand(branchcand, var);
1101  }
1102 
1103  return SCIP_OKAY;
1104 }
1105 
1106 /** updates branching candidate list for a given variable */
1108  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1109  SCIP_SET* set, /**< global SCIP settings */
1110  SCIP_VAR* var /**< variable that changed its bounds */
1111  )
1112 {
1113  assert(branchcand != NULL);
1114  assert(var != NULL);
1115 
1118  && SCIPsetIsLT(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
1119  {
1120  /* variable is neither continuous nor fixed and has non-empty domain: make sure it is member of the pseudo branching candidate list */
1121  if( var->pseudocandindex == -1 )
1122  {
1123  SCIP_CALL( ensurePseudocandsSize(branchcand, set, branchcand->npseudocands+1) );
1124 
1125  branchcand->npseudocands++;
1126  branchcandInsertPseudoCand(branchcand, var, branchcand->npseudocands-1);
1127  }
1128  }
1129  else
1130  {
1137  || SCIPsetIsGE(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
1138 
1139  /* variable is continuous or fixed or has empty domain: make sure it is not member of the pseudo branching candidate list */
1140  SCIP_CALL( SCIPbranchcandRemoveVar(branchcand, var) );
1141  }
1142 
1143  return SCIP_OKAY;
1144 }
1145 
1146 /** updates branching priority of the given variable and update the pseude candidate array if needed */
1148  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1149  SCIP_SET* set, /**< global SCIP settings */
1150  SCIP_VAR* var, /**< variable that changed its bounds */
1151  int branchpriority /**< branch priority of the variable */
1152  )
1153 {
1154  int oldbranchpriority;
1155  int pseudomaxpriority;
1156 
1157  assert(branchcand != NULL);
1158 
1159  oldbranchpriority = SCIPvarGetBranchPriority(var);
1160 
1161  if( oldbranchpriority == branchpriority )
1162  return SCIP_OKAY;
1163 
1164  pseudomaxpriority = branchcand->pseudomaxpriority;
1165 
1166  /* if the variable currently belongs to the priority set or the new branching priority is larger than the current one,
1167  * remove it from the pseudo branch candidate array */
1168  if( oldbranchpriority == pseudomaxpriority || branchpriority > pseudomaxpriority )
1169  {
1170  SCIP_CALL( SCIPbranchcandRemoveVar(branchcand, var) );
1171  assert(var->pseudocandindex == -1);
1172  }
1173 
1174  /* change the branching priority of the variable */
1175  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
1176 
1177  /* if the variable is not part of the pseudo branching candidate array, check if it is a pseudo branching candidate
1178  * and add it if so */
1179  SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1180 
1181  return SCIP_OKAY;
1182 }
1183 
1184 
1185 
1186 /*
1187  * branching rule methods
1188  */
1189 
1190 /** compares two branching rules w. r. to their priority */
1191 SCIP_DECL_SORTPTRCOMP(SCIPbranchruleComp)
1192 { /*lint --e{715}*/
1193  return ((SCIP_BRANCHRULE*)elem2)->priority - ((SCIP_BRANCHRULE*)elem1)->priority;
1194 }
1195 
1196 /** comparison method for sorting branching rules w.r.t. to their name */
1197 SCIP_DECL_SORTPTRCOMP(SCIPbranchruleCompName)
1198 {
1200 }
1201 
1202 /** method to call, when the priority of a branching rule was changed */
1203 static
1204 SCIP_DECL_PARAMCHGD(paramChgdBranchrulePriority)
1205 { /*lint --e{715}*/
1206  SCIP_PARAMDATA* paramdata;
1207 
1208  paramdata = SCIPparamGetData(param);
1209  assert(paramdata != NULL);
1210 
1211  /* use SCIPsetBranchrulePriority() to mark the branchrules unsorted */
1212  SCIP_CALL( SCIPsetBranchrulePriority(scip, (SCIP_BRANCHRULE*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
1213 
1214  return SCIP_OKAY;
1215 }
1216 
1217 /** copies the given branchrule to a new scip */
1219  SCIP_BRANCHRULE* branchrule, /**< branchrule */
1220  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
1221  )
1222 {
1223  assert(branchrule != NULL);
1224  assert(set != NULL);
1225  assert(set->scip != NULL);
1226 
1227  if( branchrule->branchcopy != NULL )
1228  {
1229  SCIPsetDebugMsg(set, "including branching rule %s in subscip %p\n", SCIPbranchruleGetName(branchrule), (void*)set->scip);
1230  SCIP_CALL( branchrule->branchcopy(set->scip, branchrule) );
1231  }
1232 
1233  return SCIP_OKAY;
1234 }
1235 
1236 /** creates a branching rule */
1238  SCIP_BRANCHRULE** branchrule, /**< pointer to store branching rule */
1239  SCIP_SET* set, /**< global SCIP settings */
1240  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1241  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
1242  const char* name, /**< name of branching rule */
1243  const char* desc, /**< description of branching rule */
1244  int priority, /**< priority of the branching rule */
1245  int maxdepth, /**< maximal depth level, up to which this branching rule should be used (or -1) */
1246  SCIP_Real maxbounddist, /**< maximal relative distance from current node's dual bound to primal bound
1247  * compared to best node's dual bound for applying branching rule
1248  * (0.0: only on current best node, 1.0: on all nodes) */
1249  SCIP_DECL_BRANCHCOPY ((*branchcopy)), /**< copy method of branching rule */
1250  SCIP_DECL_BRANCHFREE ((*branchfree)), /**< destructor of branching rule */
1251  SCIP_DECL_BRANCHINIT ((*branchinit)), /**< initialize branching rule */
1252  SCIP_DECL_BRANCHEXIT ((*branchexit)), /**< deinitialize branching rule */
1253  SCIP_DECL_BRANCHINITSOL((*branchinitsol)),/**< solving process initialization method of branching rule */
1254  SCIP_DECL_BRANCHEXITSOL((*branchexitsol)),/**< solving process deinitialization method of branching rule */
1255  SCIP_DECL_BRANCHEXECLP((*branchexeclp)), /**< branching execution method for fractional LP solutions */
1256  SCIP_DECL_BRANCHEXECEXT((*branchexecext)),/**< branching execution method for external solutions */
1257  SCIP_DECL_BRANCHEXECPS((*branchexecps)), /**< branching execution method for not completely fixed pseudo solutions */
1258  SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
1259  )
1260 {
1261  char paramname[SCIP_MAXSTRLEN];
1262  char paramdesc[SCIP_MAXSTRLEN];
1263 
1264  assert(branchrule != NULL);
1265  assert(name != NULL);
1266  assert(desc != NULL);
1267 
1268  SCIP_ALLOC( BMSallocMemory(branchrule) );
1269  SCIP_ALLOC( BMSduplicateMemoryArray(&(*branchrule)->name, name, strlen(name)+1) );
1270  SCIP_ALLOC( BMSduplicateMemoryArray(&(*branchrule)->desc, desc, strlen(desc)+1) );
1271  (*branchrule)->priority = priority;
1272  (*branchrule)->maxdepth = maxdepth;
1273  (*branchrule)->maxbounddist = maxbounddist;
1274  (*branchrule)->branchcopy = branchcopy;
1275  (*branchrule)->branchfree = branchfree;
1276  (*branchrule)->branchinit = branchinit;
1277  (*branchrule)->branchexit = branchexit;
1278  (*branchrule)->branchinitsol = branchinitsol;
1279  (*branchrule)->branchexitsol = branchexitsol;
1280  (*branchrule)->branchexeclp = branchexeclp;
1281  (*branchrule)->branchexecext = branchexecext;
1282  (*branchrule)->branchexecps = branchexecps;
1283  (*branchrule)->branchruledata = branchruledata;
1284  SCIP_CALL( SCIPclockCreate(&(*branchrule)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
1285  SCIP_CALL( SCIPclockCreate(&(*branchrule)->branchclock, SCIP_CLOCKTYPE_DEFAULT) );
1286  (*branchrule)->nlpcalls = 0;
1287  (*branchrule)->nexterncalls = 0;
1288  (*branchrule)->npseudocalls = 0;
1289  (*branchrule)->ncutoffs = 0;
1290  (*branchrule)->ncutsfound = 0;
1291  (*branchrule)->nconssfound = 0;
1292  (*branchrule)->ndomredsfound = 0;
1293  (*branchrule)->nchildren = 0;
1294  (*branchrule)->initialized = FALSE;
1295 
1296  /* add parameters */
1297  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "branching/%s/priority", name);
1298  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of branching rule <%s>", name);
1299  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
1300  &(*branchrule)->priority, FALSE, priority, INT_MIN/4, INT_MAX/4,
1301  paramChgdBranchrulePriority, (SCIP_PARAMDATA*)(*branchrule)) ); /*lint !e740*/
1302  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "branching/%s/maxdepth", name);
1303  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "maximal depth level, up to which branching rule <%s> should be used (-1 for no limit)", name);
1304  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
1305  &(*branchrule)->maxdepth, FALSE, maxdepth, -1, SCIP_MAXTREEDEPTH,
1306  NULL, NULL) ); /*lint !e740*/
1307  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "branching/%s/maxbounddist", name);
1308  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for applying branching rule (0.0: only on current best node, 1.0: on all nodes)");
1309  SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname, paramdesc,
1310  &(*branchrule)->maxbounddist, FALSE, maxbounddist, 0.0, 1.0,
1311  NULL, NULL) ); /*lint !e740*/
1312 
1313  return SCIP_OKAY;
1314 }
1315 
1316 /** frees memory of branching rule */
1318  SCIP_BRANCHRULE** branchrule, /**< pointer to branching rule data structure */
1319  SCIP_SET* set /**< global SCIP settings */
1320  )
1321 {
1322  assert(branchrule != NULL);
1323  assert(*branchrule != NULL);
1324  assert(!(*branchrule)->initialized);
1325  assert(set != NULL);
1326 
1327  /* call destructor of branching rule */
1328  if( (*branchrule)->branchfree != NULL )
1329  {
1330  SCIP_CALL( (*branchrule)->branchfree(set->scip, *branchrule) );
1331  }
1332 
1333  SCIPclockFree(&(*branchrule)->branchclock);
1334  SCIPclockFree(&(*branchrule)->setuptime);
1335  BMSfreeMemoryArray(&(*branchrule)->name);
1336  BMSfreeMemoryArray(&(*branchrule)->desc);
1337  BMSfreeMemory(branchrule);
1338 
1339  return SCIP_OKAY;
1340 }
1341 
1342 /** initializes branching rule */
1344  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1345  SCIP_SET* set /**< global SCIP settings */
1346  )
1347 {
1348  assert(branchrule != NULL);
1349  assert(set != NULL);
1350 
1351  if( branchrule->initialized )
1352  {
1353  SCIPerrorMessage("branching rule <%s> already initialized\n", branchrule->name);
1354  return SCIP_INVALIDCALL;
1355  }
1356 
1357  if( set->misc_resetstat )
1358  {
1359  SCIPclockReset(branchrule->setuptime);
1360  SCIPclockReset(branchrule->branchclock);
1361  branchrule->nlpcalls = 0;
1362  branchrule->nexterncalls = 0;
1363  branchrule->npseudocalls = 0;
1364  branchrule->ncutoffs = 0;
1365  branchrule->ncutsfound = 0;
1366  branchrule->nconssfound = 0;
1367  branchrule->ndomredsfound = 0;
1368  branchrule->nchildren = 0;
1369  }
1370 
1371  if( branchrule->branchinit != NULL )
1372  {
1373  /* start timing */
1374  SCIPclockStart(branchrule->setuptime, set);
1375 
1376  SCIP_CALL( branchrule->branchinit(set->scip, branchrule) );
1377 
1378  /* stop timing */
1379  SCIPclockStop(branchrule->setuptime, set);
1380  }
1381  branchrule->initialized = TRUE;
1382 
1383  return SCIP_OKAY;
1384 }
1385 
1386 /** deinitializes branching rule */
1388  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1389  SCIP_SET* set /**< global SCIP settings */
1390  )
1391 {
1392  assert(branchrule != NULL);
1393  assert(set != NULL);
1394 
1395  if( !branchrule->initialized )
1396  {
1397  SCIPerrorMessage("branching rule <%s> not initialized\n", branchrule->name);
1398  return SCIP_INVALIDCALL;
1399  }
1400 
1401  if( branchrule->branchexit != NULL )
1402  {
1403  /* start timing */
1404  SCIPclockStart(branchrule->setuptime, set);
1405 
1406  SCIP_CALL( branchrule->branchexit(set->scip, branchrule) );
1407 
1408  /* stop timing */
1409  SCIPclockStop(branchrule->setuptime, set);
1410  }
1411  branchrule->initialized = FALSE;
1412 
1413  return SCIP_OKAY;
1414 }
1415 
1416 /** informs branching rule that the branch and bound process is being started */
1418  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1419  SCIP_SET* set /**< global SCIP settings */
1420  )
1421 {
1422  assert(branchrule != NULL);
1423  assert(set != NULL);
1424 
1425  /* call solving process initialization method of branching rule */
1426  if( branchrule->branchinitsol != NULL )
1427  {
1428  /* start timing */
1429  SCIPclockStart(branchrule->setuptime, set);
1430 
1431  SCIP_CALL( branchrule->branchinitsol(set->scip, branchrule) );
1432 
1433  /* stop timing */
1434  SCIPclockStop(branchrule->setuptime, set);
1435  }
1436 
1437  return SCIP_OKAY;
1438 }
1439 
1440 /** informs branching rule that the branch and bound process data is being freed */
1442  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1443  SCIP_SET* set /**< global SCIP settings */
1444  )
1445 {
1446  assert(branchrule != NULL);
1447  assert(set != NULL);
1448 
1449  /* call solving process deinitialization method of branching rule */
1450  if( branchrule->branchexitsol != NULL )
1451  {
1452  /* start timing */
1453  SCIPclockStart(branchrule->setuptime, set);
1454 
1455  SCIP_CALL( branchrule->branchexitsol(set->scip, branchrule) );
1456 
1457  /* stop timing */
1458  SCIPclockStop(branchrule->setuptime, set);
1459  }
1460 
1461  return SCIP_OKAY;
1462 }
1463 
1464 /** executes branching rule for fractional LP solution */
1466  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1467  SCIP_SET* set, /**< global SCIP settings */
1468  SCIP_STAT* stat, /**< problem statistics */
1469  SCIP_TREE* tree, /**< branch and bound tree */
1470  SCIP_SEPASTORE* sepastore, /**< separation storage */
1471  SCIP_Real cutoffbound, /**< global upper cutoff bound */
1472  SCIP_Bool allowaddcons, /**< should adding constraints be allowed to avoid a branching? */
1473  SCIP_RESULT* result /**< pointer to store the result of the callback method */
1474  )
1475 {
1476  assert(branchrule != NULL);
1477  assert(set != NULL);
1478  assert(tree != NULL);
1479  assert(tree->focusnode != NULL);
1480  assert(tree->nchildren == 0);
1481  assert(result != NULL);
1482 
1483  *result = SCIP_DIDNOTRUN;
1484  if( branchrule->branchexeclp != NULL
1485  && (branchrule->maxdepth == -1 || branchrule->maxdepth >= SCIPtreeGetCurrentDepth(tree)) )
1486  {
1487  SCIP_Real loclowerbound;
1488  SCIP_Real glblowerbound;
1489  SCIP_Bool runbranchrule;
1490 
1491  loclowerbound = SCIPnodeGetLowerbound(tree->focusnode);
1492  glblowerbound = SCIPtreeGetLowerbound(tree, set);
1493 
1494  /* we distinguish between finite and infinite global lower bounds to avoid comparisons between different values > SCIPinfinity() */
1495  if( SCIPsetIsInfinity(set, -glblowerbound) )
1496  runbranchrule = SCIPsetIsInfinity(set, -loclowerbound) || SCIPsetIsGE(set, branchrule->maxbounddist, 1.0);
1497  else
1498  {
1499  assert(!SCIPsetIsInfinity(set, -loclowerbound));
1500  runbranchrule = SCIPsetIsLE(set, loclowerbound - glblowerbound, branchrule->maxbounddist * (cutoffbound - glblowerbound));
1501  }
1502 
1503  if( runbranchrule )
1504  {
1505  SCIP_Longint oldndomchgs;
1506  SCIP_Longint oldnprobdomchgs;
1507  SCIP_Longint oldnactiveconss;
1508  int oldncuts;
1509 
1510  SCIPsetDebugMsg(set, "executing LP branching rule <%s>\n", branchrule->name);
1511 
1512  oldndomchgs = stat->nboundchgs + stat->nholechgs;
1513  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
1514  oldncuts = SCIPsepastoreGetNCuts(sepastore);
1515  oldnactiveconss = stat->nactiveconssadded;
1516 
1517  /* start timing */
1518  SCIPclockStart(branchrule->branchclock, set);
1519 
1520  /* call external method */
1521  SCIP_CALL( branchrule->branchexeclp(set->scip, branchrule, allowaddcons, result) );
1522 
1523  /* stop timing */
1524  SCIPclockStop(branchrule->branchclock, set);
1525 
1526  /* evaluate result */
1527  if( *result != SCIP_CUTOFF
1528  && *result != SCIP_CONSADDED
1529  && *result != SCIP_REDUCEDDOM
1530  && *result != SCIP_SEPARATED
1531  && *result != SCIP_BRANCHED
1532  && *result != SCIP_DIDNOTFIND
1533  && *result != SCIP_DIDNOTRUN )
1534  {
1535  SCIPerrorMessage("branching rule <%s> returned invalid result code <%d> from LP solution branching\n",
1536  branchrule->name, *result);
1537  return SCIP_INVALIDRESULT;
1538  }
1539  if( *result == SCIP_CONSADDED && !allowaddcons )
1540  {
1541  SCIPerrorMessage("branching rule <%s> added a constraint in LP solution branching without permission\n",
1542  branchrule->name);
1543  return SCIP_INVALIDRESULT;
1544  }
1545 
1546  /* update statistics */
1547  if( *result != SCIP_DIDNOTRUN )
1548  branchrule->nlpcalls++;
1549  if( *result == SCIP_CUTOFF )
1550  branchrule->ncutoffs++;
1551  if( *result != SCIP_BRANCHED )
1552  {
1553  assert(tree->nchildren == 0);
1554 
1555  /* update domain reductions; therefore remove the domain
1556  * reduction counts which were generated in probing mode */
1557  branchrule->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
1558  branchrule->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
1559 
1560  branchrule->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
1561  branchrule->nconssfound += stat->nactiveconssadded - oldnactiveconss; /*lint !e776*/
1562  }
1563  else
1564  branchrule->nchildren += tree->nchildren;
1565  }
1566  }
1567 
1568  return SCIP_OKAY;
1569 }
1570 
1571 /** executes branching rule for external branching candidates */
1573  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1574  SCIP_SET* set, /**< global SCIP settings */
1575  SCIP_STAT* stat, /**< problem statistics */
1576  SCIP_TREE* tree, /**< branch and bound tree */
1577  SCIP_SEPASTORE* sepastore, /**< separation storage */
1578  SCIP_Real cutoffbound, /**< global upper cutoff bound */
1579  SCIP_Bool allowaddcons, /**< should adding constraints be allowed to avoid a branching? */
1580  SCIP_RESULT* result /**< pointer to store the result of the callback method */
1581  )
1582 {
1583  assert(branchrule != NULL);
1584  assert(set != NULL);
1585  assert(tree != NULL);
1586  assert(tree->focusnode != NULL);
1587  assert(tree->nchildren == 0);
1588  assert(result != NULL);
1589 
1590  *result = SCIP_DIDNOTRUN;
1591  if( branchrule->branchexecext != NULL
1592  && (branchrule->maxdepth == -1 || branchrule->maxdepth >= SCIPtreeGetCurrentDepth(tree)) )
1593  {
1594  SCIP_Real loclowerbound;
1595  SCIP_Real glblowerbound;
1596  SCIP_Bool runbranchrule;
1597 
1598  loclowerbound = SCIPnodeGetLowerbound(tree->focusnode);
1599  glblowerbound = SCIPtreeGetLowerbound(tree, set);
1600  assert(!SCIPsetIsInfinity(set, loclowerbound));
1601 
1602  /* we distinguish between finite and infinite global lower bounds to avoid comparisons between different values > SCIPinfinity() */
1603  if( SCIPsetIsInfinity(set, -glblowerbound) )
1604  runbranchrule = SCIPsetIsInfinity(set, -loclowerbound) || SCIPsetIsGE(set, branchrule->maxbounddist, 1.0);
1605  else
1606  {
1607  assert(!SCIPsetIsInfinity(set, -loclowerbound));
1608  runbranchrule = SCIPsetIsLE(set, loclowerbound - glblowerbound, branchrule->maxbounddist * (cutoffbound - glblowerbound));
1609  }
1610 
1611  if( runbranchrule )
1612  {
1613  SCIP_Longint oldndomchgs;
1614  SCIP_Longint oldnprobdomchgs;
1615  int oldncuts;
1616  int oldnactiveconss;
1617 
1618  SCIPsetDebugMsg(set, "executing external solution branching rule <%s>\n", branchrule->name);
1619 
1620  oldndomchgs = stat->nboundchgs + stat->nholechgs;
1621  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
1622  oldncuts = SCIPsepastoreGetNCuts(sepastore);
1623  oldnactiveconss = stat->nactiveconss;
1624 
1625  /* start timing */
1626  SCIPclockStart(branchrule->branchclock, set);
1627 
1628  /* call external method */
1629  SCIP_CALL( branchrule->branchexecext(set->scip, branchrule, allowaddcons, result) );
1630 
1631  /* stop timing */
1632  SCIPclockStop(branchrule->branchclock, set);
1633 
1634  /* evaluate result */
1635  if( *result != SCIP_CUTOFF
1636  && *result != SCIP_CONSADDED
1637  && *result != SCIP_REDUCEDDOM
1638  && *result != SCIP_SEPARATED
1639  && *result != SCIP_BRANCHED
1640  && *result != SCIP_DIDNOTFIND
1641  && *result != SCIP_DIDNOTRUN )
1642  {
1643  SCIPerrorMessage("branching rule <%s> returned invalid result code <%d> from external solution branching\n",
1644  branchrule->name, *result);
1645  return SCIP_INVALIDRESULT;
1646  }
1647  if( *result == SCIP_CONSADDED && !allowaddcons )
1648  {
1649  SCIPerrorMessage("branching rule <%s> added a constraint in external solution branching without permission\n",
1650  branchrule->name);
1651  return SCIP_INVALIDRESULT;
1652  }
1653 
1654  /* update statistics */
1655  if( *result != SCIP_DIDNOTRUN )
1656  branchrule->nexterncalls++;
1657  if( *result == SCIP_CUTOFF )
1658  branchrule->ncutoffs++;
1659  if( *result != SCIP_BRANCHED )
1660  {
1661  assert(tree->nchildren == 0);
1662 
1663  /* update domain reductions; therefore remove the domain
1664  * reduction counts which were generated in probing mode */
1665  branchrule->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
1666  branchrule->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
1667 
1668  branchrule->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
1669  branchrule->nconssfound += stat->nactiveconss - oldnactiveconss; /*lint !e776*/
1670  }
1671  else
1672  branchrule->nchildren += tree->nchildren;
1673  }
1674  }
1675  return SCIP_OKAY;
1676 }
1677 
1678 /** executes branching rule for not completely fixed pseudo solution */
1680  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1681  SCIP_SET* set, /**< global SCIP settings */
1682  SCIP_STAT* stat, /**< problem statistics */
1683  SCIP_TREE* tree, /**< branch and bound tree */
1684  SCIP_Real cutoffbound, /**< global upper cutoff bound */
1685  SCIP_Bool allowaddcons, /**< should adding constraints be allowed to avoid a branching? */
1686  SCIP_RESULT* result /**< pointer to store the result of the callback method */
1687  )
1688 {
1689  assert(branchrule != NULL);
1690  assert(set != NULL);
1691  assert(tree != NULL);
1692  assert(tree->nchildren == 0);
1693  assert(result != NULL);
1694 
1695  *result = SCIP_DIDNOTRUN;
1696  if( branchrule->branchexecps != NULL
1697  && (branchrule->maxdepth == -1 || branchrule->maxdepth >= SCIPtreeGetCurrentDepth(tree)) )
1698  {
1699  SCIP_Real loclowerbound;
1700  SCIP_Real glblowerbound;
1701  SCIP_Bool runbranchrule;
1702 
1703  loclowerbound = SCIPnodeGetLowerbound(tree->focusnode);
1704  glblowerbound = SCIPtreeGetLowerbound(tree, set);
1705 
1706  /* we distinguish between finite and infinite global lower bounds to avoid comparisons between different values > SCIPinfinity() */
1707  if( SCIPsetIsInfinity(set, -glblowerbound) )
1708  runbranchrule = SCIPsetIsInfinity(set, -loclowerbound) || SCIPsetIsGE(set, branchrule->maxbounddist, 1.0);
1709  else
1710  {
1711  assert(!SCIPsetIsInfinity(set, -loclowerbound));
1712  runbranchrule = SCIPsetIsLE(set, loclowerbound - glblowerbound, branchrule->maxbounddist * (cutoffbound - glblowerbound));
1713  }
1714 
1715  if( runbranchrule )
1716  {
1717  SCIP_Longint oldndomchgs;
1718  SCIP_Longint oldnprobdomchgs;
1719  SCIP_Longint oldnactiveconss;
1720 
1721  SCIPsetDebugMsg(set, "executing pseudo branching rule <%s>\n", branchrule->name);
1722 
1723  oldndomchgs = stat->nboundchgs + stat->nholechgs;
1724  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
1725  oldnactiveconss = stat->nactiveconss;
1726 
1727  /* start timing */
1728  SCIPclockStart(branchrule->branchclock, set);
1729 
1730  /* call external method */
1731  SCIP_CALL( branchrule->branchexecps(set->scip, branchrule, allowaddcons, result) );
1732 
1733  /* stop timing */
1734  SCIPclockStop(branchrule->branchclock, set);
1735 
1736  /* evaluate result */
1737  if( *result != SCIP_CUTOFF
1738  && *result != SCIP_CONSADDED
1739  && *result != SCIP_REDUCEDDOM
1740  && *result != SCIP_BRANCHED
1741  && *result != SCIP_DIDNOTFIND
1742  && *result != SCIP_DIDNOTRUN )
1743  {
1744  SCIPerrorMessage("branching rule <%s> returned invalid result code <%d> from pseudo solution branching\n",
1745  branchrule->name, *result);
1746  return SCIP_INVALIDRESULT;
1747  }
1748  if( *result == SCIP_CONSADDED && !allowaddcons )
1749  {
1750  SCIPerrorMessage("branching rule <%s> added a constraint in pseudo solution branching without permission\n",
1751  branchrule->name);
1752  return SCIP_INVALIDRESULT;
1753  }
1754 
1755  /* update statistics */
1756  if( *result != SCIP_DIDNOTRUN )
1757  branchrule->npseudocalls++;
1758  if( *result == SCIP_CUTOFF )
1759  branchrule->ncutoffs++;
1760  if( *result != SCIP_BRANCHED )
1761  {
1762  assert(tree->nchildren == 0);
1763 
1764  /* update domain reductions; therefore remove the domain
1765  * reduction counts which were generated in probing mode */
1766  branchrule->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
1767  branchrule->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
1768 
1769  branchrule->nconssfound += stat->nactiveconss - oldnactiveconss;
1770  }
1771  else
1772  branchrule->nchildren += tree->nchildren;
1773  }
1774  }
1775 
1776  return SCIP_OKAY;
1777 }
1778 
1779 /** gets user data of branching rule */
1781  SCIP_BRANCHRULE* branchrule /**< branching rule */
1782  )
1783 {
1784  assert(branchrule != NULL);
1785 
1786  return branchrule->branchruledata;
1787 }
1788 
1789 /** sets user data of branching rule; user has to free old data in advance! */
1791  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1792  SCIP_BRANCHRULEDATA* branchruledata /**< new branching rule user data */
1793  )
1794 {
1795  assert(branchrule != NULL);
1796 
1797  branchrule->branchruledata = branchruledata;
1798 }
1799 
1800 /** sets copy method of branching rule */
1802  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1803  SCIP_DECL_BRANCHCOPY ((*branchcopy)) /**< copy method of branching rule or NULL if you don't want to copy your plugin into sub-SCIPs */
1804  )
1805 {
1806  assert(branchrule != NULL);
1807 
1808  branchrule->branchcopy = branchcopy;
1809 }
1810 
1811 /** sets destructor method of branching rule */
1813  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1814  SCIP_DECL_BRANCHFREE ((*branchfree)) /**< destructor of branching rule */
1815  )
1816 {
1817  assert(branchrule != NULL);
1818 
1819  branchrule->branchfree = branchfree;
1820 }
1821 
1822 /** sets initialization method of branching rule */
1824  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1825  SCIP_DECL_BRANCHINIT ((*branchinit)) /**< initialize branching rule */
1826  )
1827 {
1828  assert(branchrule != NULL);
1829 
1830  branchrule->branchinit = branchinit;
1831 }
1832 
1833 /** sets deinitialization method of branching rule */
1835  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1836  SCIP_DECL_BRANCHEXIT ((*branchexit)) /**< deinitialize branching rule */
1837  )
1838 {
1839  assert(branchrule != NULL);
1840 
1841  branchrule->branchexit = branchexit;
1842 }
1843 
1844 /** sets solving process initialization method of branching rule */
1846  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1847  SCIP_DECL_BRANCHINITSOL((*branchinitsol)) /**< solving process initialization method of branching rule */
1848  )
1849 {
1850  assert(branchrule != NULL);
1851 
1852  branchrule->branchinitsol = branchinitsol;
1853 }
1854 
1855 /** sets solving process deinitialization method of branching rule */
1857  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1858  SCIP_DECL_BRANCHEXITSOL((*branchexitsol)) /**< solving process deinitialization method of branching rule */
1859  )
1860 {
1861  assert(branchrule != NULL);
1862 
1863  branchrule->branchexitsol = branchexitsol;
1864 }
1865 
1866 
1867 
1868 /** sets branching execution method for fractional LP solutions */
1870  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1871  SCIP_DECL_BRANCHEXECLP((*branchexeclp)) /**< branching execution method for fractional LP solutions */
1872  )
1873 {
1874  assert(branchrule != NULL);
1875 
1876  branchrule->branchexeclp = branchexeclp;
1877 }
1878 
1879 /** sets branching execution method for external candidates */
1881  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1882  SCIP_DECL_BRANCHEXECEXT((*branchexecext)) /**< branching execution method for external candidates */
1883  )
1884 {
1885  assert(branchrule != NULL);
1886 
1887  branchrule->branchexecext = branchexecext;
1888 }
1889 
1890 /** sets branching execution method for not completely fixed pseudo solutions */
1892  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1893  SCIP_DECL_BRANCHEXECPS((*branchexecps)) /**< branching execution method for not completely fixed pseudo solutions */
1894  )
1895 {
1896  assert(branchrule != NULL);
1897 
1898  branchrule->branchexecps = branchexecps;
1899 }
1900 
1901 /** gets name of branching rule */
1903  SCIP_BRANCHRULE* branchrule /**< branching rule */
1904  )
1905 {
1906  assert(branchrule != NULL);
1907 
1908  return branchrule->name;
1909 }
1910 
1911 /** gets description of branching rule */
1913  SCIP_BRANCHRULE* branchrule /**< branching rule */
1914  )
1915 {
1916  assert(branchrule != NULL);
1917 
1918  return branchrule->desc;
1919 }
1920 
1921 /** gets priority of branching rule */
1923  SCIP_BRANCHRULE* branchrule /**< branching rule */
1924  )
1925 {
1926  assert(branchrule != NULL);
1927 
1928  return branchrule->priority;
1929 }
1930 
1931 /** sets priority of branching rule */
1933  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1934  SCIP_SET* set, /**< global SCIP settings */
1935  int priority /**< new priority of the branching rule */
1936  )
1937 {
1938  assert(branchrule != NULL);
1939  assert(set != NULL);
1940 
1941  branchrule->priority = priority;
1942  set->branchrulessorted = FALSE;
1943 }
1944 
1945 /** gets maximal depth level, up to which this branching rule should be used (-1 for no limit) */
1947  SCIP_BRANCHRULE* branchrule /**< branching rule */
1948  )
1949 {
1950  assert(branchrule != NULL);
1951 
1952  return branchrule->maxdepth;
1953 }
1954 
1955 /** sets maximal depth level, up to which this branching rule should be used (-1 for no limit) */
1957  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1958  int maxdepth /**< new maxdepth of the branching rule */
1959  )
1960 {
1961  assert(branchrule != NULL);
1962  assert(maxdepth >= -1);
1963 
1964  branchrule->maxdepth = maxdepth;
1965 }
1966 
1967 /** gets maximal relative distance from current node's dual bound to primal bound for applying branching rule */
1969  SCIP_BRANCHRULE* branchrule /**< branching rule */
1970  )
1971 {
1972  assert(branchrule != NULL);
1973 
1974  return branchrule->maxbounddist;
1975 }
1976 
1977 /** sets maximal relative distance from current node's dual bound to primal bound for applying branching rule */
1979  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1980  SCIP_Real maxbounddist /**< new maxbounddist of the branching rule */
1981  )
1982 {
1983  assert(branchrule != NULL);
1984  assert(maxbounddist >= -1);
1985 
1986  branchrule->maxbounddist = maxbounddist;
1987 }
1988 
1989 /** enables or disables all clocks of \p branchrule, depending on the value of the flag */
1991  SCIP_BRANCHRULE* branchrule, /**< the branching rule for which all clocks should be enabled or disabled */
1992  SCIP_Bool enable /**< should the clocks of the branching rule be enabled? */
1993  )
1994 {
1995  assert(branchrule != NULL);
1996 
1997  SCIPclockEnableOrDisable(branchrule->setuptime, enable);
1998  SCIPclockEnableOrDisable(branchrule->branchclock, enable);
1999 }
2000 
2001 /** gets time in seconds used in this branching rule for setting up for next stages */
2003  SCIP_BRANCHRULE* branchrule /**< branching rule */
2004  )
2005 {
2006  assert(branchrule != NULL);
2007 
2008  return SCIPclockGetTime(branchrule->setuptime);
2009 }
2010 
2011 /** gets time in seconds used in this branching rule */
2013  SCIP_BRANCHRULE* branchrule /**< branching rule */
2014  )
2015 {
2016  assert(branchrule != NULL);
2017 
2018  return SCIPclockGetTime(branchrule->branchclock);
2019 }
2020 
2021 /** gets the total number of times, the branching rule was called on an LP solution */
2023  SCIP_BRANCHRULE* branchrule /**< branching rule */
2024  )
2025 {
2026  assert(branchrule != NULL);
2027 
2028  return branchrule->nlpcalls;
2029 }
2030 
2031 /** gets the total number of times, the branching rule was called on an external solution */
2033  SCIP_BRANCHRULE* branchrule /**< branching rule */
2034  )
2035 {
2036  assert(branchrule != NULL);
2037 
2038  return branchrule->nexterncalls;
2039 }
2040 
2041 /** gets the total number of times, the branching rule was called on a pseudo solution */
2043  SCIP_BRANCHRULE* branchrule /**< branching rule */
2044  )
2045 {
2046  assert(branchrule != NULL);
2047 
2048  return branchrule->npseudocalls;
2049 }
2050 
2051 /** gets the total number of times, the branching rule detected a cutoff */
2053  SCIP_BRANCHRULE* branchrule /**< branching rule */
2054  )
2055 {
2056  assert(branchrule != NULL);
2057 
2058  return branchrule->ncutoffs;
2059 }
2060 
2061 /** gets the total number of cuts, the branching rule separated */
2063  SCIP_BRANCHRULE* branchrule /**< branching rule */
2064  )
2065 {
2066  assert(branchrule != NULL);
2067 
2068  return branchrule->ncutsfound;
2069 }
2070 
2071 /** gets the total number of constraints, the branching rule added to the respective local nodes (not counting constraints
2072  * that were added to the child nodes as branching decisions)
2073  */
2075  SCIP_BRANCHRULE* branchrule /**< branching rule */
2076  )
2077 {
2078  assert(branchrule != NULL);
2079 
2080  return branchrule->nconssfound;
2081 }
2082 
2083 /** gets the total number of domain reductions, the branching rule found */
2085  SCIP_BRANCHRULE* branchrule /**< branching rule */
2086  )
2087 {
2088  assert(branchrule != NULL);
2089 
2090  return branchrule->ndomredsfound;
2091 }
2092 
2093 /** gets the total number of children, the branching rule created */
2095  SCIP_BRANCHRULE* branchrule /**< branching rule */
2096  )
2097 {
2098  assert(branchrule != NULL);
2099 
2100  return branchrule->nchildren;
2101 }
2102 
2103 /** is branching rule initialized? */
2105  SCIP_BRANCHRULE* branchrule /**< branching rule */
2106  )
2107 {
2108  assert(branchrule != NULL);
2109 
2110  return branchrule->initialized;
2111 }
2112 
2113 
2114 
2115 
2116 /*
2117  * branching methods
2118  */
2119 
2120 /** calculates the branching score out of the gain predictions for a binary branching */
2122  SCIP_SET* set, /**< global SCIP settings */
2123  SCIP_VAR* var, /**< variable, of which the branching factor should be applied, or NULL */
2124  SCIP_Real downgain, /**< prediction of objective gain for rounding downwards */
2125  SCIP_Real upgain /**< prediction of objective gain for rounding upwards */
2126  )
2127 {
2128  SCIP_Real score;
2129  SCIP_Real eps;
2130 
2131  assert(set != NULL);
2132 
2133  /* adjust scores near zero to always yield product score greater than 0 */
2134  eps = SCIPsetSumepsilon(set);
2135  if( set->branch_sumadjustscore )
2136  {
2137  /* adjust scores by adding eps to keep near zero score differences between variables */
2138  downgain = downgain + eps;
2139  upgain = upgain + eps;
2140  }
2141  else
2142  {
2143  /* disregard near zero score differences between variables and consider the branching factor for them */
2144  downgain = MAX(downgain, eps);
2145  upgain = MAX(upgain, eps);
2146  }
2147 
2148  switch( set->branch_scorefunc )
2149  {
2150  case 's': /* linear sum score function */
2151  /* weigh the two child nodes with branchscorefac and 1-branchscorefac */
2152  if( downgain > upgain )
2153  score = set->branch_scorefac * downgain + (1.0-set->branch_scorefac) * upgain;
2154  else
2155  score = set->branch_scorefac * upgain + (1.0-set->branch_scorefac) * downgain;
2156  break;
2157 
2158  case 'p': /* product score function */
2159  score = downgain * upgain;
2160  break;
2161  case 'q': /* quotient score function */
2162  if( downgain > upgain )
2163  score = upgain * upgain / downgain;
2164  else
2165  score = downgain * downgain / upgain;
2166  break;
2167  default:
2168  SCIPerrorMessage("invalid branching score function <%c>\n", set->branch_scorefunc);
2169  SCIPABORT();
2170  score = 0.0;
2171  }
2172 
2173  /* apply the branch factor of the variable */
2174  if( var != NULL )
2175  score *= SCIPvarGetBranchFactor(var);
2176 
2177  return score;
2178 }
2179 
2180 /** calculates the branching score out of the gain predictions for a branching with arbitrary many children */
2182  SCIP_SET* set, /**< global SCIP settings */
2183  SCIP_VAR* var, /**< variable, of which the branching factor should be applied, or NULL */
2184  int nchildren, /**< number of children that the branching will create */
2185  SCIP_Real* gains /**< prediction of objective gain for each child */
2186  )
2187 {
2188  SCIP_Real min1;
2189  SCIP_Real min2;
2190  int c;
2191 
2192  assert(nchildren == 0 || gains != NULL);
2193 
2194  /* search for the two minimal gains in the child list and use these to calculate the branching score */
2195  min1 = SCIPsetInfinity(set);
2196  min2 = SCIPsetInfinity(set);
2197  for( c = 0; c < nchildren; ++c )
2198  {
2199  if( gains[c] < min1 )
2200  {
2201  min2 = min1;
2202  min1 = gains[c];
2203  }
2204  else if( gains[c] < min2 )
2205  min2 = gains[c];
2206  }
2207 
2208  return SCIPbranchGetScore(set, var, min1, min2);
2209 }
2210 
2211 /** computes a branching point for a (not necessarily discrete) variable
2212  * a suggested branching point is first projected onto the box
2213  * if no point is suggested, then the value in the current LP or pseudo solution is used
2214  * if this value is at infinity, then 0.0 projected onto the bounds and then moved inside the interval is used
2215  * for a discrete variable, it is ensured that the returned value is fractional
2216  * for a continuous variable, the parameter branching/clamp defines how far a branching point need to be from the bounds of a variable
2217  * the latter is only applied if no point has been suggested, or the suggested point is not inside the variable's interval
2218  */
2220  SCIP_SET* set, /**< global SCIP settings */
2221  SCIP_TREE* tree, /**< branch and bound tree */
2222  SCIP_VAR* var, /**< variable, of which the branching point should be computed */
2223  SCIP_Real suggestion /**< suggestion for branching point, or SCIP_INVALID if no suggestion */
2224  )
2225 {
2226  SCIP_Real branchpoint;
2227  SCIP_Real lb;
2228  SCIP_Real ub;
2229 
2230  assert(set != NULL);
2231  assert(var != NULL);
2232 
2233  lb = SCIPvarGetLbLocal(var);
2234  ub = SCIPvarGetUbLocal(var);
2235 
2236  /* for a fixed variable, we cannot branch further */
2237  assert(!SCIPsetIsEQ(set, lb, ub));
2238 
2239  if( !SCIPsetIsInfinity(set, REALABS(suggestion)) )
2240  {
2241  /* use user suggested branching point */
2242 
2243  /* first, project it onto the current domain */
2244  branchpoint = MAX(lb, MIN(suggestion, ub));
2245 
2247  {
2248  /* if it is a discrete variable, then round it down and up and accept this choice */
2249  if( SCIPsetIsEQ(set, branchpoint, ub) )
2250  {
2251  /* in the right branch, variable is fixed to its current upper bound */
2252  return SCIPsetFloor(set, branchpoint) - 0.5;
2253  }
2254  else
2255  {
2256  /* in the left branch, variable is fixed to its current lower bound */
2257  return SCIPsetFloor(set, branchpoint) + 0.5;
2258  }
2259  }
2260  else if( (SCIPsetIsInfinity(set, -lb) || SCIPsetIsRelGT(set, branchpoint, lb)) &&
2261  (SCIPsetIsInfinity(set, ub) || SCIPsetIsRelLT(set, branchpoint, ub)) )
2262  {
2263  /* if it is continuous and inside the box, then accept it */
2264  return branchpoint;
2265  }
2266  /* if it is continuous and suggestion is on of the bounds, continue below */
2267  }
2268  else
2269  {
2270  /* if no point is suggested and the value in LP solution is not too big, try the LP or pseudo LP solution
2271  * otherwise, if the value in the LP or pseudosolution is large (here 1e+12), use 0.0
2272  * in both cases, project onto bounds of course
2273  */
2274  branchpoint = SCIPvarGetSol(var, SCIPtreeHasCurrentNodeLP(tree));
2275  if( REALABS(branchpoint) > 1e+12 )
2276  branchpoint = 0.0;
2277  branchpoint = MAX(lb, MIN(branchpoint, ub));
2278  }
2279 
2280  /* if value is at +/- infty, then choose some value a bit off from bounds or 0.0 */
2281  if( SCIPsetIsInfinity(set, branchpoint) )
2282  {
2283  /* if value is at +infty, then the upper bound should be at infinity */
2284  assert(SCIPsetIsInfinity(set, ub));
2285 
2286  /* choose 0.0 or something above lower bound if lower bound > 0 */
2287  if( SCIPsetIsPositive(set, lb) )
2288  branchpoint = lb + 1000.0;
2289  else
2290  branchpoint = 0.0;
2291  }
2292  else if( SCIPsetIsInfinity(set, -branchpoint) )
2293  {
2294  /* if value is at -infty, then the lower bound should be at -infinity */
2295  assert(SCIPsetIsInfinity(set, -lb));
2296 
2297  /* choose 0.0 or something below upper bound if upper bound < 0 */
2298  if( SCIPsetIsNegative(set, ub) )
2299  branchpoint = ub - 1000.0;
2300  else
2301  branchpoint = 0.0;
2302  }
2303 
2304  assert(SCIPsetIsInfinity(set, ub) || SCIPsetIsLE(set, branchpoint, ub));
2305  assert(SCIPsetIsInfinity(set, -lb) || SCIPsetIsGE(set, branchpoint, lb));
2306 
2307  if( SCIPvarGetType(var) >= SCIP_VARTYPE_IMPLINT )
2308  {
2309  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2310  {
2311  /* if one bound is missing, we are temporarily guessing the other one, so we can apply the clamp below */
2312  if( SCIPsetIsInfinity(set, ub) )
2313  {
2314  ub = lb + MIN(MAX(0.5 * REALABS(lb), 1000), 0.9 * (SCIPsetInfinity(set) - lb)); /*lint !e666*/
2315  }
2316  else if( SCIPsetIsInfinity(set, -lb) )
2317  {
2318  lb = ub - MIN(MAX(0.5 * REALABS(ub), 1000), 0.9 * (SCIPsetInfinity(set) + ub)); /*lint !e666*/
2319  }
2320 
2321  /* if branching point is too close to the bounds, move more into the middle of the interval */
2322  if( SCIPrelDiff(ub, lb) <= 2.02 * SCIPsetEpsilon(set) )
2323  {
2324  /* for very tiny intervals we set it exactly into the middle */
2325  branchpoint = (lb+ub)/2.0;
2326  }
2327  else
2328  {
2329  /* otherwise we project it away from the bounds */
2330  SCIP_Real minbrpoint;
2331  SCIP_Real maxbrpoint;
2332  SCIP_Real scale;
2333  SCIP_Real lbabs;
2334  SCIP_Real ubabs;
2335 
2336  lbabs = REALABS(lb);
2337  ubabs = REALABS(ub);
2338 
2339  scale = MAX3(lbabs, ubabs, 1.0);
2340 
2341  /* the minimal branching point should be
2342  * - set->clamp away from the lower bound - relative to the local domain size
2343  * - SCIPsetEpsilon(set)*scale above the lower bound - in absolute value
2344  */
2345  minbrpoint = (1.0 - set->branch_clamp) * lb + set->branch_clamp * ub;
2346  minbrpoint = MAX(lb + 1.01*SCIPsetEpsilon(set)*scale, minbrpoint); /*lint !e666*/
2347 
2348  /* the maximal branching point should be
2349  * - set->clamp away from the upper bound - relative to the local domain size
2350  * - SCIPsetEpsilon(set)*scale below the upper bound - in absolute value
2351  */
2352  maxbrpoint = set->branch_clamp * lb + (1.0 - set->branch_clamp) * ub;
2353  maxbrpoint = MIN(ub - 1.01*SCIPsetEpsilon(set)*scale, maxbrpoint); /*lint !e666*/
2354 
2355  /* project branchpoint into [minbrpoint, maxbrpoint] */
2356  branchpoint = MAX(minbrpoint, MIN(branchpoint, maxbrpoint));
2357 
2358  /* if selected branching point is close to 0.0 and bounds are away from 0.0, it often makes sense to branch exactly on 0.0 */
2359  if( SCIPsetIsFeasZero(set, branchpoint) && SCIPsetIsFeasNegative(set, lb) && SCIPsetIsFeasPositive(set, ub) )
2360  branchpoint = 0.0;
2361 
2362  assert(SCIPsetIsRelLT(set, SCIPvarGetLbLocal(var), branchpoint));
2363  assert(SCIPsetIsRelLT(set, branchpoint, SCIPvarGetUbLocal(var)));
2364  }
2365  }
2366 
2367  /* ensure fractional branching point for implicit integer variables */
2368  if( SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT && SCIPsetIsIntegral(set, branchpoint) )
2369  {
2370  /* if branchpoint is integral but not on bounds, then it should be one of the value {lb+1, ..., ub-1} */
2371  assert(SCIPsetIsGE(set, SCIPsetRound(set, branchpoint), lb + 1.0));
2372  assert(SCIPsetIsLE(set, SCIPsetRound(set, branchpoint), ub - 1.0));
2373  /* if branchpoint is integral, create one branch with x <= x'-1 and one with x >= x'
2374  * @todo could in the same way be x <= x' and x >= x'+1; is there some easy way to know which is better?
2375  */
2376  return branchpoint - 0.5;
2377  }
2378 
2379  return branchpoint;
2380  }
2381  else
2382  {
2383  /* discrete variables */
2384  if( branchpoint <= lb + 0.5 )
2385  {
2386  /* if branchpoint is on lower bound, create one branch with x = lb and one with x >= lb+1 */
2387  return lb + 0.5;
2388  }
2389  else if( branchpoint >= ub - 0.5 )
2390  {
2391  /* if branchpoint is on upper bound, create one branch with x = ub and one with x <= ub-1 */
2392  return ub - 0.5;
2393  }
2394  else if( SCIPsetIsIntegral(set, branchpoint) )
2395  {
2396  /* if branchpoint is integral but not on bounds, then it should be one of the value {lb+1, ..., ub-1} */
2397  assert(SCIPsetIsGE(set, SCIPsetRound(set, branchpoint), lb + 1.0));
2398  assert(SCIPsetIsLE(set, SCIPsetRound(set, branchpoint), ub - 1.0));
2399  /* if branchpoint is integral, create one branch with x <= x'-1 and one with x >= x'
2400  * @todo could in the same way be x <= x' and x >= x'+1; is there some easy way to know which is better? */
2401  return branchpoint - 0.5;
2402  }
2403  else
2404  {
2405  /* branchpoint is somewhere between bounds and fractional, so just round down and up */
2406  return branchpoint;
2407  }
2408  }
2409 }
2410 
2411 /** calls branching rules to branch on an LP solution; if no fractional variables exist, the result is SCIP_DIDNOTRUN;
2412  * if the branch priority of an unfixed variable is larger than the maximal branch priority of the fractional
2413  * variables, pseudo solution branching is applied on the unfixed variables with maximal branch priority
2414  */
2416  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
2417  SCIP_SET* set, /**< global SCIP settings */
2418  SCIP_STAT* stat, /**< problem statistics */
2419  SCIP_PROB* transprob, /**< transformed problem after presolve */
2420  SCIP_PROB* origprob, /**< original problem */
2421  SCIP_TREE* tree, /**< branch and bound tree */
2422  SCIP_REOPT* reopt, /**< reoptimization data structure */
2423  SCIP_LP* lp, /**< current LP data */
2424  SCIP_SEPASTORE* sepastore, /**< separation storage */
2425  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2426  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2427  SCIP_Real cutoffbound, /**< global upper cutoff bound */
2428  SCIP_Bool allowaddcons, /**< should adding constraints be allowed to avoid a branching? */
2429  SCIP_RESULT* result /**< pointer to store the result of the branching (s. branch.h) */
2430  )
2431 {
2432  int i;
2433  int nalllpcands; /* sum of binary, integer, and implicit branching candidates */
2434 
2435  assert(branchcand != NULL);
2436  assert(result != NULL);
2437 
2438  *result = SCIP_DIDNOTRUN;
2439 
2440  /* calculate branching candidates */
2441  SCIP_CALL( branchcandCalcLPCands(branchcand, set, stat, lp) );
2442  assert(0 <= branchcand->npriolpcands && branchcand->npriolpcands <= branchcand->nlpcands);
2443  assert((branchcand->npriolpcands == 0) == (branchcand->nlpcands == 0));
2444 
2445  SCIPsetDebugMsg(set, "branching on LP solution with %d (+%d) fractional (+implicit fractional) variables (%d of maximal priority)\n",
2446  branchcand->nlpcands, branchcand->nimpllpfracs, branchcand->npriolpcands);
2447 
2448  nalllpcands = branchcand->nlpcands + branchcand->nimpllpfracs;
2449  /* do nothing, if no fractional variables exist */
2450  if( nalllpcands == 0 )
2451  return SCIP_OKAY;
2452 
2453  /* if there is a non-fixed variable with higher priority than the maximal priority of the fractional candidates,
2454  * use pseudo solution branching instead
2455  */
2456  if( branchcand->pseudomaxpriority > branchcand->lpmaxpriority )
2457  {
2458  SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cutoffbound,
2459  allowaddcons, result) );
2460  assert(*result != SCIP_DIDNOTRUN && *result != SCIP_DIDNOTFIND);
2461  return SCIP_OKAY;
2462  }
2463 
2464  /* sort the branching rules by priority */
2466 
2467  /* try all branching rules until one succeeded to branch */
2468  for( i = 0; i < set->nbranchrules && (*result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND) && !SCIPsolveIsStopped(set, stat, FALSE); ++i )
2469  {
2470  SCIP_CALL( SCIPbranchruleExecLPSol(set->branchrules[i], set, stat, tree, sepastore, cutoffbound, allowaddcons, result) );
2471  }
2472 
2473  if( *result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND )
2474  {
2475  SCIP_VAR* var;
2476  SCIP_Real factor;
2477  SCIP_Real bestfactor;
2478  int priority;
2479  int bestpriority;
2480  int bestcand;
2481 
2482  /* no branching method succeeded in choosing a branching: just branch on the first fractional variable with maximal
2483  * priority, and out of these on the one with maximal branch factor
2484  */
2485  bestcand = -1;
2486  bestpriority = INT_MIN;
2487  bestfactor = SCIP_REAL_MIN;
2488  for( i = 0; i < nalllpcands; ++i )
2489  {
2490  priority = SCIPvarGetBranchPriority(branchcand->lpcands[i]);
2491  factor = SCIPvarGetBranchFactor(branchcand->lpcands[i]);
2492  if( priority > bestpriority || (priority == bestpriority && factor > bestfactor) )
2493  {
2494  bestcand = i;
2495  bestpriority = priority;
2496  bestfactor = factor;
2497  }
2498  }
2499  assert(0 <= bestcand && bestcand < nalllpcands);
2500 
2501  var = branchcand->lpcands[bestcand];
2502  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
2503  assert(branchcand->nlpcands == 0 || SCIPvarGetType(var) != SCIP_VARTYPE_IMPLINT);
2504 
2505  assert(!SCIPsetIsEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
2506 
2507  SCIP_CALL( SCIPtreeBranchVar(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, SCIP_INVALID,
2508  NULL, NULL, NULL) );
2509 
2510  *result = SCIP_BRANCHED;
2511  }
2512 
2513  return SCIP_OKAY;
2514 }
2515 
2516 /** calls branching rules to branch on an external solution; if no external branching candidates exist, the result is SCIP_DIDNOTRUN */
2518  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
2519  SCIP_SET* set, /**< global SCIP settings */
2520  SCIP_STAT* stat, /**< problem statistics */
2521  SCIP_PROB* transprob, /**< transformed problem after presolve */
2522  SCIP_PROB* origprob, /**< original problem */
2523  SCIP_TREE* tree, /**< branch and bound tree */
2524  SCIP_REOPT* reopt, /**< reoptimization data structure */
2525  SCIP_LP* lp, /**< current LP data */
2526  SCIP_SEPASTORE* sepastore, /**< separation storage */
2527  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2528  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2529  SCIP_Real cutoffbound, /**< global upper cutoff bound */
2530  SCIP_Bool allowaddcons, /**< should adding constraints be allowed to avoid a branching? */
2531  SCIP_RESULT* result /**< pointer to store the result of the branching (s. branch.h) */
2532  )
2533 {
2534  int i;
2535 
2536  assert(branchcand != NULL);
2537  assert(result != NULL);
2538  assert(0 <= branchcand->nprioexterncands && branchcand->nprioexterncands <= branchcand->nexterncands);
2539  assert((branchcand->nprioexterncands == 0) == (branchcand->nexterncands == 0));
2540 
2541  *result = SCIP_DIDNOTRUN;
2542 
2543  SCIPsetDebugMsg(set, "branching on external solution with %d branching candidates (%d of maximal priority)\n",
2544  branchcand->nexterncands, branchcand->nprioexterncands);
2545 
2546  /* do nothing, if no external candidates exist */
2547  if( branchcand->nexterncands == 0 )
2548  return SCIP_OKAY;
2549 
2550  /* if there is a non-fixed variable with higher priority than the maximal priority of the external candidates,
2551  * use pseudo solution branching instead
2552  */
2553  if( branchcand->pseudomaxpriority > branchcand->externmaxpriority )
2554  {
2555  /* @todo: adjust this, that also LP branching might be called, if lpmaxpriority != externmaxpriority.
2556  * Therefor, it has to be clear which of both has the higher priority
2557  */
2558  SCIP_CALL( SCIPbranchExecPseudo(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue, cutoffbound,
2559  allowaddcons, result) );
2560  assert(*result != SCIP_DIDNOTRUN && *result != SCIP_DIDNOTFIND);
2561  return SCIP_OKAY;
2562  }
2563 
2564  /* sort the branching rules by priority */
2566 
2567  /* try all branching rules until one succeeded to branch */
2568  for( i = 0; i < set->nbranchrules && (*result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND); ++i )
2569  {
2570  SCIP_CALL( SCIPbranchruleExecExternSol(set->branchrules[i], set, stat, tree, sepastore, cutoffbound, allowaddcons, result) );
2571  }
2572 
2573  if( *result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND )
2574  {
2575  SCIP_VAR* var;
2576  SCIP_Real val;
2577  SCIP_Real bestfactor;
2578  SCIP_Real bestdomain;
2579  int bestpriority;
2580  int bestcand;
2581 
2582  /* if all branching rules did nothing, then they should also not have cleared all branching candidates */
2583  assert(branchcand->nexterncands > 0);
2584 
2585  /* no branching method succeeded in choosing a branching: just branch on the first branching candidates with maximal
2586  * priority, and out of these on the one with maximal branch factor, and out of these on the one with largest domain
2587  */
2588  bestcand = -1;
2589  bestpriority = INT_MIN;
2590  bestfactor = SCIP_REAL_MIN;
2591  bestdomain = 0.0;
2592  for( i = 0; i < branchcand->nexterncands; ++i )
2593  {
2594  SCIP_VAR* cand;
2595  SCIP_Real domain;
2596  SCIP_Real factor;
2597  int priority;
2598 
2599  cand = branchcand->externcands[i];
2600  priority = SCIPvarGetBranchPriority(cand);
2601  factor = SCIPvarGetBranchFactor(cand);
2602 
2603  /* the domain size is infinite, iff one of the bounds is infinite */
2605  domain = SCIPsetInfinity(set);
2606  else
2607  domain = SCIPvarGetUbLocal(cand) - SCIPvarGetLbLocal(cand);
2608 
2609  /* choose variable with higher priority, higher factor, larger domain (in that order) */
2610  if( priority > bestpriority || (priority == bestpriority && factor > bestfactor) || (priority == bestpriority && factor == bestfactor && domain > bestdomain) ) /*lint !e777*/
2611  {
2612  bestcand = i;
2613  bestpriority = priority;
2614  bestfactor = factor;
2615  bestdomain = domain;
2616  }
2617  }
2618  assert(0 <= bestcand && bestcand < branchcand->nexterncands);
2619 
2620  var = branchcand->externcands[bestcand];
2621  val = SCIPbranchGetBranchingPoint(set, tree, var, branchcand->externcandssol[bestcand]);
2622  assert(!SCIPsetIsEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
2623  assert(SCIPrelDiff(SCIPvarGetUbLocal(var), SCIPvarGetLbLocal(var)) <= 2.02 * SCIPsetEpsilon(set)
2624  || SCIPsetIsLT(set, SCIPvarGetLbLocal(var), val));
2625  assert(SCIPrelDiff(SCIPvarGetUbLocal(var), SCIPvarGetLbLocal(var)) <= 2.02 * SCIPsetEpsilon(set)
2626  || SCIPsetIsLT(set, val, SCIPvarGetUbLocal(var)));
2627 
2628  SCIPsetDebugMsg(set, "no branching method succeeded; fallback selected to branch on variable <%s> with bounds [%g, %g] on value %g\n",
2629  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), val);
2630 
2631  SCIP_CALL( SCIPtreeBranchVar(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, val,
2632  NULL, NULL, NULL) );
2633 
2634  if( tree->nchildren >= 1 )
2635  *result = SCIP_BRANCHED;
2636  /* if the bounds are too close, it may happen that we cannot branch but rather fix the variable */
2637  else
2638  {
2639  assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
2640  *result = SCIP_REDUCEDDOM;
2641  }
2642  }
2643 
2644  return SCIP_OKAY;
2645 }
2646 
2647 /** calls branching rules to branch on a pseudo solution; if no unfixed variables exist, the result is SCIP_DIDNOTRUN */
2649  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
2650  SCIP_SET* set, /**< global SCIP settings */
2651  SCIP_STAT* stat, /**< problem statistics */
2652  SCIP_PROB* transprob, /**< transformed problem after presolve */
2653  SCIP_PROB* origprob, /**< original problem */
2654  SCIP_TREE* tree, /**< branch and bound tree */
2655  SCIP_REOPT* reopt, /**< reoptimization data structure */
2656  SCIP_LP* lp, /**< current LP data */
2657  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
2658  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2659  SCIP_Real cutoffbound, /**< global upper cutoff bound */
2660  SCIP_Bool allowaddcons, /**< should adding constraints be allowed to avoid a branching? */
2661  SCIP_RESULT* result /**< pointer to store the result of the branching (s. branch.h) */
2662  )
2663 {
2664  int i;
2665 
2666  assert(branchcand != NULL);
2667  assert(result != NULL);
2668 
2669  SCIPsetDebugMsg(set, "branching on pseudo solution with %d unfixed variables\n", branchcand->npseudocands);
2670 
2671  *result = SCIP_DIDNOTRUN;
2672 
2673  /* do nothing, if no unfixed variables exist */
2674  if( branchcand->npseudocands == 0 )
2675  return SCIP_OKAY;
2676 
2677  /* sort the branching rules by priority */
2679 
2680  /* try all branching rules until one succeeded to branch */
2681  for( i = 0; i < set->nbranchrules && (*result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND); ++i )
2682  {
2683  SCIP_CALL( SCIPbranchruleExecPseudoSol(set->branchrules[i], set, stat, tree, cutoffbound, allowaddcons, result) );
2684  }
2685 
2686  if( *result == SCIP_DIDNOTRUN || *result == SCIP_DIDNOTFIND )
2687  {
2688  SCIP_VAR* var;
2689  SCIP_Real factor;
2690  SCIP_Real bestfactor;
2691  int priority;
2692  int bestpriority;
2693  int bestcand;
2694 
2695  /* no branching method succeeded in choosing a branching: just branch on the first unfixed variable with maximal
2696  * priority, and out of these on the one with maximal branch factor
2697  */
2698  bestcand = -1;
2699  bestpriority = INT_MIN;
2700  bestfactor = SCIP_REAL_MIN;
2701  for( i = 0; i < branchcand->npseudocands; ++i )
2702  {
2703  priority = SCIPvarGetBranchPriority(branchcand->pseudocands[i]);
2704  factor = SCIPvarGetBranchFactor(branchcand->pseudocands[i]);
2705  if( priority > bestpriority || (priority == bestpriority && factor > bestfactor) )
2706  {
2707  bestcand = i;
2708  bestpriority = priority;
2709  bestfactor = factor;
2710  }
2711  }
2712  assert(0 <= bestcand && bestcand < branchcand->npseudocands);
2713 
2714  var = branchcand->pseudocands[bestcand];
2715  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
2716  assert(!SCIPsetIsEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
2717 
2718  SCIP_CALL( SCIPtreeBranchVar(tree, reopt, blkmem, set, stat, transprob, origprob, lp, branchcand, eventqueue, var, SCIP_INVALID,
2719  NULL, NULL, NULL) );
2720 
2721  *result = SCIP_BRANCHED;
2722  }
2723 
2724  return SCIP_OKAY;
2725 }
2726 
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real * lpcandssol
Definition: struct_branch.h:40
int SCIPbranchcandGetNPrioExternBins(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:496
SCIP_Bool SCIPsolveIsStopped(SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool checknodelimits)
Definition: solve.c:71
SCIP_RETCODE SCIPbranchruleCreate(SCIP_BRANCHRULE **branchrule, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_DECL_BRANCHCOPY((*branchcopy)), SCIP_DECL_BRANCHFREE((*branchfree)), SCIP_DECL_BRANCHINIT((*branchinit)), SCIP_DECL_BRANCHEXIT((*branchexit)), SCIP_DECL_BRANCHINITSOL((*branchinitsol)), SCIP_DECL_BRANCHEXITSOL((*branchexitsol)), SCIP_DECL_BRANCHEXECLP((*branchexeclp)), SCIP_DECL_BRANCHEXECEXT((*branchexecext)), SCIP_DECL_BRANCHEXECPS((*branchexecps)), SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1237
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5517
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1780
internal methods for managing events
SCIP_Bool SCIPbranchruleIsInitialized(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2104
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5575
SCIP_RETCODE SCIPtreeBranchVar(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: tree.c:5317
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6025
SCIP_DECL_SORTPTRCOMP(SCIPbranchruleComp)
Definition: branch.c:1191
void SCIPbranchruleSetCopy(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: branch.c:1801
SCIP_Longint ncutsfound
Definition: struct_branch.h:78
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:107
internal methods for branch and bound tree
SCIP_Real SCIPbranchruleGetMaxbounddist(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1968
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5421
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17329
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5704
SCIP_RETCODE SCIPbranchruleExitsol(SCIP_BRANCHRULE *branchrule, SCIP_SET *set)
Definition: branch.c:1441
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7192
SCIP_PARAMDATA * SCIPparamGetData(SCIP_PARAM *param)
Definition: paramset.c:661
SCIP_Longint SCIPbranchruleGetNChildren(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2094
#define SCIP_DECL_BRANCHEXECPS(x)
Definition: type_branch.h:161
#define SCIP_MAXSTRLEN
Definition: def.h:225
SCIP_Longint ndomredsfound
Definition: struct_branch.h:81
internal methods for clocks and timing issues
int SCIPbranchcandGetNPseudoCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:823
SCIP_BRANCHRULEDATA * branchruledata
Definition: struct_branch.h:94
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5640
struct SCIP_ParamData SCIP_PARAMDATA
Definition: type_paramset.h:76
void SCIPbranchruleSetFree(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: branch.c:1812
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17225
int nintvars
Definition: struct_prob.h:63
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:43
SCIP_RETCODE SCIPbranchcandCreate(SCIP_BRANCHCAND **branchcand)
Definition: branch.c:133
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5379
SCIP_Longint nactiveconssadded
Definition: struct_stat.h:113
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12561
int SCIPbranchcandGetNPrioExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:486
const char * SCIPbranchruleGetDesc(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1912
SCIP_Real SCIPbranchGetScore(SCIP_SET *set, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: branch.c:2121
#define SCIP_DECL_BRANCHFREE(x)
Definition: type_branch.h:60
SCIP_Longint nholechgs
Definition: struct_stat.h:105
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:350
#define FALSE
Definition: def.h:64
int lppos
Definition: struct_lp.h:163
SCIP_Longint SCIPbranchruleGetNDomredsFound(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2084
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6058
SCIP_Bool solved
Definition: struct_lp.h:345
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:9618
SCIP_RETCODE SCIPbranchExecPseudo(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2648
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:280
int SCIPbranchcandGetNPrioPseudoImpls(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:863
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8132
SCIP_Longint SCIPbranchruleGetNCutoffs(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2052
internal methods for branching rules and branching candidate storage
void SCIPbranchcandClearExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:668
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5091
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5726
#define SCIP_DECL_BRANCHEXECEXT(x)
Definition: type_branch.h:140
SCIP_RETCODE SCIPbranchruleInitsol(SCIP_BRANCHRULE *branchrule, SCIP_SET *set)
Definition: branch.c:1417
#define SCIPdebugMessage
Definition: pub_message.h:77
int nimplvars
Definition: struct_prob.h:64
static SCIP_RETCODE ensureLpcandsSize(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, int num)
Definition: branch.c:55
SCIP_Longint SCIPbranchruleGetNExternCalls(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2032
internal methods for handling parameter settings
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5651
void SCIPclockEnableOrDisable(SCIP_CLOCK *clck, SCIP_Bool enable)
Definition: clock.c:250
#define SCIP_DECL_BRANCHEXITSOL(x)
Definition: type_branch.h:98
#define BMSfreeMemory(ptr)
Definition: memory.h:104
static SCIP_RETCODE ensureExterncandsSize(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, int num)
Definition: branch.c:103
SCIP_RETCODE SCIPbranchruleExecLPSol(SCIP_BRANCHRULE *branchrule, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_SEPASTORE *sepastore, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:1465
int SCIPbranchcandGetNPrioExternInts(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:506
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:12527
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5715
internal methods for LP management
SCIP_Bool SCIPsetIsFeasFracIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6069
int SCIPbranchcandGetNPrioPseudoCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:833
int branchpriority
Definition: struct_var.h:260
SCIP_RETCODE SCIPbranchruleExecPseudoSol(SCIP_BRANCHRULE *branchrule, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:1679
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:16654
SCIP_Longint nexterncalls
Definition: struct_branch.h:75
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5611
SCIP_RETCODE SCIPbranchExecLP(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2415
int pseudocandindex
Definition: struct_var.h:251
int SCIPbranchcandGetNExternCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:476
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5557
SCIP_RETCODE SCIPbranchcandAddExternCand(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_VAR *var, SCIP_Real score, SCIP_Real solval)
Definition: branch.c:538
#define SCIP_DECL_BRANCHINIT(x)
Definition: type_branch.h:68
SCIP_Real lb
Definition: struct_lp.h:129
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10996
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16115
#define SCIP_DECL_BRANCHCOPY(x)
Definition: type_branch.h:52
SCIP_RETCODE SCIPbranchcandGetExternCands(SCIP_BRANCHCAND *branchcand, SCIP_VAR ***externcands, SCIP_Real **externcandssol, SCIP_Real **externcandsscore, int *nexterncands, int *nprioexterncands, int *nprioexternbins, int *nprioexternints, int *nprioexternimpls)
Definition: branch.c:439
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:106
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_VAR ** lpcands
Definition: struct_branch.h:39
SCIP_Real maxbounddist
Definition: struct_branch.h:71
SCIP_Real SCIPbranchruleGetSetupTime(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2002
SCIP_Real SCIPbranchGetBranchingPoint(SCIP_SET *set, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real suggestion)
Definition: branch.c:2219
SCIP_Longint lpcount
Definition: struct_stat.h:169
void SCIPclockReset(SCIP_CLOCK *clck)
Definition: clock.c:199
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition: lp.c:16644
#define SCIP_DECL_BRANCHINITSOL(x)
Definition: type_branch.h:87
SCIP_RETCODE SCIPbranchruleExit(SCIP_BRANCHRULE *branchrule, SCIP_SET *set)
Definition: branch.c:1387
int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1328
#define SCIP_DECL_BRANCHEXECLP(x)
Definition: type_branch.h:119
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
SCIP_RETCODE SCIPbranchcandGetPseudoCands(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_PROB *prob, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
Definition: branch.c:759
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
void SCIPbranchruleSetInit(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
Definition: branch.c:1823
SCIP_Real * externcandsscore
Definition: struct_branch.h:43
SCIP_RETCODE SCIPbranchcandGetLPCands(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: branch.c:404
#define NULL
Definition: lpi_spx1.cpp:137
SCIP_Real * externcandssol
Definition: struct_branch.h:44
SCIP_Longint SCIPbranchruleGetNConssFound(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2074
#define REALABS(x)
Definition: def.h:169
SCIP_Bool SCIPsetIsRelGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6468
SCIP_RETCODE SCIPsetBranchrulePriority(SCIP *scip, SCIP_BRANCHRULE *branchrule, int priority)
Definition: scip.c:9256
static SCIP_RETCODE branchcandCalcLPCands(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: branch.c:203
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:316
SCIP_Longint SCIPbranchruleGetNLPCalls(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2022
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6003
SCIP_Real SCIPbranchruleGetTime(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2012
SCIP_RETCODE SCIPsetAddIntParam(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: set.c:2696
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5539
SCIP_Bool SCIPbranchcandContainsExternCand(SCIP_BRANCHCAND *branchcand, SCIP_VAR *var)
Definition: branch.c:683
internal methods for storing separated cuts
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5959
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:102
SCIP_Longint nprobboundchgs
Definition: struct_stat.h:106
SCIP_RETCODE SCIPclockCreate(SCIP_CLOCK **clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:160
void SCIPbranchruleSetMaxdepth(SCIP_BRANCHRULE *branchrule, int maxdepth)
Definition: branch.c:1956
SCIP_Longint SCIPbranchruleGetNCutsFound(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2062
internal methods for problem variables
void SCIPbranchruleSetExecLp(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: branch.c:1869
void SCIPbranchruleSetPriority(SCIP_BRANCHRULE *branchrule, SCIP_SET *set, int priority)
Definition: branch.c:1932
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5662
#define SCIP_Bool
Definition: def.h:61
SCIP_Longint npseudocalls
Definition: struct_branch.h:76
SCIP_Real SCIPsetSumepsilon(SCIP_SET *set)
Definition: set.c:5411
int SCIPbranchcandGetNPrioExternConts(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:526
int nbinvars
Definition: struct_prob.h:62
static const char * paramname[]
Definition: lpi_msk.c:4271
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17341
void SCIPclockFree(SCIP_CLOCK **clck)
Definition: clock.c:175
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1790
#define MAX(x, y)
Definition: tclique_def.h:75
void SCIPbranchruleEnableOrDisableClocks(SCIP_BRANCHRULE *branchrule, SCIP_Bool enable)
Definition: branch.c:1990
#define SCIPsetDebugMsg
Definition: set.h:1870
SCIP_CLOCK * branchclock
Definition: struct_branch.h:96
SCIP_Bool SCIPsetIsRelLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6424
static SCIP_DECL_PARAMCHGD(paramChgdBranchrulePriority)
Definition: branch.c:1204
SCIP_Bool SCIPtreeHasCurrentNodeLP(SCIP_TREE *tree)
Definition: tree.c:8149
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16883
SCIP_Real SCIPbranchGetScoreMultiple(SCIP_SET *set, SCIP_VAR *var, int nchildren, SCIP_Real *gains)
Definition: branch.c:2181
SCIP_RETCODE SCIPbranchcandUpdateVar(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_VAR *var)
Definition: branch.c:1107
void SCIPbranchruleSetExecPs(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECPS((*branchexecps)))
Definition: branch.c:1891
SCIP_RETCODE SCIPbranchruleExecExternSol(SCIP_BRANCHRULE *branchrule, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_SEPASTORE *sepastore, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:1572
SCIP_Real ub
Definition: struct_lp.h:130
void SCIPbranchcandInvalidate(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:192
#define SCIP_MAXTREEDEPTH
Definition: def.h:252
SCIP_RETCODE SCIPbranchcandFree(SCIP_BRANCHCAND **branchcand)
Definition: branch.c:173
void SCIPbranchruleSetInitsol(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINITSOL((*branchinitsol)))
Definition: branch.c:1845
int SCIPbranchruleGetMaxdepth(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1946
SCIP_Real SCIPsetFeasFrac(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6115
int SCIPparamGetInt(SCIP_PARAM *param)
Definition: paramset.c:716
#define SCIP_REAL_MIN
Definition: def.h:147
void SCIPbranchruleSetExecExt(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECEXT((*branchexecext)))
Definition: branch.c:1880
void SCIPsetSortBranchrules(SCIP_SET *set)
Definition: set.c:4445
int nactiveconss
Definition: struct_stat.h:216
int lpipos
Definition: struct_lp.h:164
SCIP_Longint SCIPbranchruleGetNPseudoCalls(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2042
internal methods for main solving loop and node processing
SCIP_Longint nchildren
Definition: struct_branch.h:82
SCIP_CLOCK * setuptime
Definition: struct_branch.h:95
void SCIPbranchruleSetExitsol(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXITSOL((*branchexitsol)))
Definition: branch.c:1856
SCIP_RETCODE SCIPbranchruleInit(SCIP_BRANCHRULE *branchrule, SCIP_SET *set)
Definition: branch.c:1343
SCIP_RETCODE SCIPbranchruleCopyInclude(SCIP_BRANCHRULE *branchrule, SCIP_SET *set)
Definition: branch.c:1218
int SCIPbranchcandGetNPrioPseudoBins(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:843
SCIP_Longint nconssfound
Definition: struct_branch.h:79
SCIP_Longint validlpcandslp
Definition: struct_branch.h:46
SCIP_Longint nboundchgs
Definition: struct_stat.h:104
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16674
static void branchcandSortPseudoCands(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:966
#define SCIP_Real
Definition: def.h:145
internal methods for problem statistics
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1902
SCIP_VAR ** vars
Definition: struct_prob.h:55
datastructures for branching rules and branching candidate storage
SCIP_RETCODE SCIPbranchruleFree(SCIP_BRANCHRULE **branchrule, SCIP_SET *set)
Definition: branch.c:1317
SCIP_VAR ** pseudocands
Definition: struct_branch.h:45
#define MIN(x, y)
Definition: memory.c:75
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6036
#define BMSallocMemory(ptr)
Definition: memory.h:78
#define SCIP_INVALID
Definition: def.h:165
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:86
SCIP_Bool initialized
Definition: struct_branch.h:99
void SCIPbranchruleSetMaxbounddist(SCIP_BRANCHRULE *branchrule, SCIP_Real maxbounddist)
Definition: branch.c:1978
#define SCIP_Longint
Definition: def.h:130
void SCIPbranchruleSetExit(SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXIT((*branchexit)))
Definition: branch.c:1834
static void branchcandRemovePseudoCand(SCIP_BRANCHCAND *branchcand, SCIP_VAR *var)
Definition: branch.c:1005
static void branchcandInsertPseudoCand(SCIP_BRANCHCAND *branchcand, SCIP_VAR *var, int insertpos)
Definition: branch.c:876
SCIP_VAR * var
Definition: struct_lp.h:151
SCIP_RETCODE SCIPbranchcandRemoveVar(SCIP_BRANCHCAND *branchcand, SCIP_VAR *var)
Definition: branch.c:1090
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16720
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8029
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5401
int SCIPbranchcandGetNPrioPseudoInts(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:853
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
int nchildren
Definition: struct_tree.h:208
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17235
SCIP_Real SCIPtreeGetLowerbound(SCIP_TREE *tree, SCIP_SET *set)
Definition: tree.c:6985
common defines and data types used in all packages of SCIP
SCIP_Longint ncutoffs
Definition: struct_branch.h:77
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:396
SCIP_RETCODE SCIPsetAddRealParam(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: set.c:2744
SCIP_Longint nlpcalls
Definition: struct_branch.h:74
#define SCIP_ALLOC(x)
Definition: def.h:327
SCIP_RETCODE SCIPbranchExecExtern(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real cutoffbound, SCIP_Bool allowaddcons, SCIP_RESULT *result)
Definition: branch.c:2517
#define SCIPABORT()
Definition: def.h:288
SCIP_Longint nprobholechgs
Definition: struct_stat.h:107
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:7963
SCIP_Real * lpcandsfrac
Definition: struct_branch.h:41
#define SCIP_DECL_BRANCHEXIT(x)
Definition: type_branch.h:76
SCIP_VAR ** externcands
Definition: struct_branch.h:42
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6047
SCIP_RETCODE SCIPbranchcandUpdateVarBranchPriority(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, SCIP_VAR *var, int branchpriority)
Definition: branch.c:1147
SCIP_NODE * focusnode
Definition: struct_tree.h:179
int SCIPbranchcandGetNPrioExternImpls(SCIP_BRANCHCAND *branchcand)
Definition: branch.c:516
int SCIPbranchruleGetPriority(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1922
static SCIP_RETCODE ensurePseudocandsSize(SCIP_BRANCHCAND *branchcand, SCIP_SET *set, int num)
Definition: branch.c:80
memory allocation routines