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-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 
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  * Time 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;
68  SCIP_Bool* skipup;
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 };
77 
78 /*
79  * Callback methods of branching rule
80  */
81 
82 /** destructor of branching rule to free user data (called when SCIP is exiting) */
83 static
84 SCIP_DECL_BRANCHFREE(branchFreeCloud)
85 { /*lint --e{715}*/
86  SCIP_BRANCHRULEDATA* branchruledata;
87 
88  /* free branching rule data */
89  branchruledata = SCIPbranchruleGetData(branchrule);
90 
91  if( branchruledata->cloudclock != NULL)
92  {
93  int ntried = branchruledata->ntried;
94  int nuseful = branchruledata->nuseful;
95  int ncloudpoints = branchruledata->ncloudpoints;
96  int nsavedlps = branchruledata->nsavedlps;
97 
98  SCIPstatisticMessage("time spent diving in cloud branching: %g\n", SCIPgetClockTime(scip, branchruledata->cloudclock));
99  SCIPstatisticMessage("cloud branching tried: %6d found cloud: %6d \n", ntried, nuseful);
100  SCIPstatisticMessage("cloud used points: %6d saved LPs: %6d \n", ncloudpoints, nsavedlps);
101  SCIPstatisticMessage("cloud success rates useful/tried: %8.6g points/useful: %8.6g saved/useful: %8.6g \n",
102  ntried == 0 ? -1 : (SCIP_Real)nuseful / ntried, nuseful == 0 ? -1 : (SCIP_Real)ncloudpoints / nuseful, nuseful == 0 ? -1 : (SCIP_Real)nsavedlps / nuseful);
103  SCIP_CALL( SCIPfreeClock(scip, &(branchruledata->cloudclock)) );
104  }
105 
106  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipdown);
107  SCIPfreeMemoryArrayNull(scip, &branchruledata->skipup);
108 
109  SCIPfreeMemory(scip, &branchruledata);
110  SCIPbranchruleSetData(branchrule, NULL);
111 
112  return SCIP_OKAY;
113 }
114 
115 
116 /** initialization method of branching rule (called after problem was transformed) */
117 static
118 SCIP_DECL_BRANCHINIT(branchInitCloud)
119 { /*lint --e{715}*/
120  SCIP_BRANCHRULEDATA* branchruledata;
121 
122  /* initialize branching rule data */
123  branchruledata = SCIPbranchruleGetData(branchrule);
124  branchruledata->lastcand = 0;
125  branchruledata->nuseful = 0;
126  branchruledata->nusefulunions = 0;
127  branchruledata->ntried = 0;
128  branchruledata->ntriedunions = 0;
129  branchruledata->ncloudpoints = 0;
130  branchruledata->nsavedlps = 0;
131 
132  if( branchruledata->cloudclock != NULL)
133  {
134  SCIP_CALL( SCIPresetClock(scip, branchruledata->cloudclock) );
135  }
136 
137  return SCIP_OKAY;
138 }
139 
140 /** branching execution method for fractional LP solutions */
141 static
142 SCIP_DECL_BRANCHEXECLP(branchExeclpCloud)
143 { /*lint --e{715}*/
144  SCIP_BRANCHRULEDATA* branchruledata;
145 
146  SCIP_VAR** lpcands;
147  SCIP_VAR** lpcandscopy;
148 
149  SCIP_VAR** vars;
150  SCIP_ROW** lprows;
151  SCIP_Real* lpcandsfrac;
152  SCIP_Real* lpcandssol;
153  SCIP_Real* lpcandsfraccopy;
154  SCIP_Real* lpcandssolcopy;
155  SCIP_Real* lpcandsmin;
156  SCIP_Real* lpcandsmax;
157  SCIP_Real* newlpcandsmin;
158  SCIP_Real* newlpcandsmax;
159 
160  SCIP_Real bestdown;
161  SCIP_Real bestup;
162  SCIP_Real bestscore;
163  SCIP_Real provedbound;
164 
165  SCIP_Bool bestdownvalid;
166  SCIP_Bool bestupvalid;
167  SCIP_Bool newpoint;
168  SCIP_Bool lperror;
169 
170  int nlpcands;
171  int npriolpcands;
172  int nvars;
173  int bestcand;
174  int nlprows;
175  int i;
176  int counter;
177  int ncomplete;
178  int ndiscvars;
179 
180  assert(branchrule != NULL);
181  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
182  assert(scip != NULL);
183  assert(result != NULL);
184 
185  if( !SCIPisLPSolBasic(scip) )
186  return SCIP_OKAY;
187 
188  SCIPdebugMessage("Execlp method of " BRANCHRULE_NAME " branching\n");
189 
190  /* get problem variables and LP row data */
191  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
193  nlprows = SCIPgetNLPRows(scip);
194  lprows = SCIPgetLPRows(scip);
195 
196  /* get branching candidates */
197  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, &npriolpcands, NULL) );
198  nlpcands = SCIPgetNLPBranchCands(scip);
199  assert(nlpcands > 0);
200 
201  /* get branching rule data */
202  branchruledata = SCIPbranchruleGetData(branchrule);
203  assert(branchruledata != NULL);
204 
205  /* allocate skipping arrays on first call */
206  if( branchruledata->skipdown == NULL )
207  {
208  assert(branchruledata->skipup == NULL);
209 
210  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipdown, nvars) );
211  SCIP_CALL( SCIPallocMemoryArray(scip, &branchruledata->skipup, nvars) );
212  }
213 
214  /* reset skipping arrays to zero */
215  BMSclearMemoryArray(branchruledata->skipdown, nlpcands);
216  BMSclearMemoryArray(branchruledata->skipup, nlpcands);
217 
218  /* allocate required data structures */
219  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandsmin, nlpcands) );
220  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandsmax, nlpcands) );
221  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandscopy, nlpcands) );
222  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandsfraccopy, nlpcands) );
223  SCIP_CALL( SCIPallocBufferArray(scip, &lpcandssolcopy, nlpcands) );
224  newlpcandsmin = NULL;
225  newlpcandsmax = NULL;
226  if( branchruledata->useunion && SCIPgetDepth(scip) < branchruledata->maxdepthunion && !branchruledata->onlyF2)
227  {
228  SCIP_CALL( SCIPallocBufferArray(scip, &newlpcandsmin, ndiscvars) );
229  SCIP_CALL( SCIPallocBufferArray(scip, &newlpcandsmax, ndiscvars) );
230  }
231  BMScopyMemoryArray(lpcandsmin, lpcandssol, nlpcands);
232  BMScopyMemoryArray(lpcandsmax, lpcandssol, nlpcands);
233  BMScopyMemoryArray(lpcandssolcopy, lpcandssol, nlpcands);
234  BMScopyMemoryArray(lpcandsfraccopy, lpcandsfrac, nlpcands);
235  BMScopyMemoryArray(lpcandscopy, lpcands, nlpcands);
236 
237  SCIP_CALL( SCIPstartClock(scip, branchruledata->cloudclock) );
238  branchruledata->ntried++;
239 
240  /* start diving to calculate the solution cloud */
242 
243  /* fix variables with nonzero reduced costs to reduce LP to the optimal face */
244  for( i = 0; i < nvars; ++i )
245  {
246  SCIP_Real solval;
247  solval = SCIPgetSolVal(scip, NULL, vars[i]);
248 
249  if( !SCIPisFeasZero(scip, SCIPgetVarRedcost(scip, vars[i])) )
250  {
251  SCIP_CALL( SCIPchgVarLbDive(scip, vars[i], solval) );
252  SCIP_CALL( SCIPchgVarUbDive(scip, vars[i], solval) );
253  }
254  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_INTEGER && !SCIPisIntegral(scip, solval) )
255  {
256  SCIP_CALL( SCIPchgVarLbDive(scip, vars[i], SCIPfloor(scip, solval)) );
257  SCIP_CALL( SCIPchgVarUbDive(scip, vars[i], SCIPceil(scip, solval)) );
258  }
259 
260  SCIP_CALL( SCIPchgVarObjDive(scip, vars[i], 0.0) );
261  }
262 
263  /* fix LP rows with nonzero dual solution to reduce LP to the optimal face */
264  for( i = 0; i < nlprows; ++i )
265  {
266  SCIP_Real dualsol;
267  dualsol = SCIProwGetDualsol(lprows[i]);
268  if( !SCIPisZero(scip, dualsol) )
269  {
270  if( dualsol > 0 && SCIPisFeasEQ(scip, SCIProwGetLhs(lprows[i]), SCIPgetRowActivity(scip,lprows[i])) )
271  {
272  SCIP_CALL( SCIPchgRowRhsDive(scip, lprows[i], SCIProwGetLhs(lprows[i])) );
273  }
274  else if( dualsol < 0 && SCIPisFeasEQ(scip, SCIProwGetRhs(lprows[i]), SCIPgetRowActivity(scip,lprows[i])) )
275  {
276  SCIP_CALL( SCIPchgRowLhsDive(scip, lprows[i], SCIProwGetRhs(lprows[i])) );
277  }
278  }
279  }
280 
281  newpoint = TRUE;
282  counter = 0;
283 
284  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
285  {
286  /* update cloud intervals for candidates that have been integral in original LP, but have been fractional in previous cloud points */
287  for( i = 0; i < ndiscvars; ++i)
288  {
289  SCIP_Real solval;
290  solval = SCIPgetSolVal(scip, NULL, vars[i]);
291 
292  assert(newlpcandsmin != NULL);
293  assert(newlpcandsmax != NULL);
294 
295  newlpcandsmin[i] = solval;
296  newlpcandsmax[i] = solval;
297  }
298  }
299 
300  /* loop that generates new cloud point */
301  while( newpoint && branchruledata->usecloud )
302  {
303 #ifdef NDEBUG
304  SCIP_RETCODE retcode;
305 #endif
306 
307  /* apply feasibility pump objective function to fractional variables */
308  for( i = 0; i < nlpcands; ++i )
309  {
310  SCIP_Real frac;
311  frac = SCIPfrac(scip, SCIPgetSolVal(scip, NULL, lpcandscopy[i]));
312 
313  if( !SCIPisZero(scip, frac) && !SCIPisIntegral(scip, lpcandsmin[i]) && !SCIPisIntegral(scip, lpcandsmax[i]) )
314  {
315  if( frac < 0.5 )
316  {
317  SCIP_CALL( SCIPchgVarObjDive(scip, vars[i], 1.0) );
318  }
319  else
320  {
321  SCIP_CALL( SCIPchgVarObjDive(scip, vars[i], -1.0) );
322  }
323  }
324  }
325 
326  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
327  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
328  */
329 #ifdef NDEBUG
330  retcode = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
331  if( retcode != SCIP_OKAY )
332  {
333  SCIPwarningMessage(scip, "Error while solving LP in " BRANCHRULE_NAME "; LP solve terminated with code <%d>\n",retcode);
334  }
335 #else
336  SCIP_CALL( SCIPsolveDiveLP(scip, -1, &lperror, NULL) );
337 #endif
338 
339  if( lperror || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
340  break;
341 
342  /* check if a solution has been found */
343  if( SCIPgetNLPBranchCands(scip) == 0 )
344  {
345  SCIP_Bool success;
346  SCIP_SOL* sol;
347 
348  /* create solution from diving LP */
349  SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
350  SCIP_CALL( SCIPlinkLPSol(scip, sol) );
351  SCIPdebugMessage("cloud branching found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, sol));
352 
353  /* try to add solution to SCIP */
354  SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, FALSE, FALSE, &success) );
355 
356  /* check, if solution was feasible and good enough */
357  if( success )
358  {
359  SCIPdebugMessage(" -> solution was feasible and good enough\n");
361  *result = SCIP_CUTOFF;
362  goto TERMINATE;
363  }
364  }
365 
366  /* update cloud intervals for candidates that have been fractional in original LP */
367  newpoint = FALSE;
368  for( i = 0; i < nlpcands; ++i)
369  {
370  SCIP_Real solval;
371  solval = SCIPgetSolVal(scip, NULL, lpcandscopy[i]);
372 
373  if( SCIPisFeasIntegral(scip,solval) && !SCIPisFeasIntegral(scip, lpcandsmin[i]) && !SCIPisFeasIntegral(scip, lpcandsmax[i]) )
374  newpoint = TRUE;
375 
376  lpcandsmin[i] = MIN(lpcandsmin[i], solval);
377  lpcandsmax[i] = MAX(lpcandsmax[i], solval);
378  }
379 
380  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
381  {
382  /* update cloud intervals for candidates that have been integral in original LP, but have been fractional in previous cloud points */
383  for( i = 0; i < ndiscvars; ++i)
384  {
385  SCIP_Real solval;
386  solval = SCIPgetSolVal(scip, NULL, vars[i]);
387 
388  assert(newlpcandsmin != NULL);
389  assert(newlpcandsmax != NULL);
390 
391  newlpcandsmin[i] = MIN(newlpcandsmin[i], solval);
392  newlpcandsmax[i] = MAX(newlpcandsmax[i], solval);
393  }
394  }
395 
396  if( newpoint )
397  counter++;
398 
399  if( branchruledata->maxpoints != -1 && counter >= branchruledata->maxpoints )
400  break;
401  }
402 
403  SCIPdebugMessage("considered %d additional points in the cloud\n",counter);
404 
405 
406  /* terminate the diving */
408 
409  SCIP_CALL( SCIPstopClock(scip, branchruledata->cloudclock) );
410  ncomplete = nlpcands;
411 
412  if( counter > 0 )
413  {
414  branchruledata->ncloudpoints += (counter+1);
415  branchruledata->nuseful++;
416 
417  counter = 0;
418 
419  /* sort all variables for which both bounds are fractional to the front */
420  for( i = 0; i < nlpcands; ++i)
421  {
422  if( !SCIPisFeasIntegral(scip, lpcandsmin[i]) && !SCIPisFeasIntegral(scip, lpcandsmax[i]) )
423  {
424  assert(counter <= i);
425  lpcandscopy[counter] = lpcandscopy[i];
426  lpcandssolcopy[counter] = lpcandssolcopy[i];
427  lpcandsfraccopy[counter] = lpcandsfraccopy[i];
428  counter++;
429  }
430  }
431 
432  /* should only be in that if condition when at least one bound could be made integral */
433  assert(nlpcands - counter > 0);
434 
435  ncomplete = counter;
436 
437  /* filter all variables for which exactly one interval bound is fractional */
438  for( i = 0; i < nlpcands && !branchruledata->onlyF2; ++i)
439  {
440  if( SCIPisFeasIntegral(scip, lpcandsmin[i]) != SCIPisFeasIntegral(scip, lpcandsmax[i]) )
441  {
442  assert(counter < nlpcands);
443  lpcandscopy[counter] = lpcandscopy[i];
444  lpcandssolcopy[counter] = lpcandssolcopy[i];
445  lpcandsfraccopy[counter] = lpcandsfraccopy[i];
446 
447  if( SCIPisFeasIntegral(scip, lpcandsmin[i]) )
448  branchruledata->skipdown[counter] = TRUE;
449  if( SCIPisFeasIntegral(scip, lpcandsmax[i]) )
450  branchruledata->skipup[counter] = TRUE;
451  assert(branchruledata->skipdown[counter] != branchruledata->skipup[counter]);
452 
453  counter++;
454  }
455  }
456 
457  SCIPdebugMessage("can fully skip %d/%d strong branching candidates\n", nlpcands - counter, nlpcands);
458  SCIPdebugMessage("can half skip %d/%d strong branching candidates\n", counter - ncomplete, nlpcands);
459  }
460  else
461  counter = nlpcands;
462 
463  /* if cloud sampling was not successful enough, disable it */
464  if( branchruledata->usecloud &&
465  branchruledata->ntried > 100 &&
466  (SCIP_Real)branchruledata->nuseful / branchruledata->ntried < branchruledata->minsuccessrate )
467  {
468  SCIPdebugMessage("Disabling cloud branching (not effective)\n");
469  branchruledata->usecloud = FALSE;
470  }
471 
472  if( branchruledata->onlyF2 )
473  counter = MAX(counter,1);
474 
475  /* the second counter should maybe be replaced at some point */
476  SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcandscopy, lpcandssolcopy, lpcandsfraccopy, branchruledata->skipdown,
477  branchruledata->skipup, counter, counter, ncomplete, &branchruledata->lastcand, allowaddcons, 0, FALSE, FALSE,
478  &bestcand, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
479 
480  if( branchruledata->lastcand <= ncomplete )
481  {
482  SCIPdebugMessage("saved %d of %d LPs\n", 2*(nlpcands - ncomplete), 2*nlpcands);
483  branchruledata->nsavedlps += 2*(nlpcands - ncomplete);
484  }
485  else
486  {
487  SCIPdebugMessage("saved %d of %d LPs\n", 2*(nlpcands - counter)+counter - ncomplete, 2*nlpcands);
488  branchruledata->nsavedlps += 2*(nlpcands - counter)+counter - ncomplete;
489  }
490 
491  /* perform the branching */
492  if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED && counter > 0 )
493  {
494  SCIP_NODE* downchild;
495  SCIP_NODE* upchild;
496  SCIP_VAR* var;
497  SCIP_Bool allcolsinlp;
498  SCIP_Bool exactsolve;
499  SCIP_Bool newselected;
500 
501  assert(*result == SCIP_DIDNOTRUN);
502  assert(0 <= bestcand && bestcand < nlpcands);
503  assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
504 
505  var = lpcandscopy[bestcand];
506  newselected = FALSE;
507 
508  /* if there are new candidates variables, also try them */
509  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion && branchruledata->lastcand > ncomplete )
510  {
511  SCIP_VAR** newlpcands;
512 
513  counter = 0;
514  /* reset skipping arrays to zero */
515  BMSclearMemoryArray(branchruledata->skipdown, ndiscvars);
516  BMSclearMemoryArray(branchruledata->skipup, ndiscvars);
517 
518  SCIP_CALL( SCIPallocBufferArray(scip, &newlpcands, ndiscvars) );
519 
520  /* get new LP candidates with one fractional bound */
521  for( i = 0; i < ndiscvars; ++i)
522  {
523  if( !SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[i])) )
524  continue;
525 
526  assert(newlpcandsmin != NULL);
527  assert(newlpcandsmax != NULL);
528 
529  if( SCIPisFeasIntegral(scip, newlpcandsmin[i]) != SCIPisFeasIntegral(scip, newlpcandsmax[i]) )
530  {
531  newlpcands[counter] = vars[i];
532 
533  if( SCIPisFeasIntegral(scip, newlpcandsmin[i]) )
534  branchruledata->skipdown[counter] = TRUE;
535  if( SCIPisFeasIntegral(scip, newlpcandsmax[i]) )
536  branchruledata->skipup[counter] = TRUE;
537  assert(branchruledata->skipdown[counter] != branchruledata->skipup[counter]);
538 
539  counter++;
540  }
541  }
542 
543  /* when there are new candidates, also try these */
544  if( counter > 0 )
545  {
546  SCIP_Real newdown;
547  SCIP_Real newup;
548  SCIP_Real newscore;
549  int newcand;
550  SCIP_Bool newdownvalid;
551  SCIP_Bool newupvalid;
552  SCIP_Real newbound;
553 
554  branchruledata->ntriedunions++;
555  newscore = -SCIPinfinity(scip);
556  SCIP_CALL( SCIPselectVarPseudoStrongBranching(scip, newlpcands, branchruledata->skipdown, branchruledata->skipup, counter, counter,
557  allowaddcons, &newcand, &newdown, &newup, &newscore, &newdownvalid, &newupvalid, &newbound, result) );
558 
559  if( *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM || *result == SCIP_CONSADDED )
560  {
561  SCIPfreeBufferArray(scip, &newlpcands);
562  goto TERMINATE;
563  }
564 
565  if( newscore > bestscore )
566  {
567  bestcand = newcand;
568  var = newlpcands[newcand];
569  bestdown = newdown;
570  bestup = newup;
571  bestdownvalid = newdownvalid;
572  bestupvalid = newupvalid;
573  bestscore = newscore;
574  newselected = TRUE;
575  branchruledata->nusefulunions++;
576  }
577  }
578  /* free temporary array for new union candidates */
579  SCIPfreeBufferArray(scip, &newlpcands);
580  }
581 
582  /* perform the branching */
583  if( !newselected )
584  {
585  SCIPdebugMessage(" -> %d candidates, selected candidate %d: variable <%s> (solval=%g, down=%g, up=%g, score=%g)\n",
586  counter, bestcand, SCIPvarGetName(var), lpcandssolcopy[bestcand], bestdown, bestup, bestscore);
587  }
588  else
589  {
590  SCIPdebugMessage(" -> selected from %d new candidates, candidate %d: variable <%s> (down=%g, up=%g, score=%g)\n",
591  counter, bestcand, SCIPvarGetName(var), bestdown, bestup, bestscore);
592  }
593 
594  assert(!SCIPisFeasIntegral(scip, SCIPvarGetSol(lpcands[bestcand], TRUE)));
595 
596  SCIP_CALL( SCIPbranchVar(scip, var, &downchild, NULL, &upchild) );
597  assert(downchild != NULL);
598  assert(upchild != NULL);
599 
600  /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
601  * for cutting off sub problems and improving lower bounds of children
602  */
603  exactsolve = SCIPisExactSolve(scip);
604 
605  /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
606  allcolsinlp = SCIPallColsInLP(scip);
607 
608  /* update the lower bounds in the children */
609  if( allcolsinlp && !exactsolve )
610  {
611  SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
612  SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
613  }
614  SCIPdebugMessage(" -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
615  SCIPdebugMessage(" -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
616 
617  *result = SCIP_BRANCHED;
618  }
619 
620  TERMINATE:
621  if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
622  {
623  SCIPfreeBufferArray(scip, &newlpcandsmax);
624  SCIPfreeBufferArray(scip, &newlpcandsmin);
625  }
626  SCIPfreeBufferArray(scip, &lpcandscopy);
627  SCIPfreeBufferArray(scip, &lpcandssolcopy);
628  SCIPfreeBufferArray(scip, &lpcandsfraccopy);
629  SCIPfreeBufferArray(scip, &lpcandsmax);
630  SCIPfreeBufferArray(scip, &lpcandsmin);
631 
632  /* if union usage was not successful enough, disable it */
633  if( branchruledata->useunion &&
634  branchruledata->ntriedunions > 10 &&
635  (SCIP_Real)branchruledata->nusefulunions / branchruledata->ntriedunions < branchruledata->minsuccessunion )
636  {
637  SCIPdebugMessage("Disabling union usage (not effective)\n");
638  branchruledata->useunion = FALSE;
639  }
640 
641  return SCIP_OKAY;
642 }
643 
644 /*
645  * branching rule specific interface methods
646  */
647 
648 /** creates the cloud branching rule and includes it in SCIP */
650  SCIP* scip /**< SCIP data structure */
651  )
652 {
653  SCIP_BRANCHRULEDATA* branchruledata;
654  SCIP_BRANCHRULE* branchrule;
655 
656  /* create cloud branching rule data */
657  SCIP_CALL( SCIPallocMemory(scip, &branchruledata) );
658  branchruledata->lastcand = 0;
659  branchruledata->skipup = NULL;
660  branchruledata->skipdown = NULL;
661  SCIP_CALL( SCIPcreateClock(scip, &(branchruledata->cloudclock)) );
662 
663  /* include branching rule */
664  branchrule = NULL;
666  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
667  assert(branchrule != NULL);
668 
669  /* set non-fundamental callbacks via setter functions */
670  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeCloud) );
671  SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitCloud) );
672  SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpCloud) );
673 
674  /* add cloud branching rule parameters */
676  "branching/" BRANCHRULE_NAME "/usecloud",
677  "should a cloud of points be used?",
678  &branchruledata->usecloud, FALSE, DEFAULT_USECLOUD, NULL, NULL) );
680  "branching/" BRANCHRULE_NAME "/onlyF2",
681  "should only F2 be used?",
682  &branchruledata->onlyF2, FALSE, DEFAULT_ONLYF2, NULL, NULL) );
684  "branching/" BRANCHRULE_NAME "/useunion",
685  "should the union of candidates be used?",
686  &branchruledata->useunion, FALSE, DEFAULT_USEUNION, NULL, NULL) );
688  "branching/" BRANCHRULE_NAME "/maxpoints",
689  "maximum number of points for the cloud (-1 means no limit)",
690  &branchruledata->maxpoints, FALSE, DEFAULT_MAXPOINTS, -1, INT_MAX, NULL, NULL) );
692  "branching/" BRANCHRULE_NAME "/minsuccessrate",
693  "minimum success rate for the cloud",
694  &branchruledata->minsuccessrate, FALSE, DEFAULT_MINSUCCESSRATE, 0.0, 1.0, NULL, NULL) );
696  "branching/" BRANCHRULE_NAME "/minsuccessunion",
697  "minimum success rate for the union",
698  &branchruledata->minsuccessunion, FALSE, DEFAULT_MINSUCCESSUNION, 0.0, 1.0, NULL, NULL) );
700  "branching/" BRANCHRULE_NAME "/maxdepthunion",
701  "maximum depth for the union",
702  &branchruledata->maxdepthunion, FALSE, DEFAULT_MAXDEPTHUNION, 0, 65000, NULL, NULL) );
703 
704  return SCIP_OKAY;
705 }
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:33158
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
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
#define DEFAULT_USECLOUD
Definition: branch_cloud.c:44
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip.c:33734
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40818
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12514
#define NULL
Definition: lpi_spx.cpp:130
SCIP_RETCODE SCIPchgRowLhsDive(SCIP *scip, SCIP_ROW *row, SCIP_Real newlhs)
Definition: scip.c:31843
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40801
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
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
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40950
SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:31772
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
#define FALSE
Definition: def.h:56
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10743
#define TRUE
Definition: def.h:55
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
#define SCIP_CALL(x)
Definition: def.h:266
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1877
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:36299
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition: scip.c:26785
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
static SCIP_DECL_BRANCHINIT(branchInitCloud)
Definition: branch_cloud.c:118
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_MAXDEPTHUNION
Definition: branch_cloud.c:49
#define BRANCHRULE_PRIORITY
Definition: branch_cloud.c:40
SCIP_RETCODE SCIPstartDive(SCIP *scip)
Definition: scip.c:31575
#define BRANCHRULE_NAME
Definition: branch_cloud.c:38
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip.c:26829
SCIP_RETCODE SCIPresetClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40784
#define DEFAULT_USEUNION
Definition: branch_cloud.c:45
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition: scip.c:12363
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35066
SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:31740
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
static SCIP_DECL_BRANCHEXECLP(branchExeclpCloud)
Definition: branch_cloud.c:142
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
#define DEFAULT_MINSUCCESSUNION
Definition: branch_cloud.c:48
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_RETCODE SCIPchgRowRhsDive(SCIP *scip, SCIP_ROW *row, SCIP_Real newrhs)
Definition: scip.c:31876
cloud branching rule
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 SCIPincludeBranchruleCloud(SCIP *scip)
Definition: branch_cloud.c:649
SCIP_RETCODE SCIPchgVarObjDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:31699
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1765
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:34002
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:41758
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#define BRANCHRULE_MAXBOUNDDIST
Definition: branch_cloud.c:42
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:53
#define MAX(x, y)
Definition: tclique_def.h:75
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 SCIPfrac(SCIP *scip, SCIP_Real val)
Definition: scip.c:41794
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:17497
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34648
static SCIP_DECL_BRANCHFREE(branchFreeCloud)
Definition: branch_cloud.c:84
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
all variables full strong LP branching rule
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:41770
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:18935
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1755
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:20545
SCIP_RETCODE SCIPendDive(SCIP *scip)
Definition: scip.c:31618
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:10788
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
#define SCIP_Real
Definition: def.h:127
#define MIN(x, y)
Definition: memory.c:67
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40716
SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28245
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:10572
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:7036
#define BRANCHRULE_DESC
Definition: branch_cloud.c:39
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip.c:26847
SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:31999
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 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:3629
int SCIPgetNLPRows(SCIP *scip)
Definition: scip.c:26806
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip.c:1012