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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24/**@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
    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
    577
    578 /* call inclusion method of branchrule */
    580
    581 return SCIP_OKAY;
    582}
    583
    584/** destructor of branching rule to free user data (called when SCIP is exiting) */
    585static
    586SCIP_DECL_BRANCHFREE(branchFreeMultAggr)
    587{ /*lint --e{715}*/
    588 SCIP_BRANCHRULEDATA* branchruledata;
    589
    590 /* free branching rule data */
    591 branchruledata = SCIPbranchruleGetData(branchrule);
    592 assert(branchruledata != NULL);
    593
    594 SCIPstatistic(SCIPfreeBlockMemoryArrayNull(scip , &branchruledata->ratioggain, branchruledata->size));
    595 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->skipdown, branchruledata->skipsize);
    596 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->skipup, branchruledata->skipsize);
    597
    598 SCIPfreeBlockMemory(scip, &branchruledata);
    599 SCIPbranchruleSetData(branchrule, NULL);
    600
    601 return SCIP_OKAY;
    602}
    603
    604/** initialization method of branching rule (called after problem was transformed) */
    605static
    606SCIP_DECL_BRANCHINIT(branchInitMultAggr)
    607{ /*lint --e{715}*/
    608 SCIP_BRANCHRULEDATA* branchruledata;
    609
    610 branchruledata = SCIPbranchruleGetData(branchrule);
    611 assert(branchruledata != NULL);
    612
    613 branchruledata->lastcand = 0;
    615 branchruledata->firstmultaggrdepth = 0;
    616 branchruledata->nmultaggrbranch = 0;
    617 branchruledata->nfracbranch = 0;
    618 branchruledata->nEscore = 0;
    619 branchruledata->nmultaggrcutoff = 0;
    620 branchruledata->nmultaggrconsadd = 0;
    621 branchruledata->nfractcutoff = 0;
    622 branchruledata->nfractconsadd = 0;
    623 branchruledata->nrun = 0;
    624 branchruledata->size = 100;
    625 branchruledata->ameanratio = 0.0;
    626 branchruledata->noupdate = FALSE;
    627 branchruledata->clckstrongbr = NULL;
    628 branchruledata->clckmultaggrbr = NULL;
    629 branchruledata->nstrongbrcall = 0;
    630 branchruledata->nmultaggrbrcall = 0;
    631 branchruledata->totalmultaggrcands = 0;
    632 branchruledata->totallpcands = 0;
    633 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->ratioggain, branchruledata->size) );
    634 BMSclearMemoryArray(branchruledata->ratioggain, branchruledata->size);
    635 SCIP_CALL( SCIPcreateClock(scip, &branchruledata->clckstrongbr) );
    636 SCIP_CALL( SCIPcreateClock(scip, &branchruledata->clckmultaggrbr) );
    637 )
    638 return SCIP_OKAY;
    639}
    640
    641/** deinitialization method of branching rule (called before transformed problem is freed) */
    642static
    643SCIP_DECL_BRANCHEXIT(branchExitMultAggr)
    644{ /*lint --e{715}*/
    645 SCIP_BRANCHRULEDATA* branchruledata;
    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 int j;
    704 for( j = 0; j < branchruledata->nmultaggrbranch; j++ )
    705 {
    706 branchruledata->ameanratio += branchruledata->ratioggain[j];
    707 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " %g", branchruledata->ratioggain[j]);
    708 }
    709
    711 branchruledata->ameanratio = branchruledata->ameanratio / branchruledata->nmultaggrbranch;
    713 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " ameanratio : %4.2f\n", branchruledata->ameanratio);
    714 }
    715 else
    716 {
    717 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " ameanratio : %s\n", "--");
    718 }
    719
    721
    722 /* free arrays */
    723 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->ratioggain, branchruledata->size);
    724 SCIP_CALL( SCIPfreeClock(scip, &branchruledata->clckstrongbr) );
    725 SCIP_CALL( SCIPfreeClock(scip, &branchruledata->clckmultaggrbr) );
    726 )
    727 if( branchruledata->skipdown != NULL )
    728 {
    729 SCIPfreeBlockMemoryArray(scip, &branchruledata->skipup, branchruledata->skipsize);
    730 SCIPfreeBlockMemoryArray(scip, &branchruledata->skipdown, branchruledata->skipsize);
    731 branchruledata->skipdown = NULL;
    732 branchruledata->skipup = NULL;
    733 branchruledata->skipsize = 0;
    734 }
    735 return SCIP_OKAY;
    736}
    737
    738/** branching execution method for fractional LP solutions */
    739static
    740SCIP_DECL_BRANCHEXECLP(branchExeclpMultAggr)
    741{ /*lint --e{715}*/
    742 SCIP_BRANCHRULEDATA* branchruledata;
    743 SCIP_VAR** lpcands;
    744 SCIP_VAR** tmplpcands;
    745 SCIP_Real* lpcandssol;
    746 SCIP_Real* lpcandsfrac;
    747 SCIP_Real* tmplpcandssol;
    748 SCIP_Real* tmplpcandsfrac;
    749 SCIP_NODE* downchild;
    750 SCIP_NODE* upchild;
    751 SCIP_Real bestup;
    752 SCIP_Real bestdown;
    753 SCIP_Real bestscore;
    754 SCIP_Real provedbound;
    755 SCIP_Real estimatedown = 0.0;
    756 SCIP_Real estimateup = 0.0;
    757 SCIP_Bool bestdownvalid;
    758 SCIP_Bool bestupvalid;
    759 SCIP_Longint oldreevalage;
    760 int bestcandpos;
    761 int nlpcands;
    762 int npriolpcands;
    764 SCIP_Real lpobjval;
    766 )
    767
    768 assert(branchrule != NULL);
    769 assert(scip != NULL);
    770 assert(result != NULL);
    771
    773
    774 SCIPdebugMsg(scip, "Execlp method of mult-aggreg branching\n ");
    775 *result = SCIP_DIDNOTRUN;
    776
    777 /* get branching rule data */
    778 branchruledata = SCIPbranchruleGetData(branchrule);
    779 assert(branchruledata != NULL);
    780
    781 SCIP_CALL( SCIPgetLongintParam(scip, "branching/fullstrong/reevalage", &oldreevalage) );
    782 SCIP_CALL( SCIPsetLongintParam(scip, "branching/fullstrong/reevalage", branchruledata->reevalage) );
    783
    784 /* get the lpobjval and the number of multi aggregated variables of the problem as a statistic counter */
    787 lpobjval = SCIPgetLPObjval(scip);
    788
    789 if( SCIPgetNRuns(scip) != branchruledata->nrun )
    790 {
    791 SCIP_VAR** fixvars;
    792 int nfixvars;
    793 int i;
    794
    795 branchruledata->nmultaggrvars = 0;
    796 fixvars = SCIPgetFixedVars(scip);
    797 nfixvars = SCIPgetNFixedVars(scip);
    798
    799 if( nfixvars != 0 )
    800 {
    801 for( i = 0; i < nfixvars; i++ )
    802 {
    804 {
    805 branchruledata->nmultaggrvars += 1;
    806 }
    807 }
    808 }
    809 branchruledata->nrun = SCIPgetNRuns(scip);
    810 }
    811 )
    812
    813 /* get all branching candidates */
    814 SCIP_CALL( SCIPgetLPBranchCands(scip, &tmplpcands, &tmplpcandssol, &tmplpcandsfrac, &nlpcands, &npriolpcands, NULL) );
    815 assert(nlpcands > 0);
    816 assert(npriolpcands > 0);
    817
    818 /* copy LP branching candidates and solution values, because they will be updated w.r.t. the strong branching LP
    819 * solution
    820 */
    821 SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcands, tmplpcands, nlpcands) );
    822 SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandssol, tmplpcandssol, nlpcands) );
    823 SCIP_CALL( SCIPduplicateBufferArray(scip, &lpcandsfrac, tmplpcandsfrac, nlpcands) );
    824
    825 if( branchruledata->skipdown == NULL )
    826 {
    827 assert(branchruledata->skipup == NULL);
    828
    829 branchruledata->skipsize = SCIPgetNVars(scip);
    830 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipdown, branchruledata->skipsize) );
    831 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->skipup, branchruledata->skipsize) );
    832 BMSclearMemoryArray(branchruledata->skipdown, branchruledata->skipsize);
    833 BMSclearMemoryArray(branchruledata->skipup, branchruledata->skipsize);
    834 }
    835
    836 /* start the clock to get the time spent inside the function */
    838 SCIP_CALL( SCIPstartClock(scip, branchruledata->clckstrongbr) );
    839 );
    840
    841 /* compute strong branching among the array of fractional variables in order to get the best one */
    842 SCIP_CALL( SCIPselectVarStrongBranching(scip, lpcands, lpcandssol, lpcandsfrac, branchruledata->skipdown,
    843 branchruledata->skipup, nlpcands, npriolpcands, nlpcands, &branchruledata->lastcand,
    844 branchruledata->maxproprounds, branchruledata->probingbounds, TRUE,
    845 &bestcandpos, &bestdown, &bestup, &bestscore, &bestdownvalid, &bestupvalid, &provedbound, result) );
    846
    848 SCIP_CALL( SCIPstopClock(scip, branchruledata->clckstrongbr) );
    849 branchruledata->totallpcands += SCIPgetNLPBranchCands(scip);
    850 branchruledata->nstrongbrcall += 1;
    851 )
    852
    853 if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED )
    854 {
    855 SCIP_VAR* bestcand = lpcands[bestcandpos];
    856 SCIP_Real bestsol = lpcandssol[bestcandpos];
    857 SCIPstatistic( SCIP_Real bestmultaggrscore = -SCIPinfinity(scip); )
    858
    860 SCIP_Real fdowngain = 0.0;
    861 SCIP_Real fupgain = 0.0;
    862
    863 /* reoptimize is set to true if strong branching on fractional variables did not explicitly evaluate the objective
    864 * values of the probing child nodes and thus we do not have updated information
    865 */
    866 if( SCIPisLT(scip, SCIPgetVarStrongbranchLPAge(scip, bestcand), branchruledata->reevalage)
    867 || branchruledata->maxproprounds != 0 )
    869
    870 /* store values needed for the ratioggain statistic */
    871 if( !reoptimize )
    872 {
    873 SCIP_Real fdown;
    874 SCIP_Real fup;
    875
    876 fdown = MAX(bestdown, lpobjval);
    877 fup = MAX(bestup, lpobjval);
    878 fdowngain = fdown - lpobjval;
    879 fupgain = fup - lpobjval;
    880 }
    881
    882 /* start and then stop the clock to get the time spent inside the function */
    883 SCIP_CALL( SCIPstartClock(scip, branchruledata->clckmultaggrbr) );
    884 )
    885
    886 /* compute strong branching among the multi-aggregated variables and the best fractional variable */
    887#ifdef SCIP_STATISTIC
    888 SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
    889 &estimatedown, &estimateup, &bestmultaggrscore, result) );
    890#else
    891 SCIP_CALL( selectVarMultAggrBranching(scip, &bestcand, &bestscore, &bestsol, &bestdown, &bestup, &bestdownvalid, &bestupvalid, &provedbound,
    892 &estimatedown, &estimateup, result) );
    893#endif
    895 SCIP_CALL( SCIPstopClock(scip, branchruledata->clckmultaggrbr) );
    896 branchruledata->nmultaggrbrcall += 1;
    897 )
    898
    899 if( *result != SCIP_CUTOFF && *result != SCIP_CONSADDED )
    900 {
    902 if( !(branchruledata->noupdate) )
    903 {
    904 if( SCIPisEQ(scip, bestmultaggrscore, bestscore) )
    905 branchruledata->nEscore += 1;
    906 }
    907 )
    908
    909 assert(bestcand != NULL);
    910 SCIPdebugMsg(scip, "BRANCHING MODE:\n");
    911
    912 /* perform branching on the best found candidate */
    914 {
    915 SCIP_CONS* multaggrconsdown;
    916 SCIP_CONS* multaggrconsup;
    917
    919 if( !(branchruledata->noupdate) )
    920 {
    921 branchruledata->nmultaggrbranch += 1;
    922
    923 if( !reoptimize )
    924 {
    925 SCIP_Real gfractbranch;
    926 SCIP_Real gmultaggrbranch;
    927 SCIP_Real downgain;
    928 SCIP_Real upgain;
    929 SCIP_Real down;
    930 SCIP_Real up;
    931 int nmultaggrbranch;
    932
    933 down = MAX(bestdown, lpobjval);
    934 up = MAX(bestup, lpobjval);
    935 downgain = down - lpobjval;
    936 upgain = up - lpobjval;
    937
    938 SCIP_CALL( ensureArraySize(scip, branchruledata) );
    939
    940 gfractbranch= sqrt(MAX(fdowngain,1e-06) * MAX(fupgain,1e-06));
    941 gmultaggrbranch = sqrt(MAX(downgain,1e-06) * MAX(upgain,1e-06));
    942
    943 nmultaggrbranch = branchruledata->nmultaggrbranch;
    944
    945 if( gmultaggrbranch == 0.0 )
    946 {
    947 branchruledata->ratioggain[nmultaggrbranch - 1] = 1;
    948 }
    949 else
    950 {
    951 branchruledata->ratioggain[nmultaggrbranch - 1] = gfractbranch / gmultaggrbranch;
    952 }
    953 }
    954 }
    955 )
    956
    957 /* create the multi-aggregated constraints rounded up and down */
    958 SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsdown, "consdown", SCIPvarGetMultaggrNVars(bestcand),
    960 SCIPfeasFloor(scip, bestsol) - SCIPvarGetMultaggrConstant(bestcand),
    962
    963 SCIP_CALL( SCIPcreateConsLinear(scip, &multaggrconsup, "consup", SCIPvarGetMultaggrNVars(bestcand),
    967
    968 /* create the child nodes */
    969 SCIP_CALL( SCIPcreateChild(scip, &downchild, 1.0, estimatedown) );
    970 SCIPdebugMsg(scip, " down node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(downchild), SCIPnodeGetEstimate(downchild));
    971
    972 SCIP_CALL( SCIPcreateChild(scip, &upchild, 1.0, estimateup) );
    973 SCIPdebugMsg(scip, " up node: lowerbound %f estimate %f\n", SCIPnodeGetLowerbound(upchild), SCIPnodeGetEstimate(upchild));
    974
    975 assert(downchild != NULL);
    976 assert(upchild != NULL);
    977
    978 SCIP_CALL( SCIPaddConsNode(scip, downchild, multaggrconsdown, NULL) );
    979 SCIP_CALL( SCIPaddConsNode(scip, upchild, multaggrconsup, NULL) );
    980
    981#ifdef PRINTNODECONS
    982 SCIPdebugMsg(scip, "branching at node %lld\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
    983
    984 SCIPdebugMsg(scip, "created child node %lld with constraint:\n", SCIPnodeGetNumber(downchild));
    985 SCIP_CALL( SCIPprintCons(scip, multaggrconsdown, NULL) );
    986 SCIPinfoMessage(scip, NULL, "\n");
    987
    988 SCIPdebugMsg(scip, "created child node %lld with constraint:\n", SCIPnodeGetNumber(upchild));
    989 SCIP_CALL( SCIPprintCons(scip, multaggrconsup, NULL) );
    990 SCIPinfoMessage(scip, NULL, "\n");
    991#endif
    992
    993 /* relase constraints */
    994 SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsdown) );
    995 SCIP_CALL( SCIPreleaseCons(scip, &multaggrconsup) );
    996
    997 SCIPdebugMsg(scip, "BRANCHED on multi-aggregated variable <%s>\n", SCIPvarGetName(bestcand));
    998
    999 *result = SCIP_BRANCHED;
    1000 }
    1001 else
    1002 {
    1004 if( !(branchruledata->noupdate) )
    1005 branchruledata->nfracbranch += 1
    1006 );
    1007
    1008 assert(*result == SCIP_DIDNOTRUN);
    1009 assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
    1010
    1011 SCIP_CALL( SCIPbranchVarVal(scip, bestcand, bestsol, &downchild, NULL, &upchild) );
    1012
    1013 assert(downchild != NULL);
    1014 assert(upchild != NULL);
    1015
    1016 SCIPdebugMsg(scip, "BRANCHED on fractional variable <%s>\n", SCIPvarGetName(bestcand));
    1017
    1018 *result = SCIP_BRANCHED;
    1019 }
    1020
    1021 /* update the lower bounds in the children; we must not do this if columns are missing in the LP
    1022 * (e.g., because we are doing branch-and-price) or the problem should be solved exactly
    1023 */
    1025 {
    1026 SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, bestdownvalid ? MAX(bestdown, provedbound) : provedbound) );
    1027 SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, bestupvalid ? MAX(bestup, provedbound) : provedbound) );
    1028 }
    1029 SCIPdebugMsg(scip, " -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
    1030 SCIPdebugMsg(scip, " -> up child's lowerbound: %g\n", SCIPnodeGetLowerbound(upchild));
    1031 }
    1032 }
    1033 else
    1034 {
    1035 SCIPdebugMsg(scip, "strong branching breaks\n" );
    1036
    1038 if( *result == SCIP_CUTOFF )
    1039 {
    1040 branchruledata->nfractcutoff += 1;
    1041 }
    1042 else
    1043 {
    1044 branchruledata->nfractconsadd += 1;
    1045 }
    1046 )
    1047 }
    1048
    1049 SCIPfreeBufferArray(scip, &lpcandsfrac);
    1050 SCIPfreeBufferArray(scip, &lpcandssol);
    1051 SCIPfreeBufferArray(scip, &lpcands);
    1052
    1053 SCIP_CALL( SCIPsetLongintParam(scip, "branching/fullstrong/reevalage", oldreevalage) );
    1054
    1055 return SCIP_OKAY;
    1056}
    1057
    1058/*
    1059 * branching rule specific interface methods
    1060 */
    1061
    1062/** creates the multi-aggregated branching rule and includes it in SCIP */
    1064 SCIP* scip /**< SCIP data structure */
    1065 )
    1066{
    1067 SCIP_BRANCHRULEDATA* branchruledata;
    1068 SCIP_BRANCHRULE* branchrule;
    1069
    1070 /* create multaggr branching rule data */
    1071 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
    1072 branchruledata->lastcand = 0;
    1073 branchruledata->skipsize = 0;
    1074 branchruledata->skipup = NULL;
    1075 branchruledata->skipdown = NULL;
    1076 SCIPstatistic(branchruledata->ratioggain = NULL);
    1077
    1078 /* include branching rule */
    1080 BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
    1081
    1082 assert(branchrule != NULL);
    1083
    1084 /* set non fundamental callbacks via setter functions */
    1085 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyMultAggr) );
    1086 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeMultAggr) );
    1087 SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitMultAggr) );
    1088 SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitMultAggr) );
    1089 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpMultAggr) );
    1090
    1091 /* multi-aggregated branching rule parameters */
    1093 "branching/multaggr/reevalage",
    1094 "number of intermediate LPs solved to trigger reevaluation of strong branching value for a variable that was already evaluated at the current node",
    1095 &branchruledata->reevalage, TRUE, DEFAULT_REEVALAGE, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    1097 "branching/multaggr/maxproprounds",
    1098 "maximum number of propagation rounds to be performed during multaggr branching before solving the LP (-1: no limit, -2: parameter settings)",
    1099 &branchruledata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
    1101 "branching/multaggr/probingbounds",
    1102 "should valid bounds be identified in a probing-like fashion during multaggr branching (only with propagation)?",
    1103 &branchruledata->probingbounds, TRUE, DEFAULT_PROBINGBOUNDS, NULL, NULL) );
    1104
    1105 return SCIP_OKAY;
    1106}
    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:257
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:306
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPselectVarStrongBranching(SCIP *scip, SCIP_VAR **lpcands, SCIP_Real *lpcandssol, SCIP_Real *lpcandsfrac, SCIP_Bool *skipdown, SCIP_Bool *skipup, int nlpcands, int npriolpcands, int ncomplete, int *start, int maxproprounds, SCIP_Bool probingbounds, SCIP_Bool forcestrongbranch, int *bestcand, SCIP_Real *bestdown, SCIP_Real *bestup, SCIP_Real *bestscore, SCIP_Bool *bestdownvalid, SCIP_Bool *bestupvalid, SCIP_Real *provedbound, SCIP_RESULT *result)
    SCIP_RETCODE 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:8393
    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:8533
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8513
    SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
    Definition: tree.c:8553
    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:23875
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23538
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    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:24696
    SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
    Definition: var.c:23838
    int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
    Definition: var.c:23826
    SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
    Definition: var.c:23850
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56