Scippy

    SCIP

    Solving Constraint Integer Programs

    cutsel_ensemble.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
    25/**@file cutsel_ensemble.c
    26 * @ingroup DEFPLUGINS_CUTSEL
    27 * @brief ensemble cut selector
    28 * @author Mark Turner
    29 *
    30 * @todo separator hard limit on density is inappropriate for MINLP. Need to relax hard limit in case of all cuts dense
    31 * @todo penalising via parallelism is overly costly if many cuts. Hash cuts before and find appropriate groups?
    32 */
    33
    34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    35
    36#include <assert.h>
    37
    38#include "scip/scip_cutsel.h"
    39#include "scip/scip_cut.h"
    40#include "scip/scip_lp.h"
    43
    44
    45#define CUTSEL_NAME "ensemble"
    46#define CUTSEL_DESC "weighted sum of many terms with optional filtering and penalties"
    47#define CUTSEL_PRIORITY 7000
    48
    49#define RANDSEED 0x5EED
    50
    51#define DEFAULT_MINSCORE 0.0 /**< minimum score s.t. a cut can be selected */
    52#define DEFAULT_EFFICACYWEIGHT 0.75 /**< weight of normed-efficacy in score calculation */
    53#define DEFAULT_DIRCUTOFFDISTWEIGHT 0.0 /**< weight of normed-directed cutoff distance in score calculation */
    54#define DEFAULT_OBJPARALWEIGHT 0.25 /**< weight of objective parallelism in score calculation */
    55#define DEFAULT_INTSUPPORTWEIGHT 0.45 /**< weight of integral support in cut score calculation */
    56#define DEFAULT_EXPIMPROVWEIGHT 0.1 /**< weight of normed-expected improvement in cut score calculation */
    57#define DEFAULT_PSCOSTWEIGHT 0.75 /**< weight of normalised pseudo-costs in cut score calculation */
    58#define DEFAULT_NLOCKSWEIGHT 0.25 /**< weight of normalised number of locks in cut score calculation */
    59#define DEFAULT_MAXSPARSITYBONUS 0.5 /**< score given to a cut with complete sparsity */
    60#define DEFAULT_SPARSITYENDBONUS 0.2 /**< the density at which a cut no longer receives additional score */
    61#define DEFAULT_GOODNUMERICBONUS 0.0 /**< bonus provided for good numerics */
    62#define DEFAULT_MAXCOEFRATIOBONUS 10000 /**< maximum coefficient ratio of cut for which numeric bonus is given */
    63#define DEFAULT_PENALISELOCKS TRUE /**< whether having less locks should be rewarded instead of more */
    64#define DEFAULT_PENALISEOBJPARAL TRUE /**< whether objective parallelism should be penalised not rewarded */
    65#define DEFAULT_FILTERPARALCUTS FALSE /**< should cuts be filtered so no two parallel cuts are added */
    66#define DEFAULT_MAXPARAL 0.95 /**< threshold for when two cuts are considered parallel to each other */
    67#define DEFAULT_PENALISEPARALCUTS TRUE /**< should two parallel cuts be penalised instead of outright filtered */
    68#define DEFAULT_PARALPENALTY 0.25 /**< penalty for weaker of two parallel cuts if penalising parallel cuts */
    69#define DEFAULT_FILTERDENSECUTS TRUE /**< should cuts over a given density threshold be filtered */
    70#define DEFAULT_MAXCUTDENSITY 0.425 /**< max allowed cut density if filtering dense cuts */
    71#define DEFAULT_MAXNONZEROROOTROUND 4.5 /**< max nonzeros per round (root). Gets multiplied by num LP cols */
    72#define DEFAULT_MAXNONZEROTREEROUND 9.5 /**< max nonzeros per round (tree). Gets multiplied by num LP cols */
    73#define DEFAULT_MAXCUTS 200 /**< maximum number of cuts that can be considered by this cut selector */
    74#define DEFAULT_MAXNUMVARS 50000 /**< maximum number of variables that a problem can have while calling this cut selector */
    75
    76/*
    77 * Data structures
    78 */
    79
    80/** cut selector data */
    81struct SCIP_CutselData
    82{
    83 SCIP_RANDNUMGEN* randnumgen; /**< random generator for tie-breaking */
    84 SCIP_Real minscore; /**< minimum score for a cut to be added to the LP */
    85 SCIP_Real objparalweight; /**< weight of objective parallelism in cut score calculation */
    86 SCIP_Real efficacyweight; /**< weight of normed-efficacy in cut score calculation */
    87 SCIP_Real dircutoffdistweight;/**< weight of normed-directed cutoff distance in cut score calculation */
    88 SCIP_Real expimprovweight; /**< weight of normed-expected improvement in cut score calculation */
    89 SCIP_Real intsupportweight; /**< weight of integral support in cut score calculation */
    90 SCIP_Real pscostweight; /**< weight of normalised pseudo-costs in cut score calculation */
    91 SCIP_Real locksweight; /**< weight of normed-number of active locks in cut score calculation */
    92 SCIP_Real maxsparsitybonus; /**< weight of maximum sparsity reward in cut score calculation */
    93 SCIP_Real goodnumericsbonus; /**< weight of good numeric bonus in cut score calculation */
    94 SCIP_Real endsparsitybonus; /**< max sparsity value for which a bonus is applied */
    95 SCIP_Real maxparal; /**< threshold for when two cuts are considered parallel to each other */
    96 SCIP_Real paralpenalty; /**< penalty for weaker of two parallel cuts if penalising parallel cuts */
    97 SCIP_Real maxcutdensity; /**< max allowed cut density if filtering dense cuts */
    98 SCIP_Real maxnonzerorootround;/**< max nonzeros per round (root). Gets multiplied by num LP cols */
    99 SCIP_Real maxnonzerotreeround;/**< max nonzeros per round (tree). Gets multiplied by num LP cols */
    100 SCIP_Bool filterparalcuts; /**< should cuts be filtered so no two parallel cuts are added */
    101 SCIP_Bool penaliseparalcuts; /**< should two parallel cuts be penalised instead of outright filtered */
    102 SCIP_Bool filterdensecuts; /**< should cuts over a given density threshold be filtered */
    103 SCIP_Bool penaliselocks; /**< whether the number of locks should be penalised instead of rewarded */
    104 SCIP_Bool penaliseobjparal; /**< whether objective parallelism should be penalised */
    105 int maxcoefratiobonus; /**< maximum coefficient ratio for which numeric bonus is applied */
    106 int maxcuts; /**< maximum number of cuts that can be considered by this cut selector */
    107 int maxnumvars; /**< maximum number of variables that a problem can have while calling this cut selector */
    108};
    109
    110
    111/*
    112 * Local methods
    113 */
    114
    115/** returns the maximum score of cuts; if scores is not NULL, then stores the individual score of each cut in scores */
    116static
    118 SCIP* scip, /**< SCIP data structure */
    119 SCIP_ROW** cuts, /**< array with cuts to score */
    120 SCIP_CUTSELDATA* cutseldata, /**< cut selector data */
    121 SCIP_Real* scores, /**< array to store the score of cuts or NULL */
    122 SCIP_Bool root, /**< whether we are at the root node or not */
    123 int ncuts /**< number of cuts in cuts array */
    124 )
    125{
    126 SCIP_Real* effs;
    127 SCIP_Real* dcds;
    128 SCIP_Real* exps;
    129 SCIP_Real* cutdensities;
    130 SCIP_Real* cutlocks;
    131 SCIP_Real* pscosts;
    132 SCIP_SOL* sol;
    133 SCIP_Real maxdcd = 0.0;
    134 SCIP_Real maxeff = 0.0;
    135 SCIP_Real maxexp = 0.0;
    136 SCIP_Real maxpscost = 0.0;
    137 SCIP_Real maxlocks = 0.0;
    138 SCIP_Real ncols;
    139
    140 /* Get the solution that we use for directed cutoff distance calculations. Get the number of columns too */
    141 sol = SCIPgetBestSol(scip);
    142 ncols = SCIPgetNLPCols(scip);
    143
    144 /* Initialise all array information that we're going to use for scoring */
    145 SCIP_CALL( SCIPallocBufferArray(scip, &effs, ncuts) );
    146 SCIP_CALL( SCIPallocBufferArray(scip, &dcds, ncuts) );
    147 SCIP_CALL( SCIPallocBufferArray(scip, &exps, ncuts) );
    148 SCIP_CALL( SCIPallocBufferArray(scip, &cutdensities, ncuts) );
    149 SCIP_CALL( SCIPallocBufferArray(scip, &cutlocks, ncuts) );
    150 SCIP_CALL( SCIPallocBufferArray(scip, &pscosts, ncuts) );
    151
    152 /* Populate the number of cut locks, the pseudo-cost scores, and the cut densities */
    153 for (int i = 0; i < ncuts; ++i )
    154 {
    155 SCIP_COL** cols;
    156 SCIP_Real* cutvals;
    157 SCIP_Real sqrcutnorm;
    158 SCIP_Real ncutcols;
    159 SCIP_Real cutalpha;
    160
    161 cols = SCIProwGetCols(cuts[i]);
    162 cutvals = SCIProwGetVals(cuts[i]);
    163 sqrcutnorm = MAX(SCIPsumepsilon(scip), SQR(SCIProwGetNorm(cuts[i]))); /*lint !e666*/
    164 cutalpha = -SCIPgetRowFeasibility(scip, cuts[i]) / sqrcutnorm;
    165 ncutcols = SCIProwGetNNonz(cuts[i]);
    166 cutdensities[i] = ncutcols / ncols;
    167 cutlocks[i] = 0;
    168 pscosts[i] = 0;
    169
    170 for ( int j = 0; j < (int) ncutcols; ++j )
    171 {
    172 SCIP_VAR* colvar;
    173 SCIP_Real colval;
    174 SCIP_Real l1dist;
    175
    176 colval = SCIPcolGetPrimsol(cols[j]);
    177 colvar = SCIPcolGetVar(cols[j]);
    178 /* Get the number of active locks feature in the cut */
    179 if( ! SCIPisInfinity(scip, SCIProwGetRhs(cuts[i])) && cutvals[j] > 0.0 )
    180 cutlocks[i] += SCIPvarGetNLocksUp(colvar);
    181 if( ! SCIPisInfinity(scip, -SCIProwGetLhs(cuts[i])) && cutvals[j] < 0.0 )
    182 cutlocks[i] += SCIPvarGetNLocksUp(colvar);
    183 if( ! SCIPisInfinity(scip, SCIProwGetRhs(cuts[i])) && cutvals[j] < 0.0 )
    184 cutlocks[i] += SCIPvarGetNLocksDown(colvar);
    185 if( ! SCIPisInfinity(scip, -SCIProwGetLhs(cuts[i])) && cutvals[j] > 0.0 )
    186 cutlocks[i] += SCIPvarGetNLocksDown(colvar);
    187
    188 /* Get the L1 distance from the projection onto the cut and the LP solution in the variable direction */
    189 l1dist = ABS(colval - (cutalpha * cutvals[j]));
    190 pscosts[i] += SCIPgetVarPseudocostScore(scip, colvar, colval) * l1dist;
    191 }
    192 cutlocks[i] = cutlocks[i] / ncutcols; /*lint !e414*/
    193
    194 if( cutlocks[i] > maxlocks )
    195 maxlocks = cutlocks[i];
    196
    197 if( pscosts[i] > maxpscost )
    198 maxpscost = pscosts[i];
    199 }
    200
    201 /* account for the case where maxlocks or maxpscost is 0 */
    202 maxpscost = MAX(maxpscost, SCIPepsilon(scip)); /*lint !e666*/
    203 maxlocks = MAX(maxlocks, 1);
    204
    205 for ( int i = 0; i < ncuts; i++ )
    206 {
    207 cutlocks[i] = cutlocks[i] / maxlocks; /*lint !e414*/
    208 /* if locks are penalized, we complement the corresponding score */
    209 if( cutseldata->penaliselocks )
    210 cutlocks[i] = 1 - cutlocks[i];
    211 pscosts[i] = pscosts[i] / maxpscost; /*lint !e414*/
    212 }
    213
    214 /* Get the arrays / maximums of directed cutoff distance, efficacy, and expected improvement values. */
    215 if ( sol != NULL && root )
    216 {
    217 for ( int i = 0; i < ncuts; i++ )
    218 {
    219 dcds[i] = SCIPgetCutLPSolCutoffDistance(scip, sol, cuts[i]);
    220 maxdcd = MAX(maxdcd, dcds[i]);
    221 }
    222 }
    223
    224 for ( int i = 0; i < ncuts; ++i )
    225 {
    226 effs[i] = SCIPgetCutEfficacy(scip, NULL, cuts[i]);
    227 exps[i] = effs[i] * SCIPgetRowObjParallelism(scip, cuts[i]);
    228 maxeff = MAX(maxeff, effs[i]);
    229 maxexp = MAX(maxexp, exps[i]);
    230 }
    231
    232 /* Now score the cuts */
    233 for ( int i = 0; i < ncuts; ++i )
    234 {
    235 SCIP_Real score;
    236 SCIP_Real scaleddcd;
    237 SCIP_Real scaledeff;
    238 SCIP_Real scaledexp;
    239 SCIP_Real objparallelism;
    240 SCIP_Real intsupport;
    242 SCIP_Real dynamism;
    243 SCIP_Real mincutval;
    244 SCIP_Real maxcutval;
    245 SCIP_Real pscost;
    246 SCIP_Real cutlock;
    247
    248 /* Get the integer support */
    249 intsupport = SCIPgetRowNumIntCols(scip, cuts[i]) / (SCIP_Real) SCIProwGetNNonz(cuts[i]);
    250 intsupport *= cutseldata->intsupportweight;
    251
    252 /* Get the objective parallelism and orthogonality */
    253 if( ! cutseldata->penaliseobjparal )
    254 objparallelism = cutseldata->objparalweight * SCIPgetRowObjParallelism(scip, cuts[i]);
    255 else
    256 objparallelism = cutseldata->objparalweight * (1 - SCIPgetRowObjParallelism(scip, cuts[i]));
    257
    258 /* Get the density score */
    259 density = (cutseldata->maxsparsitybonus / cutseldata->endsparsitybonus) * -1 * cutdensities[i];
    260 density += cutseldata->maxsparsitybonus;
    261 density = MAX(density, 0.0);
    262
    263 /* Get the normalised pseudo-cost and number of locks score */
    264 if( root )
    265 pscost = 0.0;
    266 else
    267 pscost = cutseldata->pscostweight * pscosts[i];
    268 cutlock = cutseldata->locksweight * cutlocks[i];
    269
    270 /* Get the dynamism (good numerics) score */
    271 maxcutval = SCIPgetRowMaxCoef(scip, cuts[i]);
    272 mincutval = SCIPgetRowMinCoef(scip, cuts[i]);
    273 mincutval = mincutval > 0.0 ? mincutval : 1.0;
    274 dynamism = cutseldata->maxcoefratiobonus >= maxcutval / mincutval ? cutseldata->goodnumericsbonus : 0.0;
    275
    276 /* Get the dcd / eff / exp score */
    277 if ( sol != NULL && root )
    278 {
    279 if ( SCIPisSumLE(scip, dcds[i], 0.0))
    280 scaleddcd = 0.0;
    281 else
    282 scaleddcd = cutseldata->dircutoffdistweight * SQR(LOG1P(dcds[i]) / LOG1P(maxdcd)); /*lint !e666*/
    283 }
    284 else
    285 {
    286 scaleddcd = 0.0;
    287 }
    288
    289 if ( SCIPisSumLE(scip, exps[i], 0.0))
    290 scaledexp = 0.0;
    291 else
    292 scaledexp = cutseldata->expimprovweight * SQR(LOG1P(exps[i]) / LOG1P(maxexp)); /*lint !e666*/
    293
    294 if ( SCIPisSumLE(scip, effs[i], 0.0))
    295 {
    296 scaledeff = 0.0;
    297 }
    298 else
    299 {
    300 if ( sol != NULL && root )
    301 scaledeff = cutseldata->efficacyweight * SQR(LOG1P(effs[i]) / LOG1P(maxeff)); /*lint !e666*/
    302 else
    303 scaledeff = (cutseldata->efficacyweight + cutseldata->dircutoffdistweight) * SQR(LOG1P(effs[i]) / LOG1P(maxeff)); /*lint !e666*/
    304 }
    305
    306 /* Combine all scores and introduce some minor randomness */
    307 score = scaledeff + scaleddcd + scaledexp + objparallelism + intsupport + density + dynamism + pscost + cutlock;
    308
    309 score += SCIPrandomGetReal(cutseldata->randnumgen, 0.0, 1e-6);
    310
    311 scores[i] = score;
    312 }
    313
    317 SCIPfreeBufferArray(scip, &cutdensities);
    318 SCIPfreeBufferArray(scip, &cutlocks);
    319 SCIPfreeBufferArray(scip, &pscosts);
    320
    321 return SCIP_OKAY;
    322}
    323
    324
    325/** move the cut with the highest score to the first position in the array; there must be at least one cut */
    326static
    328 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
    329 SCIP_Real* scores, /**< array with scores of cuts to perform selection algorithm */
    330 int ncuts /**< number of cuts in given array */
    331 )
    332{
    333 int bestpos;
    334 SCIP_Real bestscore;
    335
    336 assert(ncuts > 0);
    337 assert(cuts != NULL);
    338 assert(scores != NULL);
    339
    340 bestscore = scores[0];
    341 bestpos = 0;
    342
    343 for( int i = 1; i < ncuts; ++i )
    344 {
    345 if( scores[i] > bestscore )
    346 {
    347 bestpos = i;
    348 bestscore = scores[i];
    349 }
    350 }
    351
    352 SCIPswapPointers((void**) &cuts[bestpos], (void**) &cuts[0]);
    353 SCIPswapReals(&scores[bestpos], &scores[0]);
    354}
    355
    356/** filters the given array of cuts to enforce a maximum parallelism constraint
    357 * w.r.t the given cut; moves filtered cuts to the end of the array and returns number of selected cuts */
    358static
    360 SCIP_ROW* cut, /**< cut to filter orthogonality with */
    361 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
    362 SCIP_Real* scores, /**< array with scores of cuts to perform selection algorithm */
    363 int ncuts, /**< number of cuts in given array */
    364 SCIP_Real maxparallel /**< maximal parallelism for all cuts that are not good */
    365 )
    366{
    367 assert( cut != NULL );
    368 assert( ncuts == 0 || cuts != NULL );
    369 assert( ncuts == 0 || scores != NULL );
    370
    371 for( int i = ncuts - 1; i >= 0; --i )
    372 {
    373 SCIP_Real thisparallel;
    374
    375 thisparallel = SCIProwGetParallelism(cut, cuts[i], 'e');
    376
    377 if( thisparallel > maxparallel )
    378 {
    379 --ncuts;
    380 SCIPswapPointers((void**) &cuts[i], (void**) &cuts[ncuts]);
    381 SCIPswapReals(&scores[i], &scores[ncuts]);
    382 }
    383 }
    384
    385 return ncuts;
    386}
    387
    388/** penalises any cut too parallel to cut by reducing the parallel cut's score. */
    389static
    391 SCIP* scip, /**< SCIP data structure */
    392 SCIP_ROW* cut, /**< cut to filter orthogonality with */
    393 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
    394 SCIP_Real* scores, /**< array with scores of cuts to perform selection algorithm */
    395 int ncuts, /**< number of cuts in given array */
    396 SCIP_Real maxparallel, /**< maximal parallelism for all cuts that are not good */
    397 SCIP_Real paralpenalty /**< penalty for weaker of two parallel cuts if penalising parallel cuts */
    398 )
    399{
    400 assert( cut != NULL );
    401 assert( ncuts == 0 || cuts != NULL );
    402 assert( ncuts == 0 || scores != NULL );
    403
    404 for( int i = ncuts - 1; i >= 0; --i )
    405 {
    406 SCIP_Real thisparallel;
    407
    408 thisparallel = SCIProwGetParallelism(cut, cuts[i], 'e');
    409
    410 /* Filter cuts that are absolutely parallel still. Otherwise penalise if closely parallel */
    411 if( thisparallel > 1 - SCIPsumepsilon(scip) )
    412 {
    413 --ncuts;
    414 SCIPswapPointers((void**) &cuts[i], (void**) &cuts[ncuts]);
    415 SCIPswapReals(&scores[i], &scores[ncuts]);
    416 }
    417 else if( thisparallel > maxparallel )
    418 {
    419 scores[i] -= paralpenalty;
    420 }
    421 }
    422
    423 return ncuts;
    424}
    425
    426/** filters the given array of cuts to enforce a maximum density constraint,
    427 * Moves filtered cuts to the end of the array and returns number of selected cuts */
    428static
    430 SCIP* scip, /**< SCIP data structure */
    431 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
    432 SCIP_Real maxdensity, /**< maximum density s.t. a cut is not filtered */
    433 int ncuts /**< number of cuts in given array */
    434 )
    435{
    436 SCIP_Real ncols;
    437
    438 assert( ncuts == 0 || cuts != NULL );
    439
    440 ncols = SCIPgetNLPCols(scip);
    441
    442 for( int i = ncuts - 1; i >= 0; --i )
    443 {
    444 SCIP_Real nvals;
    445
    446 nvals = SCIProwGetNNonz(cuts[i]);
    447
    448 if( maxdensity < nvals / ncols )
    449 {
    450 --ncuts;
    451 SCIPswapPointers((void**) &cuts[i], (void**) &cuts[ncuts]);
    452 }
    453 }
    454
    455 return ncuts;
    456}
    457
    458
    459/*
    460 * Callback methods of cut selector
    461 */
    462
    463
    464/** copy method for cut selector plugin (called when SCIP copies plugins) */
    465static
    466SCIP_DECL_CUTSELCOPY(cutselCopyEnsemble)
    467{ /*lint --e{715}*/
    468 assert(scip != NULL);
    469 assert(cutsel != NULL);
    470 assert(strcmp(SCIPcutselGetName(cutsel), CUTSEL_NAME) == 0);
    471
    472 /* call inclusion method of cut selector */
    474
    475 return SCIP_OKAY;
    476}
    477
    478/** destructor of cut selector to free user data (called when SCIP is exiting) */
    479/**! [SnippetCutselFreeEnsemble] */
    480static
    481SCIP_DECL_CUTSELFREE(cutselFreeEnsemble)
    482{ /*lint --e{715}*/
    483 SCIP_CUTSELDATA* cutseldata;
    484
    485 cutseldata = SCIPcutselGetData(cutsel);
    486
    487 SCIPfreeBlockMemory(scip, &cutseldata);
    488
    489 SCIPcutselSetData(cutsel, NULL);
    490
    491 return SCIP_OKAY;
    492}
    493/**! [SnippetCutselFreeEnsemble] */
    494
    495/** initialization method of cut selector (called after problem was transformed) */
    496static
    497SCIP_DECL_CUTSELINIT(cutselInitEnsemble)
    498{ /*lint --e{715}*/
    499 SCIP_CUTSELDATA* cutseldata;
    500
    501 cutseldata = SCIPcutselGetData(cutsel);
    502 assert(cutseldata != NULL);
    503
    504 SCIP_CALL( SCIPcreateRandom(scip, &(cutseldata)->randnumgen, RANDSEED, TRUE) );
    505
    506 return SCIP_OKAY;
    507}
    508
    509/** deinitialization method of cut selector (called before transformed problem is freed) */
    510static
    511SCIP_DECL_CUTSELEXIT(cutselExitEnsemble)
    512{ /*lint --e{715}*/
    513 SCIP_CUTSELDATA* cutseldata;
    514
    515 cutseldata = SCIPcutselGetData(cutsel);
    516 assert(cutseldata != NULL);
    517 assert(cutseldata->randnumgen != NULL);
    518
    519 SCIPfreeRandom(scip, &cutseldata->randnumgen);
    520
    521 return SCIP_OKAY;
    522}
    523
    524/** cut selection method of cut selector */
    525static
    526SCIP_DECL_CUTSELSELECT(cutselSelectEnsemble)
    527{ /*lint --e{715}*/
    528 SCIP_CUTSELDATA* cutseldata;
    529
    530 assert(cutsel != NULL);
    531 assert(result != NULL);
    532
    533 cutseldata = SCIPcutselGetData(cutsel);
    534 assert(cutseldata != NULL);
    535
    536 if( ncuts > cutseldata->maxcuts || SCIPgetNVars(scip) > cutseldata->maxnumvars )
    537 {
    538 *result = SCIP_DIDNOTFIND;
    539 return SCIP_OKAY;
    540 }
    541
    542 *result = SCIP_SUCCESS;
    543
    544 SCIP_CALL( SCIPselectCutsEnsemble(scip, cuts, forcedcuts, cutseldata, root, ncuts, nforcedcuts,
    545 maxnselectedcuts, nselectedcuts) );
    546
    547 return SCIP_OKAY;
    548}
    549
    550
    551/*
    552 * cut selector specific interface methods
    553 */
    554
    555/** creates the ensemble cut selector and includes it in SCIP */
    557 SCIP* scip /**< SCIP data structure */
    558 )
    559{
    560 SCIP_CUTSELDATA* cutseldata;
    561 SCIP_CUTSEL* cutsel;
    562
    563 /* create ensemble cut selector data */
    564 SCIP_CALL( SCIPallocBlockMemory(scip, &cutseldata) );
    565 BMSclearMemory(cutseldata);
    566
    568 cutseldata) );
    569
    570 assert(cutsel != NULL);
    571
    572 /* set non fundamental callbacks via setter functions */
    573 SCIP_CALL( SCIPsetCutselCopy(scip, cutsel, cutselCopyEnsemble) );
    574
    575 SCIP_CALL( SCIPsetCutselFree(scip, cutsel, cutselFreeEnsemble) );
    576 SCIP_CALL( SCIPsetCutselInit(scip, cutsel, cutselInitEnsemble) );
    577 SCIP_CALL( SCIPsetCutselExit(scip, cutsel, cutselExitEnsemble) );
    578
    579 /* add ensemble cut selector parameters */
    580 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/efficacyweight", "weight of normed-efficacy in cut "
    581 "score calculation", &cutseldata->efficacyweight, FALSE, DEFAULT_EFFICACYWEIGHT, 0.0, SCIP_INVALID/10.0, NULL,
    582 NULL) );
    583
    584 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/dircutoffdistweight", "weight of normed-directed "
    585 "cutoff distance in cut score calculation", &cutseldata->dircutoffdistweight, FALSE,
    587
    588 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/objparalweight", "weight of objective parallelism "
    589 "in cut score calculation", &cutseldata->objparalweight, FALSE, DEFAULT_OBJPARALWEIGHT, 0.0, SCIP_INVALID/10.0,
    590 NULL, NULL) );
    591
    592 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/intsupportweight", "weight of integral support in "
    593 "cut score calculation", &cutseldata->intsupportweight, FALSE, DEFAULT_INTSUPPORTWEIGHT, 0.0,
    594 SCIP_INVALID/10.0, NULL, NULL) );
    595
    596 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/expimprovweight", "weight of normed-expected obj "
    597 "improvement in cut score calculation", &cutseldata->expimprovweight, FALSE, DEFAULT_EXPIMPROVWEIGHT, 0.0,
    598 SCIP_INVALID/10.0, NULL, NULL) );
    599
    600 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/minscore", "minimum score s.t. a cut can be added",
    601 &cutseldata->minscore, FALSE, DEFAULT_MINSCORE, -SCIP_INVALID/10.0, SCIP_INVALID/10.0, NULL, NULL) );
    602
    603 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/pscostweight", "weight of normed-pseudo-costs in "
    604 "cut score calculation", &cutseldata->pscostweight, FALSE, DEFAULT_PSCOSTWEIGHT, 0.0, SCIP_INVALID/10.0, NULL,
    605 NULL) );
    606
    607 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/locksweight", "weight of normed-num-locks in cut "
    608 "score calculation", &cutseldata->locksweight, FALSE, DEFAULT_NLOCKSWEIGHT, 0.0, SCIP_INVALID/10.0, NULL,
    609 NULL) );
    610
    611 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/maxsparsitybonus", "weight of maximum sparsity "
    612 "reward in cut score calculation", &cutseldata->maxsparsitybonus, FALSE, DEFAULT_MAXSPARSITYBONUS, 0.0,
    613 SCIP_INVALID/10.0, NULL, NULL) );
    614
    615 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/goodnumericsbonus", "weight of good numerics bonus "
    616 "(ratio of coefficients) in cut score calculation", &cutseldata->goodnumericsbonus, FALSE,
    618
    619 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/endsparsitybonus", "max sparsity value for which a "
    620 "bonus is applied in cut score calculation", &cutseldata->endsparsitybonus, FALSE, DEFAULT_SPARSITYENDBONUS,
    621 0.0, SCIP_INVALID/10.0, NULL, NULL) );
    622
    623 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/maxparal", "threshold for when two cuts are "
    624 "considered parallel to each other", &cutseldata->maxparal, FALSE, DEFAULT_MAXPARAL, 0.0, 1.0, NULL, NULL) );
    625
    626 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/paralpenalty", "penalty for weaker of two parallel "
    627 "cuts if penalising parallel cuts", &cutseldata->paralpenalty, TRUE, DEFAULT_PARALPENALTY, 0.0,
    628 SCIP_INVALID/10.0, NULL, NULL) );
    629
    630 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/maxcutdensity", "max allowed cut density if "
    631 "filtering dense cuts", &cutseldata->maxcutdensity, TRUE, DEFAULT_MAXCUTDENSITY, 0.0, 1.0, NULL, NULL) );
    632
    633 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/maxnonzerorootround", "max non-zeros per round "
    634 "applied cuts (root). multiple num LP cols.", &cutseldata->maxnonzerorootround, FALSE,
    636
    637 SCIP_CALL( SCIPaddRealParam(scip, "cutselection/" CUTSEL_NAME "/maxnonzerotreeround", "max non-zeros per round "
    638 "applied cuts (tree). multiple num LP cols.", &cutseldata->maxnonzerotreeround, FALSE,
    640
    641 SCIP_CALL( SCIPaddBoolParam(scip, "cutselection/" CUTSEL_NAME "/filterparalcuts", "should cuts be filtered so no "
    642 "two parallel cuts are added", &cutseldata->filterparalcuts, FALSE, DEFAULT_FILTERPARALCUTS, NULL, NULL) );
    643
    644 SCIP_CALL( SCIPaddBoolParam(scip, "cutselection/" CUTSEL_NAME "/penaliseparalcuts", "should two parallel cuts be "
    645 "penalised instead of outright filtered", &cutseldata->penaliseparalcuts, TRUE, DEFAULT_PENALISEPARALCUTS,
    646 NULL, NULL) );
    647
    648 SCIP_CALL( SCIPaddBoolParam(scip, "cutselection/" CUTSEL_NAME "/filterdensecuts", "should cuts over a given density "
    649 "threshold be filtered", &cutseldata->filterdensecuts, TRUE, DEFAULT_FILTERDENSECUTS, NULL, NULL) );
    650
    651 SCIP_CALL( SCIPaddBoolParam(scip, "cutselection/" CUTSEL_NAME "/penaliselocks", "should the number of locks be "
    652 "penalised instead of rewarded", &cutseldata->penaliselocks, TRUE, DEFAULT_PENALISELOCKS, NULL, NULL) );
    653
    654 SCIP_CALL( SCIPaddBoolParam(scip, "cutselection/" CUTSEL_NAME "/penaliseobjparal", "should objective parallelism "
    655 "be penalised instead of rewarded", &cutseldata->penaliseobjparal, TRUE, DEFAULT_PENALISEOBJPARAL, NULL, NULL)
    656 );
    657
    658 SCIP_CALL( SCIPaddIntParam(scip, "cutselection/" CUTSEL_NAME "/maxcoefratiobonus", "max coefficient ratio for "
    659 "which numeric bonus is applied.", &cutseldata->maxcoefratiobonus, TRUE, DEFAULT_MAXCOEFRATIOBONUS, 1, 1000000,
    660 NULL, NULL) );
    661
    662 SCIP_CALL( SCIPaddIntParam(scip, "cutselection/" CUTSEL_NAME "/maxcuts", "max number of cuts such that cut "
    663 "selector is applied.", &cutseldata->maxcuts, TRUE, DEFAULT_MAXCUTS, 1, 1000000, NULL, NULL) );
    664
    665 SCIP_CALL( SCIPaddIntParam(scip, "cutselection/" CUTSEL_NAME "/maxnumvars", "max number of variables such that cut "
    666 "selector is applied.", &cutseldata->maxnumvars, TRUE, DEFAULT_MAXNUMVARS, 1, 1000000, NULL, NULL) );
    667
    668 return SCIP_OKAY;
    669}
    670
    671/** perform a cut selection algorithm for the given array of cuts
    672 *
    673 * This is the selection method of the ensemble cut selector. It uses a weighted sum of normalised efficacy,
    674 * normalised directed cutoff distance, normalised expected improvements, objective parallelism,
    675 * integer support, sparsity, dynamism, pseudo-costs, and variable locks.
    676 * In addition to the weighted sum score, there are optionally parallelism-based filtering and penalties,
    677 * and density filtering.
    678 * There are also additional budget constraints on the number of cuts that should be added.
    679 * The input cuts array gets re-sorted such that the selected cuts come first and the remaining ones are the end.
    680 */
    682 SCIP* scip, /**< SCIP data structure */
    683 SCIP_ROW** cuts, /**< array with cuts to perform selection algorithm */
    684 SCIP_ROW** forcedcuts, /**< array with forced cuts */
    685 SCIP_CUTSELDATA* cutseldata, /**< cut selector data */
    686 SCIP_Bool root, /**< whether we are at the root node or not */
    687 int ncuts, /**< number of cuts in cuts array */
    688 int nforcedcuts, /**< number of forced cuts */
    689 int maxselectedcuts, /**< maximal number of cuts from cuts array to select */
    690 int* nselectedcuts /**< pointer to return number of selected cuts from cuts array */
    691 )
    692{
    693 SCIP_Real* scores;
    694 SCIP_Real* origscoresptr;
    695 SCIP_Real nonzerobudget;
    696 SCIP_Real budgettaken = 0.0;
    697 SCIP_Real ncols;
    698
    699 assert(cuts != NULL && ncuts > 0);
    700 assert(forcedcuts != NULL || nforcedcuts == 0);
    701 assert(nselectedcuts != NULL);
    702
    703 *nselectedcuts = 0;
    704 ncols = SCIPgetNLPCols(scip);
    705
    706 /* filter dense cuts */
    707 if( cutseldata->filterdensecuts )
    708 {
    709 ncuts = filterWithDensity(scip, cuts, cutseldata->maxcutdensity, ncuts);
    710 if( ncuts == 0 )
    711 return SCIP_OKAY;
    712 }
    713
    714 /* Initialise the score array */
    715 SCIP_CALL( SCIPallocBufferArray(scip, &scores, ncuts) );
    716 origscoresptr = scores;
    717
    718 /* compute scores of cuts */
    719 SCIP_CALL( scoring(scip, cuts, cutseldata, scores, root, ncuts) );
    720
    721 /* perform cut selection algorithm for the cuts */
    722
    723 /* forced cuts are going to be selected so use them to filter cuts */
    724 for( int i = 0; i < nforcedcuts && ncuts > 0; ++i )
    725 {
    726 if( cutseldata->filterparalcuts )
    727 ncuts = filterWithParallelism(forcedcuts[i], cuts, scores, ncuts, cutseldata->maxparal);
    728 else if( cutseldata->penaliseparalcuts )
    729 ncuts = penaliseWithParallelism(scip, forcedcuts[i], cuts, scores, ncuts, cutseldata->maxparal, cutseldata->paralpenalty);
    730 }
    731
    732 /* Get the budget depending on if we are the root or not */
    733 nonzerobudget = root ? cutseldata->maxnonzerorootround : cutseldata->maxnonzerotreeround;
    734
    735 /* now greedily select the remaining cuts */
    736 while( ncuts > 0 )
    737 {
    738 SCIP_ROW* selectedcut;
    739
    740 selectBestCut(cuts, scores, ncuts);
    741 selectedcut = cuts[0];
    742
    743 /* if the best cut of the remaining cuts is considered bad, we discard it and all remaining cuts */
    744 if( scores[0] < cutseldata->minscore )
    745 break;
    746
    747 ++(*nselectedcuts);
    748
    749 /* if the maximal number of cuts was selected, we can stop here */
    750 if( *nselectedcuts == maxselectedcuts )
    751 break;
    752
    753 /* increase the non-zero budget counter of added cuts */
    754 budgettaken += SCIProwGetNNonz(cuts[0]) / ncols;
    755
    756 /* move the pointers to the next position and filter the remaining cuts to enforce the maximum parallelism constraint */
    757 ++cuts;
    758 ++scores;
    759 --ncuts;
    760
    761 if( cutseldata->filterparalcuts && ncuts > 0)
    762 ncuts = filterWithParallelism(selectedcut, cuts, scores, ncuts, cutseldata->maxparal);
    763 else if( cutseldata->penaliseparalcuts && ncuts > 0 )
    764 ncuts = penaliseWithParallelism(scip, selectedcut, cuts, scores, ncuts, cutseldata->maxparal, cutseldata->paralpenalty);
    765
    766 /* Filter out all remaining cuts that would go over the non-zero budget threshold */
    767 if( nonzerobudget - budgettaken < 1 && ncuts > 0 )
    768 ncuts = filterWithDensity(scip, cuts, nonzerobudget - budgettaken, ncuts);
    769 }
    770
    771 SCIPfreeBufferArray(scip, &origscoresptr);
    772
    773 return SCIP_OKAY;
    774}
    #define DEFAULT_MAXCUTS
    #define DEFAULT_SPARSITYENDBONUS
    static SCIP_DECL_CUTSELEXIT(cutselExitEnsemble)
    #define DEFAULT_EFFICACYWEIGHT
    #define DEFAULT_MAXNONZEROTREEROUND
    #define DEFAULT_OBJPARALWEIGHT
    #define RANDSEED
    #define DEFAULT_FILTERDENSECUTS
    #define DEFAULT_MAXSPARSITYBONUS
    #define DEFAULT_MINSCORE
    #define DEFAULT_PARALPENALTY
    #define DEFAULT_PENALISEPARALCUTS
    #define DEFAULT_GOODNUMERICBONUS
    #define DEFAULT_PENALISELOCKS
    static SCIP_DECL_CUTSELCOPY(cutselCopyEnsemble)
    static SCIP_DECL_CUTSELINIT(cutselInitEnsemble)
    #define DEFAULT_NLOCKSWEIGHT
    static SCIP_RETCODE scoring(SCIP *scip, SCIP_ROW **cuts, SCIP_CUTSELDATA *cutseldata, SCIP_Real *scores, SCIP_Bool root, int ncuts)
    static void selectBestCut(SCIP_ROW **cuts, SCIP_Real *scores, int ncuts)
    static int filterWithDensity(SCIP *scip, SCIP_ROW **cuts, SCIP_Real maxdensity, int ncuts)
    static int penaliseWithParallelism(SCIP *scip, SCIP_ROW *cut, SCIP_ROW **cuts, SCIP_Real *scores, int ncuts, SCIP_Real maxparallel, SCIP_Real paralpenalty)
    static SCIP_DECL_CUTSELSELECT(cutselSelectEnsemble)
    #define CUTSEL_DESC
    #define CUTSEL_PRIORITY
    static int filterWithParallelism(SCIP_ROW *cut, SCIP_ROW **cuts, SCIP_Real *scores, int ncuts, SCIP_Real maxparallel)
    #define DEFAULT_EXPIMPROVWEIGHT
    #define DEFAULT_MAXCOEFRATIOBONUS
    #define DEFAULT_DIRCUTOFFDISTWEIGHT
    #define DEFAULT_MAXCUTDENSITY
    #define DEFAULT_MAXNONZEROROOTROUND
    static SCIP_DECL_CUTSELFREE(cutselFreeEnsemble)
    #define CUTSEL_NAME
    #define DEFAULT_PENALISEOBJPARAL
    #define DEFAULT_MAXNUMVARS
    #define DEFAULT_PSCOSTWEIGHT
    #define DEFAULT_FILTERPARALCUTS
    #define DEFAULT_MAXPARAL
    #define DEFAULT_INTSUPPORTWEIGHT
    ensemble cut selector
    #define NULL
    Definition: def.h:248
    #define LOG1P(x)
    Definition: def.h:204
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define SQR(x)
    Definition: def.h:199
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL(x)
    Definition: def.h:355
    static const SCIP_Real density
    Definition: gastrans.c:145
    SCIP_RETCODE SCIPselectCutsEnsemble(SCIP *scip, SCIP_ROW **cuts, SCIP_ROW **forcedcuts, SCIP_CUTSELDATA *cutseldata, SCIP_Bool root, int ncuts, int nforcedcuts, int maxselectedcuts, int *nselectedcuts)
    SCIP_RETCODE SCIPincludeCutselEnsemble(SCIP *scip)
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    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
    void SCIPswapPointers(void **pointer1, void **pointer2)
    Definition: misc.c:10511
    void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
    Definition: misc.c:10498
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
    Definition: lp.c:17379
    SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:94
    SCIP_Real SCIPgetCutLPSolCutoffDistance(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:72
    SCIP_RETCODE SCIPsetCutselInit(SCIP *scip, SCIP_CUTSEL *cutsel, SCIP_DECL_CUTSELINIT((*cutselinit)))
    Definition: scip_cutsel.c:163
    SCIP_RETCODE SCIPincludeCutselBasic(SCIP *scip, SCIP_CUTSEL **cutsel, const char *name, const char *desc, int priority, SCIP_DECL_CUTSELSELECT((*cutselselect)), SCIP_CUTSELDATA *cutseldata)
    Definition: scip_cutsel.c:98
    SCIP_RETCODE SCIPsetCutselCopy(SCIP *scip, SCIP_CUTSEL *cutsel, SCIP_DECL_CUTSELCOPY((*cutselcopy)))
    Definition: scip_cutsel.c:131
    SCIP_CUTSELDATA * SCIPcutselGetData(SCIP_CUTSEL *cutsel)
    Definition: cutsel.c:419
    SCIP_RETCODE SCIPsetCutselFree(SCIP *scip, SCIP_CUTSEL *cutsel, SCIP_DECL_CUTSELFREE((*cutselfree)))
    Definition: scip_cutsel.c:147
    void SCIPcutselSetData(SCIP_CUTSEL *cutsel, SCIP_CUTSELDATA *cutseldata)
    Definition: cutsel.c:429
    const char * SCIPcutselGetName(SCIP_CUTSEL *cutsel)
    Definition: cutsel.c:159
    SCIP_RETCODE SCIPsetCutselExit(SCIP *scip, SCIP_CUTSEL *cutsel, SCIP_DECL_CUTSELEXIT((*cutselexit)))
    Definition: scip_cutsel.c:179
    int SCIPgetNLPCols(SCIP *scip)
    Definition: scip_lp.c:533
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1886
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_Real SCIPgetRowMinCoef(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1868
    SCIP_Real SCIPgetRowFeasibility(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:2088
    SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
    Definition: lp.c:7970
    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
    SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
    Definition: lp.c:17662
    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_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2981
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPepsilon(SCIP *scip)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    SCIP_Bool SCIPisSumLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPvarGetNLocksDown(SCIP_VAR *var)
    Definition: var.c:4449
    int SCIPvarGetNLocksUp(SCIP_VAR *var)
    Definition: var.c:4462
    SCIP_Real SCIPgetVarPseudocostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real solval)
    Definition: scip_var.c:11531
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
    Definition: misc.c:10245
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    #define BMSclearMemory(ptr)
    Definition: memory.h:129
    public methods for cuts and aggregation rows
    public methods for cut selector plugins
    public methods for the LP relaxation, rows and columns
    public methods for random numbers
    struct SCIP_CutselData SCIP_CUTSELDATA
    Definition: type_cutsel.h:53
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63