Scippy

SCIP

Solving Constraint Integer Programs

branch_relpscost.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-2014 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_relpscost.c
17  * @brief reliable pseudo costs branching rule
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include <assert.h>
26 #include <string.h>
27 
28 #include "scip/branch_relpscost.h"
29 
30 
31 #define BRANCHRULE_NAME "relpscost"
32 #define BRANCHRULE_DESC "reliability branching on pseudo cost values"
33 #define BRANCHRULE_PRIORITY 10000
34 #define BRANCHRULE_MAXDEPTH -1
35 #define BRANCHRULE_MAXBOUNDDIST 1.0
36 
37 #define DEFAULT_CONFLICTWEIGHT 0.01 /**< weight in score calculations for conflict score */
38 #define DEFAULT_CONFLENGTHWEIGHT 0.0 /**< weight in score calculations for conflict length score*/
39 #define DEFAULT_INFERENCEWEIGHT 0.0001 /**< weight in score calculations for inference score */
40 #define DEFAULT_CUTOFFWEIGHT 0.0001 /**< weight in score calculations for cutoff score */
41 #define DEFAULT_PSCOSTWEIGHT 1.0 /**< weight in score calculations for pseudo cost score */
42 #define DEFAULT_MINRELIABLE 1.0 /**< minimal value for minimum pseudo cost size to regard pseudo cost value as reliable */
43 #define DEFAULT_MAXRELIABLE 5.0 /**< maximal value for minimum pseudo cost size to regard pseudo cost value as reliable */
44 #define DEFAULT_SBITERQUOT 0.5 /**< maximal fraction of strong branching LP iterations compared to normal iterations */
45 #define DEFAULT_SBITEROFS 100000 /**< additional number of allowed strong branching LP iterations */
46 #define DEFAULT_MAXLOOKAHEAD 9 /**< maximal number of further variables evaluated without better score */
47 #define DEFAULT_INITCAND 100 /**< maximal number of candidates initialized with strong branching per node */
48 #define DEFAULT_INITITER 0 /**< iteration limit for strong branching initialization of pseudo cost entries (0: auto) */
49 #define DEFAULT_MAXBDCHGS 5 /**< maximal number of bound tightenings before the node is reevaluated (-1: unlimited) */
50 #define DEFAULT_MAXPROPROUNDS -2 /**< maximum number of propagation rounds to be performed during strong branching
51  * before solving the LP (-1: no limit, -2: parameter settings) */
52 #define DEFAULT_PROBINGBOUNDS TRUE /**< should valid bounds be identified in a probing-like fashion during strong
53  * branching (only with propagation)? */
54 
55 
56 /** branching rule data */
57 struct SCIP_BranchruleData
58 {
59  SCIP_Real conflictweight; /**< weight in score calculations for conflict score */
60  SCIP_Real conflengthweight; /**< weight in score calculations for conflict length score */
61  SCIP_Real inferenceweight; /**< weight in score calculations for inference score */
62  SCIP_Real cutoffweight; /**< weight in score calculations for cutoff score */
63  SCIP_Real pscostweight; /**< weight in score calculations for pseudo cost score */
64  SCIP_Real minreliable; /**< minimal value for minimum pseudo cost size to regard pseudo cost value as reliable */
65  SCIP_Real maxreliable; /**< maximal value for minimum pseudo cost size to regard pseudo cost value as reliable */
66  SCIP_Real sbiterquot; /**< maximal fraction of strong branching LP iterations compared to normal iterations */
67  int sbiterofs; /**< additional number of allowed strong branching LP iterations */
68  int maxlookahead; /**< maximal number of further variables evaluated without better score */
69  int initcand; /**< maximal number of candidates initialized with strong branching per node */
70  int inititer; /**< iteration limit for strong branching initialization of pseudo cost entries (0: auto) */
71  int maxbdchgs; /**< maximal number of bound tightenings before the node is reevaluated (-1: unlimited) */
72  int maxproprounds; /**< maximum number of propagation rounds to be performed during strong branching
73  * before solving the LP (-1: no limit, -2: parameter settings) */
74  SCIP_Bool probingbounds; /**< should valid bounds be identified in a probing-like fashion during strong
75  * branching (only with propagation)? */
76 };
77 
78 
79 /*
80  * local methods
81  */
82 
83 /** calculates an overall score value for the given individual score values */
84 static
86  SCIP* scip, /**< SCIP data structure */
87  SCIP_BRANCHRULEDATA* branchruledata, /**< branching rule data */
88  SCIP_Real conflictscore, /**< conflict score of current variable */
89  SCIP_Real avgconflictscore, /**< average conflict score */
90  SCIP_Real conflengthscore, /**< conflict length score of current variable */
91  SCIP_Real avgconflengthscore, /**< average conflict length score */
92  SCIP_Real inferencescore, /**< inference score of current variable */
93  SCIP_Real avginferencescore, /**< average inference score */
94  SCIP_Real cutoffscore, /**< cutoff score of current variable */
95  SCIP_Real avgcutoffscore, /**< average cutoff score */
96  SCIP_Real pscostscore, /**< pscost score of current variable */
97  SCIP_Real avgpscostscore, /**< average pscost score */
98  SCIP_Real frac /**< fractional value of variable in current solution */
99  )
100 {
101  SCIP_Real score;
102 
103  assert(branchruledata != NULL);
104  assert(0.0 < frac && frac < 1.0);
105 
106  score = branchruledata->conflictweight * (1.0 - 1.0/(1.0+conflictscore/avgconflictscore))
107  + branchruledata->conflengthweight * (1.0 - 1.0/(1.0+conflengthscore/avgconflengthscore))
108  + branchruledata->inferenceweight * (1.0 - 1.0/(1.0+inferencescore/avginferencescore))
109  + branchruledata->cutoffweight * (1.0 - 1.0/(1.0+cutoffscore/avgcutoffscore))
110  + branchruledata->pscostweight * (1.0 - 1.0/(1.0+pscostscore/avgpscostscore));
111 
112  /* avoid close to integral variables */
113  if( MIN(frac, 1.0 - frac) < 10.0*SCIPfeastol(scip) )
114  score *= 1e-6;
115 
116  return score;
117 }
118 
119 /** adds given index and direction to bound change arrays */
120 static
122  SCIP* scip, /**< SCIP data structure */
123  int** bdchginds, /**< pointer to bound change index array */
124  SCIP_BOUNDTYPE** bdchgtypes, /**< pointer to bound change types array */
125  SCIP_Real** bdchgbounds, /**< pointer to bound change new bounds array */
126  int* nbdchgs, /**< pointer to number of bound changes */
127  int ind, /**< index to store in bound change index array */
128  SCIP_BOUNDTYPE type, /**< type of the bound change to store in bound change type array */
129  SCIP_Real bound /**< new bound to store in bound change new bounds array */
130  )
131 {
132  assert(bdchginds != NULL);
133  assert(bdchgtypes != NULL);
134  assert(bdchgbounds != NULL);
135  assert(nbdchgs != NULL);
136 
137  SCIP_CALL( SCIPreallocBufferArray(scip, bdchginds, (*nbdchgs) + 1) );
138  SCIP_CALL( SCIPreallocBufferArray(scip, bdchgtypes, (*nbdchgs) + 1) );
139  SCIP_CALL( SCIPreallocBufferArray(scip, bdchgbounds, (*nbdchgs) + 1) );
140  assert(*bdchginds != NULL);
141  assert(*bdchgtypes != NULL);
142  assert(*bdchgbounds != NULL);
143 
144  (*bdchginds)[*nbdchgs] = ind;
145  (*bdchgtypes)[*nbdchgs] = type;
146  (*bdchgbounds)[*nbdchgs] = bound;
147  (*nbdchgs)++;
148 
149  return SCIP_OKAY;
150 }
151 
152 /** frees bound change arrays */
153 static
154 void freeBdchgs(
155  SCIP* scip, /**< SCIP data structure */
156  int** bdchginds, /**< pointer to bound change index array */
157  SCIP_BOUNDTYPE** bdchgtypes, /**< pointer to bound change types array */
158  SCIP_Real** bdchgbounds, /**< pointer to bound change new bounds array */
159  int* nbdchgs /**< pointer to number of bound changes */
160  )
161 {
162  assert(bdchginds != NULL);
163  assert(bdchgtypes != NULL);
164  assert(bdchgbounds != NULL);
165  assert(nbdchgs != NULL);
166 
167  SCIPfreeBufferArrayNull(scip, bdchgbounds);
168  SCIPfreeBufferArrayNull(scip, bdchgtypes);
169  SCIPfreeBufferArrayNull(scip, bdchginds);
170  *nbdchgs = 0;
171 }
172 
173 /** applies bound changes stored in bound change arrays */
174 static
176  SCIP* scip, /**< SCIP data structure */
177  SCIP_VAR** vars, /**< problem variables */
178  int* bdchginds, /**< bound change index array */
179  SCIP_BOUNDTYPE* bdchgtypes, /**< bound change types array */
180  SCIP_Real* bdchgbounds, /**< bound change new bound array */
181  int nbdchgs, /**< number of bound changes */
182  SCIP_RESULT* result /**< result pointer */
183  )
184 {
185 #ifndef NDEBUG
186  SCIP_BRANCHRULE* branchrule;
187  SCIP_BRANCHRULEDATA* branchruledata;
188 #endif
189  SCIP_Bool infeasible;
190  SCIP_Bool tightened;
191  int i;
192 
193  assert(vars != NULL);
194 
195 #ifndef NDEBUG
196  /* find branching rule */
197  branchrule = SCIPfindBranchrule(scip, BRANCHRULE_NAME);
198  assert(branchrule != NULL);
199 
200  /* get branching rule data */
201  branchruledata = SCIPbranchruleGetData(branchrule);
202  assert(branchruledata != NULL);
203 #endif
204 
205  SCIPdebugMessage("applying %d bound changes\n", nbdchgs);
206 
207  for( i = 0; i < nbdchgs; ++i )
208  {
209  int v;
210 
211  v = bdchginds[i];
212 
213  SCIPdebugMessage(" -> <%s> [%g,%g]\n",
214  SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v]));
215 
216  if( bdchgtypes[i] == SCIP_BOUNDTYPE_LOWER )
217  {
218  /* change lower bound of variable to given bound */
219  SCIP_CALL( SCIPtightenVarLb(scip, vars[v], bdchgbounds[i], TRUE, &infeasible, &tightened) );
220  if( infeasible )
221  {
222  *result = SCIP_CUTOFF;
223  return SCIP_OKAY;
224  }
225 
226  /* if we did propagation, the bound change might already have been added */
227  assert(tightened || (branchruledata->maxproprounds != 0));
228  }
229  else
230  {
231  assert(bdchgtypes[i] == SCIP_BOUNDTYPE_UPPER);
232 
233  /* change upper bound of variable to given bound */
234  SCIP_CALL( SCIPtightenVarUb(scip, vars[v], bdchgbounds[i], TRUE, &infeasible, &tightened) );
235  if( infeasible )
236  {
237  *result = SCIP_CUTOFF;
238  return SCIP_OKAY;
239  }
240 
241  /* if we did propagation, the bound change might already have been added */
242  assert(tightened || (branchruledata->maxproprounds != 0));
243  }
244  SCIPdebugMessage(" -> [%g,%g]\n", SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v]));
245  }
246 
247  return SCIP_OKAY;
248 }
249 
250 /** execute reliability pseudo cost branching */
251 static
253  SCIP* scip, /**< SCIP data structure */
254  SCIP_BRANCHRULE* branchrule, /**< branching rule */
255  SCIP_Bool allowaddcons, /**< is the branching rule allowed to add constraints to the current node
256  * in order to cut off the current solution instead of creating a branching? */
257  SCIP_VAR** branchcands, /**< branching candidates */
258  SCIP_Real* branchcandssol, /**< solution value for the branching candidates */
259  SCIP_Real* branchcandsfrac, /**< fractional part of the branching candidates */
260  int nbranchcands, /**< number of branching candidates */
261  SCIP_RESULT* result /**< pointer to the result of the execution */
262  )
263 {
264  SCIP_BRANCHRULEDATA* branchruledata;
265  SCIP_Real lpobjval;
266  SCIP_Real bestsbdown;
267  SCIP_Real bestsbup;
268  SCIP_Real provedbound;
269  SCIP_Bool bestsbdownvalid;
270  SCIP_Bool bestsbupvalid;
271  SCIP_Bool bestsbdowncutoff;
272  SCIP_Bool bestsbupcutoff;
273  SCIP_Bool bestisstrongbranch;
274  SCIP_Bool allcolsinlp;
275  SCIP_Bool exactsolve;
276  int ninitcands;
277  int bestcand;
278 
279  *result = SCIP_DIDNOTRUN;
280 
281  assert(SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL);
282 
283  /* get branching rule data */
284  branchruledata = SCIPbranchruleGetData(branchrule);
285  assert(branchruledata != NULL);
286 
287  /* get current LP objective bound of the local sub problem and global cutoff bound */
288  lpobjval = SCIPgetLPObjval(scip);
289 
290  /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
291  * for cutting off sub problems and improving lower bounds of children
292  */
293  exactsolve = SCIPisExactSolve(scip);
294 
295  /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
296  allcolsinlp = SCIPallColsInLP(scip);
297 
298  bestcand = -1;
299  bestisstrongbranch = FALSE;
300  bestsbdown = SCIP_INVALID;
301  bestsbup = SCIP_INVALID;
302  bestsbdownvalid = FALSE;
303  bestsbupvalid = FALSE;
304  bestsbdowncutoff = FALSE;
305  bestsbupcutoff = FALSE;
306  provedbound = lpobjval;
307 
308  if( nbranchcands == 1 )
309  {
310  /* only one candidate: nothing has to be done */
311  bestcand = 0;
312  ninitcands = 0;
313  }
314  else
315  {
316  SCIP_VAR** vars;
317  int* initcands;
318  SCIP_Real* initcandscores;
319  SCIP_Real* newlbs = NULL;
320  SCIP_Real* newubs = NULL;
321  int* bdchginds;
322  SCIP_BOUNDTYPE* bdchgtypes;
323  SCIP_Real* bdchgbounds;
324  int maxninitcands;
325  int nuninitcands;
326  int nbdchgs;
327  int nbdconflicts;
328  SCIP_Real avgconflictscore;
329  SCIP_Real avgconflengthscore;
330  SCIP_Real avginferencescore;
331  SCIP_Real avgcutoffscore;
332  SCIP_Real avgpscostscore;
333  SCIP_Real bestpsscore;
334  SCIP_Real bestpsfracscore;
335  SCIP_Real bestpsdomainscore;
336  SCIP_Real bestsbscore;
337  SCIP_Real bestuninitsbscore;
338  SCIP_Real bestsbfracscore;
339  SCIP_Real bestsbdomainscore;
340  SCIP_Real prio;
341  SCIP_Real reliable;
342  SCIP_Real maxlookahead;
343  SCIP_Real lookahead;
344  SCIP_Bool initstrongbranching;
345  SCIP_Bool propagate;
346  SCIP_Bool probingbounds;
347  SCIP_Longint nodenum;
348  SCIP_Longint nlpiterationsquot;
349  SCIP_Longint nsblpiterations;
350  SCIP_Longint maxnsblpiterations;
351  int bestsolidx;
352  int maxbdchgs;
353  int bestpscand;
354  int bestsbcand;
355  int inititer;
356  int nvars;
357  int i;
358  int c;
359 
360  vars = SCIPgetVars(scip);
361  nvars = SCIPgetNVars(scip);
362 
363  bestsolidx = SCIPgetBestSol(scip) == NULL ? -1 : SCIPsolGetIndex(SCIPgetBestSol(scip));
364 
365  /* get average conflict, inference, and pseudocost scores */
366  avgconflictscore = SCIPgetAvgConflictScore(scip);
367  avgconflictscore = MAX(avgconflictscore, 0.1);
368  avgconflengthscore = SCIPgetAvgConflictlengthScore(scip);
369  avgconflengthscore = MAX(avgconflengthscore, 0.1);
370  avginferencescore = SCIPgetAvgInferenceScore(scip);
371  avginferencescore = MAX(avginferencescore, 0.1);
372  avgcutoffscore = SCIPgetAvgCutoffScore(scip);
373  avgcutoffscore = MAX(avgcutoffscore, 0.1);
374  avgpscostscore = SCIPgetAvgPseudocostScore(scip);
375  avgpscostscore = MAX(avgpscostscore, 0.1);
376 
377  initstrongbranching = FALSE;
378 
379  /* check whether propagation should be performed */
380  propagate = (branchruledata->maxproprounds != 0);
381 
382  /* check whether valid bounds should be identified in probing-like fashion */
383  probingbounds = propagate && branchruledata->probingbounds;
384 
385  /* get maximal number of candidates to initialize with strong branching; if the current solutions is not basic,
386  * we cannot warmstart the simplex algorithm and therefore don't initialize any candidates
387  */
388  maxninitcands = MIN(nbranchcands, branchruledata->initcand);
389  if( !SCIPisLPSolBasic(scip) )
390  maxninitcands = 0;
391 
392  /* calculate maximal number of strong branching LP iterations; if we used too many, don't apply strong branching
393  * any more
394  */
395  nlpiterationsquot = (SCIP_Longint)(branchruledata->sbiterquot * SCIPgetNNodeLPIterations(scip));
396  maxnsblpiterations = nlpiterationsquot + branchruledata->sbiterofs + SCIPgetNRootStrongbranchLPIterations(scip);
397  nsblpiterations = SCIPgetNStrongbranchLPIterations(scip);
398  if( nsblpiterations > maxnsblpiterations )
399  maxninitcands = 0;
400 
401  /* get buffer for storing the unreliable candidates */
402  SCIP_CALL( SCIPallocBufferArray(scip, &initcands, maxninitcands+1) ); /* allocate one additional slot for convenience */
403  SCIP_CALL( SCIPallocBufferArray(scip, &initcandscores, maxninitcands+1) );
404  ninitcands = 0;
405 
406  /* get current node number */
407  nodenum = SCIPgetNNodes(scip);
408 
409  /* initialize bound change arrays */
410  bdchginds = NULL;
411  bdchgtypes = NULL;
412  bdchgbounds = NULL;
413  nbdchgs = 0;
414  nbdconflicts = 0;
415  maxbdchgs = branchruledata->maxbdchgs;
416  if( maxbdchgs == -1 )
417  maxbdchgs = INT_MAX;
418 
419  /* calculate value used as reliability */
420  prio = (maxnsblpiterations - nsblpiterations)/(nsblpiterations + 1.0);
421  prio = MIN(prio, 1.0);
422  prio = MAX(prio, (nlpiterationsquot - nsblpiterations)/(nsblpiterations + 1.0));
423  reliable = (1.0-prio) * branchruledata->minreliable + prio * branchruledata->maxreliable;
424 
425  /* search for the best pseudo cost candidate, while remembering unreliable candidates in a sorted buffer */
426  nuninitcands = 0;
427  bestpscand = -1;
428  bestpsscore = -SCIPinfinity(scip);
429  bestpsfracscore = -SCIPinfinity(scip);
430  bestpsdomainscore = -SCIPinfinity(scip);
431  for( c = 0; c < nbranchcands; ++c )
432  {
433  SCIP_Real conflictscore;
434  SCIP_Real conflengthscore;
435  SCIP_Real inferencescore;
436  SCIP_Real cutoffscore;
437  SCIP_Real pscostscore;
438  SCIP_Real score;
439  SCIP_Bool usesb;
440 
441  assert(branchcands[c] != NULL);
442  assert(!SCIPisFeasIntegral(scip, branchcandssol[c]));
443 
444  /* get conflict, inference, cutoff, and pseudo cost scores for candidate */
445  conflictscore = SCIPgetVarConflictScore(scip, branchcands[c]);
446  conflengthscore = SCIPgetVarConflictlengthScore(scip, branchcands[c]);
447  inferencescore = SCIPgetVarAvgInferenceScore(scip, branchcands[c]);
448  cutoffscore = SCIPgetVarAvgCutoffScore(scip, branchcands[c]);
449  pscostscore = SCIPgetVarPseudocostScore(scip, branchcands[c], branchcandssol[c]);
450  usesb = FALSE;
451 
452  /* don't use strong branching on variables that have already been initialized at the current node;
453  * instead replace the pseudo cost score with the already calculated one;
454  * @todo: use old data for strong branching with propagation?
455  */
456  if( SCIPgetVarStrongbranchNode(scip, branchcands[c]) == nodenum )
457  {
458  SCIP_Real down;
459  SCIP_Real up;
460  SCIP_Real lastlpobjval;
461  SCIP_Real downgain;
462  SCIP_Real upgain;
463 
464  /* use the score of the strong branching call at the current node */
465  SCIP_CALL( SCIPgetVarStrongbranchLast(scip, branchcands[c], &down, &up, NULL, NULL, NULL, &lastlpobjval) );
466  downgain = MAX(down - lastlpobjval, 0.0);
467  upgain = MAX(up - lastlpobjval, 0.0);
468  pscostscore = SCIPgetBranchScore(scip, branchcands[c], downgain, upgain);
469 
470  SCIPdebugMessage(" -> strong branching on variable <%s> already performed (down=%g (%+g), up=%g (%+g), pscostscore=%g)\n",
471  SCIPvarGetName(branchcands[c]), down, downgain, up, upgain, pscostscore);
472  }
473  else if( maxninitcands > 0 )
474  {
475  SCIP_Real downsize;
476  SCIP_Real upsize;
477  SCIP_Real size;
478 
479  /* check, if the pseudo cost score of the variable is reliable */
480  downsize = SCIPgetVarPseudocostCountCurrentRun(scip, branchcands[c], SCIP_BRANCHDIR_DOWNWARDS);
481  upsize = SCIPgetVarPseudocostCountCurrentRun(scip, branchcands[c], SCIP_BRANCHDIR_UPWARDS);
482  size = MIN(downsize, upsize);
483 
484  /* use strong branching on variables with unreliable pseudo cost scores */
485  usesb = (size < reliable);
486 
487  /* count the number of variables that are completely uninitialized */
488  if( size < 0.1 )
489  nuninitcands++;
490  }
491 
492  /* combine the four score values */
493  score = calcScore(scip, branchruledata, conflictscore, avgconflictscore, conflengthscore, avgconflengthscore,
494  inferencescore, avginferencescore, cutoffscore, avgcutoffscore, pscostscore, avgpscostscore, branchcandsfrac[c]);
495 
496  if( usesb )
497  {
498  int j;
499 
500  /* pseudo cost of variable is not reliable: insert candidate in initcands buffer */
501  for( j = ninitcands; j > 0 && score > initcandscores[j-1]; --j )
502  {
503  initcands[j] = initcands[j-1];
504  initcandscores[j] = initcandscores[j-1];
505  }
506  initcands[j] = c;
507  initcandscores[j] = score;
508  ninitcands++;
509  ninitcands = MIN(ninitcands, maxninitcands);
510  }
511  else
512  {
513  /* variable will keep it's pseudo cost value: check for better score of candidate */
514  if( SCIPisSumGE(scip, score, bestpsscore) )
515  {
516  SCIP_Real fracscore;
517  SCIP_Real domainscore;
518 
519  fracscore = MIN(branchcandsfrac[c], 1.0 - branchcandsfrac[c]);
520  domainscore = -(SCIPvarGetUbLocal(branchcands[c]) - SCIPvarGetLbLocal(branchcands[c]));
521  if( SCIPisSumGT(scip, score, bestpsscore)
522  || SCIPisSumGT(scip, fracscore, bestpsfracscore)
523  || (SCIPisSumGE(scip, fracscore, bestpsfracscore) && domainscore > bestpsdomainscore) )
524  {
525  bestpscand = c;
526  bestpsscore = score;
527  bestpsfracscore = fracscore;
528  bestpsdomainscore = domainscore;
529  }
530  }
531  }
532  }
533 
534  /* initialize unreliable candidates with strong branching until maxlookahead is reached,
535  * search best strong branching candidate
536  */
537  maxlookahead = (SCIP_Real)branchruledata->maxlookahead * (1.0 + (SCIP_Real)nuninitcands/(SCIP_Real)nbranchcands);
538  inititer = branchruledata->inititer;
539  if( inititer == 0 )
540  {
541  SCIP_Longint nlpiterations;
542  SCIP_Longint nlps;
543 
544  /* iteration limit is set to twice the average number of iterations spent to resolve a dual feasible SCIP_LP;
545  * at the first few nodes, this average is not very exact, so we better increase the iteration limit on
546  * these very important nodes
547  */
548  nlpiterations = SCIPgetNDualResolveLPIterations(scip);
549  nlps = SCIPgetNDualResolveLPs(scip);
550  if( nlps == 0 )
551  {
552  nlpiterations = SCIPgetNNodeInitLPIterations(scip);
553  nlps = SCIPgetNNodeInitLPs(scip);
554  if( nlps == 0 )
555  {
556  nlpiterations = 1000;
557  nlps = 1;
558  }
559  }
560  assert(nlps >= 1);
561  inititer = (int)(2*nlpiterations / nlps);
562  inititer = (int)((SCIP_Real)inititer * (1.0 + 20.0/nodenum));
563  inititer = MAX(inititer, 10);
564  inititer = MIN(inititer, 500);
565  }
566 
567  SCIPdebugMessage("strong branching (reliable=%g, %d/%d cands, %d uninit, maxcands=%d, maxlookahead=%g, maxbdchgs=%d, inititer=%d, iterations:%"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT", basic:%u)\n",
568  reliable, ninitcands, nbranchcands, nuninitcands, maxninitcands, maxlookahead, maxbdchgs, inititer,
569  SCIPgetNStrongbranchLPIterations(scip), maxnsblpiterations, SCIPisLPSolBasic(scip));
570 
571  bestsbcand = -1;
572  bestsbscore = -SCIPinfinity(scip);
573  bestsbfracscore = -SCIPinfinity(scip);
574  bestsbdomainscore = -SCIPinfinity(scip);
575  lookahead = 0.0;
576  for( i = 0; i < ninitcands && lookahead < maxlookahead && nbdchgs + nbdconflicts < maxbdchgs
577  && (i < (int) maxlookahead || SCIPgetNStrongbranchLPIterations(scip) < maxnsblpiterations); ++i )
578  {
579  SCIP_Real down;
580  SCIP_Real up;
581  SCIP_Real downgain;
582  SCIP_Real upgain;
583  SCIP_Bool downvalid;
584  SCIP_Bool upvalid;
585  SCIP_Bool lperror;
586  SCIP_Bool downinf;
587  SCIP_Bool upinf;
588  SCIP_Bool downconflict;
589  SCIP_Bool upconflict;
590 
591  /* get candidate number to initialize */
592  c = initcands[i];
593  assert(!SCIPisFeasIntegral(scip, branchcandssol[c]));
594 
595  SCIPdebugMessage("init pseudo cost (%g/%g) of <%s> at %g (score:%g) with strong branching (%d iterations) -- %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT" iterations\n",
598  SCIPvarGetName(branchcands[c]), branchcandssol[c], initcandscores[i],
599  inititer, SCIPgetNStrongbranchLPIterations(scip), maxnsblpiterations);
600 
601  /* use strong branching on candidate */
602  if( !initstrongbranching )
603  {
604  initstrongbranching = TRUE;
605 
606  SCIP_CALL( SCIPstartStrongbranch(scip, propagate) );
607 
608  /* create arrays for probing-like bound tightening */
609  if( probingbounds )
610  {
611  SCIP_CALL( SCIPallocBufferArray(scip, &newlbs, nvars) );
612  SCIP_CALL( SCIPallocBufferArray(scip, &newubs, nvars) );
613  }
614  }
615 
616  if( propagate )
617  {
618  /* apply strong branching */
619  SCIP_CALL( SCIPgetVarStrongbranchWithPropagation(scip, branchcands[c], branchcandssol[c], lpobjval, inititer,
620  branchruledata->maxproprounds, &down, &up, &downvalid, &upvalid, &downinf, &upinf,
621  &downconflict, &upconflict, &lperror, newlbs, newubs) );
622  }
623  else
624  {
625  /* apply strong branching */
626  SCIP_CALL( SCIPgetVarStrongbranchFrac(scip, branchcands[c], inititer,
627  &down, &up, &downvalid, &upvalid, &downinf, &upinf, &downconflict, &upconflict, &lperror) );
628  }
629 
630  /* check for an error in strong branching */
631  if( lperror )
632  {
633  if( !SCIPisStopped(scip) )
634  {
636  "(node %"SCIP_LONGINT_FORMAT") error in strong branching call for variable <%s> with solution %g\n",
637  SCIPgetNNodes(scip), SCIPvarGetName(branchcands[c]), branchcandssol[c]);
638  }
639  break;
640  }
641 
642  /* Strong branching might have found a new primal solution which updated the cutoff bound. In this case, the
643  * provedbound computed before can be higher than the cutoffbound and the current node can be cut off.
644  * Additionally, also if the value for the current best candidate is valid and exceeds the new cutoff bound,
645  * we want to change the domain of this variable rather than branching on it.
646  */
647  if( SCIPgetBestSol(scip) != NULL && SCIPsolGetIndex(SCIPgetBestSol(scip)) != bestsolidx )
648  {
649  bestsolidx = SCIPsolGetIndex(SCIPgetBestSol(scip));
650 
651  SCIPdebugMessage(" -> strong branching on variable <%s> lead to a new incumbent\n",
652  SCIPvarGetName(branchcands[c]));
653 
654  /* proved bound for current node is larger than new cutoff bound -> cut off current node */
655  if( SCIPisGE(scip, provedbound, SCIPgetCutoffbound(scip)) )
656  {
657  SCIPdebugMessage(" -> node can be cut off (provedbound=%g, cutoff=%g)\n", provedbound, SCIPgetCutoffbound(scip));
658 
659  *result = SCIP_CUTOFF;
660  break; /* terminate initialization loop, because node is infeasible */
661  }
662  /* proved bound for down child of best candidate is larger than cutoff bound -> increase lower bound of best candidate */
663  else if( bestsbcand != -1 )
664  {
665  if( !bestsbdowncutoff && bestsbdownvalid && SCIPisGE(scip, bestsbdown, SCIPgetCutoffbound(scip)) )
666  {
667  bestsbdowncutoff = TRUE;
668 
669  SCIPdebugMessage(" -> valid dual bound for down child of best candidate <%s> is higher than new cutoff bound (valid=%u, bestsbdown=%g, cutoff=%g)\n",
670  SCIPvarGetName(branchcands[bestsbcand]), bestsbdownvalid, bestsbdown, SCIPgetCutoffbound(scip));
671 
672  SCIPdebugMessage(" -> increase lower bound of best candidate <%s> to %g\n",
673  SCIPvarGetName(branchcands[bestsbcand]), SCIPfeasCeil(scip, branchcandssol[bestsbcand]));
674 
675  SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, SCIPvarGetProbindex(branchcands[bestsbcand]),
676  SCIP_BOUNDTYPE_LOWER, SCIPfeasCeil(scip, branchcandssol[bestsbcand])) );
677  }
678  /* proved bound for up child of best candidate is larger than cutoff bound -> decrease upper bound of best candidate */
679  else if( !bestsbupcutoff && bestsbupvalid && SCIPisGE(scip, bestsbup, SCIPgetCutoffbound(scip)) )
680  {
681  bestsbupcutoff = TRUE;
682 
683  SCIPdebugMessage(" -> valid dual bound for up child of best candidate <%s> is higher than new cutoff bound (valid=%u, bestsbup=%g, cutoff=%g)\n",
684  SCIPvarGetName(branchcands[bestsbcand]), bestsbupvalid, bestsbup, SCIPgetCutoffbound(scip));
685 
686  SCIPdebugMessage(" -> decrease upper bound of best candidate <%s> to %g\n",
687  SCIPvarGetName(branchcands[bestsbcand]), SCIPfeasFloor(scip, branchcandssol[bestsbcand]));
688 
689  SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, SCIPvarGetProbindex(branchcands[bestsbcand]),
690  SCIP_BOUNDTYPE_UPPER, SCIPfeasFloor(scip, branchcandssol[bestsbcand])) );
691  }
692  }
693  }
694 
695  /* evaluate strong branching */
696  down = MAX(down, lpobjval);
697  up = MAX(up, lpobjval);
698  downgain = down - lpobjval;
699  upgain = up - lpobjval;
700  assert(!allcolsinlp || exactsolve || !downvalid || downinf == SCIPisGE(scip, down, SCIPgetCutoffbound(scip)));
701  assert(!allcolsinlp || exactsolve || !upvalid || upinf == SCIPisGE(scip, up, SCIPgetCutoffbound(scip)));
702  assert(downinf || !downconflict);
703  assert(upinf || !upconflict);
704 
705  /* @todo: store pseudo cost only for valid bounds? and also if the other sb child was infeasible? */
706  if( !downinf && !upinf )
707  {
708  /* update pseudo cost values */
709  SCIP_CALL( SCIPupdateVarPseudocost(scip, branchcands[c], 0.0-branchcandsfrac[c], downgain, 1.0) );
710  SCIP_CALL( SCIPupdateVarPseudocost(scip, branchcands[c], 1.0-branchcandsfrac[c], upgain, 1.0) );
711  }
712 
713  /* the minimal lower bound of both children is a proved lower bound of the current subtree */
714  if( allcolsinlp && !exactsolve && downvalid && upvalid )
715  {
716  SCIP_Real minbound;
717 
718  minbound = MIN(down, up);
719  provedbound = MAX(provedbound, minbound);
720  assert((downinf && upinf) || SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
721 
722  /* save probing-like bounds detected during strong branching */
723  if( probingbounds )
724  {
725  int v;
726 
727  assert(newlbs != NULL);
728  assert(newubs != NULL);
729 
730  for( v = 0; v < nvars; ++v )
731  {
732  if( SCIPisGT(scip, newlbs[v], SCIPvarGetLbLocal(vars[v])) )
733  {
734  SCIPdebugMessage("better lower bound for variable <%s>: %.9g -> %.9g (by strongbranching on <%s>)\n",
735  SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]), newlbs[v], SCIPvarGetName(branchcands[c]));
736 
737  SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, v,
738  SCIP_BOUNDTYPE_LOWER, newlbs[v]) );
739  }
740  if( SCIPisLT(scip, newubs[v], SCIPvarGetUbLocal(vars[v])) )
741  {
742  SCIPdebugMessage("better upper bound for variable <%s>: %.9g -> %.9g (by strongbranching on <%s>)\n",
743  SCIPvarGetName(vars[v]), SCIPvarGetUbLocal(vars[v]), newubs[v], SCIPvarGetName(branchcands[c]));
744 
745  SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, v,
746  SCIP_BOUNDTYPE_UPPER, newubs[v]) );
747  }
748  }
749 
750  if( nbdchgs + nbdconflicts >= maxbdchgs )
751  break; /* terminate initialization loop, because enough bound changes are performed */
752  }
753  }
754 
755  /* check if there are infeasible roundings */
756  if( downinf || upinf )
757  {
758  assert(allcolsinlp || propagate);
759  assert(!exactsolve);
760 
761  /* if for both infeasibilities, a conflict constraint was created, we don't need to fix the variable by hand,
762  * but better wait for the next propagation round to fix them as an inference, and potentially produce a
763  * cutoff that can be analyzed
764  */
765  if( allowaddcons && downinf == downconflict && upinf == upconflict )
766  {
767  SCIPdebugMessage(" -> variable <%s> is infeasible in %s: conflict constraint added\n",
768  SCIPvarGetName(branchcands[c]),
769  downinf && upinf ? "both directions" : (downinf ? "downward branch" : "upward branch"));
770  *result = SCIP_CONSADDED;
771  nbdconflicts++;
772  if( (downinf && upinf) || (nbdchgs + nbdconflicts >= maxbdchgs) )
773  break; /* terminate initialization loop, because enough roundings are performed or a cutoff was found */
774  }
775  else if( downinf && upinf )
776  {
777  /* both roundings are infeasible -> node is infeasible */
778  SCIPdebugMessage(" -> variable <%s> is infeasible in both directions (conflict: %u/%u)\n",
779  SCIPvarGetName(branchcands[c]), downconflict, upconflict);
780  *result = SCIP_CUTOFF;
781  break; /* terminate initialization loop, because node is infeasible */
782  }
783  else
784  {
785  /* rounding is infeasible in one direction -> round variable in other direction */
786  SCIPdebugMessage(" -> variable <%s> is infeasible in %s branch (conflict: %u/%u)\n",
787  SCIPvarGetName(branchcands[c]), downinf ? "downward" : "upward", downconflict, upconflict);
788  SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, SCIPvarGetProbindex(branchcands[c]),
790  (downinf ? SCIPfeasCeil(scip, branchcandssol[c]) : SCIPfeasFloor(scip, branchcandssol[c]))) );
791  if( nbdchgs + nbdconflicts >= maxbdchgs )
792  break; /* terminate initialization loop, because enough roundings are performed */
793  }
794  }
795  else
796  {
797  SCIP_Real conflictscore;
798  SCIP_Real conflengthscore;
799  SCIP_Real inferencescore;
800  SCIP_Real cutoffscore;
801  SCIP_Real pscostscore;
802  SCIP_Real score;
803 
804  /* check for a better score */
805  conflictscore = SCIPgetVarConflictScore(scip, branchcands[c]);
806  conflengthscore = SCIPgetVarConflictlengthScore(scip, branchcands[c]);
807  inferencescore = SCIPgetVarAvgInferenceScore(scip, branchcands[c]);
808  cutoffscore = SCIPgetVarAvgCutoffScore(scip, branchcands[c]);
809  pscostscore = SCIPgetBranchScore(scip, branchcands[c], downgain, upgain);
810  score = calcScore(scip, branchruledata, conflictscore, avgconflictscore, conflengthscore, avgconflengthscore,
811  inferencescore, avginferencescore, cutoffscore, avgcutoffscore, pscostscore, avgpscostscore, branchcandsfrac[c]);
812 
813  if( SCIPisSumGE(scip, score, bestsbscore) )
814  {
815  SCIP_Real fracscore;
816  SCIP_Real domainscore;
817 
818  fracscore = MIN(branchcandsfrac[c], 1.0 - branchcandsfrac[c]);
819  domainscore = -(SCIPvarGetUbLocal(branchcands[c]) - SCIPvarGetLbLocal(branchcands[c]));
820  if( SCIPisSumGT(scip, score, bestsbscore)
821  || SCIPisSumGT(scip, fracscore, bestsbfracscore)
822  || (SCIPisSumGE(scip, fracscore, bestsbfracscore) && domainscore > bestsbdomainscore) )
823  {
824  bestsbcand = c;
825  bestsbscore = score;
826  bestsbdown = down;
827  bestsbup = up;
828  bestsbdownvalid = downvalid;
829  bestsbupvalid = upvalid;
830  bestsbdowncutoff = FALSE;
831  bestsbupcutoff = FALSE;
832  bestsbfracscore = fracscore;
833  bestsbdomainscore = domainscore;
834  lookahead = 0.0;
835  }
836  else
837  lookahead += 0.5;
838  }
839  else
840  lookahead += 1.0;
841 
842  SCIPdebugMessage(" -> variable <%s> (solval=%g, down=%g (%+g,valid=%u), up=%g (%+g,valid=%u), score=%g/ %g/%g %g/%g -> %g)\n",
843  SCIPvarGetName(branchcands[c]), branchcandssol[c], down, downgain, downvalid, up, upgain, upvalid,
844  pscostscore, conflictscore, conflengthscore, inferencescore, cutoffscore, score);
845  }
846  }
847 #ifdef SCIP_DEBUG
848  if( bestsbcand >= 0 )
849  {
850  SCIPdebugMessage(" -> best: <%s> (%g / %g / %g), lookahead=%g/%g\n",
851  SCIPvarGetName(branchcands[bestsbcand]), bestsbscore, bestsbfracscore, bestsbdomainscore,
852  lookahead, maxlookahead);
853  }
854 #endif
855 
856  if( initstrongbranching )
857  {
858  if( probingbounds )
859  {
860  assert(newlbs != NULL);
861  assert(newubs != NULL);
862 
863  SCIPfreeBufferArray(scip, &newubs);
864  SCIPfreeBufferArray(scip, &newlbs);
865  }
866 
868 
870  {
871  assert(SCIPhasCurrentNodeLP(scip));
872  *result = SCIP_CUTOFF;
873  }
874  }
875 
876  if( *result != SCIP_CUTOFF )
877  {
878  /* get the score of the best uninitialized strong branching candidate */
879  if( i < ninitcands )
880  bestuninitsbscore = initcandscores[i];
881  else
882  bestuninitsbscore = -SCIPinfinity(scip);
883 
884  /* if the best pseudo cost candidate is better than the best uninitialized strong branching candidate,
885  * compare it to the best initialized strong branching candidate
886  */
887  if( bestpsscore > bestuninitsbscore && SCIPisSumGT(scip, bestpsscore, bestsbscore) )
888  {
889  bestcand = bestpscand;
890  bestisstrongbranch = FALSE;
891  }
892  else if( bestsbcand >= 0 )
893  {
894  bestcand = bestsbcand;
895  bestisstrongbranch = TRUE;
896  }
897  else
898  {
899  /* no candidate was initialized, and the best score is the one of the first candidate in the initialization
900  * queue
901  */
902  assert(ninitcands >= 1);
903  bestcand = initcands[0];
904  bestisstrongbranch = FALSE;
905  }
906  }
907 
908  /* apply domain reductions */
909  if( nbdchgs > 0 )
910  {
911  if( *result != SCIP_CUTOFF )
912  {
913  SCIP_CALL( applyBdchgs(scip, vars, bdchginds, bdchgtypes, bdchgbounds, nbdchgs, result) );
914  if( *result != SCIP_CUTOFF )
915  *result = SCIP_REDUCEDDOM;
916  }
917  freeBdchgs(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs);
918  }
919 
920  /* free buffer for the unreliable candidates */
921  SCIPfreeBufferArray(scip, &initcandscores);
922  SCIPfreeBufferArray(scip, &initcands);
923  }
924 
925  /* if no domain could be reduced, create the branching */
926  if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED )
927  {
928  SCIP_NODE* downchild;
929  SCIP_NODE* upchild;
930  SCIP_VAR* var;
931  SCIP_Real proveddown;
932  SCIP_Real provedup;
933 
934  assert(*result == SCIP_DIDNOTRUN);
935  assert(0 <= bestcand && bestcand < nbranchcands);
936  assert(!SCIPisFeasIntegral(scip, branchcandssol[bestcand]));
937  assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
938  assert(!bestsbdowncutoff && !bestsbupcutoff);
939 
940  var = branchcands[bestcand];
941 
942  /* perform the branching */
943  SCIPdebugMessage(" -> %d (%d) cands, sel cand %d: var <%s> (sol=%g, down=%g (%+g), up=%g (%+g), sb=%u, psc=%g/%g [%g])\n",
944  nbranchcands, ninitcands, bestcand, SCIPvarGetName(var), branchcandssol[bestcand],
945  bestsbdown, bestsbdown - lpobjval, bestsbup, bestsbup - lpobjval, bestisstrongbranch,
948  SCIPgetVarPseudocostScoreCurrentRun(scip, var, branchcandssol[bestcand]));
949  SCIP_CALL( SCIPbranchVar(scip, var, &downchild, NULL, &upchild) );
950  assert(downchild != NULL);
951  assert(upchild != NULL);
952 
953  /* calculate proved lower bounds for children */
954  proveddown = provedbound;
955  provedup = provedbound;
956  if( bestisstrongbranch )
957  {
958  if( bestsbdownvalid )
959  proveddown = MAX(provedbound, bestsbdown);
960  if( bestsbupvalid )
961  provedup = MAX(provedbound, bestsbup);
962  }
963 
964  /* update the lower bounds in the children */
965  if( allcolsinlp && !exactsolve )
966  {
967  assert(SCIPisLT(scip, proveddown, SCIPgetCutoffbound(scip)));
968  assert(SCIPisLT(scip, provedup, SCIPgetCutoffbound(scip)));
969  SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, proveddown) );
970  SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, provedup) );
971  }
972  SCIPdebugMessage(" -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
973  SCIPdebugMessage(" -> up child's lowerbound : %g\n", SCIPnodeGetLowerbound(upchild));
974 
976 
977  *result = SCIP_BRANCHED;
978  }
979  return SCIP_OKAY;
980 }
981 
982 
983 /*
984  * Callback methods
985  */
986 
987 /** copy method for branchrule plugins (called when SCIP copies plugins) */
988 static
989 SCIP_DECL_BRANCHCOPY(branchCopyRelpscost)
990 { /*lint --e{715}*/
991  assert(scip != NULL);
992  assert(branchrule != NULL);
993  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
994 
995  /* call inclusion method of branchrule */
997 
998  return SCIP_OKAY;
999 }
1000 
1001 /** destructor of branching rule to free user data (called when SCIP is exiting) */
1002 static
1003 SCIP_DECL_BRANCHFREE(branchFreeRelpscost)
1004 { /*lint --e{715}*/
1005  SCIP_BRANCHRULEDATA* branchruledata;
1006 
1007  /* free branching rule data */
1008  branchruledata = SCIPbranchruleGetData(branchrule);
1009  SCIPfreeMemory(scip, &branchruledata);
1010  SCIPbranchruleSetData(branchrule, NULL);
1011 
1012  return SCIP_OKAY;
1013 }
1014 
1015 
1016 /** branching execution method for fractional LP solutions */
1017 static
1018 SCIP_DECL_BRANCHEXECLP(branchExeclpRelpscost)
1019 { /*lint --e{715}*/
1020  SCIP_VAR** tmplpcands;
1021  SCIP_VAR** lpcands;
1022  SCIP_Real* tmplpcandssol;
1023  SCIP_Real* lpcandssol;
1024  SCIP_Real* tmplpcandsfrac;
1025  SCIP_Real* lpcandsfrac;
1026  int nlpcands;
1027 
1028  assert(branchrule != NULL);
1029  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
1030  assert(scip != NULL);
1031  assert(result != NULL);
1032 
1033  SCIPdebugMessage("Execlp method of relpscost branching\n");
1034 
1035  /* get branching candidates */
1036  SCIP_CALL( SCIPgetLPBranchCands(scip, &tmplpcands, &tmplpcandssol, &tmplpcandsfrac, NULL, &nlpcands, NULL) );
1037  assert(nlpcands > 0);
1038 
1039  /* copy LP banching candidates and solution values, because they will be updated w.r.t. the strong branching LP
1040  * solution
1041  */
1042  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcands, tmplpcands, nlpcands) );
1043  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandssol, tmplpcandssol, nlpcands) );
1044  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandsfrac, tmplpcandsfrac, nlpcands) );
1045 
1046  /* execute branching rule */
1047  SCIP_CALL( execRelpscost(scip, branchrule, allowaddcons, lpcands, lpcandssol, lpcandsfrac, nlpcands, result) );
1048 
1049  SCIPfreeBufferArray(scip, &lpcandsfrac);
1050  SCIPfreeBufferArray(scip, &lpcandssol);
1051  SCIPfreeBufferArray(scip, &lpcands);
1052 
1053  return SCIP_OKAY;
1054 }
1055 
1056 
1057 /*
1058  * branching specific interface methods
1059  */
1060 
1061 /** creates the reliable pseudo cost branching rule and includes it in SCIP */
1063  SCIP* scip /**< SCIP data structure */
1064  )
1065 {
1066  SCIP_BRANCHRULEDATA* branchruledata;
1067  SCIP_BRANCHRULE* branchrule;
1068 
1069  /* create relpscost branching rule data */
1070  SCIP_CALL( SCIPallocMemory(scip, &branchruledata) );
1071 
1072  /* include branching rule */
1074  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
1075 
1076  assert(branchrule != NULL);
1077 
1078  /* set non-fundamental callbacks via specific setter functions*/
1079  SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyRelpscost) );
1080  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeRelpscost) );
1081  SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpRelpscost) );
1082 
1083  /* relpscost branching rule parameters */
1085  "branching/relpscost/conflictweight",
1086  "weight in score calculations for conflict score",
1087  &branchruledata->conflictweight, TRUE, DEFAULT_CONFLICTWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
1089  "branching/relpscost/conflictlengthweight",
1090  "weight in score calculations for conflict length score",
1091  &branchruledata->conflengthweight, TRUE, DEFAULT_CONFLENGTHWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
1093  "branching/relpscost/inferenceweight",
1094  "weight in score calculations for inference score",
1095  &branchruledata->inferenceweight, TRUE, DEFAULT_INFERENCEWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
1097  "branching/relpscost/cutoffweight",
1098  "weight in score calculations for cutoff score",
1099  &branchruledata->cutoffweight, TRUE, DEFAULT_CUTOFFWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
1101  "branching/relpscost/pscostweight",
1102  "weight in score calculations for pseudo cost score",
1103  &branchruledata->pscostweight, TRUE, DEFAULT_PSCOSTWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
1105  "branching/relpscost/minreliable",
1106  "minimal value for minimum pseudo cost size to regard pseudo cost value as reliable",
1107  &branchruledata->minreliable, TRUE, DEFAULT_MINRELIABLE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
1109  "branching/relpscost/maxreliable",
1110  "maximal value for minimum pseudo cost size to regard pseudo cost value as reliable",
1111  &branchruledata->maxreliable, TRUE, DEFAULT_MAXRELIABLE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
1113  "branching/relpscost/sbiterquot",
1114  "maximal fraction of strong branching LP iterations compared to node relaxation LP iterations",
1115  &branchruledata->sbiterquot, FALSE, DEFAULT_SBITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
1116  SCIP_CALL( SCIPaddIntParam(scip,
1117  "branching/relpscost/sbiterofs",
1118  "additional number of allowed strong branching LP iterations",
1119  &branchruledata->sbiterofs, FALSE, DEFAULT_SBITEROFS, 0, INT_MAX, NULL, NULL) );
1120  SCIP_CALL( SCIPaddIntParam(scip,
1121  "branching/relpscost/maxlookahead",
1122  "maximal number of further variables evaluated without better score",
1123  &branchruledata->maxlookahead, TRUE, DEFAULT_MAXLOOKAHEAD, 1, INT_MAX, NULL, NULL) );
1124  SCIP_CALL( SCIPaddIntParam(scip,
1125  "branching/relpscost/initcand",
1126  "maximal number of candidates initialized with strong branching per node",
1127  &branchruledata->initcand, FALSE, DEFAULT_INITCAND, 0, INT_MAX, NULL, NULL) );
1128  SCIP_CALL( SCIPaddIntParam(scip,
1129  "branching/relpscost/inititer",
1130  "iteration limit for strong branching initializations of pseudo cost entries (0: auto)",
1131  &branchruledata->inititer, FALSE, DEFAULT_INITITER, 0, INT_MAX, NULL, NULL) );
1132  SCIP_CALL( SCIPaddIntParam(scip,
1133  "branching/relpscost/maxbdchgs",
1134  "maximal number of bound tightenings before the node is reevaluated (-1: unlimited)",
1135  &branchruledata->maxbdchgs, TRUE, DEFAULT_MAXBDCHGS, -1, INT_MAX, NULL, NULL) );
1136  SCIP_CALL( SCIPaddIntParam(scip,
1137  "branching/relpscost/maxproprounds",
1138  "maximum number of propagation rounds to be performed during strong branching before solving the LP (-1: no limit, -2: parameter settings)",
1139  &branchruledata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
1141  "branching/relpscost/probingbounds",
1142  "should valid bounds be identified in a probing-like fashion during strong branching (only with propagation)?",
1143  &branchruledata->probingbounds, TRUE, DEFAULT_PROBINGBOUNDS, NULL, NULL) );
1144 
1145 
1146  return SCIP_OKAY;
1147 }
1148 
1149 /** execution reliability pseudo cost branching with the given branching candidates */
1151  SCIP* scip, /**< SCIP data structure */
1152  SCIP_Bool allowaddcons, /**< is the branching rule allowed to add constraints to the current node
1153  * in order to cut off the current solution instead of creating a branching? */
1154  SCIP_VAR** branchcands, /**< branching candidates */
1155  SCIP_Real* branchcandssol, /**< solution value for the branching candidates */
1156  SCIP_Real* branchcandsfrac, /**< fractional part of the branching candidates */
1157  int nbranchcands, /**< number of branching candidates */
1158  SCIP_RESULT* result /**< pointer to the result of the execution */
1159  )
1160 {
1161  SCIP_BRANCHRULE* branchrule;
1162 
1163  assert(scip != NULL);
1164  assert(result != NULL);
1165 
1166  /* find branching rule */
1167  branchrule = SCIPfindBranchrule(scip, BRANCHRULE_NAME);
1168  assert(branchrule != NULL);
1169 
1170  /* execute branching rule */
1171  SCIP_CALL( execRelpscost(scip, branchrule, allowaddcons, branchcands, branchcandssol, branchcandsfrac, nbranchcands, result) );
1172 
1173  return SCIP_OKAY;
1174 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:30002
reliable pseudo costs branching rule
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10071
SCIP_Real SCIPgetAvgCutoffScore(SCIP *scip)
Definition: scip.c:35823
#define DEFAULT_PSCOSTWEIGHT
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
static void freeBdchgs(SCIP *scip, int **bdchginds, SCIP_BOUNDTYPE **bdchgtypes, SCIP_Real **bdchgbounds, int *nbdchgs)
#define BRANCHRULE_MAXDEPTH
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip.c:30598
#define DEFAULT_MAXBDCHGS
SCIP_Bool SCIPisSumGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38593
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10026
#define NULL
Definition: lpi_spx.cpp:129
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:16426
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1111
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:38803
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:43
#define BRANCHRULE_MAXBOUNDDIST
#define DEFAULT_SBITERQUOT
#define FALSE
Definition: def.h:52
SCIP_RETCODE SCIPstartStrongbranch(SCIP *scip, SCIP_Bool enablepropagation)
Definition: scip.c:16196
#define TRUE
Definition: def.h:51
SCIP_Real SCIPgetAvgConflictScore(SCIP *scip)
Definition: scip.c:35601
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPupdateVarPseudocost(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: scip.c:21163
SCIP_Longint SCIPgetVarStrongbranchNode(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:17497
#define DEFAULT_INFERENCEWEIGHT
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1843
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:38779
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:35229
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38574
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:24136
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip.c:7721
SCIP_Longint SCIPgetNDualResolveLPIterations(SCIP *scip)
Definition: scip.c:34406
#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:16424
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:19214
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip.c:7737
SCIP_Longint SCIPgetNNodeInitLPIterations(SCIP *scip)
Definition: scip.c:34478
static SCIP_DECL_BRANCHFREE(branchFreeRelpscost)
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:19215
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:24179
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:38815
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:24526
SCIP_Real SCIPgetAvgInferenceScore(SCIP *scip)
Definition: scip.c:35737
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition: scip.c:11735
#define DEFAULT_INITITER
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:3388
SCIP_Real SCIPgetVarPseudocostCountCurrentRun(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: scip.c:21323
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:3414
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip.c:7819
#define BRANCHRULE_NAME
SCIP_Real SCIPgetAvgConflictlengthScore(SCIP *scip)
Definition: scip.c:35651
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38273
#define BRANCHRULE_PRIORITY
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:7684
SCIP_Longint SCIPgetNDualResolveLPs(SCIP *scip)
Definition: scip.c:34386
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:19159
static SCIP_RETCODE applyBdchgs(SCIP *scip, SCIP_VAR **vars, int *bdchginds, SCIP_BOUNDTYPE *bdchgtypes, SCIP_Real *bdchgbounds, int nbdchgs, SCIP_RESULT *result)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:19221
SCIP_Real SCIPgetVarConflictlengthScore(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:21524
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_Bool *downinf, SCIP_Bool *upinf, SCIP_Bool *downconflict, SCIP_Bool *upconflict, SCIP_Bool *lperror, SCIP_Real *newlbs, SCIP_Real *newubs)
Definition: scip.c:16847
SCIP_Longint SCIPgetNStrongbranchLPIterations(SCIP *scip)
Definition: scip.c:34550
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1731
static SCIP_Real calcScore(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_Real conflictscore, SCIP_Real avgconflictscore, SCIP_Real conflengthscore, SCIP_Real avgconflengthscore, SCIP_Real inferencescore, SCIP_Real avginferencescore, SCIP_Real cutoffscore, SCIP_Real avgcutoffscore, SCIP_Real pscostscore, SCIP_Real avgpscostscore, SCIP_Real frac)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:38349
#define SCIP_CALL(x)
Definition: def.h:258
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:24051
SCIP_Real SCIPgetVarPseudocostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real solval)
Definition: scip.c:21348
#define DEFAULT_SBITEROFS
#define DEFAULT_CUTOFFWEIGHT
#define DEFAULT_CONFLICTWEIGHT
SCIP_Longint SCIPgetNRootStrongbranchLPIterations(SCIP *scip)
Definition: scip.c:34586
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38311
static SCIP_RETCODE addBdchg(SCIP *scip, int **bdchginds, SCIP_BOUNDTYPE **bdchgtypes, SCIP_Real **bdchgbounds, int *nbdchgs, int ind, SCIP_BOUNDTYPE type, SCIP_Real bound)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18371
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:16436
#define SCIP_Bool
Definition: def.h:49
static SCIP_DECL_BRANCHEXECLP(branchExeclpRelpscost)
static SCIP_DECL_BRANCHCOPY(branchCopyRelpscost)
#define DEFAULT_CONFLENGTHWEIGHT
SCIP_Real SCIPgetVarConflictScore(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:21466
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:19222
#define DEFAULT_MINRELIABLE
#define MAX(x, y)
Definition: tclique_def.h:75
#define DEFAULT_MAXPROPROUNDS
static SCIP_RETCODE execRelpscost(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_Bool allowaddcons, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsfrac, int nbranchcands, SCIP_RESULT *result)
#define DEFAULT_INITCAND
SCIP_Real SCIPgetVarPseudocostCurrentRun(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: scip.c:21271
#define DEFAULT_MAXLOOKAHEAD
SCIP_RETCODE SCIPexecRelpscostBranching(SCIP *scip, SCIP_Bool allowaddcons, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsfrac, int nbranchcands, SCIP_RESULT *result)
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition: sol.c:2223
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1256
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38330
#define SCIP_REAL_MAX
Definition: def.h:124
#define SCIP_REAL_MIN
Definition: def.h:125
SCIP_Real SCIPgetVarPseudocostScoreCurrentRun(SCIP *scip, SCIP_VAR *var, SCIP_Real solval)
Definition: scip.c:21384
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:19176
SCIP_Real SCIPgetVarAvgCutoffScore(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:21863
SCIP_RETCODE SCIPincludeBranchruleRelpscost(SCIP *scip)
#define DEFAULT_PROBINGBOUNDS
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1721
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: scip.c:30455
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:19217
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16072
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:7867
#define SCIP_Real
Definition: def.h:123
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18477
#define MIN(x, y)
Definition: memory.c:59
#define SCIP_INVALID
Definition: def.h:142
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:37733
#define SCIP_Longint
Definition: def.h:107
SCIP_RETCODE SCIPendStrongbranch(SCIP *scip)
Definition: scip.c:16252
#define BRANCHRULE_DESC
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:6719
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip.c:24544
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:17453
SCIP_Real SCIPgetAvgPseudocostScore(SCIP *scip)
Definition: scip.c:35553
SCIP_Real SCIPgetVarAvgInferenceScore(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:21682
SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
Definition: scip.c:34442
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:32531
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, 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: scip.c:3470
#define DEFAULT_MAXRELIABLE
SCIP_Longint SCIPgetNNodeInitLPs(SCIP *scip)
Definition: scip.c:34460
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:34065
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip.c:998