Scippy

SCIP

Solving Constraint Integer Programs

branch_multaggr.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-2015 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 /**@file branch_multaggr.c
16  * @brief fullstrong branching on fractional and multi-aggregated variables
17  * @author Anna Melchiori
18  * @author Gerald Gamrath
19  *
20  * This branching rule uses all fractional binary and integer variables as candidates,
21  * as well as fractional multiaggregated binary and integer variables. Although not
22  * directly contained in the presolved problem anymore, the multi-aggregation provides
23  * an affine linear sum of integer variables, on which branching can be performed.
24  *
25  * For more details, see
26  * G.Gamrath, A.Melchiori, T.Berthold, A.M.Gleixner, D.Salvagnin: Branching on Multi-aggregated Variables
27  * (http://dx.doi.org/10.1007/978-3-319-18008-3_10)
28  */
29 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
30 
31 #include <assert.h>
32 #include <string.h>
33 
34 #include "scip/branch_multaggr.h"
35 #include "scip/branch_fullstrong.h"
36 #include "scip/cons_linear.h"
37 #include "scip/var.h"
38 #include "scip/set.h"
39 #include "scip/pub_tree.h"
40 #include "scip/struct_scip.h"
41 #include "scip/clock.h"
42 
43 #define BRANCHRULE_NAME "multaggr"
44 #define BRANCHRULE_DESC "fullstrong branching on fractional and multi-aggregated variables"
45 #define BRANCHRULE_PRIORITY 0
46 #define BRANCHRULE_MAXDEPTH -1
47 #define BRANCHRULE_MAXBOUNDDIST 1.0
48 
49 
50 #define DEFAULT_REEVALAGE 0LL /**< number of intermediate LPs solved to trigger reevaluation of strong branching
51  * value for a variable that was already evaluated at the current node */
52 #define DEFAULT_MAXPROPROUNDS 0 /**< maximum number of propagation rounds to be performed during multaggr branching
53  * before solving the LP (-1: no limit, -2: parameter settings) */
54 #define DEFAULT_PROBINGBOUNDS TRUE /**< should valid bounds be identified in a probing-like fashion during multi-aggr
55  * branching (only with propagation)? */
56 
57 /*
58  * Data structures
59  */
60 
61 /** branching rule data */
62 struct SCIP_BranchruleData
63 {
64  SCIP_Longint reevalage; /**< number of intermediate LPs solved to trigger reevaluation of strong branching
65  * value for a variable that was already evaluated at the current node */
66  SCIP_Bool probingbounds; /**< should valid bounds be identified in a probing-like fashion during strong
67  * branching (only with propagation)? */
68  int lastcand; /**< last evaluated candidate of last branching rule execution */
69  int maxproprounds; /**< maximum number of propagation rounds to be performed during strong branching
70  * before solving the LP (-1: no limit, -2: parameter settings) */
71  SCIP_Bool* skipdown; /**< should be branching on down child be skipped? */
72  SCIP_Bool* skipup; /**< should be branching on up child be skipped? */
73 #ifdef SCIP_STATISTIC
74  SCIP_CLOCK* clckstrongbr; /**< clock to store the time spent inside the strong branching function on fractional variables */
75  SCIP_CLOCK* clckmultaggrbr; /**< clock to store the time spent inside the strong branching function on multi-aggragated variables */
76  SCIP_Real* ratioggain; /**< for each occurence of a branching on a multi-aggregated variable we store the ratio of the gain that
77  * we would have obtained branching on the best fractional variable over the gain obtained
78  * branching on the current multi-aggregated variable */
79  SCIP_Real ameanratio; /**< arithmetic mean of the ratioggain array */
80  SCIP_Bool noupdate; /**< pointer to store if the probing LP has not been solved so we do not want to
81  * update statistics */
82  int firstmultaggrdepth; /**< depth of the first branching on a multi-aggregated variable */
83  int rundepth; /**< the run of the first multi-aggregated branching */
84  int nmultaggrbranch; /**< number of branchings on multi-aggregated variables */
85  int nfracbranch; /**< number of branchings on fractional variables */
86  int nEscore; /**< number of times that the bestscore over all multi-aggregated variables is equal to the best
87  * fractional variable´s score and thus we do not branch on the multi-aggregate variable */
88  int nmultaggrcutoff; /**< number of cutoffs detected during the probing mode on multi-aggregated variables */
89  int nmultaggrconsadd; /**< number of times that a probing constraint of a multi-aggregated variable has been
90  * added to the original problem */
91  int nfractcutoff; /**< number of cutoffs detected during strong branching on fractional variables */
92  int nfractconsadd; /**< number of times that during strong branching on fractional variables a constraint has been
93  * added to the original problem or a variable´s domain has been reduced */
94  int nmultaggrvars; /**< number of multi-aggregated variables in the problem of the last run */
95  int nrun; /**< number of restarts */
96  int size; /**< size of the provided array to store the ratio gain */
97  int nstrongbrcall; /**< number of times that the selectVarstrongBranching function has been called */
98  int nmultaggrbrcall; /**< number of times that the selectVarMultAggrBranching function has been called */
99  int totallpcands; /**< total number of observed lpcands over all selectVarstrongBranching function calls */
100  int totalmultaggrcands; /**< total number of observed multi-aggregregated candidates over all selectVarMultAggrBranching
101  * function calls */
102 #endif
103 };
104 
105 
106 /*
107  * Local methods
108  */
109 
110 /* this function ensures that the allocated memory is enough to store statistics data */
111 #ifdef SCIP_STATISTIC
112 static
113 SCIP_RETCODE ensureArraySize(
114  SCIP* scip, /**< original SCIP data structure */
115  SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
116  )
117 {
118  assert(scip != NULL);
119  assert(branchruledata != NULL);
120  assert(branchruledata->ratioggain != NULL);
121  assert(branchruledata->nmultaggrbranch >= 0);
122  assert(branchruledata->size >= 0);
123 
124  /* check whether the size of the array is big enough; reallocate memory if needed */
125  if( branchruledata->nmultaggrbranch + 1 > branchruledata->size )
126  {
127  branchruledata->size = 2 * branchruledata->size;
128  assert(branchruledata->size >= branchruledata->nmultaggrbranch + 1);
129  SCIP_CALL( SCIPreallocMemoryArray(scip, &branchruledata->ratioggain, branchruledata->size) );
130  }
131  return SCIP_OKAY;
132 }
133 #endif
134 
135 /* this function gives us the best candidate for branching among the multi-aggregated variables of the problem
136  * and the best fractional integer variable already selected by strong branching
137 */
138 static
140  SCIP* scip, /**< original SCIP data structure */
141  SCIP_VAR** bestcand, /**< the best candidate variable selected by strong branching */
142  SCIP_Real* bestscore, /**< score of the best branching candidate */
143  SCIP_Real* bestsol, /**< solution value of the best branching candidate */
144  SCIP_Real* bestdown, /**< objective value of the down node when branching on bestcand */
145  SCIP_Real* bestup, /**< objective value of the up node when branching on bestcand */
146  SCIP_Bool* bestdownvalid, /**< is bestdown a valid dual bound for the down branch? */
147  SCIP_Bool* bestupvalid, /**< is bestup a valid dual bound for the up branch? */
148  SCIP_Real* provedbound, /**< proved dual bound for the current subtree */
149  SCIP_Real* estimatedown, /**< pointer to store the down child node´s estimate */
150  SCIP_Real* estimateup, /**< pointer to store the up child node´s estimate */
151 #ifdef SCIP_STATISTIC
152  SCIP_Real* bestmultaggrscore, /**< pointer to store the multi aggregated score */
153 #endif
154  SCIP_RESULT* result /**< pointer to store results of branching */
155  )
156 {
157  SCIP_VAR** fixvars;
158  SCIP_CONS* probingconsdown;
159  SCIP_CONS* probingconsup;
160  SCIP_NODE* node;
161  SCIP_Real* fixvarssols;
162  SCIP_Real fixvarssol;
163  SCIP_Real lpobjval;
164  SCIP_Bool exactsolve;
165  SCIP_Bool allcolsinlp;
166  SCIP_Bool downnodeinf = FALSE;
167  SCIP_Bool startprobing = TRUE;
168  SCIP_Bool endprobing = FALSE;
169  int nfixvars;
170  int i;
171  int j;
172  int k;
173 
174  /* import branchrule data for statistics */
175 #ifdef SCIP_STATISTIC
176  SCIP_BRANCHRULE* branchrule;
177  SCIP_BRANCHRULEDATA* branchruledata;
178 
179  branchrule = SCIPfindBranchrule(scip, BRANCHRULE_NAME);
180  assert(branchrule != NULL);
181 
182  branchruledata = SCIPbranchruleGetData(branchrule);
183  assert(branchruledata != NULL);
184 #endif
185 
186  assert(scip != NULL);
187  assert(bestcand != NULL);
188  assert(bestscore != NULL);
189 
190  /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
191  * for cutting off sub problems and improving lower bounds of children
192  */
193  exactsolve = SCIPisExactSolve(scip);
194 
195  /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
196  allcolsinlp = SCIPallColsInLP(scip);
197 
198  /* get fixed variables */
199  fixvars = SCIPgetFixedVars(scip);
200  nfixvars = SCIPgetNFixedVars(scip);
201  SCIPdebugMessage(" fractional variable: <%s> with value: %f is selected by strong branching\n", SCIPvarGetName(*bestcand), *bestsol);
202 
203  if( nfixvars != 0 )
204  {
205  assert(fixvars != NULL);
206 
207  SCIP_CALL( SCIPallocBufferArray(scip, &fixvarssols, nfixvars) );
208  lpobjval = SCIPgetLPObjval(scip);
209 
210  /* store the values of the fixed variables at the current optimal solution */
211  for( i = 0; i < nfixvars; i++ )
212  {
213  assert(fixvars[i] != NULL);
214  fixvarssols[i] = SCIPvarGetLPSol(fixvars[i]);
215  }
216 
217  for( i = 0; i < nfixvars; i++ )
218  {
219  assert(fixvars[i] != NULL);
220 
221  /* only integer and binary multi-aggregated variables are potential branching candidates */
222  if( SCIPvarGetStatus(fixvars[i]) == SCIP_VARSTATUS_MULTAGGR && (SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_INTEGER ||
223  SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_BINARY) )
224  {
225  fixvarssol = fixvarssols[i];
226 
227  /* start probing mode for the fractional multi-aggregated variable */
228  if( !SCIPisFeasIntegral(scip, fixvarssol) )
229  {
230  SCIP_VAR** downvars = NULL;
231  SCIP_VAR** upvars = NULL;
232  SCIP_Real* downvarssols = NULL;
233  SCIP_Real* upvarssols = NULL;
234  SCIP_LPSOLSTAT solstatdown;
235  SCIP_LPSOLSTAT solstatup;
236  SCIP_Real downobjval;
237  SCIP_Real upobjval;
238  SCIP_Real estimateprobdown = 0.0;
239  SCIP_Real estimateprobup = 0.0;
240  SCIP_Bool downinf;
241  SCIP_Bool upinf;
242  SCIP_Bool lperror;
243  int ndownvars;
244  int nupvars;
245 
246  /* start the probing mode if this is the first entrance */
247  if( startprobing )
248  {
249  SCIP_CALL( SCIPstartProbing(scip) );
250  startprobing = FALSE;
251  endprobing = TRUE;
252 
253  SCIPdebugMessage("PROBING MODE:\n");
254  }
255 
256  SCIPdebugMessage(" multi-aggregated variable: <%s> with value: %f\n", SCIPvarGetName(fixvars[i]), fixvarssol);
257 
258  SCIPstatistic(branchruledata->totalmultaggrcands += 1);
259 
260  /* create the multi-aggregated rounded down constraint */
261  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsdown, "probingconsdown", SCIPvarGetMultaggrNVars(fixvars[i]),
262  SCIPvarGetMultaggrVars(fixvars[i]), SCIPvarGetMultaggrScalars(fixvars[i]), -SCIPinfinity(scip),
263  SCIPfeasFloor(scip, fixvarssol) - SCIPvarGetMultaggrConstant(fixvars[i]), TRUE, TRUE, FALSE, FALSE,
264  TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
265  assert(probingconsdown != NULL);
266 
267  /* create the down child probing node */
268  SCIP_CALL( SCIPnewProbingNode(scip) );
269  node = SCIPgetCurrentNode(scip);
270  assert(node != NULL);
271 
272  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsdown, NULL) );
273  SCIP_CALL( SCIPreleaseCons(scip, &probingconsdown) );
274 
275 #ifdef PRINTNODECONS
276  SCIPdebugMessage(" created down probing node with constraint:\n");
277  SCIP_CALL( SCIPprintCons(scip, probingconsdown, NULL) );
278  SCIPinfoMessage(scip, NULL, "\n");
279 #endif
280 
281  /* solve the down child probing node */
282  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, &downinf) );
283  solstatdown = SCIPgetLPSolstat(scip);
284  lperror = lperror || (solstatdown == SCIP_LPSOLSTAT_NOTSOLVED && downinf == 0) || (solstatdown == SCIP_LPSOLSTAT_ITERLIMIT) ||
285  (solstatdown == SCIP_LPSOLSTAT_TIMELIMIT);
286  assert(solstatdown != SCIP_LPSOLSTAT_UNBOUNDEDRAY);
287 
288  /* break the branching rule if an error occurred, problem was not solved, iteration or time limit was reached */
289  if( lperror )
290  {
291  SCIPdebugMessage("error solving down node probing LP: status=%d\n", solstatdown);
292  SCIPstatistic(branchruledata->noupdate = TRUE);
293  break;
294  }
295 
296  downobjval = SCIPgetLPObjval(scip);
297  downinf = downinf || SCIPisGE(scip, downobjval, SCIPgetCutoffbound(scip));
298  assert(((solstatdown != SCIP_LPSOLSTAT_INFEASIBLE) && (solstatdown != SCIP_LPSOLSTAT_OBJLIMIT)) || downinf);
299 
300  if( !downinf )
301  {
302  /* when an optimal solution has been found calculate down child's estimate based on pseudo costs */
303  /* estimate = lowerbound + sum(min{f_j * pscdown_j, (1-f_j) * pscup_j}) */
304  estimateprobdown = SCIPnodeGetLowerbound(node);
305  SCIP_CALL( SCIPgetLPBranchCands(scip, &downvars, &downvarssols, NULL, &ndownvars, NULL, NULL) );
306 
307  for( j = 0 ; j < ndownvars; j++ )
308  {
309  SCIP_Real estimateincr;
310  SCIP_Real pscdown;
311  SCIP_Real pscup;
312 
313  assert(downvars != NULL);
314  assert(downvars[j] != NULL);
315 
316  pscdown = SCIPvarGetPseudocost(downvars[j], scip->stat, SCIPsetFeasFloor(scip->set, downvarssols[j]) - downvarssols[j]);
317  pscup = SCIPvarGetPseudocost(downvars[j], scip->stat, SCIPsetFeasCeil(scip->set, downvarssols[j]) - downvarssols[j]);
318  estimateincr = MIN(pscdown, pscup);
319 
320  estimateprobdown += estimateincr;
321  }
322  }
323  SCIP_CALL( SCIPbacktrackProbing(scip, 0) );
324 
325  /* create the multi-aggregated rounded up constraint */
326  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsup, "probingconsup", SCIPvarGetMultaggrNVars(fixvars[i]), SCIPvarGetMultaggrVars(fixvars[i]),
327  SCIPvarGetMultaggrScalars(fixvars[i]), SCIPfeasCeil(scip, fixvarssol) - SCIPvarGetMultaggrConstant(fixvars[i]), SCIPinfinity(scip),
329  assert(probingconsup != NULL);
330 
331  /* create the up child probing node */
332  SCIP_CALL( SCIPnewProbingNode(scip) );
333  node = SCIPgetCurrentNode(scip);
334 
335  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsup, NULL) );
336  SCIP_CALL( SCIPreleaseCons(scip, &probingconsup) );
337 
338 #ifdef PRINTNODECONS
339  SCIPdebugMessage(" created up probing node with constraint:\n");
340  SCIP_CALL( SCIPprintCons(scip, probingconsup, NULL) );
341  SCIPinfoMessage(scip, NULL, "\n");
342 #endif
343  /* solve the up child probing node */
344  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, &upinf) );
345  solstatup = SCIPgetLPSolstat(scip);
346  lperror = lperror || (solstatup == SCIP_LPSOLSTAT_NOTSOLVED && upinf == 0) || (solstatup == SCIP_LPSOLSTAT_ITERLIMIT) ||
347  (solstatup == SCIP_LPSOLSTAT_TIMELIMIT);
348  assert(solstatup != SCIP_LPSOLSTAT_UNBOUNDEDRAY);
349 
350  /* break the branching rule if an error occurred, problem was not solved, iteration or time limit was reached */
351  if( lperror )
352  {
353  SCIPdebugMessage("error solving up node probing LP: status=%d\n", solstatup);
354  SCIPstatistic(branchruledata->noupdate = TRUE);
355  break;
356  }
357 
358  upobjval = SCIPgetLPObjval(scip);
359  upinf = upinf || SCIPisGE(scip, upobjval, SCIPgetCutoffbound(scip));
360  assert(((solstatup != SCIP_LPSOLSTAT_INFEASIBLE) && (solstatup != SCIP_LPSOLSTAT_OBJLIMIT)) || upinf);
361 
362  SCIPdebugMessage(" down node objval: %g up node objval: %g\n", downobjval, upobjval);
363 
364  if( !upinf )
365  {
366  /* when an optimal solution has been found calculate up child's estimate based on pseudo costs */
367  /* estimate = lowerbound + sum(min{f_j * pscdown_j, (1-f_j) * pscup_j}) */
368  estimateprobup = SCIPnodeGetLowerbound(node);
369  SCIP_CALL( SCIPgetLPBranchCands(scip, &upvars, &upvarssols, NULL, &nupvars, NULL, NULL) );
370 
371  for( k = 0 ; k < nupvars; k++ )
372  {
373  SCIP_Real estimateincr;
374  SCIP_Real pscdown;
375  SCIP_Real pscup;
376 
377  assert(upvars != NULL);
378  assert(upvars[k] != NULL);
379 
380  pscdown = SCIPvarGetPseudocost(upvars[k], scip->stat, SCIPsetFeasFloor(scip->set, upvarssols[k]) - upvarssols[k]);
381  pscup = SCIPvarGetPseudocost(upvars[k], scip->stat, SCIPsetFeasCeil(scip->set, upvarssols[k]) - upvarssols[k]);
382  estimateincr = MIN(pscdown, pscup);
383  estimateprobup += estimateincr;
384  }
385  }
386  SCIP_CALL( SCIPbacktrackProbing(scip, 0) );
387 
388  /* check whether the children nodes are solved to optimality and give a valid new lower bound or not */
389  if( downinf || upinf )
390  {
391  /* check if the LP is a valid relaxation and we can then collect new information */
392  if( allcolsinlp )
393  {
394  /* cut off the node either when both children are infeasible or the objective limit was reached;
395  * if only one child is feasible with LP value smaller than objective limit, add the corresponding
396  * constraint to the problem and break the branching rule in order to solve the updated LP
397  */
398  if( downinf && upinf )
399  {
400  SCIPdebugMessage("node can be cut off due to strong branching on multi-aggregated variable <%s>\n",
401  SCIPvarGetName(fixvars[i]));
402  SCIPstatistic(branchruledata->nmultaggrcutoff += 1);
403 
404  *result = SCIP_CUTOFF;
405  break;
406  }
407  else
408  {
409  assert(!lperror);
410 
411  if( downinf )
412  downnodeinf = TRUE;
413 
414  SCIPdebugMessage("%s child of multi-aggregated variable <%s> is infeasible\n",
415  downinf ? "down" : "up", SCIPvarGetName(fixvars[i]) );
416  SCIPstatistic(branchruledata->nmultaggrconsadd += 1);
417 
418  *result = SCIP_CONSADDED;
419  break;
420  }
421  }
422  }
423  else
424  {
425  /* if both children are solved to optimality and they both give a new valid bound, calculate the score of the
426  * multi-aggregated variable
427  */
428  SCIP_Real downgain;
429  SCIP_Real upgain;
430  SCIP_Real down;
431  SCIP_Real up;
432  SCIP_Real score;
433  SCIP_Real minbound;
434 
435  assert(!downinf);
436  assert(!upinf);
437  assert(!lperror);
438 
439  SCIPdebugMessage(" both probing nodes are valid while branching on multi-aggregated variable: <%s>\n ", SCIPvarGetName(fixvars[i]));
440 
441  down = MAX(downobjval, lpobjval);
442  up = MAX(upobjval, lpobjval);
443  downgain = down - lpobjval;
444  upgain = up - lpobjval;
445  score = SCIPgetBranchScore(scip, NULL, downgain, upgain);
446 
447  if( allcolsinlp && !exactsolve )
448  {
449  /* the minimal lower bound of both children is a proved lower bound of the current subtree */
450  minbound = MIN(downobjval, upobjval);
451  *provedbound = MAX(*provedbound, minbound);
452  }
453 
455  if( score > *bestmultaggrscore )
456  *bestmultaggrscore = score;
457  );
458 
459  /* update the best branching candidate and all its values if a strictly greater score has been found */
460  if( score > *bestscore )
461  {
463  if( branchruledata->nmultaggrbranch == 0 )
464  {
465  branchruledata->rundepth = SCIPgetNRuns(scip);
466  branchruledata->firstmultaggrdepth = SCIPgetFocusDepth(scip);
467  }
468  )
469 
470  SCIPdebugMessage(" <%s> is a better candidate for branching\n", SCIPvarGetName(fixvars[i]));
471 
472  *bestscore = MAX(score, *bestscore);
473  *bestcand = fixvars[i];
474  *bestsol = fixvarssol;
475  *bestdown = downobjval;
476  *bestup = upobjval;
477  *bestdownvalid = TRUE;
478  *bestupvalid = TRUE;
479  *estimatedown = estimateprobdown;
480  *estimateup = estimateprobup;
481  }
482  assert(bestscore != NULL);
483  assert(bestcand != NULL);
484  assert(bestup != NULL);
485  assert(bestdown != NULL);
486  }
487  }
488  }
489  }
490 
491  /* end probing mode */
492  if( endprobing )
493  {
494  SCIP_CALL( SCIPendProbing(scip) );
495  }
496 
497  SCIPdebugMessage("\n");
498 
499  /* one of the child nodes was infeasible, add the other constraint to the current node */
500  if( *result == SCIP_CONSADDED )
501  {
502  node = SCIPgetCurrentNode(scip);
503  if( downnodeinf )
504  {
505  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsup, "infconsup", SCIPvarGetMultaggrNVars(fixvars[i]),
506  SCIPvarGetMultaggrVars(fixvars[i]), SCIPvarGetMultaggrScalars(fixvars[i]),
507  SCIPfeasCeil(scip, fixvarssols[i]) - SCIPvarGetMultaggrConstant(fixvars[i]), SCIPinfinity(scip),
509  assert(probingconsup != NULL);
510  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsup, NULL) );
511  SCIPdebugMessage(" <%s> new valid constraint has been added to the original problem\n", SCIPconsGetName(probingconsup));
512  SCIP_CALL( SCIPreleaseCons(scip, &probingconsup) );
513  }
514  else
515  {
516  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsdown, "infconsdown", SCIPvarGetMultaggrNVars(fixvars[i]),
517  SCIPvarGetMultaggrVars(fixvars[i]), SCIPvarGetMultaggrScalars(fixvars[i]), - SCIPinfinity(scip),
518  SCIPfeasFloor(scip, fixvarssols[i]) - SCIPvarGetMultaggrConstant(fixvars[i]), TRUE, TRUE, FALSE, FALSE,
519  TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
520  assert(probingconsdown != NULL);
521  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsdown, NULL) );
522  SCIPdebugMessage(" <%s> new valid constraint has been added to the original problem\n", SCIPconsGetName(probingconsdown));
523  SCIP_CALL( SCIPreleaseCons(scip, &probingconsdown) );
524  }
525  }
526  SCIPfreeBufferArray(scip, &fixvarssols);
527  }
528  return SCIP_OKAY;
529 }
530 
531 
532 /*
533  * Callback methods of branching rule
534  */
535 
536 /** copy method for branchrule plugins (called when SCIP copies plugins) */
537 static
538 SCIP_DECL_BRANCHCOPY(branchCopyMultAggr)
539 { /*lint --e{715}*/
540  assert(scip != NULL);
541  assert(branchrule != NULL);
542  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
543 
544  /* call inclusion method of branchrule */
546 
547  return SCIP_OKAY;
548 }
549 
550 /** destructor of branching rule to free user data (called when SCIP is exiting) */
551 static
552 SCIP_DECL_BRANCHFREE(branchFreeMultAggr)
553 { /*lint --e{715}*/
554  SCIP_BRANCHRULEDATA* branchruledata;
556  /* free branching rule data */
557  branchruledata = SCIPbranchruleGetData(branchrule);
558  assert(branchruledata != NULL);
559 
560  SCIPstatistic(SCIPfreeMemoryArrayNull(scip , &branchruledata->ratioggain));
561  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipdown);
562  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipup);
563 
564  SCIPfreeMemory(scip, &branchruledata);
565  SCIPbranchruleSetData(branchrule, NULL);
566 
567  return SCIP_OKAY;
568 }
569 
570 /** initialization method of branching rule (called after problem was transformed) */
571 static
572 SCIP_DECL_BRANCHINIT(branchInitMultAggr)
573 { /*lint --e{715}*/
574  SCIP_BRANCHRULEDATA* branchruledata;
576  branchruledata = SCIPbranchruleGetData(branchrule);
577  assert(branchruledata != NULL);
578 
579  branchruledata->lastcand = 0;
581  branchruledata->firstmultaggrdepth = 0;
582  branchruledata->nmultaggrbranch = 0;
583  branchruledata->nfracbranch = 0;
584  branchruledata->nEscore = 0;
585  branchruledata->nmultaggrcutoff = 0;
586  branchruledata->nmultaggrconsadd = 0;
587  branchruledata->nfractcutoff = 0;
588  branchruledata->nfractconsadd = 0;
589  branchruledata->nrun = 0;
590  branchruledata->size = 100;
591  branchruledata->ameanratio = 0.0;
592  branchruledata->noupdate = FALSE;
593  branchruledata->clckstrongbr = NULL;
594  branchruledata->clckmultaggrbr = NULL;
595  branchruledata->nstrongbrcall = 0;
596  branchruledata->nmultaggrbrcall = 0;
597  branchruledata->totalmultaggrcands = 0;
598  branchruledata->totallpcands = 0;
599  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->ratioggain, branchruledata->size) );
600  BMSclearMemoryArray(branchruledata->ratioggain, branchruledata->size);
601  SCIP_CALL( SCIPcreateClock(scip, &branchruledata->clckstrongbr) );
602  SCIP_CALL( SCIPcreateClock(scip, &branchruledata->clckmultaggrbr) );
603  )
604  return SCIP_OKAY;
605 }
606 
607 /** deinitialization method of branching rule (called before transformed problem is freed) */
608 static
609 SCIP_DECL_BRANCHEXIT(branchExitMultAggr)
610 { /*lint --e{715}*/
611  SCIP_BRANCHRULEDATA* branchruledata;
612  SCIPstatistic(int j = 0);
613 
614  /* initialize branching rule data */
615  branchruledata = SCIPbranchruleGetData(branchrule);
616  assert(branchruledata != NULL);
617  assert((branchruledata->skipdown != NULL) == (branchruledata->skipup != NULL));
618 
619  /* print statistics */
622  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Multi-aggregated branching stats : \n");
623  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrvars : %d (last run)\n",
624  branchruledata->nmultaggrvars);
625  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " firstmultaggrbranchdepth : %d (in run %d)\n",
626  branchruledata->firstmultaggrdepth,
627  branchruledata->rundepth);
628  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrbranch : %d (tot %d)\n",
629  branchruledata->nmultaggrbranch, branchruledata->nmultaggrbranch + branchruledata->nfracbranch);
630  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrcutoff : %d\n", branchruledata->nmultaggrcutoff);
631  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrconsadd : %d\n", branchruledata->nmultaggrconsadd);
632  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nfractcutoff : %d\n", branchruledata->nfractcutoff);
633  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nfractconsadd : %d\n", branchruledata->nfractconsadd);
634  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nEscore : %d\n", branchruledata->nEscore);
635 
636  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Branching Time : \n");
637  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nstrongbrcall : %d\n", branchruledata->nstrongbrcall);
638  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalstrongbrtime : %g\n",
639  SCIPgetClockTime(scip, branchruledata->clckstrongbr));
640  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totallpcands : %d\n", branchruledata->totallpcands);
641 
642  if( branchruledata->totallpcands != 0 )
643  {
644  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimestrongbr : %g\n",
645  SCIPgetClockTime(scip, branchruledata->clckstrongbr) / branchruledata->totallpcands);
646  }
647  else
648  {
649  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimestrongbr : %s\n", "--");
650  }
651 
652  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrbrcall : %d\n", branchruledata->nmultaggrbrcall);
653  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalmultaggrbrtime : %g\n",
654  SCIPgetClockTime(scip, branchruledata->clckmultaggrbr));
655  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalmultaggrcands : %d\n", branchruledata->totalmultaggrcands);
656 
657  if( branchruledata->totalmultaggrcands != 0 )
658  {
659  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimemultaggrbr : %g\n",
660  SCIPgetClockTime(scip, branchruledata->clckmultaggrbr) / branchruledata->totalmultaggrcands);
661  }
662  else
663  {
664  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimemultaggrbr : %s\n", "--");
665  }
666 
667  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Ratioggain :\n");
668  if( branchruledata->nmultaggrbranch != 0 )
669  {
670  for( j = 0; j < branchruledata->nmultaggrbranch; j++ )
671  {
672  branchruledata->ameanratio += branchruledata->ratioggain[j];
673  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " %g", branchruledata->ratioggain[j]);
674  }
675 
677  branchruledata->ameanratio = branchruledata->ameanratio / branchruledata->nmultaggrbranch;
679  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " ameanratio : %4.2f\n", branchruledata->ameanratio);
680  }
681  else
682  {
683  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " ameanratio : %s\n", "--");
684  }
685 
687 
688  /* free arrays */
689  if( branchruledata->ratioggain != NULL )
690  {
691  SCIPfreeMemoryArray(scip, &branchruledata->ratioggain);
692  branchruledata->ratioggain = NULL;
693  }
694  SCIP_CALL( SCIPfreeClock(scip, &branchruledata->clckstrongbr) );
695  SCIP_CALL( SCIPfreeClock(scip, &branchruledata->clckmultaggrbr) );
696  )
697  if( branchruledata->skipdown != NULL )
698  {
699  SCIPfreeMemoryArray(scip, &branchruledata->skipup);
700  SCIPfreeMemoryArray(scip, &branchruledata->skipdown);
701  branchruledata->skipdown = NULL;
702  branchruledata->skipup = NULL;
703  }
704  return SCIP_OKAY;
705 }
706 
707 /** branching execution method for fractional LP solutions */
708 static
709 SCIP_DECL_BRANCHEXECLP(branchExeclpMultAggr)
710 { /*lint --e{715}*/
711 
712  SCIP_BRANCHRULEDATA* branchruledata;
713  SCIP_VAR** lpcands;
714  SCIP_VAR** tmplpcands;
715  SCIP_Real* lpcandssol;
716  SCIP_Real* lpcandsfrac;
717  SCIP_Real* tmplpcandssol;
718  SCIP_Real* tmplpcandsfrac;
719  SCIP_NODE* downchild;
720  SCIP_NODE* upchild;
721  SCIP_Real bestup;
722  SCIP_Real bestdown;
723  SCIP_Real bestscore;
724  SCIP_Real provedbound;
725  SCIP_Real estimatedown = 0.0;
726  SCIP_Real estimateup = 0.0;
727  SCIP_Bool bestdownvalid;
728  SCIP_Bool bestupvalid;
729  SCIP_Longint oldreevalage;
730  int bestcandpos;
731  int nlpcands;
732  int npriolpcands;
734  SCIP_Real lpobjval;
735  SCIP_Bool reoptimize;
736  )
737 
738  assert(branchrule != NULL);
739  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
740  assert(scip != NULL);
741  assert(result != NULL);
742 
743  SCIPdebugMessage("Execlp method of mult-aggreg branching\n ");
744  *result = SCIP_DIDNOTRUN;
745 
746  /* get branching rule data */
747  branchruledata = SCIPbranchruleGetData(branchrule);
748  assert(branchruledata != NULL);
749 
750  SCIP_CALL( SCIPgetLongintParam(scip, "branching/fullstrong/reevalage", &oldreevalage) );
751  SCIP_CALL( SCIPsetLongintParam(scip, "branching/fullstrong/reevalage", branchruledata->reevalage) );
752 
753  /* get the lpobjval and the number of multi aggregated variables of the problem as a statistic counter */
755  reoptimize = FALSE;
756  lpobjval = SCIPgetLPObjval(scip);
757 
758  if( SCIPgetNRuns(scip) != branchruledata->nrun )
759  {
760  SCIP_VAR** fixvars = NULL;
761  int nfixvars;
762  int i;
763 
764  branchruledata->nmultaggrvars = 0;
765  fixvars = SCIPgetFixedVars(scip);
766  nfixvars = SCIPgetNFixedVars(scip);
767 
768  if( nfixvars != 0 )
769  {
770  for( i = 0; i < nfixvars; i++ )
771  {
772  if( SCIPvarGetStatus(fixvars[i]) == SCIP_VARSTATUS_MULTAGGR && (SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_INTEGER ||
773  SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_BINARY) )
774  {
775  branchruledata->nmultaggrvars += 1;
776  }
777  }
778  }
779  branchruledata->nrun = SCIPgetNRuns(scip);
780  }
781  )
782 
783  /* get all branching candidates */
784  SCIP_CALL( SCIPgetLPBranchCands(scip, &tmplpcands, &tmplpcandssol, &tmplpcandsfrac, &nlpcands, &npriolpcands, NULL) );
785  assert(nlpcands > 0);
786  assert(npriolpcands > 0);
787 
788  /* copy LP branching candidates and solution values, because they will be updated w.r.t. the strong branching LP
789  * solution
790  */
791  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcands, tmplpcands, nlpcands) );
792  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandssol, tmplpcandssol, nlpcands) );
793  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandsfrac, tmplpcandsfrac, nlpcands) );
794 
795  if( branchruledata->skipdown == NULL )
796  {
797  int nvars = SCIPgetNVars(scip);
798 
799  assert(branchruledata->skipup == NULL);
800 
801  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipdown, nvars) );
802  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipup, nvars) );
803  BMSclearMemoryArray(branchruledata->skipdown, nvars);
804  BMSclearMemoryArray(branchruledata->skipup, nvars);
805  }
806 
807  /* start the clock to get the time spent inside the function */
809  SCIP_CALL( SCIPstartClock(scip, branchruledata->clckstrongbr) );
810  );
811 
812  /* compute strong branching among the array of fractional variables in order to get the best one */
813  SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcands, lpcandssol, lpcandsfrac, branchruledata->skipdown,
814  branchruledata->skipup, nlpcands, npriolpcands, nlpcands, &branchruledata->lastcand, allowaddcons,
815  branchruledata->maxproprounds, branchruledata->probingbounds, TRUE,
816  &bestcandpos, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
817 
819  SCIP_CALL( SCIPstopClock(scip, branchruledata->clckstrongbr) );
820  branchruledata->totallpcands += SCIPgetNLPBranchCands(scip);
821  branchruledata->nstrongbrcall += 1;
822  )
823 
824  if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED )
825  {
826  SCIP_VAR* bestcand = lpcands[bestcandpos];
827  SCIP_Real bestsol = lpcandssol[bestcandpos];
828  SCIPstatistic( SCIP_Real bestmultaggrscore = -SCIPinfinity(scip); )
829 
831  SCIP_Real fdowngain = 0.0;
832  SCIP_Real fupgain = 0.0;
833 
834  /* reoptimize is set to true if strong branching on fractional variables did not explicitly evaluate the objective
835  * values of the probing child nodes and thus we do not have updated information
836  */
837  if( SCIPisLT(scip, SCIPgetVarStrongbranchLPAge(scip, bestcand), branchruledata->reevalage)
838  || branchruledata->maxproprounds != 0 )
839  reoptimize = TRUE;
840 
841  /* store values needed for the ratioggain statistic */
842  if( !reoptimize )
843  {
844  SCIP_Real fdown;
845  SCIP_Real fup;
846 
847  fdown = MAX(bestdown, lpobjval);
848  fup = MAX(bestup, lpobjval);
849  fdowngain = fdown - lpobjval;
850  fupgain = fup - lpobjval;
851  }
852 
853  /* start and then stop the clock to get the time spent inside the function */
854  SCIP_CALL( SCIPstartClock(scip, branchruledata->clckmultaggrbr) );
855  )
856 
857  /* compute strong branching among the multi-aggregated variables and the best fractional variable */
858 #ifdef SCIP_STATISTIC
859  SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
860  &estimatedown, &estimateup, &bestmultaggrscore, result) );
861 #else
862  SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
863  &estimatedown, &estimateup, result) );
864 #endif
866  SCIP_CALL( SCIPstopClock(scip, branchruledata->clckmultaggrbr) );
867  branchruledata->nmultaggrbrcall += 1;
868  )
869 
870  if( *result != SCIP_CUTOFF && *result != SCIP_CONSADDED )
871  {
873  if( !(branchruledata->noupdate) )
874  {
875  if( SCIPisEQ(scip, bestmultaggrscore, bestscore) )
876  branchruledata->nEscore += 1;
877  }
878  )
879 
880  assert(bestcand != NULL);
881  SCIPdebugMessage("BRANCHING MODE:\n");
882 
883  /* perform branching on the best found candidate */
884  if( SCIPvarGetStatus(bestcand) == SCIP_VARSTATUS_MULTAGGR )
885  {
886  SCIP_CONS* multaggrconsdown;
887  SCIP_CONS* multaggrconsup;
888 
890  if( !(branchruledata->noupdate) )
891  {
892  branchruledata->nmultaggrbranch += 1;
893 
894  if( !reoptimize )
895  {
896  SCIP_Real gfractbranch;
897  SCIP_Real gmultaggrbranch;
898  SCIP_Real downgain;
899  SCIP_Real upgain;
900  SCIP_Real down;
901  SCIP_Real up;
902  int nmultaggrbranch;
903 
904  down = MAX(bestdown, lpobjval);
905  up = MAX(bestup, lpobjval);
906  downgain = down - lpobjval;
907  upgain = up - lpobjval;
908 
909  SCIP_CALL( ensureArraySize(scip, branchruledata) );
910 
911  gfractbranch= SQRT(MAX(fdowngain,1e-06) * MAX(fupgain,1e-06));
912  gmultaggrbranch = SQRT(MAX(downgain,1e-06) * MAX(upgain,1e-06));
913 
914  nmultaggrbranch = branchruledata->nmultaggrbranch;
915 
916  if( gmultaggrbranch == 0.0 )
917  {
918  branchruledata->ratioggain[nmultaggrbranch - 1] = 1;
919  }
920  else
921  {
922  branchruledata->ratioggain[nmultaggrbranch - 1] = gfractbranch / gmultaggrbranch;
923  }
924  }
925  }
926  )
927 
928  /* create the multi-aggregated constraints rounded up and down */
929  SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsdown, "consdown", SCIPvarGetMultaggrNVars(bestcand),
930  SCIPvarGetMultaggrVars(bestcand), SCIPvarGetMultaggrScalars(bestcand), - SCIPinfinity(scip),
931  SCIPfeasFloor(scip, bestsol) - SCIPvarGetMultaggrConstant(bestcand),
933 
934  SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsup, "consup", SCIPvarGetMultaggrNVars(bestcand),
936  SCIPfeasCeil(scip, bestsol) - SCIPvarGetMultaggrConstant(bestcand), SCIPinfinity(scip),
938 
939  /* create the child nodes */
940  SCIP_CALL( SCIPcreateChild(scip, &downchild, 1.0, estimatedown) );
941  SCIPdebugMessage(" down node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(downchild), SCIPnodeGetEstimate(downchild));
942 
943  SCIP_CALL( SCIPcreateChild(scip, &upchild, 1.0, estimateup) );
944  SCIPdebugMessage(" up node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(upchild), SCIPnodeGetEstimate(upchild));
945 
946  assert(downchild != NULL);
947  assert(upchild != NULL);
948 
949  SCIP_CALL( SCIPaddConsNode(scip, downchild, multaggrconsdown, NULL) );
950  SCIP_CALL( SCIPaddConsNode(scip, upchild, multaggrconsup, NULL) );
951 
952 #ifdef PRINTNODECONS
953  SCIPdebugMessage("branching at node %lld\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
954 
955  SCIPdebugMessage("created child node %lld with constraint:\n", SCIPnodeGetNumber(downchild));
956  SCIP_CALL( SCIPprintCons(scip, multaggrconsdown, NULL) );
957  SCIPinfoMessage(scip, NULL, "\n");
958 
959  SCIPdebugMessage("created child node %lld with constraint:\n", SCIPnodeGetNumber(upchild));
960  SCIP_CALL( SCIPprintCons(scip, multaggrconsup, NULL) );
961  SCIPinfoMessage(scip, NULL, "\n");
962 #endif
963 
964  /* relase constraints */
965  SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsdown) );
966  SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsup) );
967 
968  SCIPdebugMessage("BRANCHED on multi-aggregated variable <%s>\n", SCIPvarGetName(bestcand));
969 
970  *result = SCIP_BRANCHED;
971  }
972  else
973  {
975  if( !(branchruledata->noupdate) )
976  branchruledata->nfracbranch += 1
977  );
978 
979  assert(*result == SCIP_DIDNOTRUN);
980  assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
981 
982  SCIP_CALL( SCIPbranchVar(scip, bestcand, &downchild, NULL, &upchild) );
983 
984  assert(downchild != NULL);
985  assert(upchild != NULL);
986 
987  SCIPdebugMessage("BRANCHED on fractional variable <%s>\n", SCIPvarGetName(bestcand));
988 
989  *result = SCIP_BRANCHED;
990  }
991 
992  /* update the lower bounds in the children; we must not do this if columns are missing in the LP
993  * (e.g., because we are doing branch-and-price) or the problem should be solved exactly
994  */
995  if( SCIPallColsInLP(scip) && !SCIPisExactSolve(scip) )
996  {
997  SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
998  SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
999  }
1000  SCIPdebugMessage(" -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
1001  SCIPdebugMessage(" -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
1002  }
1003  }
1004  else
1005  {
1006  SCIPdebugMessage("strong branching breaks\n" );
1007 
1008  SCIPstatistic(
1009  if( *result == SCIP_CUTOFF )
1010  {
1011  branchruledata->nfractcutoff += 1;
1012  }
1013  else
1014  {
1015  branchruledata->nfractconsadd += 1;
1016  }
1017  )
1018  }
1019 
1020  SCIPfreeBufferArray(scip, &lpcandsfrac);
1021  SCIPfreeBufferArray(scip, &lpcandssol);
1022  SCIPfreeBufferArray(scip, &lpcands);
1023 
1024  SCIP_CALL( SCIPsetLongintParam(scip, "branching/fullstrong/reevalage", oldreevalage) );
1025 
1026  return SCIP_OKAY;
1027 }
1028 
1029 /*
1030  * branching rule specific interface methods
1031  */
1032 
1033 /** creates the multi-aggregated branching rule and includes it in SCIP */
1035  SCIP* scip /**< SCIP data structure */
1036 )
1038  SCIP_BRANCHRULEDATA* branchruledata;
1039  SCIP_BRANCHRULE* branchrule;
1040 
1041  /* create multaggr branching rule data */
1042  SCIP_CALL( SCIPallocMemory(scip, &branchruledata) );
1043  branchruledata->lastcand = 0;
1044  branchruledata->skipup = NULL;
1045  branchruledata->skipdown = NULL;
1046  SCIPstatistic(branchruledata->ratioggain = NULL);
1047 
1048  /* include branching rule */
1050  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
1051 
1052  assert(branchrule != NULL);
1053 
1054  /* set non fundamental callbacks via setter functions */
1055  SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyMultAggr) );
1056  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeMultAggr) );
1057  SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitMultAggr) );
1058  SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitMultAggr) );
1059  SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpMultAggr) );
1060 
1061  /* multi-aggregated branching rule parameters */
1063  "branching/multaggr/reevalage",
1064  "number of intermediate LPs solved to trigger reevaluation of strong branching value for a variable that was already evaluated at the current node",
1065  &branchruledata->reevalage, TRUE, DEFAULT_REEVALAGE, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1066  SCIP_CALL( SCIPaddIntParam(scip,
1067  "branching/multaggr/maxproprounds",
1068  "maximum number of propagation rounds to be performed during multaggr branching before solving the LP (-1: no limit, -2: parameter settings)",
1069  &branchruledata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
1071  "branching/multaggr/probingbounds",
1072  "should valid bounds be identified in a probing-like fashion during multaggr branching (only with propagation)?",
1073  &branchruledata->probingbounds, TRUE, DEFAULT_PROBINGBOUNDS, NULL, NULL) );
1074 
1075  return SCIP_OKAY;
1076 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:32768
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41180
SCIP_STAT * stat
Definition: struct_scip.h:64
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16759
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:32398
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:32735
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40341
static SCIP_DECL_BRANCHFREE(branchFreeMultAggr)
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10735
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
SCIP_RETCODE SCIPsetBranchruleExit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXIT((*branchexit)))
Definition: scip.c:8307
public methods for branch and bound tree
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip.c:33344
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40392
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:31860
int SCIPgetFocusDepth(SCIP *scip)
Definition: scip.c:37776
internal methods for clocks and timing issues
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41640
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40375
SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
Definition: scip.c:8291
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:43
#define DEFAULT_REEVALAGE
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40524
#define FALSE
Definition: def.h:53
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4015
#define BRANCHRULE_MAXDEPTH
#define TRUE
Definition: def.h:52
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1877
static SCIP_DECL_BRANCHEXIT(branchExitMultAggr)
SCIP_VAR ** SCIPgetFixedVars(SCIP *scip)
Definition: scip.c:11009
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41616
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38147
#define DEFAULT_MAXPROPROUNDS
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26426
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip.c:8259
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3570
#define SCIPdebugMessage
Definition: pub_message.h:77
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20414
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip.c:8275
#define DEFAULT_PROBINGBOUNDS
#define SCIP_LONGINT_MAX
Definition: def.h:110
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:26224
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24936
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:26469
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41652
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:26816
static SCIP_RETCODE selectVarMultAggrBranching(SCIP *scip, SCIP_VAR **bestcand, SCIP_Real *bestscore, SCIP_Real *bestsol, SCIP_Real *bestdown, SCIP_Real *bestup, SCIP_Bool *bestdownvalid, SCIP_Bool *bestupvalid, SCIP_Real *provedbound, SCIP_Real *estimatedown, SCIP_Real *estimateup, SCIP_RESULT *result)
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition: scip.c:12400
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7016
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:3516
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16460
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:3542
SCIP_Longint SCIPgetVarStrongbranchLPAge(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19400
#define BRANCHRULE_NAME
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip.c:8357
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41193
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13666
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:8222
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20355
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20426
SCIP_RETCODE SCIPincludeBranchruleMultAggr(SCIP *scip)
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1765
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7624
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5609
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16735
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41245
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:263
SCIP main data structure.
#define BRANCHRULE_MAXBOUNDDIST
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11966
internal methods for problem variables
full strong LP branching rule
fullstrong branching on fractional and multi-aggregated variables
#define SCIP_Bool
Definition: def.h:50
static SCIP_DECL_BRANCHINIT(branchInitMultAggr)
#define MAX(x, y)
Definition: tclique_def.h:75
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16723
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20373
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:31763
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:36928
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip.h:20363
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16747
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:31895
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20357
Constraint handler for linear constraints in their most general form, .
SCIP_RETCODE SCIPgetLongintParam(SCIP *scip, const char *name, SCIP_Longint *value)
Definition: scip.c:3747
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:36389
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:7046
#define BRANCHRULE_DESC
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1270
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41232
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17329
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16506
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5598
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20371
int SCIPgetNFixedVars(SCIP *scip)
Definition: scip.c:11052
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1755
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1253
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: scip.c:33190
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_SET * set
Definition: struct_scip.h:57
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20422
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:8405
#define SCIPstatistic(x)
Definition: pub_message.h:101
static SCIP_DECL_BRANCHCOPY(branchCopyMultAggr)
#define SCIP_Real
Definition: def.h:124
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:31800
#define MIN(x, y)
Definition: memory.c:63
static SCIP_DECL_BRANCHEXECLP(branchExeclpMultAggr)
#define BRANCHRULE_PRIORITY
#define SCIP_Longint
Definition: def.h:109
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40290
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7036
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip.c:33311
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_RETCODE SCIPselectVarStrongBranching(SCIP *scip, SCIP_VAR **lpcands, SCIP_Real *lpcandssol, SCIP_Real *lpcandsfrac, SCIP_Bool *skipdown, SCIP_Bool *skipup, int nlpcands, int npriolpcands, int ncomplete, int *start, SCIP_Bool allowaddcons, int maxproprounds, SCIP_Bool probingbounds, SCIP_Bool forcestrongbranch, int *bestcand, SCIP_Real *bestdown, SCIP_Real *bestup, SCIP_Real *bestscore, SCIP_Bool *bestdownvalid, SCIP_Bool *bestupvalid, SCIP_Real *provedbound, SCIP_RESULT *result)
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:20374
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip.c:1012