Scippy

    SCIP

    Solving Constraint Integer Programs

    sepa_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-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 sepa_gomory.c
    26 * @ingroup DEFPLUGINS_SEPA
    27 * @brief Gomory MIR Cuts
    28 * @author Tobias Achterberg
    29 * @author Stefan Heinz
    30 * @author Domenico Salvagnin
    31 * @author Marc Pfetsch
    32 * @author Leona Gottwald
    33 */
    34
    35/**@todo try k-Gomory-cuts (s. Cornuejols: K-Cuts: A Variation of Gomory Mixed Integer Cuts from the LP Tableau)
    36 *
    37 * @todo Try cuts on the objective tableau row.
    38 *
    39 * @todo Also try negative basis inverse row?
    40 *
    41 * @todo It happens that the SCIPcalcMIR() function returns with the same cut for different calls. Check if this is a
    42 * bug or do not use it for the MIP below and turn off presolving and all heuristics:
    43 *
    44 * Max y
    45 * Subject to
    46 * c1: -x + y <= 1
    47 * c2: 2x + 3y <= 12
    48 * c3: 3x + 2y <= 12
    49 * Bounds
    50 * 0 <= x
    51 * 0 <= y
    52 * General
    53 * x
    54 * y
    55 * END
    56 */
    57
    58/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    59
    61#include "scip/cuts.h"
    62#include "scip/pub_lp.h"
    63#include "scip/pub_lpexact.h"
    64#include "scip/pub_message.h"
    65#include "scip/pub_misc.h"
    66#include "scip/pub_misc_sort.h"
    67#include "scip/pub_sepa.h"
    68#include "scip/pub_var.h"
    69#include "scip/scip_branch.h"
    71#include "scip/scip_cut.h"
    72#include "scip/scip_exact.h"
    73#include "scip/scip_general.h"
    74#include "scip/scip_lp.h"
    75#include "scip/scip_lpexact.h"
    76#include "scip/scip_mem.h"
    77#include "scip/scip_message.h"
    78#include "scip/scip_numerics.h"
    79#include "scip/scip_param.h"
    80#include "scip/scip_prob.h"
    82#include "scip/scip_sepa.h"
    84#include "scip/scip_tree.h"
    85#include "scip/scip_var.h"
    86#include "scip/sepa_gomory.h"
    87#include <string.h>
    88
    89#define SEPA_NAME "gomory"
    90#define SEPA_DESC "separator for Gomory mixed-integer and strong CG cuts from LP tableau rows"
    91#define SEPA_PRIORITY -1000
    92#define SEPA_FREQ 10
    93#define SEPA_MAXBOUNDDIST 1.0
    94#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
    95#define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
    96
    97#define DEFAULT_MAXROUNDS 5 /**< maximal number of gomory separation rounds per node (-1: unlimited) */
    98#define DEFAULT_MAXROUNDSROOT 10 /**< maximal number of gomory separation rounds in the root node (-1: unlimited) */
    99#define DEFAULT_MAXSEPACUTS 50 /**< maximal number of gomory cuts separated per separation round */
    100#define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of gomory cuts separated per separation round in root node */
    101#define DEFAULT_MAXRANK -1 /**< maximal rank of a gomory cut that could not be scaled to integral coefficients (-1: unlimited) */
    102#define DEFAULT_MAXRANKINTEGRAL -1 /**< maximal rank of a gomory cut that could be scaled to integral coefficients (-1: unlimited) */
    103#define DEFAULT_DYNAMICCUTS TRUE /**< should generated cuts be removed from the LP if they are no longer tight? */
    104#define DEFAULT_AWAY 0.01 /**< minimal integrality violation of a basis variable in order to try Gomory cut */
    105#define DEFAULT_MAKEINTEGRAL FALSE /**< try to scale all cuts to integral coefficients */
    106#define DEFAULT_FORCECUTS TRUE /**< if conversion to integral coefficients failed still consider the cut */
    107#define DEFAULT_SEPARATEROWS TRUE /**< separate rows with integral slack */
    108#define DEFAULT_DELAYEDCUTS FALSE /**< should cuts be added to the delayed cut pool? */
    109#define DEFAULT_SIDETYPEBASIS TRUE /**< choose side types of row (lhs/rhs) based on basis information? */
    110#define DEFAULT_TRYSTRONGCG TRUE /**< try to generate strengthened Chvatal-Gomory cuts? */
    111#define DEFAULT_GENBOTHGOMSCG TRUE /**< should both Gomory and strong CG cuts be generated (otherwise take best) */
    112#define DEFAULT_RANDSEED 53 /**< initial random seed */
    113
    114#define BOUNDSWITCH 0.9999 /**< threshold for bound switching - see SCIPcalcMIR() */
    115#define POSTPROCESS TRUE /**< apply postprocessing after MIR calculation - see SCIPcalcMIR() */
    116#define VARTYPEUSEVBDS 2 /**< We allow variable bound substitution for variables with continuous vartype only.
    117 * See SCIPcalcMIR() for more information. */
    118#define FIXINTEGRALRHS FALSE /**< try to generate an integral rhs - see SCIPcalcMIR() */
    119#define MAKECONTINTEGRAL FALSE /**< convert continuous variable to integral variables in SCIPmakeRowIntegral() */
    120
    121#define MAXAGGRLEN(nvars) (0.1*(nvars)+1000) /**< maximal length of base inequality */
    122
    123
    124/** separator data */
    125struct SCIP_SepaData
    126{
    127 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    128 SCIP_SEPA* strongcg; /**< strong CG cut separator */
    129 SCIP_SEPA* gomory; /**< gomory cut separator */
    130 SCIP_Real away; /**< minimal integrality violation of a basis variable in order to try Gomory cut */
    131 int maxrounds; /**< maximal number of gomory separation rounds per node (-1: unlimited) */
    132 int maxroundsroot; /**< maximal number of gomory separation rounds in the root node (-1: unlimited) */
    133 int maxsepacuts; /**< maximal number of gomory cuts separated per separation round */
    134 int maxsepacutsroot; /**< maximal number of gomory cuts separated per separation round in root node */
    135 int maxrank; /**< maximal rank of a gomory cut that could not be scaled to integral coefficients (-1: unlimited) */
    136 int maxrankintegral; /**< maximal rank of a gomory cut that could be scaled to integral coefficients (-1: unlimited) */
    137 int lastncutsfound; /**< total number of cuts found after last call of separator */
    138 SCIP_Bool dynamiccuts; /**< should generated cuts be removed from the LP if they are no longer tight? */
    139 SCIP_Bool makeintegral; /**< try to scale all cuts to integral coefficients */
    140 SCIP_Bool forcecuts; /**< if conversion to integral coefficients failed still consider the cut */
    141 SCIP_Bool separaterows; /**< separate rows with integral slack */
    142 SCIP_Bool delayedcuts; /**< should cuts be added to the delayed cut pool? */
    143 SCIP_Bool sidetypebasis; /**< choose side types of row (lhs/rhs) based on basis information? */
    144 SCIP_Bool trystrongcg; /**< try to generate strengthened Chvatal-Gomory cuts? */
    145 SCIP_Bool genbothgomscg; /**< should both Gomory and strong CG cuts be generated (otherwise take best) */
    146};
    147
    148
    149/** returns TRUE if the cut can be taken, otherwise FALSE if there some numerical evidences */
    150static
    152 SCIP* scip, /**< SCIP data structure */
    153 SCIP_SEPADATA* sepadata, /**< data of the separator */
    154 SCIP_ROW* cut, /**< cut to check */
    155 SCIP_Longint maxdnom, /**< maximal denominator to use for scaling */
    156 SCIP_Real maxscale, /**< maximal scaling factor */
    157 SCIP_Bool* useful /**< pointer to store if the cut is useful */
    158 )
    159{
    160 SCIP_Bool madeintegral = FALSE;
    161
    162 assert(useful != NULL);
    163
    164 *useful = FALSE;
    165
    166 if( sepadata->makeintegral && SCIPgetRowNumIntCols(scip, cut) == SCIProwGetNNonz(cut) )
    167 {
    168 /* try to scale the cut to integral values */
    170 maxdnom, maxscale, MAKECONTINTEGRAL, &madeintegral) );
    171
    172 if( !madeintegral && !sepadata->forcecuts )
    173 return SCIP_OKAY;
    174
    175 /* in case the right hand side is plus infinity (due to scaling) the cut is useless so we are not taking it at all */
    176 if( madeintegral && SCIPisInfinity(scip, SCIProwGetRhs(cut)) )
    177 return SCIP_OKAY;
    178 }
    179
    180 /* discard integral cut if the rank is too high */
    181 if( madeintegral && sepadata->maxrankintegral != -1 && (SCIProwGetRank(cut) > sepadata->maxrankintegral) )
    182 return SCIP_OKAY;
    183
    184 /* discard cut if the rank is too high */
    185 if( !madeintegral && (sepadata->maxrank != -1) && (SCIProwGetRank(cut) > sepadata->maxrank) )
    186 return SCIP_OKAY;
    187
    188 *useful = TRUE;
    189
    190 return SCIP_OKAY;
    191}
    192
    193
    194/** add cut */
    195static
    197 SCIP* scip, /**< SCIP instance */
    198 SCIP_SEPADATA* sepadata, /**< separator data */
    199 SCIP_VAR** vars, /**< array of variables */
    200 int c, /**< index of basic variable (< 0 for slack variables) */
    201 SCIP_Longint maxdnom, /**< maximal denominator to use for scaling */
    202 SCIP_Real maxscale, /**< maximal scaling factor */
    203 int cutnnz, /**< number of nonzeros in cut */
    204 int* cutinds, /**< variable indices in cut */
    205 SCIP_Real* cutcoefs, /**< cut cofficients */
    206 SCIP_Real cutefficacy, /**< cut efficacy */
    207 SCIP_Real cutrhs, /**< rhs of cut */
    208 SCIP_Bool cutislocal, /**< whether cut is local */
    209 int cutrank, /**< rank of cut */
    210 SCIP_Bool strongcg, /**< whether the cut arises from the strong-CG procedure */
    211 SCIP_Bool* cutoff, /**< pointer to store whether a cutoff appeared */
    212 int* naddedcuts /**< pointer to store number of added cuts */
    213 )
    214{
    215 int j;
    216
    217 assert(scip != NULL);
    218 assert(cutoff != NULL);
    219 assert(naddedcuts != NULL);
    220
    221 if( cutnnz == 0 && SCIPisFeasNegative(scip, cutrhs) && !SCIPisExact(scip) ) /*lint !e644*/
    222 {
    223 SCIPdebugMsg(scip, " -> gomory cut detected infeasibility with cut 0 <= %g.\n", cutrhs);
    224 *cutoff = TRUE;
    225 return SCIP_OKAY;
    226 }
    227
    228 /* Only take efficient cuts, except for cuts with one non-zero coefficient (= bound
    229 * changes); the latter cuts will be handled internally in sepastore. */
    230 if( SCIPisEfficacious(scip, cutefficacy) || ( cutnnz == 1 && SCIPisFeasPositive(scip, cutefficacy) ) )
    231 {
    232 SCIP_ROW* cut;
    233 SCIP_SEPA* cutsepa;
    234 char cutname[SCIP_MAXSTRLEN];
    235 int v;
    236
    237 /* construct cut name */
    238 if( strongcg )
    239 {
    240 cutsepa = sepadata->strongcg;
    241
    242 if( c >= 0 )
    243 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "scg%" SCIP_LONGINT_FORMAT "_x%d", SCIPgetNLPs(scip), c);
    244 else
    245 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "scg%" SCIP_LONGINT_FORMAT "_s%d", SCIPgetNLPs(scip), -c-1);
    246 }
    247 else
    248 {
    249 cutsepa = sepadata->gomory;
    250
    251 if( c >= 0 )
    252 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "gom%" SCIP_LONGINT_FORMAT "_x%d", SCIPgetNLPs(scip), c);
    253 else
    254 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "gom%" SCIP_LONGINT_FORMAT "_s%d", SCIPgetNLPs(scip), -c-1);
    255 }
    256
    257 if( SCIPisExact(scip) )
    258 {
    259 SCIP_ROUNDMODE roundmode;
    260
    261 roundmode = SCIPintervalGetRoundingMode();
    263 /* postprocess cut for exact solving, i.e. change almost integer values to integer by weakening side */
    264 for( j = 0; j < cutnnz; j++ )
    265 {
    266 if( SCIPisIntegral(scip, cutcoefs[j]) )
    267 {
    268 SCIP_Real roundedval = SCIPround(scip, cutcoefs[j]);
    269 SCIP_Real delta = roundedval - cutcoefs[j];
    270 SCIP_VAR* var = vars[cutinds[j]];
    271 SCIP_Real sideval;
    272
    273 if( delta == 0 )
    274 continue;
    275
    276 if( cutislocal )
    277 sideval = delta > 0 ? SCIPvarGetUbLocal(var) : SCIPvarGetLbLocal(var);
    278 else
    279 sideval = delta > 0 ? SCIPvarGetUbGlobal(var) : SCIPvarGetLbGlobal(var);
    280
    281 if( SCIPisInfinity(scip, REALABS(sideval)) )
    282 continue;
    283
    284 cutcoefs[j]= roundedval;
    285 cutrhs += delta * sideval;
    286 }
    287 }
    289 }
    290
    291 /* create empty cut */
    292 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &cut, cutsepa, cutname, -SCIPinfinity(scip), cutrhs,
    293 cutislocal, FALSE, sepadata->dynamiccuts) );
    294
    295 /* set cut rank */
    296 SCIProwChgRank(cut, cutrank); /*lint !e644*/
    297
    298 /* cache the row extension and only flush them if the cut gets added */
    300
    301 /* collect all non-zero coefficients */
    302 for( v = 0; v < cutnnz; ++v )
    303 {
    304 SCIP_CALL( SCIPaddVarToRow(scip, cut, vars[cutinds[v]], cutcoefs[v]) );
    305 }
    306
    307 /* flush all changes before adding the cut */
    309
    310 if( SCIProwGetNNonz(cut) == 0 && !SCIPisExact(scip) )
    311 {
    312 assert( SCIPisFeasNegative(scip, cutrhs) );
    313 SCIPdebugMsg(scip, " -> gomory cut detected infeasibility with cut 0 <= %g.\n", cutrhs);
    314 *cutoff = TRUE;
    315 return SCIP_OKAY;
    316 }
    317 else if( SCIProwGetNNonz(cut) == 1 )
    318 {
    319 /* Add the bound change as cut to avoid that the LP gets modified. This would mean that the LP is not flushed
    320 * and the method SCIPgetLPBInvRow() fails; SCIP internally will apply this bound change automatically. */
    321 SCIP_CALL( SCIPaddRow(scip, cut, TRUE, cutoff) );
    322 ++(*naddedcuts);
    323 if( SCIPisCertified(scip) )
    324 {
    327 }
    328 }
    329 else
    330 {
    331 SCIP_Bool useful;
    332
    333 assert(SCIPisInfinity(scip, -SCIProwGetLhs(cut)));
    334 assert(!SCIPisInfinity(scip, SCIProwGetRhs(cut)));
    335
    336 SCIPdebugMsg(scip, " -> %s cut <%s>: rhs=%f, eff=%f\n", strongcg ? "strong-CG" : "gomory", cutname, cutrhs, cutefficacy);
    337
    338 SCIP_CALL( evaluateCutNumerics(scip, sepadata, cut, maxdnom, maxscale, &useful) );
    339
    340 if( useful )
    341 {
    342 SCIPdebugMsg(scip, " -> found %s cut <%s>: act=%f, rhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n",
    343 strongcg ? "strong-CG" : "gomory", cutname, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut),
    347
    349
    350 if( SCIPisCutNew(scip, cut) )
    351 {
    352 /* add global cuts which are not implicit bound changes to the cut pool */
    353 if( !cutislocal )
    354 {
    355 if( sepadata->delayedcuts )
    356 {
    358 }
    359 else
    360 {
    362 }
    363 }
    364 else
    365 {
    366 /* local cuts we add to the sepastore */
    367 SCIP_CALL( SCIPaddRow(scip, cut, FALSE, cutoff) );
    368 }
    369
    370 ++(*naddedcuts);
    371
    372 /* For certification we need to create the exact representation of the row; we need to perform this here
    373 * because the certificate uses the current variable bounds; if certification is not active, we delay the
    374 * creation of the exact row until the cut is actually selected to enter the LP, see sepastore.c.
    375 *
    376 * Note that this can lead to different solving paths when solving with/without certification, because
    377 * the floating-point coefficients can change slightly during the creation of the exact row (if rational
    378 * coefficients are rounded to smaller denominators) and this may affect cut selection.
    379 */
    380 if( SCIPisCertified(scip) )
    381 {
    384
    385 if( SCIProwGetRowExact(cut) == NULL )
    386 {
    387 /**@todo delay creation of exact row for globally valid cuts */
    388 if( !cutislocal )
    389 {
    393 }
    394 else
    395 {
    397 }
    398 }
    399
    401 }
    402 }
    403 }
    404 }
    405 /* release the row */
    406 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    407 }
    408
    409 return SCIP_OKAY;
    410}
    411
    412/*
    413 * Callback methods
    414 */
    415
    416/** copy method for separator plugins (called when SCIP copies plugins) */
    417static
    418SCIP_DECL_SEPACOPY(sepaCopyGomory)
    419{ /*lint --e{715}*/
    420 assert(scip != NULL);
    421 assert(sepa != NULL);
    422 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
    423
    424 /* call inclusion method of separator */
    426
    427 return SCIP_OKAY;
    428}
    429
    430/** destructor of separator to free user data (called when SCIP is exiting) */
    431/**! [SnippetSepaFreeGomory] */
    432static
    433SCIP_DECL_SEPAFREE(sepaFreeGomory)
    434{ /*lint --e{715}*/
    435 SCIP_SEPADATA* sepadata;
    436
    437 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
    438
    439 /* free separator data */
    440 sepadata = SCIPsepaGetData(sepa);
    441 assert(sepadata != NULL);
    442
    443 SCIPfreeBlockMemory(scip, &sepadata);
    444
    445 SCIPsepaSetData(sepa, NULL);
    446
    447 return SCIP_OKAY;
    448}
    449/**! [SnippetSepaFreeGomory] */
    450
    451/** initialization method of separator (called after problem was transformed) */
    452static
    453SCIP_DECL_SEPAINIT(sepaInitGomory)
    454{
    455 SCIP_SEPADATA* sepadata;
    456
    457 sepadata = SCIPsepaGetData(sepa);
    458 assert(sepadata != NULL);
    459
    460 /* create and initialize random number generator */
    461 SCIP_CALL( SCIPcreateRandom(scip, &sepadata->randnumgen, DEFAULT_RANDSEED, TRUE) );
    462
    463 return SCIP_OKAY;
    464}
    465
    466/** deinitialization method of separator (called before transformed problem is freed) */
    467static
    468SCIP_DECL_SEPAEXIT(sepaExitGomory)
    469{ /*lint --e{715}*/
    470 SCIP_SEPADATA* sepadata;
    471
    472 sepadata = SCIPsepaGetData(sepa);
    473 assert(sepadata != NULL);
    474
    475 SCIPfreeRandom(scip, &sepadata->randnumgen);
    476
    477 return SCIP_OKAY;
    478}
    479
    480
    481/** LP solution separation method of separator */
    482static
    483SCIP_DECL_SEPAEXECLP(sepaExeclpGomory)
    484{ /*lint --e{715}*/
    485 SCIP_SEPADATA* sepadata;
    486 SCIP_VAR** vars;
    487 SCIP_COL** cols;
    488 SCIP_ROW** rows;
    489 SCIP_AGGRROW* aggrrow;
    490 SCIP_VAR* var;
    491 SCIP_Real* binvrow;
    492 SCIP_Real* cutcoefs;
    493 SCIP_Real* basisfrac;
    494 SCIP_Real* cutefficacies;
    495 int* basisind;
    496 int* basisperm;
    497 int* inds;
    498 int* cutinds;
    499 int* colindsproducedcut;
    500 SCIP_Real maxscale;
    501 SCIP_Real minfrac;
    502 SCIP_Real maxfrac;
    503 SCIP_Real maxcutefficacy;
    504 SCIP_Longint maxdnom;
    505 SCIP_Bool cutoff;
    506 SCIP_Bool separatescg;
    507 SCIP_Bool separategmi;
    508 int naddedcuts;
    509 int nvars;
    510 int ncols;
    511 int nrows;
    512 int ncalls;
    513 int maxdepth;
    514 int maxsepacuts;
    515 int freq;
    516 int c;
    517 int i;
    518 int j;
    519
    520 assert(sepa != NULL);
    521 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
    522 assert(scip != NULL);
    523 assert(result != NULL);
    524
    525 *result = SCIP_DIDNOTRUN;
    526
    527 sepadata = SCIPsepaGetData(sepa);
    528 assert(sepadata != NULL);
    529
    530 ncalls = SCIPsepaGetNCallsAtNode(sepa);
    531
    532 minfrac = sepadata->away;
    533 maxfrac = 1.0 - sepadata->away;
    534
    535 /* only call separator, if we are not close to terminating */
    536 if( SCIPisStopped(scip) )
    537 return SCIP_OKAY;
    538
    539 /* only call the gomory cut separator a given number of times at each node */
    540 if( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
    541 || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
    542 return SCIP_OKAY;
    543
    544 /* only call separator, if an optimal LP solution is at hand */
    546 return SCIP_OKAY;
    547
    548 /* only call separator, if the LP solution is basic */
    549 if( !SCIPisLPSolBasic(scip) )
    550 return SCIP_OKAY;
    551
    552 /* only call separator, if there are fractional variables */
    553 if( SCIPgetNLPBranchCands(scip) == 0 )
    554 return SCIP_OKAY;
    555
    556 /* check whether strong CG cuts should be separated */
    557 freq = SCIPsepaGetFreq(sepadata->strongcg);
    558 if( freq > 0 )
    559 separatescg = (depth % freq == 0);
    560 else
    561 separatescg = (freq == depth);
    562
    563 /* check whether Gomory MI cuts should be separated */
    564 freq = SCIPsepaGetFreq(sepadata->gomory);
    565 if( freq > 0 )
    566 separategmi = (depth % freq == 0);
    567 else
    568 separategmi = (freq == depth);
    569
    570 if( !separatescg && !separategmi )
    571 return SCIP_OKAY;
    572
    573 /* get variables data */
    574 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    575
    576 /* get LP data */
    577 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    578 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    579 if( ncols == 0 || nrows == 0 )
    580 return SCIP_OKAY;
    581
    582 /* set the maximal denominator in rational representation of gomory cut and the maximal scale factor to
    583 * scale resulting cut to integral values to avoid numerical instabilities
    584 */
    585 /**@todo find better but still stable gomory cut settings: look at dcmulti, gesa3, khb0525, misc06, p2756 */
    586 maxdepth = SCIPgetMaxDepth(scip);
    587 if( depth == 0 )
    588 {
    589 maxdnom = 1000;
    590 maxscale = 1000.0;
    591 }
    592 else if( depth <= maxdepth/4 )
    593 {
    594 maxdnom = 1000;
    595 maxscale = 1000.0;
    596 }
    597 else if( depth <= maxdepth/2 )
    598 {
    599 maxdnom = 100;
    600 maxscale = 100.0;
    601 }
    602 else
    603 {
    604 maxdnom = 10;
    605 maxscale = 10.0;
    606 }
    607
    608 /* allocate temporary memory */
    609 SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, nvars) );
    610 SCIP_CALL( SCIPallocClearBufferArray(scip, &cutinds, nvars) );
    611 SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
    612 SCIP_CALL( SCIPallocBufferArray(scip, &basisperm, nrows) );
    613 SCIP_CALL( SCIPallocBufferArray(scip, &basisfrac, nrows) );
    614 SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
    615 SCIP_CALL( SCIPallocBufferArray(scip, &inds, nrows) );
    616 SCIP_CALL( SCIPallocBufferArray(scip, &cutefficacies, nrows) );
    617 SCIP_CALL( SCIPallocBufferArray(scip, &colindsproducedcut, nrows) );
    618 SCIP_CALL( SCIPaggrRowCreate(scip, &aggrrow) );
    619
    620 /* get basis indices */
    621 SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
    622
    623 for( i = 0; i < nrows; ++i )
    624 {
    625 SCIP_Real frac = 0.0;
    626
    627 c = basisind[i];
    628 cutefficacies[i] = 0.0;
    629
    630 basisperm[i] = i;
    631
    632 colindsproducedcut[i] = -1;
    633
    634 if( c >= 0 )
    635 {
    636 assert(c < ncols);
    637 var = SCIPcolGetVar(cols[c]);
    639 {
    640 frac = SCIPfeasFrac(scip, SCIPcolGetPrimsol(cols[c]));
    641 frac = MIN(frac, 1.0 - frac);
    642 }
    643 }
    644 else if( sepadata->separaterows )
    645 {
    646 SCIP_ROW* row;
    647
    648 assert(0 <= -c-1 && -c-1 < nrows);
    649 row = rows[-c-1];
    650 /* We allow separating on rows with a 'slack' implied integral variable */
    652 {
    654 frac = MIN(frac, 1.0 - frac);
    655 }
    656 }
    657
    658 if( frac >= minfrac )
    659 {
    660 /* slightly change fractionality to have random order for equal fractions */
    661 basisfrac[i] = frac + SCIPrandomGetReal(sepadata->randnumgen, -1e-6, 1e-6);
    662 }
    663 else
    664 {
    665 basisfrac[i] = 0.0;
    666 }
    667 }
    668
    669 /* sort basis indices by fractionality */
    670 SCIPsortDownRealInt(basisfrac, basisperm, nrows);
    671
    672 /* get the maximal number of cuts allowed in a separation round */
    673 if( depth == 0 )
    674 maxsepacuts = sepadata->maxsepacutsroot;
    675 else
    676 maxsepacuts = sepadata->maxsepacuts;
    677
    678 SCIPdebugMsg(scip, "searching gomory cuts: %d cols, %d rows, maxdnom=%" SCIP_LONGINT_FORMAT ", maxscale=%g, maxcuts=%d\n",
    679 ncols, nrows, maxdnom, maxscale, maxsepacuts);
    680
    681 cutoff = FALSE;
    682 naddedcuts = 0;
    683
    684 /* for all basic columns belonging to integer variables, try to generate a gomory cut */
    685 for( i = 0; i < nrows && naddedcuts < maxsepacuts && !SCIPisStopped(scip) && !cutoff; ++i )
    686 {
    687 SCIP_Real cutrhs;
    688 SCIP_Real cutefficacy = 0.0;
    689 SCIP_Bool success;
    690 SCIP_Bool cutislocal;
    691 SCIP_Bool strongcgsuccess = FALSE;
    692 int ninds = -1;
    693 int cutnnz;
    694 int cutrank;
    695
    696 if( basisfrac[i] == 0.0 )
    697 break;
    698
    699 j = basisperm[i];
    700 c = basisind[j];
    701
    702 /* get the row of B^-1 for this basic integer variable with fractional solution value */
    703 SCIP_CALL( SCIPgetLPBInvRow(scip, j, binvrow, inds, &ninds) );
    704
    705 SCIP_CALL( SCIPaggrRowSumRows(scip, aggrrow, binvrow, inds, ninds,
    706 sepadata->sidetypebasis, allowlocal, SCIPallowNegSlack(scip) ? 2 : 0, (int) MAXAGGRLEN(nvars), &success) );
    707
    708 if( !success )
    709 continue;
    710
    711 /* try to create a strong CG cut out of the aggregation row */
    712 if( separatescg && !SCIPisExact(scip) )
    713 {
    714 SCIP_CALL( SCIPcalcStrongCG(scip, NULL, POSTPROCESS, BOUNDSWITCH, VARTYPEUSEVBDS, allowlocal, minfrac, maxfrac,
    715 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, &cutrank, &cutislocal, &strongcgsuccess) );
    716
    717 /* if we want to generate both cuts, add cut and reset cutefficacy and strongcgsuccess */
    718 if( strongcgsuccess && sepadata->genbothgomscg )
    719 {
    720 assert(allowlocal || !cutislocal); /*lint !e644*/
    721 SCIP_CALL( addCut(scip, sepadata, vars, c, maxdnom, maxscale, cutnnz, cutinds, cutcoefs, cutefficacy, cutrhs,
    722 cutislocal, cutrank, TRUE, &cutoff, &naddedcuts) );
    723 if( c >= 0 )
    724 {
    725 cutefficacies[i] = cutefficacy;
    726 colindsproducedcut[i] = c;
    727 }
    728 cutefficacy = 0.0;
    729 strongcgsuccess = FALSE;
    730 if( cutoff )
    731 break;
    732 }
    733 }
    734 /* try to create Gomory cut out of the aggregation row */
    735 if( separategmi )
    736 {
    737 /* SCIPcalcMIR will only override the cut if its efficacy is larger than the one of the strongcg cut */
    739 minfrac, maxfrac, 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, &cutrank, &cutislocal, &success) );
    740
    741 if( success || strongcgsuccess )
    742 {
    743 assert(allowlocal || !cutislocal); /*lint !e644*/
    744 if( success )
    745 strongcgsuccess = FALSE; /* Set strongcgsuccess to FALSE, since the MIR cut has overriden the strongcg cut. */
    746
    747 SCIP_CALL( addCut(scip, sepadata, vars, c, maxdnom, maxscale, cutnnz, cutinds, cutcoefs, cutefficacy, cutrhs,
    748 cutislocal, cutrank, strongcgsuccess, &cutoff, &naddedcuts) );
    749 if( c >= 0 )
    750 {
    751 cutefficacies[i] = cutefficacy;
    752 colindsproducedcut[i] = c;
    753 }
    754 }
    755 }
    756 if( SCIPisCertified(scip) )
    757 {
    760 }
    761 }
    762
    763 /* Add normalized efficacy GMI statistics to history */
    764 maxcutefficacy = 0.0;
    765 for( i = 0; i < nrows; ++i )
    766 {
    767 if( cutefficacies[i] > maxcutefficacy && colindsproducedcut[i] >= 0 )
    768 {
    769 maxcutefficacy = cutefficacies[i];
    770 }
    771 }
    772
    773 for( i = 0; i < nrows; ++i )
    774 {
    775 if( colindsproducedcut[i] >= 0 && SCIPisEfficacious(scip, cutefficacies[i]) )
    776 {
    777 assert( maxcutefficacy > 0.0 );
    778 var = SCIPcolGetVar(cols[colindsproducedcut[i]]);
    779 SCIP_CALL( SCIPsetVarLastGMIScore(scip, var, cutefficacies[i] / maxcutefficacy) );
    780 SCIP_CALL( SCIPincVarGMISumScore(scip, var, cutefficacies[i] / maxcutefficacy) );
    781 }
    782 }
    783
    784 /* free temporary memory */
    785 SCIPaggrRowFree(scip, &aggrrow);
    786 SCIPfreeBufferArray(scip, &colindsproducedcut);
    787 SCIPfreeBufferArray(scip, &cutefficacies);
    789 SCIPfreeBufferArray(scip, &binvrow);
    790 SCIPfreeBufferArray(scip, &basisfrac);
    791 SCIPfreeBufferArray(scip, &basisperm);
    792 SCIPfreeBufferArray(scip, &basisind);
    793 SCIPfreeBufferArray(scip, &cutinds);
    794 SCIPfreeBufferArray(scip, &cutcoefs);
    795
    796 SCIPdebugMsg(scip, "end searching gomory cuts: found %d cuts\n", naddedcuts);
    797
    798 sepadata->lastncutsfound = SCIPgetNCutsFound(scip);
    799
    800 /* evaluate the result of the separation */
    801 if( cutoff )
    802 *result = SCIP_CUTOFF;
    803 else if ( naddedcuts > 0 )
    804 *result = SCIP_SEPARATED;
    805 else
    806 *result = SCIP_DIDNOTFIND;
    807
    808 return SCIP_OKAY;
    809}
    810
    811
    812/*
    813 * separator specific interface methods
    814 */
    815
    816/** LP solution separation method of dummy separator */
    817static
    818SCIP_DECL_SEPAEXECLP(sepaExeclpDummy)
    819{ /*lint --e{715}*/
    820 assert( result != NULL );
    821
    822 *result = SCIP_DIDNOTRUN;
    823
    824 return SCIP_OKAY;
    825}
    826
    827/** arbitrary primal solution separation method of dummy separator */
    828static
    829SCIP_DECL_SEPAEXECSOL(sepaExecsolDummy)
    830{ /*lint --e{715}*/
    831 assert( result != NULL );
    832
    833 *result = SCIP_DIDNOTRUN;
    834
    835 return SCIP_OKAY;
    836}
    837
    838/** creates the Gomory MIR cut separator and includes it in SCIP */
    840 SCIP* scip /**< SCIP data structure */
    841 )
    842{
    843 SCIP_SEPADATA* sepadata;
    844 SCIP_SEPA* sepa;
    845
    846 /* create separator data */
    847 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
    848 sepadata->lastncutsfound = 0;
    849
    850 /* include separator */
    853 sepaExeclpGomory, NULL,
    854 sepadata) );
    855
    856 assert(sepa != NULL);
    857
    858 /* gomory is safe to use in exact solving mode */
    859 SCIPsepaMarkExact(sepa);
    860
    861 SCIP_CALL( SCIPincludeSepaBasic(scip, &sepadata->strongcg, "strongcg", "separator for strong CG cuts", -100000, SEPA_FREQ, 0.0,
    862 SEPA_USESSUBSCIP, FALSE, sepaExeclpDummy, sepaExecsolDummy, NULL) );
    863 assert(sepadata->strongcg != NULL);
    864
    865 SCIP_CALL( SCIPincludeSepaBasic(scip, &sepadata->gomory, "gomorymi", "separator for Gomory mixed-integer cuts", -100000, SEPA_FREQ, 0.0,
    866 SEPA_USESSUBSCIP, FALSE, sepaExeclpDummy, sepaExecsolDummy, NULL) );
    867 assert(sepadata->gomory != NULL);
    868
    869 /* set non-NULL pointers to callback methods */
    870 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyGomory) );
    871 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGomory) );
    872 SCIP_CALL( SCIPsetSepaInit(scip, sepa, sepaInitGomory) );
    873 SCIP_CALL( SCIPsetSepaExit(scip, sepa, sepaExitGomory) );
    874
    875 /* mark main separator as a parent */
    877
    878 /* set pointer from child separators to main separator */
    879 SCIPsetSepaParentsepa(scip, sepadata->strongcg, sepa);
    880 SCIPsetSepaParentsepa(scip, sepadata->gomory, sepa);
    881
    882 /* add separator parameters */
    884 "separating/gomory/maxrounds",
    885 "maximal number of gomory separation rounds per node (-1: unlimited)",
    886 &sepadata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
    888 "separating/gomory/maxroundsroot",
    889 "maximal number of gomory separation rounds in the root node (-1: unlimited)",
    890 &sepadata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
    892 "separating/gomory/maxsepacuts",
    893 "maximal number of gomory cuts separated per separation round",
    894 &sepadata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
    896 "separating/gomory/maxsepacutsroot",
    897 "maximal number of gomory cuts separated per separation round in the root node",
    898 &sepadata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
    900 "separating/gomory/maxrank",
    901 "maximal rank of a gomory cut that could not be scaled to integral coefficients (-1: unlimited)",
    902 &sepadata->maxrank, FALSE, DEFAULT_MAXRANK, -1, INT_MAX, NULL, NULL) );
    904 "separating/gomory/maxrankintegral",
    905 "maximal rank of a gomory cut that could be scaled to integral coefficients (-1: unlimited)",
    906 &sepadata->maxrankintegral, FALSE, DEFAULT_MAXRANKINTEGRAL, -1, INT_MAX, NULL, NULL) );
    908 "separating/gomory/away",
    909 "minimal integrality violation of a basis variable in order to try Gomory cut",
    910 &sepadata->away, FALSE, DEFAULT_AWAY, 1e-4, 0.5, NULL, NULL) );
    912 "separating/gomory/dynamiccuts",
    913 "should generated cuts be removed from the LP if they are no longer tight?",
    914 &sepadata->dynamiccuts, FALSE, DEFAULT_DYNAMICCUTS, NULL, NULL) );
    916 "separating/gomory/makeintegral",
    917 "try to scale cuts to integral coefficients",
    918 &sepadata->makeintegral, TRUE, DEFAULT_MAKEINTEGRAL, NULL, NULL) );
    920 "separating/gomory/forcecuts",
    921 "if conversion to integral coefficients failed still consider the cut",
    922 &sepadata->forcecuts, TRUE, DEFAULT_FORCECUTS, NULL, NULL) );
    924 "separating/gomory/separaterows",
    925 "separate rows with integral slack",
    926 &sepadata->separaterows, TRUE, DEFAULT_SEPARATEROWS, NULL, NULL) );
    928 "separating/gomory/delayedcuts",
    929 "should cuts be added to the delayed cut pool?",
    930 &sepadata->delayedcuts, TRUE, DEFAULT_DELAYEDCUTS, NULL, NULL) );
    932 "separating/gomory/sidetypebasis",
    933 "choose side types of row (lhs/rhs) based on basis information?",
    934 &sepadata->sidetypebasis, TRUE, DEFAULT_SIDETYPEBASIS, NULL, NULL) );
    936 "separating/gomory/trystrongcg",
    937 "try to generate strengthened Chvatal-Gomory cuts?",
    938 &sepadata->trystrongcg, TRUE, DEFAULT_TRYSTRONGCG, NULL, NULL) );
    940 "separating/gomory/genbothgomscg",
    941 "Should both Gomory and strong CG cuts be generated (otherwise take best)?",
    942 &sepadata->genbothgomscg, TRUE, DEFAULT_GENBOTHGOMSCG, NULL, NULL) );
    943
    944 return SCIP_OKAY;
    945}
    methods for the aggregation rows
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    #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 SCIPgetNLPBranchCands(SCIP *scip)
    Definition: scip_branch.c:436
    SCIP_RETCODE SCIPfreeCertificateActiveMirInfo(SCIP *scip)
    SCIP_RETCODE SCIPstoreCertificateActiveAggrInfo(SCIP *scip, SCIP_ROW *row)
    SCIP_Bool SCIPisCertified(SCIP *scip)
    SCIP_RETCODE SCIPfreeCertificateActiveAggrInfo(SCIP *scip)
    SCIP_RETCODE SCIPcertifyMirCut(SCIP *scip, SCIP_ROW *row)
    SCIP_RETCODE SCIPstoreCertificateActiveMirInfo(SCIP *scip, SCIP_ROW *row)
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
    Definition: lp.c:17379
    SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:336
    SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:94
    SCIP_RETCODE SCIPcalcMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, int vartypeusevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
    Definition: cuts.c:7923
    SCIP_RETCODE SCIPaggrRowCreate(SCIP *scip, SCIP_AGGRROW **aggrrow)
    Definition: cuts.c:2668
    SCIP_Bool SCIPisCutNew(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:318
    SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
    Definition: scip_cut.c:135
    SCIP_RETCODE SCIPcalcStrongCG(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, int vartypeusevbds, SCIP_Bool allowlocal, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
    Definition: cuts.c:13281
    void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
    Definition: cuts.c:2700
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPaggrRowSumRows(SCIP *scip, SCIP_AGGRROW *aggrrow, SCIP_Real *weights, int *rowinds, int nrowinds, SCIP_Bool sidetypebasis, SCIP_Bool allowlocal, int negslack, int maxaggrlen, SCIP_Bool *valid)
    Definition: cuts.c:3523
    SCIP_RETCODE SCIPdelPoolCut(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:356
    SCIP_RETCODE SCIPaddDelayedPoolCut(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:616
    SCIP_Bool SCIPallowNegSlack(SCIP *scip)
    Definition: scip_exact.c:212
    SCIP_Bool SCIPisExact(SCIP *scip)
    Definition: scip_exact.c:193
    void SCIPintervalSetRoundingModeUpwards(void)
    SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
    void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
    int SCIP_ROUNDMODE
    Definition: intervalarith.h:65
    SCIP_RETCODE SCIPcreateRowExactFromRow(SCIP *scip, SCIP_ROW *fprow)
    Definition: scip_lpexact.c:285
    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_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 SCIPallocClearBufferArray(scip, ptr, num)
    Definition: scip_mem.h:126
    #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_Bool SCIProwIsIntegral(SCIP_ROW *row)
    Definition: lp.c:17785
    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_Bool SCIProwIsModifiable(SCIP_ROW *row)
    Definition: lp.c:17805
    SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1581
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1957
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
    Definition: lp.c:17662
    SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1604
    int SCIPgetRowNumImpliedIntCols(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1850
    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_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 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_ROWEXACT * SCIProwGetRowExact(SCIP_ROW *row)
    Definition: lp.c:17959
    int SCIPgetRowNumIntCols(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1832
    SCIP_RETCODE SCIPsetSepaExit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXIT((*sepaexit)))
    Definition: scip_sepa.c:205
    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
    int SCIPsepaGetFreq(SCIP_SEPA *sepa)
    Definition: sepa.c:790
    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
    void SCIPsepaMarkExact(SCIP_SEPA *sepa)
    Definition: sepa.c:811
    SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
    Definition: sepa.c:636
    void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
    Definition: sepa.c:646
    void SCIPsetSepaIsParentsepa(SCIP *scip, SCIP_SEPA *sepa)
    Definition: scip_sepa.c:309
    SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
    Definition: scip_sepa.c:157
    void SCIPsetSepaParentsepa(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPA *parentsepa)
    Definition: scip_sepa.c:324
    SCIP_RETCODE SCIPsetSepaInit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINIT((*sepainit)))
    Definition: scip_sepa.c:189
    int SCIPgetMaxDepth(SCIP *scip)
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    int SCIPgetNCutsFound(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFrac(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPepsilon(SCIP *scip)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_RETCODE SCIPincVarGMISumScore(SCIP *scip, SCIP_VAR *var, SCIP_Real gmieff)
    Definition: scip_var.c:12375
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPsetVarLastGMIScore(SCIP *scip, SCIP_VAR *var, SCIP_Real gmieff)
    Definition: scip_var.c:12429
    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)
    SCIP_RETCODE SCIPincludeSepaGomory(SCIP *scip)
    Definition: sepa_gomory.c:839
    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
    public methods for LP management
    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 branching rule plugins and branching
    public methods for certified solving
    public methods for cuts and aggregation rows
    public methods for exact solving
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for random numbers
    public methods for separator plugins
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    #define SEPA_PRIORITY
    Definition: sepa_gomory.c:91
    static SCIP_RETCODE addCut(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_VAR **vars, int c, SCIP_Longint maxdnom, SCIP_Real maxscale, int cutnnz, int *cutinds, SCIP_Real *cutcoefs, SCIP_Real cutefficacy, SCIP_Real cutrhs, SCIP_Bool cutislocal, int cutrank, SCIP_Bool strongcg, SCIP_Bool *cutoff, int *naddedcuts)
    Definition: sepa_gomory.c:196
    static SCIP_DECL_SEPAEXECLP(sepaExeclpGomory)
    Definition: sepa_gomory.c:483
    static SCIP_DECL_SEPAEXIT(sepaExitGomory)
    Definition: sepa_gomory.c:468
    #define DEFAULT_TRYSTRONGCG
    Definition: sepa_gomory.c:110
    #define BOUNDSWITCH
    Definition: sepa_gomory.c:114
    #define SEPA_DELAY
    Definition: sepa_gomory.c:95
    #define DEFAULT_DYNAMICCUTS
    Definition: sepa_gomory.c:103
    #define DEFAULT_MAKEINTEGRAL
    Definition: sepa_gomory.c:105
    #define POSTPROCESS
    Definition: sepa_gomory.c:115
    #define SEPA_DESC
    Definition: sepa_gomory.c:90
    #define DEFAULT_MAXRANKINTEGRAL
    Definition: sepa_gomory.c:102
    static SCIP_DECL_SEPAFREE(sepaFreeGomory)
    Definition: sepa_gomory.c:433
    #define MAKECONTINTEGRAL
    Definition: sepa_gomory.c:119
    #define DEFAULT_MAXROUNDSROOT
    Definition: sepa_gomory.c:98
    #define SEPA_USESSUBSCIP
    Definition: sepa_gomory.c:94
    #define DEFAULT_DELAYEDCUTS
    Definition: sepa_gomory.c:108
    #define VARTYPEUSEVBDS
    Definition: sepa_gomory.c:116
    #define DEFAULT_SIDETYPEBASIS
    Definition: sepa_gomory.c:109
    #define FIXINTEGRALRHS
    Definition: sepa_gomory.c:118
    static SCIP_DECL_SEPACOPY(sepaCopyGomory)
    Definition: sepa_gomory.c:418
    #define DEFAULT_MAXSEPACUTSROOT
    Definition: sepa_gomory.c:100
    #define DEFAULT_MAXRANK
    Definition: sepa_gomory.c:101
    #define SEPA_MAXBOUNDDIST
    Definition: sepa_gomory.c:93
    static SCIP_DECL_SEPAINIT(sepaInitGomory)
    Definition: sepa_gomory.c:453
    static SCIP_RETCODE evaluateCutNumerics(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_ROW *cut, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool *useful)
    Definition: sepa_gomory.c:151
    #define DEFAULT_AWAY
    Definition: sepa_gomory.c:104
    #define DEFAULT_FORCECUTS
    Definition: sepa_gomory.c:106
    #define SEPA_FREQ
    Definition: sepa_gomory.c:92
    #define DEFAULT_RANDSEED
    Definition: sepa_gomory.c:112
    #define MAXAGGRLEN(nvars)
    Definition: sepa_gomory.c:121
    static SCIP_DECL_SEPAEXECSOL(sepaExecsolDummy)
    Definition: sepa_gomory.c:829
    #define DEFAULT_MAXSEPACUTS
    Definition: sepa_gomory.c:99
    #define SEPA_NAME
    Definition: sepa_gomory.c:89
    #define DEFAULT_MAXROUNDS
    Definition: sepa_gomory.c:97
    #define DEFAULT_SEPARATEROWS
    Definition: sepa_gomory.c:107
    #define DEFAULT_GENBOTHGOMSCG
    Definition: sepa_gomory.c:111
    Gomory MIR Cuts.
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    struct SCIP_SepaData SCIP_SEPADATA
    Definition: type_sepa.h:52
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71