Scippy

GCG

Branch-and-Price & Column Generation for Everyone

branch_bpstrong.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file branch_bpstrong.c
29  * @ingroup BRANCHINGRULES
30  * @brief generic branch-and-price strong branching heuristics
31  * @author Oliver Gaul
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 /*#define SCIP_DEBUG*/
36 #include <assert.h>
37 
38 #include "branch_bpstrong.h"
39 #include "type_branchgcg.h"
40 #include "gcg.h"
41 #include "branch_orig.h"
42 
43 #include <string.h>
44 
45 #include "gcg.h"
46 #include "branch_relpsprob.h"
47 #include "cons_integralorig.h"
48 #include "cons_masterbranch.h"
49 #include "cons_origbranch.h"
50 #include "relax_gcg.h"
51 #include "pricer_gcg.h"
52 #include "type_branchgcg.h"
53 
54 #include "scip/cons_linear.h"
55 #include "scip/scipdefplugins.h"
56 #include "scip/var.h"
57 
58 #define BRANCHRULE_NAME "bpstrong" /**< name of branching rule */
59 #define BRANCHRULE_DESC "strong branching for branch-and-price" /**< short description of branching rule */
60 #define BRANCHRULE_PRIORITY -536870912 /**< priority of this branching rule */
61 #define BRANCHRULE_MAXDEPTH 0 /**< maximal depth level of the branching rule */
62 #define BRANCHRULE_MAXBOUNDDIST 0.0 /**< maximal relative distance from current node's
63  * dual bound to primal bound compared to best node's
64  * dual bound for applying branching */
65 #define DEFAULT_ENFORCEBYCONS FALSE
66 #define DEFAULT_MOSTFRAC FALSE
67 #define DEFAULT_USEPSEUDO TRUE
68 #define DEFAULT_USEPSSTRONG FALSE
69 
70 #define DEFAULT_USESTRONG FALSE
71 #define DEFAULT_STRONGLITE FALSE
72 #define DEFAULT_STRONGTRAIN FALSE
73 #define DEFAULT_IMMEDIATEINF TRUE
74 #define DEFAULT_MAXSBLPITERS INT_MAX
75 #define DEFAULT_MAXSBPRICEROUNDS INT_MAX
76 
77 #define DEFAULT_RFUSEPSEUDOCOSTS TRUE
78 #define DEFAULT_RFUSEMOSTFRAC FALSE
79 
80 #define DEFAULT_REEVALAGE 1
81 #define DEFAULT_MINCOLGENCANDS 4
82 #define DEFAULT_HISTWEIGHT 0.5
83 #define DEFAULT_MAXLOOKAHEAD 8
84 #define DEFAULT_LOOKAHEADSCALES 0.5
85 #define DEFAULT_MINPHASE0DEPTH 0
86 #define DEFAULT_MAXPHASE1DEPTH 4
87 #define DEFAULT_MAXPHASE2DEPTH 3
88 #define DEFAULT_DEPTHLOGWEIGHT 0.5
89 #define DEFAULT_DEPTHLOGBASE 3.5
90 #define DEFAULT_DEPTHLOGPHASE0FRAC 0
91 #define DEFAULT_DEPTHLOGPHASE2FRAC 0.75
92 
93 #define DEFAULT_CLOSEPERCENTAGE 0.90
94 #define DEFAULT_MAXCONSECHEURCLOSE 4
95 
96 #define DEFAULT_SBPSEUDOCOSTWEIGHT 1
97 
98 #define DEFAULT_PHASE1RELIABLE INT_MAX
99 #define DEFAULT_PHASE2RELIABLE INT_MAX
100 
101 #define DEFAULT_FORCEP0 FALSE
102 
103 #define ORIG 0
104 #define RYANFOSTER 1
105 #define GENERIC 2
106 
107 
108 /** branching data for branching decisions (for Ryan-Foster branching) */
110 {
111  SCIP_VAR* var1; /**< first original variable on which the branching is done */
112  SCIP_VAR* var2; /**< second original variable on which the branching is done */
113  SCIP_Bool same; /**< should each master var contain either both or none of the vars? */
114  int blocknr; /**< number of the block in which branching was performed */
115  SCIP_CONS* pricecons; /**< constraint enforcing the branching restriction in the pricing
116  problem */
117 };
118 
119 /* stores candidates and their corresponding index to insert them into a hashtable */
120 typedef struct VarTuple{
121  SCIP_VAR* var1;
122  SCIP_VAR* var2;
123  int index;
124 } VarTuple;
125 
126 /** branching rule data */
128 {
129  int lastcand; /**< last evaluated candidate of last branching rule execution */
130  int nvars; /**< the number of candidates currently in the hashtable */
131  int maxvars; /**< the maximal number of cands that were in the hashtable at the same
132  * time */
133  int maxcands; /**< (realistically) the maximum total amount of candidates */
134  SCIP_HASHTABLE* candhashtable; /**< hashtable mapping candidates to their index */
135  VarTuple **vartuples; /**< all VarTuples that are in candhashtable */
136  SCIP_Real *score; /**< the candidates' last scores */
137  int *uniqueblockflags; /**< flags assigned by assignUniqueBlockFlags() */
138  SCIP_Real *strongbranchscore; /**< the candidates' last scores from strong branching with column
139  * generation */
140  SCIP_Bool *sbscoreisrecent; /**< was the score saved in strongbranchscore computed in a parent of
141  * the current node where all node on the path to the parent were
142  * created for domain reduction due to infeasibility? */
143  int *lastevalnode; /**< the last node at which the candidates were evaluated */
144 
145  int nphase1lps; /**< number of phase 1 lps solved */
146  int nphase2lps; /**< number of phase 2 lps solved */
147  SCIP_Longint nsblpiterations; /**< total number of strong branching lp iterations during phase 1 */
148  int nsbpricerounds; /**< total number of strong branching pricing rounds */
149 
150  int initiator; /**< the identifier of the branching rule that initiated strong
151  * branching */
152  SCIP_BRANCHRULE* initiatorbranchrule; /**< the branching rule that initiated strong branching */
153 
154  SCIP_Bool mostfrac; /**< should most infeasible/fractional branching be used in phase 0? */
155  SCIP_Bool usepseudocosts; /**< should pseudocost branching be used in phase 0? */
156 
157  SCIP_Bool usestronglite; /**< should strong branching use column generation during variable
158  * evaluation? */
159  SCIP_Bool usestrongtrain; /**< should strong branching run as precise as possible
160  * (to generate more valuable training data, currently not
161  * implemented)? */
162  SCIP_Bool immediateinf; /**< should infeasibility detected during strong branching be handled
163  * immediately, or only if the variable is selected? */
164  SCIP_Longint maxsblpiters; /**< maximum number of strong branching lp iterations, set to 2*avg lp
165  * iterations if <= 0 */
166  int maxsbpricerounds; /**< maximum number of strong branching pricing rounds, set to 2*avg lp
167  * iterations if <= 0 */
168  int reevalage; /**< how many times can bounds be changed due to infeasibility during
169  * strong branching until an already evaluated variable needs to be
170  * reevaluated? */
171  int mincolgencands; /**< minimum number of variables for phase 2 to be executed, otherwise
172  * the best candidate from phase 1 will be chosen */
173 
174  int minphase0depth; /**< minimum tree depth from which on phase 0 is performed (~ hybrid
175  * branching) */
176  int maxphase1depth; /**< maximum tree depth up to which phase 1 is performed (~ hybrid
177  * branching) */
178  int maxphase2depth; /**< maximum tree depth up to which phase 2 is performed (~ hybrid
179  * branching) */
180 
181  int minphase0outcands; /**< minimum number of output candidates from phase 0 */
182  int maxphase0outcands; /**< maximum number of output candidates from phase 0 */
183  SCIP_Real maxphase0outcandsfrac; /**< maximum number of output candidates from phase 0 as fraction of
184  * total cands */
185  SCIP_Real phase1gapweight; /**< how much impact should the node gap have on the number of
186  * precisely evaluated candidates in phase 1? */
187 
188  int minphase1outcands; /**< minimum number of output candidates from phase 1 */
189  int maxphase1outcands; /**< maximum number of output candidates from phase 1 */
190  SCIP_Real maxphase1outcandsfrac; /**< maximum number of output candidates from phase 0 as fraction of
191  * phase 1 candidates */
192  SCIP_Real phase2gapweight; /**< how much impact should the node gap have on the number of
193  * precisely evaluated candidates in phase 2? */
194  int maxlookahead; /**< maximum number of non-improving candidates until phase 2 is
195  * stopped */
196  SCIP_Real lookaheadscales; /**< how much should the look ahead scale with the overall evaluation
197  * effort? (0 = not at all, 1 = fully) */
198 
199  SCIP_Real histweight; /**< how many candidates should be chosen based on historical strong
200  * branching scores as opposed to current heuristic scores in phase 0
201  * (e.g. 0.5 = 50%)? */
202 
203  SCIP_Real closepercentage; /**< what percentage of the strong branching score of the candidate
204  * that was selected does the best candidate according to the phase 0
205  * heuristic need to have to be considered close? */
206  int consecheurclose; /**< how many times in a row the best candidate according to the phase
207  * 0 heuristic was close to that selected by SBw/CG */
208  int maxconsecheurclose; /**< how many times in a row can the heuristic be close before strong
209  * branching is stopped? */
210 
211  SCIP_Bool done; /**< has any of the permanent stopping criteria been reached? */
212 
213  SCIP_Real sbpseudocostweight; /**< with how much weight should strong branching scores be considered
214  * for pseudocost scores? */
215 
216  int phase1reliable; /**< min count of pseudocost scores for a variable to be considered
217  * reliable in phase 1 (~ reliability branching) */
218  int phase2reliable; /**< min count of pseudocost scores for a variable to be considered
219  * reliable in phase 2 (~ reliability branching) */
220 
221  SCIP_Bool forcephase0; /**< should phase 0 be performed even if the number of input candidates
222  * is already lower or equal to the number of output candidates? */
223 
224  SCIP_Bool initialized; /**< has the branching rule been initialized? */
225 };
226 
227 /* needed for compare_function (for now) */
228 SCIP_BRANCHRULEDATA* this_branchruledata;
229 
230 /*
231  * Hash functions
232  */
233 
234 /** gets the hash key of a variable tuple */
235 static
236 SCIP_DECL_HASHGETKEY(hashGetKeyVars)
237 {
238  VarTuple* vars;
239 
240  vars = (VarTuple*)elem;
241  assert(vars != NULL);
242 
243  /* the key of a variable tuple is the variable tuple itself */
244  return vars;
245 }
246 
247 /** returns TRUE iff both variable tuples contain the same variables (ignoring order) */
248 static
249 SCIP_DECL_HASHKEYEQ(hashKeyEqVars)
250 {
251  VarTuple* vars1;
252  VarTuple* vars2;
253 
254  vars1 = (VarTuple*)key1;
255  vars2 = (VarTuple*)key2;
256  assert(vars1 != NULL);
257  assert(vars2 != NULL);
258 
259  /* check if first variable is equal */
260  if( SCIPvarGetIndex(vars1->var1) != SCIPvarGetIndex(vars2->var1) )
261  return FALSE;
262 
263  /* second variable might be NULL */
264  if( (vars1->var2 == NULL) && (vars2->var2 == NULL) )
265  return TRUE;
266 
267  if( (vars1->var2 == NULL) || (vars2->var2 == NULL) )
268  return FALSE;
269 
270  /* check if second variable is equal */
271  if( SCIPvarGetIndex(vars1->var2) != SCIPvarGetIndex(vars2->var2) )
272  return FALSE;
273 
274  return TRUE;
275 }
276 
277 static
278 SCIP_DECL_HASHKEYVAL(hashKeyValVars)
279 {
280  VarTuple* vars;
281  unsigned int hashvalue;
282  SCIP_VAR* var1;
283  SCIP_VAR* var2;
284 
285  vars = (VarTuple*)key;
286  assert(vars != NULL);
287 
288  var1 = vars->var1;
289  var2 = vars->var2;
290 
291  /* return hashvalue of indices */
292  if( var2 == NULL )
293  hashvalue = SCIPhashSignature64( SCIPvarGetIndex(var1) );
294  else
295  hashvalue = SCIPhashTwo( MIN( SCIPvarGetIndex(var1), SCIPvarGetIndex(var2) ), MAX( SCIPvarGetIndex(var1), SCIPvarGetIndex(var2) ) );
296 
297  return hashvalue;
298 }
299 
300 /* calculates the number of needed candidates based on the min and max number of candidates as well as the node gap */
301 static
303  SCIP* scip, /**< scip data structure */
304  SCIP_BRANCHRULEDATA* branchruledata, /**< strong branching branchruledata */
305  SCIP_Real nodegap, /**< node gap in current focus node */
306  int phase, /**< phase we are calculating this for */
307  int ncands /**< number of input candidates for the phase */
308 )
309 {
310  int min;
311  int max;
312  int dif;
313  SCIP_Real gapweight;
314  SCIP_Real candfrac;
315 
316  if( phase == 0 )
317  {
318  min = branchruledata->minphase0outcands;
319  max = branchruledata->maxphase0outcands;
320  candfrac = branchruledata->maxphase0outcandsfrac;
321  gapweight = branchruledata->phase1gapweight;
322  }
323  else
324  {
325  min = branchruledata->minphase1outcands;
326  max = branchruledata->maxphase1outcands;
327  candfrac = branchruledata->maxphase1outcandsfrac;
328  gapweight = branchruledata->phase2gapweight;
329  }
330 
331  dif = max-min;
332 
333  assert(min >= 1);
334 
335  return MIN( candfrac*ncands,
336  min + (int) SCIPceil(scip, MIN( dif, dif * nodegap * gapweight + dif * (1-gapweight) )) );
337 }
338 
339 /* assigns a flag to the given branching candidate based on the block it is in
340  *
341  * return 1: integer variables belonging to a unique block with fractional value
342  * return 0: variables that belong to no block but were directly transferred to the
343  * master problem and which have a fractional value in the current solution
344  * return -1: neither
345  */
346 static
348  SCIP* scip, /**< SCIP data structure */
349  SCIP_VAR* branchcand /**< branching candidate to be considered */
350 )
351 {
352  assert(GCGvarIsOriginal(branchcand));
353 
354  for ( int iter = 0; iter <= 1; iter++ )
355  {
356  /* continue if variable belongs to a block in second iteration*/
357  if (iter == 0)
358  {
359  /* variable belongs to no block */
360  if ( GCGvarGetBlock(branchcand) == -1 )
361  continue;
362 
363  /* block is not unique (non-linking variables) */
364  if ( !GCGoriginalVarIsLinking(branchcand) && GCGgetNIdenticalBlocks(scip, GCGvarGetBlock(branchcand)) != 1 )
365  continue;
366 
367  /* check that blocks of linking variable are unique */
368  if ( GCGoriginalVarIsLinking(branchcand) )
369  {
370  int nvarblocks;
371  int *varblocks;
372  SCIP_Bool unique;
373  int j;
374 
375  nvarblocks = GCGlinkingVarGetNBlocks(branchcand);
376  SCIP_CALL( SCIPallocBufferArray(scip, &varblocks, nvarblocks) );
377  SCIP_CALL( GCGlinkingVarGetBlocks(branchcand, nvarblocks, varblocks) );
378 
379  unique = TRUE;
380  for ( j = 0; j < nvarblocks; ++j )
381  if ( GCGgetNIdenticalBlocks(scip, varblocks[j]) != 1 )
382  unique = FALSE;
383 
384  SCIPfreeBufferArray(scip, &varblocks);
385 
386  if( !unique )
387  continue;
388  }
389  /* candidate is valid in first iteration */
390  return 1;
391  }
392  else /* iter == 1 */
393  {
394  if ( GCGvarGetBlock(branchcand) != -1 )
395  return -1;
396 
397  /* candidate is valid in second iteration */
398  return 0;
399  }
400  }
401  return -1;
402 }
403 
404 /** adds branching candidates to branchruledata to collect infos about it */
405 static
406 SCIP_RETCODE addBranchcandsToData(
407  SCIP* scip, /**< SCIP data structure */
408  SCIP_BRANCHRULE* branchrule, /**< branching rule */
409  SCIP_VAR** var1s, /**< first parts of branching candidates */
410  SCIP_VAR** var2s, /**< second parts of branching candidates */
411  int ncands /**< number of priority branching candidates */
412  )
413 {
414  SCIP* masterscip;
415  SCIP_BRANCHRULEDATA* branchruledata;
416  int i;
417  VarTuple* vartuple = NULL;
418  int nvars;
419  int newsize;
420 
421  /* get branching rule data */
422  branchruledata = SCIPbranchruleGetData(branchrule);
423  assert(branchruledata != NULL);
424 
425  masterscip = GCGgetMasterprob(scip);
426 
427  /* if var is not in hashtable, insert it */
428  for( i = 0; i < ncands; i++ )
429  {
430  nvars = branchruledata->nvars;
431 
432  /* if variable is not in hashmtable insert it, initialize its array entries, and increase array sizes */
433  SCIP_CALL( SCIPallocBlockMemory(masterscip, &vartuple) );
434  vartuple->var1 = var1s[i];
435  vartuple->var2 = var2s!=NULL? var2s[i] : NULL;
436  vartuple->index = nvars;
437 
438  if( !SCIPhashtableExists(branchruledata->candhashtable, (void *) vartuple) )
439  {
440  newsize = SCIPcalcMemGrowSize(masterscip, nvars + 1);
441  SCIP_CALL( SCIPreallocBlockMemoryArray(masterscip, &branchruledata->strongbranchscore,
442  branchruledata->maxvars, newsize) );
443  SCIP_CALL( SCIPreallocBlockMemoryArray(masterscip, &branchruledata->sbscoreisrecent,
444  branchruledata->maxvars, newsize) );
445  SCIP_CALL( SCIPreallocBlockMemoryArray(masterscip, &branchruledata->lastevalnode, branchruledata->maxvars,
446  newsize) );
447  SCIP_CALL( SCIPreallocBlockMemoryArray(masterscip, &branchruledata->uniqueblockflags,
448  branchruledata->maxvars, newsize) );
449  SCIP_CALL( SCIPreallocBlockMemoryArray(masterscip, &branchruledata->vartuples,
450  branchruledata->maxvars, newsize) );
451  branchruledata->maxvars = newsize;
452 
453  branchruledata->strongbranchscore[nvars] = -1;
454  branchruledata->sbscoreisrecent[nvars] = FALSE;
455  branchruledata->lastevalnode[nvars] = -1;
456  branchruledata->uniqueblockflags[nvars] = -2;
457  branchruledata->vartuples[nvars] = vartuple;
458  SCIP_CALL( SCIPhashtableInsert(branchruledata->candhashtable,
459  (void*) branchruledata->vartuples[nvars]) );
460 
461  assert(SCIPhashtableExists(branchruledata->candhashtable, (void*) branchruledata->vartuples[nvars])
462  && ( (VarTuple *) SCIPhashtableRetrieve(branchruledata->candhashtable,
463  (void*) branchruledata->vartuples[nvars]) )->index == nvars);
464 
465  ++(branchruledata->nvars);
466  }
467  else
468  {
469  SCIPfreeBlockMemory(masterscip, &vartuple);
470  }
471  }
472 
473  return SCIP_OKAY;
474 }
475 
476 /* compare two indices corresponding to entries in branchruledata->score, returns TRUE iff the first elements score is
477  * larger
478  */
480  const void *index1, /**< index in branchruledata->score of first element */
481  const void *index2 /**< index in branchruledata->score of first element */
482  )
483 {
484  return this_branchruledata->score[*(int *)index1] > this_branchruledata->score[*(int *)index2]? -1 : 1;
485 }
486 
487 /* compare two indices based on descending numerical order, returns TRUE iff the first index is smaller */
489  const void *index1, /**< first index */
490  const void *index2 /**< second index */
491  )
492 {
493  return *(int *)index1 < *(int *)index2? -1 : 1;
494 }
495 
496 /* creates a probing node that is "equal" to the same or differ branch of a given Ryan-Foster candidate, mostly copied
497  * from the corresponding method in branch_ryanfoster.c
498  */
499 static
501  SCIP* scip, /**< SCIP data structure */
502  SCIP_BRANCHRULE* branchrule, /**< branching rule */
503  SCIP_VAR* ovar1, /**< first original variable */
504  SCIP_VAR* ovar2, /**< second original variable */
505  int blocknr, /**< number of the pricing block */
506  SCIP_Bool same /**< do we want to create the same (TRUE) or differ (FALSE) branch? */
507  )
508 {
509  SCIP* masterscip;
510  SCIP_VAR* pricingvar1;
511  SCIP_VAR* pricingvar2;
512  GCG_BRANCHDATA* branchdata;
513  char name[SCIP_MAXSTRLEN];
514 
515  SCIP_VAR** origvars1;
516  SCIP_VAR** origvars2;
517  int norigvars;
518  int maxorigvars;
519  int v;
520 
521  SCIP_CONS** origbranchconss;
522 
523 
524  assert(scip != NULL);
525  assert(branchrule != NULL);
526  assert(ovar1 != NULL);
527  assert(ovar2 != NULL);
528  assert(GCGvarIsOriginal(ovar1));
529  assert(GCGvarIsOriginal(ovar2));
530 
531  origbranchconss = NULL;
532 
533  masterscip = GCGgetMasterprob(scip);
534  assert(masterscip != NULL);
535 
536  /* for cons_masterbranch */
537 
538  /* allocate branchdata for same child and store information */
539  SCIP_CALL( SCIPallocBlockMemory(scip, &branchdata) );
540  branchdata->var1 = ovar1;
541  branchdata->var2 = ovar2;
542  branchdata->same = same;
543  branchdata->blocknr = blocknr;
544  branchdata->pricecons = NULL;
545 
546  /* define name for origbranch constraints */
547  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s(%s,%s)", same? "same" : "differ", SCIPvarGetName(branchdata->var1),
548  SCIPvarGetName(branchdata->var2));
549 
550  pricingvar1 = GCGoriginalVarGetPricingVar(branchdata->var1);
551  pricingvar2 = GCGoriginalVarGetPricingVar(branchdata->var2);
552  assert(GCGvarIsPricing(pricingvar1));
553  assert(GCGvarIsPricing(pricingvar2));
554  assert(GCGvarGetBlock(pricingvar1) == GCGvarGetBlock(pricingvar2));
555  assert(GCGpricingVarGetNOrigvars(pricingvar1) == GCGpricingVarGetNOrigvars(pricingvar2));
556 
557  norigvars = GCGpricingVarGetNOrigvars(pricingvar1);
558  assert(norigvars == GCGpricingVarGetNOrigvars(pricingvar2));
559 
560  origvars1 = GCGpricingVarGetOrigvars(pricingvar1);
561  origvars2 = GCGpricingVarGetOrigvars(pricingvar2);
562 
563  if( norigvars > 0 )
564  {
565  maxorigvars = SCIPcalcMemGrowSize(masterscip, norigvars);
566  SCIP_CALL( SCIPallocBlockMemoryArray(masterscip, &origbranchconss, maxorigvars) );
567  }
568  else
569  {
570  maxorigvars = 0;
571  }
572 
573  /* add branching decision as varbound constraints to original problem */
574  for( v = 0; v < norigvars; v++ )
575  {
576  SCIP_CONS* origcons;
577 
578  assert(GCGvarGetBlock(origvars1[v]) == GCGvarGetBlock(origvars2[v]));
579  assert(origbranchconss != NULL);
580 
581  /* create constraint for same-child */
582  SCIP_CALL( SCIPcreateConsVarbound(scip, &origcons, name, origvars1[v], origvars2[v],
583  same? -1.0 : 1.0, same ? 0.0 : -SCIPinfinity(scip), same? 0.0 : 1.0, TRUE, TRUE,
584  TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
585 
586  origbranchconss[v] = origcons;
587  }
588 
589  /* create and add the masterbranch constraints */
590  SCIP_CALL( GCGrelaxNewProbingnodeMasterCons(scip, branchrule, branchdata, origbranchconss, norigvars,
591  maxorigvars) );
592 
593  return SCIP_OKAY;
594 }
595 
596 /* executes strong branching on one variable, with or without pricing */
597 static
599  SCIP *scip, /* SCIP data structure */
600  SCIP_BRANCHRULE* branchrule, /* pointer to the branching rule */
601  SCIP_VAR *branchvar1, /* first variable to get strong branching values for */
602  SCIP_VAR *branchvar2, /* second variable to get strong branching values for */
603  SCIP_Real solval1, /* value of the first variable in the current solution */
604  SCIP_Real solval2, /* value of the second variable in the current solution */
605  int candinfo, /* additional intager information about the candidate */
606  SCIP_Bool pricing, /* should pricing be applied? */
607  int maxpricingrounds, /* maximal number of pricing rounds, -1 for no limit */
608  SCIP_Real *up, /* stores dual bound for up/same child */
609  SCIP_Real *down, /* stores dual bound for down/differ child */
610  SCIP_Bool *upvalid, /* stores whether the up/samebranch was solved properly */
611  SCIP_Bool *downvalid, /* stores whether the down/differbranch was solved properly */
612  SCIP_Bool *upinf, /* stores whether the up/samebranch is infeasible */
613  SCIP_Bool *downinf /* stores whether the down/differbranch is infeasible */
614 )
615 {
616  /* get bound values */
617  SCIP_BRANCHRULEDATA* branchruledata;
618 
619  SCIP_Bool cutoff;
620  SCIP_Bool lperror;
621  SCIP_Bool lpsolved;
622 
623  branchruledata = SCIPbranchruleGetData(branchrule);
624  assert(branchruledata != NULL);
625 
626  *downvalid = FALSE;
627  *upvalid = FALSE;
628  *downinf = FALSE;
629  *upinf = FALSE;
630 
631  assert(scip != NULL);
632 
633  /* probe for each child node */
634  for( int cnode = 0; cnode <= 1; cnode++ )
635  {
636  /* start probing */
637  SCIP_CALL( GCGrelaxStartProbing(scip, NULL) );
638  SCIP_CALL( GCGrelaxNewProbingnodeOrig(scip) );
639 
640  cutoff = FALSE;
641  lperror = FALSE;
642  lpsolved = FALSE;
643 
644  if( branchruledata->initiator == ORIG )
645  {
646  if( cnode == 0 )
647  {
648  SCIP_CALL( SCIPchgVarUbProbing(scip, branchvar1, SCIPfeasFloor(scip, solval1)) );
649  }
650  else
651  {
652  SCIP_CALL( SCIPchgVarLbProbing(scip, branchvar1, SCIPfeasCeil(scip, solval1)) );
653  }
654  }
655 
656  /* propagate the new b&b-node */
657  SCIP_CALL( SCIPpropagateProbing(scip, -1, &cutoff, NULL) );
658 
659  /* solve the LP with or without pricing */
660  if( !cutoff )
661  {
662  if( branchruledata->initiator == RYANFOSTER )
663  {
664  SCIP_CALL( newProbingNodeRyanfosterMaster(scip, branchruledata->initiatorbranchrule, branchvar1,
665  branchvar2, candinfo, cnode == 1) );
666  }
667  else
668  {
669  SCIP_CALL( GCGrelaxNewProbingnodeMaster(scip) );
670  }
671 
672  if( pricing )
673  {
674  int npricerounds;
675 
676  SCIP_CALL( GCGrelaxPerformProbingWithPricing(scip, branchruledata->maxsbpricerounds, NULL, &npricerounds,
677  cnode == 0? down : up, &lpsolved, &lperror, &cutoff) );
678  branchruledata->nphase2lps++;
679  branchruledata->nsbpricerounds += npricerounds;
680  }
681  else
682  {
683  SCIP_Longint nlpiterations;
684 
685  SCIP_CALL( GCGrelaxPerformProbing(scip, branchruledata->maxsblpiters, &nlpiterations,
686  cnode == 0? down : up, &lpsolved, &lperror, &cutoff) );
687  branchruledata->nphase1lps++;
688  branchruledata->nsblpiterations += nlpiterations;
689  }
690  }
691 
692  if( cnode == 0 )
693  {
694  *downvalid = lpsolved;
695  *downinf = cutoff && pricing;
696  }
697  else
698  {
699  *upvalid = lpsolved;
700  *upinf = cutoff && pricing;
701  }
702 
703  SCIP_CALL( GCGrelaxEndProbing(scip) );
704  }
705  return SCIP_OKAY;
706 }
707 
708 /* Returns true iff the second node is a k-successor of the to the first number corresponding node
709  * (i.e. iff there are at most k edges between them)
710  */
711 static
712 SCIP_Bool isKAncestor(
713  SCIP* scip, /**< SCIP data structure */
714  int ancestornodenr, /**< number of the supposed ancestor */
715  SCIP_NODE *successornode, /**< the supposed successor */
716  int k /**< maximal allowed distance between the nodes */
717 )
718 {
719  SCIP_NODE* curnode;
720  curnode = successornode;
721 
722  for( int i = 0; i <= k && SCIPnodeGetNumber(curnode) >= ancestornodenr; i++ )
723  {
724  if( SCIPnodeGetNumber(curnode) == ancestornodenr )
725  return TRUE;
726 
727  if( SCIPnodeGetNumber(curnode) == 1 )
728  break;
729 
730  curnode = SCIPnodeGetParent(curnode);
731  }
732 
733  return FALSE;
734 }
735 
736 /* Evaluates the given variable based on a score function of choice. Higher scores are given to better variables. */
737 static
738 SCIP_Real score_function(
739  SCIP *scip, /**< SCIP data structure */
740  SCIP_BRANCHRULE* branchrule, /**< pointer to the branching rule */
741  SCIP_VAR *var1, /**< first var to be scored */
742  SCIP_VAR *var2, /**< second var to be scored */
743  SCIP_Real solval1, /**< the first var's current solution value */
744  SCIP_Real solval2, /**< the second var's current solution value */
745  int candinfo, /**< additional integer information about the candidate */
746  SCIP_Bool useheuristic, /**< should heuristics be used instead of strong branching? */
747  SCIP_Bool usehistorical, /**< should historical data from phase 2 be used as heuristic? */
748  SCIP_Bool usecolgen, /**< should column generation be used during strong branching? */
749  SCIP_Real *score, /**< stores the computed score */
750  SCIP_Bool *upinf, /**< stores whether the upbranch is infeasible */
751  SCIP_Bool *downinf /**< stores whether the downbranch is infeasible */
752 )
753 {
754  SCIP_BRANCHRULEDATA* branchruledata;
755  VarTuple vartuple = {var1, var2, 0};
756 
757  branchruledata = SCIPbranchruleGetData(branchrule);
758  assert(branchruledata != NULL);
759 
760  /* define score functions and calculate score for all variables for sorting dependent on used heuristic */
761  /* phase 0 */
762  if( useheuristic)
763  {
764  if( usehistorical )
765  {
766  int hashindex;
767 
768  assert(SCIPhashtableExists(branchruledata->candhashtable, (void *) &vartuple));
769  hashindex = ((VarTuple *) SCIPhashtableRetrieve(branchruledata->candhashtable, (void *) &vartuple))->index;
770 
771  return branchruledata->strongbranchscore[hashindex];
772  }
773  else if( branchruledata->usepseudocosts )
774  {
775  *score = SCIPgetVarPseudocostScore(scip, var1, solval1);
776  if( var2 != NULL )
777  *score = *score * SCIPgetVarPseudocostScore(scip, var2, solval2);
778  }
779  else
780  {
781  if( !branchruledata->mostfrac )
782  return 1;
783 
784  *score = solval1 - SCIPfloor(scip, solval1);
785  *score = MIN( *score, 1.0 - *score );
786 
787  if( var2 != NULL )
788  {
789  SCIP_Real frac2;
790 
791  frac2 = solval2 - SCIPfloor(scip, solval2);
792  *score = *score * MIN( frac2, 1.0 - frac2 );
793  }
794  }
795  }
796  else
797  /* phases 1 & 2 */
798  {
799  SCIP* masterscip;
800 
801  int hashindex;
802  int currentnodenr;
803 
804  SCIP_Real down;
805  SCIP_Real up;
806  SCIP_Real downgain;
807  SCIP_Real upgain;
808  SCIP_Bool upvalid;
809  SCIP_Bool downvalid;
810  SCIP_Real lpobjval;
811 
812  SCIP_Real frac;
813 
814  /* get master problem */
815  masterscip = GCGgetMasterprob(scip);
816  assert(masterscip != NULL);
817 
818  assert(SCIPhashtableExists(branchruledata->candhashtable, &vartuple));
819  hashindex = ((VarTuple *) SCIPhashtableRetrieve(branchruledata->candhashtable, (void *) &vartuple))->index;
820  currentnodenr = SCIPnodeGetNumber(SCIPgetFocusNode(scip));
821 
822  if( !usecolgen
823  || !branchruledata->sbscoreisrecent[hashindex]
824  || !isKAncestor(scip, branchruledata->lastevalnode[hashindex], SCIPgetFocusNode(scip),
825  branchruledata->reevalage) )
826  {
827  up = -SCIPinfinity(scip);
828  down = -SCIPinfinity(scip);
829 
830  lpobjval = SCIPgetLPObjval(masterscip);
831 
832  /* usecolgen is True for phase 1 and False for phase 2 */
833  SCIP_CALL( executeStrongBranching(scip, branchrule, var1, var2, solval1, solval2, candinfo, usecolgen, -1,
834  &up, &down, &upvalid, &downvalid, upinf, downinf) );
835 
836  down = downvalid? down : upvalid? up : 0;
837  up = upvalid? up : down;
838 
839  downgain = MAX(down - lpobjval, 0.0);
840  upgain = MAX(up - lpobjval, 0.0);
841 
842  *score = SCIPgetBranchScore(scip, var1, downgain, upgain);
843 
844  if( usecolgen && upvalid && downvalid )
845  {
846  frac = solval1 - SCIPfloor(scip, solval1);
847  if( !*upinf && !*downinf )
848  {
849  branchruledata->strongbranchscore[hashindex] = *score;
850  branchruledata->sbscoreisrecent[hashindex] = TRUE;
851  branchruledata->lastevalnode[hashindex] = currentnodenr;
852  }
853 
854  if( branchruledata->initiator == ORIG )
855  {
856  /* update pseudocost scores */
857  if( !*upinf )
858  {
859  SCIP_CALL( SCIPupdateVarPseudocost(scip, var1, 1.0-frac, upgain, 1.0) );
860  }
861 
862  if( !*downinf)
863  {
864  SCIP_CALL( SCIPupdateVarPseudocost(scip, var1, 0.0-frac, downgain, 1.0) );
865  }
866  }
867  }
868  }
869  else
870  {
871  *score = branchruledata->strongbranchscore[hashindex];
872  }
873  }
874 
875  return SCIP_OKAY;
876 }
877 
878 /** branching method for relaxation solutions */
879 static
880 SCIP_RETCODE selectCandidate(
881  SCIP* scip, /**< SCIP data structure */
882  SCIP_BRANCHRULE* branchrule, /**< pointer to the branching rule */
883  SCIP_VAR** cand1s, /**< first variable candidates */
884  SCIP_VAR** cand2s, /**< second variable candidates (each cand2 corresponds to exactly one
885  * cand1 and vice versa) */
886  int* candinfos, /**< additional information for each candidate */
887  int ncands, /**< number of input candidates */
888  SCIP_VAR** outcand1, /**< pointer to store the pointer of the first selected variable */
889  SCIP_VAR** outcand2, /**< pointer to store the pointer of the second selected variable (if
890  * applicable) */
891  int* outcandinfo, /**< pointer to store additional (integer) info */
892  SCIP_Bool* bestupinf, /**< pointer to store whether strong branching detected infeasibility in
893  * the upbranch */
894  SCIP_Bool* bestdowninf, /**< pointer to store whether strong branching detected infeasibility in
895  * the downbranch */
896  SCIP_RESULT* result /**< pointer to store the result of the branching call */
897  )
898 {
899  SCIP* masterscip;
900  SCIP_BRANCHRULEDATA* branchruledata;
901 
902  /* branching candidates */
903  SCIP_VAR** branchcands;
904  SCIP_Real* branchcandssol;
905  int npriobranchcands;
906 
907  SCIP_HASHMAP* solhashmap;
908 
909  int hashindex;
910 
911  /* values for choosing the variable to branch on */
912  SCIP_Real maxscore;
913  SCIP_Real score;
914 
915  /* variables for controlling the evaluation effort */
916  int lookahead;
917  int lastimproved;
918 
919  int depth;
920  int phase0nneededcands;
921 
922  SCIP_Real minpscount;
923 
924  SCIP_Real nodegap;
925  SCIP_Real upperbound;
926  SCIP_Real nodelowerbound;
927 
928  int nneededcands;
929 
930  int heurincumbentindex;
931  SCIP_Real heurincumbentsbscore;
932 
933  /* infeasibility results during strong branching */
934  SCIP_Bool upinf;
935  SCIP_Bool downinf;
936 
937  /* storing best candidates */
938  int *indices;
939  int nvalidcands;
940 
941  /* storing best candidates based on historical strong branching scores */
942  int *histindices;
943  int nvalidhistcands;
944  int nneededhistcands;
945 
946  VarTuple vartuple = {NULL,NULL,0};
947 
948  assert(branchrule != NULL);
949  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
950  assert(scip != NULL);
951  assert(result != NULL);
952  assert(SCIPisRelaxSolValid(scip));
953 
954  branchruledata = SCIPbranchruleGetData(branchrule);
955 
956  assert(branchruledata->maxphase1depth + 1 >= branchruledata->minphase0depth ||
957  branchruledata->maxphase2depth + 1 >= branchruledata->minphase0depth);
958 
959  *result = SCIP_DIDNOTRUN;
960 
961  /* get master problem */
962  masterscip = GCGgetMasterprob(scip);
963  assert(masterscip != NULL);
964 
965  heurincumbentindex = -1;
966 
967  /* get the branching candidates */
968  SCIP_CALL( SCIPgetExternBranchCands(scip, &branchcands, &branchcandssol, NULL, NULL,
969  &npriobranchcands, NULL, NULL, NULL) );
970 
971  if( branchruledata->initiator == ORIG )
972  {
973  cand1s = branchcands;
974  ncands = npriobranchcands;
975  }
976  else if( branchruledata->initiator == RYANFOSTER && (branchruledata->usepseudocosts || branchruledata->mostfrac ) )
977  {
978  SCIP_CALL( SCIPhashmapCreate(&solhashmap, SCIPblkmem(scip), npriobranchcands) );
979  for( int r = 0; r<npriobranchcands; r++ )
980  {
981  SCIP_CALL( SCIPhashmapInsertReal(solhashmap, branchcands[r], branchcandssol[r]) );
982  }
983  }
984 
985  *outcand1 = NULL;
986 
987  maxscore = -1.0;
988 
989  upinf = FALSE;
990  downinf = FALSE;
991  *bestupinf = FALSE;
992  *bestdowninf = FALSE;
993 
994  depth = SCIPnodeGetDepth(SCIPgetFocusNode(scip));
995 
996  /* set maximum strong branching lp iterations and pricing rounds to 2 times the average unless the value is
997  * fixed in the settings (as it is done in SCIP)
998  */
999  SCIP_CALL( SCIPgetLongintParam(scip, "branching/bp_strong/maxsblpiters", &branchruledata->maxsblpiters) );
1000  if( branchruledata->maxsblpiters == 0 )
1001  {
1002  SCIP_Longint nlpiterations;
1003  SCIP_Longint nlps;
1004  SCIP_Longint maxlpiters;
1005 
1006  nlpiterations = branchruledata->nsblpiterations;
1007  nlps = branchruledata->nphase1lps;
1008  if( nlps == 0 )
1009  {
1010  nlpiterations = SCIPgetNNodeInitLPIterations(masterscip);
1011  nlps = SCIPgetNNodeInitLPs(masterscip);
1012  if( nlps == 0 )
1013  {
1014  nlpiterations = 1000;
1015  nlps = 1;
1016  }
1017  }
1018  assert(nlps >= 1);
1019  maxlpiters = (int)(2*nlpiterations / nlps);
1020  maxlpiters = (int)((SCIP_Real)maxlpiters * (1.0 + 10.0 / SCIPgetNNodes(masterscip)));
1021  branchruledata->maxsblpiters = maxlpiters;
1022  }
1023 
1024  SCIP_CALL( SCIPgetIntParam(scip, "branching/bp_strong/maxsbpricerounds", &branchruledata->maxsbpricerounds) );
1025  if( branchruledata->maxsbpricerounds == 0 )
1026  {
1027  SCIP_Longint npricerounds;
1028  SCIP_Longint nlps;
1029  SCIP_Longint maxpricerounds;
1030 
1031  npricerounds = branchruledata->nsbpricerounds;
1032  nlps = branchruledata->nphase2lps;
1033  if( nlps == 0 )
1034  {
1035  npricerounds = SCIPgetNNodeInitLPIterations(masterscip);
1036  nlps = SCIPgetNNodeInitLPs(masterscip);
1037  if( nlps == 0 )
1038  {
1039  npricerounds = 100000;
1040  nlps = 1;
1041  }
1042  }
1043  assert(nlps >= 1);
1044  maxpricerounds = (int)(2 * npricerounds / nlps);
1045  maxpricerounds = (int)((SCIP_Real)maxpricerounds * (1.0 + 10.0 / SCIPgetNNodes(masterscip)));
1046  branchruledata->maxsbpricerounds = maxpricerounds;
1047  }
1048 
1049  upperbound = SCIPgetUpperbound(scip);
1050  nodelowerbound = SCIPnodeGetLowerbound( SCIPgetFocusNode(scip) );
1051  nodegap = ((upperbound >= 0) == (nodelowerbound >= 0) && MIN( ABS( upperbound ), ABS( nodelowerbound ) ) != 0)?
1052  MIN( ABS( (upperbound-nodelowerbound) / MIN( ABS( upperbound ), ABS( nodelowerbound ) ) ), 1 ) : 1;
1053  assert(0 <= nodegap && nodegap <= 1);
1054 
1055  /* number of candidates we evaluate precisely should be based on the likely relevance of this branching decision
1056  * via the nodegap */
1057  nneededcands = calculateNCands(scip, branchruledata, nodegap, 0, ncands);
1058 
1059  /* insert branchcands into hashtable */
1060  SCIP_CALL( addBranchcandsToData(scip, branchrule, cand1s, cand2s, ncands) );
1061 
1062  SCIP_CALL( SCIPallocBufferArray(masterscip, &branchruledata->score, ncands) );
1063  for( int init = 0; init < ncands; ++init )
1064  {
1065  vartuple.var1 = cand1s[init];
1066  vartuple.var2 = cand2s == NULL? NULL : cand2s[init];
1067  hashindex = ((VarTuple *) SCIPhashtableRetrieve(branchruledata->candhashtable, (void *) &vartuple))->index;
1068 
1069  branchruledata->score[init] = branchruledata->strongbranchscore[hashindex];
1070  }
1071 
1072  /* allocate memory */
1073  SCIP_CALL( SCIPallocBufferArray(masterscip, &indices, ncands) );
1074  SCIP_CALL( SCIPallocBufferArray(masterscip, &histindices, ncands) );
1075  indices[0] = 0;
1076 
1077  if( branchruledata->initiator == ORIG )
1078  {
1079  nvalidcands = 0;
1080  nvalidhistcands = 0;
1081 
1082  /* iter = 0: integer variables belonging to a unique block with fractional value,
1083  * iter = 1: we did not find enough variables to branch on so far, so we look for integer variables that belong
1084  * to no block but were directly transferred to the master problem and which have a fractional value in the
1085  * current solution
1086  */
1087  for( int iter = 0; iter <= 1 && nvalidcands < nneededcands; iter++ )
1088  {
1089  for( int i = 0; i < ncands; i++ )
1090  {
1091  vartuple.var1 = cand1s[i];
1092  vartuple.var2 = NULL;
1093 
1094  hashindex = ((VarTuple *) SCIPhashtableRetrieve(branchruledata->candhashtable, (void *) &vartuple))->index;
1095 
1096  if (iter == 0)
1097  {
1098  if( branchruledata->uniqueblockflags[hashindex] < -1 )
1099  {
1100  branchruledata->uniqueblockflags[hashindex] = assignUniqueBlockFlags(scip, cand1s[i]);
1101  }
1102 
1103  if( branchruledata->uniqueblockflags[hashindex] == 1 )
1104  {
1105  indices[nvalidcands] = i;
1106  nvalidcands++;
1107 
1108  if( branchruledata->strongbranchscore[hashindex] != -1)
1109  {
1110  histindices[nvalidhistcands] = i;
1111  nvalidhistcands++;
1112  }
1113  }
1114  }
1115  else if( nvalidcands == 0 )
1116  {
1117  if( branchruledata->uniqueblockflags[hashindex] == 0 )
1118  {
1119  indices[nvalidcands] = i;
1120  nvalidcands++;
1121  if( branchruledata->strongbranchscore[hashindex] != -1 )
1122  {
1123  histindices[nvalidhistcands] = i;
1124  nvalidhistcands++;
1125  }
1126  }
1127  }
1128  }
1129  }
1130 
1131  if( nvalidcands == 0 )
1132  {
1133  SCIPfreeBufferArray(masterscip, &indices);
1134  SCIPfreeBufferArray(masterscip, &histindices);
1135  SCIPfreeBufferArray(masterscip, &branchruledata->score);
1136  return SCIP_OKAY;
1137  }
1138  }
1139  else
1140  {
1141  nvalidhistcands = 0;
1142  for( int i=0; i<ncands; i++ )
1143  {
1144  indices[i] = i;
1145  if( branchruledata->score[i] != -1 )
1146  {
1147  histindices[nvalidhistcands] = i;
1148  nvalidhistcands++;
1149  }
1150  }
1151  nvalidcands = ncands;
1152  }
1153 
1154  /* the number of candidates we select based on historical strong branching scores needs to depend on the number of
1155  * candidates for which we have historical scores, otherwise some candidates would be selected simply because they
1156  * have been scored before
1157  */
1158  nneededhistcands = (int) SCIPfloor(scip, MIN( (SCIP_Real)nvalidhistcands / (SCIP_Real)(nvalidcands+nvalidhistcands),
1159  branchruledata->histweight ) * nvalidcands);
1160  qsort(histindices, nvalidhistcands, sizeof(int), score_compare_function);
1161  qsort(histindices, nneededhistcands, sizeof(int), geq_compare_function);
1162 
1163  /* go through the three phases:
1164  * - phase 0: select a first selection of candidates based on some traditional variable selection
1165  * heuristic, some (half) of the candidates are new, and some are selected based on previous calls
1166  * - phase 1: filter the best candidates by evaluating the Master LP, w/o column and cut generation
1167  * - phase 2: select the best of the candidates from phase 1 by solving the Master LP with column and cut generation
1168  */
1169  for( int phase = 0; phase <= 2; phase++ )
1170  {
1171  /* skip phase 1 if we are below its max depth */
1172  if( depth > branchruledata->maxphase1depth && phase == 1 )
1173  phase = 2;
1174 
1175  switch( phase )
1176  {
1177  case 0:
1178  ncands = nvalidcands;
1179 
1180  /* necessary in case we skip phase 0 */
1181  phase0nneededcands = nneededcands;
1182 
1183  /* skip phase 0 we are too high in the tree, and phases 1 and 2 if we are too low */
1184  if( branchruledata->minphase0depth > depth )
1185  {
1186  nneededcands = ncands;
1187  }
1188  else if( depth > branchruledata->maxphase1depth )
1189  {
1190  if( depth > branchruledata->maxphase2depth )
1191  {
1192  nneededcands = 1;
1193 
1194  /* strong branching can be fully stopped if all open nodes are below the max depth */
1195  if( SCIPgetEffectiveRootDepth(scip) > branchruledata->maxphase1depth &&
1196  SCIPgetEffectiveRootDepth(scip) > branchruledata->maxphase2depth )
1197  branchruledata->done = TRUE;
1198  }
1199  else
1200  {
1201  /* we only want to skip phase 1, so we need to set nneededcands to the number of output candidates
1202  * for phase 1
1203  */
1204  nneededcands = calculateNCands(scip, branchruledata, nodegap, 1, phase0nneededcands);
1205  }
1206  }
1207 
1208  break;
1209 
1210  case 1:
1211  nneededcands = calculateNCands(scip, branchruledata, nodegap, 1, phase0nneededcands);
1212 
1213  /* skip phase 2 if we are in lite mode,
1214  * or if the number of available candidates is lower than the min amount for phase 2,
1215  * or if we are too low in the tree
1216  */
1217  if( branchruledata->usestronglite
1218  || nneededcands < branchruledata->mincolgencands
1219  || ncands < branchruledata->mincolgencands
1220  || depth > branchruledata->maxphase2depth )
1221  nneededcands = 1;
1222 
1223  break;
1224 
1225  case 2:
1226  nneededcands = 1;
1227  lastimproved = 0;
1228 
1229  /* the lookahead can be partially based on the overall evaluation effort for phase 2 */
1230  lookahead = branchruledata->maxlookahead;
1231  if( lookahead && branchruledata->lookaheadscales>0 )
1232  {
1233  lookahead = MAX( 1, (int) SCIPround(scip,
1234  (SCIP_Real) ((1-branchruledata->lookaheadscales) * lookahead) -
1235  (SCIP_Real) (branchruledata->lookaheadscales *
1236  ncands / branchruledata->maxphase1outcands) * lookahead) );
1237  }
1238  break;
1239  }
1240 
1241  if( nneededcands >= ncands && (phase != 0 || !branchruledata->forcephase0) )
1242  continue;
1243 
1244  /* compute scores */
1245  for( int i = 0, c=branchruledata->lastcand; i < ncands; i++, c++ )
1246  {
1247  c = c % ncands;
1248 
1249  /* select the variable as new best candidate (if it is) if we look for only one candidate,
1250  * or remember its score if we look for multiple
1251  */
1252  if( branchruledata->initiator == ORIG )
1253  {
1254  minpscount = MIN( SCIPgetVarPseudocostCount(scip, cand1s[indices[c]], 0),
1255  SCIPgetVarPseudocostCount(scip, cand1s[indices[c]], 1) );
1256 
1257  /* only call strong branching if this variable is not sufficiently reliable yet */
1258  if( phase == 0 ||
1259  (phase == 1 && minpscount < branchruledata->phase1reliable) ||
1260  (phase == 2 && minpscount < branchruledata->phase2reliable) )
1261  {
1262  SCIP_CALL( score_function(scip, branchrule, cand1s[indices[c]], NULL, branchcandssol[indices[c]], 0, 0,
1263  phase == 0, FALSE, phase == 2 && !branchruledata->usestronglite,
1264  &score, &upinf, &downinf) );
1265  }
1266  else
1267  {
1268  score = branchruledata->score[indices[c]];
1269  }
1270  }
1271  else
1272  {
1273  SCIP_CALL( score_function(scip, branchrule, cand1s[indices[c]], cand2s[indices[c]],
1274  SCIPhashmapGetImageReal(solhashmap, cand1s[indices[c]]),
1275  SCIPhashmapGetImageReal(solhashmap, cand2s[indices[c]]),
1276  candinfos[indices[c]], phase == 0, FALSE,
1277  phase == 2 && !branchruledata->usestronglite, &score, &upinf, &downinf) );
1278  }
1279 
1280  /* variable pointers for orig candidates sometimes change during probing in strong branching */
1281  if( branchruledata->initiator == ORIG && phase >= 1 )
1282  {
1283  SCIP_CALL( SCIPgetExternBranchCands(scip, &cand1s, &branchcandssol, NULL, NULL,
1284  NULL, NULL, NULL, NULL) );
1285  }
1286 
1287  /* handle infeasibility detected during strong branching */
1288  if( phase == 2 && !branchruledata->usestronglite && branchruledata->immediateinf && (upinf || downinf) )
1289  {
1290  if( upinf && downinf )
1291  {
1292  for( int k = 0; k < branchruledata->maxvars; k++ )
1293  {
1294  branchruledata->sbscoreisrecent[k] = FALSE;
1295  }
1296  *result = SCIP_CUTOFF;
1297 
1298  SCIPfreeBufferArray(masterscip, &indices);
1299  SCIPfreeBufferArray(masterscip, &histindices);
1300  SCIPfreeBufferArray(masterscip, &branchruledata->score);
1301 
1302  *bestupinf = TRUE;
1303  *bestdowninf = TRUE;
1304 
1305  SCIPdebugMessage("Strong branching detected current node to be infeasible!\n");
1306  return SCIP_OKAY;
1307  }
1308 
1309  branchruledata->lastcand = c;
1310  indices[0] = indices[c];
1311  *bestupinf = upinf;
1312  *bestdowninf = downinf;
1313  break;
1314  }
1315 
1316  /* store strong branching score of the candidate that was selected by the heuristic */
1317  if( phase>0 && heurincumbentindex == indices[c] )
1318  heurincumbentsbscore = score;
1319 
1320  if( nneededcands == 1 )
1321  {
1322  if( score > maxscore )
1323  {
1324  lastimproved = 0;
1325  indices[0] = indices[c];
1326  maxscore = score;
1327  *bestupinf = upinf;
1328  *bestdowninf = downinf;
1329  }
1330  /* if the last improving candidate is lookahead or more steps away, abort phase 2 */
1331  else
1332  {
1333  lastimproved++;
1334  if( lookahead && lastimproved >= lookahead && phase == 2 )
1335  {
1336  break;
1337  }
1338  }
1339 
1340  }
1341  else
1342  {
1343  branchruledata->score[indices[c]] = score;
1344  }
1345  }
1346 
1347  if( nneededcands > 1 )
1348  {
1349  qsort(indices, ncands, sizeof(int), score_compare_function);
1350  ncands = MIN( ncands, nneededcands );
1351 
1352  if( phase == 0 )
1353  {
1354  heurincumbentindex = indices[0];
1355 
1356  if( nneededhistcands )
1357  {
1358  /* swap out the worst performing "new" candidates with the best performing historical candidates */
1359  int *indicescopy;
1360  int pos;
1361 
1362  SCIP_CALL( SCIPallocBufferArray(masterscip, &indicescopy, ncands) );
1363  pos = nneededhistcands;
1364 
1365  for( int i = 0; i<ncands; i++ )
1366  {
1367  indicescopy[i] = indices[i];
1368  }
1369 
1370  for( int i = 0; i<nneededhistcands; i++ )
1371  {
1372  indices[i] = histindices[i];
1373  }
1374 
1375  /* concatenate the two arrays, while avoiding duplicates */
1376  for( int i = 0; i<ncands && pos<=ncands; i++ )
1377  {
1378  for( int j = 0; j <= nneededhistcands; j++ )
1379  {
1380  if( j == nneededhistcands )
1381  {
1382  indices[pos] = indicescopy[i];
1383  pos++;
1384  }
1385  else if( indices[j] == indicescopy[i] )
1386  break;
1387  }
1388  }
1389 
1390  SCIPfreeBufferArray(masterscip, &indicescopy);
1391  }
1392  }
1393  }
1394  else
1395  {
1396  break;
1397  }
1398  }
1399 
1400  *outcand1 = cand1s[indices[0]];
1401  if( branchruledata->initiator == RYANFOSTER )
1402  {
1403  *outcand2 = cand2s[indices[0]];
1404  *outcandinfo = candinfos[indices[0]];
1405  }
1406 
1407  /* free memory */
1408  SCIPfreeBufferArray(masterscip, &indices);
1409  SCIPfreeBufferArray(masterscip, &histindices);
1410  SCIPfreeBufferArray(masterscip, &branchruledata->score);
1411 
1412  if( *outcand1 == NULL )
1413  {
1414  SCIPdebugMessage("Strong branching could not find a variable to branch on!\n");
1415  return SCIP_OKAY;
1416  }
1417 
1418  if( branchruledata->initiator == ORIG )
1419  {
1420  SCIPdebugMessage("Strong branching selected variable %s%s\n",
1421  SCIPvarGetName(*outcand1),
1422  (*bestupinf || *bestdowninf)? ", branching on which is infeasible in one direction" : "");
1423  }
1424  else
1425  {
1426  SCIPdebugMessage("Strong branching selected variables %s and %s%s\n",
1427  SCIPvarGetName(*outcand1), SCIPvarGetName(*outcand2),
1428  (*bestupinf || *bestdowninf)? ", branching on which is infeasible in one direction" : "");
1429  }
1430 
1431  if( branchruledata->initiator == RYANFOSTER && (branchruledata->usepseudocosts || branchruledata->mostfrac) )
1432  {
1433  SCIPhashmapFree(&solhashmap);
1434  }
1435 
1436  if( !*bestupinf && !*bestdowninf )
1437  {
1438  /* if the heuristic was close multiple times in a row, stop strong branching */
1439  if( branchruledata->maxconsecheurclose >= 0
1440  && heurincumbentsbscore >= branchruledata->closepercentage * maxscore )
1441  {
1442  branchruledata->consecheurclose++;
1443  if( branchruledata->consecheurclose >= branchruledata->maxconsecheurclose )
1444  branchruledata->done = TRUE;
1445  }
1446  else
1447  branchruledata->consecheurclose = 0;
1448 
1449  for( int i=0; i<branchruledata->maxvars; i++ )
1450  {
1451  branchruledata->sbscoreisrecent[i] = FALSE;
1452  }
1453  }
1454 
1455  *result = SCIP_BRANCHED;
1456 
1457  return SCIP_OKAY;
1458 }
1459 
1460 /*
1461  * Callback methods
1462  */
1463 #define branchDeactiveMasterBPStrong NULL
1464 #define branchPropMasterBPStrong NULL
1465 #define branchActiveMasterBPStrong NULL
1466 #define branchMasterSolvedBPStrong NULL
1467 #define branchDataDeleteBPStrong NULL
1468 
1469 #define branchExeclpBPStrong NULL
1470 #define branchExecextBPStrong NULL
1471 #define branchExecpsBPStrong NULL
1472 
1473 /** free remaining allocated memory */
1474 static
1475 SCIP_DECL_BRANCHFREE(branchFreeBPStrong)
1476 {
1477  SCIP_BRANCHRULEDATA* branchruledata;
1478  SCIP_HASHTABLE* candhashtable;
1479  int i;
1480 
1481  branchruledata = SCIPbranchruleGetData(branchrule);
1482 
1483  if( branchruledata->initialized )
1484  {
1485  candhashtable = branchruledata->candhashtable;
1486 
1487  SCIPfreeBlockMemoryArray(scip, &branchruledata->lastevalnode, branchruledata->maxvars);
1488  SCIPfreeBlockMemoryArray(scip, &branchruledata->sbscoreisrecent, branchruledata->maxvars);
1489  SCIPfreeBlockMemoryArray(scip, &branchruledata->strongbranchscore, branchruledata->maxvars);
1490  SCIPfreeBlockMemoryArray(scip, &branchruledata->uniqueblockflags, branchruledata->maxvars);
1491 
1492  for( i=0; i<branchruledata->nvars; i++ )
1493  {
1494  SCIPfreeBlockMemory(scip, &(branchruledata->vartuples[i]));
1495  }
1496 
1497  SCIPfreeBlockMemoryArray(scip, &branchruledata->vartuples, branchruledata->maxvars);
1498 
1499  if( branchruledata->candhashtable != NULL )
1500  {
1501  SCIPhashtableFree(&candhashtable);
1502  }
1503  }
1504 
1505  SCIPfreeBlockMemory(scip, &branchruledata);
1506  SCIPbranchruleSetData(branchrule, NULL);
1507 
1508  return SCIP_OKAY;
1509 }
1510 
1511 /** initialization method of branching rule (called after problem was transformed) */
1512 static
1513 SCIP_DECL_BRANCHINIT(branchInitBPStrong)
1514 {
1515  SCIP* origprob;
1516  SCIP_BRANCHRULEDATA* branchruledata;
1517  SCIP_HASHTABLE* candhashtable;
1518 
1519  int i;
1520  int maxcands;
1521 
1522  SCIP_Real logweight;
1523  SCIP_Real logbase;
1524  SCIP_Real phase0frac;
1525  SCIP_Real phase2frac;
1526 
1527  SCIP_Real phase1depth;
1528 
1529  origprob = GCGmasterGetOrigprob(scip);
1530  assert(branchrule != NULL);
1531  assert(origprob != NULL);
1532 
1533  SCIPdebugMessage("Init BPStrong branching rule\n");
1534 
1535  SCIP_CALL( GCGrelaxIncludeBranchrule( origprob, branchrule, branchActiveMasterBPStrong,
1538 
1539  branchruledata = SCIPbranchruleGetData(branchrule);
1540 
1541  /* free data if we already solved another instance but branchFreeBPStrong was not called inbetween */
1542  if( branchruledata->initialized )
1543  {
1544  candhashtable = branchruledata->candhashtable;
1545 
1546  for( i=0; i<branchruledata->nvars; i++ )
1547  {
1548  SCIPfreeBlockMemory(scip, &branchruledata->vartuples[i]);
1549  }
1550 
1551  SCIPfreeBlockMemoryArray(scip, &branchruledata->vartuples, branchruledata->maxvars);
1552  SCIPfreeBlockMemoryArray(scip, &branchruledata->lastevalnode, branchruledata->maxvars);
1553  SCIPfreeBlockMemoryArray(scip, &branchruledata->sbscoreisrecent, branchruledata->maxvars);
1554  SCIPfreeBlockMemoryArray(scip, &branchruledata->strongbranchscore, branchruledata->maxvars);
1555  SCIPfreeBlockMemoryArray(scip, &branchruledata->uniqueblockflags, branchruledata->maxvars);
1556 
1557  if( branchruledata->candhashtable != NULL )
1558  {
1559  SCIPhashtableFree(&candhashtable);
1560  }
1561  }
1562 
1563  branchruledata->lastcand = 0;
1564  branchruledata->nvars = 0;
1565  branchruledata->maxvars = 0;
1566  branchruledata->initiator = -1;
1567 
1568  branchruledata->nphase1lps = 0;
1569  branchruledata->nphase2lps = 0;
1570  branchruledata->nsblpiterations = 0;
1571  branchruledata->nsbpricerounds = 0;
1572 
1573  branchruledata->consecheurclose = 0;
1574  branchruledata->done = FALSE;
1575 
1576  SCIP_CALL( SCIPgetRealParam(origprob, "branching/bp_strong/depthlogweight", &logweight) );
1577  if( logweight > 0 )
1578  {
1579  SCIP_CALL( SCIPgetRealParam(origprob, "branching/bp_strong/depthlogbase", &logbase) );
1580  SCIP_CALL( SCIPgetRealParam(origprob, "branching/bp_strong/depthlogphase0frac", &phase0frac) );
1581  SCIP_CALL( SCIPgetRealParam(origprob, "branching/bp_strong/depthlogphase2frac", &phase2frac) );
1582  branchruledata->maxcands = SCIPgetNIntVars(origprob) + SCIPgetNBinVars(origprob);
1583 
1584  phase1depth = log(branchruledata->maxcands)/log(logbase);
1585 
1586  branchruledata->minphase0depth = (int) SCIPround(origprob, (1-logweight) * branchruledata->minphase0depth
1587  + logweight * phase0frac * phase1depth);
1588  branchruledata->maxphase1depth = (int) SCIPround(origprob, (1-logweight) * branchruledata->maxphase1depth
1589  + logweight * phase1depth);
1590  branchruledata->maxphase2depth = (int) SCIPround(origprob, (1-logweight) * branchruledata->maxphase2depth
1591  + logweight * phase2frac * phase1depth);
1592  }
1593 
1594  /* create hash table TODO: better inital table sizes */
1595  maxcands = branchruledata->maxcands;
1596  SCIP_CALL( SCIPhashtableCreate(&(branchruledata->candhashtable), SCIPblkmem(scip),
1597  branchruledata->initiator == RYANFOSTER? maxcands*2 : maxcands,
1598  hashGetKeyVars, hashKeyEqVars, hashKeyValVars, (void*) scip) );
1599 
1600  assert(branchruledata->candhashtable != NULL);
1601 
1602  /* create arrays */
1603  branchruledata->nvars = 0;
1604  branchruledata->maxvars = SCIPcalcMemGrowSize(scip, 0);
1605  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->uniqueblockflags, branchruledata->maxvars) );
1606  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->strongbranchscore, branchruledata->maxvars) );
1607  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->sbscoreisrecent, branchruledata->maxvars) );
1608  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->lastevalnode, branchruledata->maxvars) );
1609  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->vartuples, branchruledata->maxvars) );
1610 
1611  branchruledata->initialized = TRUE;
1612 
1613  this_branchruledata = branchruledata;
1614 
1615  return SCIP_OKAY;
1616 }
1617 
1618 /** creates the b&p strong-branching branching rule and includes it in SCIP */
1620  SCIP* scip /**< SCIP data structure */
1621  )
1622 {
1623  SCIP* origscip;
1624  SCIP_BRANCHRULE* branchrule;
1625  SCIP_BRANCHRULEDATA* branchruledata;
1626 
1627  SCIPdebugMessage("Include BPStrong branching rule\n");
1628 
1629  /* get original problem */
1630  origscip = GCGmasterGetOrigprob(scip);
1631  assert(origscip != NULL);
1632 
1633  /* alloc branching rule data */
1634  SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
1635 
1636  /* include branching rule */
1637  SCIP_CALL( SCIPincludeBranchruleBasic(scip, &branchrule, BRANCHRULE_NAME, BRANCHRULE_DESC, BRANCHRULE_PRIORITY,
1638  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
1639  assert(branchrule != NULL);
1640 
1641  branchruledata->initialized = FALSE;
1642 
1643  /* set non fundamental callbacks via setter functions */
1644  SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitBPStrong) );
1645  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeBPStrong) );
1646 
1647  /* add branching rule parameters */
1648  SCIP_CALL( SCIPaddBoolParam(origscip, "branching/bp_strong/stronglite",
1649  "should strong branching use column generation during variable evaluation?",
1650  &branchruledata->usestronglite, FALSE, DEFAULT_STRONGLITE, NULL, NULL) );
1651 
1652  SCIP_CALL( SCIPaddBoolParam(origscip, "branching/bp_strong/strongtraining",
1653  "should strong branching run as precise as possible (to generate more valuable training data)?",
1654  &branchruledata->usestrongtrain, FALSE, DEFAULT_STRONGTRAIN, NULL, NULL) );
1655 
1656  SCIP_CALL( SCIPaddBoolParam(origscip, "branching/bp_strong/immediateinf",
1657  "should infeasibility detected during strong branching be handled immediately, or only if the candidate is selected?",
1658  &branchruledata->immediateinf, FALSE, DEFAULT_IMMEDIATEINF, NULL, NULL) );
1659 
1660  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/reevalage",
1661  "how many times can bounds be changed due to infeasibility during strong branching until an already evaluated variable needs to be reevaluated?",
1662  &branchruledata->reevalage, FALSE, DEFAULT_REEVALAGE, 0, INT_MAX, NULL, NULL) );
1663 
1664  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/mincolgencands",
1665  "minimum number of variables for phase 2 to be executed, otherwise the best candidate from phase 1 will be chosen",
1666  &branchruledata->mincolgencands, FALSE, DEFAULT_MINCOLGENCANDS, 0, INT_MAX, NULL, NULL) );
1667 
1668  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/histweight",
1669  "how many candidates should be chosen based on historical strong branching scores as opposed to current heuristic scores in phase 0 (e.g. 0.5 = 50%)?",
1670  &branchruledata->histweight, FALSE, DEFAULT_HISTWEIGHT, 0, 1, NULL, NULL) );
1671 
1672  SCIP_CALL( SCIPaddLongintParam(origscip, "branching/bp_strong/maxsblpiters",
1673  "maximum number of strong branching lp iterations, set to 2*avg lp iterations if <= 0",
1674  NULL, FALSE, DEFAULT_MAXSBLPITERS, 0, INT_MAX, NULL, NULL) );
1675 
1676  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/maxsbpricerounds",
1677  "maximum number of strong branching price rounds, set to 2*avg lp iterations if <= 0",
1678  NULL, FALSE, DEFAULT_MAXSBPRICEROUNDS, 0, INT_MAX, NULL, NULL) );
1679 
1680  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/maxlookahead",
1681  "maximum number of non-improving candidates until phase 2 is stopped",
1682  &branchruledata->maxlookahead, FALSE, DEFAULT_MAXLOOKAHEAD, 0, INT_MAX, NULL, NULL) );
1683 
1684  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/lookaheadscales",
1685  "how much should the lookahead scale with the overall evaluation effort? (0 = not at all, 1 = fully)",
1686  &branchruledata->lookaheadscales, FALSE, DEFAULT_LOOKAHEADSCALES, 0, 1, NULL, NULL) );
1687 
1688  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/minphase0depth",
1689  "minimum tree depth from which on phase 0 is performed (intended for heuristics like pseudocost branching)",
1690  &branchruledata->minphase0depth, FALSE, DEFAULT_MINPHASE0DEPTH, 0, INT_MAX, NULL, NULL) );
1691 
1692  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/maxphase1depth",
1693  "maximum tree depth up to which phase 1 is performed (intended for heuristics like pseudocost branching)",
1694  &branchruledata->maxphase1depth, FALSE, DEFAULT_MAXPHASE1DEPTH, 0, INT_MAX, NULL, NULL) );
1695 
1696  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/maxphase2depth",
1697  "maximum tree depth up to which phase 2 is performed (intended for heuristics like pseudocost branching)",
1698  &branchruledata->maxphase2depth, FALSE, DEFAULT_MAXPHASE2DEPTH, 0, INT_MAX, NULL, NULL) );
1699 
1700  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/depthlogweight",
1701  "how much should the logarithm of the number of variables influence the depth for hybrid branching? (0 = not at all, 1 = fully)",
1702  NULL, FALSE, DEFAULT_DEPTHLOGWEIGHT, 0, 1, NULL, NULL) );
1703 
1704  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/depthlogbase",
1705  "what should be the base of the logarithm that is used to compute the depth of hybrid branching?",
1706  NULL, FALSE, DEFAULT_DEPTHLOGBASE, 0, INT_MAX, NULL, NULL) );
1707 
1708  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/depthlogphase0frac",
1709  "if using a logarithm to compute the depth of hybrid branching, what should be the fraction of the depth assigned to phase 1 that is assigned to phase 0?",
1710  NULL, FALSE, DEFAULT_DEPTHLOGPHASE0FRAC, 0, 1, NULL, NULL) );
1711 
1712  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/depthlogphase2frac",
1713  "if using a logarithm to compute the depth of hybrid branching, what should be the fraction of the depth assigned to phase 1 that is assigned to phase 2?",
1714  NULL, FALSE, DEFAULT_DEPTHLOGPHASE2FRAC, 0, 1, NULL, NULL) );
1715 
1716  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/closepercentage",
1717  "what percentage of the strong branching score of the candidate that was selected does the heuristic's incumbent need to be considered close (e.g. 0.5 = 50%)?",
1718  &branchruledata->closepercentage, FALSE, DEFAULT_CLOSEPERCENTAGE, 0, 1, NULL, NULL) );
1719 
1720  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/maxconsecheurclose",
1721  "how many times in a row can the heuristic be close before strong branching is stopped?",
1722  &branchruledata->maxconsecheurclose, FALSE, DEFAULT_MAXCONSECHEURCLOSE, -1, INT_MAX, NULL, NULL) );
1723 
1724  SCIP_CALL( SCIPaddRealParam(origscip, "branching/bp_strong/sbpseudocostweight",
1725  "with how much weight should strong branching scores be considered for pseudocost scores?",
1726  &branchruledata->sbpseudocostweight, FALSE, DEFAULT_SBPSEUDOCOSTWEIGHT, 0, 1, NULL, NULL) );
1727 
1728  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/phase1reliable",
1729  "min count of pseudocost scores for a variable to be considered reliable in phase 1",
1730  &branchruledata->phase1reliable, FALSE, DEFAULT_PHASE1RELIABLE, -1, INT_MAX, NULL, NULL) );
1731 
1732  SCIP_CALL( SCIPaddIntParam(origscip, "branching/bp_strong/phase2reliable",
1733  "min count of pseudocost scores for a variable to be considered reliable in phase 2",
1734  &branchruledata->phase2reliable, FALSE, DEFAULT_PHASE2RELIABLE, -1, INT_MAX, NULL, NULL) );
1735 
1736  SCIP_CALL( SCIPaddBoolParam(origscip, "branching/bp_strong/forcep0",
1737  "should phase 0 be performed even if the number of input candidates is already lower or equal to the number of output candidates?",
1738  &branchruledata->forcephase0, FALSE, DEFAULT_FORCEP0, NULL, NULL) );
1739 
1740 
1741  SCIP_CALL( SCIPaddBoolParam(origscip, "branching/bp_strong/ryanfoster/usepseudocosts",
1742  "should single-variable-pseudocosts be used as a heuristic for strong branching for Ryan-Foster branching?",
1743  NULL, FALSE, DEFAULT_RFUSEPSEUDOCOSTS, NULL, NULL) );
1744 
1745  SCIP_CALL( SCIPaddBoolParam(origscip, "branching/bp_strong/ryanfoster/usemostfrac",
1746  "should single-variable-fractionality be used as a heuristic for strong branching for Ryan-Foster branching?",
1747  NULL, FALSE, DEFAULT_RFUSEMOSTFRAC, NULL, NULL) );
1748 
1749 
1750  /* notify cons_integralorig about the branching rule */
1751  SCIP_CALL( GCGconsIntegralorigAddBranchrule(scip, branchrule) );
1752 
1753  return SCIP_OKAY;
1754 }
1755 
1756 SCIP_RETCODE
1758  SCIP* scip, /**< SCIP data structure */
1759  SCIP_BRANCHRULE *origbranchrule, /**< pointer storing original branching rule */
1760  SCIP_VAR **branchvar, /**< pointer to store output var pointer */
1761  SCIP_Bool *upinf, /**< pointer to store whether strong branching detected infeasibility in
1762  * the upbranch */
1763  SCIP_Bool *downinf, /**< pointer to store whether strong branching detected infeasibility in
1764  * the downbranch */
1765  SCIP_RESULT *result, /**< pointer to store result */
1766  SCIP_Bool *stillusestrong /**< pointer to store whether strong branching has reached a permanent
1767  * stopping condition for orig */
1768 )
1769 {
1770  SCIP_BRANCHRULEDATA *branchruledata;
1771  SCIP_BRANCHRULE *branchrule;
1772  SCIP* masterscip;
1773 
1774  masterscip = GCGgetMasterprob(scip);
1775  branchrule = SCIPfindBranchrule(masterscip, BRANCHRULE_NAME);
1776  assert(branchrule != NULL);
1777 
1778  branchruledata = SCIPbranchruleGetData(branchrule);
1779 
1780  if( branchruledata->initiator != ORIG )
1781  {
1782  branchruledata->initiator = ORIG;
1783 
1784  SCIP_CALL( SCIPgetBoolParam(scip, "branching/orig/usepseudocosts", &branchruledata->usepseudocosts) );
1785  SCIP_CALL( SCIPgetBoolParam(scip, "branching/orig/mostfrac", &branchruledata->mostfrac) );
1786 
1787  SCIP_CALL( SCIPgetIntParam(scip, "branching/orig/minphase0outcands", &branchruledata->minphase0outcands) );
1788  SCIP_CALL( SCIPgetIntParam(scip, "branching/orig/maxphase0outcands", &branchruledata->maxphase0outcands) );
1789  SCIP_CALL( SCIPgetRealParam(scip, "branching/orig/maxphase0outcandsfrac",
1790  &branchruledata->maxphase0outcandsfrac) );
1791  SCIP_CALL( SCIPgetRealParam(scip, "branching/orig/phase1gapweight", &branchruledata->phase1gapweight) );
1792 
1793  SCIP_CALL( SCIPgetIntParam(scip, "branching/orig/minphase1outcands", &branchruledata->minphase1outcands) );
1794  SCIP_CALL( SCIPgetIntParam(scip, "branching/orig/maxphase1outcands", &branchruledata->maxphase1outcands) );
1795  SCIP_CALL( SCIPgetRealParam(scip, "branching/orig/maxphase1outcandsfrac",
1796  &branchruledata->maxphase1outcandsfrac) );
1797  SCIP_CALL( SCIPgetRealParam(scip, "branching/orig/phase2gapweight", &branchruledata->phase2gapweight) );
1798 
1799  assert(branchruledata->maxphase0outcands >= branchruledata->minphase0outcands);
1800  assert(branchruledata->maxphase1outcands >= branchruledata->minphase1outcands);
1801  }
1802 
1803  selectCandidate(scip, branchrule, NULL, NULL, NULL, 0, branchvar, NULL, NULL, upinf, downinf, result);
1804 
1805  *stillusestrong = !branchruledata->done;
1806 
1807  return SCIP_OKAY;
1808 }
1809 
1810 /** interface method for Ryan-Foster branching to strong branching heuristics */
1811 SCIP_RETCODE
1813  SCIP* scip, /**< original SCIP data structure */
1814  SCIP_BRANCHRULE* rfbranchrule, /**< Ryan-Foster branchrule */
1815  SCIP_VAR **ovar1s, /**< first elements of candidate pairs */
1816  SCIP_VAR **ovar2s, /**< second elements of candidate pairs */
1817  int *nspricingblock, /**< pricing block numbers corresponding to input pairs */
1818  int npairs, /**< number of input pairs */
1819  SCIP_VAR **ovar1, /**< pointer to store output var 1 pointer */
1820  SCIP_VAR **ovar2, /**< pointer to store output var 2 pointer */
1821  int *pricingblock, /**< pointer to store output pricing block number */
1822  SCIP_Bool *sameinf, /**< pointer to store whether strong branching detected infeasibility in
1823  * the same branch */
1824  SCIP_Bool *differinf, /**< pointer to store whether strong branching detected infeasibility in
1825  * the differ branch */
1826  SCIP_RESULT *result, /**< pointer to store result */
1827  SCIP_Bool *stillusestrong /**< pointer to store whether strong branching has reached a permanent
1828  * stopping condition for Ryan-Foster */
1829 )
1830 {
1831  SCIP_BRANCHRULEDATA *branchruledata;
1832  SCIP_BRANCHRULE *branchrule;
1833  SCIP* masterscip;
1834 
1835  masterscip = GCGgetMasterprob(scip);
1836  branchrule = SCIPfindBranchrule(masterscip, BRANCHRULE_NAME);
1837  assert(branchrule != NULL);
1838 
1839  branchruledata = SCIPbranchruleGetData(branchrule);
1840 
1841  if( branchruledata->initiator != RYANFOSTER )
1842  {
1843  branchruledata->initiator = RYANFOSTER;
1844  branchruledata->initiatorbranchrule = rfbranchrule;
1845  SCIP_CALL( SCIPgetBoolParam(scip, "branching/bp_strong/ryanfoster/usepseudocosts",
1846  &branchruledata->usepseudocosts) );
1847  SCIP_CALL( SCIPgetBoolParam(scip, "branching/bp_strong/ryanfoster/usemostfrac", &branchruledata->mostfrac) );
1848 
1849  SCIP_CALL( SCIPgetIntParam(scip, "branching/ryanfoster/minphase0outcands",
1850  &branchruledata->minphase0outcands) );
1851  SCIP_CALL( SCIPgetIntParam(scip, "branching/ryanfoster/maxphase0outcands",
1852  &branchruledata->maxphase0outcands) );
1853  SCIP_CALL( SCIPgetRealParam(scip, "branching/ryanfoster/maxphase0outcandsfrac",
1854  &branchruledata->maxphase0outcandsfrac) );
1855  SCIP_CALL( SCIPgetRealParam(scip, "branching/ryanfoster/phase1gapweight",
1856  &branchruledata->phase1gapweight) );
1857 
1858  SCIP_CALL( SCIPgetIntParam(scip, "branching/ryanfoster/minphase1outcands",
1859  &branchruledata->minphase1outcands) );
1860  SCIP_CALL( SCIPgetIntParam(scip, "branching/ryanfoster/maxphase1outcands",
1861  &branchruledata->maxphase1outcands) );
1862  SCIP_CALL( SCIPgetRealParam(scip, "branching/ryanfoster/maxphase1outcandsfrac",
1863  &branchruledata->maxphase1outcandsfrac) );
1864  SCIP_CALL( SCIPgetRealParam(scip, "branching/ryanfoster/phase2gapweight",
1865  &branchruledata->phase2gapweight) );
1866 
1867  assert(branchruledata->maxphase0outcands >= branchruledata->minphase0outcands);
1868  assert(branchruledata->maxphase1outcands >= branchruledata->minphase1outcands);
1869  }
1870 
1871  selectCandidate(scip, branchrule, ovar1s, ovar2s, nspricingblock, npairs,
1872  ovar1, ovar2, pricingblock, sameinf, differinf, result);
1873 
1874  *stillusestrong = !branchruledata->done;
1875 
1876  assert(*ovar1 != NULL);
1877  assert(*ovar2 != NULL);
1878 
1879  return SCIP_OKAY;
1880 }
type definitions for branching rules in GCG projects
#define DEFAULT_PHASE2RELIABLE
SCIP_VAR * var2
#define DEFAULT_MINCOLGENCANDS
#define DEFAULT_MAXLOOKAHEAD
static SCIP_DECL_HASHGETKEY(hashGetKeyVars)
SCIP_BRANCHRULEDATA * this_branchruledata
static SCIP_Bool isKAncestor(SCIP *scip, int ancestornodenr, SCIP_NODE *successornode, int k)
#define branchActiveMasterBPStrong
GCG interface methods.
SCIP_RETCODE GCGrelaxNewProbingnodeMasterCons(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata, SCIP_CONS **origbranchconss, int norigbranchconss, int maxorigbranchconss)
Definition: relax_gcg.c:4430
static SCIP_RETCODE newProbingNodeRyanfosterMaster(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR *ovar1, SCIP_VAR *ovar2, int blocknr, SCIP_Bool same)
SCIP_RETCODE GCGrelaxPerformProbing(SCIP *scip, int maxlpiterations, SCIP_Longint *nlpiterations, SCIP_Real *lpobjvalue, SCIP_Bool *lpsolved, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: relax_gcg.c:4620
SCIP_RETCODE GCGrelaxNewProbingnodeMaster(SCIP *scip)
Definition: relax_gcg.c:4378
#define branchDeactiveMasterBPStrong
#define DEFAULT_RFUSEMOSTFRAC
#define DEFAULT_MAXPHASE2DEPTH
static SCIP_RETCODE executeStrongBranching(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR *branchvar1, SCIP_VAR *branchvar2, SCIP_Real solval1, SCIP_Real solval2, int candinfo, SCIP_Bool pricing, int maxpricingrounds, SCIP_Real *up, SCIP_Real *down, SCIP_Bool *upvalid, SCIP_Bool *downvalid, SCIP_Bool *upinf, SCIP_Bool *downinf)
SCIP_Real maxphase0outcandsfrac
struct VarTuple VarTuple
#define DEFAULT_CLOSEPERCENTAGE
#define branchMasterSolvedBPStrong
#define DEFAULT_MINPHASE0DEPTH
#define DEFAULT_MAXSBLPITERS
int GCGvarGetBlock(SCIP_VAR *var)
Definition: gcgvar.c:1033
int GCGlinkingVarGetNBlocks(SCIP_VAR *var)
Definition: gcgvar.c:493
SCIP_Bool GCGvarIsPricing(SCIP_VAR *var)
Definition: gcgvar.c:134
#define DEFAULT_MAXPHASE1DEPTH
SCIP_VAR * GCGoriginalVarGetPricingVar(SCIP_VAR *var)
Definition: gcgvar.c:216
static int score_compare_function(const void *index1, const void *index2)
branching rule for original problem in GCG
SCIP_Bool GCGvarIsOriginal(SCIP_VAR *var)
Definition: gcgvar.c:166
GCG variable pricer.
#define BRANCHRULE_PRIORITY
SCIP_RETCODE SCIPincludeBranchruleBPStrong(SCIP *scip)
#define branchDataDeleteBPStrong
#define DEFAULT_HISTWEIGHT
SCIP_RETCODE GCGrelaxEndProbing(SCIP *scip)
Definition: relax_gcg.c:4658
SCIP_Bool * sbscoreisrecent
#define ORIG
#define DEFAULT_MAXCONSECHEURCLOSE
#define DEFAULT_MAXSBPRICEROUNDS
SCIP_HASHTABLE * candhashtable
SCIP * GCGgetMasterprob(SCIP *scip)
Definition: relax_gcg.c:3920
SCIP_Longint nsblpiterations
constraint handler for the integrality constraint
SCIP_VAR * var1
constraint handler for storing the branching decisions at each node of the tree
#define DEFAULT_SBPSEUDOCOSTWEIGHT
#define BRANCHRULE_NAME
#define DEFAULT_FORCEP0
int GCGpricingVarGetNOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:997
#define DEFAULT_IMMEDIATEINF
constraint handler for storing the branching decisions at each node of the tree
#define BRANCHRULE_MAXDEPTH
SCIP_Real sbpseudocostweight
int GCGgetNIdenticalBlocks(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4053
#define DEFAULT_PHASE1RELIABLE
SCIP_RETCODE GCGrelaxStartProbing(SCIP *scip, SCIP_HEUR *probingheur)
Definition: relax_gcg.c:4264
SCIP_Real * strongbranchscore
SCIP_RETCODE GCGrelaxNewProbingnodeOrig(SCIP *scip)
Definition: relax_gcg.c:4331
SCIP * GCGmasterGetOrigprob(SCIP *scip)
SCIP_Longint maxsblpiters
#define DEFAULT_DEPTHLOGPHASE2FRAC
#define BRANCHRULE_MAXBOUNDDIST
#define DEFAULT_DEPTHLOGPHASE0FRAC
static int calculateNCands(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_Real nodegap, int phase, int ncands)
#define RYANFOSTER
#define BRANCHRULE_DESC
GCG relaxator.
static SCIP_DECL_BRANCHFREE(branchFreeBPStrong)
SCIP_VAR ** GCGpricingVarGetOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:1015
static SCIP_RETCODE addBranchcandsToData(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR **var1s, SCIP_VAR **var2s, int ncands)
#define branchPropMasterBPStrong
#define DEFAULT_DEPTHLOGWEIGHT
SCIP_RETCODE GCGrelaxPerformProbingWithPricing(SCIP *scip, int maxpricerounds, SCIP_Longint *nlpiterations, int *npricerounds, SCIP_Real *lpobjvalue, SCIP_Bool *lpsolved, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: relax_gcg.c:4639
static SCIP_DECL_HASHKEYVAL(hashKeyValVars)
static SCIP_Real score_function(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR *var1, SCIP_VAR *var2, SCIP_Real solval1, SCIP_Real solval2, int candinfo, SCIP_Bool useheuristic, SCIP_Bool usehistorical, SCIP_Bool usecolgen, SCIP_Real *score, SCIP_Bool *upinf, SCIP_Bool *downinf)
static SCIP_DECL_HASHKEYEQ(hashKeyEqVars)
SCIP_Bool GCGoriginalVarIsLinking(SCIP_VAR *var)
Definition: gcgvar.c:182
static int assignUniqueBlockFlags(SCIP *scip, SCIP_VAR *branchcand)
#define DEFAULT_DEPTHLOGBASE
static SCIP_DECL_BRANCHINIT(branchInitBPStrong)
SCIP_BRANCHRULE * initiatorbranchrule
generic branch and price strong branching as described in Pecin, D., Pessoa, A., Poggi,...
#define DEFAULT_LOOKAHEADSCALES
SCIP_RETCODE GCGbranchSelectCandidateStrongBranchingRyanfoster(SCIP *scip, SCIP_BRANCHRULE *rfbranchrule, SCIP_VAR **ovar1s, SCIP_VAR **ovar2s, int *nspricingblock, int npairs, SCIP_VAR **ovar1, SCIP_VAR **ovar2, int *pricingblock, SCIP_Bool *sameinf, SCIP_Bool *differinf, SCIP_RESULT *result, SCIP_Bool *stillusestrong)
#define DEFAULT_STRONGTRAIN
SCIP_Real maxphase1outcandsfrac
#define DEFAULT_STRONGLITE
#define DEFAULT_RFUSEPSEUDOCOSTS
static SCIP_RETCODE selectCandidate(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR **cand1s, SCIP_VAR **cand2s, int *candinfos, int ncands, SCIP_VAR **outcand1, SCIP_VAR **outcand2, int *outcandinfo, SCIP_Bool *bestupinf, SCIP_Bool *bestdowninf, SCIP_RESULT *result)
SCIP_CONS * pricecons
static int geq_compare_function(const void *index1, const void *index2)
SCIP_RETCODE GCGbranchSelectCandidateStrongBranchingOrig(SCIP *scip, SCIP_BRANCHRULE *origbranchrule, SCIP_VAR **branchvar, SCIP_Bool *upinf, SCIP_Bool *downinf, SCIP_RESULT *result, SCIP_Bool *stillusestrong)
reliable pseudo costs branching rule
SCIP_RETCODE GCGrelaxIncludeBranchrule(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_DECL_BRANCHACTIVEMASTER((*branchactivemaster)), GCG_DECL_BRANCHDEACTIVEMASTER((*branchdeactivemaster)), GCG_DECL_BRANCHPROPMASTER((*branchpropmaster)), GCG_DECL_BRANCHMASTERSOLVED((*branchmastersolved)), GCG_DECL_BRANCHDATADELETE((*branchdatadelete)))
Definition: relax_gcg.c:3545
SCIP_RETCODE GCGlinkingVarGetBlocks(SCIP_VAR *var, int nblocks, int *blocks)
Definition: gcgvar.c:450
#define DEFAULT_REEVALAGE
SCIP_RETCODE GCGconsIntegralorigAddBranchrule(SCIP *scip, SCIP_BRANCHRULE *branchrule)