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-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 /**@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 variables 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 variables 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 nodes estimate */
150  SCIP_Real* estimateup, /**< pointer to store the up child nodes 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  /* check if we would exceed the depth limit */
204  if( SCIPgetDepthLimit(scip) <= SCIPgetDepth(scip) )
205  {
206  SCIPdebugMessage("cannot perform probing in selectVarMultAggrBranching, depth limit reached.\n");
207  *result = SCIP_DIDNOTRUN;
208  return SCIP_OKAY;
209  }
210 
211  if( nfixvars != 0 )
212  {
213  assert(fixvars != NULL);
214 
215  SCIP_CALL( SCIPallocBufferArray(scip, &fixvarssols, nfixvars) );
216  lpobjval = SCIPgetLPObjval(scip);
217 
218  /* store the values of the fixed variables at the current optimal solution */
219  for( i = 0; i < nfixvars; i++ )
220  {
221  assert(fixvars[i] != NULL);
222  fixvarssols[i] = SCIPvarGetLPSol(fixvars[i]);
223  }
224 
225  for( i = 0; i < nfixvars; i++ )
226  {
227  assert(fixvars[i] != NULL);
228 
229  /* only integer and binary multi-aggregated variables are potential branching candidates */
230  if( SCIPvarGetStatus(fixvars[i]) == SCIP_VARSTATUS_MULTAGGR && (SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_INTEGER ||
231  SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_BINARY) )
232  {
233  fixvarssol = fixvarssols[i];
234 
235  /* start probing mode for the fractional multi-aggregated variable */
236  if( !SCIPisFeasIntegral(scip, fixvarssol) )
237  {
238  SCIP_VAR** downvars = NULL;
239  SCIP_VAR** upvars = NULL;
240  SCIP_Real* downvarssols = NULL;
241  SCIP_Real* upvarssols = NULL;
242  SCIP_LPSOLSTAT solstatdown;
243  SCIP_LPSOLSTAT solstatup;
244  SCIP_Real downobjval;
245  SCIP_Real upobjval;
246  SCIP_Real estimateprobdown = 0.0;
247  SCIP_Real estimateprobup = 0.0;
248  SCIP_Bool downinf;
249  SCIP_Bool upinf;
250  SCIP_Bool lperror;
251  int ndownvars;
252  int nupvars;
253 
254  /* start the probing mode if this is the first entrance */
255  if( startprobing )
256  {
257  SCIP_CALL( SCIPstartProbing(scip) );
258  startprobing = FALSE;
259  endprobing = TRUE;
260 
261  SCIPdebugMessage("PROBING MODE:\n");
262  }
263 
264  SCIPdebugMessage(" multi-aggregated variable: <%s> with value: %f\n", SCIPvarGetName(fixvars[i]), fixvarssol);
265 
266  SCIPstatistic(branchruledata->totalmultaggrcands += 1);
267 
268  /* create the multi-aggregated rounded down constraint */
269  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsdown, "probingconsdown", SCIPvarGetMultaggrNVars(fixvars[i]),
270  SCIPvarGetMultaggrVars(fixvars[i]), SCIPvarGetMultaggrScalars(fixvars[i]), -SCIPinfinity(scip),
271  SCIPfeasFloor(scip, fixvarssol) - SCIPvarGetMultaggrConstant(fixvars[i]), TRUE, TRUE, FALSE, FALSE,
272  TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
273  assert(probingconsdown != NULL);
274 
275  /* create the down child probing node */
276  SCIP_CALL( SCIPnewProbingNode(scip) );
277  node = SCIPgetCurrentNode(scip);
278  assert(node != NULL);
279 
280  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsdown, NULL) );
281  SCIP_CALL( SCIPreleaseCons(scip, &probingconsdown) );
282 
283 #ifdef PRINTNODECONS
284  SCIPdebugMessage(" created down probing node with constraint:\n");
285  SCIP_CALL( SCIPprintCons(scip, probingconsdown, NULL) );
286  SCIPinfoMessage(scip, NULL, "\n");
287 #endif
288 
289  /* solve the down child probing node */
290  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, &downinf) );
291  solstatdown = SCIPgetLPSolstat(scip);
292  lperror = lperror || (solstatdown == SCIP_LPSOLSTAT_NOTSOLVED && downinf == 0) || (solstatdown == SCIP_LPSOLSTAT_ITERLIMIT) ||
293  (solstatdown == SCIP_LPSOLSTAT_TIMELIMIT);
294  assert(solstatdown != SCIP_LPSOLSTAT_UNBOUNDEDRAY);
295 
296  /* break the branching rule if an error occurred, problem was not solved, iteration or time limit was reached */
297  if( lperror )
298  {
299  SCIPdebugMessage("error solving down node probing LP: status=%d\n", solstatdown);
300  SCIPstatistic(branchruledata->noupdate = TRUE);
301  break;
302  }
303 
304  downobjval = SCIPgetLPObjval(scip);
305  downinf = downinf || SCIPisGE(scip, downobjval, SCIPgetCutoffbound(scip));
306  assert(((solstatdown != SCIP_LPSOLSTAT_INFEASIBLE) && (solstatdown != SCIP_LPSOLSTAT_OBJLIMIT)) || downinf);
307 
308  if( !downinf )
309  {
310  /* when an optimal solution has been found calculate down child's estimate based on pseudo costs */
311  /* estimate = lowerbound + sum(min{f_j * pscdown_j, (1-f_j) * pscup_j}) */
312  estimateprobdown = SCIPnodeGetLowerbound(node);
313  SCIP_CALL( SCIPgetLPBranchCands(scip, &downvars, &downvarssols, NULL, &ndownvars, NULL, NULL) );
314 
315  for( j = 0 ; j < ndownvars; j++ )
316  {
317  SCIP_Real estimateincr;
318  SCIP_Real pscdown;
319  SCIP_Real pscup;
320 
321  assert(downvars != NULL);
322  assert(downvars[j] != NULL);
323 
324  pscdown = SCIPvarGetPseudocost(downvars[j], scip->stat, SCIPsetFeasFloor(scip->set, downvarssols[j]) - downvarssols[j]);
325  pscup = SCIPvarGetPseudocost(downvars[j], scip->stat, SCIPsetFeasCeil(scip->set, downvarssols[j]) - downvarssols[j]);
326  estimateincr = MIN(pscdown, pscup);
327 
328  estimateprobdown += estimateincr;
329  }
330  }
331  SCIP_CALL( SCIPbacktrackProbing(scip, 0) );
332 
333  /* create the multi-aggregated rounded up constraint */
334  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsup, "probingconsup", SCIPvarGetMultaggrNVars(fixvars[i]), SCIPvarGetMultaggrVars(fixvars[i]),
335  SCIPvarGetMultaggrScalars(fixvars[i]), SCIPfeasCeil(scip, fixvarssol) - SCIPvarGetMultaggrConstant(fixvars[i]), SCIPinfinity(scip),
337  assert(probingconsup != NULL);
338 
339  /* create the up child probing node */
340  SCIP_CALL( SCIPnewProbingNode(scip) );
341  node = SCIPgetCurrentNode(scip);
342 
343  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsup, NULL) );
344  SCIP_CALL( SCIPreleaseCons(scip, &probingconsup) );
345 
346 #ifdef PRINTNODECONS
347  SCIPdebugMessage(" created up probing node with constraint:\n");
348  SCIP_CALL( SCIPprintCons(scip, probingconsup, NULL) );
349  SCIPinfoMessage(scip, NULL, "\n");
350 #endif
351  /* solve the up child probing node */
352  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, &upinf) );
353  solstatup = SCIPgetLPSolstat(scip);
354  lperror = lperror || (solstatup == SCIP_LPSOLSTAT_NOTSOLVED && upinf == 0) || (solstatup == SCIP_LPSOLSTAT_ITERLIMIT) ||
355  (solstatup == SCIP_LPSOLSTAT_TIMELIMIT);
356  assert(solstatup != SCIP_LPSOLSTAT_UNBOUNDEDRAY);
357 
358  /* break the branching rule if an error occurred, problem was not solved, iteration or time limit was reached */
359  if( lperror )
360  {
361  SCIPdebugMessage("error solving up node probing LP: status=%d\n", solstatup);
362  SCIPstatistic(branchruledata->noupdate = TRUE);
363  break;
364  }
365 
366  upobjval = SCIPgetLPObjval(scip);
367  upinf = upinf || SCIPisGE(scip, upobjval, SCIPgetCutoffbound(scip));
368  assert(((solstatup != SCIP_LPSOLSTAT_INFEASIBLE) && (solstatup != SCIP_LPSOLSTAT_OBJLIMIT)) || upinf);
369 
370  SCIPdebugMessage(" down node objval: %g up node objval: %g\n", downobjval, upobjval);
371 
372  if( !upinf )
373  {
374  /* when an optimal solution has been found calculate up child's estimate based on pseudo costs */
375  /* estimate = lowerbound + sum(min{f_j * pscdown_j, (1-f_j) * pscup_j}) */
376  estimateprobup = SCIPnodeGetLowerbound(node);
377  SCIP_CALL( SCIPgetLPBranchCands(scip, &upvars, &upvarssols, NULL, &nupvars, NULL, NULL) );
378 
379  for( k = 0 ; k < nupvars; k++ )
380  {
381  SCIP_Real estimateincr;
382  SCIP_Real pscdown;
383  SCIP_Real pscup;
384 
385  assert(upvars != NULL);
386  assert(upvars[k] != NULL);
387 
388  pscdown = SCIPvarGetPseudocost(upvars[k], scip->stat, SCIPsetFeasFloor(scip->set, upvarssols[k]) - upvarssols[k]);
389  pscup = SCIPvarGetPseudocost(upvars[k], scip->stat, SCIPsetFeasCeil(scip->set, upvarssols[k]) - upvarssols[k]);
390  estimateincr = MIN(pscdown, pscup);
391  estimateprobup += estimateincr;
392  }
393  }
394  SCIP_CALL( SCIPbacktrackProbing(scip, 0) );
395 
396  /* check whether the children nodes are solved to optimality and give a valid new lower bound or not */
397  if( downinf || upinf )
398  {
399  /* check if the LP is a valid relaxation and we can then collect new information */
400  if( allcolsinlp )
401  {
402  /* cut off the node either when both children are infeasible or the objective limit was reached;
403  * if only one child is feasible with LP value smaller than objective limit, add the corresponding
404  * constraint to the problem and break the branching rule in order to solve the updated LP
405  */
406  if( downinf && upinf )
407  {
408  SCIPdebugMessage("node can be cut off due to strong branching on multi-aggregated variable <%s>\n",
409  SCIPvarGetName(fixvars[i]));
410  SCIPstatistic(branchruledata->nmultaggrcutoff += 1);
411 
412  *result = SCIP_CUTOFF;
413  break;
414  }
415  else
416  {
417  assert(!lperror);
418 
419  if( downinf )
420  downnodeinf = TRUE;
421 
422  SCIPdebugMessage("%s child of multi-aggregated variable <%s> is infeasible\n",
423  downinf ? "down" : "up", SCIPvarGetName(fixvars[i]) );
424  SCIPstatistic(branchruledata->nmultaggrconsadd += 1);
425 
426  *result = SCIP_CONSADDED;
427  break;
428  }
429  }
430  }
431  else
432  {
433  /* if both children are solved to optimality and they both give a new valid bound, calculate the score of the
434  * multi-aggregated variable
435  */
436  SCIP_Real downgain;
437  SCIP_Real upgain;
438  SCIP_Real down;
439  SCIP_Real up;
440  SCIP_Real score;
441  SCIP_Real minbound;
442 
443  assert(!downinf);
444  assert(!upinf);
445  assert(!lperror);
446 
447  SCIPdebugMessage(" both probing nodes are valid while branching on multi-aggregated variable: <%s>\n ", SCIPvarGetName(fixvars[i]));
448 
449  down = MAX(downobjval, lpobjval);
450  up = MAX(upobjval, lpobjval);
451  downgain = down - lpobjval;
452  upgain = up - lpobjval;
453  score = SCIPgetBranchScore(scip, NULL, downgain, upgain);
454 
455  if( allcolsinlp && !exactsolve )
456  {
457  /* the minimal lower bound of both children is a proved lower bound of the current subtree */
458  minbound = MIN(downobjval, upobjval);
459  *provedbound = MAX(*provedbound, minbound);
460  }
461 
463  if( score > *bestmultaggrscore )
464  *bestmultaggrscore = score;
465  );
466 
467  /* update the best branching candidate and all its values if a strictly greater score has been found */
468  if( score > *bestscore )
469  {
471  if( branchruledata->nmultaggrbranch == 0 )
472  {
473  branchruledata->rundepth = SCIPgetNRuns(scip);
474  branchruledata->firstmultaggrdepth = SCIPgetFocusDepth(scip);
475  }
476  )
477 
478  SCIPdebugMessage(" <%s> is a better candidate for branching\n", SCIPvarGetName(fixvars[i]));
479 
480  *bestscore = MAX(score, *bestscore);
481  *bestcand = fixvars[i];
482  *bestsol = fixvarssol;
483  *bestdown = downobjval;
484  *bestup = upobjval;
485  *bestdownvalid = TRUE;
486  *bestupvalid = TRUE;
487  *estimatedown = estimateprobdown;
488  *estimateup = estimateprobup;
489  }
490  assert(bestscore != NULL);
491  assert(bestcand != NULL);
492  assert(bestup != NULL);
493  assert(bestdown != NULL);
494  }
495  }
496  }
497  }
498 
499  /* end probing mode */
500  if( endprobing )
501  {
502  SCIP_CALL( SCIPendProbing(scip) );
503  }
504 
505  SCIPdebugMessage("\n");
506 
507  /* one of the child nodes was infeasible, add the other constraint to the current node */
508  if( *result == SCIP_CONSADDED )
509  {
510  node = SCIPgetCurrentNode(scip);
511  if( downnodeinf )
512  {
513  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsup, "infconsup", SCIPvarGetMultaggrNVars(fixvars[i]),
514  SCIPvarGetMultaggrVars(fixvars[i]), SCIPvarGetMultaggrScalars(fixvars[i]),
515  SCIPfeasCeil(scip, fixvarssols[i]) - SCIPvarGetMultaggrConstant(fixvars[i]), SCIPinfinity(scip),
517  assert(probingconsup != NULL);
518  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsup, NULL) );
519  SCIPdebugMessage(" <%s> new valid constraint has been added to the original problem\n", SCIPconsGetName(probingconsup));
520  SCIP_CALL( SCIPreleaseCons(scip, &probingconsup) );
521  }
522  else
523  {
524  SCIP_CALL( SCIPcreateConsLinear(scip, &probingconsdown, "infconsdown", SCIPvarGetMultaggrNVars(fixvars[i]),
525  SCIPvarGetMultaggrVars(fixvars[i]), SCIPvarGetMultaggrScalars(fixvars[i]), - SCIPinfinity(scip),
526  SCIPfeasFloor(scip, fixvarssols[i]) - SCIPvarGetMultaggrConstant(fixvars[i]), TRUE, TRUE, FALSE, FALSE,
527  TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );
528  assert(probingconsdown != NULL);
529  SCIP_CALL( SCIPaddConsNode(scip, node, probingconsdown, NULL) );
530  SCIPdebugMessage(" <%s> new valid constraint has been added to the original problem\n", SCIPconsGetName(probingconsdown));
531  SCIP_CALL( SCIPreleaseCons(scip, &probingconsdown) );
532  }
533  }
534  SCIPfreeBufferArray(scip, &fixvarssols);
535  }
536  return SCIP_OKAY;
537 }
538 
539 
540 /*
541  * Callback methods of branching rule
542  */
543 
544 /** copy method for branchrule plugins (called when SCIP copies plugins) */
545 static
546 SCIP_DECL_BRANCHCOPY(branchCopyMultAggr)
547 { /*lint --e{715}*/
548  assert(scip != NULL);
549  assert(branchrule != NULL);
550  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
551 
552  /* call inclusion method of branchrule */
554 
555  return SCIP_OKAY;
556 }
557 
558 /** destructor of branching rule to free user data (called when SCIP is exiting) */
559 static
560 SCIP_DECL_BRANCHFREE(branchFreeMultAggr)
561 { /*lint --e{715}*/
562  SCIP_BRANCHRULEDATA* branchruledata;
564  /* free branching rule data */
565  branchruledata = SCIPbranchruleGetData(branchrule);
566  assert(branchruledata != NULL);
567 
568  SCIPstatistic(SCIPfreeMemoryArrayNull(scip , &branchruledata->ratioggain));
569  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipdown);
570  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipup);
571 
572  SCIPfreeMemory(scip, &branchruledata);
573  SCIPbranchruleSetData(branchrule, NULL);
574 
575  return SCIP_OKAY;
576 }
577 
578 /** initialization method of branching rule (called after problem was transformed) */
579 static
580 SCIP_DECL_BRANCHINIT(branchInitMultAggr)
581 { /*lint --e{715}*/
582  SCIP_BRANCHRULEDATA* branchruledata;
584  branchruledata = SCIPbranchruleGetData(branchrule);
585  assert(branchruledata != NULL);
586 
587  branchruledata->lastcand = 0;
589  branchruledata->firstmultaggrdepth = 0;
590  branchruledata->nmultaggrbranch = 0;
591  branchruledata->nfracbranch = 0;
592  branchruledata->nEscore = 0;
593  branchruledata->nmultaggrcutoff = 0;
594  branchruledata->nmultaggrconsadd = 0;
595  branchruledata->nfractcutoff = 0;
596  branchruledata->nfractconsadd = 0;
597  branchruledata->nrun = 0;
598  branchruledata->size = 100;
599  branchruledata->ameanratio = 0.0;
600  branchruledata->noupdate = FALSE;
601  branchruledata->clckstrongbr = NULL;
602  branchruledata->clckmultaggrbr = NULL;
603  branchruledata->nstrongbrcall = 0;
604  branchruledata->nmultaggrbrcall = 0;
605  branchruledata->totalmultaggrcands = 0;
606  branchruledata->totallpcands = 0;
607  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->ratioggain, branchruledata->size) );
608  BMSclearMemoryArray(branchruledata->ratioggain, branchruledata->size);
609  SCIP_CALL( SCIPcreateClock(scip, &branchruledata->clckstrongbr) );
610  SCIP_CALL( SCIPcreateClock(scip, &branchruledata->clckmultaggrbr) );
611  )
612  return SCIP_OKAY;
613 }
614 
615 /** deinitialization method of branching rule (called before transformed problem is freed) */
616 static
617 SCIP_DECL_BRANCHEXIT(branchExitMultAggr)
618 { /*lint --e{715}*/
619  SCIP_BRANCHRULEDATA* branchruledata;
620  SCIPstatistic(int j = 0);
621 
622  /* initialize branching rule data */
623  branchruledata = SCIPbranchruleGetData(branchrule);
624  assert(branchruledata != NULL);
625  assert((branchruledata->skipdown != NULL) == (branchruledata->skipup != NULL));
626 
627  /* print statistics */
630  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Multi-aggregated branching stats : \n");
631  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrvars : %d (last run)\n",
632  branchruledata->nmultaggrvars);
633  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " firstmultaggrbranchdepth : %d (in run %d)\n",
634  branchruledata->firstmultaggrdepth,
635  branchruledata->rundepth);
636  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrbranch : %d (tot %d)\n",
637  branchruledata->nmultaggrbranch, branchruledata->nmultaggrbranch + branchruledata->nfracbranch);
638  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrcutoff : %d\n", branchruledata->nmultaggrcutoff);
639  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrconsadd : %d\n", branchruledata->nmultaggrconsadd);
640  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nfractcutoff : %d\n", branchruledata->nfractcutoff);
641  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nfractconsadd : %d\n", branchruledata->nfractconsadd);
642  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nEscore : %d\n", branchruledata->nEscore);
643 
644  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Branching Time : \n");
645  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nstrongbrcall : %d\n", branchruledata->nstrongbrcall);
646  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalstrongbrtime : %g\n",
647  SCIPgetClockTime(scip, branchruledata->clckstrongbr));
648  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totallpcands : %d\n", branchruledata->totallpcands);
649 
650  if( branchruledata->totallpcands != 0 )
651  {
652  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimestrongbr : %g\n",
653  SCIPgetClockTime(scip, branchruledata->clckstrongbr) / branchruledata->totallpcands);
654  }
655  else
656  {
657  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimestrongbr : %s\n", "--");
658  }
659 
660  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrbrcall : %d\n", branchruledata->nmultaggrbrcall);
661  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalmultaggrbrtime : %g\n",
662  SCIPgetClockTime(scip, branchruledata->clckmultaggrbr));
663  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalmultaggrcands : %d\n", branchruledata->totalmultaggrcands);
664 
665  if( branchruledata->totalmultaggrcands != 0 )
666  {
667  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimemultaggrbr : %g\n",
668  SCIPgetClockTime(scip, branchruledata->clckmultaggrbr) / branchruledata->totalmultaggrcands);
669  }
670  else
671  {
672  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimemultaggrbr : %s\n", "--");
673  }
674 
675  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Ratioggain :\n");
676  if( branchruledata->nmultaggrbranch != 0 )
677  {
678  for( j = 0; j < branchruledata->nmultaggrbranch; j++ )
679  {
680  branchruledata->ameanratio += branchruledata->ratioggain[j];
681  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " %g", branchruledata->ratioggain[j]);
682  }
683 
685  branchruledata->ameanratio = branchruledata->ameanratio / branchruledata->nmultaggrbranch;
687  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " ameanratio : %4.2f\n", branchruledata->ameanratio);
688  }
689  else
690  {
691  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " ameanratio : %s\n", "--");
692  }
693 
695 
696  /* free arrays */
697  if( branchruledata->ratioggain != NULL )
698  {
699  SCIPfreeMemoryArray(scip, &branchruledata->ratioggain);
700  branchruledata->ratioggain = NULL;
701  }
702  SCIP_CALL( SCIPfreeClock(scip, &branchruledata->clckstrongbr) );
703  SCIP_CALL( SCIPfreeClock(scip, &branchruledata->clckmultaggrbr) );
704  )
705  if( branchruledata->skipdown != NULL )
706  {
707  SCIPfreeMemoryArray(scip, &branchruledata->skipup);
708  SCIPfreeMemoryArray(scip, &branchruledata->skipdown);
709  branchruledata->skipdown = NULL;
710  branchruledata->skipup = NULL;
711  }
712  return SCIP_OKAY;
713 }
714 
715 /** branching execution method for fractional LP solutions */
716 static
717 SCIP_DECL_BRANCHEXECLP(branchExeclpMultAggr)
718 { /*lint --e{715}*/
719 
720  SCIP_BRANCHRULEDATA* branchruledata;
721  SCIP_VAR** lpcands;
722  SCIP_VAR** tmplpcands;
723  SCIP_Real* lpcandssol;
724  SCIP_Real* lpcandsfrac;
725  SCIP_Real* tmplpcandssol;
726  SCIP_Real* tmplpcandsfrac;
727  SCIP_NODE* downchild;
728  SCIP_NODE* upchild;
729  SCIP_Real bestup;
730  SCIP_Real bestdown;
731  SCIP_Real bestscore;
732  SCIP_Real provedbound;
733  SCIP_Real estimatedown = 0.0;
734  SCIP_Real estimateup = 0.0;
735  SCIP_Bool bestdownvalid;
736  SCIP_Bool bestupvalid;
737  SCIP_Longint oldreevalage;
738  int bestcandpos;
739  int nlpcands;
740  int npriolpcands;
742  SCIP_Real lpobjval;
743  SCIP_Bool reoptimize;
744  )
745 
746  assert(branchrule != NULL);
747  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
748  assert(scip != NULL);
749  assert(result != NULL);
750 
751  SCIPdebugMessage("Execlp method of mult-aggreg branching\n ");
752  *result = SCIP_DIDNOTRUN;
753 
754  /* get branching rule data */
755  branchruledata = SCIPbranchruleGetData(branchrule);
756  assert(branchruledata != NULL);
757 
758  SCIP_CALL( SCIPgetLongintParam(scip, "branching/fullstrong/reevalage", &oldreevalage) );
759  SCIP_CALL( SCIPsetLongintParam(scip, "branching/fullstrong/reevalage", branchruledata->reevalage) );
760 
761  /* get the lpobjval and the number of multi aggregated variables of the problem as a statistic counter */
763  reoptimize = FALSE;
764  lpobjval = SCIPgetLPObjval(scip);
765 
766  if( SCIPgetNRuns(scip) != branchruledata->nrun )
767  {
768  SCIP_VAR** fixvars = NULL;
769  int nfixvars;
770  int i;
771 
772  branchruledata->nmultaggrvars = 0;
773  fixvars = SCIPgetFixedVars(scip);
774  nfixvars = SCIPgetNFixedVars(scip);
775 
776  if( nfixvars != 0 )
777  {
778  for( i = 0; i < nfixvars; i++ )
779  {
780  if( SCIPvarGetStatus(fixvars[i]) == SCIP_VARSTATUS_MULTAGGR && (SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_INTEGER ||
781  SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_BINARY) )
782  {
783  branchruledata->nmultaggrvars += 1;
784  }
785  }
786  }
787  branchruledata->nrun = SCIPgetNRuns(scip);
788  }
789  )
790 
791  /* get all branching candidates */
792  SCIP_CALL( SCIPgetLPBranchCands(scip, &tmplpcands, &tmplpcandssol, &tmplpcandsfrac, &nlpcands, &npriolpcands, NULL) );
793  assert(nlpcands > 0);
794  assert(npriolpcands > 0);
795 
796  /* copy LP branching candidates and solution values, because they will be updated w.r.t. the strong branching LP
797  * solution
798  */
799  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcands, tmplpcands, nlpcands) );
800  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandssol, tmplpcandssol, nlpcands) );
801  SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandsfrac, tmplpcandsfrac, nlpcands) );
802 
803  if( branchruledata->skipdown == NULL )
804  {
805  int nvars = SCIPgetNVars(scip);
806 
807  assert(branchruledata->skipup == NULL);
808 
809  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipdown, nvars) );
810  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipup, nvars) );
811  BMSclearMemoryArray(branchruledata->skipdown, nvars);
812  BMSclearMemoryArray(branchruledata->skipup, nvars);
813  }
814 
815  /* start the clock to get the time spent inside the function */
817  SCIP_CALL( SCIPstartClock(scip, branchruledata->clckstrongbr) );
818  );
819 
820  /* compute strong branching among the array of fractional variables in order to get the best one */
821  SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcands, lpcandssol, lpcandsfrac, branchruledata->skipdown,
822  branchruledata->skipup, nlpcands, npriolpcands, nlpcands, &branchruledata->lastcand, allowaddcons,
823  branchruledata->maxproprounds, branchruledata->probingbounds, TRUE,
824  &bestcandpos, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
825 
827  SCIP_CALL( SCIPstopClock(scip, branchruledata->clckstrongbr) );
828  branchruledata->totallpcands += SCIPgetNLPBranchCands(scip);
829  branchruledata->nstrongbrcall += 1;
830  )
831 
832  if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED )
833  {
834  SCIP_VAR* bestcand = lpcands[bestcandpos];
835  SCIP_Real bestsol = lpcandssol[bestcandpos];
836  SCIPstatistic( SCIP_Real bestmultaggrscore = -SCIPinfinity(scip); )
837 
839  SCIP_Real fdowngain = 0.0;
840  SCIP_Real fupgain = 0.0;
841 
842  /* reoptimize is set to true if strong branching on fractional variables did not explicitly evaluate the objective
843  * values of the probing child nodes and thus we do not have updated information
844  */
845  if( SCIPisLT(scip, SCIPgetVarStrongbranchLPAge(scip, bestcand), branchruledata->reevalage)
846  || branchruledata->maxproprounds != 0 )
847  reoptimize = TRUE;
848 
849  /* store values needed for the ratioggain statistic */
850  if( !reoptimize )
851  {
852  SCIP_Real fdown;
853  SCIP_Real fup;
854 
855  fdown = MAX(bestdown, lpobjval);
856  fup = MAX(bestup, lpobjval);
857  fdowngain = fdown - lpobjval;
858  fupgain = fup - lpobjval;
859  }
860 
861  /* start and then stop the clock to get the time spent inside the function */
862  SCIP_CALL( SCIPstartClock(scip, branchruledata->clckmultaggrbr) );
863  )
864 
865  /* compute strong branching among the multi-aggregated variables and the best fractional variable */
866 #ifdef SCIP_STATISTIC
867  SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
868  &estimatedown, &estimateup, &bestmultaggrscore, result) );
869 #else
870  SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
871  &estimatedown, &estimateup, result) );
872 #endif
874  SCIP_CALL( SCIPstopClock(scip, branchruledata->clckmultaggrbr) );
875  branchruledata->nmultaggrbrcall += 1;
876  )
877 
878  if( *result != SCIP_CUTOFF && *result != SCIP_CONSADDED )
879  {
881  if( !(branchruledata->noupdate) )
882  {
883  if( SCIPisEQ(scip, bestmultaggrscore, bestscore) )
884  branchruledata->nEscore += 1;
885  }
886  )
887 
888  assert(bestcand != NULL);
889  SCIPdebugMessage("BRANCHING MODE:\n");
890 
891  /* perform branching on the best found candidate */
892  if( SCIPvarGetStatus(bestcand) == SCIP_VARSTATUS_MULTAGGR )
893  {
894  SCIP_CONS* multaggrconsdown;
895  SCIP_CONS* multaggrconsup;
896 
898  if( !(branchruledata->noupdate) )
899  {
900  branchruledata->nmultaggrbranch += 1;
901 
902  if( !reoptimize )
903  {
904  SCIP_Real gfractbranch;
905  SCIP_Real gmultaggrbranch;
906  SCIP_Real downgain;
907  SCIP_Real upgain;
908  SCIP_Real down;
909  SCIP_Real up;
910  int nmultaggrbranch;
911 
912  down = MAX(bestdown, lpobjval);
913  up = MAX(bestup, lpobjval);
914  downgain = down - lpobjval;
915  upgain = up - lpobjval;
916 
917  SCIP_CALL( ensureArraySize(scip, branchruledata) );
918 
919  gfractbranch= SQRT(MAX(fdowngain,1e-06) * MAX(fupgain,1e-06));
920  gmultaggrbranch = SQRT(MAX(downgain,1e-06) * MAX(upgain,1e-06));
921 
922  nmultaggrbranch = branchruledata->nmultaggrbranch;
923 
924  if( gmultaggrbranch == 0.0 )
925  {
926  branchruledata->ratioggain[nmultaggrbranch - 1] = 1;
927  }
928  else
929  {
930  branchruledata->ratioggain[nmultaggrbranch - 1] = gfractbranch / gmultaggrbranch;
931  }
932  }
933  }
934  )
935 
936  /* create the multi-aggregated constraints rounded up and down */
937  SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsdown, "consdown", SCIPvarGetMultaggrNVars(bestcand),
938  SCIPvarGetMultaggrVars(bestcand), SCIPvarGetMultaggrScalars(bestcand), - SCIPinfinity(scip),
939  SCIPfeasFloor(scip, bestsol) - SCIPvarGetMultaggrConstant(bestcand),
941 
942  SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsup, "consup", SCIPvarGetMultaggrNVars(bestcand),
944  SCIPfeasCeil(scip, bestsol) - SCIPvarGetMultaggrConstant(bestcand), SCIPinfinity(scip),
946 
947  /* create the child nodes */
948  SCIP_CALL( SCIPcreateChild(scip, &downchild, 1.0, estimatedown) );
949  SCIPdebugMessage(" down node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(downchild), SCIPnodeGetEstimate(downchild));
950 
951  SCIP_CALL( SCIPcreateChild(scip, &upchild, 1.0, estimateup) );
952  SCIPdebugMessage(" up node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(upchild), SCIPnodeGetEstimate(upchild));
953 
954  assert(downchild != NULL);
955  assert(upchild != NULL);
956 
957  SCIP_CALL( SCIPaddConsNode(scip, downchild, multaggrconsdown, NULL) );
958  SCIP_CALL( SCIPaddConsNode(scip, upchild, multaggrconsup, NULL) );
959 
960 #ifdef PRINTNODECONS
961  SCIPdebugMessage("branching at node %lld\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
962 
963  SCIPdebugMessage("created child node %lld with constraint:\n", SCIPnodeGetNumber(downchild));
964  SCIP_CALL( SCIPprintCons(scip, multaggrconsdown, NULL) );
965  SCIPinfoMessage(scip, NULL, "\n");
966 
967  SCIPdebugMessage("created child node %lld with constraint:\n", SCIPnodeGetNumber(upchild));
968  SCIP_CALL( SCIPprintCons(scip, multaggrconsup, NULL) );
969  SCIPinfoMessage(scip, NULL, "\n");
970 #endif
971 
972  /* relase constraints */
973  SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsdown) );
974  SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsup) );
975 
976  SCIPdebugMessage("BRANCHED on multi-aggregated variable <%s>\n", SCIPvarGetName(bestcand));
977 
978  *result = SCIP_BRANCHED;
979  }
980  else
981  {
983  if( !(branchruledata->noupdate) )
984  branchruledata->nfracbranch += 1
985  );
986 
987  assert(*result == SCIP_DIDNOTRUN);
988  assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
989 
990  SCIP_CALL( SCIPbranchVarVal(scip, bestcand, bestsol, &downchild, NULL, &upchild) );
991 
992  assert(downchild != NULL);
993  assert(upchild != NULL);
994 
995  SCIPdebugMessage("BRANCHED on fractional variable <%s>\n", SCIPvarGetName(bestcand));
996 
997  *result = SCIP_BRANCHED;
998  }
999 
1000  /* update the lower bounds in the children; we must not do this if columns are missing in the LP
1001  * (e.g., because we are doing branch-and-price) or the problem should be solved exactly
1002  */
1003  if( SCIPallColsInLP(scip) && !SCIPisExactSolve(scip) )
1004  {
1005  SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
1006  SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
1007  }
1008  SCIPdebugMessage(" -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
1009  SCIPdebugMessage(" -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
1010  }
1011  }
1012  else
1013  {
1014  SCIPdebugMessage("strong branching breaks\n" );
1015 
1016  SCIPstatistic(
1017  if( *result == SCIP_CUTOFF )
1018  {
1019  branchruledata->nfractcutoff += 1;
1020  }
1021  else
1022  {
1023  branchruledata->nfractconsadd += 1;
1024  }
1025  )
1026  }
1027 
1028  SCIPfreeBufferArray(scip, &lpcandsfrac);
1029  SCIPfreeBufferArray(scip, &lpcandssol);
1030  SCIPfreeBufferArray(scip, &lpcands);
1031 
1032  SCIP_CALL( SCIPsetLongintParam(scip, "branching/fullstrong/reevalage", oldreevalage) );
1033 
1034  return SCIP_OKAY;
1035 }
1036 
1037 /*
1038  * branching rule specific interface methods
1039  */
1040 
1041 /** creates the multi-aggregated branching rule and includes it in SCIP */
1043  SCIP* scip /**< SCIP data structure */
1044  )
1046  SCIP_BRANCHRULEDATA* branchruledata;
1047  SCIP_BRANCHRULE* branchrule;
1048 
1049  /* create multaggr branching rule data */
1050  SCIP_CALL( SCIPallocMemory(scip, &branchruledata) );
1051  branchruledata->lastcand = 0;
1052  branchruledata->skipup = NULL;
1053  branchruledata->skipdown = NULL;
1054  SCIPstatistic(branchruledata->ratioggain = NULL);
1055 
1056  /* include branching rule */
1058  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
1059 
1060  assert(branchrule != NULL);
1061 
1062  /* set non fundamental callbacks via setter functions */
1063  SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyMultAggr) );
1064  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeMultAggr) );
1065  SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitMultAggr) );
1066  SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitMultAggr) );
1067  SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpMultAggr) );
1068 
1069  /* multi-aggregated branching rule parameters */
1071  "branching/multaggr/reevalage",
1072  "number of intermediate LPs solved to trigger reevaluation of strong branching value for a variable that was already evaluated at the current node",
1073  &branchruledata->reevalage, TRUE, DEFAULT_REEVALAGE, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1074  SCIP_CALL( SCIPaddIntParam(scip,
1075  "branching/multaggr/maxproprounds",
1076  "maximum number of propagation rounds to be performed during multaggr branching before solving the LP (-1: no limit, -2: parameter settings)",
1077  &branchruledata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
1079  "branching/multaggr/probingbounds",
1080  "should valid bounds be identified in a probing-like fashion during multaggr branching (only with propagation)?",
1081  &branchruledata->probingbounds, TRUE, DEFAULT_PROBINGBOUNDS, NULL, NULL) );
1082 
1083  return SCIP_OKAY;
1084 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:33158
SCIP_STAT * stat
Definition: struct_scip.h:64
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16861
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:32788
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:33125
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40767
static SCIP_DECL_BRANCHFREE(branchFreeMultAggr)
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
SCIP_RETCODE SCIPsetBranchruleExit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXIT((*branchexit)))
Definition: scip.c:8338
public methods for branch and bound tree
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40818
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:32250
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:42032
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40801
SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
Definition: scip.c:8322
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:43
#define DEFAULT_REEVALAGE
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40950
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4046
#define BRANCHRULE_MAXDEPTH
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIP_CALL(x)
Definition: def.h:266
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1877
static SCIP_DECL_BRANCHEXIT(branchExitMultAggr)
SCIP_VAR ** SCIPgetFixedVars(SCIP *scip)
Definition: scip.c:10972
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
#define DEFAULT_MAXPROPROUNDS
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip.c:8290
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3601
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip.c:8306
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
#define DEFAULT_PROBINGBOUNDS
#define SCIP_LONGINT_MAX
Definition: def.h:113
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:26237
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:26482
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:42044
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:26829
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:12363
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:3547
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3573
SCIP_Longint SCIPgetVarStrongbranchLPAge(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19334
#define BRANCHRULE_NAME
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip.c:8388
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13708
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
Definition: scip.c:8253
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:7620
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5758
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16837
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
internal methods for global SCIP settings
SCIP main data structure.
int SCIPgetDepthLimit(SCIP *scip)
Definition: scip.c:38190
#define BRANCHRULE_MAXBOUNDDIST
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11929
internal methods for problem variables
full strong LP branching rule
fullstrong branching on fractional and multi-aggregated variables
#define SCIP_Bool
Definition: def.h:53
static SCIP_DECL_BRANCHINIT(branchInitMultAggr)
#define MAX(x, y)
Definition: tclique_def.h:75
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16825
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:32153
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:37318
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip.h:20534
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16849
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:32285
Constraint handler for linear constraints in their most general form, .
#define SCIPstatistic(x)
Definition: pub_message.h:101
SCIP_RETCODE SCIPgetLongintParam(SCIP *scip, const char *name, SCIP_Longint *value)
Definition: scip.c:3778
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:36779
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:7046
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
#define BRANCHRULE_DESC
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1298
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17431
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5747
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
int SCIPgetNFixedVars(SCIP *scip)
Definition: scip.c:11015
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1755
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1281
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:20545
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: scip.c:33580
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:20593
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:8436
static SCIP_DECL_BRANCHCOPY(branchCopyMultAggr)
#define SCIP_Real
Definition: def.h:127
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:32190
#define MIN(x, y)
Definition: memory.c:67
static SCIP_DECL_BRANCHEXECLP(branchExeclpMultAggr)
#define BRANCHRULE_PRIORITY
#define SCIP_Longint
Definition: def.h:112
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40716
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
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:33701
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)
SCIP_RETCODE SCIPbranchVarVal(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip.c:33810
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip.c:1012