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