Scippy

SCIP

Solving Constraint Integer Programs

branch_cloud.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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file branch_cloud.c
17  * @brief cloud branching rule
18  * @author Timo Berthold
19  * @author Domenico Salvagnin
20  *
21  * Branching rule based on muliple optimal solutions to the current LP relaxation. See@n
22  * Cloud Branching@n
23  * Timo Berthold and Domenico Salvagnin@n
24  * Integration of AI and OR Techniques in Constraint Programming for Combinatorial Optimization Problems, CPAIOR 2013, LNCS 7874@n
25  * Preliminary version available as <a href="http://opus4.kobv.de/opus4-zib/frontdoor/index/index/docId/1730">ZIB-Report 13-01</a>.
26  */
27 
28 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
29 
30 #include <assert.h>
31 #include <string.h>
32 
33 #include "scip/branch_cloud.h"
34 #include "scip/branch_fullstrong.h"
36 
37 
38 #define BRANCHRULE_NAME "cloud"
39 #define BRANCHRULE_DESC "branching rule that considers several alternative LP optima"
40 #define BRANCHRULE_PRIORITY 0
41 #define BRANCHRULE_MAXDEPTH -1
42 #define BRANCHRULE_MAXBOUNDDIST 1.0
43 
44 #define DEFAULT_USECLOUD TRUE /**< should a cloud of points be used? */
45 #define DEFAULT_USEUNION FALSE /**< should the union of candidates be used? */
46 #define DEFAULT_MAXPOINTS -1 /**< maximum number of points for the cloud (-1 means no limit) */
47 #define DEFAULT_MINSUCCESSRATE 0.0 /**< minimum success rate for the cloud */
48 #define DEFAULT_MINSUCCESSUNION 0.0 /**< minimum success rate for the union */
49 #define DEFAULT_MAXDEPTHUNION 65000 /**< maximum depth for the union */
50 #define DEFAULT_ONLYF2 FALSE /**< should only F2 be used? */
51 
52 /*
53  * Data structures
54  */
55 
56 /** branching rule data */
57 struct SCIP_BranchruleData
58 {
59  int lastcand; /**< last evaluated candidate of last branching rule execution */
60  SCIP_Bool usecloud; /**< should a cloud of points be used? */
61  SCIP_Bool useunion; /**< should the union of candidates be used? */
62  SCIP_Bool onlyF2; /**< should only F2 be used? */
63  int maxpoints; /**< maximum number of points for the cloud (-1 means no limit) */
64  SCIP_Real minsuccessrate; /**< minimum success rate for the cloud */
65  SCIP_Real minsuccessunion; /**< minimum success rate for the union */
66  SCIP_CLOCK* cloudclock; /**< clock for cloud diving */
67  SCIP_Bool* skipdown; /**< should down branch be skiped? */
68  SCIP_Bool* skipup; /**< should up branch be skiped? */
69  int ntried; /**< number of times the cloud was tried */
70  int ntriedunions; /**< number of times the cloud was tried */
71  int nuseful; /**< number of times the cloud was useful (at least one LP skipped) */
72  int nusefulunions; /**< number of times the union was useful (took candidate from new list) */
73  int ncloudpoints; /**< sum of cloud points taken over all nodes with at least two poitns in cloud */
74  int nsavedlps; /**< sum of saved LPs taken over all nodes with at least two points in cloud */
75  int maxdepthunion; /**< maximum depth for the union */
76  int skipsize; /**< size of skipdown and skipup array */
77 };
78 
79 /*
80  * Callback methods of branching rule
81  */
82 
83 /** destructor of branching rule to free user data (called when SCIP is exiting) */
84 static
85 SCIP_DECL_BRANCHFREE(branchFreeCloud)
86 { /*lint --e{715}*/
87  SCIP_BRANCHRULEDATA* branchruledata;
88 
89  /* free branching rule data */
90  branchruledata = SCIPbranchruleGetData(branchrule);
91 
92  if( branchruledata->cloudclock != NULL)
93  {
94  int ntried;
95  int nuseful;
96  int ncloudpoints;
97  int nsavedlps;
98 
100  ntried = branchruledata->ntried;
101  nuseful = branchruledata->nuseful;
102  ncloudpoints = branchruledata->ncloudpoints;
103  nsavedlps = branchruledata->nsavedlps;
104  )
105 
106  SCIPstatisticMessage("time spent diving in cloud branching: %g\n", SCIPgetClockTime(scip, branchruledata->cloudclock));
107  SCIPstatisticMessage("cloud branching tried: %6d found cloud: %6d \n", ntried, nuseful);
108  SCIPstatisticMessage("cloud used points: %6d saved LPs: %6d \n", ncloudpoints, nsavedlps);
109  SCIPstatisticMessage("cloud success rates useful/tried: %8.6g points/useful: %8.6g saved/useful: %8.6g \n",
110  ntried == 0 ? -1 : (SCIP_Real)nuseful / ntried, nuseful == 0 ? -1 : (SCIP_Real)ncloudpoints / nuseful, nuseful == 0 ? -1 : (SCIP_Real)nsavedlps / nuseful);
111  SCIP_CALL( SCIPfreeClock(scip, &(branchruledata->cloudclock)) );
112  }
113 
114  SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->skipdown, branchruledata->skipsize);
115  SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->skipup, branchruledata->skipsize);
116 
117  SCIPfreeBlockMemory(scip, &branchruledata);
118  SCIPbranchruleSetData(branchrule, NULL);
119 
120  return SCIP_OKAY;
121 }
122 
123 
124 /** initialization method of branching rule (called after problem was transformed) */
125 static
126 SCIP_DECL_BRANCHINIT(branchInitCloud)
127 { /*lint --e{715}*/
128  SCIP_BRANCHRULEDATA* branchruledata;
129 
130  /* initialize branching rule data */
131  branchruledata = SCIPbranchruleGetData(branchrule);
132  branchruledata->lastcand = 0;
133  branchruledata->nuseful = 0;
134  branchruledata->nusefulunions = 0;
135  branchruledata->ntried = 0;
136  branchruledata->ntriedunions = 0;
137  branchruledata->ncloudpoints = 0;
138  branchruledata->nsavedlps = 0;
139 
140  if( branchruledata->cloudclock != NULL)
141  {
142  SCIP_CALL( SCIPresetClock(scip, branchruledata->cloudclock) );
143  }
144 
145  return SCIP_OKAY;
146 }
147 
148 /** branching execution method for fractional LP solutions */
149 static
150 SCIP_DECL_BRANCHEXECLP(branchExeclpCloud)
151 { /*lint --e{715}*/
152  SCIP_BRANCHRULEDATA* branchruledata;
153 
154  SCIP_VAR** lpcands;
155  SCIP_VAR** lpcandscopy;
156 
157  SCIP_VAR** vars;
158  SCIP_ROW** lprows;
159  SCIP_Real* lpcandsfrac;
160  SCIP_Real* lpcandssol;
161  SCIP_Real* lpcandsfraccopy;
162  SCIP_Real* lpcandssolcopy;
163  SCIP_Real* lpcandsmin;
164  SCIP_Real* lpcandsmax;
165  SCIP_Real* newlpcandsmin;
166  SCIP_Real* newlpcandsmax;
167 
168  SCIP_Real bestdown;
169  SCIP_Real bestup;
170  SCIP_Real bestscore;
171  SCIP_Real provedbound;
172 
173  SCIP_Bool bestdownvalid;
174  SCIP_Bool bestupvalid;
175  SCIP_Bool newpoint;
176  SCIP_Bool lperror;
177 
178  int nlpcands;
179  int npriolpcands;
180  int nvars;
181  int bestcand;
182  int nlprows;
183  int i;
184  int counter;
185  int ncomplete;
186  int ndiscvars;
187 
188  assert(branchrule != NULL);
189  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
190  assert(scip != NULL);
191  assert(result != NULL);
192 
193  if( !SCIPisLPSolBasic(scip) )
194  return SCIP_OKAY;
195 
196  SCIPdebugMsg(scip, "Execlp method of " BRANCHRULE_NAME " branching\n");
197 
198  /* get problem variables and LP row data */
199  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
201  nlprows = SCIPgetNLPRows(scip);
202  lprows = SCIPgetLPRows(scip);
203 
204  /* get branching candidates */
205  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, &npriolpcands, NULL) );
206  nlpcands = SCIPgetNLPBranchCands(scip);
207  assert(nlpcands > 0);
208 
209  /* get branching rule data */
210  branchruledata = SCIPbranchruleGetData(branchrule);
211  assert(branchruledata != NULL);
212 
213  /* allocate skipping arrays on first call */
214  if( branchruledata->skipdown == NULL )
215  {
216  assert(branchruledata->skipup == NULL);
217 
218  branchruledata->skipsize = nvars;
219  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipdown, branchruledata->skipsize) );
220  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipup, branchruledata->skipsize) );
221  }
222 
223  /* reset skipping arrays to zero */
224  BMSclearMemoryArray(branchruledata->skipdown, branchruledata->skipsize);
225  BMSclearMemoryArray(branchruledata->skipup, branchruledata->skipsize);
226 
227  /* allocate required data structures */
228  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandsmin, nlpcands) );
229  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandsmax, nlpcands) );
230  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandscopy, nlpcands) );
231  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandsfraccopy, nlpcands) );
232  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandssolcopy, nlpcands) );
233  newlpcandsmin = NULL;
234  newlpcandsmax = NULL;
235  if( branchruledata->useunion && SCIPgetDepth(scip) < branchruledata->maxdepthunion && !branchruledata->onlyF2)
236  {
237  SCIP_CALL( SCIPallocBufferArray(scip, &newlpcandsmin, ndiscvars) );
238  SCIP_CALL( SCIPallocBufferArray(scip, &newlpcandsmax, ndiscvars) );
239  }
240  BMScopyMemoryArray(lpcandsmin, lpcandssol, nlpcands);
241  BMScopyMemoryArray(lpcandsmax, lpcandssol, nlpcands);
242  BMScopyMemoryArray(lpcandssolcopy, lpcandssol, nlpcands);
243  BMScopyMemoryArray(lpcandsfraccopy, lpcandsfrac, nlpcands);
244  BMScopyMemoryArray(lpcandscopy, lpcands, nlpcands);
245 
246  SCIP_CALL( SCIPstartClock(scip, branchruledata->cloudclock) );
247  branchruledata->ntried++;
248 
249  /* start diving to calculate the solution cloud */
251 
252  /* fix variables with nonzero reduced costs to reduce LP to the optimal face */
253  for( i = 0; i < nvars; ++i )
254  {
255  SCIP_Real solval;
256  solval = SCIPgetSolVal(scip, NULL, vars[i]);
257 
258  if( !SCIPisFeasZero(scip, SCIPgetVarRedcost(scip, vars[i])) )
259  {
260  SCIP_CALL( SCIPchgVarLbDive(scip, vars[i], solval) );
261  SCIP_CALL( SCIPchgVarUbDive(scip, vars[i], solval) );
262  }
263  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_INTEGER && !SCIPisIntegral(scip, solval) )
264  {
265  SCIP_CALL( SCIPchgVarLbDive(scip, vars[i], SCIPfloor(scip, solval)) );
266  SCIP_CALL( SCIPchgVarUbDive(scip, vars[i], SCIPceil(scip, solval)) );
267  }
268 
269  SCIP_CALL( SCIPchgVarObjDive(scip, vars[i], 0.0) );
270  }
271 
272  /* fix LP rows with nonzero dual solution to reduce LP to the optimal face */
273  for( i = 0; i < nlprows; ++i )
274  {
275  SCIP_Real dualsol;
276  dualsol = SCIProwGetDualsol(lprows[i]);
277  if( !SCIPisZero(scip, dualsol) )
278  {
279  if( dualsol > 0 && SCIPisFeasEQ(scip, SCIProwGetLhs(lprows[i]), SCIPgetRowActivity(scip,lprows[i])) )
280  {
281  SCIP_CALL( SCIPchgRowRhsDive(scip, lprows[i], SCIProwGetLhs(lprows[i])) );
282  }
283  else if( dualsol < 0 && SCIPisFeasEQ(scip, SCIProwGetRhs(lprows[i]), SCIPgetRowActivity(scip,lprows[i])) )
284  {
285  SCIP_CALL( SCIPchgRowLhsDive(scip, lprows[i], SCIProwGetRhs(lprows[i])) );
286  }
287  }
288  }
289 
290  newpoint = TRUE;
291  counter = 0;
292 
293  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
294  {
295  /* update cloud intervals for candidates that have been integral in original LP, but have been fractional in previous cloud points */
296  for( i = 0; i < ndiscvars; ++i)
297  {
298  SCIP_Real solval;
299  solval = SCIPgetSolVal(scip, NULL, vars[i]);
300 
301  assert(newlpcandsmin != NULL);
302  assert(newlpcandsmax != NULL);
303 
304  newlpcandsmin[i] = solval;
305  newlpcandsmax[i] = solval;
306  }
307  }
308 
309  /* loop that generates new cloud point */
310  while( newpoint && branchruledata->usecloud )
311  {
312 #ifdef NDEBUG
313  SCIP_RETCODE retcode;
314 #endif
315 
316  /* apply feasibility pump objective function to fractional variables */
317  for( i = 0; i < nlpcands; ++i )
318  {
319  SCIP_Real frac;
320  frac = SCIPfrac(scip, SCIPgetSolVal(scip, NULL, lpcandscopy[i]));
321 
322  if( !SCIPisZero(scip, frac) && !SCIPisIntegral(scip, lpcandsmin[i]) && !SCIPisIntegral(scip, lpcandsmax[i]) )
323  {
324  if( frac < 0.5 )
325  {
326  SCIP_CALL( SCIPchgVarObjDive(scip, vars[i], 1.0) );
327  }
328  else
329  {
330  SCIP_CALL( SCIPchgVarObjDive(scip, vars[i], -1.0) );
331  }
332  }
333  }
334 
335  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
336  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
337  */
338 #ifdef NDEBUG
339  retcode = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
340  if( retcode != SCIP_OKAY )
341  {
342  SCIPwarningMessage(scip, "Error while solving LP in " BRANCHRULE_NAME "; LP solve terminated with code <%d>\n",retcode);
343  }
344 #else
345  SCIP_CALL( SCIPsolveDiveLP(scip, -1, &lperror, NULL) );
346 #endif
347 
348  if( lperror || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
349  break;
350 
351  /* check if a solution has been found */
352  if( SCIPgetNLPBranchCands(scip) == 0 )
353  {
354  SCIP_Bool success;
355  SCIP_SOL* sol;
356 
357  /* create solution from diving LP */
358  SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
359  SCIP_CALL( SCIPlinkLPSol(scip, sol) );
360  SCIPdebugMsg(scip, "cloud branching found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, sol));
361 
362  /* try to add solution to SCIP */
363  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
364 
365  /* check, if solution was feasible and good enough */
366  if( success )
367  {
368  SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
370  *result = SCIP_CUTOFF;
371  goto TERMINATE;
372  }
373  }
374 
375  /* update cloud intervals for candidates that have been fractional in original LP */
376  newpoint = FALSE;
377  for( i = 0; i < nlpcands; ++i)
378  {
379  SCIP_Real solval;
380  solval = SCIPgetSolVal(scip, NULL, lpcandscopy[i]);
381 
382  if( SCIPisFeasIntegral(scip,solval) && !SCIPisFeasIntegral(scip, lpcandsmin[i]) && !SCIPisFeasIntegral(scip, lpcandsmax[i]) )
383  newpoint = TRUE;
384 
385  lpcandsmin[i] = MIN(lpcandsmin[i], solval);
386  lpcandsmax[i] = MAX(lpcandsmax[i], solval);
387  }
388 
389  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
390  {
391  /* update cloud intervals for candidates that have been integral in original LP, but have been fractional in previous cloud points */
392  for( i = 0; i < ndiscvars; ++i)
393  {
394  SCIP_Real solval;
395  solval = SCIPgetSolVal(scip, NULL, vars[i]);
396 
397  assert(newlpcandsmin != NULL);
398  assert(newlpcandsmax != NULL);
399 
400  newlpcandsmin[i] = MIN(newlpcandsmin[i], solval);
401  newlpcandsmax[i] = MAX(newlpcandsmax[i], solval);
402  }
403  }
404 
405  if( newpoint )
406  counter++;
407 
408  if( branchruledata->maxpoints != -1 && counter >= branchruledata->maxpoints )
409  break;
410  }
411 
412  SCIPdebugMsg(scip, "considered %d additional points in the cloud\n",counter);
413 
414 
415  /* terminate the diving */
417 
418  SCIP_CALL( SCIPstopClock(scip, branchruledata->cloudclock) );
419  ncomplete = nlpcands;
420 
421  if( counter > 0 )
422  {
423  branchruledata->ncloudpoints += (counter+1);
424  branchruledata->nuseful++;
425 
426  counter = 0;
427 
428  /* sort all variables for which both bounds are fractional to the front */
429  for( i = 0; i < nlpcands; ++i)
430  {
431  if( !SCIPisFeasIntegral(scip, lpcandsmin[i]) && !SCIPisFeasIntegral(scip, lpcandsmax[i]) )
432  {
433  assert(counter <= i);
434  lpcandscopy[counter] = lpcandscopy[i];
435  lpcandssolcopy[counter] = lpcandssolcopy[i];
436  lpcandsfraccopy[counter] = lpcandsfraccopy[i];
437  counter++;
438  }
439  }
440 
441  /* should only be in that if condition when at least one bound could be made integral */
442  assert(nlpcands - counter > 0);
443 
444  ncomplete = counter;
445 
446  /* filter all variables for which exactly one interval bound is fractional */
447  for( i = 0; i < nlpcands && !branchruledata->onlyF2; ++i)
448  {
449  if( SCIPisFeasIntegral(scip, lpcandsmin[i]) != SCIPisFeasIntegral(scip, lpcandsmax[i]) )
450  {
451  assert(counter < nlpcands);
452  lpcandscopy[counter] = lpcandscopy[i];
453  lpcandssolcopy[counter] = lpcandssolcopy[i];
454  lpcandsfraccopy[counter] = lpcandsfraccopy[i];
455 
456  if( SCIPisFeasIntegral(scip, lpcandsmin[i]) )
457  branchruledata->skipdown[counter] = TRUE;
458  if( SCIPisFeasIntegral(scip, lpcandsmax[i]) )
459  branchruledata->skipup[counter] = TRUE;
460  assert(branchruledata->skipdown[counter] != branchruledata->skipup[counter]);
461 
462  counter++;
463  }
464  }
465 
466  SCIPdebugMsg(scip, "can fully skip %d/%d strong branching candidates\n", nlpcands - counter, nlpcands);
467  SCIPdebugMsg(scip, "can half skip %d/%d strong branching candidates\n", counter - ncomplete, nlpcands);
468  }
469  else
470  counter = nlpcands;
471 
472  /* if cloud sampling was not successful enough, disable it */
473  if( branchruledata->usecloud &&
474  branchruledata->ntried > 100 &&
475  (SCIP_Real)branchruledata->nuseful / branchruledata->ntried < branchruledata->minsuccessrate )
476  {
477  SCIPdebugMsg(scip, "Disabling cloud branching (not effective)\n");
478  branchruledata->usecloud = FALSE;
479  }
480 
481  if( branchruledata->onlyF2 )
482  counter = MAX(counter,1);
483 
484  /* the second counter should maybe be replaced at some point */
485  SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcandscopy, lpcandssolcopy, lpcandsfraccopy, branchruledata->skipdown,
486  branchruledata->skipup, counter, counter, ncomplete, &branchruledata->lastcand, allowaddcons, 0, FALSE, FALSE,
487  &bestcand, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
488 
489  if( branchruledata->lastcand <= ncomplete )
490  {
491  SCIPdebugMsg(scip, "saved %d of %d LPs\n", 2*(nlpcands - ncomplete), 2*nlpcands);
492  branchruledata->nsavedlps += 2*(nlpcands - ncomplete);
493  }
494  else
495  {
496  SCIPdebugMsg(scip, "saved %d of %d LPs\n", 2*(nlpcands - counter)+counter - ncomplete, 2*nlpcands);
497  branchruledata->nsavedlps += 2*(nlpcands - counter)+counter - ncomplete;
498  }
499 
500  /* perform the branching */
501  if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED && counter > 0 )
502  {
503  SCIP_NODE* downchild;
504  SCIP_NODE* upchild;
505  SCIP_VAR* var;
506  SCIP_Bool allcolsinlp;
507  SCIP_Bool exactsolve;
508  SCIP_Bool newselected;
509 
510  assert(*result == SCIP_DIDNOTRUN);
511  assert(0 <= bestcand && bestcand < nlpcands);
512  assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
513 
514  var = lpcandscopy[bestcand];
515  newselected = FALSE;
516 
517  /* if there are new candidates variables, also try them */
518  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion && branchruledata->lastcand > ncomplete )
519  {
520  SCIP_VAR** newlpcands;
521 
522  counter = 0;
523  /* reset skipping arrays to zero */
524  BMSclearMemoryArray(branchruledata->skipdown, branchruledata->skipsize);
525  BMSclearMemoryArray(branchruledata->skipup, branchruledata->skipsize);
526 
527  SCIP_CALL( SCIPallocBufferArray(scip, &newlpcands, ndiscvars) );
528 
529  /* get new LP candidates with one fractional bound */
530  for( i = 0; i < ndiscvars; ++i)
531  {
532  if( !SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[i])) )
533  continue;
534 
535  assert(newlpcandsmin != NULL);
536  assert(newlpcandsmax != NULL);
537 
538  if( SCIPisFeasIntegral(scip, newlpcandsmin[i]) != SCIPisFeasIntegral(scip, newlpcandsmax[i]) )
539  {
540  newlpcands[counter] = vars[i];
541 
542  if( SCIPisFeasIntegral(scip, newlpcandsmin[i]) )
543  branchruledata->skipdown[counter] = TRUE;
544  if( SCIPisFeasIntegral(scip, newlpcandsmax[i]) )
545  branchruledata->skipup[counter] = TRUE;
546  assert(branchruledata->skipdown[counter] != branchruledata->skipup[counter]);
547 
548  counter++;
549  }
550  }
551 
552  /* when there are new candidates, also try these */
553  if( counter > 0 )
554  {
555  SCIP_Real newdown;
556  SCIP_Real newup;
557  SCIP_Real newscore;
558  int newcand;
559  SCIP_Bool newdownvalid;
560  SCIP_Bool newupvalid;
561  SCIP_Real newbound;
562 
563  branchruledata->ntriedunions++;
564  newscore = -SCIPinfinity(scip);
565  SCIP_CALL( SCIPselectVarPseudoStrongBranching(scip, newlpcands, branchruledata->skipdown, branchruledata->skipup, counter, counter,
566  allowaddcons, &newcand, &newdown, &newup, &newscore, &newdownvalid, &newupvalid, &newbound, result) );
567 
568  if( *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM || *result == SCIP_CONSADDED )
569  {
570  SCIPfreeBufferArray(scip, &newlpcands);
571  goto TERMINATE;
572  }
573 
574  if( newscore > bestscore )
575  {
576  bestcand = newcand;
577  var = newlpcands[newcand];
578  bestdown = newdown;
579  bestup = newup;
580  bestdownvalid = newdownvalid;
581  bestupvalid = newupvalid;
582  bestscore = newscore;
583  newselected = TRUE;
584  branchruledata->nusefulunions++;
585  }
586  }
587  /* free temporary array for new union candidates */
588  SCIPfreeBufferArray(scip, &newlpcands);
589  }
590 
591  /* perform the branching */
592  if( !newselected )
593  {
594  SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s> (solval=%g, down=%g, up=%g, score=%g)\n",
595  counter, bestcand, SCIPvarGetName(var), lpcandssolcopy[bestcand], bestdown, bestup, bestscore);
596  }
597  else
598  {
599  SCIPdebugMsg(scip, " -> selected from %d new candidates, candidate %d: variable <%s> (down=%g, up=%g, score=%g)\n",
600  counter, bestcand, SCIPvarGetName(var), bestdown, bestup, bestscore);
601  }
602 
603  assert(!SCIPisFeasIntegral(scip, SCIPvarGetSol(lpcands[bestcand], TRUE)));
604 
605  SCIP_CALL( SCIPbranchVar(scip, var, &downchild, NULL, &upchild) );
606  assert(downchild != NULL);
607  assert(upchild != NULL);
608 
609  /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
610  * for cutting off sub problems and improving lower bounds of children
611  */
612  exactsolve = SCIPisExactSolve(scip);
613 
614  /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
615  allcolsinlp = SCIPallColsInLP(scip);
616 
617  /* update the lower bounds in the children */
618  if( allcolsinlp && !exactsolve )
619  {
620  SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
621  SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
622  }
623  SCIPdebugMsg(scip, " -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
624  SCIPdebugMsg(scip, " -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
625 
626  *result = SCIP_BRANCHED;
627  }
628 
629  TERMINATE:
630  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
631  {
632  SCIPfreeBufferArray(scip, &newlpcandsmax);
633  SCIPfreeBufferArray(scip, &newlpcandsmin);
634  }
635  SCIPfreeBufferArray(scip, &lpcandscopy);
636  SCIPfreeBufferArray(scip, &lpcandssolcopy);
637  SCIPfreeBufferArray(scip, &lpcandsfraccopy);
638  SCIPfreeBufferArray(scip, &lpcandsmax);
639  SCIPfreeBufferArray(scip, &lpcandsmin);
640 
641  /* if union usage was not successful enough, disable it */
642  if( branchruledata->useunion &&
643  branchruledata->ntriedunions > 10 &&
644  (SCIP_Real)branchruledata->nusefulunions / branchruledata->ntriedunions < branchruledata->minsuccessunion )
645  {
646  SCIPdebugMsg(scip, "Disabling union usage (not effective)\n");
647  branchruledata->useunion = FALSE;
648  }
649 
650  return SCIP_OKAY;
651 }
652 
653 /*
654  * branching rule specific interface methods
655  */
656 
657 /** creates the cloud branching rule and includes it in SCIP */
659  SCIP* scip /**< SCIP data structure */
660  )
661 {
662  SCIP_BRANCHRULEDATA* branchruledata;
663  SCIP_BRANCHRULE* branchrule;
664 
665  /* create cloud branching rule data */
666  SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
667  branchruledata->lastcand = 0;
668  branchruledata->skipsize = 0;
669  branchruledata->skipup = NULL;
670  branchruledata->skipdown = NULL;
671  SCIP_CALL( SCIPcreateClock(scip, &(branchruledata->cloudclock)) );
672 
673  /* include branching rule */
674  branchrule = NULL;
676  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
677  assert(branchrule != NULL);
678 
679  /* set non-fundamental callbacks via setter functions */
680  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeCloud) );
681  SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitCloud) );
682  SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpCloud) );
683 
684  /* add cloud branching rule parameters */
686  "branching/" BRANCHRULE_NAME "/usecloud",
687  "should a cloud of points be used?",
688  &branchruledata->usecloud, FALSE, DEFAULT_USECLOUD, NULL, NULL) );
690  "branching/" BRANCHRULE_NAME "/onlyF2",
691  "should only F2 be used?",
692  &branchruledata->onlyF2, FALSE, DEFAULT_ONLYF2, NULL, NULL) );
694  "branching/" BRANCHRULE_NAME "/useunion",
695  "should the union of candidates be used?",
696  &branchruledata->useunion, FALSE, DEFAULT_USEUNION, NULL, NULL) );
698  "branching/" BRANCHRULE_NAME "/maxpoints",
699  "maximum number of points for the cloud (-1 means no limit)",
700  &branchruledata->maxpoints, FALSE, DEFAULT_MAXPOINTS, -1, INT_MAX, NULL, NULL) );
702  "branching/" BRANCHRULE_NAME "/minsuccessrate",
703  "minimum success rate for the cloud",
704  &branchruledata->minsuccessrate, FALSE, DEFAULT_MINSUCCESSRATE, 0.0, 1.0, NULL, NULL) );
706  "branching/" BRANCHRULE_NAME "/minsuccessunion",
707  "minimum success rate for the union",
708  &branchruledata->minsuccessunion, FALSE, DEFAULT_MINSUCCESSUNION, 0.0, 1.0, NULL, NULL) );
710  "branching/" BRANCHRULE_NAME "/maxdepthunion",
711  "maximum depth for the union",
712  &branchruledata->maxdepthunion, FALSE, DEFAULT_MAXDEPTHUNION, 0, 65000, NULL, NULL) );
713 
714  return SCIP_OKAY;
715 }
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:36128
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition: scip.c:29200
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11721
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:46151
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:37672
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1774
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21892
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46086
#define DEFAULT_USECLOUD
Definition: branch_cloud.c:44
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:42499
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7163
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18997
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:43
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:44946
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12561
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip.c:9054
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11505
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:16311
#define FALSE
Definition: def.h:64
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:45816
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define DEFAULT_MAXPOINTS
Definition: branch_cloud.c:46
#define SCIPstatisticMessage
Definition: pub_message.h:104
SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:34642
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21907
static SCIP_DECL_BRANCHINIT(branchInitCloud)
Definition: branch_cloud.c:126
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:9001
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:44895
#define DEFAULT_MAXDEPTHUNION
Definition: branch_cloud.c:49
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:21937
#define BRANCHRULE_PRIORITY
Definition: branch_cloud.c:40
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21890
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:36161
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1260
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:16331
#define SCIPdebugMsg
Definition: scip.h:451
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:4202
#define BRANCHRULE_NAME
Definition: branch_cloud.c:38
#define DEFAULT_USEUNION
Definition: branch_cloud.c:45
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip.c:9136
static SCIP_DECL_BRANCHEXECLP(branchExeclpCloud)
Definition: branch_cloud.c:150
#define DEFAULT_MINSUCCESSUNION
Definition: branch_cloud.c:48
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip.c:29262
SCIP_RETCODE SCIPchgRowLhsDive(SCIP *scip, SCIP_ROW *row, SCIP_Real newlhs)
Definition: scip.c:34745
cloud branching rule
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:44844
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip.c:36737
SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:34901
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45764
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
#define NULL
Definition: lpi_spx1.cpp:137
int SCIPgetNLPRows(SCIP *scip)
Definition: scip.c:29221
#define SCIP_CALL(x)
Definition: def.h:306
#define BRANCHRULE_MAXBOUNDDIST
Definition: branch_cloud.c:42
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:16321
SCIP_RETCODE SCIPincludeBranchruleCloud(SCIP *scip)
Definition: branch_cloud.c:658
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21925
full strong LP branching rule
#define BRANCHRULE_MAXDEPTH
Definition: branch_cloud.c:41
#define DEFAULT_MINSUCCESSRATE
Definition: branch_cloud.c:47
#define SCIP_Bool
Definition: def.h:61
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:28854
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:45078
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:42094
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition: scip.c:13394
SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:34674
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1784
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:39843
SCIP_RETCODE SCIPselectVarPseudoStrongBranching(SCIP *scip, SCIP_VAR **pseudocands, SCIP_Bool *skipdown, SCIP_Bool *skipup, int npseudocands, int npriopseudocands, SCIP_Bool allowaddcons, int *bestpseudocand, SCIP_Real *bestdown, SCIP_Real *bestup, SCIP_Real *bestscore, SCIP_Bool *bestdownvalid, SCIP_Bool *bestupvalid, SCIP_Real *provedbound, SCIP_RESULT *result)
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
#define DEFAULT_ONLYF2
Definition: branch_cloud.c:50
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38090
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11676
static SCIP_DECL_BRANCHFREE(branchFreeCloud)
Definition: branch_cloud.c:85
all variables full strong LP branching rule
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:45900
SCIP_RETCODE SCIPchgVarObjDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:34601
SCIP_RETCODE SCIPresetClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:44912
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 SCIPstatistic(x)
Definition: pub_message.h:101
#define SCIP_Real
Definition: def.h:135
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1896
#define MIN(x, y)
Definition: memory.c:75
SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
Definition: scip.c:9070
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:29244
SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
Definition: scip.c:45973
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16717
SCIP_RETCODE SCIPstartDive(SCIP *scip)
Definition: scip.c:34477
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:45864
#define BRANCHRULE_DESC
Definition: branch_cloud.c:39
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:21910
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:46187
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_RETCODE SCIPendDive(SCIP *scip)
Definition: scip.c:34520
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:45949
SCIP_RETCODE SCIPchgRowRhsDive(SCIP *scip, SCIP_ROW *row, SCIP_Real newrhs)
Definition: scip.c:34778
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:44929
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38007
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip.c:1025
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4258
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:45937
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:4176
SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30673
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37005