Scippy

SCIP

Solving Constraint Integer Programs

branch_fullstrong.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file branch_fullstrong.c
17  * @brief full strong LP branching rule
18  * @author Tobias Achterberg
19  * @author Gerald Gamrath
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <assert.h>
25 #include <string.h>
26 
27 #include "scip/branch_fullstrong.h"
28 
29 
30 #define BRANCHRULE_NAME "fullstrong"
31 #define BRANCHRULE_DESC "full strong branching"
32 #define BRANCHRULE_PRIORITY 0
33 #define BRANCHRULE_MAXDEPTH -1
34 #define BRANCHRULE_MAXBOUNDDIST 1.0
35 
36 #define DEFAULT_REEVALAGE 10LL /**< number of intermediate LPs solved to trigger reevaluation of strong branching
37  * value for a variable that was already evaluated at the current node */
38 #define DEFAULT_MAXPROPROUNDS -2 /**< maximum number of propagation rounds to be performed during strong branching
39  * before solving the LP (-1: no limit, -2: parameter settings) */
40 #define DEFAULT_PROBINGBOUNDS TRUE /**< should valid bounds be identified in a probing-like fashion during strong
41  * branching (only with propagation)? */
42 #define DEFAULT_FORCESTRONGBRANCH FALSE /**< should strong branching be applied even if there is just a single candidate? */
43 
44 
45 /** branching rule data */
46 struct SCIP_BranchruleData
47 {
48  SCIP_Longint reevalage; /**< number of intermediate LPs solved to trigger reevaluation of strong branching
49  * value for a variable that was already evaluated at the current node */
50  int maxproprounds; /**< maximum number of propagation rounds to be performed during strong branching
51  * before solving the LP (-1: no limit, -2: parameter settings) */
52  SCIP_Bool probingbounds; /**< should valid bounds be identified in a probing-like fashion during strong
53  * branching (only with propagation)? */
54  SCIP_Bool forcestrongbranch; /**< should strong branching be applied even if there is just a single candidate? */
55  int lastcand; /**< last evaluated candidate of last branching rule execution */
56  SCIP_Bool* skipdown;
57  SCIP_Bool* skipup;
58 };
59 
60 
61 /*
62  * Callback methods
63  */
64 
65 /** copy method for branchrule plugins (called when SCIP copies plugins) */
66 static
67 SCIP_DECL_BRANCHCOPY(branchCopyFullstrong)
68 { /*lint --e{715}*/
69  assert(scip != NULL);
70  assert(branchrule != NULL);
71  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
72 
73  /* call inclusion method of branchrule */
75 
76  return SCIP_OKAY;
77 }
78 
79 /** destructor of branching rule to free user data (called when SCIP is exiting) */
80 static
81 SCIP_DECL_BRANCHFREE(branchFreeFullstrong)
82 { /*lint --e{715}*/
83  SCIP_BRANCHRULEDATA* branchruledata;
84 
85  /* free branching rule data */
86  branchruledata = SCIPbranchruleGetData(branchrule);
87  assert(branchruledata != NULL);
88 
89  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipdown);
90  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipup);
91 
92  SCIPfreeMemory(scip, &branchruledata);
93  SCIPbranchruleSetData(branchrule, NULL);
94 
95  return SCIP_OKAY;
96 }
97 
98 
99 /** initialization method of branching rule (called after problem was transformed) */
100 static
101 SCIP_DECL_BRANCHINIT(branchInitFullstrong)
102 { /*lint --e{715}*/
103  SCIP_BRANCHRULEDATA* branchruledata;
105  /* initialize branching rule data */
106  branchruledata = SCIPbranchruleGetData(branchrule);
107  assert(branchruledata != NULL);
108 
109  branchruledata->lastcand = 0;
110 
111  return SCIP_OKAY;
112 }
113 
114 /** deinitialization method of branching rule (called before transformed problem is freed) */
115 static
116 SCIP_DECL_BRANCHEXIT(branchExitFullstrong)
117 { /*lint --e{715}*/
118  SCIP_BRANCHRULEDATA* branchruledata;
120  /* initialize branching rule data */
121  branchruledata = SCIPbranchruleGetData(branchrule);
122  assert(branchruledata != NULL);
123  assert((branchruledata->skipdown != NULL) == (branchruledata->skipup != NULL));
124 
125  if( branchruledata->skipdown != NULL )
126  {
127  SCIPfreeMemoryArray(scip, &branchruledata->skipup);
128  SCIPfreeMemoryArray(scip, &branchruledata->skipdown);
129  branchruledata->skipdown = NULL;
130  branchruledata->skipup = NULL;
131 
132  }
133 
134  return SCIP_OKAY;
135 }
136 
137 /**
138  * Selects a variable from a set of candidates by strong branching
139  *
140  * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
141  * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
142  *
143  * @note The variables in the lpcands array must have a fractional value in the current LP solution
144  */
146  SCIP* scip, /**< original SCIP data structure */
147  SCIP_VAR** lpcands, /**< branching candidates */
148  SCIP_Real* lpcandssol, /**< solution values of the branching candidates */
149  SCIP_Real* lpcandsfrac, /**< fractional values of the branching candidates */
150  SCIP_Bool* skipdown, /**< should down branchings be skipped? */
151  SCIP_Bool* skipup, /**< should up branchings be skipped? */
152  int nlpcands, /**< number of branching candidates */
153  int npriolpcands, /**< number of priority branching candidates */
154  int ncomplete, /**< number of branching candidates without skip */
155  int* start, /**< starting index in lpcands */
156  SCIP_Bool allowaddcons, /**< is the branching rule allowed to add constraints? */
157  int maxproprounds, /**< maximum number of propagation rounds to be performed during strong
158  * branching before solving the LP (-1: no limit, -2: parameter settings) */
159  SCIP_Bool probingbounds, /**< should valid bounds be identified in a probing-like fashion during
160  * strong branching (only with propagation)? */
161  SCIP_Bool forcestrongbranch, /**< should strong branching be applied even if there is just a single candidate? */
162  int* bestcand, /**< best candidate for branching */
163  SCIP_Real* bestdown, /**< objective value of the down branch for bestcand */
164  SCIP_Real* bestup, /**< objective value of the up branch for bestcand */
165  SCIP_Real* bestscore, /**< score for bestcand */
166  SCIP_Bool* bestdownvalid, /**< is bestdown a valid dual bound for the down branch? */
167  SCIP_Bool* bestupvalid, /**< is bestup a valid dual bound for the up branch? */
168  SCIP_Real* provedbound, /**< proved dual bound for current subtree */
169  SCIP_RESULT* result /**< result pointer */
170  )
171 {
172  SCIP_VAR** vars = NULL;
173  SCIP_Real* newlbs = NULL;
174  SCIP_Real* newubs = NULL;
175  SCIP_BRANCHRULE* branchrule;
176  SCIP_BRANCHRULEDATA* branchruledata;
177  SCIP_Longint reevalage;
178  SCIP_Longint nodenum;
179  SCIP_Real down;
180  SCIP_Real up;
181  SCIP_Real downgain;
182  SCIP_Real upgain;
183  SCIP_Real score;
184  SCIP_Real lpobjval;
185  SCIP_Bool exactsolve;
186  SCIP_Bool lperror;
187  SCIP_Bool allcolsinlp;
188  SCIP_Bool downvalid;
189  SCIP_Bool upvalid;
190  SCIP_Bool downinf;
191  SCIP_Bool upinf;
192  SCIP_Bool downconflict;
193  SCIP_Bool upconflict;
194  SCIP_Bool bothgains;
195  SCIP_Bool propagate;
196  int nvars = 0;
197  int nsbcalls;
198  int i;
199  int c;
200 
201  assert(scip != NULL);
202  assert(lpcands != NULL);
203  assert(lpcandssol != NULL);
204  assert(lpcandsfrac != NULL);
205  assert(bestcand != NULL);
206  assert(skipdown != NULL);
207  assert(skipup != NULL);
208  assert(bestdown != NULL);
209  assert(bestup != NULL);
210  assert(bestscore != NULL);
211  assert(bestdownvalid != NULL);
212  assert(bestupvalid != NULL);
213  assert(provedbound != NULL);
214  assert(result != NULL);
215  assert(nlpcands > 0);
216 
217  /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
218  * for cutting off sub problems and improving lower bounds of children
219  */
220  exactsolve = SCIPisExactSolve(scip);
221 
222  /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
223  allcolsinlp = SCIPallColsInLP(scip);
224 
225  /* get current node number */
226  nodenum = SCIPgetNNodes(scip);
227 
228  /* get current LP objective bound of the local sub problem and global cutoff bound */
229  lpobjval = SCIPgetLPObjval(scip);
230  *provedbound = lpobjval;
231 
232  *bestcand = 0;
233  *bestdown = lpobjval;
234  *bestup = lpobjval;
235  *bestdownvalid = TRUE;
236  *bestupvalid = TRUE;
237  *bestscore = -SCIPinfinity(scip);
238 
239  /* if only one candidate exists, choose this one without applying strong branching; also, when SCIP is about to be
240  * stopped, all strongbranching evaluations will be aborted anyway, thus we can return immediately
241  */
242  if( (!forcestrongbranch && nlpcands == 1) || SCIPisStopped(scip) )
243  return SCIP_OKAY;
244 
245  /* this assert may not hold if SCIP is stopped, thus we only check it here */
246  assert(SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL);
247 
248  /* get branching rule */
249  branchrule = SCIPfindBranchrule(scip, BRANCHRULE_NAME);
250  assert(branchrule != NULL);
251 
252  /* get branching rule data */
253  branchruledata = SCIPbranchruleGetData(branchrule);
254  assert(branchruledata != NULL);
255 
256  /* auto-setting for reevalage */
257  reevalage = branchruledata->reevalage;
258 
259  /* check whether propagation should be performed */
260  propagate = (maxproprounds != 0);
261 
262  /* if we don't do propagation, we cannot identify valid bounds in a probing-like fashion */
263  if( !propagate )
264  probingbounds = FALSE;
265 
266  /* create arrays for probing-like bound tightening */
267  if( probingbounds )
268  {
269  vars = SCIPgetVars(scip);
270  nvars = SCIPgetNVars(scip);
271 
272  SCIP_CALL( SCIPallocBufferArray(scip, &newlbs, nvars) );
273  SCIP_CALL( SCIPallocBufferArray(scip, &newubs, nvars) );
274  }
275 
276  /* initialize strong branching */
277  SCIP_CALL( SCIPstartStrongbranch(scip, propagate) );
278 
279  /* search the full strong candidate
280  * cycle through the candidates, starting with the position evaluated in the last run
281  */
282  nsbcalls = 0;
283  bothgains = TRUE;
284  for( i = 0, c = *start; i < nlpcands && (!bothgains || i < ncomplete); ++i, ++c )
285  {
286  c = c % nlpcands;
287  assert(lpcands[c] != NULL);
288 
289  /* don't use strong branching on variables that have already been initialized at the current node,
290  * and that were evaluated not too long ago
291  */
292  if( SCIPgetVarStrongbranchNode(scip, lpcands[c]) == nodenum
293  && SCIPgetVarStrongbranchLPAge(scip, lpcands[c]) < reevalage )
294  {
295  SCIP_Real lastlpobjval;
296 
297  /* use the score of the strong branching call at the current node */
298  SCIP_CALL( SCIPgetVarStrongbranchLast(scip, lpcands[c], &down, &up, NULL, NULL, NULL, &lastlpobjval) );
299  downgain = MAX(down - lastlpobjval, 0.0);
300  upgain = MAX(up - lastlpobjval, 0.0);
301  downvalid = FALSE;
302  upvalid = FALSE;
303  downinf = FALSE;
304  upinf = FALSE;
305  downconflict = FALSE;
306  upconflict = FALSE;
307  lperror = FALSE;
308  SCIPdebugMessage("strong branching on variable <%s> already performed (lpage=%" SCIP_LONGINT_FORMAT ", down=%g (%+g), up=%g (%+g))\n",
309  SCIPvarGetName(lpcands[c]), SCIPgetVarStrongbranchLPAge(scip, lpcands[c]), down, downgain, up, upgain);
310  }
311  else
312  {
313  SCIPdebugMessage("applying strong branching%s on variable <%s> with solution %g\n",
314  propagate ? "with propagation" : "", SCIPvarGetName(lpcands[c]), lpcandssol[c]);
315  assert(i >= ncomplete || (!skipdown[i] && !skipup[i]));
316 
317  /* apply strong branching */
318  up = -SCIPinfinity(scip);
319  down = -SCIPinfinity(scip);
320 
321  if( propagate )
322  {
323  SCIP_CALL( SCIPgetVarStrongbranchWithPropagation(scip, lpcands[c], lpcandssol[c], lpobjval, INT_MAX,
324  maxproprounds, skipdown[i] ? NULL : &down, skipup[i] ? NULL : &up, &downvalid,
325  &upvalid, NULL, NULL, &downinf, &upinf, &downconflict, &upconflict, &lperror, newlbs, newubs) );
326 
327  SCIPdebugMessage("-> down=%.9g (gain=%.9g, valid=%u, inf=%u, conflict=%u), up=%.9g (gain=%.9g, valid=%u, inf=%u, conflict=%u)\n",
328  down, down - lpobjval, downvalid, downinf, downconflict, up, up - lpobjval, upvalid, upinf, upconflict);
329  }
330  else
331  {
332  SCIP_CALL( SCIPgetVarStrongbranchFrac(scip, lpcands[c], INT_MAX,
333  skipdown[i] ? NULL : &down, skipup[i] ? NULL : &up, &downvalid, &upvalid, &downinf, &upinf,
334  &downconflict, &upconflict, &lperror) );
335  }
336  nsbcalls++;
337 
338  /* display node information line */
339  if( SCIPgetDepth(scip) == 0 && nsbcalls % 100 == 0 )
340  {
342  }
343 
344  /* check for an error in strong branching */
345  if( lperror )
346  {
348  "(node %" SCIP_LONGINT_FORMAT ") error in strong branching call%s for variable <%s> with solution %g\n",
349  SCIPgetNNodes(scip), propagate ? " with propagation" : "", SCIPvarGetName(lpcands[c]), lpcandssol[c]);
350  break;
351  }
352 
353  /* evaluate strong branching */
354  down = MAX(down, lpobjval);
355  up = MAX(up, lpobjval);
356  downgain = down - lpobjval;
357  upgain = up - lpobjval;
358  if( !SCIPisFeasZero(scip,downgain) && !SCIPisFeasZero(scip,upgain) )
359  bothgains = TRUE;
360 
361  assert(!allcolsinlp || exactsolve || !downvalid || downinf == SCIPisGE(scip, down, SCIPgetCutoffbound(scip)));
362  assert(!allcolsinlp || exactsolve || !upvalid || upinf == SCIPisGE(scip, up, SCIPgetCutoffbound(scip)));
363  assert(downinf || !downconflict);
364  assert(upinf || !upconflict);
365 
366  /* check if there are infeasible roundings */
367  if( downinf || upinf )
368  {
369  /* if we didn't do propagation, we can only detect infeasibility if the LP is a valid relaxation */
370  assert(allcolsinlp || propagate);
371  assert(!exactsolve);
372 
373  /* if for both infeasibilities, a conflict constraint was created, we don't need to fix the variable by
374  * hand, but better wait for the next propagation round to fix them as an inference, and potentially
375  * produce a cutoff that can be analyzed
376  */
377  if( allowaddcons && downinf == downconflict && upinf == upconflict )
378  {
379  *result = SCIP_CONSADDED;
380  break; /* terminate initialization loop, because constraint was added */
381  }
382  else if( downinf && upinf )
383  {
384  /* both roundings are infeasible -> node is infeasible */
385  *result = SCIP_CUTOFF;
386  SCIPdebugMessage(" -> variable <%s> is infeasible in both directions\n", SCIPvarGetName(lpcands[c]));
387  break; /* terminate initialization loop, because node is infeasible */
388  }
389  else if( downinf )
390  {
391  SCIP_Bool infeasible;
392  SCIP_Bool tightened;
393 
394  /* downwards rounding is infeasible -> change lower bound of variable to upward rounding */
395  SCIP_CALL( SCIPtightenVarLb(scip, lpcands[c], SCIPfeasCeil(scip, lpcandssol[c]), TRUE, &infeasible, &tightened) );
396  assert(!infeasible);
397 
398  /* if we did propagation, the bound change might already have been added */
399  assert(tightened || propagate);
400 
401  *result = SCIP_REDUCEDDOM;
402  SCIPdebugMessage(" -> variable <%s> is infeasible in downward branch\n", SCIPvarGetName(lpcands[c]));
403  break; /* terminate initialization loop, because LP was changed */
404  }
405  else
406  {
407  SCIP_Bool infeasible;
408  SCIP_Bool tightened;
409 
410  /* upwards rounding is infeasible -> change upper bound of variable to downward rounding */
411  assert(upinf);
412  SCIP_CALL( SCIPtightenVarUb(scip, lpcands[c], SCIPfeasFloor(scip, lpcandssol[c]), TRUE, &infeasible, &tightened) );
413  assert(!infeasible);
414 
415  /* if we did propagation, the bound change might already have been added */
416  assert(tightened || propagate);
417 
418  *result = SCIP_REDUCEDDOM;
419  SCIPdebugMessage(" -> variable <%s> is infeasible in upward branch\n", SCIPvarGetName(lpcands[c]));
420  break; /* terminate initialization loop, because LP was changed */
421  }
422  }
423  else if( allcolsinlp && !exactsolve && downvalid && upvalid )
424  {
425  SCIP_Real minbound;
426 
427  /* the minimal lower bound of both children is a proved lower bound of the current subtree */
428  minbound = MIN(down, up);
429  *provedbound = MAX(*provedbound, minbound);
430 
431  /* apply probing-like bounds detected during strong branching */
432  if( probingbounds )
433  {
434  int nboundchgs;
435  int v;
436 
437  assert(vars != NULL);
438  assert(nvars > 0);
439  assert(newlbs != NULL);
440  assert(newubs != NULL);
441 
442  nboundchgs = 0;
443 
444  for( v = 0; v < nvars; ++v )
445  {
446  if( SCIPisGT(scip, newlbs[v], SCIPvarGetLbLocal(vars[v])) )
447  {
448  SCIPdebugMessage("better lower bound for variable <%s>: %.9g -> %.9g (strongbranching on var <%s>\n",
449  SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]), newlbs[v], SCIPvarGetName(lpcands[c]));
450 
451  SCIP_CALL( SCIPchgVarLb(scip, vars[v], newlbs[v]) );
452  ++nboundchgs;
453  }
454  if( SCIPisLT(scip, newubs[v], SCIPvarGetUbLocal(vars[v])) )
455  {
456  SCIPdebugMessage("better upper bound for variable <%s>: %.9g -> %.9g (strongbranching on var <%s>\n",
457  SCIPvarGetName(vars[v]), SCIPvarGetUbLocal(vars[v]), newubs[v], SCIPvarGetName(lpcands[c]));
458 
459  SCIP_CALL( SCIPchgVarUb(scip, vars[v], newubs[v]) );
460  ++nboundchgs;
461  }
462  }
463 
464  if( nboundchgs > 0 )
465  {
466  *result = SCIP_REDUCEDDOM;
467  SCIPdebugMessage(" -> strong branching with propagation on variable <%s> led to %d bound changes\n",
468  SCIPvarGetName(lpcands[c]), nboundchgs);
469  break; /* terminate initialization loop, because LP was changed */
470  }
471  }
472  }
473 
474  /* update pseudo cost values */
475  assert(!downinf); /* otherwise, we would have terminated the initialization loop */
476  assert(!upinf);
477  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[c], 0.0-lpcandsfrac[c], downgain, 1.0) );
478  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[c], 1.0-lpcandsfrac[c], upgain, 1.0) );
479  }
480 
481  /* check for a better score, if we are within the maximum priority candidates */
482  if( c < npriolpcands )
483  {
484  score = SCIPgetBranchScore(scip, lpcands[c], downgain, upgain);
485  if( score > *bestscore )
486  {
487  *bestcand = c;
488  *bestdown = down;
489  *bestup = up;
490  *bestdownvalid = downvalid;
491  *bestupvalid = upvalid;
492  *bestscore = score;
493  }
494  }
495  else
496  score = 0.0;
497 
498  SCIPdebugMessage(" -> cand %d/%d (prio:%d) var <%s> (solval=%g, downgain=%g, upgain=%g, score=%g) -- best: <%s> (%g)\n",
499  c, nlpcands, npriolpcands, SCIPvarGetName(lpcands[c]), lpcandssol[c], downgain, upgain, score,
500  SCIPvarGetName(lpcands[*bestcand]), *bestscore);
501  }
502 
503  /* end strong branching */
505 
506  *start = c;
507 
508  if( probingbounds )
509  {
510  assert(newlbs != NULL);
511  assert(newubs != NULL);
512 
513  SCIPfreeBufferArray(scip, &newlbs);
514  SCIPfreeBufferArray(scip, &newubs);
515  }
516 
517  return SCIP_OKAY;
518 }
519 
520 /** branching execution method for fractional LP solutions */
521 static
522 SCIP_DECL_BRANCHEXECLP(branchExeclpFullstrong)
523 { /*lint --e{715}*/
524  SCIP_BRANCHRULEDATA* branchruledata;
525  SCIP_VAR** tmplpcands;
526  SCIP_VAR** lpcands;
527  SCIP_Real* tmplpcandssol;
528  SCIP_Real* lpcandssol;
529  SCIP_Real* tmplpcandsfrac;
530  SCIP_Real* lpcandsfrac;
531  SCIP_Real bestdown;
532  SCIP_Real bestup;
533  SCIP_Real bestscore;
534  SCIP_Real provedbound;
535  SCIP_Bool bestdownvalid;
536  SCIP_Bool bestupvalid;
537  int nlpcands;
538  int npriolpcands;
539  int bestcand;
540 
541  assert(branchrule != NULL);
542  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
543  assert(scip != NULL);
544  assert(result != NULL);
545 
546  SCIPdebugMessage("Execlp method of fullstrong branching\n");
547 
548  *result = SCIP_DIDNOTRUN;
549 
550  /* get branching rule data */
551  branchruledata = SCIPbranchruleGetData(branchrule);
552  assert(branchruledata != NULL);
553 
554  /* get branching candidates */
555  SCIP_CALL( SCIPgetLPBranchCands(scip, &tmplpcands, &tmplpcandssol, &tmplpcandsfrac, &nlpcands, &npriolpcands, NULL) );
556  assert(nlpcands > 0);
557  assert(npriolpcands > 0);
558 
559  /* copy LP banching candidates and solution values, because they will be updated w.r.t. the strong branching LP
560  * solution
561  */
562  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcands, tmplpcands, nlpcands) );
563  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandssol, tmplpcandssol, nlpcands) );
564  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandsfrac, tmplpcandsfrac, nlpcands) );
565 
566  if( branchruledata->skipdown == NULL )
567  {
568  int nvars;
569  nvars = SCIPgetNVars(scip);
570 
571  assert(branchruledata->skipup == NULL);
572 
573  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipdown, nvars) );
574  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipup, nvars) );
575  BMSclearMemoryArray(branchruledata->skipdown, nvars);
576  BMSclearMemoryArray(branchruledata->skipup, nvars);
577  }
578 
579  SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcands, lpcandssol, lpcandsfrac, branchruledata->skipdown,
580  branchruledata->skipup, nlpcands, npriolpcands, nlpcands, &branchruledata->lastcand, allowaddcons,
581  branchruledata->maxproprounds, branchruledata->probingbounds, branchruledata->forcestrongbranch, &bestcand,
582  &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
583 
584  if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED )
585  {
586  SCIP_NODE* downchild;
587  SCIP_NODE* upchild;
588  SCIP_VAR* var;
589  SCIP_Real val;
590  SCIP_Bool allcolsinlp;
591  SCIP_Bool exactsolve;
592 
593  assert(*result == SCIP_DIDNOTRUN);
594  assert(0 <= bestcand && bestcand < nlpcands);
595  assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
596 
597  var = lpcands[bestcand];
598  val = lpcandssol[bestcand];
599 
600  /* perform the branching */
601  SCIPdebugMessage(" -> %d candidates, selected candidate %d: variable <%s> (solval=%g, down=%g, up=%g, score=%g)\n",
602  nlpcands, bestcand, SCIPvarGetName(var), lpcandssol[bestcand], bestdown, bestup, bestscore);
603  SCIP_CALL( SCIPbranchVarVal(scip, var, val, &downchild, NULL, &upchild) );
604  assert(downchild != NULL);
605  assert(upchild != NULL);
606 
607  /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
608  * for cutting off sub problems and improving lower bounds of children
609  */
610  exactsolve = SCIPisExactSolve(scip);
611 
612  /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
613  allcolsinlp = SCIPallColsInLP(scip);
614 
615  /* update the lower bounds in the children */
616  if( allcolsinlp && !exactsolve )
617  {
618  SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
619  SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
620  }
621  SCIPdebugMessage(" -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
622  SCIPdebugMessage(" -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
623 
624  *result = SCIP_BRANCHED;
625  }
626 
627  SCIPfreeBufferArray(scip, &lpcandsfrac);
628  SCIPfreeBufferArray(scip, &lpcandssol);
629  SCIPfreeBufferArray(scip, &lpcands);
630 
631  return SCIP_OKAY;
632 }
633 
634 
635 /*
636  * branching specific interface methods
637  */
638 
639 /** creates the full strong LP branching rule and includes it in SCIP */
641  SCIP* scip /**< SCIP data structure */
642  )
643 {
644  SCIP_BRANCHRULEDATA* branchruledata;
645  SCIP_BRANCHRULE* branchrule;
646 
647  /* create fullstrong branching rule data */
648  SCIP_CALL( SCIPallocMemory(scip, &branchruledata) );
649  branchruledata->lastcand = 0;
650  branchruledata->skipup = NULL;
651  branchruledata->skipdown = NULL;
652 
653  /* include branching rule */
655  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
656 
657  assert(branchrule != NULL);
658 
659  /* set non-fundamental callbacks via specific setter functions*/
660  SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyFullstrong) );
661  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeFullstrong) );
662  SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitFullstrong) );
663  SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitFullstrong) );
664  SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpFullstrong) );
665 
666  /* fullstrong branching rule parameters */
668  "branching/fullstrong/reevalage",
669  "number of intermediate LPs solved to trigger reevaluation of strong branching value for a variable that was already evaluated at the current node",
670  &branchruledata->reevalage, TRUE, DEFAULT_REEVALAGE, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
672  "branching/fullstrong/maxproprounds",
673  "maximum number of propagation rounds to be performed during strong branching before solving the LP (-1: no limit, -2: parameter settings)",
674  &branchruledata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
676  "branching/fullstrong/probingbounds",
677  "should valid bounds be identified in a probing-like fashion during strong branching (only with propagation)?",
678  &branchruledata->probingbounds, TRUE, DEFAULT_PROBINGBOUNDS, NULL, NULL) );
680  "branching/fullstrong/forcestrongbranch",
681  "should strong branching be applied even if there is just a single candidate?",
682  &branchruledata->forcestrongbranch, TRUE, DEFAULT_FORCESTRONGBRANCH, NULL, NULL) );
683 
684  return SCIP_OKAY;
685 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:33125
SCIP_RETCODE SCIPprintDisplayLine(SCIP *scip, FILE *file, SCIP_VERBLEVEL verblevel, SCIP_Bool endline)
Definition: scip.c:40623
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
static SCIP_DECL_BRANCHFREE(branchFreeFullstrong)
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
SCIP_RETCODE SCIPsetBranchruleExit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXIT((*branchexit)))
Definition: scip.c:8338
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19748
SCIP_RETCODE SCIPincludeBranchruleFullstrong(SCIP *scip)
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:42032
SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
Definition: scip.c:8322
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:43
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPstartStrongbranch(SCIP *scip, SCIP_Bool enablepropagation)
Definition: scip.c:17963
#define BRANCHRULE_PRIORITY
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_DECL_BRANCHCOPY(branchCopyFullstrong)
SCIP_RETCODE SCIPupdateVarPseudocost(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: scip.c:23184
SCIP_Longint SCIPgetVarStrongbranchNode(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19300
#define SCIP_CALL(x)
Definition: def.h:266
static SCIP_DECL_BRANCHINIT(branchInitFullstrong)
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1877
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip.c:8290
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3601
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPgetVarStrongbranchFrac(SCIP *scip, SCIP_VAR *var, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Bool *downinf, SCIP_Bool *upinf, SCIP_Bool *downconflict, SCIP_Bool *upconflict, SCIP_Bool *lperror)
Definition: scip.c:18191
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip.c:8306
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
#define SCIP_LONGINT_MAX
Definition: def.h:113
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:26482
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:42044
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:26829
#define BRANCHRULE_MAXDEPTH
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition: scip.c:12363
#define DEFAULT_MAXPROPROUNDS
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, 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: scip.c:3573
SCIP_Longint SCIPgetVarStrongbranchLPAge(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19334
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip.c:8388
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
Definition: scip.c:8253
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1765
#define BRANCHRULE_DESC
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#define DEFAULT_REEVALAGE
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20193
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
full strong LP branching rule
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19828
#define SCIP_Bool
Definition: def.h:53
#define MAX(x, y)
Definition: tclique_def.h:75
#define DEFAULT_FORCESTRONGBRANCH
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
#define BRANCHRULE_NAME
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1298
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
#define BRANCHRULE_MAXBOUNDDIST
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1755
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:20545
static SCIP_DECL_BRANCHEXIT(branchExitFullstrong)
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: scip.c:33580
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20593
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:8436
#define SCIP_Real
Definition: def.h:127
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20299
#define MIN(x, y)
Definition: memory.c:67
static SCIP_DECL_BRANCHEXECLP(branchExeclpFullstrong)
#define SCIP_Longint
Definition: def.h:112
SCIP_RETCODE SCIPendStrongbranch(SCIP *scip)
Definition: scip.c:18019
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7036
SCIP_RETCODE SCIPgetVarStrongbranchLast(SCIP *scip, SCIP_VAR *var, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Real *solval, SCIP_Real *lpobjval)
Definition: scip.c:19256
SCIP_RETCODE SCIPselectVarStrongBranching(SCIP *scip, SCIP_VAR **lpcands, SCIP_Real *lpcandssol, SCIP_Real *lpcandsfrac, SCIP_Bool *skipdown, SCIP_Bool *skipup, int nlpcands, int npriolpcands, int ncomplete, int *start, SCIP_Bool allowaddcons, int maxproprounds, SCIP_Bool probingbounds, SCIP_Bool forcestrongbranch, int *bestcand, SCIP_Real *bestdown, SCIP_Real *bestup, SCIP_Real *bestscore, SCIP_Bool *bestdownvalid, SCIP_Bool *bestupvalid, SCIP_Real *provedbound, SCIP_RESULT *result)
#define DEFAULT_PROBINGBOUNDS
SCIP_RETCODE SCIPbranchVarVal(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip.c:33810
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:37372
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip.c:1012
SCIP_RETCODE SCIPgetVarStrongbranchWithPropagation(SCIP *scip, SCIP_VAR *var, SCIP_Real solval, SCIP_Real lpobjval, int itlim, int maxproprounds, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Longint *ndomredsdown, SCIP_Longint *ndomredsup, SCIP_Bool *downinf, SCIP_Bool *upinf, SCIP_Bool *downconflict, SCIP_Bool *upconflict, SCIP_Bool *lperror, SCIP_Real *newlbs, SCIP_Real *newubs)
Definition: scip.c:18633