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