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_general.h"
53#include "scip/scip_lp.h"
54#include "scip/scip_mem.h"
55#include "scip/scip_message.h"
56#include "scip/scip_numerics.h"
57#include "scip/scip_param.h"
58#include "scip/scip_prob.h"
59#include "scip/scip_probing.h"
61#include "scip/scip_timing.h"
62#include "scip/scip_tree.h"
63#include "scip/scip_var.h"
64#include <string.h>
65
66#define BRANCHRULE_NAME "multaggr"
67#define BRANCHRULE_DESC "fullstrong branching on fractional and multi-aggregated variables"
68#define BRANCHRULE_PRIORITY 0
69#define BRANCHRULE_MAXDEPTH -1
70#define BRANCHRULE_MAXBOUNDDIST 1.0
71
72
73#define DEFAULT_REEVALAGE 0LL /**< number of intermediate LPs solved to trigger reevaluation of strong branching
74 * value for a variable that was already evaluated at the current node */
75#define DEFAULT_MAXPROPROUNDS 0 /**< maximum number of propagation rounds to be performed during multaggr branching
76 * before solving the LP (-1: no limit, -2: parameter settings) */
77#define DEFAULT_PROBINGBOUNDS TRUE /**< should valid bounds be identified in a probing-like fashion during multi-aggr
78 * branching (only with propagation)? */
79
80/*
81 * Data structures
82 */
83
84/** branching rule data */
85struct SCIP_BranchruleData
86{
87 SCIP_Longint reevalage; /**< number of intermediate LPs solved to trigger reevaluation of strong branching
88 * value for a variable that was already evaluated at the current node */
89 SCIP_Bool probingbounds; /**< should valid bounds be identified in a probing-like fashion during strong
90 * branching (only with propagation)? */
91 int lastcand; /**< last evaluated candidate of last branching rule execution */
92 int maxproprounds; /**< maximum number of propagation rounds to be performed during strong branching
93 * before solving the LP (-1: no limit, -2: parameter settings) */
94 int skipsize; /**< size of skipdown and skipup array */
95 SCIP_Bool* skipdown; /**< should be branching on down child be skipped? */
96 SCIP_Bool* skipup; /**< should be branching on up child be skipped? */
97#ifdef SCIP_STATISTIC
98 SCIP_CLOCK* clckstrongbr; /**< clock to store the time spent inside the strong branching function on fractional variables */
99 SCIP_CLOCK* clckmultaggrbr; /**< clock to store the time spent inside the strong branching function on multi-aggragated variables */
100 SCIP_Real* ratioggain; /**< for each occurence of a branching on a multi-aggregated variable we store the ratio of the gain that
101 * we would have obtained branching on the best fractional variable over the gain obtained
102 * branching on the current multi-aggregated variable */
103 SCIP_Real ameanratio; /**< arithmetic mean of the ratioggain array */
104 SCIP_Bool noupdate; /**< pointer to store if the probing LP has not been solved so we do not want to
105 * update statistics */
106 int firstmultaggrdepth; /**< depth of the first branching on a multi-aggregated variable */
107 int rundepth; /**< the run of the first multi-aggregated branching */
108 int nmultaggrbranch; /**< number of branchings on multi-aggregated variables */
109 int nfracbranch; /**< number of branchings on fractional variables */
110 int nEscore; /**< number of times that the bestscore over all multi-aggregated variables is equal to the best
111 * fractional variables score and thus we do not branch on the multi-aggregate variable */
112 int nmultaggrcutoff; /**< number of cutoffs detected during the probing mode on multi-aggregated variables */
113 int nmultaggrconsadd; /**< number of times that a probing constraint of a multi-aggregated variable has been
114 * added to the original problem */
115 int nfractcutoff; /**< number of cutoffs detected during strong branching on fractional variables */
116 int nfractconsadd; /**< number of times that during strong branching on fractional variables a constraint has been
117 * added to the original problem or a variables domain has been reduced */
118 int nmultaggrvars; /**< number of multi-aggregated variables in the problem of the last run */
119 int nrun; /**< number of restarts */
120 int size; /**< size of the provided array to store the ratio gain */
121 int nstrongbrcall; /**< number of times that the selectVarstrongBranching function has been called */
122 int nmultaggrbrcall; /**< number of times that the selectVarMultAggrBranching function has been called */
123 int totallpcands; /**< total number of observed lpcands over all selectVarstrongBranching function calls */
124 int totalmultaggrcands; /**< total number of observed multi-aggregregated candidates over all selectVarMultAggrBranching
125 * function calls */
126#endif
127};
128
129
130/*
131 * Local methods
132 */
133
134/* this function ensures that the allocated memory is enough to store statistics data */
135#ifdef SCIP_STATISTIC
136static
137SCIP_RETCODE ensureArraySize(
138 SCIP* scip, /**< original SCIP data structure */
139 SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
140 )
141{
142 assert(scip != NULL);
143 assert(branchruledata != NULL);
144 assert(branchruledata->ratioggain != NULL);
145 assert(branchruledata->nmultaggrbranch >= 0);
146 assert(branchruledata->size >= 0);
147
148 /* check whether the size of the array is big enough; reallocate memory if needed */
149 if( branchruledata->nmultaggrbranch + 1 > branchruledata->size )
150 {
151 int newsize = SCIPcalcMemGrowSize(scip, branchruledata->nmultaggrbranch + 1);
152 assert(newsize >= branchruledata->nmultaggrbranch + 1);
153 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->ratioggain, branchruledata->size, newsize) );
154 branchruledata->size = newsize;
155 }
156 return SCIP_OKAY;
157}
158#endif
159
160/* this function gives us the best candidate for branching among the multi-aggregated variables of the problem
161 * and the best fractional integer variable already selected by strong branching
162*/
163static
165 SCIP* scip, /**< original SCIP data structure */
166 SCIP_VAR** bestcand, /**< the best candidate variable selected by strong branching */
167 SCIP_Real* bestscore, /**< score of the best branching candidate */
168 SCIP_Real* bestsol, /**< solution value of the best branching candidate */
169 SCIP_Real* bestdown, /**< objective value of the down node when branching on bestcand */
170 SCIP_Real* bestup, /**< objective value of the up node when branching on bestcand */
171 SCIP_Bool* bestdownvalid, /**< is bestdown a valid dual bound for the down branch? */
172 SCIP_Bool* bestupvalid, /**< is bestup a valid dual bound for the up branch? */
173 SCIP_Real* provedbound, /**< proved dual bound for the current subtree */
174 SCIP_Real* estimatedown, /**< pointer to store the down child nodes estimate */
175 SCIP_Real* estimateup, /**< pointer to store the up child nodes estimate */
176#ifdef SCIP_STATISTIC
177 SCIP_Real* bestmultaggrscore, /**< pointer to store the multi aggregated score */
178#endif
179 SCIP_RESULT* result /**< pointer to store results of branching */
180 )
181{
182 SCIP_VAR** fixvars;
183 SCIP_CONS* probingconsdown;
184 SCIP_CONS* probingconsup;
185 SCIP_NODE* node;
186 SCIP_Real* fixvarssols;
187 SCIP_Real fixvarssol;
188 SCIP_Real lpobjval;
189 SCIP_Bool exactsolve;
190 SCIP_Bool allcolsinlp;
191 SCIP_Bool downnodeinf = FALSE;
192 SCIP_Bool startprobing = TRUE;
193 SCIP_Bool endprobing = FALSE;
194 int nfixvars;
195 int i;
196 int j;
197 int k;
198
199 /* import branchrule data for statistics */
200#ifdef SCIP_STATISTIC
201 SCIP_BRANCHRULE* branchrule;
202 SCIP_BRANCHRULEDATA* branchruledata;
203
205 assert(branchrule != NULL);
206
207 branchruledata = SCIPbranchruleGetData(branchrule);
208 assert(branchruledata != NULL);
209#endif
210
211 assert(scip != NULL);
212 assert(bestcand != NULL);
213 assert(bestscore != NULL);
214
215 /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
216 * for cutting off sub problems and improving lower bounds of children
217 */
218 exactsolve = SCIPisExactSolve(scip);
219
220 /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
221 allcolsinlp = SCIPallColsInLP(scip);
222
223 /* get fixed variables */
224 fixvars = SCIPgetFixedVars(scip);
225 nfixvars = SCIPgetNFixedVars(scip);
226 SCIPdebugMsg(scip, " fractional variable: <%s> with value: %f is selected by strong branching\n", SCIPvarGetName(*bestcand), *bestsol);
227
228 /* check if we would exceed the depth limit */
230 {
231 SCIPdebugMsg(scip, "cannot perform probing in selectVarMultAggrBranching, depth limit reached.\n");
232 *result = SCIP_DIDNOTRUN;
233 return SCIP_OKAY;
234 }
235
236 if( nfixvars != 0 )
237 {
238 assert(fixvars != NULL);
239
240 SCIP_CALL( SCIPallocBufferArray(scip, &fixvarssols, nfixvars) );
241 lpobjval = SCIPgetLPObjval(scip);
242
243 /* store the values of the fixed variables at the current optimal solution */
244 for( i = 0; i < nfixvars; i++ )
245 {
246 assert(fixvars[i] != NULL);
247 fixvarssols[i] = SCIPvarGetLPSol(fixvars[i]);
248 }
249
250 for( i = 0; i < nfixvars; i++ )
251 {
252 assert(fixvars[i] != NULL);
253
254 /* only integer and binary multi-aggregated variables are potential branching candidates */
255 if( SCIPvarGetStatus(fixvars[i]) == SCIP_VARSTATUS_MULTAGGR && (SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_INTEGER ||
256 SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_BINARY) )
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 SCIPstatistic(int j = 0);
646
647 /* initialize branching rule data */
648 branchruledata = SCIPbranchruleGetData(branchrule);
649 assert(branchruledata != NULL);
650 assert((branchruledata->skipdown != NULL) == (branchruledata->skipup != NULL));
651
652 /* print statistics */
655 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Multi-aggregated branching stats : \n");
656 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrvars : %d (last run)\n",
657 branchruledata->nmultaggrvars);
658 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " firstmultaggrbranchdepth : %d (in run %d)\n",
659 branchruledata->firstmultaggrdepth,
660 branchruledata->rundepth);
661 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrbranch : %d (tot %d)\n",
662 branchruledata->nmultaggrbranch, branchruledata->nmultaggrbranch + branchruledata->nfracbranch);
663 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrcutoff : %d\n", branchruledata->nmultaggrcutoff);
664 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrconsadd : %d\n", branchruledata->nmultaggrconsadd);
665 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nfractcutoff : %d\n", branchruledata->nfractcutoff);
666 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nfractconsadd : %d\n", branchruledata->nfractconsadd);
667 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nEscore : %d\n", branchruledata->nEscore);
668
669 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Branching Time : \n");
670 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nstrongbrcall : %d\n", branchruledata->nstrongbrcall);
671 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalstrongbrtime : %g\n",
672 SCIPgetClockTime(scip, branchruledata->clckstrongbr));
673 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totallpcands : %d\n", branchruledata->totallpcands);
674
675 if( branchruledata->totallpcands != 0 )
676 {
677 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimestrongbr : %g\n",
678 SCIPgetClockTime(scip, branchruledata->clckstrongbr) / branchruledata->totallpcands);
679 }
680 else
681 {
682 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimestrongbr : %s\n", "--");
683 }
684
685 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " nmultaggrbrcall : %d\n", branchruledata->nmultaggrbrcall);
686 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalmultaggrbrtime : %g\n",
687 SCIPgetClockTime(scip, branchruledata->clckmultaggrbr));
688 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " totalmultaggrcands : %d\n", branchruledata->totalmultaggrcands);
689
690 if( branchruledata->totalmultaggrcands != 0 )
691 {
692 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimemultaggrbr : %g\n",
693 SCIPgetClockTime(scip, branchruledata->clckmultaggrbr) / branchruledata->totalmultaggrcands);
694 }
695 else
696 {
697 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " averagetimemultaggrbr : %s\n", "--");
698 }
699
700 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Ratioggain :\n");
701 if( branchruledata->nmultaggrbranch != 0 )
702 {
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 {
801 if( SCIPvarGetStatus(fixvars[i]) == SCIP_VARSTATUS_MULTAGGR && (SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_INTEGER ||
802 SCIPvarGetType(fixvars[i]) == SCIP_VARTYPE_BINARY) )
803 {
804 branchruledata->nmultaggrvars += 1;
805 }
806 }
807 }
808 branchruledata->nrun = SCIPgetNRuns(scip);
809 }
810 )
811
812 /* get all branching candidates */
813 SCIP_CALL( SCIPgetLPBranchCands(scip, &tmplpcands, &tmplpcandssol, &tmplpcandsfrac, &nlpcands, &npriolpcands, NULL) );
814 assert(nlpcands > 0);
815 assert(npriolpcands > 0);
816
817 /* copy LP branching candidates and solution values, because they will be updated w.r.t. the strong branching LP
818 * solution
819 */
820 SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcands, tmplpcands, nlpcands) );
821 SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandssol, tmplpcandssol, nlpcands) );
822 SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandsfrac, tmplpcandsfrac, nlpcands) );
823
824 if( branchruledata->skipdown == NULL )
825 {
826 assert(branchruledata->skipup == NULL);
827
828 branchruledata->skipsize = SCIPgetNVars(scip);
829 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipdown, branchruledata->skipsize) );
830 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipup, branchruledata->skipsize) );
831 BMSclearMemoryArray(branchruledata->skipdown, branchruledata->skipsize);
832 BMSclearMemoryArray(branchruledata->skipup, branchruledata->skipsize);
833 }
834
835 /* start the clock to get the time spent inside the function */
837 SCIP_CALL( SCIPstartClock(scip, branchruledata->clckstrongbr) );
838 );
839
840 /* compute strong branching among the array of fractional variables in order to get the best one */
841 SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcands, lpcandssol, lpcandsfrac, branchruledata->skipdown,
842 branchruledata->skipup, nlpcands, npriolpcands, nlpcands, &branchruledata->lastcand,
843 branchruledata->maxproprounds, branchruledata->probingbounds, TRUE,
844 &bestcandpos, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
845
847 SCIP_CALL( SCIPstopClock(scip, branchruledata->clckstrongbr) );
848 branchruledata->totallpcands += SCIPgetNLPBranchCands(scip);
849 branchruledata->nstrongbrcall += 1;
850 )
851
852 if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED )
853 {
854 SCIP_VAR* bestcand = lpcands[bestcandpos];
855 SCIP_Real bestsol = lpcandssol[bestcandpos];
856 SCIPstatistic( SCIP_Real bestmultaggrscore = -SCIPinfinity(scip); )
857
859 SCIP_Real fdowngain = 0.0;
860 SCIP_Real fupgain = 0.0;
861
862 /* reoptimize is set to true if strong branching on fractional variables did not explicitly evaluate the objective
863 * values of the probing child nodes and thus we do not have updated information
864 */
865 if( SCIPisLT(scip, SCIPgetVarStrongbranchLPAge(scip, bestcand), branchruledata->reevalage)
866 || branchruledata->maxproprounds != 0 )
868
869 /* store values needed for the ratioggain statistic */
870 if( !reoptimize )
871 {
872 SCIP_Real fdown;
873 SCIP_Real fup;
874
875 fdown = MAX(bestdown, lpobjval);
876 fup = MAX(bestup, lpobjval);
877 fdowngain = fdown - lpobjval;
878 fupgain = fup - lpobjval;
879 }
880
881 /* start and then stop the clock to get the time spent inside the function */
882 SCIP_CALL( SCIPstartClock(scip, branchruledata->clckmultaggrbr) );
883 )
884
885 /* compute strong branching among the multi-aggregated variables and the best fractional variable */
886#ifdef SCIP_STATISTIC
887 SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
888 &estimatedown, &estimateup, &bestmultaggrscore, result) );
889#else
890 SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
891 &estimatedown, &estimateup, result) );
892#endif
894 SCIP_CALL( SCIPstopClock(scip, branchruledata->clckmultaggrbr) );
895 branchruledata->nmultaggrbrcall += 1;
896 )
897
898 if( *result != SCIP_CUTOFF && *result != SCIP_CONSADDED )
899 {
901 if( !(branchruledata->noupdate) )
902 {
903 if( SCIPisEQ(scip, bestmultaggrscore, bestscore) )
904 branchruledata->nEscore += 1;
905 }
906 )
907
908 assert(bestcand != NULL);
909 SCIPdebugMsg(scip, "BRANCHING MODE:\n");
910
911 /* perform branching on the best found candidate */
913 {
914 SCIP_CONS* multaggrconsdown;
915 SCIP_CONS* multaggrconsup;
916
918 if( !(branchruledata->noupdate) )
919 {
920 branchruledata->nmultaggrbranch += 1;
921
922 if( !reoptimize )
923 {
924 SCIP_Real gfractbranch;
925 SCIP_Real gmultaggrbranch;
926 SCIP_Real downgain;
927 SCIP_Real upgain;
928 SCIP_Real down;
929 SCIP_Real up;
930 int nmultaggrbranch;
931
932 down = MAX(bestdown, lpobjval);
933 up = MAX(bestup, lpobjval);
934 downgain = down - lpobjval;
935 upgain = up - lpobjval;
936
937 SCIP_CALL( ensureArraySize(scip, branchruledata) );
938
939 gfractbranch= sqrt(MAX(fdowngain,1e-06) * MAX(fupgain,1e-06));
940 gmultaggrbranch = sqrt(MAX(downgain,1e-06) * MAX(upgain,1e-06));
941
942 nmultaggrbranch = branchruledata->nmultaggrbranch;
943
944 if( gmultaggrbranch == 0.0 )
945 {
946 branchruledata->ratioggain[nmultaggrbranch - 1] = 1;
947 }
948 else
949 {
950 branchruledata->ratioggain[nmultaggrbranch - 1] = gfractbranch / gmultaggrbranch;
951 }
952 }
953 }
954 )
955
956 /* create the multi-aggregated constraints rounded up and down */
957 SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsdown, "consdown", SCIPvarGetMultaggrNVars(bestcand),
959 SCIPfeasFloor(scip, bestsol) - SCIPvarGetMultaggrConstant(bestcand),
961
962 SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsup, "consup", SCIPvarGetMultaggrNVars(bestcand),
966
967 /* create the child nodes */
968 SCIP_CALL( SCIPcreateChild(scip, &downchild, 1.0, estimatedown) );
969 SCIPdebugMsg(scip, " down node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(downchild), SCIPnodeGetEstimate(downchild));
970
971 SCIP_CALL( SCIPcreateChild(scip, &upchild, 1.0, estimateup) );
972 SCIPdebugMsg(scip, " up node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(upchild), SCIPnodeGetEstimate(upchild));
973
974 assert(downchild != NULL);
975 assert(upchild != NULL);
976
977 SCIP_CALL( SCIPaddConsNode(scip, downchild, multaggrconsdown, NULL) );
978 SCIP_CALL( SCIPaddConsNode(scip, upchild, multaggrconsup, NULL) );
979
980#ifdef PRINTNODECONS
981 SCIPdebugMsg(scip, "branching at node %lld\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
982
983 SCIPdebugMsg(scip, "created child node %lld with constraint:\n", SCIPnodeGetNumber(downchild));
984 SCIP_CALL( SCIPprintCons(scip, multaggrconsdown, NULL) );
985 SCIPinfoMessage(scip, NULL, "\n");
986
987 SCIPdebugMsg(scip, "created child node %lld with constraint:\n", SCIPnodeGetNumber(upchild));
988 SCIP_CALL( SCIPprintCons(scip, multaggrconsup, NULL) );
989 SCIPinfoMessage(scip, NULL, "\n");
990#endif
991
992 /* relase constraints */
993 SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsdown) );
994 SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsup) );
995
996 SCIPdebugMsg(scip, "BRANCHED on multi-aggregated variable <%s>\n", SCIPvarGetName(bestcand));
997
998 *result = SCIP_BRANCHED;
999 }
1000 else
1001 {
1003 if( !(branchruledata->noupdate) )
1004 branchruledata->nfracbranch += 1
1005 );
1006
1007 assert(*result == SCIP_DIDNOTRUN);
1008 assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
1009
1010 SCIP_CALL( SCIPbranchVarVal(scip, bestcand, bestsol, &downchild, NULL, &upchild) );
1011
1012 assert(downchild != NULL);
1013 assert(upchild != NULL);
1014
1015 SCIPdebugMsg(scip, "BRANCHED on fractional variable <%s>\n", SCIPvarGetName(bestcand));
1016
1017 *result = SCIP_BRANCHED;
1018 }
1019
1020 /* update the lower bounds in the children; we must not do this if columns are missing in the LP
1021 * (e.g., because we are doing branch-and-price) or the problem should be solved exactly
1022 */
1024 {
1025 SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
1026 SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
1027 }
1028 SCIPdebugMsg(scip, " -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
1029 SCIPdebugMsg(scip, " -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
1030 }
1031 }
1032 else
1033 {
1034 SCIPdebugMsg(scip, "strong branching breaks\n" );
1035
1037 if( *result == SCIP_CUTOFF )
1038 {
1039 branchruledata->nfractcutoff += 1;
1040 }
1041 else
1042 {
1043 branchruledata->nfractconsadd += 1;
1044 }
1045 )
1046 }
1047
1048 SCIPfreeBufferArray(scip, &lpcandsfrac);
1049 SCIPfreeBufferArray(scip, &lpcandssol);
1050 SCIPfreeBufferArray(scip, &lpcands);
1051
1052 SCIP_CALL( SCIPsetLongintParam(scip, "branching/fullstrong/reevalage", oldreevalage) );
1053
1054 return SCIP_OKAY;
1055}
1056
1057/*
1058 * branching rule specific interface methods
1059 */
1060
1061/** creates the multi-aggregated branching rule and includes it in SCIP */
1063 SCIP* scip /**< SCIP data structure */
1064 )
1065{
1066 SCIP_BRANCHRULEDATA* branchruledata;
1067 SCIP_BRANCHRULE* branchrule;
1068
1069 /* create multaggr branching rule data */
1070 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
1071 branchruledata->lastcand = 0;
1072 branchruledata->skipsize = 0;
1073 branchruledata->skipup = NULL;
1074 branchruledata->skipdown = NULL;
1075 SCIPstatistic(branchruledata->ratioggain = NULL);
1076
1077 /* include branching rule */
1079 BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
1080
1081 assert(branchrule != NULL);
1082
1083 /* set non fundamental callbacks via setter functions */
1084 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyMultAggr) );
1085 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeMultAggr) );
1086 SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitMultAggr) );
1087 SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitMultAggr) );
1088 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpMultAggr) );
1089
1090 /* multi-aggregated branching rule parameters */
1092 "branching/multaggr/reevalage",
1093 "number of intermediate LPs solved to trigger reevaluation of strong branching value for a variable that was already evaluated at the current node",
1094 &branchruledata->reevalage, TRUE, DEFAULT_REEVALAGE, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1096 "branching/multaggr/maxproprounds",
1097 "maximum number of propagation rounds to be performed during multaggr branching before solving the LP (-1: no limit, -2: parameter settings)",
1098 &branchruledata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
1100 "branching/multaggr/probingbounds",
1101 "should valid bounds be identified in a probing-like fashion during multaggr branching (only with propagation)?",
1102 &branchruledata->probingbounds, TRUE, DEFAULT_PROBINGBOUNDS, NULL, NULL) );
1103
1104 return SCIP_OKAY;
1105}
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:266
#define SCIP_Longint
Definition: def.h:157
#define SCIP_MAXTREEDEPTH
Definition: def.h:315
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_LONGINT_MAX
Definition: def.h:158
#define SCIP_CALL(x)
Definition: def.h:373
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)
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip_general.c:621
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
int SCIPgetNFixedVars(SCIP *scip)
Definition: scip_prob.c:2309
SCIP_VAR ** SCIPgetFixedVars(SCIP *scip)
Definition: scip_prob.c:2266
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition: scip_prob.c:3762
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3324
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:201
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip_branch.c:249
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip_branch.c:297
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip_branch.c:153
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:116
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1971
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1849
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip_branch.c:169
SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
Definition: scip_branch.c:185
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1859
SCIP_RETCODE SCIPbranchVarVal(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip_branch.c:1126
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip_branch.c:395
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:428
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip_branch.c:1017
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: scip_branch.c:849
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2537
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1174
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:168
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip_lp.c:649
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip_lp.c:247
#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:7535
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7515
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:7545
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip_probing.c:225
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip_probing.c:119
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip_probing.c:165
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip_probing.c:820
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip_probing.c:260
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:17902
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17558
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17604
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17439
SCIP_Longint SCIPgetVarStrongbranchLPAge(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:4317
SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
Definition: scip_var.c:8937
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18472
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17878
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17866
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17890
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:1504
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
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:51
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition: type_lp.h:42
@ SCIP_LPSOLSTAT_TIMELIMIT
Definition: type_lp.h:48
@ SCIP_LPSOLSTAT_UNBOUNDEDRAY
Definition: type_lp.h:45
@ SCIP_LPSOLSTAT_INFEASIBLE
Definition: type_lp.h:44
@ SCIP_LPSOLSTAT_OBJLIMIT
Definition: type_lp.h:46
@ SCIP_LPSOLSTAT_ITERLIMIT
Definition: type_lp.h:47
@ SCIP_VERBLEVEL_NORMAL
Definition: type_message.h:55
@ 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_VARTYPE_INTEGER
Definition: type_var.h:63
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54