SCIP

    Solving Constraint Integer Programs

    branch_gomory.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file branch_gomory.c
    26 * @ingroup DEFPLUGINS_BRANCH
    27 * @brief Gomory cut branching rule
    28 * @author Mark Turner
    29 *
    30 * The approach is based on the following papers.
    31 *
    32 * M. Turner, T. Berthold, M. Besancon, T. Koch@n
    33 * Branching via Cutting Plane Selection: Improving Hybrid Branching,@n
    34 * arXiv preprint arXiv:2306.06050
    35 *
    36 * The Gomory cut branching rule selects a candidate integer variable $j$ with a fractional solution value.
    37 * Each candidate variable must be a basic variable in the LP Tableau (if not then it would have to be at its bound
    38 * that is integer-valued)
    39 * This branching rule calculates the GMI cut for the aggregated row of the LP tableau associated with the
    40 * candidate variable.
    41 * The generated cut is then scored using a weighted sum rule.
    42 * The branching candidate whose cut is highest scoring is then selected.
    43 * For more details on the method, see:
    44 *
    45 * @par
    46 * Mark Turner, Timo Berthold, Mathieu Besançon, Thorsten Koch@n
    47 * Branching via Cutting Plane Selection: Improving Hybrid Branching@n
    48 * 2023@n
    49 */
    50
    51/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    52
    53#include "scip/branch_gomory.h"
    54#include "scip/pub_branch.h"
    55#include "scip/pub_var.h"
    56#include "scip/pub_lp.h"
    57#include "scip/pub_tree.h"
    58#include "scip/pub_message.h"
    59#include "scip/scip_branch.h"
    60#include "scip/scip_cut.h"
    61#include "scip/scip_mem.h"
    62#include "scip/scip_message.h"
    63#include "scip/scip_numerics.h"
    64#include "scip/scip_lp.h"
    65#include "scip/scip_tree.h"
    66#include "scip/scip_param.h"
    68
    69
    70#define BRANCHRULE_NAME "gomory"
    71#define BRANCHRULE_DESC "Gomory cut score branching"
    72#define BRANCHRULE_PRIORITY -1000
    73#define BRANCHRULE_MAXDEPTH -1
    74#define BRANCHRULE_MAXBOUNDDIST 1.0
    75
    76#define DEFAULT_MAXNCANDS -1 /**< maximum number of branching candidates to produce a cut for */
    77#define DEFAULT_EFFICACYWEIGHT 1.0 /**< the weight of efficacy in weighted sum cut scoring rule */
    78#define DEFAULT_OBJPARALLELWEIGHT 0.0 /**< the weight of objective parallelism in weighted sum scoring rule */
    79#define DEFAULT_INTSUPPORTWEIGHT 0.0 /**< the weight of integer support in weighted sum cut scoring rule */
    80#define DEFAULT_PERFORMRELPSCOST FALSE /**< if relpscost branching should be called without actual branching */
    81#define DEFAULT_USEWEAKERCUTS TRUE /**< use weaker cuts derived from the exact branching split */
    82
    83
    84/*
    85 * Data structures
    86 */
    87
    88/** branching rule data */
    89struct SCIP_BranchruleData
    90{
    91 int maxncands; /**< maximum number of variable candidates to produce cut for */
    92 SCIP_Real efficacyweight; /**< the weight of efficacy in weighted sum cut scoring rule */
    93 SCIP_Real objparallelweight; /**< the weight of objective parallelism in weighted sum scoring rule */
    94 SCIP_Real intsupportweight; /**< the weight of integer support in weighted sum cut scoring rule */
    95 SCIP_Bool performrelpscost; /**< if relpscost branching should be called without actual branching */
    96 SCIP_Bool useweakercuts; /**< use weaker cuts derived from the exact branching split */
    97};
    98
    99
    100/*
    101 * Local methods
    102 */
    103
    104/** Generate GMI cut: The GMI is given by
    105 * sum(f_j x_j , j in J_I s.t. f_j <= f_0) +
    106 * sum((1-f_j)*f_0/(1 - f_0) x_j, j in J_I s.t. f_j > f_0) +
    107 * sum(a_j x_j, , j in J_C s.t. a_j >= 0) -
    108 * sum(a_j*f_0/(1-f_0) x_j , j in J_C s.t. a_j < 0) >= f_0.
    109 * where J_I are the integer non-basic variables and J_C are the continuous.
    110 * f_0 is the fractional part of lpval
    111 * a_j is the j-th coefficient of the tableau row and f_j its fractional part
    112 * Note: we create -% <= -f_0 !!
    113 * Note: this formula is valid for a problem of the form Ax = b, x>= 0. Since we do not have
    114 * such problem structure in general, we have to (implicitly) transform whatever we are given
    115 * to that form. Specifically, non-basic variables at their lower bound are shifted so that the lower
    116 * bound is 0 and non-basic at their upper bound are complemented. */
    117static
    119 SCIP* scip, /**< SCIP data structure */
    120 int ncols, /**< Number of columns (original variables) in the LP */
    121 int nrows, /**< Number of rows (slack variables) in the LP */
    122 SCIP_COL** cols, /**< Column data of the LP */
    123 SCIP_ROW** rows, /**< Row data of the LP */
    124 const SCIP_Real* binvrow, /**< row of B^-1 for current basic variable */
    125 const SCIP_Real* binvarow, /**< row of B^-1A for current basic variable */
    126 const SCIP_Real* lpval, /**< value of variable at current LP solution */
    127 SCIP_Real* cutcoefs, /**< array to store cut coefficients */
    128 SCIP_Real* cutrhs, /**< pointer to store rhs of cut */
    129 SCIP_Bool useweakerscuts /**< use weakener cuts derived from the exact branching split */
    130 )
    131{
    132 SCIP_COL** rowcols;
    133 SCIP_COL* col;
    134 SCIP_ROW* row;
    135 SCIP_Real* rowvals;
    136 SCIP_BASESTAT basestat;
    137 SCIP_Real rowelem;
    138 SCIP_Real cutelem;
    139 SCIP_Real f0;
    140 SCIP_Real f0complementratio;
    141 SCIP_Real rowrhs;
    142 SCIP_Real rowlhs;
    143 SCIP_Real rowact;
    144 SCIP_Real rowrhsslack;
    145 int i;
    146 int c;
    147
    148 /* Clear the memory array of cut coefficients. It may store that of the last computed cut */
    149 BMSclearMemoryArray(cutcoefs, ncols);
    150
    151 /* compute fractionality f0 and f0/(1-f0) */
    152 f0 = SCIPfeasFrac(scip, *lpval);
    153 f0complementratio = f0 / (1.0 - f0);
    154
    155 /* The rhs of the cut is the fractional part of the LP solution of the basic variable */
    156 *cutrhs = -f0;
    157
    158 /* Generate cut coefficient for the original variables */
    159 for ( c = 0; c < ncols; c++ )
    160 {
    161 col = cols[c];
    162 assert( col != NULL );
    163
    164 basestat = SCIPcolGetBasisStatus(col);
    165 /* Get simplex tableau coefficient */
    166 if ( basestat == SCIP_BASESTAT_LOWER )
    167 {
    168 /* Take coefficient if nonbasic at lower bound */
    169 rowelem = binvarow[c];
    170 }
    171 else if ( basestat == SCIP_BASESTAT_UPPER )
    172 {
    173 /* Flip coefficient if nonbasic at upper bound: x --> u - x */
    174 rowelem = -binvarow[c];
    175 }
    176 else
    177 {
    178 /* Nonbasic free variable at zero or basic variable. Just skip it. */
    179 continue;
    180 }
    181
    182 /* Integer variables */
    183 if ( SCIPcolIsIntegral(col) && !useweakerscuts )
    184 {
    185 /* Warning: Because of numerics we can have cutelem < 0
    186 * In such a case it is very close to 0, so isZero will catch and we can ignore the coefficient */
    187 cutelem = SCIPfrac(scip, rowelem);
    188 if ( cutelem > f0 )
    189 {
    190 /* sum((1 - f_j) * f_0/(1 - f_0) x_j, j in J_I s.t. f_j > f_0 */
    191 cutelem = -((1.0 - cutelem) * f0complementratio);
    192 }
    193 else
    194 {
    195 /* sum(f_j * x_j, j in J_I s.t. f_j <= 0 */
    196 cutelem = -cutelem;
    197 }
    198 }
    199 /* Then continuous variables */
    200 else
    201 {
    202 if ( rowelem < 0 )
    203 {
    204 /* sum(a_j* f_0/(1 - f_0) x_j, j in J_C s.t. a_j < 0 */
    205 cutelem = rowelem * f0complementratio;
    206 }
    207 else
    208 {
    209 /* sum(a_j * x_j, j in J_C s.t. a_j >= 0 */
    210 cutelem = -rowelem;
    211 }
    212 }
    213
    214 /* Cut is defined when variables are in [0, infinity). Translate to general bounds. */
    215 if ( !SCIPisZero(scip, cutelem) )
    216 {
    217 if ( basestat == SCIP_BASESTAT_UPPER )
    218 {
    219 cutelem = -cutelem;
    220 *cutrhs += cutelem * SCIPcolGetUb(col);
    221 }
    222 else
    223 {
    224 *cutrhs += cutelem * SCIPcolGetLb(col);
    225 }
    226 /* Add coefficient to cut */
    227 cutcoefs[SCIPcolGetLPPos(col)] = cutelem;
    228 }
    229 }
    230
    231 /* generate cut coefficient for the slack variables. Skip the basic ones */
    232 for ( c = 0; c < nrows; c++ )
    233 {
    234 row = rows[c];
    235 assert( row != NULL );
    236 basestat = SCIProwGetBasisStatus(row);
    237
    238 /* Get the simplex tableau coefficient */
    239 if ( basestat == SCIP_BASESTAT_LOWER )
    240 {
    241 /* Take coefficient if nonbasic at lower bound */
    242 rowelem = binvrow[SCIProwGetLPPos(row)];
    243 /* If there is a >= constraint or ranged constraint at the lower bound, we have to flip the row element */
    244 if ( !SCIPisInfinity(scip, -SCIProwGetLhs(row)) )
    245 rowelem = -rowelem;
    246 }
    247 else if ( basestat == SCIP_BASESTAT_UPPER )
    248 {
    249 /* Take element if nonbasic at upper bound. Only non-positive slack variables can be nonbasic at upper,
    250 * therefore they should be flipped twice, meaning we can take the element directly */
    251 rowelem = binvrow[SCIProwGetLPPos(row)];
    252 }
    253 else
    254 {
    255 /* Nonbasic free variable at zero or basic variable. Free variable should not happen here. Just skip if free */
    256 assert( basestat == SCIP_BASESTAT_BASIC );
    257 continue;
    258 }
    259
    260 /* Integer rows */
    261 if ( SCIProwIsIntegral(row) && !SCIProwIsModifiable(row) && !useweakerscuts )
    262 {
    263 /* Warning: Because of numerics we can have cutelem < 0
    264 * In such a case it is very close to 0, so isZero will catch and we can ignore the coefficient */
    265 cutelem = SCIPfrac(scip, rowelem);
    266 if ( cutelem > f0 )
    267 {
    268 /* sum((1 - f_j) * f_0/(1 - f_0) x_j, j in J_I s.t. f_j > f_0 */
    269 cutelem = -((1.0 - cutelem) * f0complementratio);
    270 }
    271 else
    272 {
    273 /* sum(f_j * x_j, j in J_I s.t. f_j <= 0 */
    274 cutelem = -cutelem;
    275 }
    276 }
    277 /* Then continuous variables */
    278 else
    279 {
    280 if ( rowelem < 0 )
    281 {
    282 /* sum(a_j* f_0/(1 - f_0) x_j, j in J_C s.t. a_j < 0 */
    283 cutelem = rowelem * f0complementratio;
    284 }
    285 else
    286 {
    287 /* sum(a_j * x_j, j in J_C s.t. a_j >= 0 */
    288 cutelem = -rowelem;
    289 }
    290 }
    291
    292 /* Cut is defined in original variables, so we replace slack variables by their original definition */
    293 if ( !SCIPisZero(scip, cutelem) )
    294 {
    295 /* Coefficient is large enough so we keep it */
    296 rowlhs = SCIProwGetLhs(row);
    297 rowrhs = SCIProwGetRhs(row);
    298 assert( SCIPisLE(scip, rowlhs, rowrhs) );
    299 assert( !SCIPisInfinity(scip, rowlhs) || !SCIPisInfinity(scip, rowrhs) );
    300
    301 /* If the slack variable is fixed we can ignore this cut coefficient */
    302 if ( SCIPisFeasZero(scip, rowrhs - rowlhs) )
    303 continue;
    304
    305 /* Un-flip sack variable and adjust rhs if necessary.
    306 * Row at lower basis means the slack variable is at its upper bound.
    307 * Since SCIP adds +1 slacks, this can only happen when constraints have finite lhs */
    309 {
    310 assert( !SCIPisInfinity(scip, -rowlhs) );
    311 cutelem = -cutelem;
    312 }
    313
    314 rowcols = SCIProwGetCols(row);
    315 rowvals = SCIProwGetVals(row);
    316
    317 /* Eliminate slack variables. rowcols is sorted [columns in LP, columns not in LP] */
    318 for ( i = 0; i < SCIProwGetNLPNonz(row); i++ )
    319 cutcoefs[SCIPcolGetLPPos(rowcols[i])] -= cutelem * rowvals[i];
    320
    321 /* Modify the rhs */
    322 rowact = SCIPgetRowActivity(scip, row);
    323 rowrhsslack = rowrhs - rowact;
    324
    325 if ( SCIPisFeasZero(scip, rowrhsslack) )
    326 *cutrhs -= cutelem * (rowrhs - SCIProwGetConstant(row));
    327 else
    328 {
    329 assert( SCIPisFeasZero(scip, rowact - rowlhs) );
    330 *cutrhs -= cutelem * (rowlhs - SCIProwGetConstant(row));
    331 }
    332 }
    333 }
    334}
    335
    336
    337/*
    338 * Callback methods of branching rule
    339 */
    340
    341
    342/** copy method for branchrule plugins (called when SCIP copies plugins) */
    343static
    344SCIP_DECL_BRANCHCOPY(branchCopyGomory)
    345{ /*lint --e{715}*/
    346 assert(scip != NULL);
    347 assert(branchrule != NULL);
    348
    350
    351 /* call inclusion method of branchrule */
    353
    354 return SCIP_OKAY;
    355}
    356
    357
    358/** destructor of branching rule to free user data (called when SCIP is exiting) */
    359static
    360SCIP_DECL_BRANCHFREE(branchFreeGomory)
    361{ /*lint --e{715}*/
    362 SCIP_BRANCHRULEDATA* branchruledata;
    363
    364 /* free branching rule data */
    365 branchruledata = SCIPbranchruleGetData(branchrule);
    366 assert(branchruledata != NULL);
    367
    368 SCIPfreeBlockMemoryNull(scip, &branchruledata);
    369
    370 return SCIP_OKAY;
    371}
    372
    373
    374/** branching execution method for fractional LP solutions */
    375static
    376SCIP_DECL_BRANCHEXECLP(branchExeclpGomory)
    377{ /*lint --e{715}*/
    378 SCIP_BRANCHRULEDATA* branchruledata;
    379 SCIP_VAR** lpcands;
    380 SCIP_COL** cols;
    381 SCIP_ROW** rows;
    382 SCIP_Real* lpcandssol;
    383 SCIP_Real* lpcandsfrac;
    384 SCIP_Real* binvrow;
    385 SCIP_Real* binvarow;
    386 SCIP_Real* cutcoefs;
    387 SCIP_ROW* cut;
    388 SCIP_COL* col;
    389 int* basisind;
    390 int* basicvarpos2tableaurow;
    391 int* inds;
    392 const char* name;
    393 SCIP_Real cutrhs;
    394 SCIP_Real score;
    395 SCIP_Real bestscore;
    396 int nlpcands;
    397 int maxncands;
    398 int ncols;
    399 int nrows;
    400 int lppos;
    401 int ninds;
    402 int bestcand;
    403 int i;
    404 int j;
    405
    406 name = (char *) "test";
    407
    408 assert(branchrule != NULL);
    409 assert(scip != NULL);
    410 assert(result != NULL);
    411
    413
    414 SCIPdebugMsg(scip, "Execlp method of Gomory branching in node %" SCIP_LONGINT_FORMAT "\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
    415
    417 {
    418 *result = SCIP_DIDNOTRUN;
    419 SCIPdebugMsg(scip, "Could not apply Gomory branching, as the current LP was not solved to optimality.\n");
    420
    421 return SCIP_OKAY;
    422 }
    423
    424 /* Get branching candidates */
    425 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, NULL, &nlpcands, NULL) );
    426 assert(nlpcands > 0);
    427
    428 *result = SCIP_DIDNOTRUN;
    429
    430 /* Get branching rule data */
    431 branchruledata = SCIPbranchruleGetData(branchrule);
    432 assert(branchruledata != NULL);
    433
    434 /* Compute the reliability pseudo-cost branching scores for the candidates */
    435 if ( branchruledata->performrelpscost )
    436 {
    437 /* We do not branch using this rule, but if enabled do take all the bound and conflict inferences made */
    438 SCIP_CALL( SCIPexecRelpscostBranching(scip, lpcands, lpcandssol, lpcandsfrac, nlpcands, FALSE, result) );
    439 assert(*result == SCIP_DIDNOTRUN || *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM);
    440 }
    441
    442 /* Return SCIP_OKAY if relpscost has shown that this node can be cutoff or some variable domains have changed */
    443 if( *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM )
    444 {
    445 return SCIP_OKAY;
    446 }
    447
    448 /* Get the maximum number of LP branching candidates that we generate cuts for and score */
    449 if( branchruledata->maxncands >= 0 )
    450 {
    451 maxncands = MIN(nlpcands, branchruledata->maxncands);
    452 }
    453 else
    454 {
    455 maxncands = nlpcands;
    456 }
    457
    458 /* Get the Column and Row data */
    459 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    460 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    461
    462 /* Allocate temporary memory */
    463 SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, ncols) );
    464 SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
    465 SCIP_CALL( SCIPallocBufferArray(scip, &basicvarpos2tableaurow, ncols) );
    466 SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
    467 SCIP_CALL( SCIPallocBufferArray(scip, &binvarow, ncols) );
    468 SCIP_CALL( SCIPallocBufferArray(scip, &inds, nrows) );
    469
    470 /* Create basis indices mapping (from the column position to LP tableau rox index) */
    471 for( i = 0; i < ncols; ++i )
    472 {
    473 basicvarpos2tableaurow[i] = -1;
    474 }
    475 SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
    476 for( i = 0; i < nrows; ++i )
    477 {
    478 if( basisind[i] >= 0 )
    479 basicvarpos2tableaurow[basisind[i]] = i;
    480 }
    481
    482 /* Initialise the best candidate */
    483 bestcand = 0;
    484 bestscore = -SCIPinfinity(scip);
    485 ninds = -1;
    486
    487 /* Iterate over candidates and get best cut score */
    488 for( i = 0; i < maxncands; i++ )
    489 {
    490 /* Initialise the score of the cut */
    491 score = 0;
    492
    493 /* Get the LP position of the branching candidate */
    494 col = SCIPvarGetCol(lpcands[i]);
    495 lppos = SCIPcolGetLPPos(col);
    496 assert(lppos != -1);
    497
    498 /* get the row of B^-1 for this basic integer variable with fractional solution value */
    499 SCIP_CALL( SCIPgetLPBInvRow(scip, basicvarpos2tableaurow[lppos], binvrow, inds, &ninds) );
    500
    501 /* Get the Tableau row for this basic integer variable with fractional solution value */
    502 SCIP_CALL( SCIPgetLPBInvARow(scip, basicvarpos2tableaurow[lppos], binvrow, binvarow, inds, &ninds) );
    503
    504 /* Compute the GMI cut */
    505 getGMIFromRow(scip, ncols, nrows, cols, rows, binvrow, binvarow, &lpcandssol[i], cutcoefs,
    506 &cutrhs, branchruledata->useweakercuts);
    507
    508 /* Calculate the weighted sum score of measures */
    509 cut = NULL;
    511 for( j = 0; j < ncols; ++j )
    512 {
    513 if( !SCIPisZero(scip, cutcoefs[j]) )
    514 {
    515 SCIP_CALL( SCIPaddVarToRow(scip, cut, SCIPcolGetVar(cols[j]), cutcoefs[SCIPcolGetLPPos(cols[j])]) );
    516 }
    517 }
    518 assert( SCIPgetCutEfficacy(scip, NULL, cut) >= -SCIPfeastol(scip) );
    519 if ( branchruledata-> efficacyweight != 0 )
    520 score += branchruledata->efficacyweight * SCIPgetCutEfficacy(scip, NULL, cut);
    521 if ( branchruledata->objparallelweight != 0 )
    522 score += branchruledata->objparallelweight * SCIPgetRowObjParallelism(scip, cut);
    523 if ( branchruledata->intsupportweight != 0 )
    524 score += branchruledata->intsupportweight * SCIPgetRowNumIntCols(scip, cut) / (SCIP_Real) SCIProwGetNNonz(cut);
    525 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    526
    527 /* Replace the best cut if score is higher */
    528 if (score > bestscore)
    529 {
    530 bestscore = score;
    531 bestcand = i;
    532 }
    533 }
    534
    535 /* Free temporary memory */
    537 SCIPfreeBufferArray(scip, &binvrow);
    538 SCIPfreeBufferArray(scip, &binvarow);
    539 SCIPfreeBufferArray(scip, &basicvarpos2tableaurow);
    540 SCIPfreeBufferArray(scip, &basisind);
    541 SCIPfreeBufferArray(scip, &cutcoefs);
    542
    543 SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s> (frac=%g, factor=%g, score=%g)\n",
    544 nlpcands, bestcand, SCIPvarGetName(lpcands[bestcand]), lpcandsfrac[bestcand],
    545 SCIPvarGetBranchFactor(lpcands[bestcand]), bestscore);
    546
    547 /* Perform the branching */
    548 SCIP_CALL( SCIPbranchVar(scip, lpcands[bestcand], NULL, NULL, NULL) );
    549 *result = SCIP_BRANCHED;
    550
    551 return SCIP_OKAY;
    552}
    553
    554
    555/*
    556 * branching rule specific interface methods
    557 */
    558
    559/** creates the Gomory cut branching rule and includes it in SCIP */
    561 SCIP* scip /**< SCIP data structure */
    562 )
    563{
    564 SCIP_BRANCHRULEDATA* branchruledata;
    565 SCIP_BRANCHRULE* branchrule;
    566
    567 /* create branching rule data */
    568 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
    569
    570 /* include branching rule */
    573
    574 assert(branchrule != NULL);
    575
    576 /* set non-fundamental callbacks via specific setter functions*/
    577 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyGomory) );
    578 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeGomory) );
    579 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpGomory) );
    580
    581 /* Gomory cut branching rule parameters */
    582 SCIP_CALL( SCIPaddIntParam(scip,"branching/gomory/maxncands",
    583 "maximum amount of branching candidates to generate Gomory cuts for (-1: all candidates)",
    584 &branchruledata->maxncands, FALSE, DEFAULT_MAXNCANDS, -1, INT_MAX, NULL, NULL) );
    585 SCIP_CALL( SCIPaddRealParam(scip,"branching/gomory/efficacyweight",
    586 "weight of efficacy in the weighted sum cut scoring rule",
    587 &branchruledata->efficacyweight, FALSE, DEFAULT_EFFICACYWEIGHT, -1.0, 1.0, NULL, NULL) );
    588 SCIP_CALL( SCIPaddRealParam(scip,"branching/gomory/objparallelweight",
    589 "weight of objective parallelism in the weighted sum cut scoring rule",
    590 &branchruledata->objparallelweight, FALSE, DEFAULT_OBJPARALLELWEIGHT, -1.0, 1.0, NULL, NULL) );
    591 SCIP_CALL( SCIPaddRealParam(scip,"branching/gomory/intsupportweight",
    592 "weight of integer support in the weighted sum cut scoring rule",
    593 &branchruledata->intsupportweight, FALSE, DEFAULT_INTSUPPORTWEIGHT, -1.0, 1.0, NULL, NULL) );
    594 SCIP_CALL( SCIPaddBoolParam(scip,"branching/gomory/performrelpscost",
    595 "whether relpscost branching should be called without branching (used for bound inferences and conflicts)",
    596 &branchruledata->performrelpscost, FALSE, DEFAULT_PERFORMRELPSCOST, NULL, NULL) );
    597 SCIP_CALL( SCIPaddBoolParam(scip,"branching/gomory/useweakercuts",
    598 "use weaker cuts that are exactly derived from the branching split disjunction",
    599 &branchruledata->useweakercuts, FALSE, DEFAULT_USEWEAKERCUTS, NULL, NULL) );
    600
    601 return SCIP_OKAY;
    602}
    #define BRANCHRULE_DESC
    Definition: branch_gomory.c:71
    static SCIP_DECL_BRANCHFREE(branchFreeGomory)
    #define BRANCHRULE_PRIORITY
    Definition: branch_gomory.c:72
    #define DEFAULT_EFFICACYWEIGHT
    Definition: branch_gomory.c:77
    #define BRANCHRULE_NAME
    Definition: branch_gomory.c:70
    static SCIP_DECL_BRANCHCOPY(branchCopyGomory)
    static void getGMIFromRow(SCIP *scip, int ncols, int nrows, SCIP_COL **cols, SCIP_ROW **rows, const SCIP_Real *binvrow, const SCIP_Real *binvarow, const SCIP_Real *lpval, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, SCIP_Bool useweakerscuts)
    #define DEFAULT_OBJPARALLELWEIGHT
    Definition: branch_gomory.c:78
    static SCIP_DECL_BRANCHEXECLP(branchExeclpGomory)
    #define DEFAULT_PERFORMRELPSCOST
    Definition: branch_gomory.c:80
    #define BRANCHRULE_MAXDEPTH
    Definition: branch_gomory.c:73
    #define BRANCHRULE_MAXBOUNDDIST
    Definition: branch_gomory.c:74
    #define DEFAULT_USEWEAKERCUTS
    Definition: branch_gomory.c:81
    #define DEFAULT_INTSUPPORTWEIGHT
    Definition: branch_gomory.c:79
    #define DEFAULT_MAXNCANDS
    Definition: branch_gomory.c:76
    Gomory cut branching rule.
    reliable pseudo costs branching rule
    #define NULL
    Definition: def.h:257
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPexecRelpscostBranching(SCIP *scip, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsfrac, int nbranchcands, SCIP_Bool executebranching, SCIP_RESULT *result)
    SCIP_RETCODE SCIPincludeBranchruleGomory(SCIP *scip)
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
    Definition: scip_branch.c:256
    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 SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
    Definition: scip_branch.c:402
    SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
    Definition: scip_branch.c:1058
    int SCIPcolGetLPPos(SCIP_COL *col)
    Definition: lp.c:17487
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
    Definition: lp.c:17455
    SCIP_Real SCIPcolGetLb(SCIP_COL *col)
    Definition: lp.c:17346
    SCIP_Real SCIPcolGetUb(SCIP_COL *col)
    Definition: lp.c:17356
    SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
    Definition: lp.c:17414
    SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:94
    SCIP_RETCODE SCIPgetLPBasisInd(SCIP *scip, int *basisind)
    Definition: scip_lp.c:692
    SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
    Definition: scip_lp.c:477
    SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
    Definition: scip_lp.c:576
    SCIP_RETCODE SCIPgetLPBInvARow(SCIP *scip, int r, SCIP_Real *binvrow, SCIP_Real *coefs, int *inds, int *ninds)
    Definition: scip_lp.c:791
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    SCIP_RETCODE SCIPgetLPBInvRow(SCIP *scip, int r, SCIP_Real *coefs, int *inds, int *ninds)
    Definition: scip_lp.c:720
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemoryNull(scip, ptr)
    Definition: scip_mem.h:109
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8513
    SCIP_Bool SCIProwIsIntegral(SCIP_ROW *row)
    Definition: lp.c:17785
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
    Definition: lp.c:17805
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    int SCIProwGetNLPNonz(SCIP_ROW *row)
    Definition: lp.c:17621
    int SCIProwGetLPPos(SCIP_ROW *row)
    Definition: lp.c:17895
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:2068
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_RETCODE SCIPcreateEmptyRowUnspec(SCIP *scip, SCIP_ROW **row, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1458
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Real SCIPgetRowObjParallelism(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:2154
    int SCIPgetRowNumIntCols(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1832
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
    Definition: lp.c:17734
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Real SCIPfeasFrac(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeastol(SCIP *scip)
    SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23715
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
    Definition: var.c:24482
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for branching rules
    public methods for LP management
    public methods for message output
    public methods for branch and bound tree
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for cuts and aggregation rows
    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 the branch-and-bound tree
    struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
    Definition: type_branch.h:57
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_BASESTAT_BASIC
    Definition: type_lpi.h:92
    @ SCIP_BASESTAT_UPPER
    Definition: type_lpi.h:93
    @ SCIP_BASESTAT_LOWER
    Definition: type_lpi.h:91
    enum SCIP_BaseStat SCIP_BASESTAT
    Definition: type_lpi.h:96
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_BRANCHED
    Definition: type_result.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63