SCIP

    Solving Constraint Integer Programs

    sepa_disjunctive.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 sepa_disjunctive.c
    26 * @ingroup DEFPLUGINS_SEPA
    27 * @brief disjunctive cut separator
    28 * @author Tobias Fischer
    29 * @author Marc Pfetsch
    30 *
    31 * We separate disjunctive cuts for two term disjunctions of the form \f$x_1 = 0 \vee x_2 = 0\f$. They can be generated
    32 * directly from the simplex tableau. For further information, we refer to@n
    33 * "A complementarity-based partitioning and disjunctive cut algorithm for mathematical programming problems with
    34 * equilibrium constraints"@n
    35 * Júdice, J.J., Sherali, H.D., Ribeiro, I.M., Faustino, A.M., Journal of Global Optimization 36(1), 89–114 (2006)
    36 *
    37 * Cut coefficients belonging to integer variables can be strengthened by the 'monoidal cut strengthening' procedure, see@n
    38 * "Strengthening cuts for mixed integer programs"@n
    39 * Egon Balas, Robert G. Jeroslow, European Journal of Operational Research, Volume 4, Issue 4, 1980, Pages 224-234
    40 */
    41
    42/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    43
    45#include "scip/cons_sos1.h"
    46#include "scip/pub_cons.h"
    47#include "scip/pub_lp.h"
    48#include "scip/pub_message.h"
    49#include "scip/pub_misc.h"
    50#include "scip/pub_misc_sort.h"
    51#include "scip/pub_sepa.h"
    52#include "scip/pub_var.h"
    53#include "scip/scip_cons.h"
    54#include "scip/scip_cut.h"
    55#include "scip/scip_general.h"
    56#include "scip/scip_lp.h"
    57#include "scip/scip_mem.h"
    58#include "scip/scip_message.h"
    59#include "scip/scip_numerics.h"
    60#include "scip/scip_param.h"
    61#include "scip/scip_sepa.h"
    62#include "scip/scip_sol.h"
    64#include "scip/scip_tree.h"
    66
    67
    68#define SEPA_NAME "disjunctive"
    69#define SEPA_DESC "disjunctive cut separator"
    70#define SEPA_PRIORITY 10 /**< priority for separation */
    71#define SEPA_FREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
    72#define SEPA_MAXBOUNDDIST 0.0 /**< maximal relative distance from the current node's dual bound to primal bound
    73 * compared to best node's dual bound for applying separation.*/
    74#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
    75#define SEPA_DELAY TRUE /**< should separation method be delayed, if other separators found cuts? */
    76
    77#define DEFAULT_MAXRANK 20 /**< maximal rank of a cut that could not be scaled to integral coefficients (-1: unlimited) */
    78#define DEFAULT_MAXRANKINTEGRAL -1 /**< maximal rank of a cut that could be scaled to integral coefficients (-1: unlimited) */
    79#define DEFAULT_MAXWEIGHTRANGE 1e+03 /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
    80#define DEFAULT_STRENGTHEN TRUE /**< strengthen cut if integer variables are present */
    81
    82#define DEFAULT_MAXDEPTH -1 /**< node depth of separating cuts (-1: no limit) */
    83#define DEFAULT_MAXROUNDS 25 /**< maximal number of separation rounds in a branching node (-1: no limit) */
    84#define DEFAULT_MAXROUNDSROOT 100 /**< maximal number of separation rounds in the root node (-1: no limit) */
    85#define DEFAULT_MAXINVCUTS 50 /**< maximal number of cuts investigated per iteration in a branching node */
    86#define DEFAULT_MAXINVCUTSROOT 250 /**< maximal number of cuts investigated per iteration in the root node */
    87#define DEFAULT_MAXCONFSDELAY 100000 /**< delay separation if number of conflict graph edges is larger than predefined value (-1: no limit) */
    88
    89#define MAKECONTINTEGRAL FALSE /**< convert continuous variable to integral variables in SCIPmakeRowIntegral() */
    90
    91
    92/** separator data */
    93struct SCIP_SepaData
    94{
    95 SCIP_Bool strengthen; /**< strengthen cut if integer variables are present */
    96 SCIP_CONSHDLR* conshdlr; /**< SOS1 constraint handler */
    97 SCIP_Real maxweightrange; /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
    98 int maxrank; /**< maximal rank of a cut that could not be scaled to integral coefficients (-1: unlimited) */
    99 int maxrankintegral; /**< maximal rank of a cut that could be scaled to integral coefficients (-1: unlimited) */
    100 int maxdepth; /**< node depth of separating cuts (-1: no limit) */
    101 int maxrounds; /**< maximal number of separation rounds in a branching node (-1: no limit) */
    102 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: no limit) */
    103 int maxinvcuts; /**< maximal number of cuts separated per iteration in a branching node */
    104 int maxinvcutsroot; /**< maximal number of cuts separated per iteration in the root node */
    105 int maxconfsdelay; /**< delay separation if number of conflict graph edges is larger than predefined value (-1: no limit) */
    106 int lastncutsfound; /**< total number of cuts found after last call of separator */
    107};
    108
    109
    110/** gets rank of variable corresponding to row of \f$B^{-1}\f$ */
    111static
    113 SCIP* scip, /**< SCIP pointer */
    114 SCIP_Real* binvrow, /**< row of \f$B^{-1}\f$ */
    115 SCIP_Real* rowsmaxval, /**< maximal row multiplicator from nonbasic matrix A_N */
    116 SCIP_Real maxweightrange, /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
    117 SCIP_ROW** rows, /**< rows of LP relaxation of scip */
    118 int nrows /**< number of rows */
    119 )
    120{
    121 SCIP_Real maxweight = 0.0;
    122 int maxrank = 0;
    123 int r;
    124
    125 assert( scip != NULL );
    126 assert( binvrow != NULL || nrows == 0 );
    127 assert( rowsmaxval != NULL || nrows == 0 );
    128 assert( rows != NULL || nrows == 0 );
    129
    130 /* compute maximum row weights resulting from multiplication */
    131 for (r = 0; r < nrows; ++r)
    132 {
    133 SCIP_Real val;
    134
    135 val = REALABS(binvrow[r] * rowsmaxval[r]);/*lint !e613*/
    136 if ( SCIPisGT(scip, val, maxweight) )
    137 maxweight = val;
    138 }
    139
    140 /* compute rank */
    141 for (r = 0; r < nrows; ++r)
    142 {
    143 SCIP_Real val;
    144 int rank;
    145
    146 val = REALABS(binvrow[r] * rowsmaxval[r]);/*lint !e613*/
    147 rank = SCIProwGetRank(rows[r]);/*lint !e613*/
    148 if ( rank > maxrank && SCIPisGT(scip, val * maxweightrange, maxweight) )
    149 maxrank = rank;
    150 }
    151
    152 return maxrank;
    153}
    154
    155
    156/** gets the nonbasic coefficients of a simplex row */
    157static
    159 SCIP* scip, /**< SCIP pointer */
    160 SCIP_ROW** rows, /**< LP rows */
    161 int nrows, /**< number LP rows */
    162 SCIP_COL** cols, /**< LP columns */
    163 int ncols, /**< number of LP columns */
    164 SCIP_Real* coef, /**< row of \f$B^{-1} \cdot A\f$ */
    165 SCIP_Real* binvrow, /**< row of \f$B^{-1}\f$ */
    166 SCIP_Real* simplexcoefs, /**< pointer to store the nonbasic simplex-coefficients */
    167 int* nonbasicnumber /**< pointer to store the number of nonbasic simplex-coefficients */
    168 )
    169{
    170 int r;
    171 int c;
    172
    173 assert( scip != NULL );
    174 assert( rows != NULL );
    175 assert( nonbasicnumber != NULL );
    176 assert( simplexcoefs != NULL );
    177 assert( cols != NULL );
    178
    179 *nonbasicnumber = 0;
    180
    181 /* note: the non-slack variables have to be added first (see the function generateDisjCutSOS1()) */
    182
    183 /* get simplex-coefficients of the non-basic non-slack variables */
    184 for (c = 0; c < ncols; ++c)
    185 {
    186 SCIP_COL* col;
    187
    188 col = cols[c];
    189 assert( col != NULL );
    191 simplexcoefs[(*nonbasicnumber)++] = coef[c];
    192 }
    193
    194 /* get simplex-coefficients of the non-basic slack variables */
    195 for (r = 0; r < nrows; ++r)
    196 {
    197 SCIP_ROW* row;
    198 row = rows[r];
    199 assert( row != NULL );
    200
    202 {
    204
    205 simplexcoefs[(*nonbasicnumber)++] = binvrow[r];
    206 }
    207 }
    208
    209 return SCIP_OKAY;
    210}
    211
    212
    213/** computes a disjunctive cut inequality based on two simplex tableau rows */
    214static
    216 SCIP* scip, /**< SCIP pointer */
    217 SCIP_SEPA* sepa, /**< separator */
    218 int depth, /**< current depth */
    219 SCIP_ROW** rows, /**< LP rows */
    220 int nrows, /**< number of LP rows */
    221 SCIP_COL** cols, /**< LP columns */
    222 int ncols, /**< number of LP columns */
    223 int ndisjcuts, /**< number of disjunctive cuts found so far */
    224 SCIP_Bool scale, /**< should cut be scaled */
    225 SCIP_Bool strengthen, /**< should cut be strengthened if integer variables are present */
    226 SCIP_Real cutlhs1, /**< left hand side of the first simplex row */
    227 SCIP_Real cutlhs2, /**< left hand side of the second simplex row */
    228 SCIP_Real bound1, /**< bound of first simplex row */
    229 SCIP_Real bound2, /**< bound of second simplex row */
    230 SCIP_Real* simplexcoefs1, /**< simplex coefficients of first row */
    231 SCIP_Real* simplexcoefs2, /**< simplex coefficients of second row */
    232 SCIP_Real* cutcoefs, /**< pointer to store cut coefficients (length: nscipvars) */
    233 SCIP_ROW** row, /**< pointer to store disjunctive cut inequality */
    234 SCIP_Bool* madeintegral /**< pointer to store whether cut has been scaled to integral values */
    235 )
    236{
    237 char cutname[SCIP_MAXSTRLEN];
    238 SCIP_COL** rowcols;
    239 SCIP_COL* col;
    240 SCIP_Real* rowvals;
    241 SCIP_Real lhsrow;
    242 SCIP_Real rhsrow;
    243 SCIP_Real cutlhs;
    244 SCIP_Real sgn;
    245 SCIP_Real lb;
    246 SCIP_Real ub;
    247 int nonbasicnumber = 0;
    248 int rownnonz;
    249 int ind;
    250 int r;
    251 int c;
    252
    253 assert( scip != NULL );
    254 assert( row != NULL );
    255 assert( rows != NULL );
    256 assert( cols != NULL );
    257 assert( simplexcoefs1 != NULL );
    258 assert( simplexcoefs2 != NULL );
    259 assert( cutcoefs != NULL );
    260 assert( sepa != NULL );
    261 assert( madeintegral != NULL );
    262
    263 *madeintegral = FALSE;
    264
    265 /* check signs */
    266 if ( SCIPisFeasPositive(scip, cutlhs1) == SCIPisFeasPositive(scip, cutlhs2) )
    267 sgn = 1.0;
    268 else
    269 sgn = -1.0;
    270
    271 /* check bounds */
    272 if ( SCIPisInfinity(scip, REALABS(bound1)) || SCIPisInfinity(scip, REALABS(bound2)) )
    273 strengthen = FALSE;
    274
    275 /* compute left hand side of row (a later update is possible, see below) */
    276 cutlhs = sgn * cutlhs1 * cutlhs2;
    277
    278 /* add cut-coefficients of the non-basic non-slack variables */
    279 for (c = 0; c < ncols; ++c)
    280 {
    281 col = cols[c];
    282 assert( col != NULL );
    283 ind = SCIPcolGetLPPos(col);
    284 assert( ind >= 0 );
    285
    287 {
    288 lb = SCIPcolGetLb(col);
    289
    290 /* for integer variables we may obtain stronger coefficients */
    291 if ( strengthen && SCIPcolIsIntegral(col) )
    292 {
    293 SCIP_Real mval;
    294 SCIP_Real mvalfloor;
    295 SCIP_Real mvalceil;
    296
    297 mval = (cutlhs2 * simplexcoefs1[nonbasicnumber] - cutlhs1 * simplexcoefs2[nonbasicnumber]) / (cutlhs2 * bound1 + cutlhs1 * bound2);
    298 mvalfloor = SCIPfloor(scip, mval);
    299 mvalceil = SCIPceil(scip, mval);
    300
    301 cutcoefs[ind] = MIN(sgn * cutlhs2 * (simplexcoefs1[nonbasicnumber] - mvalfloor * bound1), sgn * cutlhs1 * (simplexcoefs2[nonbasicnumber] + mvalceil * bound2));
    302 assert( SCIPisFeasLE(scip, cutcoefs[ind], MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber])) );
    303 }
    304 else
    305 cutcoefs[ind] = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
    306
    307 cutlhs += cutcoefs[ind] * lb;
    308 ++nonbasicnumber;
    309 }
    311 {
    312 ub = SCIPcolGetUb(col);
    313
    314 /* for integer variables we may obtain stronger coefficients */
    315 if ( strengthen && SCIPcolIsIntegral(col) )
    316 {
    317 SCIP_Real mval;
    318 SCIP_Real mvalfloor;
    319 SCIP_Real mvalceil;
    320
    321 mval = (cutlhs2 * simplexcoefs1[nonbasicnumber] - cutlhs1 * simplexcoefs2[nonbasicnumber]) / (cutlhs2 * bound1 + cutlhs1 * bound2);
    322 mvalfloor = SCIPfloor(scip, -mval);
    323 mvalceil = SCIPceil(scip, -mval);
    324
    325 cutcoefs[ind] = MAX(sgn * cutlhs2 * (simplexcoefs1[nonbasicnumber] + mvalfloor * bound1), sgn * cutlhs1 * (simplexcoefs2[nonbasicnumber] - mvalceil * bound2));
    326 assert( SCIPisFeasLE(scip, -cutcoefs[ind], -MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber])) );
    327 }
    328 else
    329 cutcoefs[ind] = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
    330
    331 cutlhs += cutcoefs[ind] * ub;
    332 ++nonbasicnumber;
    333 }
    334 else
    335 {
    337 cutcoefs[ind] = 0.0;
    338 }
    339 }
    340
    341 /* add cut-coefficients of the non-basic slack variables */
    342 for (r = 0; r < nrows; ++r)
    343 {
    344 rhsrow = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]);
    345 lhsrow = SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]);
    346
    347 assert( SCIProwGetBasisStatus(rows[r]) != SCIP_BASESTAT_ZERO );
    348 assert( SCIPisFeasZero(scip, lhsrow - rhsrow) || SCIPisNegative(scip, lhsrow - rhsrow) );
    349 assert( SCIProwIsInLP(rows[r]) );
    350
    352 {
    353 SCIP_Real cutcoef;
    354
    356 {
    357 assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetRhs(rows[r])) );
    358
    359 cutcoef = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
    360 cutlhs -= cutcoef * rhsrow;
    361 ++nonbasicnumber;
    362 }
    363 else /* SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER */
    364 {
    365 assert( SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER );
    366 assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetLhs(rows[r])) );
    367
    368 cutcoef = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
    369 cutlhs -= cutcoef * lhsrow;
    370 ++nonbasicnumber;
    371 }
    372
    373 rownnonz = SCIProwGetNNonz(rows[r]);
    374 rowvals = SCIProwGetVals(rows[r]);
    375 rowcols = SCIProwGetCols(rows[r]);
    376
    377 for (c = 0; c < rownnonz; ++c)
    378 {
    379 ind = SCIPcolGetLPPos(rowcols[c]);
    380
    381 /* if column is not in LP, then return without generating cut */
    382 if ( ind < 0 )
    383 {
    384 *row = NULL;
    385 return SCIP_OKAY;
    386 }
    387
    388 cutcoefs[ind] -= cutcoef * rowvals[c];
    389 }
    390 }
    391 }
    392
    393 /* create cut */
    394 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "%s_%" SCIP_LONGINT_FORMAT "_%d", SCIPsepaGetName(sepa), SCIPgetNLPs(scip), ndisjcuts);
    395
    396 /* we create the cut as locally valid, SCIP will make it globally valid if we are at the root node */
    397 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, cutname, cutlhs, SCIPinfinity(scip), TRUE, FALSE, TRUE) );
    398
    400 for (c = 0; c < ncols; ++c)
    401 {
    402 ind = SCIPcolGetLPPos(cols[c]);
    403 assert( ind >= 0 );
    404 if ( ! SCIPisFeasZero(scip, cutcoefs[ind]) )
    405 {
    406 SCIP_CALL( SCIPaddVarToRow(scip, *row, SCIPcolGetVar(cols[c]), cutcoefs[ind] ) );
    407 }
    408 }
    410
    411 /* try to scale the cut to integral values
    412 * @todo find better but still stable disjunctive cut settings
    413 */
    414 if ( scale )
    415 {
    416 SCIP_Longint maxdnom;
    417 SCIP_Real maxscale;
    418
    419 assert( depth >= 0 );
    420 if( depth == 0 )
    421 {
    422 maxdnom = 100;
    423 maxscale = 100.0;
    424 }
    425 else
    426 {
    427 maxdnom = 10;
    428 maxscale = 10.0;
    429 }
    430
    431 SCIP_CALL( SCIPmakeRowIntegral(scip, *row, -SCIPepsilon(scip), SCIPsumepsilon(scip), maxdnom, maxscale, TRUE, madeintegral) );
    432 }
    433
    434 return SCIP_OKAY;
    435}
    436
    437
    438/*
    439 * Callback methods
    440 */
    441
    442/** copy method for separator plugins (called when SCIP copies plugins) */
    443static
    444SCIP_DECL_SEPACOPY(sepaCopyDisjunctive)
    445{
    446 assert( scip != NULL );
    447 assert( sepa != NULL );
    448
    450
    451 /* call inclusion method of constraint handler */
    453
    454 return SCIP_OKAY;
    455}
    456
    457
    458/** destructor of separator to free user data (called when SCIP is exiting) */
    459static
    460SCIP_DECL_SEPAFREE(sepaFreeDisjunctive)/*lint --e{715}*/
    461{
    462 SCIP_SEPADATA* sepadata;
    463
    465
    466 /* free separator data */
    467 sepadata = SCIPsepaGetData(sepa);
    468 assert( sepadata != NULL );
    469
    470 SCIPfreeBlockMemory(scip, &sepadata);
    471
    472 SCIPsepaSetData(sepa, NULL);
    473
    474 return SCIP_OKAY;
    475}
    476
    477
    478/** solving process initialization method of separator */
    479static
    480SCIP_DECL_SEPAEXITSOL(sepaInitsolDisjunctive)
    481{ /*lint --e{715}*/
    482 SCIP_SEPADATA* sepadata;
    483
    484 sepadata = SCIPsepaGetData(sepa);
    485 assert(sepadata != NULL);
    486
    487 sepadata->conshdlr = SCIPfindConshdlr(scip, "SOS1");
    488
    489 return SCIP_OKAY;
    490}
    491
    492
    493/** LP solution separation method for disjunctive cuts */
    494static
    495SCIP_DECL_SEPAEXECLP(sepaExeclpDisjunctive)
    496{
    497 SCIP_SEPADATA* sepadata;
    498 SCIP_CONSHDLR* conshdlr;
    499 SCIP_DIGRAPH* conflictgraph;
    500 SCIP_ROW** rows;
    501 SCIP_COL** cols;
    502 SCIP_Real* cutcoefs = NULL;
    503 SCIP_Real* simplexcoefs1 = NULL;
    504 SCIP_Real* simplexcoefs2 = NULL;
    505 SCIP_Real* coef = NULL;
    506 SCIP_Real* binvrow = NULL;
    507 SCIP_Real* rowsmaxval = NULL;
    508 SCIP_Real* violationarray = NULL;
    509 int* fixings1 = NULL;
    510 int* fixings2 = NULL;
    511 int* basisind = NULL;
    512 int* basisrow = NULL;
    513 int* varrank = NULL;
    514 int* edgearray = NULL;
    515 int nedges;
    516 int ndisjcuts;
    517 int nrelevantedges;
    518 int nsos1vars;
    519 int nconss;
    520 int maxcuts;
    521 int ncalls;
    522 int ncols;
    523 int nrows;
    524 int ind;
    525 int j;
    526 int i;
    527
    528 assert( sepa != NULL );
    529 assert( scip != NULL );
    530 assert( result != NULL );
    531
    533
    534 *result = SCIP_DIDNOTRUN;
    535
    536 if( !allowlocal )
    537 return SCIP_OKAY;
    538
    539 /* only generate disjunctive cuts if we are not close to terminating */
    540 if ( SCIPisStopped(scip) )
    541 return SCIP_OKAY;
    542
    543 /* only generate disjunctive cuts if an optimal LP solution is at hand */
    545 return SCIP_OKAY;
    546
    547 /* only generate disjunctive cuts if the LP solution is basic */
    548 if ( ! SCIPisLPSolBasic(scip) )
    549 return SCIP_OKAY;
    550
    551 /* get LP data */
    552 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    553 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    554
    555 /* return if LP has no columns or no rows */
    556 if ( ncols == 0 || nrows == 0 )
    557 return SCIP_OKAY;
    558
    559 assert( cols != NULL );
    560 assert( rows != NULL );
    561
    562 /* get sepa data */
    563 sepadata = SCIPsepaGetData(sepa);
    564 assert( sepadata != NULL );
    565
    566 /* get constraint handler */
    567 conshdlr = sepadata->conshdlr;
    568 if ( conshdlr == NULL )
    569 return SCIP_OKAY;
    570
    571 /* get number of constraints */
    572 nconss = SCIPconshdlrGetNConss(conshdlr);
    573 if ( nconss == 0 )
    574 return SCIP_OKAY;
    575
    576 /* check for maxdepth < depth, maxinvcutsroot = 0 and maxinvcuts = 0 */
    577 if ( ( sepadata->maxdepth >= 0 && sepadata->maxdepth < depth )
    578 || ( depth == 0 && sepadata->maxinvcutsroot == 0 )
    579 || ( depth > 0 && sepadata->maxinvcuts == 0 ) )
    580 return SCIP_OKAY;
    581
    582 /* only call the cut separator a given number of times at each node */
    583 ncalls = SCIPsepaGetNCallsAtNode(sepa);
    584 if ( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
    585 || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
    586 return SCIP_OKAY;
    587
    588 /* get conflict graph and number of conflict graph edges (note that the digraph arcs were added in both directions) */
    589 conflictgraph = SCIPgetConflictgraphSOS1(conshdlr);
    590 if( conflictgraph == NULL )
    591 return SCIP_OKAY;
    592
    593 nedges = (int)SCIPceil(scip, (SCIP_Real)SCIPdigraphGetNArcs(conflictgraph)/2);
    594
    595 /* if too many conflict graph edges, the separator can be slow: delay it until no other cuts have been found */
    596 if ( sepadata->maxconfsdelay >= 0 && nedges >= sepadata->maxconfsdelay )
    597 {
    598 int ncutsfound;
    599
    600 ncutsfound = SCIPgetNCutsFound(scip);
    601 if ( ncutsfound > sepadata->lastncutsfound || ! SCIPsepaWasLPDelayed(sepa) )
    602 {
    603 sepadata->lastncutsfound = ncutsfound;
    604 *result = SCIP_DELAYED;
    605 return SCIP_OKAY;
    606 }
    607 }
    608
    609 /* check basis status */
    610 for (j = 0; j < ncols; ++j)
    611 {
    613 return SCIP_OKAY;
    614 }
    615
    616 /* check accuracy of rows */
    617 for (j = 0; j < nrows; ++j)
    618 {
    619 SCIP_ROW* row;
    620
    621 row = rows[j];
    622
    625 return SCIP_OKAY;
    626 }
    627
    628 /* get number of SOS1 variables */
    629 nsos1vars = SCIPgetNSOS1Vars(conshdlr);
    630
    631 /* allocate buffer arrays */
    632 SCIP_CALL( SCIPallocBufferArray(scip, &edgearray, nedges) );
    633 SCIP_CALL( SCIPallocBufferArray(scip, &fixings1, nedges) );
    634 SCIP_CALL( SCIPallocBufferArray(scip, &fixings2, nedges) );
    635 SCIP_CALL( SCIPallocBufferArray(scip, &violationarray, nedges) );
    636
    637 /* get all violated conflicts {i, j} in the conflict graph and sort them based on the degree of a violation value */
    638 nrelevantedges = 0;
    639 for (j = 0; j < nsos1vars; ++j)
    640 {
    641 SCIP_VAR* var;
    642
    643 var = SCIPnodeGetVarSOS1(conflictgraph, j);
    644
    646 {
    647 int* succ;
    648 int nsucc;
    649
    650 /* get successors and number of successors */
    651 nsucc = SCIPdigraphGetNSuccessors(conflictgraph, j);
    652 succ = SCIPdigraphGetSuccessors(conflictgraph, j);
    653
    654 for (i = 0; i < nsucc; ++i)
    655 {
    656 SCIP_VAR* varsucc;
    657 int succind;
    658
    659 succind = succ[i];
    660 varsucc = SCIPnodeGetVarSOS1(conflictgraph, succind);
    661 if ( SCIPvarIsActive(varsucc) && succind < j && ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, NULL, varsucc) ) &&
    663 {
    664 fixings1[nrelevantedges] = j;
    665 fixings2[nrelevantedges] = succind;
    666 edgearray[nrelevantedges] = nrelevantedges;
    667 violationarray[nrelevantedges++] = SCIPgetSolVal(scip, NULL, var) * SCIPgetSolVal(scip, NULL, varsucc);
    668 }
    669 }
    670 }
    671 }
    672
    673 /* sort violation score values */
    674 if ( nrelevantedges > 0)
    675 SCIPsortDownRealInt(violationarray, edgearray, nrelevantedges);
    676 else
    677 {
    678 SCIPfreeBufferArrayNull(scip, &violationarray);
    679 SCIPfreeBufferArrayNull(scip, &fixings2);
    680 SCIPfreeBufferArrayNull(scip, &fixings1);
    681 SCIPfreeBufferArrayNull(scip, &edgearray);
    682
    683 return SCIP_OKAY;
    684 }
    685 SCIPfreeBufferArrayNull(scip, &violationarray);
    686
    687 /* compute maximal number of cuts */
    688 if ( depth == 0 )
    689 maxcuts = MIN(sepadata->maxinvcutsroot, nrelevantedges);
    690 else
    691 maxcuts = MIN(sepadata->maxinvcuts, nrelevantedges);
    692 assert( maxcuts > 0 );
    693
    694 /* allocate buffer arrays */
    695 SCIP_CALL( SCIPallocBufferArray(scip, &varrank, ncols) );
    696 SCIP_CALL( SCIPallocBufferArray(scip, &rowsmaxval, nrows) );
    697 SCIP_CALL( SCIPallocBufferArray(scip, &basisrow, ncols) );
    698 SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
    699 SCIP_CALL( SCIPallocBufferArray(scip, &coef, ncols) );
    700 SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs1, ncols) );
    701 SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs2, ncols) );
    702 SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, ncols) );
    703 SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
    704
    705 /* get basis indices */
    706 SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
    707
    708 /* create vector "basisrow" with basisrow[column of non-slack basis variable] = corresponding row of B^-1;
    709 * compute maximum absolute value of nonbasic row coefficients */
    710 for (j = 0; j < nrows; ++j)
    711 {
    712 SCIP_COL** rowcols;
    713 SCIP_Real* rowvals;
    714 SCIP_ROW* row;
    715 SCIP_Real val;
    716 SCIP_Real max = 0.0;
    717 int nnonz;
    718
    719 /* fill basisrow vector */
    720 ind = basisind[j];
    721 if ( ind >= 0 )
    722 basisrow[ind] = j;
    723
    724 /* compute maximum absolute value of nonbasic row coefficients */
    725 row = rows[j];
    726 assert( row != NULL );
    727 rowvals = SCIProwGetVals(row);
    728 nnonz = SCIProwGetNNonz(row);
    729 rowcols = SCIProwGetCols(row);
    730
    731 for (i = 0; i < nnonz; ++i)
    732 {
    734 {
    735 val = REALABS(rowvals[i]);
    736 if ( SCIPisFeasGT(scip, val, max) )
    737 max = REALABS(val);
    738 }
    739 }
    740
    741 /* handle slack variable coefficient and save maximum value */
    742 rowsmaxval[j] = MAX(max, 1.0);
    743 }
    744
    745 /* initialize variable ranks with -1 */
    746 for (j = 0; j < ncols; ++j)
    747 varrank[j] = -1;
    748
    749 /* free buffer array */
    750 SCIPfreeBufferArrayNull(scip, &basisind);
    751
    752 /* for the most promising disjunctions: try to generate disjunctive cuts */
    753 ndisjcuts = 0;
    754 for (i = 0; i < maxcuts; ++i)
    755 {
    756 SCIP_Bool madeintegral;
    757 SCIP_Real cutlhs1;
    758 SCIP_Real cutlhs2;
    759 SCIP_Real bound1;
    760 SCIP_Real bound2;
    761 SCIP_ROW* row = NULL;
    762 SCIP_VAR* var;
    763 SCIP_COL* col;
    764
    765 int nonbasicnumber;
    766 int cutrank = 0;
    767 int edgenumber;
    768 int rownnonz;
    769
    770 edgenumber = edgearray[i];
    771
    772 /* determine first simplex row */
    773 var = SCIPnodeGetVarSOS1(conflictgraph, fixings1[edgenumber]);
    774 col = SCIPvarGetCol(var);
    775 ind = SCIPcolGetLPPos(col);
    776 assert( ind >= 0 );
    778
    779 /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
    780 SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
    781 SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );
    782
    783 /* get the simplex-coefficients of the non-basic variables */
    784 SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs1, &nonbasicnumber) );
    785
    786 /* get rank of variable if not known already */
    787 if ( varrank[ind] < 0 )
    788 varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
    789 cutrank = MAX(cutrank, varrank[ind]);
    790
    791 /* get right hand side and bound of simplex talbeau row */
    792 cutlhs1 = SCIPcolGetPrimsol(col);
    793 if ( SCIPisFeasPositive(scip, cutlhs1) )
    794 bound1 = SCIPcolGetUb(col);
    795 else
    796 bound1 = SCIPcolGetLb(col);
    797
    798 /* determine second simplex row */
    799 var = SCIPnodeGetVarSOS1(conflictgraph, fixings2[edgenumber]);
    800 col = SCIPvarGetCol(var);
    801 ind = SCIPcolGetLPPos(col);
    802 assert( ind >= 0 );
    804
    805 /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
    806 SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
    807 SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );
    808
    809 /* get the simplex-coefficients of the non-basic variables */
    810 SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs2, &nonbasicnumber) );
    811
    812 /* get rank of variable if not known already */
    813 if ( varrank[ind] < 0 )
    814 varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
    815 cutrank = MAX(cutrank, varrank[ind]);
    816
    817 /* get right hand side and bound of simplex talbeau row */
    818 cutlhs2 = SCIPcolGetPrimsol(col);
    819 if ( SCIPisFeasPositive(scip, cutlhs2) )
    820 bound2 = SCIPcolGetUb(col);
    821 else
    822 bound2 = SCIPcolGetLb(col);
    823
    824 /* add coefficients to cut */
    825 SCIP_CALL( generateDisjCutSOS1(scip, sepa, depth, rows, nrows, cols, ncols, ndisjcuts, MAKECONTINTEGRAL, sepadata->strengthen, cutlhs1, cutlhs2, bound1, bound2, simplexcoefs1, simplexcoefs2, cutcoefs, &row, &madeintegral) );
    826 if ( row == NULL )
    827 continue;
    828
    829 /* raise cutrank for present cut */
    830 ++cutrank;
    831
    832 /* check if there are numerical evidences */
    833 if ( ( madeintegral && ( sepadata->maxrankintegral == -1 || cutrank <= sepadata->maxrankintegral ) )
    834 || ( ! madeintegral && ( sepadata->maxrank == -1 || cutrank <= sepadata->maxrank ) ) )
    835 {
    836 /* possibly add cut to LP if it is useful; in case the lhs of the cut is minus infinity (due to scaling) the cut is useless */
    837 rownnonz = SCIProwGetNNonz(row);
    838 if ( rownnonz > 0 && ! SCIPisInfinity(scip, -SCIProwGetLhs(row)) && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, NULL, row) )
    839 {
    840 SCIP_Bool infeasible;
    841
    842 /* set cut rank */
    843 SCIProwChgRank(row, cutrank);
    844
    845 /* add cut */
    846 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
    848 if ( infeasible )
    849 {
    850 *result = SCIP_CUTOFF;
    851 break;
    852 }
    853 ++ndisjcuts;
    854 }
    855 }
    856
    857 /* release row */
    858 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    859 }
    860
    861 /* save total number of cuts found so far */
    862 sepadata->lastncutsfound = SCIPgetNCutsFound(scip);
    863
    864 /* evaluate the result of the separation */
    865 if ( *result != SCIP_CUTOFF )
    866 {
    867 if ( ndisjcuts > 0 )
    868 *result = SCIP_SEPARATED;
    869 else
    870 *result = SCIP_DIDNOTFIND;
    871 }
    872
    873 SCIPdebugMsg(scip, "Number of found disjunctive cuts: %d.\n", ndisjcuts);
    874
    875 /* free buffer arrays */
    876 SCIPfreeBufferArrayNull(scip, &cutcoefs);
    877 SCIPfreeBufferArrayNull(scip, &simplexcoefs2);
    878 SCIPfreeBufferArrayNull(scip, &simplexcoefs1);
    880 SCIPfreeBufferArrayNull(scip, &binvrow);
    881 SCIPfreeBufferArrayNull(scip, &basisrow);
    882 SCIPfreeBufferArrayNull(scip, &rowsmaxval);
    883 SCIPfreeBufferArrayNull(scip, &varrank);
    884 SCIPfreeBufferArrayNull(scip, &fixings2);
    885 SCIPfreeBufferArrayNull(scip, &fixings1);
    886 SCIPfreeBufferArrayNull(scip, &edgearray);
    887
    888 return SCIP_OKAY;
    889}
    890
    891
    892/** creates the disjunctive cut separator and includes it in SCIP */
    894 SCIP* scip /**< SCIP data structure */
    895 )
    896{
    897 SCIP_SEPADATA* sepadata = NULL;
    898 SCIP_SEPA* sepa = NULL;
    899
    900 /* create separator data */
    901 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
    902 sepadata->conshdlr = NULL;
    903 sepadata->lastncutsfound = 0;
    904
    905 /* include separator */
    907 SEPA_USESSUBSCIP, SEPA_DELAY, sepaExeclpDisjunctive, NULL, sepadata) );
    908
    909 assert( sepa != NULL );
    910
    911 /* set non fundamental callbacks via setter functions */
    912 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyDisjunctive) );
    913 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeDisjunctive) );
    914 SCIP_CALL( SCIPsetSepaInitsol(scip, sepa, sepaInitsolDisjunctive) );
    915
    916 /* add separator parameters */
    917 SCIP_CALL( SCIPaddBoolParam(scip, "separating/" SEPA_NAME "/strengthen",
    918 "strengthen cut if integer variables are present.",
    919 &sepadata->strengthen, TRUE, DEFAULT_STRENGTHEN, NULL, NULL) );
    920
    921 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxdepth",
    922 "node depth of separating bipartite disjunctive cuts (-1: no limit)",
    923 &sepadata->maxdepth, TRUE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
    924
    925 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrounds",
    926 "maximal number of separation rounds per iteration in a branching node (-1: no limit)",
    927 &sepadata->maxrounds, TRUE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
    928
    929 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxroundsroot",
    930 "maximal number of separation rounds in the root node (-1: no limit)",
    931 &sepadata->maxroundsroot, TRUE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
    932
    933 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxinvcuts",
    934 "maximal number of cuts investigated per iteration in a branching node",
    935 &sepadata->maxinvcuts, TRUE, DEFAULT_MAXINVCUTS, 0, INT_MAX, NULL, NULL) );
    936
    937 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxinvcutsroot",
    938 "maximal number of cuts investigated per iteration in the root node",
    939 &sepadata->maxinvcutsroot, TRUE, DEFAULT_MAXINVCUTSROOT, 0, INT_MAX, NULL, NULL) );
    940
    941 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxconfsdelay",
    942 "delay separation if number of conflict graph edges is larger than predefined value (-1: no limit)",
    943 &sepadata->maxconfsdelay, TRUE, DEFAULT_MAXCONFSDELAY, -1, INT_MAX, NULL, NULL) );
    944
    945 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrank",
    946 "maximal rank of a disj. cut that could not be scaled to integral coefficients (-1: unlimited)",
    947 &sepadata->maxrank, FALSE, DEFAULT_MAXRANK, -1, INT_MAX, NULL, NULL) );
    948
    949 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/maxrankintegral",
    950 "maximal rank of a disj. cut that could be scaled to integral coefficients (-1: unlimited)",
    951 &sepadata->maxrankintegral, FALSE, DEFAULT_MAXRANKINTEGRAL, -1, INT_MAX, NULL, NULL) );
    952
    953 SCIP_CALL( SCIPaddRealParam(scip, "separating/" SEPA_NAME "/maxweightrange",
    954 "maximal valid range max(|weights|)/min(|weights|) of row weights",
    955 &sepadata->maxweightrange, TRUE, DEFAULT_MAXWEIGHTRANGE, 1.0, SCIP_REAL_MAX, NULL, NULL) );
    956
    957 return SCIP_OKAY;
    958}
    SCIP_Real * r
    Definition: circlepacking.c:59
    constraint handler for SOS type 1 constraints
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #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_FORMAT
    Definition: def.h:157
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_DIGRAPH * SCIPgetConflictgraphSOS1(SCIP_CONSHDLR *conshdlr)
    Definition: cons_sos1.c:10872
    int SCIPgetNSOS1Vars(SCIP_CONSHDLR *conshdlr)
    Definition: cons_sos1.c:10890
    SCIP_VAR * SCIPnodeGetVarSOS1(SCIP_DIGRAPH *conflictgraph, int node)
    Definition: cons_sos1.c:10955
    int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
    Definition: misc.c:7881
    int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
    Definition: misc.c:7863
    int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
    Definition: misc.c:7896
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    #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
    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 SCIPcolGetPrimsol(SCIP_COL *col)
    Definition: lp.c:17379
    SCIP_Real SCIPcolGetUb(SCIP_COL *col)
    Definition: lp.c:17356
    SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
    Definition: lp.c:17414
    int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4782
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:117
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    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_Bool SCIPisLPSolBasic(SCIP *scip)
    Definition: scip_lp.c:673
    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 SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1581
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1957
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1604
    SCIP_RETCODE SCIPmakeRowIntegral(SCIP *scip, SCIP_ROW *row, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool usecontvars, SCIP_Bool *success)
    Definition: scip_lp.c:1790
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1429
    int SCIProwGetRank(SCIP_ROW *row)
    Definition: lp.c:17775
    void SCIProwChgRank(SCIP_ROW *row, int rank)
    Definition: lp.c:17928
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
    Definition: lp.c:17734
    SCIP_RETCODE SCIPsetSepaInitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINITSOL((*sepainitsol)))
    Definition: scip_sepa.c:221
    SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata)
    Definition: scip_sepa.c:115
    const char * SCIPsepaGetName(SCIP_SEPA *sepa)
    Definition: sepa.c:746
    int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
    Definition: sepa.c:893
    SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
    Definition: scip_sepa.c:173
    SCIP_Bool SCIPsepaWasLPDelayed(SCIP_SEPA *sepa)
    Definition: sepa.c:1112
    SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
    Definition: sepa.c:636
    void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
    Definition: sepa.c:646
    SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
    Definition: scip_sepa.c:157
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    int SCIPgetNCutsFound(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPepsilon(SCIP *scip)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23715
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_RETCODE SCIPincludeSepaDisjunctive(SCIP *scip)
    void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    memory allocation routines
    INLINE Rational & max(Rational &r1, Rational &r2)
    public methods for managing constraints
    public methods for LP management
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for separators
    public methods for problem variables
    public methods for constraint handler plugins and constraints
    public methods for cuts and aggregation rows
    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 separator plugins
    public methods for solutions
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    #define SEPA_PRIORITY
    #define DEFAULT_MAXINVCUTS
    #define SEPA_DELAY
    #define DEFAULT_MAXWEIGHTRANGE
    static SCIP_DECL_SEPAFREE(sepaFreeDisjunctive)
    #define DEFAULT_MAXINVCUTSROOT
    static SCIP_DECL_SEPAEXECLP(sepaExeclpDisjunctive)
    #define DEFAULT_STRENGTHEN
    #define SEPA_DESC
    #define DEFAULT_MAXRANKINTEGRAL
    #define MAKECONTINTEGRAL
    #define DEFAULT_MAXROUNDSROOT
    #define SEPA_USESSUBSCIP
    #define DEFAULT_MAXCONFSDELAY
    #define DEFAULT_MAXDEPTH
    static SCIP_RETCODE getSimplexCoefficients(SCIP *scip, SCIP_ROW **rows, int nrows, SCIP_COL **cols, int ncols, SCIP_Real *coef, SCIP_Real *binvrow, SCIP_Real *simplexcoefs, int *nonbasicnumber)
    #define DEFAULT_MAXRANK
    #define SEPA_MAXBOUNDDIST
    #define SEPA_FREQ
    #define SEPA_NAME
    static SCIP_DECL_SEPACOPY(sepaCopyDisjunctive)
    #define DEFAULT_MAXROUNDS
    static SCIP_RETCODE generateDisjCutSOS1(SCIP *scip, SCIP_SEPA *sepa, int depth, SCIP_ROW **rows, int nrows, SCIP_COL **cols, int ncols, int ndisjcuts, SCIP_Bool scale, SCIP_Bool strengthen, SCIP_Real cutlhs1, SCIP_Real cutlhs2, SCIP_Real bound1, SCIP_Real bound2, SCIP_Real *simplexcoefs1, SCIP_Real *simplexcoefs2, SCIP_Real *cutcoefs, SCIP_ROW **row, SCIP_Bool *madeintegral)
    static SCIP_DECL_SEPAEXITSOL(sepaInitsolDisjunctive)
    static int getVarRank(SCIP *scip, SCIP_Real *binvrow, SCIP_Real *rowsmaxval, SCIP_Real maxweightrange, SCIP_ROW **rows, int nrows)
    disjunctive cut separator
    @ 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
    @ SCIP_BASESTAT_ZERO
    Definition: type_lpi.h:94
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DELAYED
    Definition: type_result.h:43
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    struct SCIP_SepaData SCIP_SEPADATA
    Definition: type_sepa.h:52