Scippy

SCIP

Solving Constraint Integer Programs

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