SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file branch_cloud.c
26 * @ingroup DEFPLUGINS_BRANCH
27 * @brief cloud branching rule
28 * @author Timo Berthold
29 * @author Domenico Salvagnin
30 *
31 * Branching rule based on muliple optimal solutions to the current LP relaxation. See@n
32 * Cloud Branching@n
33 * Timo Berthold and Domenico Salvagnin@n
34 * Integration of AI and OR Techniques in Constraint Programming for Combinatorial Optimization Problems, CPAIOR 2013, LNCS 7874@n
35 * Preliminary version available as <a href="http://opus4.kobv.de/opus4-zib/frontdoor/index/index/docId/1730">ZIB-Report 13-01</a>.
36 */
37
38/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
39
42#include "scip/branch_cloud.h"
44#include "scip/pub_branch.h"
45#include "scip/pub_lp.h"
46#include "scip/pub_message.h"
47#include "scip/pub_tree.h"
48#include "scip/pub_var.h"
49#include "scip/scip_branch.h"
50#include "scip/scip_exact.h"
51#include "scip/scip_general.h"
52#include "scip/scip_lp.h"
53#include "scip/scip_mem.h"
54#include "scip/scip_message.h"
55#include "scip/scip_numerics.h"
56#include "scip/scip_param.h"
57#include "scip/scip_prob.h"
58#include "scip/scip_sol.h"
60#include "scip/scip_timing.h"
61#include "scip/scip_tree.h"
62#include "scip/scip_var.h"
63
64
65#define BRANCHRULE_NAME "cloud"
66#define BRANCHRULE_DESC "branching rule that considers several alternative LP optima"
67#define BRANCHRULE_PRIORITY 0
68#define BRANCHRULE_MAXDEPTH -1
69#define BRANCHRULE_MAXBOUNDDIST 1.0
70
71#define DEFAULT_USECLOUD TRUE /**< should a cloud of points be used? */
72#define DEFAULT_USEUNION FALSE /**< should the union of candidates be used? */
73#define DEFAULT_MAXPOINTS -1 /**< maximum number of points for the cloud (-1 means no limit) */
74#define DEFAULT_MINSUCCESSRATE 0.0 /**< minimum success rate for the cloud */
75#define DEFAULT_MINSUCCESSUNION 0.0 /**< minimum success rate for the union */
76#define DEFAULT_MAXDEPTHUNION 65000 /**< maximum depth for the union */
77#define DEFAULT_ONLYF2 FALSE /**< should only F2 be used? */
78
79/*
80 * Data structures
81 */
82
83/** branching rule data */
84struct SCIP_BranchruleData
85{
86 int lastcand; /**< last evaluated candidate of last branching rule execution */
87 SCIP_Bool usecloud; /**< should a cloud of points be used? */
88 SCIP_Bool useunion; /**< should the union of candidates be used? */
89 SCIP_Bool onlyF2; /**< should only F2 be used? */
90 int maxpoints; /**< maximum number of points for the cloud (-1 means no limit) */
91 SCIP_Real minsuccessrate; /**< minimum success rate for the cloud */
92 SCIP_Real minsuccessunion; /**< minimum success rate for the union */
93 SCIP_CLOCK* cloudclock; /**< clock for cloud diving */
94 SCIP_Bool* skipdown; /**< should down branch be skiped? */
95 SCIP_Bool* skipup; /**< should up branch be skiped? */
96 int ntried; /**< number of times the cloud was tried */
97 int ntriedunions; /**< number of times the cloud was tried */
98 int nuseful; /**< number of times the cloud was useful (at least one LP skipped) */
99 int nusefulunions; /**< number of times the union was useful (took candidate from new list) */
100 int ncloudpoints; /**< sum of cloud points taken over all nodes with at least two poitns in cloud */
101 int nsavedlps; /**< sum of saved LPs taken over all nodes with at least two points in cloud */
102 int maxdepthunion; /**< maximum depth for the union */
103 int skipsize; /**< size of skipdown and skipup array */
104};
105
106/*
107 * Callback methods of branching rule
108 */
109
110/** copy method for branchrule plugins (called when SCIP copies plugins) */
111static
112SCIP_DECL_BRANCHCOPY(branchCopyCloud)
113{ /*lint --e{715}*/
114 assert(scip != NULL);
115 assert(branchrule != NULL);
116
118
119 /* call inclusion method of branchrule */
121
122 return SCIP_OKAY;
123}
124
125/** destructor of branching rule to free user data (called when SCIP is exiting) */
126static
127SCIP_DECL_BRANCHFREE(branchFreeCloud)
128{ /*lint --e{715}*/
129 SCIP_BRANCHRULEDATA* branchruledata;
130
131 /* free branching rule data */
132 branchruledata = SCIPbranchruleGetData(branchrule);
133
134 if( branchruledata->cloudclock != NULL)
135 {
137 int ntried;
138 int nuseful;
139 int ncloudpoints;
140 int nsavedlps;
141
142 ntried = branchruledata->ntried;
143 nuseful = branchruledata->nuseful;
144 ncloudpoints = branchruledata->ncloudpoints;
145 nsavedlps = branchruledata->nsavedlps;
146
147 SCIPstatisticMessage("time spent diving in cloud branching: %g\n", SCIPgetClockTime(scip, branchruledata->cloudclock));
148 SCIPstatisticMessage("cloud branching tried: %6d found cloud: %6d \n", ntried, nuseful);
149 SCIPstatisticMessage("cloud used points: %6d saved LPs: %6d \n", ncloudpoints, nsavedlps);
150 SCIPstatisticMessage("cloud success rates useful/tried: %8.6g points/useful: %8.6g saved/useful: %8.6g \n",
151 ntried == 0 ? -1 : (SCIP_Real)nuseful / ntried, nuseful == 0 ? -1 : (SCIP_Real)ncloudpoints / nuseful, nuseful == 0 ? -1 : (SCIP_Real)nsavedlps / nuseful);
152 )
153
154 SCIP_CALL( SCIPfreeClock(scip, &(branchruledata->cloudclock)) );
155 }
156
157 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->skipdown, branchruledata->skipsize);
158 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->skipup, branchruledata->skipsize);
159
160 SCIPfreeBlockMemory(scip, &branchruledata);
161 SCIPbranchruleSetData(branchrule, NULL);
162
163 return SCIP_OKAY;
164}
165
166
167/** initialization method of branching rule (called after problem was transformed) */
168static
169SCIP_DECL_BRANCHINIT(branchInitCloud)
170{ /*lint --e{715}*/
171 SCIP_BRANCHRULEDATA* branchruledata;
172
173 /* initialize branching rule data */
174 branchruledata = SCIPbranchruleGetData(branchrule);
175 branchruledata->lastcand = 0;
176 branchruledata->nuseful = 0;
177 branchruledata->nusefulunions = 0;
178 branchruledata->ntried = 0;
179 branchruledata->ntriedunions = 0;
180 branchruledata->ncloudpoints = 0;
181 branchruledata->nsavedlps = 0;
182
183 if( branchruledata->cloudclock != NULL)
184 {
185 SCIP_CALL( SCIPresetClock(scip, branchruledata->cloudclock) );
186 }
187
188 return SCIP_OKAY;
189}
190
191/** branching execution method for fractional LP solutions */
192static
193SCIP_DECL_BRANCHEXECLP(branchExeclpCloud)
194{ /*lint --e{715}*/
195 SCIP_BRANCHRULEDATA* branchruledata;
196
198 SCIP_VAR** lpcandscopy;
199
200 SCIP_VAR** vars;
204 SCIP_Real* lpcandsfraccopy;
205 SCIP_Real* lpcandssolcopy;
206 SCIP_Real* lpcandsmin;
207 SCIP_Real* lpcandsmax;
208 SCIP_Real* newlpcandsmin;
209 SCIP_Real* newlpcandsmax;
210
211 SCIP_Real bestdown;
212 SCIP_Real bestup;
213 SCIP_Real bestscore;
214 SCIP_Real provedbound;
215
216 SCIP_Bool bestdownvalid;
217 SCIP_Bool bestupvalid;
218 SCIP_Bool newpoint;
220
221 int nlpcands;
222 int npriolpcands;
223 int nvars;
224 int bestcand;
225 int nlprows;
226 int i;
227 int counter;
228 int ncomplete;
229 int ndiscvars;
230
231 assert(branchrule != NULL);
232 assert(scip != NULL);
233 assert(result != NULL);
234
236
237 if( !SCIPisLPSolBasic(scip) )
238 return SCIP_OKAY;
239
240 SCIPdebugMsg(scip, "Execlp method of " BRANCHRULE_NAME " branching\n");
241
242 /* get problem variables and LP row data */
247
248 /* get branching candidates */
251 assert(nlpcands > 0);
252
253 /* get branching rule data */
254 branchruledata = SCIPbranchruleGetData(branchrule);
255 assert(branchruledata != NULL);
256
257 /* allocate skipping arrays on first call */
258 if( branchruledata->skipdown == NULL )
259 {
260 assert(branchruledata->skipup == NULL);
261
262 branchruledata->skipsize = nvars;
263 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipdown, branchruledata->skipsize) );
264 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipup, branchruledata->skipsize) );
265 }
266
267 /* reset skipping arrays to zero */
268 BMSclearMemoryArray(branchruledata->skipdown, branchruledata->skipsize);
269 BMSclearMemoryArray(branchruledata->skipup, branchruledata->skipsize);
270
271 /* allocate required data structures */
274 SCIP_CALL( SCIPallocBufferArray(scip, &lpcandscopy, nlpcands) );
275 SCIP_CALL( SCIPallocBufferArray(scip, &lpcandsfraccopy, nlpcands) );
276 SCIP_CALL( SCIPallocBufferArray(scip, &lpcandssolcopy, nlpcands) );
277 newlpcandsmin = NULL;
278 newlpcandsmax = NULL;
279 if( branchruledata->useunion && SCIPgetDepth(scip) < branchruledata->maxdepthunion && !branchruledata->onlyF2)
280 {
281 SCIP_CALL( SCIPallocBufferArray(scip, &newlpcandsmin, ndiscvars) );
282 SCIP_CALL( SCIPallocBufferArray(scip, &newlpcandsmax, ndiscvars) );
283 }
286 BMScopyMemoryArray(lpcandssolcopy, lpcandssol, nlpcands);
287 BMScopyMemoryArray(lpcandsfraccopy, lpcandsfrac, nlpcands);
288 BMScopyMemoryArray(lpcandscopy, lpcands, nlpcands);
289
290 SCIP_CALL( SCIPstartClock(scip, branchruledata->cloudclock) );
291 branchruledata->ntried++;
292
293 /* start diving to calculate the solution cloud */
295
296 /* fix variables with nonzero reduced costs to reduce LP to the optimal face */
297 for( i = 0; i < nvars; ++i )
298 {
299 SCIP_Real solval;
300 solval = SCIPgetSolVal(scip, NULL, vars[i]);
301
303 {
304 SCIP_CALL( SCIPchgVarLbDive(scip, vars[i], solval) );
305 SCIP_CALL( SCIPchgVarUbDive(scip, vars[i], solval) );
306 }
307 /* for non-implied integral variables with zero cost and fractional value we only allow the next integral values */
309 && !SCIPisIntegral(scip, solval) )
310 {
313 }
314
316 }
317
318 /* fix LP rows with nonzero dual solution to reduce LP to the optimal face */
319 for( i = 0; i < nlprows; ++i )
320 {
321 SCIP_Real dualsol;
322 dualsol = SCIProwGetDualsol(lprows[i]);
323 if( !SCIPisZero(scip, dualsol) )
324 {
326 {
328 }
329 else if( dualsol < 0 && SCIPisFeasEQ(scip, SCIProwGetRhs(lprows[i]), SCIPgetRowActivity(scip,lprows[i])) )
330 {
332 }
333 }
334 }
335
336 newpoint = TRUE;
337 counter = 0;
338
339 if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
340 {
341 /* update cloud intervals for candidates that have been integral in original LP, but have been fractional in previous cloud points */
342 for( i = 0; i < ndiscvars; ++i)
343 {
344 SCIP_Real solval;
345 solval = SCIPgetSolVal(scip, NULL, vars[i]);
346
347 assert(newlpcandsmin != NULL);
348 assert(newlpcandsmax != NULL);
349
350 newlpcandsmin[i] = solval;
351 newlpcandsmax[i] = solval;
352 }
353 }
354
355 /* loop that generates new cloud point */
356 while( newpoint && branchruledata->usecloud )
357 {
358#ifdef NDEBUG
359 SCIP_RETCODE retcode;
360#endif
361
362 /* apply feasibility pump objective function to fractional variables */
363 for( i = 0; i < nlpcands; ++i )
364 {
366 frac = SCIPfrac(scip, SCIPgetSolVal(scip, NULL, lpcandscopy[i]));
367
368 if( !SCIPisZero(scip, frac) && !SCIPisIntegral(scip, lpcandsmin[i]) && !SCIPisIntegral(scip, lpcandsmax[i]) )
369 {
370 if( frac < 0.5 )
371 {
373 }
374 else
375 {
377 }
378 }
379 }
380
381 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
382 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
383 */
384#ifdef NDEBUG
385 retcode = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
386 if( retcode != SCIP_OKAY )
387 {
388 SCIPwarningMessage(scip, "Error while solving LP in " BRANCHRULE_NAME "; LP solve terminated with code <%d>\n",retcode);
389 }
390#else
392#endif
393
395 break;
396
397 /* check if a solution has been found */
398 if( SCIPgetNLPBranchCands(scip) == 0 )
399 {
400 SCIP_Bool success;
401 SCIP_SOL* sol;
402
403 /* create solution from diving LP */
406 SCIPdebugMsg(scip, "cloud branching found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, sol));
407
408 /* try to add solution to SCIP */
410
411 /* check, if solution was feasible and good enough */
412 if( success )
413 {
414 SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
417 goto TERMINATE;
418 }
419 }
420
421 /* update cloud intervals for candidates that have been fractional in original LP */
422 newpoint = FALSE;
423 for( i = 0; i < nlpcands; ++i)
424 {
425 SCIP_Real solval;
426 solval = SCIPgetSolVal(scip, NULL, lpcandscopy[i]);
427
428 if( SCIPisFeasIntegral(scip,solval) && !SCIPisFeasIntegral(scip, lpcandsmin[i]) && !SCIPisFeasIntegral(scip, lpcandsmax[i]) )
429 newpoint = TRUE;
430
431 lpcandsmin[i] = MIN(lpcandsmin[i], solval);
432 lpcandsmax[i] = MAX(lpcandsmax[i], solval);
433 }
434
435 if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
436 {
437 /* update cloud intervals for candidates that have been integral in original LP, but have been fractional in previous cloud points */
438 for( i = 0; i < ndiscvars; ++i)
439 {
440 SCIP_Real solval;
441 solval = SCIPgetSolVal(scip, NULL, vars[i]);
442
443 assert(newlpcandsmin != NULL);
444 assert(newlpcandsmax != NULL);
445
446 newlpcandsmin[i] = MIN(newlpcandsmin[i], solval);
447 newlpcandsmax[i] = MAX(newlpcandsmax[i], solval);
448 }
449 }
450
451 if( newpoint )
452 counter++;
453
454 if( branchruledata->maxpoints != -1 && counter >= branchruledata->maxpoints )
455 break;
456 }
457
458 SCIPdebugMsg(scip, "considered %d additional points in the cloud\n",counter);
459
460 /* terminate the diving */
462
463 SCIP_CALL( SCIPstopClock(scip, branchruledata->cloudclock) );
464 ncomplete = nlpcands;
465
466 if( counter > 0 )
467 {
468 branchruledata->ncloudpoints += (counter+1);
469 branchruledata->nuseful++;
470
471 counter = 0;
472
473 /* sort all variables for which both bounds are fractional to the front */
474 for( i = 0; i < nlpcands; ++i)
475 {
476 if( !SCIPisFeasIntegral(scip, lpcandsmin[i]) && !SCIPisFeasIntegral(scip, lpcandsmax[i]) )
477 {
478 assert(counter <= i);
479 lpcandscopy[counter] = lpcandscopy[i];
480 lpcandssolcopy[counter] = lpcandssolcopy[i];
481 lpcandsfraccopy[counter] = lpcandsfraccopy[i];
482 counter++;
483 }
484 }
485
486 /* should only be in that if condition when at least one bound could be made integral */
487 assert(nlpcands - counter > 0);
488
489 ncomplete = counter;
490
491 /* filter all variables for which exactly one interval bound is fractional */
492 for( i = 0; i < nlpcands && !branchruledata->onlyF2; ++i)
493 {
494 if( SCIPisFeasIntegral(scip, lpcandsmin[i]) != SCIPisFeasIntegral(scip, lpcandsmax[i]) )
495 {
496 assert(counter < nlpcands);
497 lpcandscopy[counter] = lpcandscopy[i];
498 lpcandssolcopy[counter] = lpcandssolcopy[i];
499 lpcandsfraccopy[counter] = lpcandsfraccopy[i];
500
501 if( SCIPisFeasIntegral(scip, lpcandsmin[i]) )
502 branchruledata->skipdown[counter] = TRUE;
503 if( SCIPisFeasIntegral(scip, lpcandsmax[i]) )
504 branchruledata->skipup[counter] = TRUE;
505 assert(branchruledata->skipdown[counter] != branchruledata->skipup[counter]);
506
507 counter++;
508 }
509 }
510
511 SCIPdebugMsg(scip, "can fully skip %d/%d strong branching candidates\n", nlpcands - counter, nlpcands);
512 SCIPdebugMsg(scip, "can half skip %d/%d strong branching candidates\n", counter - ncomplete, nlpcands);
513 }
514 else
515 counter = nlpcands;
516
517 /* if cloud sampling was not successful enough, disable it */
518 if( branchruledata->usecloud &&
519 branchruledata->ntried > 100 &&
520 (SCIP_Real)branchruledata->nuseful / branchruledata->ntried < branchruledata->minsuccessrate )
521 {
522 SCIPdebugMsg(scip, "Disabling cloud branching (not effective)\n");
523 branchruledata->usecloud = FALSE;
524 }
525
526 if( branchruledata->onlyF2 )
527 counter = MAX(counter,1);
528
529 /* the second counter should maybe be replaced at some point */
530 SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcandscopy, lpcandssolcopy, lpcandsfraccopy, branchruledata->skipdown,
531 branchruledata->skipup, counter, counter, ncomplete, &branchruledata->lastcand, 0, FALSE, FALSE,
532 &bestcand, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
533
534 if( branchruledata->lastcand <= ncomplete )
535 {
536 SCIPdebugMsg(scip, "saved %d of %d LPs\n", 2*(nlpcands - ncomplete), 2*nlpcands);
537 branchruledata->nsavedlps += 2*(nlpcands - ncomplete);
538 }
539 else
540 {
541 SCIPdebugMsg(scip, "saved %d of %d LPs\n", 2*(nlpcands - counter)+counter - ncomplete, 2*nlpcands);
542 branchruledata->nsavedlps += 2*(nlpcands - counter)+counter - ncomplete;
543 }
544
545 /* perform the branching */
546 if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED && counter > 0 )
547 {
548 SCIP_NODE* downchild;
549 SCIP_NODE* upchild;
550 SCIP_VAR* var;
551 SCIP_Bool allcolsinlp;
552 SCIP_Bool exactsolve;
553 SCIP_Bool newselected;
554
556 assert(0 <= bestcand && bestcand < nlpcands);
557 assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
558
559 var = lpcandscopy[bestcand];
560 newselected = FALSE;
561
562 /* if there are new candidates variables, also try them */
563 if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion && branchruledata->lastcand > ncomplete )
564 {
565 SCIP_VAR** newlpcands;
566
567 counter = 0;
568 /* reset skipping arrays to zero */
569 BMSclearMemoryArray(branchruledata->skipdown, branchruledata->skipsize);
570 BMSclearMemoryArray(branchruledata->skipup, branchruledata->skipsize);
571
572 SCIP_CALL( SCIPallocBufferArray(scip, &newlpcands, ndiscvars) );
573
574 /* get new LP candidates with one fractional bound */
575 for( i = 0; i < ndiscvars; ++i)
576 {
578 continue;
579
580 assert(newlpcandsmin != NULL);
581 assert(newlpcandsmax != NULL);
582
583 if( SCIPisFeasIntegral(scip, newlpcandsmin[i]) != SCIPisFeasIntegral(scip, newlpcandsmax[i]) )
584 {
585 newlpcands[counter] = vars[i];
586
587 if( SCIPisFeasIntegral(scip, newlpcandsmin[i]) )
588 branchruledata->skipdown[counter] = TRUE;
589 if( SCIPisFeasIntegral(scip, newlpcandsmax[i]) )
590 branchruledata->skipup[counter] = TRUE;
591 assert(branchruledata->skipdown[counter] != branchruledata->skipup[counter]);
592
593 counter++;
594 }
595 }
596
597 /* when there are new candidates, also try these */
598 if( counter > 0 )
599 {
600 SCIP_Real newdown;
601 SCIP_Real newup;
602 SCIP_Real newscore;
603 int newcand;
604 SCIP_Bool newdownvalid;
605 SCIP_Bool newupvalid;
606 SCIP_Real newbound;
607
608 branchruledata->ntriedunions++;
609 newscore = -SCIPinfinity(scip);
610 SCIP_CALL( SCIPselectVarPseudoStrongBranching(scip, newlpcands, branchruledata->skipdown, branchruledata->skipup, counter, counter,
611 &newcand, &newdown, &newup, &newscore, &newdownvalid, &newupvalid, &newbound, result) );
612
614 {
615 SCIPfreeBufferArray(scip, &newlpcands);
616 goto TERMINATE;
617 }
618
619 if( newscore > bestscore )
620 {
621 bestcand = newcand;
622 var = newlpcands[newcand];
623 bestdown = newdown;
624 bestup = newup;
625 bestdownvalid = newdownvalid;
626 bestupvalid = newupvalid;
627 bestscore = newscore;
628 newselected = TRUE;
629 branchruledata->nusefulunions++;
630 }
631 }
632 /* free temporary array for new union candidates */
633 SCIPfreeBufferArray(scip, &newlpcands);
634 }
635
636 /* perform the branching */
637 if( !newselected )
638 {
639 SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s> (solval=%g, down=%g, up=%g, score=%g)\n",
640 counter, bestcand, SCIPvarGetName(var), lpcandssolcopy[bestcand], bestdown, bestup, bestscore);
641 }
642 else
643 {
644 SCIPdebugMsg(scip, " -> selected from %d new candidates, candidate %d: variable <%s> (down=%g, up=%g, score=%g)\n",
645 counter, bestcand, SCIPvarGetName(var), bestdown, bestup, bestscore);
646 }
647
649
650 SCIP_CALL( SCIPbranchVar(scip, var, &downchild, NULL, &upchild) );
651 assert(downchild != NULL);
652 assert(upchild != NULL);
653
654 /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
655 * for cutting off sub problems and improving lower bounds of children
656 */
657 exactsolve = SCIPisExact(scip);
658
659 /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
660 allcolsinlp = SCIPallColsInLP(scip);
661
662 /* update the lower bounds in the children */
663 if( allcolsinlp && !exactsolve )
664 {
665 SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
666 SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
667 }
668 SCIPdebugMsg(scip, " -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
669 SCIPdebugMsg(scip, " -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
670
672 }
673
674 TERMINATE:
675 if( branchruledata->useunion && !branchruledata->onlyF2 && SCIPgetDepth(scip) < branchruledata->maxdepthunion )
676 {
677 SCIPfreeBufferArray(scip, &newlpcandsmax);
678 SCIPfreeBufferArray(scip, &newlpcandsmin);
679 }
680 SCIPfreeBufferArray(scip, &lpcandscopy);
681 SCIPfreeBufferArray(scip, &lpcandssolcopy);
682 SCIPfreeBufferArray(scip, &lpcandsfraccopy);
683 SCIPfreeBufferArray(scip, &lpcandsmax);
684 SCIPfreeBufferArray(scip, &lpcandsmin);
685
686 /* if union usage was not successful enough, disable it */
687 if( branchruledata->useunion &&
688 branchruledata->ntriedunions > 10 &&
689 (SCIP_Real)branchruledata->nusefulunions / branchruledata->ntriedunions < branchruledata->minsuccessunion )
690 {
691 SCIPdebugMsg(scip, "Disabling union usage (not effective)\n");
692 branchruledata->useunion = FALSE;
693 }
694
695 return SCIP_OKAY; /*lint !e438*/
696}
697
698/*
699 * branching rule specific interface methods
700 */
701
702/** creates the cloud branching rule and includes it in SCIP */
704 SCIP* scip /**< SCIP data structure */
705 )
706{
707 SCIP_BRANCHRULEDATA* branchruledata;
708 SCIP_BRANCHRULE* branchrule;
709
710 /* create cloud branching rule data */
711 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
712 branchruledata->lastcand = 0;
713 branchruledata->skipsize = 0;
714 branchruledata->skipup = NULL;
715 branchruledata->skipdown = NULL;
716 SCIP_CALL( SCIPcreateClock(scip, &(branchruledata->cloudclock)) );
717
718 /* include branching rule */
719 branchrule = NULL;
722 assert(branchrule != NULL);
723
724 /* set non-fundamental callbacks via setter functions */
725 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyCloud) );
726 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeCloud) );
727 SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitCloud) );
728 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpCloud) );
729
730 /* add cloud branching rule parameters */
732 "branching/" BRANCHRULE_NAME "/usecloud",
733 "should a cloud of points be used?",
734 &branchruledata->usecloud, FALSE, DEFAULT_USECLOUD, NULL, NULL) );
736 "branching/" BRANCHRULE_NAME "/onlyF2",
737 "should only F2 be used?",
738 &branchruledata->onlyF2, FALSE, DEFAULT_ONLYF2, NULL, NULL) );
740 "branching/" BRANCHRULE_NAME "/useunion",
741 "should the union of candidates be used?",
742 &branchruledata->useunion, FALSE, DEFAULT_USEUNION, NULL, NULL) );
744 "branching/" BRANCHRULE_NAME "/maxpoints",
745 "maximum number of points for the cloud (-1 means no limit)",
746 &branchruledata->maxpoints, FALSE, DEFAULT_MAXPOINTS, -1, INT_MAX, NULL, NULL) );
748 "branching/" BRANCHRULE_NAME "/minsuccessrate",
749 "minimum success rate for the cloud",
750 &branchruledata->minsuccessrate, FALSE, DEFAULT_MINSUCCESSRATE, 0.0, 1.0, NULL, NULL) );
752 "branching/" BRANCHRULE_NAME "/minsuccessunion",
753 "minimum success rate for the union",
754 &branchruledata->minsuccessunion, FALSE, DEFAULT_MINSUCCESSUNION, 0.0, 1.0, NULL, NULL) );
756 "branching/" BRANCHRULE_NAME "/maxdepthunion",
757 "maximum depth for the union",
758 &branchruledata->maxdepthunion, FALSE, DEFAULT_MAXDEPTHUNION, 0, 65000, NULL, NULL) );
759
760 return SCIP_OKAY;
761}
#define BRANCHRULE_DESC
SCIP_RETCODE SCIPselectVarPseudoStrongBranching(SCIP *scip, SCIP_VAR **pseudocands, SCIP_Bool *skipdown, SCIP_Bool *skipup, int npseudocands, int npriopseudocands, int *bestpseudocand, SCIP_Real *bestdown, SCIP_Real *bestup, SCIP_Real *bestscore, SCIP_Bool *bestdownvalid, SCIP_Bool *bestupvalid, SCIP_Real *provedbound, SCIP_RESULT *result)
#define BRANCHRULE_PRIORITY
#define BRANCHRULE_NAME
#define BRANCHRULE_MAXDEPTH
#define BRANCHRULE_MAXBOUNDDIST
all variables full strong LP branching rule
#define DEFAULT_MAXPOINTS
#define DEFAULT_MINSUCCESSUNION
#define DEFAULT_USEUNION
#define DEFAULT_MAXDEPTHUNION
#define DEFAULT_ONLYF2
#define DEFAULT_MINSUCCESSRATE
#define DEFAULT_USECLOUD
cloud branching rule
full strong LP branching rule
#define NULL
Definition def.h:257
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL(x)
Definition def.h:364
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, 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 SCIPincludeBranchruleCloud(SCIP *scip)
int SCIPgetNIntVars(SCIP *scip)
Definition scip_prob.c:2340
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition scip_prob.c:2115
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition scip_prob.c:4354
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
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_param.c:83
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_param.c:139
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_param.c:57
SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition branch.c:2018
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition branch.c:1886
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition branch.c:1896
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
int SCIPgetNLPBranchCands(SCIP *scip)
SCIP_Bool SCIPisExact(SCIP *scip)
Definition scip_exact.c:193
SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition scip_lp.c:2384
SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition scip_lp.c:2416
SCIP_RETCODE SCIPchgRowLhsDive(SCIP *scip, SCIP_ROW *row, SCIP_Real newlhs)
Definition scip_lp.c:2487
SCIP_RETCODE SCIPchgRowRhsDive(SCIP *scip, SCIP_ROW *row, SCIP_Real newrhs)
Definition scip_lp.c:2520
SCIP_RETCODE SCIPstartDive(SCIP *scip)
Definition scip_lp.c:2206
SCIP_RETCODE SCIPchgVarObjDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition scip_lp.c:2343
SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition scip_lp.c:2643
SCIP_RETCODE SCIPendDive(SCIP *scip)
Definition scip_lp.c:2255
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition scip_lp.c:611
int SCIPgetNLPRows(SCIP *scip)
Definition scip_lp.c:632
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition scip_lp.c:174
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition scip_lp.c:655
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition scip_lp.c:673
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition tree.c:8533
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition lp.c:17686
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition lp.c:17696
SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:2068
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17706
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_sol.c:4114
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1890
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition scip_timing.c:76
SCIP_RETCODE SCIPresetClock(SCIP *scip, SCIP_CLOCK *clck)
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition var.c:19036
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:2608
return SCIP_OKAY
SCIPcreateSol(scip, &heurdata->sol, heur))
SCIP_Bool lperror
int nlprows
SCIP_ROW ** lprows
static SCIP_SOL * sol
SCIP_Real * lpcandssol
int nlpcands
SCIP_VAR ** lpcands
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIPlinkLPSol(scip, sol))
SCIP_VAR * var
int bestcand
SCIP_Real frac
SCIP_Real * lpcandsfrac
static SCIP_VAR ** vars
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
public methods for branching rules
public methods for LP management
public methods for message output
#define SCIPstatisticMessage
#define SCIPstatistic(x)
public methods for branch and bound tree
public methods for problem variables
public methods for branching rule plugins and branching
public methods for exact solving
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for solutions
public methods for querying solving statistics
public methods for timing
public methods for the branch-and-bound tree
public methods for SCIP variables
#define SCIP_DECL_BRANCHEXECLP(x)
#define SCIP_DECL_BRANCHINIT(x)
Definition type_branch.h:83
#define SCIP_DECL_BRANCHCOPY(x)
Definition type_branch.h:67
#define SCIP_DECL_BRANCHFREE(x)
Definition type_branch.h:75
struct SCIP_Branchrule SCIP_BRANCHRULE
Definition type_branch.h:56
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition type_branch.h:57
struct SCIP_Clock SCIP_CLOCK
Definition type_clock.h:49
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_LPSOLSTAT_OPTIMAL
Definition type_lp.h:44
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_REDUCEDDOM
Definition type_result.h:51
@ SCIP_CONSADDED
Definition type_result.h:52
@ SCIP_BRANCHED
Definition type_result.h:54
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65