Scippy

    SCIP

    Solving Constraint Integer Programs

    sepa_cgmip.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/* #define SCIP_WRITEPROB */
    25/* #define SCIP_OUTPUT */
    26/**@file sepa_cgmip.c
    27 * @ingroup DEFPLUGINS_SEPA
    28 * @brief Chvatal-Gomory cuts computed via a sub-MIP
    29 * @author Marc Pfetsch
    30 *
    31 * Separate Chvátal-Gomory cuts using a sub-MIP. The approach is based on the following papers.
    32 *
    33 * M. Fischetti and A. Lodi@n
    34 * Optimizing over the first Chvátal closure,@n
    35 * in: M. Jünger and V. Kaibel (eds.) Integer Programming and Combinatorial Optimization IPCO 2005,@n
    36 * LNCS 3509, pp. 12-22. Springer, Berlin Heidelberg New York (2005)
    37 *
    38 * M. Fischetti and A. Lodi@n
    39 * Optimizing over the first Chvátal closure,@n
    40 * Mathematical Programming 110, 3-20 (2007)
    41 *
    42 * P. Bonami, G. Cornuéjols, S. Dash, M. Fischetti, and A. Lodi@n
    43 * Projected Chvátal-Gomory cuts for mixed integer linear programs,@n
    44 * Mathematical Programming 113, No. 2 (2008)
    45 *
    46 *
    47 * There are several possibilities to generate the final cut:
    48 *
    49 * - The CMIR-routines of SCIP can be used (if @p usecmir is true). One can determine which bound is
    50 * used in the rounding operation (if @p cmirownbounds is true) or let SCIP choose the best. This
    51 * version is generally numerically the most stable.
    52 * - If @p usestrongcg is true, we try to generate Strong-CG cuts (as done in sepa_strongcg.c).
    53 * - One can directly generate the CG-cut as computed (if @p usecmir and @p usestrongcg are
    54 * false). The cut is not taken from the solution of the MIP, but is recomputed, and some care (but
    55 * not as much as in the first version) has been taken to create a valid cut.
    56 *
    57 * The computation time of the separation MIP is limited as follows:
    58 * - There is a node limit (parameters @a minnodelimit and @a maxnodelimit).
    59 * - There is a time limit (parameter @a timelimit).
    60 * - If paramter @a earlyterm is true, the separation is run until the first cut that is violated is
    61 * found. (Note that these cuts are not necessarily added to the LP, because here also the norm of
    62 * the cuts are taken into account - which cannot easily be included into the separation subscip.)
    63 * Then the solution process is continued for a certain number of nodes.
    64 *
    65 * @todo Check whether one can weaken the conditions on the continuous variables.
    66 * @todo Use pointers to originating separators to sort out cuts that should not be used.
    67 *
    68 * @warning This separator should be used carefully - it may require a long separation time.
    69 */
    70
    71/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    72
    74#include "scip/cons_linear.h"
    75#include "scip/cuts.h"
    76#include "scip/pub_cons.h"
    77#include "scip/pub_lp.h"
    78#include "scip/pub_message.h"
    79#include "scip/pub_misc.h"
    80#include "scip/pub_sepa.h"
    81#include "scip/pub_var.h"
    82#include "scip/scip_branch.h"
    83#include "scip/scip_cons.h"
    84#include "scip/scip_copy.h"
    85#include "scip/scip_cut.h"
    86#include "scip/scip_general.h"
    87#include "scip/scip_lp.h"
    88#include "scip/scip_mem.h"
    89#include "scip/scip_message.h"
    90#include "scip/scip_numerics.h"
    91#include "scip/scip_param.h"
    92#include "scip/scip_prob.h"
    94#include "scip/scip_sepa.h"
    95#include "scip/scip_sol.h"
    96#include "scip/scip_solve.h"
    98#include "scip/scip_timing.h"
    99#include "scip/scip_tree.h"
    100#include "scip/scip_var.h"
    101#include "scip/scipdefplugins.h"
    102#include "scip/sepa_cgmip.h"
    103#include <string.h>
    104
    105
    106#define SEPA_NAME "cgmip"
    107#define SEPA_DESC "Chvatal-Gomory cuts via MIPs separator"
    108#define SEPA_PRIORITY -1000
    109#define SEPA_FREQ -1
    110#define SEPA_MAXBOUNDDIST 0.0
    111#define SEPA_USESSUBSCIP TRUE /**< does the separator use a secondary SCIP instance? */
    112#define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
    113
    114#define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
    115#define DEFAULT_MAXROUNDSROOT 50 /**< maximal number of separation rounds in the root node (-1: unlimited) */
    116#define DEFAULT_MAXDEPTH -1 /**< maximal depth at which the separator is applied */
    117#define DEFAULT_DECISIONTREE FALSE /**< Use decision tree to turn separation on/off? */
    118#define DEFAULT_TIMELIMIT 1e20 /**< time limit for sub-MIP (set to infinity in order to be deterministic) */
    119#define DEFAULT_MEMORYLIMIT 1e20 /**< memory limit for sub-MIP */
    120#define DEFAULT_CUTCOEFBND 1000.0 /**< bounds on the values of the coefficients in the CG-cut */
    121#define DEFAULT_MINNODELIMIT 500LL /**< minimum number of nodes considered for sub-MIP (-1: unlimited) */
    122#define DEFAULT_MAXNODELIMIT 5000LL /**< maximum number of nodes considered for sub-MIP (-1: unlimited) */
    123#define DEFAULT_ONLYACTIVEROWS FALSE /**< Use only active rows to generate cuts? */
    124#define DEFAULT_MAXROWAGE -1 /**< maximal age of rows to consider if onlyactiverows is false */
    125#define DEFAULT_ONLYRANKONE FALSE /**< Separate rank 1 inequalities w.r.t. CG-MIP separator? */
    126#define DEFAULT_ONLYINTVARS FALSE /**< Generate cuts for problems with only integer variables? */
    127#define DEFAULT_CONTCONVERT FALSE /**< Convert some integral variables to be continuous to reduce the size of the sub-MIP? */
    128#define DEFAULT_CONTCONVFRAC 0.1 /**< fraction of integral variables converted to be continuous (if contconvert) */
    129#define DEFAULT_CONTCONVMIN 100 /**< minimum number of integral variables before some are converted to be continuous */
    130#define DEFAULT_INTCONVERT FALSE /**< Convert some integral variables attaining fractional values to have integral value? */
    131#define DEFAULT_INTCONVFRAC 0.1 /**< fraction of fractional integral variables converted to have integral value (if intconvert) */
    132#define DEFAULT_INTCONVMIN 100 /**< minimum number of integral variables before some are converted to have integral value */
    133#define DEFAULT_SKIPMULTBOUNDS TRUE /**< Skip the upper bounds on the multipliers in the sub-MIP? */
    134#define DEFAULT_OBJLONE FALSE /**< Should the objective of the sub-MIP only minimize the l1-norm of the multipliers? */
    135#define DEFAULT_OBJWEIGHT 1e-03 /**< objective weight for artificial variables */
    136#define DEFAULT_OBJWEIGHTSIZE TRUE /**< Weight each row by its size? */
    137#define DEFAULT_DYNAMICCUTS TRUE /**< Should generated cuts be removed from the LP if they are no longer tight? */
    138#define DEFAULT_USECMIR TRUE /**< Use CMIR-generator (otherwise add cut directly)? */
    139#define DEFAULT_USESTRONGCG FALSE /**< Use strong CG-function to strengthen cut? */
    140#define DEFAULT_CMIROWNBOUNDS FALSE /**< Tell CMIR-generator which bounds to used in rounding? */
    141#define DEFAULT_USECUTPOOL TRUE /**< Use cutpool to store CG-cuts even if the are not efficient? */
    142#define DEFAULT_PRIMALSEPARATION TRUE /**< Only separate cuts that are tight for the best feasible solution? */
    143#define DEFAULT_EARLYTERM TRUE /**< Terminate separation if a violated (but possibly sub-optimal) cut has been found? */
    144#define DEFAULT_ADDVIOLATIONCONS FALSE /**< Add constraint to subscip that only allows violated cuts (otherwise add obj. limit)?*/
    145#define DEFAULT_ADDVIOLCONSHDLR FALSE /**< Add constraint handler to filter out violated cuts? */
    146#define DEFAULT_CONSHDLRUSENORM TRUE /**< Should the violation constraint handler use the norm of a cut to check for feasibility? */
    147#define DEFAULT_USEOBJUB FALSE /**< Use upper bound on objective function (via primal solution)? */
    148#define DEFAULT_USEOBJLB FALSE /**< Use lower bound on objective function (via lower bound)? */
    149#define DEFAULT_SUBSCIPFAST TRUE /**< Should the settings for the sub-MIP be optimized for speed? */
    150#define DEFAULT_OUTPUT FALSE /**< Should information about the sub-MIP and cuts be displayed? */
    151#define DEFAULT_RANDSEED 101 /**< start random seed for random number generation */
    152#define DEFAULT_GENPRIMALSOLS FALSE /**< Try to generate primal solutions from Gomory cuts? */
    153
    154
    155#define NROWSTOOSMALL 5 /**< only separate if the number of rows is larger than this number */
    156#define NCOLSTOOSMALL 5 /**< only separate if the number of columns is larger than this number */
    157
    158#define EPSILONVALUE 1e-03 /**< epsilon value needed to model strict-inequalities */
    159#define BETAEPSILONVALUE 1e-02 /**< epsilon value for fracbeta - is larger than EPSILONVALUE for numerical stability */
    160#define STALLNODELIMIT 1000LL /**< number of stalling nodes if earlyterm is true */
    161#define CONSHDLRFULLNORM FALSE /**< compute real cut and compute norm for this (if addviolconshdlr and conshdlrusenorm are true) */
    162#define MINEFFICACY 0.05 /**< minimum efficacy of a cut - compare set.c */
    163#define MAXNSOLS 1000 /**< maximal number of solutions stored in sub-SCIP */
    164#define OBJWEIGHTRANGE 0.01 /**< maximal range of scaling of objective w.r.t. size of rows */
    165
    166/* parameters used for CMIR-generation (taken from sepa_gomory) */
    167#define BOUNDSWITCH 0.9999
    168#define VARTYPEUSEVBDS 2 /**< We allow variable bound substitution for variables with continuous vartype only.
    169 * See SCIPcalcMIR() for more information. */
    170#define POSTPROCESS TRUE
    171#define MINFRAC 0.0009 /**< to allow a deviation of the same size as EPSILONVALUE */
    172#define MAXFRAC 0.9991 /**< to allow a deviation of the same size as EPSILONVALUE */
    173#define FIXINTEGRALRHS FALSE
    174#define MAKECONTINTEGRAL FALSE
    175#define MAXWEIGHTRANGE 1e+05 /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
    176#define AWAY 0.005 /**< minimal fractionality of a basic variable in order to try GMI cut */
    177#define SEPARATEROWS TRUE /**< Separate rows with integral slack? */
    178
    179#define MAXAGGRLEN(nvars) nvars /**< currently very large to allow any generation; an alternative would be (0.1*(nvars)+1000) */
    180
    181/** separator data */
    182struct SCIP_SepaData
    183{
    184 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    185 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
    186 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
    187 int maxdepth; /**< maximal depth at which the separator is applied */
    188 SCIP_Bool decisiontree; /**< Use decision tree to turn separation on/off? */
    189 SCIP_Real timelimit; /**< time limit for subscip */
    190 SCIP_Real memorylimit; /**< memory limit for subscip */
    191 SCIP_Longint minnodelimit; /**< minimum number of nodes considered for sub-MIP (-1: unlimited) */
    192 SCIP_Longint maxnodelimit; /**< maximum number of nodes considered for sub-MIP (-1: unlimited) */
    193 SCIP_Real cutcoefbnd; /**< bounds on the values of the coefficients in the CG-cut */
    194 SCIP_Bool onlyactiverows; /**< Use only active rows to generate cuts? */
    195 int maxrowage; /**< maximal age of rows to consider if onlyactiverows is false */
    196 SCIP_Bool onlyrankone; /**< Separate only rank 1 inequalities w.r.t. CG-MIP separator? */
    197 SCIP_Bool onlyintvars; /**< Generate cuts for problems with only integer variables? */
    198 SCIP_Bool allowlocal; /**< Allow local cuts? */
    199 SCIP_Bool contconvert; /**< Convert some integral variables to be continuous to reduce the size of the sub-MIP? */
    200 SCIP_Real contconvfrac; /**< fraction of integral variables converted to be continuous (if contconvert) */
    201 int contconvmin; /**< minimum number of integral variables before some are converted to be continuous */
    202 SCIP_Bool intconvert; /**< Convert some integral variables attaining fractional values to have integral value? */
    203 SCIP_Real intconvfrac; /**< fraction of frac. integral variables converted to have integral value (if intconvert) */
    204 int intconvmin; /**< minimum number of integral variables before some are converted to have integral value */
    205 SCIP_Bool skipmultbounds; /**< Skip the upper bounds on the multipliers in the sub-MIP? */
    206 SCIP_Bool objlone; /**< Should the objective of the sub-MIP only minimize the l1-norm of the multipliers? */
    207 SCIP_Real objweight; /**< objective weight for artificial variables */
    208 SCIP_Bool objweightsize; /**< Weight each row by its size? */
    209 SCIP_Bool dynamiccuts; /**< Should generated cuts be removed from the LP if they are no longer tight? */
    210 SCIP_Bool usecmir; /**< Use CMIR-generator (otherwise add cut directly)? */
    211 SCIP_Bool usestrongcg; /**< Use strong CG-function to strengthen cut? */
    212 SCIP_Bool cmirownbounds; /**< Tell CMIR-generator which bounds to used in rounding? */
    213 SCIP_Bool usecutpool; /**< Use cutpool to store CG-cuts even if the are not efficient? */
    214 SCIP_Bool primalseparation; /**< Only separate cuts that are tight for the best feasible solution? */
    215 SCIP_Bool earlyterm; /**< Terminate separation if a violated (but possibly sub-optimal) cut has been found? */
    216 SCIP_Bool addviolationcons; /**< Add constraint to subscip that only allows violated cuts? */
    217 SCIP_Bool addviolconshdlr; /**< Add constraint handler to filter out violated cuts? */
    218 SCIP_Bool conshdlrusenorm; /**< Should the violation constraint handler use the cut-norm to check for feasibility? */
    219 SCIP_Bool useobjub; /**< Use upper bound on objective function (via primal solution)? */
    220 SCIP_Bool useobjlb; /**< Use lower bound on objective function (via lower bound)? */
    221 SCIP_Bool subscipfast; /**< Should the settings for the sub-MIP be optimized for speed? */
    222 SCIP_Bool output; /**< Should information about the sub-MIP and cuts be displayed? */
    223 SCIP_Bool genprimalsols; /**< Try to generate primal solutions from Gomory cuts? */
    224};
    225
    226
    227/** what happens for columns in the LP */
    229{
    230 colPresent = 0, /**< column is present in the separating MIP */
    231 colContinuous = 1, /**< column corresponds to a continuous variable */
    232 colConverted = 2, /**< column is converted to be continuous */
    233 colAtUb = 3, /**< variable corresponding to column was at it's upper bound and was complemented */
    234 colAtLb = 4 /**< variable corresponding to column was at it's lower bound (possibly complemented) */
    237
    238
    239/** data for the sub-MIP */
    240struct CGMIP_MIPData
    241{
    242 SCIP* subscip; /**< pointer to (sub)SCIP data structure containing the auxiliary IP */
    243 unsigned int m; /**< number of constraints of subscip */
    244 unsigned int n; /**< number of variables of subscip */
    245 unsigned int nrows; /**< number of rows of original LP */
    246 unsigned int ncols; /**< number of columns of original LP */
    247 unsigned int ntotalrows; /**< number of total rows used (possibly including objective rows) */
    248
    249 SCIP_VAR** alpha; /**< cut coefficient variable (NULL if not in separating MIP) */
    250 SCIP_VAR* beta; /**< rhs of cut */
    251 SCIP_VAR** fracalpha; /**< fractional part of lhs of cut (NULL if not present) */
    252 SCIP_VAR* fracbeta; /**< fractional part of rhs of cut */
    253 CGMIP_COLTYPE* coltype; /**< type for the columns */
    254 SCIP_Bool* iscomplemented; /**< whether the variable was complemented */
    255 SCIP_Bool* isshifted; /**< whether the variable was shifted to have 0 lower bound */
    256
    257 SCIP_VAR** ylhs; /**< auxiliary row variables for lhs (NULL if not present) */
    258 SCIP_VAR** yrhs; /**< auxiliary row variables for rhs (NULL if not present) */
    259
    260 SCIP_VAR** z; /**< auxiliary variables for upper bounds (NULL if not present) */
    261
    262 SCIP_Real* lhs; /**< transformed left hand sides */
    263 SCIP_Real* rhs; /**< transformed left hand sides */
    264
    265 char normtype; /**< type of norm to use for efficacy norm calculation */
    266
    267 /* additional redundant data */
    268 SCIP_Bool conshdlrusenorm; /**< copy from sepadata */
    269 SCIP_Bool conshdlrfullnorm; /**< compute real cut and compute norm for this (if addviolconshdlr and conshdlrusenorm are true) */
    270 SCIP* scip; /**< original SCIP */
    271 SCIP_SEPA* sepa; /**< CG-cut separator */
    272 SCIP_SEPADATA* sepadata; /**< CG-cut separator data */
    273};
    274typedef struct CGMIP_MIPData CGMIP_MIPDATA;
    275
    276
    277/*
    278 * constraint handler to filter out violated cuts
    279 */
    280
    281/* constraint handler properties */
    282#define CONSHDLR_NAME "violatedCuts"
    283#define CONSHDLR_DESC "only allow solutions corresponding to violated cuts"
    284
    285/** constraint handler data */
    286struct SCIP_ConshdlrData
    287{
    288 CGMIP_MIPDATA* mipdata; /**< data of separating sub-MIP */
    289};
    290
    291/* temporary forward declaration */
    292static
    294 SCIP* scip, /**< original scip */
    295 SCIP_SEPA* sepa, /**< separator */
    296 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    297 SCIP_SEPADATA* sepadata, /**< separator data */
    298 SCIP_SOL* sol, /**< current solution for sub-MIP */
    299 SCIP_Bool usefrac, /**< use fractional value of multipliers */
    300 SCIP_Real* cutcoefs, /**< coefficients of the cut */
    301 SCIP_Real* cutrhs, /**< rhs of the cut */
    302 SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
    303 SCIP_Bool* localboundsused, /**< pointer to store whether local bounds were used in summation */
    304 int * cutrank, /**< pointer to store the cut rank */
    305 SCIP_Bool* success /**< whether we produced a valid cut */
    306 );
    307
    308/** check whether cut corresponding to solution is violated */
    309static
    311 SCIP* scip, /**< SCIP data structure */
    312 CGMIP_MIPDATA* mipdata, /**< data of separating sub-MIP */
    313 SCIP_SOL* sol, /**< solution to be checked */
    314 SCIP_Bool* violated /**< pointer to store if the cut is violated */
    315 )
    316{
    317 SCIP_Real cutsqrnorm = 0.0;
    318 SCIP* subscip;
    319 SCIP_Real act;
    320 SCIP_Real norm;
    321 SCIP_Real val;
    322 SCIP_VAR* var;
    323 SCIP_Real rhs;
    324 unsigned int j;
    325 int len = 0;
    326
    327 assert( mipdata != NULL );
    328 subscip = mipdata->subscip;
    329 assert( subscip != NULL );
    330 assert( violated != NULL );
    331
    332 /* initialize activity and norm */
    333 act = 0.0;
    334 norm = 1.0;
    335 *violated = FALSE;
    336
    337 /* compute activity and norm */
    338 if ( mipdata->conshdlrusenorm )
    339 {
    340 /* check whether we should compute the full cut and then compute the norm */
    341 if ( mipdata->conshdlrfullnorm )
    342 {
    343 SCIP_Real* cutcoefs;
    344 SCIP_Bool localrowsused;
    345 SCIP_Bool localboundsused;
    346 SCIP_Bool success;
    347 SCIP_VAR** vars;
    348 int cutrank = 0;
    349 int nvars;
    350
    351 /* get data */
    352 SCIP_CALL( SCIPgetVarsData(mipdata->scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    353 assert(nvars >= 0);
    354 SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, nvars) );
    355
    356 /* compute coefficients */
    357 SCIP_CALL( computeCut(mipdata->scip, mipdata->sepa, mipdata, mipdata->sepadata, sol, TRUE, cutcoefs, &rhs, &localrowsused, &localboundsused, &cutrank, &success) );
    358
    359 /* try again if cut was not valid */
    360 if ( ! success )
    361 {
    362 SCIP_CALL( computeCut(mipdata->scip, mipdata->sepa, mipdata, mipdata->sepadata, sol, FALSE,
    363 cutcoefs, &rhs, &localrowsused, &localboundsused, &cutrank, &success) );
    364
    365 if ( ! success )
    366 return SCIP_OKAY;
    367 }
    368
    369#ifdef SCIP_MORE_DEBUG
    370 for (j = 0; j < (unsigned int) nvars; ++j)
    371 {
    372 if ( ! SCIPisZero(scip, cutcoefs[j]) )
    373 SCIPinfoMessage(scip, NULL, "+ %f x%d", cutcoefs[j], j);
    374 }
    375 SCIPinfoMessage(scip, NULL, "\n");
    376#endif
    377
    378 /* compute activity and Euclidean norm (todo: use arbitrary norm) */
    379 cutsqrnorm = 0.0;
    380 for (j = 0; j < (unsigned int) nvars; ++j)
    381 {
    382 if ( ! SCIPisZero(scip, cutcoefs[j]) )
    383 {
    384 act += cutcoefs[j] * SCIPvarGetLPSol(vars[j]);
    385 cutsqrnorm += SQR(cutcoefs[j]);
    386 }
    387 }
    388 norm = sqrt(cutsqrnorm);
    389
    390 SCIPfreeBufferArray(scip, &cutcoefs);
    391 } /*lint !e438*/
    392 else
    393 {
    394 switch ( mipdata->normtype )
    395 {
    396 case 'e':
    397 cutsqrnorm = 0.0;
    398 for (j = 0; j < mipdata->ncols; ++j)
    399 {
    400 var = mipdata->alpha[j];
    401 if ( var == NULL )
    402 continue;
    403
    404 val = SCIPgetSolVal(subscip, sol, var);
    405 if ( !SCIPisZero(scip, val) )
    406 {
    407 act += val * SCIPvarGetObj(var);
    408 cutsqrnorm += SQR(val);
    409 }
    410 }
    411 norm = sqrt(cutsqrnorm);
    412 break;
    413 case 'm':
    414 for (j = 0; j < mipdata->ncols; ++j)
    415 {
    416 var = mipdata->alpha[j];
    417 if ( var == NULL )
    418 continue;
    419
    420 val = SCIPgetSolVal(subscip, sol, var);
    421 if ( !SCIPisZero(scip, val) )
    422 {
    423 act += val * SCIPvarGetObj(var);
    424 if ( REALABS(val) > norm )
    425 norm = REALABS(val);
    426 }
    427 }
    428 break;
    429 case 's':
    430 for (j = 0; j < mipdata->ncols; ++j)
    431 {
    432 var = mipdata->alpha[j];
    433 if ( var == NULL )
    434 continue;
    435
    436 val = SCIPgetSolVal(subscip, sol, var);
    437 if ( !SCIPisZero(scip, val) )
    438 {
    439 act += val * SCIPvarGetObj(var);
    440 norm += REALABS(val);
    441 }
    442 }
    443 break;
    444 case 'd':
    445 for (j = 0; j < mipdata->ncols; ++j)
    446 {
    447 var = mipdata->alpha[j];
    448 if ( var == NULL )
    449 continue;
    450
    451 val = SCIPgetSolVal(subscip, sol, var);
    452 if ( !SCIPisZero(scip, val) )
    453 {
    454 act += val * SCIPvarGetObj(var);
    455 ++len;
    456 }
    457 }
    458 if ( len > 0 )
    459 norm = 1.0;
    460 break;
    461 default:
    462 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", mipdata->normtype);
    463 return SCIP_INVALIDDATA;
    464 }
    465 /* get rhs */
    466 rhs = SCIPgetSolVal(subscip, sol, mipdata->beta);
    467 }
    468
    469 /* if norm is 0, the cut is trivial */
    470 if ( SCIPisZero(subscip, norm) )
    471 return SCIP_OKAY;
    472 }
    473 else
    474 {
    475 for (j = 0; j < mipdata->ncols; ++j)
    476 {
    477 var = mipdata->alpha[j];
    478 if ( var == NULL )
    479 continue;
    480
    481 val = SCIPgetSolVal(subscip, sol, var);
    482 if ( !SCIPisZero(subscip, val) )
    483 act += SCIPvarGetObj(var) * val;
    484 }
    485
    486 /* get rhs */
    487 rhs = SCIPgetSolVal(subscip, sol, mipdata->beta);
    488 }
    489
    490#ifdef SCIP_DEBUG
    491 if ( SCIPisEfficacious(subscip, (act - rhs)/norm) )
    492 {
    493 SCIPdebugMsg(scip, "Violated cut from solution - act: %f, rhs: %f, norm: %f, eff.: %f\n", act, rhs, norm, (act-rhs)/norm);
    494 }
    495 else
    496 {
    497 SCIPdebugMsg(scip, "Rejected cut from solution - act: %f, rhs: %f, norm: %f, eff.: %f\n", act, rhs, norm, (act-rhs)/norm);
    498 }
    499#endif
    500
    501 *violated = SCIPisEfficacious(subscip, (act - rhs)/norm);
    502
    503 return SCIP_OKAY;
    504}
    505
    506
    507/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    508static
    509SCIP_DECL_CONSFREE(consFreeViolatedCuts)
    510{ /*lint --e{715}*/
    511 SCIP_CONSHDLRDATA* conshdlrdata;
    512
    513 assert( scip != NULL );
    514 assert( conshdlr != NULL );
    515 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    516 assert( conshdlrdata != NULL );
    517
    518 SCIPfreeBlockMemory(scip, &conshdlrdata);
    519
    520 return SCIP_OKAY;
    521}
    522
    523
    524/** constraint enforcing method of constraint handler for LP solutions */
    525static
    526SCIP_DECL_CONSENFOLP(consEnfolpViolatedCuts)
    527{ /*lint --e{715}*/
    528 SCIP_CONSHDLRDATA* conshdlrdata;
    529 SCIP_Bool violated;
    530
    531 assert( scip != NULL );
    532 assert( conshdlr != NULL );
    533 assert( result != NULL );
    534
    535 assert( SCIPgetNLPBranchCands(scip) == 0 );
    536
    537 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    538 assert( conshdlrdata != NULL );
    539
    540 SCIP_CALL( solCutIsViolated(scip, conshdlrdata->mipdata, NULL, &violated) );
    541
    542 if ( violated )
    543 *result = SCIP_FEASIBLE;
    544 else
    545 *result = SCIP_CUTOFF; /* cutoff, since all integer variables are integer, but the solution is not feasible */
    546
    547 return SCIP_OKAY;
    548}
    549
    550
    551/** constraint enforcing method of constraint handler for pseudo solutions */
    552static
    553SCIP_DECL_CONSENFOPS(consEnfopsViolatedCuts)
    554{ /*lint --e{715}*/
    555 assert( result != NULL );
    556
    557 /* this function should better not be called, since we need an LP solution for the sub-MIP to
    558 * make sense, because of the multiplier variables. We therefore return SCIP_FEASIBLE. */
    559 *result = SCIP_FEASIBLE;
    560
    561 return SCIP_OKAY;
    562}
    563
    564
    565/** feasibility check method of constraint handler for integral solutions */
    566static
    567SCIP_DECL_CONSCHECK(consCheckViolatedCuts)
    568{ /*lint --e{715}*/
    569 SCIP_CONSHDLRDATA* conshdlrdata;
    570 SCIP_Bool violated;
    571
    572 assert( scip != NULL );
    573 assert( conshdlr != NULL );
    574 assert( sol != NULL );
    575 assert( result != NULL );
    576
    577 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    578 assert( conshdlrdata != NULL );
    579
    580 SCIP_CALL( solCutIsViolated(scip, conshdlrdata->mipdata, sol, &violated) );
    581
    582 if ( violated )
    583 *result = SCIP_FEASIBLE;
    584 else
    585 *result = SCIP_INFEASIBLE;
    586
    587 return SCIP_OKAY;
    588}
    589
    590
    591/** variable rounding lock method of constraint handler */
    592static
    593SCIP_DECL_CONSLOCK(consLockViolatedCuts)
    594{ /*lint --e{715}*/
    595 /* do not lock variables */
    596 return SCIP_OKAY;
    597}
    598
    599
    600/** creates the violated CG-cut constraint handler and includes it in SCIP */
    601static
    603 SCIP* scip, /**< SCIP data structure */
    604 CGMIP_MIPDATA* mipdata /**< data of separating sub-MIP */
    605 )
    606{
    607 SCIP_CONSHDLRDATA* conshdlrdata;
    608 SCIP_CONSHDLR* conshdlr;
    609
    610 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
    611 conshdlrdata->mipdata = mipdata;
    612
    613 /* include constraint handler */
    615 -1000000, -1000000, 100, FALSE,
    616 consEnfolpViolatedCuts, consEnfopsViolatedCuts, consCheckViolatedCuts, consLockViolatedCuts,
    617 conshdlrdata) );
    618
    619 assert(conshdlr != NULL);
    620
    621 /* set non-fundamental callbacks via specific setter functions */
    622 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeViolatedCuts) );
    623
    624 return SCIP_OKAY;
    625}
    626
    627
    628/*
    629 * local methods
    630 */
    631
    632
    633/** stores nonzero elements of dense coefficient vector as sparse vector and calculates activity and norm
    634 *
    635 * copied from sepa_gomory.c
    636 */
    637static
    639 SCIP* scip, /**< SCIP data structure */
    640 int nvars, /**< number of problem variables */
    641 SCIP_Real* cutcoefs, /**< dense coefficient vector */
    642 SCIP_Real* varsolvals, /**< dense variable LP solution vector */
    643 char normtype, /**< type of norm to use for efficacy norm calculation */
    644 int* cutinds, /**< array to store variables of sparse cut vector */
    645 SCIP_Real* cutvals, /**< array to store coefficients of sparse cut vector */
    646 int* cutlen, /**< pointer to store number of nonzero entries in cut */
    647 SCIP_Real* cutact, /**< pointer to store activity of cut */
    648 SCIP_Real* cutnorm /**< pointer to store norm of cut vector */
    649 )
    650{
    651 SCIP_Real val;
    652 SCIP_Real cutsqrnorm;
    653 SCIP_Real act;
    654 SCIP_Real norm;
    655 int len;
    656 int v;
    657
    658 assert( nvars == 0 || cutcoefs != NULL );
    659 assert( nvars == 0 || varsolvals != NULL );
    660 assert( cutinds != NULL );
    661 assert( cutvals != NULL );
    662 assert( cutlen != NULL );
    663 assert( cutact != NULL );
    664 assert( cutnorm != NULL );
    665
    666 len = 0;
    667 act = 0.0;
    668 norm = 0.0;
    669 switch ( normtype )
    670 {
    671 case 'e':
    672 cutsqrnorm = 0.0;
    673 for (v = 0; v < nvars; ++v)
    674 {
    675 val = cutcoefs[v];
    676 if ( !SCIPisZero(scip, val) )
    677 {
    678 act += val * varsolvals[v];
    679 cutsqrnorm += SQR(val);
    680 cutinds[len] = v;
    681 cutvals[len++] = val;
    682 }
    683 }
    684 norm = sqrt(cutsqrnorm);
    685 break;
    686 case 'm':
    687 for (v = 0; v < nvars; ++v)
    688 {
    689 val = cutcoefs[v];
    690 if ( !SCIPisZero(scip, val) )
    691 {
    692 act += val * varsolvals[v];
    693 if ( REALABS(val) > norm )
    694 norm = REALABS(val);
    695 cutinds[len] = v;
    696 cutvals[len++] = val;
    697 }
    698 }
    699 break;
    700 case 's':
    701 for (v = 0; v < nvars; ++v)
    702 {
    703 val = cutcoefs[v];
    704 if ( !SCIPisZero(scip, val) )
    705 {
    706 act += val * varsolvals[v];
    707 norm += REALABS(val);
    708 cutinds[len] = v;
    709 cutvals[len++] = val;
    710 }
    711 }
    712 break;
    713 case 'd':
    714 for (v = 0; v < nvars; ++v)
    715 {
    716 val = cutcoefs[v];
    717 if ( !SCIPisZero(scip, val) )
    718 {
    719 act += val * varsolvals[v];
    720 cutinds[len] = v;
    721 cutvals[len++] = val;
    722 }
    723 }
    724 if ( len > 0 )
    725 norm = 1.0;
    726 break;
    727 default:
    728 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", normtype);
    729 return SCIP_INVALIDDATA;
    730 }
    731
    732 *cutlen = len;
    733 *cutact = act;
    734 *cutnorm = norm;
    735
    736 return SCIP_OKAY;
    737}
    738
    739
    740/** Compute lhs/rhs for transformed column
    741 *
    742 * Consider a variable \f$x_j\f$ and some row of the original system:
    743 * \f[
    744 * \gamma \leq a^T x \leq \delta, \quad \ell_j \leq x_j \leq u_j.
    745 * \f]
    746 * We perform the transformation
    747 * \f[
    748 * x_i' = \left\{
    749 * \begin{array}{ll}
    750 * s + \frac{1}{\sigma}\, x_j & \mbox{if }i = j\\
    751 * x_i & \mbox{otherwise},
    752 * \end{array}
    753 * \right.
    754 * \f]
    755 * where \f$s\f$ is the offset value and \f$\sigma\f$ is a scaling factor. The new system is
    756 * \f[
    757 * \gamma + \sigma\, a_j\,s \leq \sum_{i \neq j} a_i\, x_i' + \sigma a_j\, x_j' \leq \delta + \sigma\, a_j\, s
    758 * \f]
    759 * with bounds
    760 * \f[
    761 * \frac{1}{\sigma} \ell_j + s \leq x_j' \leq \frac{1}{\sigma} u_j + s, \qquad \mbox{ if }\sigma > 0
    762 * \f]
    763 * and
    764 * \f[
    765 * \frac{1}{\sigma} u_j + s \leq x_j' \leq \frac{1}{\sigma} \ell_j + s, \qquad \mbox{ if }\sigma < 0.
    766 * \f]
    767 *
    768 * This can be used as follows:
    769 *
    770 * - If \f$x_j \geq \ell_j\f$ has a (nonzero) lower bound, one can use \f$s = -\ell_j\f$, \f$\sigma = 1\f$,
    771 * and obtain \f$\gamma - a_j\,\ell_j \leq a^T x' \leq \delta - a_j\,\ell_j\f$, \f$0 \leq x_j' \leq u_j - \ell_j\f$.
    772 *
    773 * - If \f$x_j \leq u_j\f$ has a (nonzero) upper bound, one can use \f$s = u_j\f$, \f$\sigma = -1\f$,
    774 * and obtain \f$\gamma - a_j\,u_j \leq \sum_{i \neq j} a_i\, x_i' - a_j\, x_j' \leq \delta - a_j\, u_j\f$,
    775 * \f$0 \leq x_j' \leq u_j - \ell_j\f$.
    776 */
    777static
    779 SCIP* scip, /**< SCIP data structure */
    780 SCIP_SEPADATA* sepadata, /**< separator data */
    781 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    782 SCIP_COL* col, /**< column that should be complemented */
    783 SCIP_Real offset, /**< offset by which column should be shifted */
    784 SCIP_Real sigma, /**< scaling factor */
    785 SCIP_Real* lhs, /**< array of lhs of rows */
    786 SCIP_Real* rhs, /**< array rhs of rows */
    787 SCIP_Real* lb, /**< pointer to lb of column */
    788 SCIP_Real* ub, /**< pointer to ub of column */
    789 SCIP_Real* primsol /**< pointer to solution value */
    790 )
    791{
    792 SCIP_ROW** colrows;
    793 SCIP_Real* colvals;
    794 int pos, i;
    795
    796 assert( scip != NULL );
    797 assert( lhs != NULL );
    798 assert( rhs != NULL );
    799 assert( col != NULL );
    800
    801 colrows = SCIPcolGetRows(col);
    802 colvals = SCIPcolGetVals(col);
    803 assert( SCIPcolGetNLPNonz(col) == 0 || colrows != NULL );
    804 assert( SCIPcolGetNLPNonz(col) == 0 || colvals != NULL );
    805 assert( ! SCIPisZero(scip, sigma) );
    806
    807 /* loop through rows that contain column */
    808 for (i = 0; i < SCIPcolGetNLPNonz(col); ++i)
    809 {
    810 SCIP_ROW* row;
    811
    812 row = colrows[i];
    813 assert( row != NULL );
    814
    815 /* skip modifiable rows and local rows, unless allowed */
    816 if ( SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && !sepadata->allowlocal) )
    817 continue;
    818
    819 pos = SCIProwGetLPPos(row);
    820 assert( 0 <= pos && pos < (int) mipdata->nrows );
    821
    822 assert( ! SCIPisInfinity(scip, lhs[pos]) );
    823 if ( ! SCIPisInfinity(scip, -lhs[pos]) )
    824 lhs[pos] += sigma * colvals[i] * offset;
    825
    826 assert( ! SCIPisInfinity(scip, -rhs[pos]) );
    827 if ( ! SCIPisInfinity(scip, rhs[pos]) )
    828 rhs[pos] += sigma * colvals[i] * offset;
    829 }
    830
    831 /* check objective function */
    832 if ( sepadata->useobjub || sepadata->useobjlb )
    833 {
    834 assert( SCIPisEQ(scip, SCIPcolGetObj(col), SCIPvarGetObj(SCIPcolGetVar(col))) );
    835 assert( mipdata->ntotalrows == mipdata->nrows + 1 );
    836
    837 if ( ! SCIPisInfinity(scip, -lhs[mipdata->nrows]) )
    838 lhs[mipdata->nrows] += sigma * SCIPcolGetObj(col) * offset;
    839
    840 if ( ! SCIPisInfinity(scip, rhs[mipdata->nrows]) )
    841 rhs[mipdata->nrows] += sigma * SCIPcolGetObj(col) * offset;
    842 }
    843
    844 /* correct lower and upper bounds and solution */
    845 if ( SCIPisNegative(scip, sigma) )
    846 {
    847 SCIP_Real l;
    848
    849 assert( ! SCIPisInfinity(scip, -*ub) );
    850 if ( ! SCIPisInfinity(scip, *ub) )
    851 l = *ub/sigma + offset;
    852 else
    853 l = -SCIPinfinity(scip);
    854
    855 assert( ! SCIPisInfinity(scip, *lb) );
    856 if ( ! SCIPisInfinity(scip, -*lb) )
    857 *ub = *lb/sigma + offset;
    858 else
    859 *ub = SCIPinfinity(scip);
    860 *lb = l;
    861 }
    862 else
    863 {
    864 assert( ! SCIPisInfinity(scip, *lb) );
    865 if ( ! SCIPisInfinity(scip, -*lb) )
    866 *lb = *lb/sigma + offset;
    867 assert( ! SCIPisInfinity(scip, -*ub) );
    868 if ( ! SCIPisInfinity(scip, *ub) )
    869 *ub = *ub/sigma + offset;
    870 }
    871 *primsol = *primsol/sigma + offset;
    872
    873 return SCIP_OKAY;
    874}
    875
    876
    877/** compute objective coefficient for rows that are weighted by size
    878 *
    879 * The objective is computed by multiplying a default value by
    880 * \f[
    881 * 1 - (r_{\mbox{max}} - r) \frac{1 - a}{r_{\mbox{max}} - r_{\mbox{min}}},
    882 * \f]
    883 * where \f$r\f$ is the size of the current row, \f$a \in [0,1]\f$ is a parameter, and \f$r_{\mbox{max}}\f$ and
    884 * \f$r_{\mbox{min}}\f$ are the maximal and minimal size of a row, respectively.
    885 *
    886 * Thus, if \f$r = r_{\mbox{max}}\f$, we get 1 and if \f$r = r_{\mbox{min}}\f$, we get \f$a\f$.
    887 */
    888static
    890 int rowsize, /**< size of current row */
    891 int minrowsize, /**< maximal size of rows */
    892 int maxrowsize /**< minimal size of rows */
    893 )
    894{
    895 SCIP_Real a;
    896
    897 assert( maxrowsize > 0 );
    898 assert( minrowsize < INT_MAX );
    899 assert( minrowsize <= maxrowsize );
    900 assert( minrowsize <= rowsize && rowsize <= maxrowsize );
    901
    902 if ( minrowsize == maxrowsize )
    903 return 1.0;
    904
    905 a = (1.0 - OBJWEIGHTRANGE)/((SCIP_Real) (maxrowsize - minrowsize));
    906
    907 return 1.0 - a * ((SCIP_Real) (maxrowsize - rowsize));
    908}
    909
    910
    911/** Creates a subscip representing the separating MIP.
    912 *
    913 * Let the constraints of the original MIP be of the following form:
    914 * \f[
    915 * \begin{array}{l@{\;}ll}
    916 * a \leq A x + & C r & \leq b\\
    917 * \ell \leq x & & \leq u\\
    918 * c \leq & r & \leq d\\
    919 * x \in Z^n.
    920 * \end{array}
    921 * \f]
    922 * Here, some of the bounds may have value \f$\infty\f$ or \f$-\infty\f$. Written in
    923 * \f$\leq\f$-form this becomes:
    924 * \f[
    925 * \begin{array}{r@{\;}l}
    926 * \tilde{A} x + \tilde{C} r & \leq \tilde{b}\\
    927 * -x & \leq -\ell\\
    928 * x & \leq u\\
    929 * -r & \leq -c\\
    930 * r & \leq d\\
    931 * x \in Z^n,
    932 * \end{array}
    933 * \f]
    934 * where we use
    935 * \f[
    936 * \tilde{A} =
    937 * \left[
    938 * \begin{array}{r}
    939 * -A \\
    940 * A
    941 * \end{array}
    942 * \right],
    943 * \quad
    944 * \tilde{C} =
    945 * \left[
    946 * \begin{array}{r}
    947 * - C\\
    948 * C
    949 * \end{array}
    950 * \right]
    951 * \qquad\mbox{ and }\qquad
    952 * \tilde{b} =
    953 * \left[
    954 * \begin{array}{r}
    955 * -a\\
    956 * b
    957 * \end{array}
    958 * \right].
    959 * \f]
    960 * For the moment we assume that \f$c = 0\f$, i.e., the lower bounds on the continuous variables
    961 * are 0. To obtain a Chv&aacute;tal-Gomory cut we have to find nonnegative multipliers \f$y\f$,
    962 * \f$\underline{z}\f$, and \f$\overline{z}\f$ such that
    963 * \f[
    964 * y^T \tilde{A} - \underline{z}^T + \overline{z}^T \in Z \qquad\mbox{ and }\qquad
    965 * y^T \tilde{C} \geq 0.
    966 * \f]
    967 * Note that we use zero multipliers for the bounds on the continuous variables \f$r\f$. Moreover,
    968 * if some bounds are infinity, the corresponding multipliers are assumed to be 0. From these
    969 * conditions, we obtain
    970 * \f[
    971 * (y^T \tilde{A} - \underline{z}^T + \overline{z}^T)\, x +
    972 * y^T \tilde{C} \, r \leq
    973 * y^T \tilde{b} - \underline{z}^T \ell + \overline{z}^T u.
    974 * \f]
    975 * Because \f$r \geq 0\f$, we can ignore the term \f$y^T \tilde{C} \, r \geq 0\f$ and obtain the
    976 * following cut:
    977 * \f[
    978 * (y^T \tilde{A} - \underline{z}^T + \overline{z}^T )\, x \leq
    979 * \lfloor y^T \tilde{b} - \underline{z}^T \ell + \overline{z}^T u \rfloor.
    980 * \f]
    981 * Assume that \f$\ell = 0\f$ for the meantime. Then the cut can be written as:
    982 * \f[
    983 * \lfloor y^T \tilde{A} + \overline{z}^T \rfloor \, x \leq
    984 * \lfloor y^T \tilde{b} + \overline{z}^T u \rfloor.
    985 * \f]
    986 *
    987 * Following Fischetti and Lodi [2005], let \f$(x^*,r^*)\f$ be a fractional solution of the above
    988 * original system. The separating MIP created below is
    989 * \f[
    990 * \begin{array}{rlr@{\;}l}
    991 * \max & (x^*)^T \alpha - \beta - w^T y \\
    992 * & f = \tilde{A}^T y + \overline{z} - \alpha \\
    993 * & \tilde{f} = \tilde{b}^T y + u^T \overline{z} - \beta\\
    994 * & \tilde{C}^T y \geq 0\\
    995 * & 0 \leq f \leq 1 - \epsilon \\
    996 * & 0 \leq \tilde{f} \leq 1 - \epsilon\\
    997 * & 0 \leq y, \overline{z} \leq 1 - \epsilon.\\
    998 * & \alpha \in Z^m, \beta \in Z.
    999 * \end{array}
    1000 * \f]
    1001 * Here, \f$w\f$ is a weight vector; it's idea is to make the sum over all components of \f$y\f$ as
    1002 * small as possible, in order to generate sparse cuts.
    1003 *
    1004 * We perform the following additional computations:
    1005 *
    1006 * - If the lower bounds on \f$x_i\f$ or \f$r_j\f$ are finite, we shift the variable to have a zero
    1007 * lower bound, i.e., we replace it by \f$x_i - \ell_i\f$ (or \f$r_j - u_j\f$). This is helpful in
    1008 * several ways: As seen above, the resulting inequalities/formulations simplify. Moreover, it
    1009 * allows to drop a variable if \f$x^*_i = 0\f$, see the next comment. If the lower bounds are not
    1010 * finite, but the upper bounds are finite, we can complement the variable. If the variables are
    1011 * free, the above formulation changes as follows: For free continuous variables, we require
    1012 * \f$\tilde{C}^T y = 0\f$. For a free integer variable \f$x_j\f$ (which rarely occurs in
    1013 * practice), we require \f$f_j = 0\f$, i.e., we force that \f$(\tilde{A}^T y + \overline{z})_j =
    1014 * \alpha_j\f$.
    1015 *
    1016 * - If \f$x^*_j = 0 = \ell_j\f$ (after the above preprocessing), we drop variable \f$\alpha_j\f$
    1017 * from the formulation. Let \f$(\alpha^*, \beta^*, y^*, \overline{z}^*)\f$ be an
    1018 * optimal solution to the separating MIP. Then we can compute \f$\alpha_j =
    1019 * \lfloor(\tilde{A}_j^T y^* + \overline{z}^*)\rfloor\f$.
    1020 *
    1021 * - If \f$x^*_i = u_i\f$, we complement the variable and drop it from the formulation, since the
    1022 * lower bound is 0 afterwards.
    1023 *
    1024 * - If a variable has been shifted or complemented, we have to recompute \f$\beta\f$ with the
    1025 * original lhs/rhs.
    1026 *
    1027 * - If a continuous variable \f$r_j\f$ is free, we have to force equality for the corresponding components in
    1028 * \f$y^T \tilde{C} \, r \geq 0\f$.
    1029 *
    1030 * - If an integer variable \f$x_i\f$ is free, we are not allowed to round the cut down. In this
    1031 * case, the combintation of rows and bounds has to be integral. We force this by requiring that
    1032 * \f$f_i = 0\f$.
    1033 *
    1034 * - If @p contconvert is true, some integral variables are randomly treated as if they were
    1035 * continuous. This has the effect that in the resulting cut the corresponding coefficient has
    1036 * value 0. This makes the cuts more sparse. Moreover, the separation problems should become
    1037 * easier.
    1038 *
    1039 * - If required, i.e., parameter @p primalseparation is true, we force a primal separation step. For
    1040 * this we require that the cut is tight at the currently best solution. To get reliable solutions
    1041 * we relax equality by EPSILONVALUE.
    1042 *
    1043 * - If required (via parameters @p useobjub or @p useobjlb), we add a row corresponding to the objective function with
    1044 * respect to the current lower and upper bounds.
    1045 */
    1046static
    1048 SCIP* origscip, /**< SCIP data structure */
    1049 SCIP_SEPA* sepa, /**< separator */
    1050 SCIP_SEPADATA* sepadata, /**< separator data */
    1051 CGMIP_MIPDATA* mipdata /**< data for sub-MIP */
    1052 )
    1053{
    1054 SCIP* subscip;
    1055 SCIP_COL** cols;
    1056 SCIP_ROW** rows;
    1057 SCIP_Real* lhs;
    1058 SCIP_Real* rhs;
    1059 SCIP_Real* lb;
    1060 SCIP_Real* ub;
    1061 SCIP_Real* primsol;
    1062 SCIP_Real multvarub;
    1063
    1064 unsigned int cnt;
    1065 unsigned int ucnt;
    1066 unsigned int nshifted;
    1067 unsigned int ncomplemented;
    1068#ifndef NDEBUG
    1069 unsigned int ncontconverted = 0;
    1070 unsigned int nintconverted = 0;
    1071#endif
    1072 unsigned int nlbounds;
    1073 unsigned int nubounds;
    1074
    1075 SCIP_VAR** consvars;
    1076 SCIP_Real* consvals;
    1077 SCIP_CONS* cons;
    1078 int nconsvars;
    1079 char name[SCIP_MAXSTRLEN];
    1080
    1081 int ncols;
    1082 int nrows;
    1083 int ntotalrows;
    1084 int maxrowsize = 0;
    1085 int minrowsize = INT_MAX;
    1086 int i, j;
    1087
    1088 assert( origscip != NULL );
    1089 assert( sepadata != NULL );
    1090
    1091 assert( mipdata->subscip == NULL );
    1092
    1093 SCIP_CALL( SCIPgetLPColsData(origscip, &cols, &ncols) );
    1094 SCIP_CALL( SCIPgetLPRowsData(origscip, &rows, &nrows) );
    1095 assert( ncols > 0 && nrows > 0 );
    1096
    1097 mipdata->m = 0;
    1098 mipdata->n = 0;
    1099 mipdata->nrows = (unsigned int) nrows;
    1100 mipdata->ncols = (unsigned int) ncols;
    1101 mipdata->ntotalrows = mipdata->nrows;
    1102
    1103 if ( sepadata->useobjub || sepadata->useobjlb )
    1104 mipdata->ntotalrows = mipdata->nrows + 1;
    1105
    1106 assert(mipdata->ntotalrows <= INT_MAX);
    1107 ntotalrows = (int) mipdata->ntotalrows;
    1108
    1109 /* copy value */
    1110 mipdata->conshdlrusenorm = sepadata->conshdlrusenorm;
    1111
    1112 /* create subscip */
    1113 SCIP_CALL( SCIPcreate( &(mipdata->subscip) ) );
    1114 subscip = mipdata->subscip;
    1116
    1117 /* add violation constraint handler if requested */
    1118 if ( sepadata->addviolconshdlr )
    1119 {
    1120 SCIP_CALL( SCIPincludeConshdlrViolatedCut(subscip, mipdata) );
    1121 }
    1122
    1123 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sepa_cgmip separating MIP (%s)", SCIPgetProbName(origscip));
    1124 SCIP_CALL( SCIPcreateProb(subscip, name, NULL, NULL , NULL , NULL , NULL , NULL , NULL) );
    1125 SCIPsetSubscipDepth(subscip, SCIPgetSubscipDepth(origscip) + 1);
    1127
    1128 /* alloc memory for subscipdata elements */
    1129 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->alpha), ncols) );
    1130 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->fracalpha), ncols) );
    1131 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->coltype), ncols) );
    1132 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->iscomplemented), ncols) );
    1133 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->isshifted), ncols) );
    1134 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->ylhs), ntotalrows) );
    1135 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->yrhs), ntotalrows) );
    1136 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->z), 2*ncols) );
    1137 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->lhs), ntotalrows) );
    1138 SCIP_CALL( SCIPallocBlockMemoryArray(origscip, &(mipdata->rhs), ntotalrows) );
    1139 lhs = mipdata->lhs;
    1140 rhs = mipdata->rhs;
    1141
    1142 /* get temporary storage */
    1143 SCIP_CALL( SCIPallocBufferArray(origscip, &lb, ncols) );
    1144 SCIP_CALL( SCIPallocBufferArray(origscip, &ub, ncols) );
    1145 SCIP_CALL( SCIPallocBufferArray(origscip, &primsol, ncols) );
    1146
    1147 /* store lhs/rhs for complementing (see below) and compute maximal nonzeros of candidate rows */
    1148 for (i = 0; i < nrows; ++i)
    1149 {
    1150 SCIP_Real val;
    1151 SCIP_ROW* row;
    1152
    1153 row = rows[i];
    1154 assert( row != NULL );
    1155
    1156 val = SCIProwGetLhs(row) - SCIProwGetConstant(row);
    1157 if ( SCIProwIsIntegral(row) )
    1158 val = SCIPfeasCeil(origscip, val); /* row is integral: round left hand side up */
    1159 lhs[i] = val;
    1160
    1161 val = SCIProwGetRhs(row) - SCIProwGetConstant(row);
    1162 if ( SCIProwIsIntegral(row) )
    1163 val = SCIPfeasFloor(origscip, val); /* row is integral: round right hand side down */
    1164 rhs[i] = val;
    1165
    1166 /* skip modifiable rows and local rows, unless allowed */
    1167 if ( SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && !sepadata->allowlocal) )
    1168 continue;
    1169
    1170 /* skip rows that not have been active for a longer time */
    1171 if ( ! sepadata->onlyactiverows && sepadata->maxrowage > 0 && SCIProwGetAge(row) > sepadata->maxrowage )
    1172 continue;
    1173
    1174 /* check whether we want to skip cuts produced by the CGMIP separator */
    1175 if ( sepadata->onlyrankone )
    1176 {
    1177 if ( SCIProwGetOriginSepa(row) == sepa )
    1178 continue;
    1179 }
    1180
    1181 /* determine maximal row size: */
    1182 val = SCIPgetRowLPActivity(origscip, row);
    1183 if ( ! SCIPisInfinity(origscip, REALABS(lhs[i])) )
    1184 {
    1185 if ( ! sepadata->onlyactiverows || SCIPisFeasEQ(origscip, val, SCIProwGetLhs(row)) )
    1186 {
    1187 if ( SCIProwGetNLPNonz(row) > maxrowsize )
    1188 maxrowsize = SCIProwGetNLPNonz(row);
    1189 if ( SCIProwGetNLPNonz(row) < minrowsize )
    1190 minrowsize = SCIProwGetNLPNonz(row);
    1191 }
    1192 }
    1193 else
    1194 {
    1195 if ( ! SCIPisInfinity(origscip, rhs[i]) )
    1196 {
    1197 if ( ! sepadata->onlyactiverows || SCIPisFeasEQ(origscip, val, SCIProwGetRhs(row)) )
    1198 {
    1199 if ( SCIProwGetNLPNonz(row) > maxrowsize )
    1200 maxrowsize = SCIProwGetNLPNonz(row);
    1201 if ( SCIProwGetNLPNonz(row) < minrowsize )
    1202 minrowsize = SCIProwGetNLPNonz(row);
    1203 }
    1204 }
    1205 }
    1206 }
    1207 assert( maxrowsize > 0 );
    1208 assert( minrowsize < INT_MAX );
    1209
    1210 /* add cuts for objective function if required */
    1211 if ( sepadata->useobjub )
    1212 {
    1213 assert( mipdata->ntotalrows == mipdata->nrows + 1 );
    1214 rhs[mipdata->nrows] = SCIPgetUpperbound(origscip);
    1215 assert( ! SCIPisObjIntegral(origscip) || SCIPisFeasIntegral(origscip, SCIPgetUpperbound(origscip)) );
    1216
    1217 if ( ! SCIPisInfinity(origscip, SCIPgetUpperbound(origscip)) && SCIPgetNObjVars(origscip) > maxrowsize )
    1218 maxrowsize = SCIPgetNObjVars(origscip);
    1219 if ( ! SCIPisInfinity(origscip, SCIPgetUpperbound(origscip)) && SCIPgetNObjVars(origscip) < minrowsize )
    1220 minrowsize = SCIPgetNObjVars(origscip);
    1221 }
    1222 if ( sepadata->useobjlb )
    1223 {
    1224 assert( mipdata->ntotalrows == mipdata->nrows + 1 );
    1225
    1226 if ( SCIPisObjIntegral(origscip) )
    1227 lhs[mipdata->nrows] = SCIPfeasCeil(origscip, SCIPgetLowerbound(origscip));
    1228 else
    1229 lhs[mipdata->nrows] = SCIPgetLowerbound(origscip);
    1230
    1231 if ( ! SCIPisInfinity(origscip, -SCIPgetLowerbound(origscip)) && SCIPgetNObjVars(origscip) > maxrowsize )
    1232 maxrowsize = SCIPgetNObjVars(origscip);
    1233 if ( ! SCIPisInfinity(origscip, -SCIPgetLowerbound(origscip)) && SCIPgetNObjVars(origscip) < minrowsize )
    1234 minrowsize = SCIPgetNObjVars(origscip);
    1235 }
    1236
    1237 /* store lb/ub for complementing and perform preprocessing */
    1238 nshifted = 0;
    1239 ncomplemented = 0;
    1240 nlbounds = 0;
    1241 nubounds = 0;
    1242 for (j = 0; j < ncols; ++j)
    1243 {
    1244 SCIP_COL* col;
    1245 SCIP_VAR* var;
    1246
    1247 col = cols[j];
    1248 assert( col != NULL );
    1249 var = SCIPcolGetVar(col);
    1250 assert( var != NULL );
    1251
    1252 primsol[j] = SCIPcolGetPrimsol(col);
    1253 assert( SCIPisEQ(origscip, SCIPgetVarSol(origscip, var), primsol[j]) );
    1254
    1255 lb[j] = SCIPvarGetLbGlobal(var);
    1256 assert( SCIPisEQ(origscip, SCIPvarGetLbLocal(var), SCIPcolGetLb(col)) );
    1257
    1258 /* if allowed, try to use stronger local bound */
    1259 if ( sepadata->allowlocal && SCIPisGT(origscip, SCIPvarGetLbLocal(var), lb[j]) )
    1260 lb[j] = SCIPvarGetLbLocal(var);
    1261
    1262 ub[j] = SCIPvarGetUbGlobal(var);
    1263 assert( SCIPisEQ(origscip, SCIPvarGetUbLocal(var), SCIPcolGetUb(col)) );
    1264
    1265 /* if allowed, try to use stronger local bound */
    1266 if ( sepadata->allowlocal && SCIPisLT(origscip, SCIPvarGetUbLocal(var), ub[j]) )
    1267 ub[j] = SCIPvarGetUbLocal(var);
    1268
    1269 mipdata->coltype[j] = colPresent;
    1270 mipdata->iscomplemented[j] = FALSE;
    1271 mipdata->isshifted[j] = FALSE;
    1272
    1273 /* check status of column/variable */
    1274 if ( SCIPcolIsIntegral(col) )
    1275 {
    1276 /* integral variables taking integral values are not interesting - will be substituted out below */
    1277 if ( ! SCIPisFeasIntegral(origscip, primsol[j]) )
    1278 {
    1279 /* possibly convert fractional integral variables to take integral values */
    1280 if ( sepadata->intconvert && ncols >= sepadata->intconvmin )
    1281 {
    1282 /* randomly convert variables */
    1283 if ( SCIPrandomGetReal(sepadata->randnumgen, 0.0, 1.0) <= sepadata->intconvfrac )
    1284 {
    1285 assert( ! SCIPisInfinity(origscip, ub[j]) || ! SCIPisInfinity(origscip, -lb[j]) );
    1286
    1287 /* if both bounds are finite, take the closer one */
    1288 if ( ! SCIPisInfinity(origscip, ub[j]) && ! SCIPisInfinity(origscip, -lb[j]) )
    1289 {
    1290 assert( SCIPisFeasIntegral(origscip, ub[j]) );
    1291 assert( SCIPisFeasIntegral(origscip, lb[j]) );
    1292 assert( SCIPisFeasLT(origscip, primsol[j], ub[j]) );
    1293 assert( SCIPisFeasGT(origscip, primsol[j], lb[j]) );
    1294 if ( ub[j] - primsol[j] < primsol[j] - lb[j] )
    1295 primsol[j] = ub[j];
    1296 else
    1297 primsol[j] = lb[j];
    1298#ifndef NDEBUG
    1299 ++nintconverted;
    1300#endif
    1301 }
    1302 else
    1303 {
    1304 /* if only lower bound is finite */
    1305 if ( ! SCIPisInfinity(origscip, -lb[j]) )
    1306 {
    1307 assert( SCIPisFeasIntegral(origscip, lb[j]) );
    1308 primsol[j] = lb[j];
    1309#ifndef NDEBUG
    1310 ++nintconverted;
    1311#endif
    1312 }
    1313 else
    1314 {
    1315 assert( ! SCIPisInfinity(origscip, ub[j]) );
    1316 assert( SCIPisFeasIntegral(origscip, ub[j]) );
    1317 primsol[j] = ub[j];
    1318#ifndef NDEBUG
    1319 ++nintconverted;
    1320#endif
    1321 }
    1322 }
    1323 }
    1324 }
    1325 }
    1326
    1327 /* integral variables taking integral values are not interesting - will be substituted out below */
    1328 if ( ! SCIPisFeasIntegral(origscip, primsol[j]) )
    1329 {
    1330 /* possibly convert integral variables to be continuous */
    1331 if ( sepadata->contconvert && ncols >= sepadata->contconvmin )
    1332 {
    1333 /* randomly convert variables */
    1334 if ( SCIPrandomGetReal(sepadata->randnumgen, 0.0, 1.0) <= sepadata->contconvfrac )
    1335 {
    1336 /* preprocessing is also performed for converted columns */
    1337 mipdata->coltype[j] = colConverted;
    1338#ifndef NDEBUG
    1339 ++ncontconverted;
    1340#endif
    1341 }
    1342 }
    1343 }
    1344 }
    1345 else
    1346 {
    1347 /* detect continuous variables, but perform preprocessing for them */
    1348 mipdata->coltype[j] = colContinuous;
    1349 }
    1350
    1351 /* if integer variable is at its upper bound -> complementing (this also generates a 0 lower bound) */
    1352 if ( mipdata->coltype[j] == colPresent && SCIPisFeasEQ(origscip, primsol[j], ub[j]) )
    1353 {
    1354 assert( ! SCIPisInfinity(origscip, ub[j]) );
    1355 SCIP_CALL( transformColumn(origscip, sepadata, mipdata, col, ub[j], -1.0, lhs, rhs, &(lb[j]), &(ub[j]), &(primsol[j])) );
    1356 mipdata->iscomplemented[j] = TRUE;
    1357 mipdata->coltype[j] = colAtUb;
    1358 ++nubounds;
    1359 }
    1360 else
    1361 {
    1362 /* if a variable has a finite nonzero lower bound -> shift */
    1363 if ( ! SCIPisInfinity(origscip, -lb[j]) )
    1364 {
    1365 if ( ! SCIPisZero(origscip, lb[j]) )
    1366 {
    1367 SCIP_CALL( transformColumn(origscip, sepadata, mipdata, col, -lb[j], 1.0, lhs, rhs, &(lb[j]), &(ub[j]), &(primsol[j])) );
    1368 assert( SCIPisZero(origscip, lb[j]) );
    1369 mipdata->isshifted[j] = TRUE;
    1370 ++nshifted;
    1371 }
    1372
    1373 /* if integer variable is at its lower bound */
    1374 if ( mipdata->coltype[j] == colPresent && SCIPisZero(origscip, primsol[j]) )
    1375 {
    1376 mipdata->coltype[j] = colAtLb;
    1377 ++nlbounds;
    1378 }
    1379 }
    1380 else
    1381 {
    1382 /* lower bound is minus-infinity -> check whether upper bound is finite */
    1383 if ( ! SCIPisInfinity(origscip, ub[j]) )
    1384 {
    1385 /* complement variable */
    1386 SCIP_CALL( transformColumn(origscip, sepadata, mipdata, col, ub[j], -1.0, lhs, rhs, &(lb[j]), &(ub[j]), &(primsol[j])) );
    1387 assert( SCIPisZero(origscip, lb[j]) );
    1388 mipdata->iscomplemented[j] = TRUE;
    1389 ++ncomplemented;
    1390
    1391 /* if integer variable is at its lower bound */
    1392 if ( mipdata->coltype[j] == colPresent && SCIPisZero(origscip, primsol[j]) )
    1393 {
    1394 mipdata->coltype[j] = colAtLb;
    1395 ++nlbounds;
    1396 }
    1397 }
    1398 }
    1399 }
    1400
    1401 assert( SCIPisFeasLE(origscip, lb[j], primsol[j]) );
    1402 assert( SCIPisFeasLE(origscip, primsol[j], ub[j]) );
    1403 }
    1404
    1405#ifndef NDEBUG
    1406 if ( sepadata->intconvert && ncols >= sepadata->intconvmin )
    1407 {
    1408 SCIPdebugMsg(origscip, "Converted %u fractional integral variables to have integral value.\n", nintconverted);
    1409 }
    1410 if ( sepadata->contconvert && ncols >= sepadata->contconvmin )
    1411 {
    1412 SCIPdebugMsg(origscip, "Converted %u integral variables to be continuous.\n", ncontconverted);
    1413 }
    1414#endif
    1415 SCIPdebugMsg(origscip, "Original variables: %d integral, %d continuous, %u shifted, %u complemented, %u at lb, %u at ub\n",
    1416 SCIPgetNBinVars(origscip) + SCIPgetNIntVars(origscip) + SCIPgetNImplVars(origscip), SCIPgetNContVars(origscip),
    1417 nshifted, ncomplemented, nlbounds, nubounds);
    1418
    1419 /* prepare upper bound on y-variables */
    1420 if ( sepadata->skipmultbounds )
    1421 multvarub = SCIPinfinity(origscip);
    1422 else
    1423 multvarub = 1.0 - EPSILONVALUE;
    1424
    1425 /* create artificial variables for row combinations (y-variables) */
    1426 cnt = 0;
    1427 for (i = 0; i < nrows; ++i)
    1428 {
    1429 SCIP_ROW* row;
    1430
    1431 row = rows[i];
    1432 assert( row != NULL );
    1433
    1434 mipdata->ylhs[i] = NULL;
    1435 mipdata->yrhs[i] = NULL;
    1436
    1437 /* skip modifiable rows and local rows, unless allowed */
    1438 if ( SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && !sepadata->allowlocal) )
    1439 continue;
    1440
    1441 /* skip rows that not have been active for a longer time */
    1442 if ( ! sepadata->onlyactiverows && sepadata->maxrowage > 0 && SCIProwGetAge(row) > sepadata->maxrowage )
    1443 continue;
    1444
    1445 /* check whether we want to skip cuts produced by the CGMIP separator */
    1446 if ( sepadata->onlyrankone )
    1447 {
    1448 if ( SCIProwGetOriginSepa(row) == sepa )
    1449 continue;
    1450 }
    1451
    1452 /* if we have an equation */
    1453 if ( SCIPisEQ(origscip, lhs[i], rhs[i]) )
    1454 {
    1455 SCIP_Real weight = -sepadata->objweight;
    1456
    1457 assert( ! SCIPisInfinity(origscip, rhs[i]) );
    1458 assert( SCIPisFeasEQ(origscip, SCIPgetRowLPActivity(origscip, row), SCIProwGetLhs(row)) ); /* equations should always be active */
    1459 assert( SCIPisFeasEQ(origscip, SCIPgetRowLPActivity(origscip, row), SCIProwGetRhs(row)) );
    1460
    1461 if ( sepadata->objweightsize )
    1462 weight = - sepadata->objweight * computeObjWeightSize(SCIProwGetNLPNonz(row), minrowsize, maxrowsize);
    1463
    1464 /* create two variables for each equation */
    1465 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "yeq1_%d", i);
    1466 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->ylhs[i]), name, 0.0, multvarub,
    1468 SCIP_CALL( SCIPaddVar(subscip, mipdata->ylhs[i]) );
    1469 ++cnt;
    1470
    1471#ifdef SCIP_MORE_DEBUG
    1472 SCIPdebugMsg(origscip, "Created variable <%s> for equation <%s>.\n", name, SCIProwGetName(row));
    1473#endif
    1474
    1475 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "yeq2_%d", i);
    1476 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->yrhs[i]), name, 0.0, multvarub,
    1478 SCIP_CALL( SCIPaddVar(subscip, mipdata->yrhs[i]) );
    1479 ++cnt;
    1480
    1481#ifdef SCIP_MORE_DEBUG
    1482 SCIPdebugMsg(origscip, "Created variable <%s> for equation <%s>.\n", name, SCIProwGetName(row));
    1483#endif
    1484 }
    1485 else
    1486 {
    1487 /* create variable for lhs of row if necessary */
    1488 if ( ! SCIPisInfinity(origscip, -lhs[i]) )
    1489 {
    1490 SCIP_Bool isactive = FALSE;
    1491 SCIP_Real weight = 0.0;
    1492
    1493 /* if the row is active, use objective weight equal to -sepadata->objweight */
    1494 if ( SCIPisFeasEQ(origscip, SCIPgetRowLPActivity(origscip, row), SCIProwGetLhs(row)) )
    1495 {
    1496 isactive = TRUE;
    1497 if ( sepadata->objweightsize )
    1498 weight = -sepadata->objweight * computeObjWeightSize(SCIProwGetNLPNonz(row), minrowsize, maxrowsize);
    1499 else
    1500 weight = -sepadata->objweight;
    1501 }
    1502
    1503 if ( ! sepadata->onlyactiverows || isactive )
    1504 {
    1505 /* add variable */
    1506 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ylhs_%d", i);
    1507 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->ylhs[i]), name, 0.0, multvarub,
    1509 SCIP_CALL( SCIPaddVar(subscip, mipdata->ylhs[i]) );
    1510 ++cnt;
    1511
    1512#ifdef SCIP_MORE_DEBUG
    1513 SCIPdebugMsg(origscip, "Created variable <%s> for >= inequality <%s> (weight: %f).\n", name, SCIProwGetName(row), weight);
    1514#endif
    1515 }
    1516 }
    1517
    1518 /* create variable for rhs of row if necessary */
    1519 if ( ! SCIPisInfinity(origscip, rhs[i]) )
    1520 {
    1521 SCIP_Bool isactive = FALSE;
    1522 SCIP_Real weight = 0.0;
    1523
    1524 /* if the row is active, use objective weight equal to -sepadata->objweight */
    1525 if ( SCIPisFeasEQ(origscip, SCIPgetRowLPActivity(origscip, row), SCIProwGetRhs(row)) )
    1526 {
    1527 isactive = TRUE;
    1528 if ( sepadata->objweightsize )
    1529 weight = -sepadata->objweight * computeObjWeightSize(SCIProwGetNLPNonz(row), minrowsize, maxrowsize);
    1530 else
    1531 weight = -sepadata->objweight;
    1532 }
    1533
    1534 if ( ! sepadata->onlyactiverows || isactive )
    1535 {
    1536 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "yrhs_%d", i);
    1537 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->yrhs[i]), name, 0.0, multvarub,
    1539 SCIP_CALL( SCIPaddVar(subscip, mipdata->yrhs[i]) );
    1540 ++cnt;
    1541
    1542#ifdef SCIP_MORE_DEBUG
    1543 SCIPdebugMsg(origscip, "Created variable <%s> for <= inequality <%s> (weight: %f).\n", name, SCIProwGetName(row), weight);
    1544#endif
    1545 }
    1546 }
    1547 }
    1548 }
    1549 assert( (int) cnt <= 2 * nrows );
    1550 mipdata->n += cnt;
    1551
    1552 /* create artificial variables for objective function (if required) (y-variables) */
    1553 if ( sepadata->useobjub || sepadata->useobjlb )
    1554 {
    1555 SCIP_Real weight = 0.0;
    1556
    1557 assert( mipdata->ntotalrows == mipdata->nrows + 1 );
    1558 mipdata->ylhs[mipdata->nrows] = NULL;
    1559 mipdata->yrhs[mipdata->nrows] = NULL;
    1560 cnt = 0;
    1561
    1562 if ( sepadata->objweightsize )
    1563 weight = -sepadata->objweight * computeObjWeightSize(SCIPgetNObjVars(origscip), minrowsize, maxrowsize);
    1564 else
    1565 weight = -sepadata->objweight;
    1566
    1567 /* create variable for upper objective bound if necessary */
    1568 if ( sepadata->useobjub && ! SCIPisInfinity(origscip, rhs[mipdata->nrows]) )
    1569 {
    1570 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "yobjub");
    1571 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->yrhs[mipdata->nrows]), name, 0.0, multvarub,
    1573 SCIP_CALL( SCIPaddVar(subscip, mipdata->yrhs[mipdata->nrows]) );
    1574 ++cnt;
    1575
    1576#ifdef SCIP_MORE_DEBUG
    1577 SCIPdebugMsg(origscip, "Created variable <%s> for upper bound on objective (weight: %f).\n", name, weight);
    1578#endif
    1579 }
    1580
    1581 /* create variable for lower bound objective if necessary */
    1582 if ( sepadata->useobjlb && ! SCIPisInfinity(origscip, -lhs[mipdata->nrows]) )
    1583 {
    1584 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "yobjlb");
    1585 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->ylhs[mipdata->nrows]), name, 0.0, multvarub,
    1587 SCIP_CALL( SCIPaddVar(subscip, mipdata->ylhs[mipdata->nrows]) );
    1588 ++cnt;
    1589
    1590#ifdef SCIP_MORE_DEBUG
    1591 SCIPdebugMsg(origscip, "Created variable <%s> for lower bound on objective (weight: %f).\n", name, weight);
    1592#endif
    1593 }
    1594
    1595 assert( (int) cnt <= 2 * ntotalrows );
    1596 mipdata->n += cnt;
    1597 }
    1598
    1599 /* create alpha, bound, and fractional variables */
    1600 cnt = 0;
    1601 ucnt = 0;
    1602 for (j = 0; j < ncols; ++j)
    1603 {
    1604 mipdata->z[j] = NULL;
    1605 mipdata->alpha[j] = NULL;
    1606 mipdata->fracalpha[j] = NULL;
    1607
    1608 if ( mipdata->coltype[j] == colPresent )
    1609 {
    1610 SCIP_Real obj;
    1611
    1612 if ( sepadata->objlone )
    1613 obj = 0.0;
    1614 else
    1615 obj = primsol[j];
    1616
    1617 /* create alpha variables */
    1618 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "alpha_%d", j);
    1619 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->alpha[j]), name, -sepadata->cutcoefbnd, sepadata->cutcoefbnd, obj,
    1621 SCIP_CALL( SCIPaddVar(subscip, mipdata->alpha[j]) );
    1622 ++cnt;
    1623
    1624 /* create fractional variables */
    1625 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "f_%d", j);
    1626 if ( SCIPisInfinity(origscip, -lb[j]) && SCIPisInfinity(origscip, ub[j]) )
    1627 {
    1628 /* fix fractional value to be zero for free original variables */
    1629 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->fracalpha[j]), name, 0.0, 0.0, 0.0,
    1631 }
    1632 else
    1633 {
    1634 /* fractional value in [0, 1) for variables with finite bounds */
    1635 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->fracalpha[j]), name, 0.0, 1.0-EPSILONVALUE, 0.0,
    1637 }
    1638 SCIP_CALL( SCIPaddVar(subscip, mipdata->fracalpha[j]) );
    1639 ++cnt;
    1640
    1641 /* create variables for upper bounds */
    1642 if ( ! SCIPisInfinity(origscip, ub[j]) )
    1643 {
    1644 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "zub_%d", j);
    1645 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->z[j]), name, 0.0, multvarub,
    1647 SCIP_CALL( SCIPaddVar(subscip, mipdata->z[j]) );
    1648 ++ucnt;
    1649 }
    1650 }
    1651 }
    1652 assert( (int) cnt <= 2 * ncols );
    1653 assert( (int) ucnt <= ncols );
    1654
    1655 /* create variable for the rhs of the cut */
    1656 if ( sepadata->objlone )
    1657 {
    1658 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->beta), "beta", -sepadata->cutcoefbnd, sepadata->cutcoefbnd, 0.0,
    1660 }
    1661 else
    1662 {
    1663 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->beta), "beta", -sepadata->cutcoefbnd, sepadata->cutcoefbnd, -1.0,
    1665 }
    1666 SCIP_CALL( SCIPaddVar(subscip, mipdata->beta) );
    1667
    1668 /* create fractional variable for the rhs */
    1669 SCIP_CALL( SCIPcreateVar(subscip, &(mipdata->fracbeta), "fracbeta", 0.0, 1.0-BETAEPSILONVALUE, 0.0,
    1671 SCIP_CALL( SCIPaddVar(subscip, mipdata->fracbeta) );
    1672 mipdata->n += cnt + ucnt + 2;
    1673
    1674 /* get temporary storage */
    1675 SCIP_CALL( SCIPallocBufferArray(origscip, &consvals, (int) mipdata->n) );
    1676 SCIP_CALL( SCIPallocBufferArray(origscip, &consvars, (int) mipdata->n) );
    1677
    1678 /* create constraints for alpha variables of CG-cut */
    1679 cnt = 0;
    1680 for (j = 0; j < ncols; ++j)
    1681 {
    1682 SCIP_ROW** colrows;
    1683 SCIP_Real* colvals;
    1684
    1685 /* create ordinary part for all selected variables */
    1686 if ( mipdata->coltype[j] == colPresent )
    1687 {
    1688 SCIP_Real sigma;
    1689
    1690 assert( cols[j] != NULL );
    1691 colrows = SCIPcolGetRows(cols[j]);
    1692 colvals = SCIPcolGetVals(cols[j]);
    1693 nconsvars = 0;
    1694
    1695 if ( mipdata->iscomplemented[j] )
    1696 sigma = -1.0;
    1697 else
    1698 sigma = 1.0;
    1699
    1700 /* add part for columns */
    1701 for (i = 0; i < SCIPcolGetNLPNonz(cols[j]); ++i)
    1702 {
    1703 SCIP_ROW* row;
    1704 int pos;
    1705
    1706 row = colrows[i];
    1707 assert( row != NULL );
    1708
    1709 /* skip modifiable rows and local rows, unless allowed */
    1710 if ( SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && !sepadata->allowlocal) )
    1711 continue;
    1712
    1713 pos = SCIProwGetLPPos(row);
    1714 assert( 0 <= pos && pos < nrows );
    1715
    1716 if ( mipdata->ylhs[pos] != NULL )
    1717 {
    1718 consvars[nconsvars] = mipdata->ylhs[pos];
    1719 consvals[nconsvars] = -sigma * colvals[i];
    1720 ++nconsvars;
    1721 }
    1722 if ( mipdata->yrhs[pos] != NULL )
    1723 {
    1724 consvars[nconsvars] = mipdata->yrhs[pos];
    1725 consvals[nconsvars] = sigma * colvals[i];
    1726 ++nconsvars;
    1727 }
    1728 assert( nconsvars <= (int) mipdata->n );
    1729 }
    1730 /* add part for upper bounds */
    1731 if ( mipdata->z[j] != NULL )
    1732 {
    1733 assert( ! SCIPisInfinity(origscip, ub[j]) );
    1734 consvars[nconsvars] = mipdata->z[j];
    1735 consvals[nconsvars] = 1.0;
    1736 ++nconsvars;
    1737 }
    1738 assert( nconsvars <= (int) mipdata->n );
    1739
    1740 /* add alpha variable */
    1741 consvars[nconsvars] = mipdata->alpha[j];
    1742 consvals[nconsvars] = -1.0;
    1743 ++nconsvars;
    1744 assert( nconsvars <= (int) mipdata->n );
    1745
    1746 /* add fractional-alpha variable */
    1747 consvars[nconsvars] = mipdata->fracalpha[j];
    1748 consvals[nconsvars] = -1.0;
    1749 ++nconsvars;
    1750 assert( nconsvars <= (int) mipdata->n );
    1751
    1752 /* check for lower and upper objective bounds */
    1753 if ( (sepadata->useobjub || sepadata->useobjlb) && ! SCIPisZero(origscip, SCIPcolGetObj(cols[j])) )
    1754 {
    1755 /* add lower objective bound */
    1756 if ( mipdata->ylhs[mipdata->nrows] != NULL )
    1757 {
    1758 assert( sepadata->useobjlb );
    1759 consvars[nconsvars] = mipdata->ylhs[mipdata->nrows];
    1760 consvals[nconsvars] = -sigma * SCIPcolGetObj(cols[j]);
    1761 ++nconsvars;
    1762 }
    1763
    1764 /* add upper objective bound */
    1765 if ( mipdata->yrhs[mipdata->nrows] != NULL )
    1766 {
    1767 assert( sepadata->useobjub );
    1768 consvars[nconsvars] = mipdata->yrhs[mipdata->nrows];
    1769 consvals[nconsvars] = sigma * SCIPcolGetObj(cols[j]);
    1770 ++nconsvars;
    1771 }
    1772 }
    1773
    1774 /* add linear constraint */
    1775 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "alpha_%d", j);
    1776 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, name, nconsvars, consvars, consvals, 0.0, 0.0,
    1778 SCIP_CALL( SCIPaddCons(subscip, cons) );
    1779 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
    1780 ++cnt;
    1781 }
    1782 /* generate part that makes sure that cut is valid for continuous variables */
    1783 else if ( mipdata->coltype[j] == colContinuous || mipdata->coltype[j] == colConverted )
    1784 {
    1785 SCIP_Real sigma;
    1786 SCIP_Real r;
    1787
    1788 assert( cols[j] != NULL );
    1789 colrows = SCIPcolGetRows(cols[j]);
    1790 colvals = SCIPcolGetVals(cols[j]);
    1791 nconsvars = 0;
    1792
    1793 if ( mipdata->iscomplemented[j] )
    1794 sigma = -1.0;
    1795 else
    1796 sigma = 1.0;
    1797
    1798 /* add part for columns */
    1799 for (i = 0; i < SCIPcolGetNLPNonz(cols[j]); ++i)
    1800 {
    1801 SCIP_ROW* row;
    1802 int pos;
    1803
    1804 row = colrows[i];
    1805 assert( row != NULL );
    1806
    1807 /* skip modifiable rows and local rows, unless allowed */
    1808 if ( SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && !sepadata->allowlocal) )
    1809 continue;
    1810
    1811 pos = SCIProwGetLPPos(row);
    1812 assert( 0 <= pos && pos < nrows );
    1813
    1814 if ( mipdata->ylhs[pos] != NULL )
    1815 {
    1816 consvars[nconsvars] = mipdata->ylhs[pos];
    1817 consvals[nconsvars] = -sigma * colvals[i];
    1818 ++nconsvars;
    1819 }
    1820 if ( mipdata->yrhs[pos] != NULL )
    1821 {
    1822 consvars[nconsvars] = mipdata->yrhs[pos];
    1823 consvals[nconsvars] = sigma * colvals[i];
    1824 ++nconsvars;
    1825 }
    1826 assert( nconsvars <= (int) mipdata->n );
    1827 }
    1828
    1829 /* check for lower and upper objective bounds */
    1830 if ( (sepadata->useobjub || sepadata->useobjlb) && ! SCIPisZero(origscip, SCIPcolGetObj(cols[j])) )
    1831 {
    1832 /* add lower objective bound */
    1833 if ( mipdata->ylhs[mipdata->nrows] )
    1834 {
    1835 assert( sepadata->useobjlb );
    1836 consvars[nconsvars] = mipdata->ylhs[mipdata->nrows];
    1837 consvals[nconsvars] = -sigma * SCIPcolGetObj(cols[j]);
    1838 ++nconsvars;
    1839 }
    1840
    1841 /* add upper objective bound */
    1842 if ( mipdata->yrhs[mipdata->nrows] )
    1843 {
    1844 assert( sepadata->useobjub );
    1845 consvars[nconsvars] = mipdata->yrhs[mipdata->nrows];
    1846 consvals[nconsvars] = sigma * SCIPcolGetObj(cols[j]);
    1847 ++nconsvars;
    1848 }
    1849 }
    1850
    1851 /* add linear constraint */
    1852 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cont_%d", j);
    1853
    1854 /* for free continuous variables require equality */
    1855 r = SCIPinfinity(subscip);
    1856 if ( SCIPisInfinity(origscip, -lb[j]) && SCIPisInfinity(origscip, ub[j]) )
    1857 r = 0.0;
    1858 else
    1859 assert( SCIPisZero(origscip, lb[j]) );
    1860
    1861 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, name, nconsvars, consvars, consvals, 0.0, r,
    1863 SCIP_CALL( SCIPaddCons(subscip, cons) );
    1864 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
    1865 ++cnt;
    1866 }
    1867 }
    1868 assert( (int) cnt <= ncols );
    1869 mipdata->m += cnt;
    1870
    1871 /* create constraints for rhs of cut */
    1872 nconsvars = 0;
    1873
    1874 /* first for the rows */
    1875 for (i = 0; i < nrows; ++i)
    1876 {
    1877 assert( rows[i] != NULL );
    1878
    1879 /* skip modifiable rows and local rows, unless allowed */
    1880 if ( SCIProwIsModifiable(rows[i]) || (SCIProwIsLocal(rows[i]) && !sepadata->allowlocal) )
    1881 continue;
    1882
    1883 /* if lhs is there */
    1884 if ( mipdata->ylhs[i] != NULL && ! SCIPisZero(origscip, lhs[i]) )
    1885 {
    1886 assert( ! SCIPisInfinity(origscip, -lhs[i]) );
    1887 consvars[nconsvars] = mipdata->ylhs[i];
    1888 consvals[nconsvars] = -lhs[i];
    1889 ++nconsvars;
    1890 }
    1891 /* if rhs is there */
    1892 if ( mipdata->yrhs[i] != NULL && ! SCIPisZero(origscip, rhs[i]) )
    1893 {
    1894 assert( ! SCIPisInfinity(origscip, rhs[i]) );
    1895 consvars[nconsvars] = mipdata->yrhs[i];
    1896 consvals[nconsvars] = rhs[i];
    1897 ++nconsvars;
    1898 }
    1899 assert( nconsvars <= (int) mipdata->n );
    1900 }
    1901
    1902 if ( sepadata->useobjub || sepadata->useobjlb )
    1903 {
    1904 /* add lower objective bound */
    1905 if ( mipdata->ylhs[mipdata->nrows] != NULL && ! SCIPisZero(origscip, lhs[mipdata->nrows]) )
    1906 {
    1907 assert( sepadata->useobjlb );
    1908 assert( ! SCIPisInfinity(origscip, -lhs[mipdata->nrows]) );
    1909 consvars[nconsvars] = mipdata->ylhs[mipdata->nrows];
    1910 consvals[nconsvars] = -lhs[mipdata->nrows];
    1911 ++nconsvars;
    1912 }
    1913
    1914 /* add upper objective bound */
    1915 if ( mipdata->yrhs[mipdata->nrows] != NULL && ! SCIPisZero(origscip, rhs[mipdata->nrows]) )
    1916 {
    1917 assert( sepadata->useobjub );
    1918 assert( ! SCIPisInfinity(origscip, rhs[mipdata->nrows]) );
    1919 consvars[nconsvars] = mipdata->yrhs[mipdata->nrows];
    1920 consvals[nconsvars] = rhs[mipdata->nrows];
    1921 ++nconsvars;
    1922 }
    1923 assert( nconsvars <= (int) mipdata->n );
    1924 }
    1925
    1926 /* next for the columns */
    1927 for (j = 0; j < ncols; ++j)
    1928 {
    1929 /* if ub is there */
    1930 if ( mipdata->z[j] != NULL && ! SCIPisZero(origscip, ub[j]) )
    1931 {
    1932 assert( mipdata->coltype[j] == colPresent );
    1933 assert( ! SCIPisInfinity(origscip, ub[j]) );
    1934 consvars[nconsvars] = mipdata->z[j];
    1935 consvals[nconsvars] = ub[j];
    1936 ++nconsvars;
    1937 assert( nconsvars <= (int) mipdata->n );
    1938 }
    1939 }
    1940 /* add beta variable */
    1941 consvars[nconsvars] = mipdata->beta;
    1942 consvals[nconsvars] = -1.0;
    1943 ++nconsvars;
    1944
    1945 /* add fractional-beta variable */
    1946 consvars[nconsvars] = mipdata->fracbeta;
    1947 consvals[nconsvars] = -1.0;
    1948 ++nconsvars;
    1949 assert( nconsvars <= (int) mipdata->n );
    1950
    1951 /* add linear constraint */
    1952 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, "beta", nconsvars, consvars, consvals, 0.0, 0.0,
    1954 SCIP_CALL( SCIPaddCons(subscip, cons) );
    1955 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
    1956 ++mipdata->m;
    1957
    1958 /* add primal separation constraint if required */
    1959 if ( sepadata->primalseparation )
    1960 {
    1961 SCIP_SOL* bestsol;
    1962 bestsol = SCIPgetBestSol(origscip);
    1963 if ( bestsol != NULL )
    1964 {
    1965 nconsvars = 0;
    1966 for (j = 0; j < ncols; ++j)
    1967 {
    1968 if ( mipdata->alpha[j] != NULL )
    1969 {
    1970 SCIP_Real val;
    1971 assert( mipdata->coltype[j] == colPresent );
    1972
    1973 val = SCIPgetSolVal(origscip, bestsol, SCIPcolGetVar(cols[j]));
    1974 consvars[nconsvars] = mipdata->alpha[j];
    1975 consvals[nconsvars] = val;
    1976 ++nconsvars;
    1977 assert( nconsvars <= (int) mipdata->n );
    1978 }
    1979 }
    1980 consvars[nconsvars] = mipdata->beta;
    1981 consvals[nconsvars] = -1.0;
    1982 ++nconsvars;
    1983
    1984 /* add linear constraint - allow slight deviation from equality */
    1985 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, "primalseparation", nconsvars, consvars, consvals, -EPSILONVALUE, EPSILONVALUE,
    1987 SCIP_CALL( SCIPaddCons(subscip, cons) );
    1988 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
    1989 ++mipdata->m;
    1990 }
    1991 }
    1992
    1993 /* add constraint to force violated cuts if required */
    1994 if ( sepadata->addviolationcons )
    1995 {
    1996 nconsvars = 0;
    1997 for (j = 0; j < ncols; ++j)
    1998 {
    1999 if ( mipdata->alpha[j] != NULL )
    2000 {
    2001 consvars[nconsvars] = mipdata->alpha[j];
    2002 consvals[nconsvars] = primsol[j];
    2003 ++nconsvars;
    2004 assert( nconsvars <= (int) mipdata->n );
    2005 }
    2006 }
    2007 consvars[nconsvars] = mipdata->beta;
    2008 consvals[nconsvars] = -1.0;
    2009 ++nconsvars;
    2010
    2011 /* add linear constraint - allow slight deviation from equality */
    2012 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, "violationConstraint", nconsvars, consvars, consvals, MINEFFICACY, SCIPinfinity(subscip),
    2014 SCIP_CALL( SCIPaddCons(subscip, cons) );
    2015 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
    2016 ++mipdata->m;
    2017 }
    2018
    2019 SCIPdebugMsg(origscip, "Subscip has %u vars (%d integral, %d continuous), %u conss.\n",
    2020 mipdata->n, SCIPgetNIntVars(subscip), SCIPgetNContVars(subscip), mipdata->m);
    2021
    2022 /* free temporary memory */
    2023 SCIPfreeBufferArray(origscip, &consvars);
    2024 SCIPfreeBufferArray(origscip, &consvals);
    2025
    2026 SCIPfreeBufferArray(origscip, &primsol);
    2027 SCIPfreeBufferArray(origscip, &lb);
    2028 SCIPfreeBufferArray(origscip, &ub);
    2029
    2030 /* SCIPdebug( SCIP_CALL( SCIPprintOrigProblem(subscip, NULL, NULL, FALSE) ) ); */
    2031
    2032#ifdef SCIP_WRITEPROB
    2033 {
    2034 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cgsepa%s%s%s%s_%s.lp",
    2035 sepadata->objlone ? "_l1" : "",
    2036 sepadata->addviolationcons ? "_vc" : "",
    2037 sepadata->skipmultbounds ? "_ub" : "",
    2038 sepadata->primalseparation ? "_ps" : "",
    2039 SCIPgetProbName(origscip));
    2040 SCIP_CALL( SCIPwriteOrigProblem(subscip, name, "lp", FALSE) );
    2041 SCIPinfoMessage(origscip, NULL, "Wrote subscip to file <%s>.\n", name);
    2042 }
    2043#endif
    2044
    2045 return SCIP_OKAY;
    2046}
    2047
    2048
    2049/** sets parameters for subscip */
    2050static
    2052 SCIP_SEPADATA* sepadata, /**< separator data */
    2053 CGMIP_MIPDATA* mipdata /**< data for sub-MIP */
    2054 )
    2055{
    2056 SCIP* subscip;
    2057
    2058 assert( sepadata != NULL );
    2059 assert( mipdata != NULL );
    2060
    2061 subscip = mipdata->subscip;
    2062 assert( subscip != NULL );
    2063
    2064 /* set objective limit, if no corresponding constraint has been added */
    2065 if ( ! sepadata->addviolationcons && ! sepadata->addviolconshdlr )
    2066 {
    2068 }
    2069
    2070 /* do not abort subscip on CTRL-C */
    2071 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    2072
    2073 /* disable memory saving mode: this is likely to result in the maximal depth being reached. This is because DFS
    2074 * results in a repeated branching on the alpha-variables, which often have large bounds resulting in deep levels of
    2075 * the tree. */
    2076 SCIP_CALL( SCIPsetRealParam(subscip, "memory/savefac", 1.0) );
    2077
    2078 /* set number of solutions stored */
    2079 SCIP_CALL( SCIPsetIntParam(subscip, "limits/maxsol", MAXNSOLS) );
    2080
    2081 /* determine output to console */
    2082#ifdef SCIP_OUTPUT
    2083 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    2084 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1000) );
    2085 SCIP_CALL( SCIPsetIntParam(subscip, "display/nsols/active", 2) );
    2086#else
    2087 if ( sepadata->output )
    2088 {
    2089 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    2090 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1000) );
    2091 SCIP_CALL( SCIPsetIntParam(subscip, "display/nsols/active", 2) );
    2092 }
    2093 else
    2094 {
    2095 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    2096 }
    2097#endif
    2098
    2099 if ( sepadata->subscipfast )
    2100 {
    2101 /* forbid recursive call of plugins solving subMIPs (also disables CG-separation) */
    2102#ifdef SCIP_OUTPUT
    2103 SCIP_CALL( SCIPsetSubscipsOff(subscip, FALSE) );
    2104#else
    2105 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) ); /* quiet */
    2106#endif
    2107 }
    2108 else
    2109 {
    2110 /* avoid recursive call */
    2111 if ( ! SCIPisParamFixed(subscip, "separating/cgmip/freq") )
    2112 {
    2113 SCIP_CALL( SCIPsetIntParam(subscip, "separating/cgmip/freq", -1) );
    2114 }
    2115 }
    2116
    2117#ifdef SCIP_DISABLED_CODE
    2118 /* the following possibly helps to improve performance (untested) */
    2120#else
    2121
    2122 /* zirounding is often successful, so allow it some more calls */
    2123 if ( ! SCIPisParamFixed(subscip, "heuristics/zirounding/minstopncalls") )
    2124 {
    2125 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/zirounding/minstopncalls", 10000) );
    2126 }
    2127
    2128 if ( sepadata->subscipfast )
    2129 {
    2130 /* set other heuristics */
    2131 if ( ! SCIPisParamFixed(subscip, "heuristics/shifting/freq") )
    2132 {
    2133 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/shifting/freq", 3) );
    2134 }
    2135 if ( ! SCIPisParamFixed(subscip, "heuristics/simplerounding/freq") )
    2136 {
    2137 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/simplerounding/freq", 1) );
    2138 }
    2139 if ( ! SCIPisParamFixed(subscip, "heuristics/rounding/freq") )
    2140 {
    2141 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/rounding/freq", 1) );
    2142 }
    2143 if ( ! SCIPisParamFixed(subscip, "heuristics/oneopt/freq") )
    2144 {
    2145 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/oneopt/freq", 1) );
    2146 }
    2147
    2148 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/pscostdiving/freq", 1) ); */
    2149 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/feaspump/freq", 3) ); */
    2150
    2151 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/coefdiving/freq", -1) ); */
    2152 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/fracdiving/freq", -1) ); */
    2153 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/guideddiving/freq", -1) ); */
    2154 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/linesearchdiving/freq", -1) ); */
    2155 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/objpscostdiving/freq", -1) ); */
    2156 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/rootsoldiving/freq", -1) ); */
    2157 /* SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/veclendiving/freq", -1) ); */
    2158
    2159 /* use fast presolving */
    2161
    2162 /* disable conflict analysis */
    2163 /* SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useprop", FALSE) ); */
    2164 /* SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useinflp", 'o') ); */
    2165 /* SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') ); */
    2166 /* SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usesb", FALSE) ); */
    2167 /* SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usepseudo", FALSE) ); */
    2168
    2169 /* use fast separation */
    2171 }
    2172#endif
    2173
    2174#ifdef SCIP_WRITEPROB
    2175 {
    2176 char name[SCIP_MAXSTRLEN];
    2177
    2178 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cgsepa%s%s%s%s_%s.set",
    2179 sepadata->objlone ? "_l1" : "",
    2180 sepadata->addviolationcons ? "_vc" : "",
    2181 sepadata->skipmultbounds ? "_ub" : "",
    2182 sepadata->primalseparation ? "_ps" : "",
    2183 SCIPgetProbName(mipdata->scip));
    2184 SCIP_CALL( SCIPwriteParams(subscip, name, TRUE, FALSE) );
    2185 SCIPinfoMessage(mipdata->scip, NULL, "Wrote settings to file <%s>.\n", name);
    2186 }
    2187#endif
    2188
    2189 return SCIP_OKAY;
    2190}
    2191
    2192
    2193/** try to convert fractional gomory cuts to primal solutions of CG-MIP */
    2194static
    2196 SCIP* scip, /**< original SCIP data structure */
    2197 SCIP_SEPADATA* sepadata, /**< separator data */
    2198 CGMIP_MIPDATA* mipdata /**< data for sub-MIP */
    2199 )
    2200{
    2201 SCIP_VAR** vars;
    2202 SCIP_ROW** rows;
    2203 SCIP_COL** cols;
    2204 SCIP_Real* binvrow;
    2205 SCIP_Real* cutcoefs;
    2206 int* basisind;
    2207 int nvars;
    2208 int nrows;
    2209 int ncols;
    2210 int ngen = 0;
    2211 int ntried = 0;
    2212 int i;
    2213
    2214 assert( scip != NULL );
    2215 assert( sepadata != NULL );
    2216 assert( mipdata != NULL );
    2217
    2218 /* get variables */
    2219 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    2220
    2221 /* get rows and columns */
    2222 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    2223 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    2224 assert( ncols <= nvars );
    2225
    2226 /* get storage */
    2227 SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
    2228 SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
    2229 SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, ncols) );
    2230
    2231 /* get basis indices */
    2232 SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
    2233
    2234 /* loop through rows */
    2235 for (i = 0; i < nrows; ++i)
    2236 {
    2237 SCIP_Bool tryrow = FALSE;
    2238 SCIP_Real primsol = SCIP_INVALID;
    2239 int c;
    2240 int r;
    2241
    2242 c = basisind[i];
    2243 assert( c < ncols );
    2244
    2245 if ( c >= 0 )
    2246 {
    2247 SCIP_VAR* var;
    2248
    2249 var = SCIPcolGetVar(cols[c]);
    2250
    2251 if( SCIPvarIsIntegral(var) )
    2252 {
    2253 primsol = SCIPcolGetPrimsol(cols[c]);
    2254 assert( SCIPgetVarSol(scip, var) == primsol ); /*lint !e777*/
    2255
    2256 if ( SCIPfeasFrac(scip, primsol) >= AWAY && SCIPfeasFrac(scip, primsol) <= 1 - AWAY )
    2257 tryrow = TRUE;
    2258 }
    2259 }
    2260#if ( SEPARATEROWS == TRUE )
    2261 else
    2262 {
    2263 SCIP_ROW* row;
    2264
    2265 assert(0 <= -c-1 && -c-1 < nrows);
    2266
    2267 row = rows[-c-1];
    2268
    2269 if ( SCIProwIsIntegral(row) && ! SCIProwIsModifiable(row) )
    2270 {
    2271 /* Compute value of the slack variable (we only care about the correct fractionality) */
    2272 if ( SCIPisInfinity(scip, SCIProwGetRhs(row)) )
    2273 primsol = SCIProwGetLhs(row) - SCIPgetRowLPActivity(scip, row);
    2274 else
    2275 primsol = SCIProwGetRhs(row) - SCIPgetRowLPActivity(scip, row);
    2276
    2277 if ( SCIPfeasFrac(scip, primsol) >= AWAY && SCIPfeasFrac(scip, primsol) <= 1 - AWAY )
    2278 tryrow = TRUE;
    2279 }
    2280 }
    2281#endif
    2282
    2283 if ( tryrow )
    2284 {
    2285 SCIP_Bool success;
    2286 SCIP_SOL* sol;
    2287 SCIP_Real cutrhs = 0.0;
    2288 SCIP_ROW* row;
    2289 SCIP_Real val;
    2290 int j;
    2291
    2292 assert( primsol != SCIP_INVALID ); /*lint !e777*/
    2293
    2294 /* get the row of B^-1 for this basic integer variable with fractional solution value */
    2295 SCIP_CALL( SCIPgetLPBInvRow(scip, i, binvrow, NULL, NULL) );
    2296
    2297 /* clear cutcoefs */
    2298 BMSclearMemoryArray(cutcoefs, ncols);
    2299
    2300 /* create solution */
    2301 SCIP_CALL( SCIPcreateSol(mipdata->subscip, &sol, NULL) );
    2302
    2303 /* add values of multipliers to solution and compute coefficients */
    2304 for (r = 0; r < nrows; ++r)
    2305 {
    2306 SCIP_COL** rowcols;
    2307 SCIP_Real* rowvals;
    2308 SCIP_Real binvval;
    2309 SCIP_Real weight;
    2310
    2311 row = rows[r];
    2312 assert( row != NULL );
    2313
    2314 binvval = binvrow[r];
    2315 binvval = SCIPfrac(scip, binvval); /* can always take fractional value */
    2316 if ( ! SCIPisFeasZero(scip, binvval) )
    2317 {
    2318 SCIP_Real lhs;
    2319 SCIP_Real rhs;
    2320 SCIP_Bool uselhs;
    2321
    2322 lhs = SCIProwGetLhs(row);
    2323 rhs = SCIProwGetRhs(row);
    2324
    2325 if ( ! SCIPisEQ(scip, lhs, rhs) )
    2326 {
    2327 SCIP_BASESTAT stat;
    2328
    2329 stat = SCIProwGetBasisStatus(row);
    2330
    2331 if ( stat == SCIP_BASESTAT_LOWER )
    2332 {
    2333 assert( ! SCIPisInfinity(scip, -lhs) );
    2334 uselhs = TRUE;
    2335 }
    2336 else if ( stat == SCIP_BASESTAT_UPPER )
    2337 {
    2338 assert( ! SCIPisInfinity(scip, rhs) );
    2339 uselhs = FALSE;
    2340 }
    2341 else if ( SCIPisInfinity(scip, rhs) )
    2342 uselhs = TRUE;
    2343 else
    2344 uselhs = FALSE;
    2345 }
    2346 else if ( binvval < 0.0 )
    2347 uselhs = TRUE;
    2348 else
    2349 uselhs = FALSE;
    2350
    2351 if ( uselhs )
    2352 {
    2353 assert( mipdata->ylhs[r] != NULL );
    2354 SCIP_CALL( SCIPsetSolVal(mipdata->subscip, sol, mipdata->ylhs[r], fabs(binvval)) );
    2355 weight = -fabs(binvval);
    2356 }
    2357 else
    2358 {
    2359 assert( mipdata->yrhs[r] != NULL );
    2360 SCIP_CALL( SCIPsetSolVal(mipdata->subscip, sol, mipdata->yrhs[r], fabs(binvval)) );
    2361 weight = fabs(binvval);
    2362 }
    2363
    2364 /* update cut coefficients */
    2365 rowcols = SCIProwGetCols(row);
    2366 rowvals = SCIProwGetVals(row);
    2367
    2368 /* add the row coefficients to the sum */
    2369 for (j = 0; j < SCIProwGetNLPNonz(row); ++j)
    2370 {
    2371 int idx;
    2372
    2373 assert( rowcols[j] != NULL );
    2374
    2375 idx = SCIPcolGetLPPos(rowcols[j]);
    2376 assert( 0 <= idx && idx < ncols );
    2377
    2378 cutcoefs[idx] += weight * rowvals[j];
    2379 }
    2380
    2381 /* compute rhs */
    2382 if ( uselhs )
    2383 {
    2384 assert( ! SCIPisInfinity(scip, -SCIProwGetLhs(row)) );
    2385 val = mipdata->lhs[r];
    2386 }
    2387 else
    2388 {
    2389 assert( ! SCIPisInfinity(scip, SCIProwGetRhs(row)) );
    2390 val = mipdata->rhs[r];
    2391 }
    2392 cutrhs += weight * val;
    2393 }
    2394 }
    2395
    2396 /* fill in values of cut */
    2397 for (c = 0; c < ncols; ++c)
    2398 {
    2399 if ( mipdata->coltype[c] != colPresent )
    2400 continue;
    2401
    2402 val = SCIPfloor(scip, cutcoefs[c]);
    2403 if ( mipdata->iscomplemented[c] )
    2404 val = -val;
    2405 if ( ! SCIPisFeasZero(scip, val) )
    2406 {
    2407 SCIP_CALL( SCIPsetSolVal(mipdata->subscip, sol, mipdata->alpha[c], val) );
    2408 }
    2409 val = SCIPfeasFrac(scip, cutcoefs[c]);
    2410 if ( ! SCIPisFeasZero(scip, val) )
    2411 {
    2412 SCIP_CALL( SCIPsetSolVal(mipdata->subscip, sol, mipdata->fracalpha[c], val) );
    2413 }
    2414 }
    2415
    2416 if ( ! SCIPisFeasZero(scip, SCIPfloor(scip, cutrhs)) )
    2417 {
    2418 SCIP_CALL( SCIPsetSolVal(mipdata->subscip, sol, mipdata->beta, SCIPfloor(scip, cutrhs)) );
    2419 }
    2420 if ( ! SCIPisFeasZero(scip, SCIPfeasFrac(scip, cutrhs)) )
    2421 {
    2422 SCIP_CALL( SCIPsetSolVal(mipdata->subscip, sol, mipdata->fracbeta, SCIPfeasFrac(scip, cutrhs)) );
    2423 }
    2424
    2425 SCIP_CALL( SCIPtrySolFree(mipdata->subscip, &sol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    2426 ++ntried;
    2427 if ( success )
    2428 ++ngen;
    2429 }
    2430 }
    2431
    2432 SCIPfreeBufferArray(scip, &cutcoefs);
    2433 SCIPfreeBufferArray(scip, &binvrow);
    2434 SCIPfreeBufferArray(scip, &basisind);
    2435
    2436 SCIPdebugMsg(scip, "Created %d primal solutions for CG-MIP from tableau cuts (tried: %d).\n", ngen, ntried);
    2437
    2438 return SCIP_OKAY;
    2439}
    2440
    2441
    2442/** solve subscip */
    2443static
    2445 SCIP* origscip, /**< SCIP data structure */
    2446 SCIP_SEPADATA* sepadata, /**< separator data */
    2447 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    2448 SCIP_Bool* success /**< if setting was successful -> stop */
    2449 )
    2450{
    2451 SCIP* subscip;
    2452 SCIP_RETCODE retcode;
    2453 SCIP_STATUS status;
    2454 SCIP_Real timelimit;
    2455 SCIP_Real memorylimit;
    2456 SCIP_Longint nodelimit;
    2457
    2458 assert( origscip != NULL );
    2459 assert( sepadata != NULL );
    2460 assert( mipdata != NULL );
    2461 assert( success != NULL );
    2462
    2463 *success = TRUE;
    2464
    2465 subscip = mipdata->subscip;
    2466
    2467 SCIP_CALL( SCIPcheckCopyLimits(origscip, success) );
    2468
    2469 if ( ! (*success) )
    2470 return SCIP_OKAY;
    2471
    2472 /* @todo Check whether copying the parameters is useful */
    2473 /* SCIP_CALL( SCIPcopyLimits(origscip, subscip) ); */
    2474
    2475 /* determine time limit */
    2476 SCIP_CALL( SCIPgetRealParam(origscip, "limits/time", &timelimit) );
    2477 if ( sepadata->timelimit < timelimit )
    2478 timelimit = sepadata->timelimit;
    2479
    2480 if ( ! SCIPisInfinity(origscip, timelimit) )
    2481 {
    2482 timelimit -= SCIPgetSolvingTime(origscip);
    2483 if ( timelimit > 0.0 )
    2484 {
    2485 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
    2486 }
    2487 else
    2488 {
    2489 SCIPdebugMsg(origscip, "Reached timelimit.\n");
    2490 *success = FALSE;
    2491 return SCIP_OKAY;
    2492 }
    2493 }
    2494
    2495 /* determine memory limit */
    2496 SCIP_CALL( SCIPgetRealParam(origscip, "limits/memory", &memorylimit) );
    2497 if ( sepadata->memorylimit < memorylimit )
    2498 memorylimit = sepadata->memorylimit;
    2499
    2500 if ( ! SCIPisInfinity(origscip, memorylimit) )
    2501 {
    2502 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
    2503 memorylimit -= SCIPgetMemUsed(origscip)/1048576.0;
    2504 memorylimit -= SCIPgetMemExternEstim(origscip)/1048576.0;
    2505 if ( memorylimit > 0.0 )
    2506 {
    2507 SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
    2508 }
    2509 else
    2510 {
    2511 SCIPdebugMsg(origscip, "Reached memorylimit.\n");
    2512 *success = TRUE;
    2513 return SCIP_OKAY;
    2514 }
    2515 }
    2516
    2517 /* set node limit for subproblem */
    2518 if ( sepadata->minnodelimit < 0 || sepadata->maxnodelimit < 0 )
    2519 nodelimit = SCIP_LONGINT_MAX;
    2520 else
    2521 {
    2522 assert( sepadata->minnodelimit >= 0 && sepadata->maxnodelimit >= 0 );
    2523 nodelimit = SCIPgetNLPIterations(origscip);
    2524 nodelimit = MAX(sepadata->minnodelimit, nodelimit);
    2525 nodelimit = MIN(sepadata->maxnodelimit, nodelimit);
    2526 }
    2527 assert( nodelimit >= 0 );
    2528 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit) );
    2529
    2530 /* try to create primal solutions of CG-MIP problem via tableau cuts */
    2531 if ( sepadata->genprimalsols )
    2532 {
    2533 SCIP_CALL( SCIPtransformProb(subscip) );
    2534 SCIP_CALL( createCGMIPprimalsols(origscip, sepadata, mipdata) );
    2535 }
    2536
    2537 SCIPdebugMsg(origscip, "Solving sub-SCIP (time limit: %f mem limit: %f node limit: %" SCIP_LONGINT_FORMAT ") ...\n", timelimit, memorylimit, nodelimit);
    2538
    2539 /* disable statistic timing inside sub SCIP */
    2540 if ( ! sepadata->output )
    2541 {
    2542 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    2543 }
    2544
    2545 /* check whether we want a complete solve */
    2546 if ( ! sepadata->earlyterm )
    2547 {
    2548 retcode = SCIPsolve(subscip);
    2549 SCIPdebugMsg(origscip, "Finished solving CG-MIP (dualbound: %g, solving time: %.2f, nodes: %" SCIP_LONGINT_FORMAT ", nodelimit: %" SCIP_LONGINT_FORMAT").\n",
    2550 SCIPgetDualbound(subscip), SCIPgetSolvingTime(subscip), SCIPgetNNodes(subscip), nodelimit);
    2551
    2552 /* errors in solving the subproblem should not kill the overall solving process;
    2553 * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
    2554 if ( retcode != SCIP_OKAY )
    2555 {
    2556#ifndef NDEBUG
    2557 SCIP_CALL( retcode );
    2558#endif
    2559 SCIPwarningMessage(origscip, "Error while solving subproblem in CGMIP separator; sub-SCIP terminated with code <%d>\n", retcode);
    2560 *success = FALSE;
    2561 return SCIP_OKAY;
    2562 }
    2563
    2564 status = SCIPgetStatus(subscip);
    2565
    2566#ifdef SCIP_OUTPUT
    2567 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2568#else
    2569 if ( sepadata->output )
    2570 {
    2571 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2572 }
    2573#endif
    2574
    2575 /* if the problem is infeasible (can happen because of violation constraint) */
    2576 if ( status == SCIP_STATUS_INFEASIBLE || status == SCIP_STATUS_INFORUNBD )
    2577 {
    2578 SCIPdebugMsg(origscip, "CG-MIP separation problem infeasible.\n");
    2579 *success = FALSE;
    2580 return SCIP_OKAY;
    2581 }
    2582
    2583 /* if the solution ran into the time limit */
    2584 if ( status == SCIP_STATUS_TIMELIMIT )
    2585 {
    2586 SCIPdebugMsg(origscip, "CG-MIP separation problem ran into time limit.\n");
    2587 *success = FALSE;
    2588 return SCIP_OKAY;
    2589 }
    2590
    2591 /* if the solution process was terminated */
    2592 if ( status == SCIP_STATUS_USERINTERRUPT )
    2593 {
    2594 SCIPdebugMsg(origscip, "CG-MIP separation problem stopped by user interrupt.\n");
    2595 *success = FALSE;
    2596 return SCIP_OKAY;
    2597 }
    2598
    2599 /* all other statuses except optimal or node limit are invalid */
    2600 if ( status != SCIP_STATUS_OPTIMAL && status != SCIP_STATUS_NODELIMIT )
    2601 {
    2602 SCIPerrorMessage("Solution of subscip for CG-separation returned with invalid status %d.\n", status);
    2603 return SCIP_ERROR;
    2604 }
    2605 }
    2606 else
    2607 {
    2608 /* otherwise we want a heuristic solve */
    2609
    2610 /* -> solve until first solution is found */
    2611 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", 1) );
    2612 retcode = SCIPsolve(subscip);
    2613 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", -1) );
    2614
    2615 /* errors in solving the subproblem should not kill the overall solving process;
    2616 * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
    2617 if ( retcode != SCIP_OKAY )
    2618 {
    2619#ifndef NDEBUG
    2620 SCIP_CALL( retcode );
    2621#endif
    2622 SCIPwarningMessage(origscip, "Error while solving subproblem in CGMIP separator; sub-SCIP terminated with code <%d>\n", retcode);
    2623 *success = FALSE;
    2624 return SCIP_OKAY;
    2625 }
    2626
    2627 status = SCIPgetStatus(subscip);
    2628
    2629 /* if the solution process was terminated or the problem is infeasible (can happen because of violation constraint) */
    2630 if ( status == SCIP_STATUS_TIMELIMIT || status == SCIP_STATUS_USERINTERRUPT || status == SCIP_STATUS_NODELIMIT ||
    2631 status == SCIP_STATUS_INFEASIBLE || status == SCIP_STATUS_INFORUNBD || status == SCIP_STATUS_MEMLIMIT )
    2632 {
    2633 /* output statistics before stopping */
    2634#ifdef SCIP_OUTPUT
    2635 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2636#else
    2637 if ( sepadata->output )
    2638 {
    2639 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2640 }
    2641#endif
    2642 *success = FALSE;
    2643 return SCIP_OKAY;
    2644 }
    2645
    2646 /* all other statuses except optimal or bestsollimit are invalid - (problem cannot be infeasible) */
    2647 if ( status != SCIP_STATUS_OPTIMAL && status != SCIP_STATUS_BESTSOLLIMIT )
    2648 {
    2649 SCIPerrorMessage("Solution of subscip for CG-separation returned with invalid status %d.\n", status);
    2650 return SCIP_ERROR;
    2651 }
    2652
    2653 /* solve some more, if a feasible solution was found */
    2654 if ( status == SCIP_STATUS_BESTSOLLIMIT )
    2655 {
    2656 SCIPdebugMsg(origscip, "Continue solving separation problem (current time: %.2f, nodes: %" SCIP_LONGINT_FORMAT ") ...\n",
    2657 SCIPgetSolvingTime(subscip), SCIPgetNNodes(subscip));
    2658
    2659 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", STALLNODELIMIT) );
    2660 retcode = SCIPsolve(subscip);
    2661 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", -1LL) );
    2662
    2663 SCIPdebugMsg(origscip, "Finished solving CG-MIP (dualbound: %g, solving time: %.2f, nodes: %" SCIP_LONGINT_FORMAT ", nodelimit: %" SCIP_LONGINT_FORMAT").\n",
    2664 SCIPgetDualbound(subscip), SCIPgetSolvingTime(subscip), SCIPgetNNodes(subscip), nodelimit);
    2665
    2666 /* errors in solving the subproblem should not kill the overall solving process;
    2667 * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
    2668 if ( retcode != SCIP_OKAY )
    2669 {
    2670#ifndef NDEBUG
    2671 SCIP_CALL( retcode );
    2672#endif
    2673 SCIPwarningMessage(origscip, "Error while solving subproblem in CGMIP separator; sub-SCIP terminated with code <%d>\n", retcode);
    2674 *success = FALSE;
    2675 return SCIP_OKAY;
    2676 }
    2677
    2678 status = SCIPgetStatus(subscip);
    2679 assert( status != SCIP_STATUS_BESTSOLLIMIT );
    2680
    2681#ifdef SCIP_OUTPUT
    2682 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2683#else
    2684 if ( sepadata->output )
    2685 {
    2686 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2687 }
    2688#endif
    2689
    2690 /* if the solution process was terminated */
    2691 if ( status == SCIP_STATUS_TIMELIMIT || status == SCIP_STATUS_USERINTERRUPT || status == SCIP_STATUS_MEMLIMIT )
    2692 {
    2693 *success = FALSE;
    2694 return SCIP_OKAY;
    2695 }
    2696
    2697 /* all other statuses except optimal or bestsollimit are invalid */
    2698 if ( status != SCIP_STATUS_OPTIMAL && status != SCIP_STATUS_STALLNODELIMIT && status != SCIP_STATUS_NODELIMIT )
    2699 {
    2700 SCIPerrorMessage("Solution of subscip for CG-separation returned with invalid status %d.\n", status);
    2701 return SCIP_ERROR;
    2702 }
    2703 }
    2704 }
    2705
    2706 return SCIP_OKAY;
    2707}
    2708
    2709/** Computes cut from the given multipliers
    2710 *
    2711 * When computing the cut, we take the fractional part of the multipliers. This is known to produce stronger cuts in
    2712 * the pure integer case, since the cut is the sum of the one using fractional parts and integer multiples of the
    2713 * original constraints. However, if there are continuous variables, the resulting cut might not be valid. This is
    2714 * checked and returned.
    2715 *
    2716 * Moreover, the cut computed here in general will not be the same as the one computed with the
    2717 * sub-MIP, because of numerical differences. Here, we only combine rows whose corresponding
    2718 * multiplier is positive w.r.t. the feasibility tolerance. In the sub-MIP, however, the rows are
    2719 * combined in any case. This makes a difference, if the coefficients in the matrix are large and
    2720 * hence yield a value that is larger than the tolerance.
    2721 *
    2722 * Because of the transformations we have the following:
    2723 *
    2724 * If variable \f$x_j\f$ was complemented, we have \f$x'_j = u_j - x_j\f$. If in the transformed
    2725 * system the lower bound is used, its corresponding multiplier is \f$y^T A'_j - \lfloor y^T A'_j
    2726 * \rfloor\f$, which corresponds to
    2727 * \f[
    2728 * y^T A'_j - \lfloor y^T A'_j \rfloor = - y^T A_j - \lfloor - y^T A_j \rfloor = - y^T A_j + \lceil y^T A_j \rceil
    2729 * \f]
    2730 * in the original system.
    2731 *
    2732 * If such a variable was at its upper bound before the transformation, it is at its lower bound
    2733 * afterwards. Hence, its contribution to the cut is 0.
    2734 *
    2735 * Note that if the original LP-solution does not satisfy some of the rows with equality, the
    2736 * violation of the cut might be smaller than what is computed with the reduced sub-MIP.
    2737 *
    2738 * Furthermore, note that if continuous variables have been shifted, the computed violation may be
    2739 * different as well, because the necessary changes in the lhs/rhs are not used here anymore.
    2740 *
    2741 * @todo Check if cut is correct if continuous variables have been shifted.
    2742 */
    2743static
    2745 SCIP* scip, /**< original scip */
    2746 SCIP_SEPA* sepa, /**< separator */
    2747 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    2748 SCIP_SEPADATA* sepadata, /**< separator data */
    2749 SCIP_SOL* sol, /**< current solution for sub-MIP */
    2750 SCIP_Bool usefrac, /**< use fractional value of multipliers */
    2751 SCIP_Real* cutcoefs, /**< coefficients of the cut */
    2752 SCIP_Real* cutrhs, /**< rhs of the cut */
    2753 SCIP_Bool* localrowsused, /**< pointer to store whether local rows were used in summation */
    2754 SCIP_Bool* localboundsused, /**< pointer to store whether local bounds were used in summation */
    2755 int* cutrank, /**< pointer to store the cut rank */
    2756 SCIP_Bool* success /**< whether we produced a valid cut */
    2757 )
    2758{
    2759 SCIP* subscip;
    2760 SCIP_VAR** vars;
    2761 SCIP_ROW** rows;
    2762 SCIP_COL** cols;
    2763 SCIP_Real val;
    2764 SCIP_Real maxabsweight;
    2765 int nvars;
    2766 int ncols;
    2767 int nrows;
    2768 int i;
    2769 int j;
    2770
    2771 assert( scip != NULL );
    2772 assert( mipdata != NULL );
    2773 assert( sepadata != NULL );
    2774 assert( cutcoefs != NULL );
    2775 assert( cutrhs != NULL );
    2776 assert( localrowsused != NULL );
    2777 assert( localboundsused != NULL );
    2778 assert( cutrank != NULL );
    2779 assert( success != NULL );
    2780
    2781 /* initialize */
    2782 *localrowsused = FALSE;
    2783 *localboundsused = FALSE;
    2784 *cutrank = 0;
    2785 *success = TRUE;
    2786
    2787 subscip = mipdata->subscip;
    2788 assert( subscip != NULL );
    2789
    2790 /* get data */
    2791 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    2792 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    2793 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    2794 assert( nrows == (int) mipdata->nrows );
    2795 assert( ncols == (int) mipdata->ncols );
    2796
    2797 BMSclearMemoryArray(cutcoefs, nvars);
    2798 *cutrhs = 0.0;
    2799
    2800 /* find maximal absolute weight */
    2801 maxabsweight = 0.0;
    2802 for (i = 0; i < nrows; ++i)
    2803 {
    2804 SCIP_ROW* row;
    2805 SCIP_Real absweight = 0.0;
    2806
    2807 row = rows[i];
    2808 assert( row != NULL );
    2809
    2810 /* skip modifiable rows and local rows, unless allowed */
    2811 if ( SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && !sepadata->allowlocal) )
    2812 {
    2813 assert( mipdata->ylhs[i] == NULL && mipdata->yrhs[i] == NULL );
    2814 continue;
    2815 }
    2816
    2817 /* get weight from solution (take larger of the values of lhs/rhs) */
    2818 if ( mipdata->ylhs[i] != NULL )
    2819 {
    2820 val = SCIPgetSolVal(subscip, sol, mipdata->ylhs[i]);
    2821
    2822 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    2823 if ( usefrac )
    2824 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    2825
    2826 if ( SCIPisFeasPositive(scip, val) )
    2827 absweight = val;
    2828
    2829 assert( ! sepadata->onlyrankone || SCIProwGetOriginSepa(row) != sepa );
    2830 }
    2831 if ( mipdata->yrhs[i] != NULL )
    2832 {
    2833 val = SCIPgetSolVal(subscip, sol, mipdata->yrhs[i]);
    2834
    2835 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    2836 if ( usefrac )
    2837 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    2838
    2839 /* in a suboptimal solution both values may be positive - take the one with larger absolute value */
    2840 if ( SCIPisFeasGT(scip, val, absweight) )
    2841 absweight = val;
    2842
    2843 assert( ! sepadata->onlyrankone || SCIProwGetOriginSepa(row) != sepa );
    2844 }
    2845 assert( ! SCIPisNegative(scip, absweight) );
    2846
    2847 if ( absweight > maxabsweight )
    2848 maxabsweight = absweight;
    2849 }
    2850
    2851 /* get weight from objective cuts */
    2852 if ( sepadata->useobjub || sepadata->useobjlb )
    2853 {
    2854 SCIP_Real absweight = 0.0;
    2855
    2856 assert( mipdata->ntotalrows == mipdata->nrows + 1 );
    2857
    2858 if ( mipdata->ylhs[mipdata->nrows] != NULL )
    2859 {
    2860 val = SCIPgetSolVal(subscip, sol, mipdata->ylhs[mipdata->nrows]);
    2861 if ( usefrac )
    2862 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    2863
    2864 if ( SCIPisFeasPositive(scip, val) )
    2865 absweight = val;
    2866 }
    2867 if ( mipdata->yrhs[mipdata->nrows] != NULL )
    2868 {
    2869 val = SCIPgetSolVal(subscip, sol, mipdata->yrhs[mipdata->nrows]);
    2870 if ( usefrac )
    2871 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    2872
    2873 /* in a suboptimal solution both values may be positive - take the one with larger absolute value */
    2874 if ( SCIPisFeasGT(scip, val, absweight) )
    2875 absweight = val;
    2876 }
    2877
    2878 if ( absweight > maxabsweight )
    2879 maxabsweight = absweight;
    2880 }
    2881
    2882 /* calculate the row summation */
    2883 for (i = 0; i < nrows; ++i)
    2884 {
    2885 SCIP_ROW* row;
    2886 SCIP_Real weight;
    2887 SCIP_Real absweight;
    2888 SCIP_Bool uselhs;
    2889
    2890 row = rows[i];
    2891 assert( row != NULL );
    2892
    2893 /* skip modifiable rows and local rows, unless allowed */
    2894 if ( SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && ! sepadata->allowlocal) )
    2895 {
    2896 assert( mipdata->ylhs[i] == NULL && mipdata->yrhs[i] == NULL );
    2897 continue;
    2898 }
    2899
    2900 /* get weight from solution */
    2901 weight = 0.0;
    2902 uselhs = FALSE;
    2903 if ( mipdata->ylhs[i] != NULL )
    2904 {
    2905 val = SCIPgetSolVal(subscip, sol, mipdata->ylhs[i]);
    2906 assert( ! SCIPisFeasNegative(subscip, val) );
    2907
    2908 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    2909 if ( usefrac )
    2910 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    2911
    2912 if ( SCIPisFeasPositive(scip, val) )
    2913 {
    2914 uselhs = TRUE;
    2915 weight = -val;
    2916 }
    2917 }
    2918 if ( mipdata->yrhs[i] != NULL )
    2919 {
    2920 val = SCIPgetSolVal(subscip, sol, mipdata->yrhs[i]);
    2921 assert( ! SCIPisFeasNegative(subscip, val) );
    2922
    2923 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    2924 if ( usefrac )
    2925 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    2926
    2927 /* in a suboptimal solution both values may be positive - take the one with larger absolute value */
    2928 if ( SCIPisFeasGT(scip, val, REALABS(weight)) )
    2929 {
    2930 uselhs = FALSE;
    2931 weight = val;
    2932 }
    2933 }
    2934
    2935 /* add row if weight is nonzero and lies within range */
    2936 absweight = REALABS(weight);
    2937 if ( ! SCIPisSumZero(scip, weight) && absweight * MAXWEIGHTRANGE >= maxabsweight )
    2938 {
    2939 SCIP_COL** rowcols;
    2940 SCIP_Real* rowvals;
    2941
    2942 rowcols = SCIProwGetCols(row);
    2943 rowvals = SCIProwGetVals(row);
    2944
    2945 /* add the row coefficients to the sum */
    2946 for (j = 0; j < SCIProwGetNLPNonz(row); ++j)
    2947 {
    2948 SCIP_VAR* var;
    2949 int idx;
    2950
    2951 assert( rowcols[j] != NULL );
    2952 var = SCIPcolGetVar(rowcols[j]);
    2953
    2954 assert( var != NULL );
    2955 assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN );
    2956 assert( SCIPvarGetCol(var) == rowcols[j] );
    2957
    2958 idx = SCIPvarGetProbindex(var);
    2959 assert( 0 <= idx && idx < nvars );
    2960
    2961 cutcoefs[idx] += weight * rowvals[j];
    2962 }
    2963
    2964 /* compute rhs */
    2965 if ( uselhs )
    2966 {
    2967 assert( ! SCIPisInfinity(scip, -SCIProwGetLhs(row)) );
    2968 val = SCIProwGetLhs(row) - SCIProwGetConstant(row);
    2969 if ( SCIProwIsIntegral(row) )
    2970 val = SCIPfeasCeil(scip, val); /* row is integral: round left hand side up */
    2971 }
    2972 else
    2973 {
    2974 assert( ! SCIPisInfinity(scip, SCIProwGetRhs(row)) );
    2975 val = SCIProwGetRhs(row) - SCIProwGetConstant(row);
    2976 if ( SCIProwIsIntegral(row) )
    2977 val = SCIPfeasFloor(scip, val); /* row is integral: round right hand side down */
    2978 }
    2979 *cutrhs += weight * val;
    2980
    2981 *localrowsused = *localrowsused || SCIProwIsLocal(row);
    2982
    2983 if ( SCIProwGetRank(row) > *cutrank )
    2984 *cutrank = SCIProwGetRank(row);
    2985 }
    2986 }
    2987 /* add 1 to cutrank */
    2988 ++(*cutrank);
    2989
    2990 /* get weight from objective bounds */
    2991 if ( sepadata->useobjub || sepadata->useobjlb )
    2992 {
    2993 SCIP_Real weight = 0.0;
    2994 SCIP_Bool uselhs = FALSE;
    2995 SCIP_Real absweight;
    2996
    2997 assert( mipdata->ntotalrows == mipdata->nrows + 1 );
    2998
    2999 if ( mipdata->ylhs[mipdata->nrows] != NULL )
    3000 {
    3001 val = SCIPgetSolVal(subscip, sol, mipdata->ylhs[mipdata->nrows]);
    3002 assert( ! SCIPisFeasNegative(subscip, val) );
    3003 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    3004 if ( usefrac )
    3005 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    3006
    3007 if ( SCIPisFeasPositive(scip, val) )
    3008 {
    3009 uselhs = TRUE;
    3010 weight = -val;
    3011 }
    3012 }
    3013 if ( mipdata->yrhs[mipdata->nrows] != NULL )
    3014 {
    3015 val = SCIPgetSolVal(subscip, sol, mipdata->yrhs[mipdata->nrows]);
    3016 assert( ! SCIPisFeasNegative(subscip, val) );
    3017 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    3018 if ( usefrac )
    3019 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    3020
    3021 /* in a suboptimal solution both values may be positive - take the one with larger absolute value */
    3022 if ( SCIPisFeasGT(scip, val, REALABS(weight)) )
    3023 {
    3024 uselhs = FALSE;
    3025 weight = val;
    3026 }
    3027 }
    3028
    3029 /* add objective row if weight is nonzero and lies within range */
    3030 absweight = REALABS(weight);
    3031 if ( ! SCIPisSumZero(scip, weight) && absweight * MAXWEIGHTRANGE >= maxabsweight )
    3032 {
    3033 SCIP_Real obj;
    3034 int idx;
    3035
    3036 /* add the objective row coefficients to the sum */
    3037 for (j = 0; j < ncols; ++j)
    3038 {
    3039 assert( cols[j] != NULL );
    3040
    3041 obj = SCIPcolGetObj(cols[j]);
    3042 if ( ! SCIPisZero(scip, obj) )
    3043 {
    3044 idx = SCIPvarGetProbindex( SCIPcolGetVar(cols[j]) );
    3045 assert( 0 <= idx && idx < nvars );
    3046 cutcoefs[idx] += weight * obj;
    3047 }
    3048 }
    3049
    3050 /* compute rhs */
    3051 if ( uselhs )
    3052 {
    3053 val = SCIPgetLowerbound(scip);
    3054 assert( ! SCIPisInfinity(scip, -val) );
    3055 if ( SCIPisObjIntegral(scip) )
    3056 val = SCIPfeasCeil(scip, val); /* objective is integral: round left hand side up */
    3057 }
    3058 else
    3059 {
    3060 val = SCIPgetUpperbound(scip);
    3061 assert( ! SCIPisInfinity(scip, val) );
    3062 if ( SCIPisObjIntegral(scip) )
    3063 val = SCIPfeasFloor(scip, val); /* objective is integral: round right hand side down */
    3064 }
    3065 *cutrhs += weight * val;
    3066 }
    3067 }
    3068
    3069 /* add upper bounds */
    3070 for (j = 0; j < ncols; ++j)
    3071 {
    3072 assert( cols[j] != NULL );
    3073 if ( mipdata->z[j] != NULL )
    3074 {
    3075 assert( mipdata->coltype[j] == colPresent );
    3076
    3077 val = SCIPgetSolVal(subscip, sol, mipdata->z[j]);
    3078 assert( ! SCIPisFeasNegative(subscip, val) );
    3079
    3080 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    3081 if ( usefrac )
    3082 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    3083
    3084 /* if a bound has been used */
    3085 if ( SCIPisSumPositive(subscip, val) )
    3086 {
    3087 SCIP_VAR* var;
    3088 int idx;
    3089
    3090 var = SCIPcolGetVar(cols[j]);
    3091
    3092 assert( var != NULL );
    3093 assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN );
    3094 assert( SCIPvarIsIntegral(var) );
    3095 assert( SCIPvarGetCol(var) == cols[j] );
    3096
    3097 idx = SCIPvarGetProbindex(var);
    3098 assert( 0 <= idx && idx < nvars );
    3099
    3100 /* check whether variable is complemented */
    3101 if ( mipdata->iscomplemented[j] )
    3102 {
    3103 SCIP_Real lbnd;
    3104 lbnd = SCIPvarGetLbGlobal(var);
    3105 assert( ! SCIPisInfinity(scip, -lbnd) );
    3106 assert( SCIPisIntegral(scip, lbnd) );
    3107 assert( SCIPisEQ(scip, SCIPvarGetLbLocal(var), SCIPcolGetLb(cols[j])) );
    3108
    3109 /* variable should not be free */
    3110 assert( ! SCIPisInfinity(scip, -lbnd) || ! SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) );
    3111
    3112 /* if allowed, try to use stronger local bound */
    3113 if ( sepadata->allowlocal && SCIPvarGetLbLocal(var) - 0.5 > lbnd )
    3114 {
    3115 lbnd = SCIPvarGetLbLocal(var);
    3116 assert( SCIPisIntegral(scip, lbnd) );
    3117 *localboundsused = TRUE;
    3118 }
    3119
    3120 cutcoefs[idx] -= val;
    3121 *cutrhs -= lbnd * val;
    3122 }
    3123 else
    3124 {
    3125 SCIP_Real ubnd;
    3126 ubnd = SCIPvarGetUbGlobal(var);
    3127 assert( ! SCIPisInfinity(scip, ubnd) );
    3128 assert( SCIPisIntegral(scip, ubnd) );
    3129 assert( SCIPisEQ(scip, SCIPvarGetUbLocal(var), SCIPcolGetUb(cols[j])) );
    3130
    3131 /* if allowed, try to use stronger local bound */
    3132 if ( sepadata->allowlocal && SCIPvarGetUbLocal(var) + 0.5 < ubnd )
    3133 {
    3134 ubnd = SCIPvarGetUbLocal(var);
    3135 assert( SCIPisIntegral(scip, ubnd) );
    3136 *localboundsused = TRUE;
    3137 }
    3138
    3139 cutcoefs[idx] += val;
    3140 *cutrhs += ubnd * val;
    3141 }
    3142 }
    3143 }
    3144 }
    3145
    3146 /* check lower bounds for integral variables */
    3147 for (j = 0; j < nvars; ++j)
    3148 {
    3149 SCIP_VAR* var;
    3150 int pos;
    3151
    3152 var = vars[j];
    3153 assert( var != NULL );
    3154 pos = SCIPcolGetLPPos(SCIPvarGetCol(var));
    3155
    3156 /* a variable may have status COLUMN, but the corresponding column may not (yet) be in the LP */
    3157 if ( pos >= 0 && mipdata->coltype[pos] != colContinuous && mipdata->coltype[pos] != colConverted )
    3158 {
    3159 assert( pos < ncols );
    3160 assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN );
    3161 assert( SCIPvarIsIntegral(var) );
    3162
    3163 /* check whether variable is complemented */
    3164 if ( mipdata->iscomplemented[pos] )
    3165 {
    3166 assert( ! mipdata->isshifted[pos] );
    3167 /* if the variable is complemented, the multiplier for the upper bound arises from the
    3168 lower bound multiplier for the transformed problem - because of the minus-sign in the
    3169 transformation this yields a round-up operation. */
    3170 val = SCIPfeasCeil(scip, cutcoefs[j]) - cutcoefs[j];
    3171 assert( ! SCIPisFeasNegative(scip, val) );
    3172
    3173 /* only if variable needs to be rounded */
    3174 if ( SCIPisSumPositive(scip, val) )
    3175 {
    3176 SCIP_Real ubnd;
    3177 ubnd = SCIPvarGetUbGlobal(var);
    3178 assert( ! SCIPisInfinity(scip, ubnd) );
    3179 assert( SCIPisIntegral(scip, ubnd) );
    3180
    3181 /* variable should not be free */
    3182 assert( ! SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)) || ! SCIPisInfinity(scip, ubnd) );
    3183
    3184 /* if allowed, try to use stronger local bound */
    3185 if ( sepadata->allowlocal && SCIPvarGetUbLocal(var) + 0.5 < ubnd )
    3186 {
    3187 ubnd = SCIPvarGetUbLocal(var);
    3188 assert( SCIPisIntegral(scip, ubnd) );
    3189 *localboundsused = TRUE;
    3190 }
    3191
    3192 /* round cut coefficients, i.e., add val to cutcoefs[j] */
    3193 cutcoefs[j] = SCIPfeasCeil(scip, cutcoefs[j]);
    3194
    3195 /* correct rhs */
    3196 if ( ! SCIPisSumZero(scip, ubnd) )
    3197 *cutrhs += ubnd * val;
    3198 }
    3199 }
    3200 else
    3201 {
    3202 /* compute multiplier for lower bound: */
    3203 val = cutcoefs[j] - SCIPfeasFloor(scip, cutcoefs[j]);
    3204 assert( ! SCIPisFeasNegative(scip, val) );
    3205
    3206 /* only if variable needs to be rounded */
    3207 if ( SCIPisSumPositive(scip, val) )
    3208 {
    3209 SCIP_Real lbnd;
    3210 lbnd = SCIPvarGetLbGlobal(var);
    3211 assert( ! SCIPisInfinity(scip, -lbnd) );
    3212 assert( SCIPisIntegral(scip, lbnd) );
    3213
    3214 /* variable should not be free */
    3215 assert( ! SCIPisInfinity(scip, -lbnd) || ! SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) );
    3216
    3217 /* if allowed, try to use stronger local bound */
    3218 if ( sepadata->allowlocal && SCIPvarGetLbLocal(var) - 0.5 > lbnd )
    3219 {
    3220 lbnd = SCIPvarGetLbLocal(var);
    3221 assert( SCIPisIntegral(scip, lbnd) );
    3222 *localboundsused = TRUE;
    3223 }
    3224
    3225 /* round cut coefficients, i.e., subtract val from cutcoefs[j] */
    3226 cutcoefs[j] = SCIPfeasFloor(scip, cutcoefs[j]);
    3227
    3228 /* correct rhs */
    3229 if ( ! SCIPisSumZero(scip, lbnd) )
    3230 *cutrhs -= lbnd * val;
    3231 }
    3232 }
    3233 }
    3234 else
    3235 {
    3236 /* force coefficients of all continuous variables or of variables not in the lp to zero */
    3237 assert( pos == -1 || mipdata->coltype[pos] == colContinuous || mipdata->coltype[pos] == colConverted );
    3238
    3239 /* check whether all coefficients for continuous or converted variables are nonnegative */
    3240 if ( pos >= 0 )
    3241 {
    3242 if ( SCIPisFeasNegative(scip, cutcoefs[j]) )
    3243 {
    3244 *success = FALSE;
    3245 break;
    3246 }
    3247 }
    3248
    3249 cutcoefs[j] = 0.0;
    3250 }
    3251 }
    3252
    3253 /* round rhs */
    3254 *cutrhs = SCIPfeasFloor(scip, *cutrhs);
    3255
    3256 return SCIP_OKAY;
    3257}
    3258
    3259/** Create CG-cut directly from solution of sub-MIP */
    3260static
    3262 SCIP* scip, /**< SCIP data structure */
    3263 SCIP_SEPA* sepa, /**< separator */
    3264 SCIP_SEPADATA* sepadata, /**< separator data */
    3265 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    3266 SCIP_SOL* sol, /**< solution of sub-MIP */
    3267 SCIP_Real* cutcoefs, /**< cut coefficients */
    3268 int* cutinds, /**< problem indices of variables appearing in cut */
    3269 SCIP_Real* cutvals, /**< values of variables in cut */
    3270 SCIP_Real* varsolvals, /**< solution value of variables */
    3271 SCIP_Real* weights, /**< weights to compute cmir cut */
    3272 int* nprevrows, /**< number of previously generated rows */
    3273 SCIP_ROW** prevrows, /**< previously generated rows */
    3274 SCIP_Bool* cutoff, /**< whether a cutoff has been detected */
    3275 unsigned int* ngen /**< number of generated cuts */
    3276 )
    3277{
    3278 char name[SCIP_MAXSTRLEN];
    3279 SCIP_Bool cutislocal;
    3280 SCIP_Bool localrowsused;
    3281 SCIP_Bool localboundsused;
    3282 SCIP_Real cutrhs;
    3283 SCIP_Real cutact;
    3284 SCIP_Bool success;
    3285 SCIP_VAR** vars;
    3286 int cutrank = 0;
    3287 int nvars;
    3288 int k;
    3289
    3290 assert( scip != NULL );
    3291 assert( sepadata != NULL );
    3292 assert( mipdata != NULL );
    3293 assert( sol != NULL );
    3294 assert( cutcoefs != NULL );
    3295 assert( cutinds != NULL );
    3296 assert( cutvals != NULL );
    3297 assert( varsolvals != NULL );
    3298 assert( weights != NULL );
    3299 assert( nprevrows != NULL );
    3300 assert( prevrows != NULL );
    3301 assert( cutoff != NULL );
    3302 assert( ngen != NULL );
    3303
    3304 /* get variable data */
    3305 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    3306
    3307 cutrhs = 0.0;
    3308 localrowsused = FALSE;
    3309 localboundsused = FALSE;
    3310 *cutoff = FALSE;
    3311 success = TRUE;
    3312
    3313 /* compute coefficients */
    3314 SCIP_CALL( computeCut(scip, sepa, mipdata, sepadata, sol, TRUE, cutcoefs, &cutrhs, &localrowsused, &localboundsused, &cutrank, &success) );
    3315 cutislocal = localrowsused || localboundsused;
    3316
    3317 /* Take next solution if cut was not valid - this can easily happen for mixed-integer problems, see function computeCut(). */
    3318 if ( ! success )
    3319 {
    3320 /* try again without using fractional value */
    3321 SCIP_CALL( computeCut(scip, sepa, mipdata, sepadata, sol, FALSE, cutcoefs, &cutrhs, &localrowsused, &localboundsused, &cutrank, &success) );
    3322 cutislocal = localrowsused || localboundsused;
    3323
    3324 if ( ! success )
    3325 {
    3326 SCIPdebugMsg(scip, "cut not valid - skipping ...\n");
    3327 return SCIP_OKAY;
    3328 }
    3329 }
    3330
    3331 /* compute activity */
    3332 cutact = 0.0;
    3333 for (k = 0; k < nvars; ++k)
    3334 cutact += cutcoefs[k] * varsolvals[k];
    3335
    3336#ifdef SCIP_DISABLED_CODE
    3337 /* the following test should be treated with care because of numerical differences - see computeCut() */
    3338 {
    3339 /* check for correctness of computed values */
    3340 SCIP* subscip;
    3341 SCIP_Real obj = 0.0;
    3342 SCIP_Real val;
    3343 SCIP_Bool contVarShifted = FALSE;
    3344 unsigned int j;
    3345 SCIP_COL** cols;
    3346 int ncols;
    3347
    3348 subscip = mipdata->subscip;
    3349 assert( subscip != NULL );
    3350
    3351 SCIP_CALL( SCIPprintSol(subscip, sol, NULL, FALSE) );
    3352
    3353 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
    3354 for (j = 0; j < mipdata->ncols; ++j)
    3355 {
    3356 if ( mipdata->coltype[j] == colPresent )
    3357 {
    3358 int idx;
    3359 assert( mipdata->alpha[j] != NULL );
    3360 val = SCIPgetSolVal(subscip, sol, mipdata->alpha[j]);
    3361 assert( SCIPisFeasIntegral(subscip, val) );
    3362 idx = SCIPvarGetProbindex(SCIPcolGetVar(cols[j]));
    3363 assert( SCIPisFeasEQ(scip, val, cutcoefs[idx]) );
    3364 obj += val * SCIPvarGetObj(mipdata->alpha[j]);
    3365 }
    3366 else
    3367 {
    3368 if ( (mipdata->coltype[j] == colContinuous || mipdata->coltype[j] == colConverted) && mipdata->isshifted[j] )
    3369 contVarShifted = TRUE;
    3370 }
    3371 }
    3372 assert( mipdata->beta != NULL );
    3373 val = SCIPgetSolVal(subscip, sol, mipdata->beta);
    3374 assert( SCIPisFeasIntegral(subscip, val) );
    3375 obj += val * SCIPvarGetObj(mipdata->beta);
    3376 assert( contVarShifted || SCIPisFeasEQ(scip, obj, cutact - cutrhs) );
    3377 }
    3378#endif
    3379
    3380 /* if successful, convert dense cut into sparse row, and add the row as a cut */
    3381 if ( SCIPisFeasGT(scip, cutact, cutrhs) )
    3382 {
    3383 SCIP_Real cutnorm;
    3384 int cutlen;
    3385
    3386 /* store the cut as sparse row, calculate activity and norm of cut */
    3387 SCIP_CALL( storeCutInArrays(scip, nvars, cutcoefs, varsolvals, mipdata->normtype,
    3388 cutinds, cutvals, &cutlen, &cutact, &cutnorm) );
    3389
    3390 SCIPdebugMsg(scip, "act=%f, rhs=%f, norm=%f, eff=%f\n", cutact, cutrhs, cutnorm, (cutact - cutrhs)/cutnorm);
    3391
    3392 /* if norm is 0, the cut is trivial */
    3393 if ( SCIPisPositive(scip, cutnorm) )
    3394 {
    3395 SCIP_Bool violated = SCIPisEfficacious(scip, (cutact - cutrhs)/cutnorm);
    3396
    3397 if ( violated || (sepadata->usecutpool && ! cutislocal ) )
    3398 {
    3399 SCIP_ROW* cut;
    3400
    3401 /* create the cut */
    3402 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cgcut%" SCIP_LONGINT_FORMAT "_%u", SCIPgetNLPs(scip), *ngen);
    3403 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &cut, sepa, name, -SCIPinfinity(scip), cutrhs, cutislocal, FALSE, sepadata->dynamiccuts) );
    3405
    3406 for (k = 0; k < cutlen; ++k)
    3407 {
    3408 SCIP_CALL( SCIPaddVarToRow(scip, cut, vars[cutinds[k]], cutvals[k]) );
    3409 }
    3410
    3411 /* set cut rank */
    3412 SCIProwChgRank(cut, cutrank);
    3413
    3415
    3416 /*SCIPdebug( SCIP_CALL( SCIPprintRow(scip, cut, NULL) ) );*/
    3417
    3418 /* add cut to pool */
    3419 if ( ! cutislocal )
    3420 {
    3421 assert( violated || sepadata->usecutpool );
    3422 SCIP_CALL( SCIPaddPoolCut(scip, cut) );
    3423 }
    3424
    3425 /* add cut if it is violated */
    3426 if ( violated )
    3427 {
    3428 /* check whether cut has been found before - may happened due to projection */
    3429 for (k = 0; k < *nprevrows; ++k)
    3430 {
    3431 SCIP_Real parval;
    3432
    3433 assert( prevrows[k] != NULL );
    3434 parval = SCIProwGetParallelism(cut, prevrows[k], 'e');
    3435 /* exit if row is parallel to existing cut and rhs is not better */
    3436 if ( SCIPisEQ(scip, parval, 1.0) && SCIPisGE(scip, cutrhs, SCIProwGetRhs(prevrows[k])) )
    3437 break;
    3438 }
    3439
    3440 /* if cut is new */
    3441 if ( k >= *nprevrows )
    3442 {
    3443 prevrows[*nprevrows] = cut;
    3444 ++(*nprevrows);
    3445
    3446 SCIPdebugMsg(scip, " -> CG-cut <%s>: act=%f, rhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n",
    3447 name, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
    3451#ifdef SCIP_DEBUG
    3452 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3453#else
    3454 if ( sepadata->output )
    3455 {
    3456 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3457 }
    3458#endif
    3459 SCIP_CALL( SCIPaddRow(scip, cut, FALSE, cutoff) );
    3460 ++(*ngen);
    3461 }
    3462 else
    3463 {
    3464 SCIPdebugMsg(scip, "Cut already exists.\n");
    3465 /* release the row */
    3466 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3467 }
    3468 }
    3469 else
    3470 {
    3471 /* release the row */
    3472 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3473 }
    3474 }
    3475 }
    3476 }
    3477
    3478 return SCIP_OKAY;
    3479}
    3480
    3481
    3482/** create CG-cut via CMIR-function */
    3483static
    3485 SCIP* scip, /**< SCIP data structure */
    3486 SCIP_SEPA* sepa, /**< separator */
    3487 SCIP_SEPADATA* sepadata, /**< separator data */
    3488 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    3489 SCIP_SOL* sol, /**< solution of sub-MIP */
    3490 SCIP_AGGRROW* aggrrow, /**< aggregation row to use for creating MIR cut */
    3491 SCIP_Real* cutcoefs, /**< cut coefficients */
    3492 int* cutinds, /**< problem indices of variables appearing in cut */
    3493 SCIP_Real* cutvals, /**< values of variables in cut */
    3494 SCIP_Real* varsolvals, /**< solution value of variables */
    3495 SCIP_Real* weights, /**< weights to compute cmir cut */
    3496 int* boundsfortrans, /**< bounds for cmir function of NULL */
    3497 SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds for cmir function or NULL */
    3498 int* nprevrows, /**< number of previously generated rows */
    3499 SCIP_ROW** prevrows, /**< previously generated rows */
    3500 SCIP_Bool* cutoff, /**< whether a cutoff has been detected */
    3501 unsigned int* ngen /**< number of generated cuts */
    3502 )
    3503{
    3504 char name[SCIP_MAXSTRLEN];
    3505 SCIP_Longint maxdnom;
    3506 SCIP_Bool cutislocal;
    3507 SCIP_Real maxscale;
    3508 SCIP_Real cutrhs;
    3509 SCIP_Real cutefficacy;
    3510 SCIP_Bool success;
    3511 SCIP_ROW** rows;
    3512 SCIP_VAR** vars;
    3513 SCIP* subscip;
    3514 int nrows;
    3515 int nvars;
    3516 int k;
    3517 int cutrank;
    3518 int cutnnz;
    3519
    3520 assert( scip != NULL );
    3521 assert( sepadata != NULL );
    3522 assert( mipdata != NULL );
    3523 assert( sol != NULL );
    3524 assert( cutcoefs != NULL );
    3525 assert( cutinds != NULL );
    3526 assert( cutvals != NULL );
    3527 assert( varsolvals != NULL );
    3528 assert( weights != NULL );
    3529 assert( nprevrows != NULL );
    3530 assert( prevrows != NULL );
    3531 assert( cutoff != NULL );
    3532 assert( ngen != NULL );
    3533
    3534 *cutoff = FALSE;
    3535 subscip = mipdata->subscip;
    3536 assert( subscip != NULL );
    3537
    3538 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    3539 assert( nrows > 0 );
    3540 assert( (int) mipdata->nrows == nrows );
    3541
    3542 /* @todo more advanced settings - compare sepa_gomory.c */
    3543 maxdnom = (SCIP_Longint) sepadata->cutcoefbnd+1;
    3544 maxscale = 10000.0;
    3545
    3546 /* get variable data */
    3547 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    3548
    3549 /* generate weights */
    3550 for (k = 0; k < nrows; ++k)
    3551 {
    3552 SCIP_Real val;
    3553
    3554 weights[k] = 0;
    3555 if ( mipdata->ylhs[k] != NULL )
    3556 {
    3557 assert( !SCIProwIsModifiable(rows[k]) && (!SCIProwIsLocal(rows[k]) || sepadata->allowlocal) );
    3558
    3559 val = SCIPgetSolVal(subscip, sol, mipdata->ylhs[k]);
    3560 assert( ! SCIPisFeasNegative(subscip, val) );
    3561
    3562 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    3563 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    3564
    3565 if ( SCIPisFeasPositive(subscip, val) )
    3566 weights[k] = -val;
    3567 }
    3568
    3569 if ( mipdata->yrhs[k] != NULL )
    3570 {
    3571 assert( !SCIProwIsModifiable(rows[k]) && (!SCIProwIsLocal(rows[k]) || sepadata->allowlocal) );
    3572
    3573 val = SCIPgetSolVal(subscip, sol, mipdata->yrhs[k]);
    3574 assert( ! SCIPisFeasNegative(subscip, val) );
    3575
    3576 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    3577 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    3578
    3579 /* in a suboptimal solution both values may be positive - take the one with larger absolute value */
    3580 if ( SCIPisFeasGT(scip, val, ABS(weights[k])) )
    3581 weights[k] = val;
    3582 }
    3583 }
    3584
    3585 /* set up data for bounds to use */
    3586 if ( sepadata->cmirownbounds )
    3587 {
    3588 int typefortrans;
    3589
    3590 assert( boundsfortrans != NULL );
    3591 assert( boundtypesfortrans != NULL );
    3592
    3593 if ( sepadata->allowlocal )
    3594 typefortrans = -2;
    3595 else
    3596 typefortrans = -1;
    3597
    3598 /* check all variables */
    3599 for (k = 0; k < nvars; ++k)
    3600 {
    3601 int pos;
    3602 SCIP_VAR* var;
    3603
    3604 var = vars[k];
    3605 assert( var != NULL );
    3606 pos = SCIPcolGetLPPos(SCIPvarGetCol(var));
    3607
    3608 if ( pos < 0 )
    3609 continue;
    3610
    3611 assert( pos < (int) mipdata->ncols );
    3612 assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN );
    3613
    3614 boundsfortrans[k] = typefortrans;
    3615 boundtypesfortrans[k] = SCIP_BOUNDTYPE_LOWER;
    3616
    3617 if ( mipdata->coltype[pos] == colContinuous || mipdata->coltype[pos] == colConverted )
    3618 {
    3619 assert( SCIPvarIsIntegral(var) || mipdata->coltype[pos] != colContinuous );
    3620 continue;
    3621 }
    3622
    3623 /* check upper bound */
    3624 if ( mipdata->z[pos] != NULL && SCIPisSumPositive(subscip, SCIPgetSolVal(subscip, sol, mipdata->z[pos])) )
    3625 {
    3626 /* check whether variable is complemented */
    3627 if ( ! mipdata->iscomplemented[pos] )
    3628 boundtypesfortrans[k] = SCIP_BOUNDTYPE_UPPER;
    3629 /* otherwise use lower bound */
    3630 }
    3631 else
    3632 {
    3633 /* check whether variable is complemented */
    3634 if ( mipdata->iscomplemented[pos] )
    3635 boundtypesfortrans[k] = SCIP_BOUNDTYPE_UPPER;
    3636 /* otherwise use lower bound */
    3637 }
    3638 }
    3639 }
    3640
    3641 /* create a MIR cut using the above calculated weights */
    3642 cutefficacy = -1.0;
    3643 cutrhs = -1.0;
    3644 SCIP_CALL( SCIPaggrRowSumRows(scip, aggrrow, weights, NULL, -1, FALSE,
    3645 sepadata->allowlocal, 2, (int) MAXAGGRLEN(nvars), &success) );
    3646
    3647 if ( ! success )
    3648 return SCIP_OKAY;
    3649
    3650 SCIP_CALL( SCIPcalcMIR(scip, NULL, POSTPROCESS, BOUNDSWITCH, VARTYPEUSEVBDS, sepadata->allowlocal, FIXINTEGRALRHS, boundsfortrans,
    3651 boundtypesfortrans, MINFRAC, MAXFRAC, 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy,
    3652 &cutrank, &cutislocal, &success) );
    3653
    3654 assert( sepadata->allowlocal || !cutislocal );
    3655 SCIPdebugMsg(scip, "CMIR: success = %u, cut is%sefficacious (cutefficacy: %g, cutrhs: %g)\n", success,
    3656 SCIPisEfficacious(scip, cutefficacy) ? " " : " not ", cutefficacy, cutrhs);
    3657
    3658 /* If successful, convert dense cut into sparse row, and add the row as a cut only if the cut if violated - if it is
    3659 * not violated we might store non-local cuts in the pool. */
    3660 if ( success && (SCIPisEfficacious(scip, cutefficacy) || (sepadata->usecutpool && ! cutislocal)) )
    3661 {
    3662 SCIP_ROW* cut;
    3663
    3664 /* create the cut */
    3665 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cgcut%" SCIP_LONGINT_FORMAT "_%u", SCIPgetNLPs(scip), *ngen);
    3666 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &cut, sepa, name, -SCIPinfinity(scip), cutrhs, cutislocal, FALSE, sepadata->dynamiccuts) );
    3667
    3669
    3670 for (k = 0; k < cutnnz; ++k)
    3671 {
    3672 SCIP_CALL( SCIPaddVarToRow(scip, cut, vars[cutinds[k]], cutcoefs[k]) );
    3673 }
    3674
    3675 assert( success );
    3676
    3677 /* set cut rank */
    3678 SCIProwChgRank(cut, cutrank);
    3679
    3680#ifdef SCIP_DEBUG
    3681 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3682#else
    3683 if ( sepadata->output )
    3684 {
    3685 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3686 }
    3687#endif
    3688
    3689 /* try to scale the cut to integral values */
    3691 maxdnom, maxscale, MAKECONTINTEGRAL, &success) );
    3692
    3693 /* if the cut could be made integral */
    3694 if ( success )
    3695 {
    3697
    3698 /* add cut to pool */
    3699 if ( ! cutislocal )
    3700 {
    3701 assert( SCIPisEfficacious(scip, cutefficacy) || sepadata->usecutpool );
    3702 SCIP_CALL( SCIPaddPoolCut(scip, cut) );
    3703 }
    3704
    3705 if ( ! SCIPisCutEfficacious(scip, NULL, cut) )
    3706 {
    3707 SCIPdebugMsg(scip, " -> CG-cut <%s> no longer efficacious: act=%f, rhs=%f, norm=%f, eff=%f\n",
    3708 name, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
    3710
    3711 /* release the row */
    3712 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3713 }
    3714 else
    3715 {
    3716 /* check whether cut has been found before - may happend due to projection */
    3717 for (k = 0; k < *nprevrows; ++k)
    3718 {
    3719 SCIP_Real parval;
    3720
    3721 assert( prevrows[k] != NULL );
    3722 parval = SCIProwGetParallelism(cut, prevrows[k], 'e');
    3723 /* exit if row is parallel to existing cut and rhs is not better */
    3724 if ( SCIPisEQ(scip, parval, 1.0) && SCIPisGE(scip, cutrhs, SCIProwGetRhs(prevrows[k])) )
    3725 break;
    3726 }
    3727
    3728 /* if cut is new */
    3729 if ( k >= *nprevrows )
    3730 {
    3731 prevrows[*nprevrows] = cut;
    3732 ++(*nprevrows);
    3733
    3734 SCIPdebugMsg(scip, " -> CG-cut <%s>: act=%f, rhs=%f, norm=%f, eff=%f, rank=%d, min=%f, max=%f (range=%f)\n",
    3735 name, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
    3739#ifdef SCIP_OUTPUT
    3740 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3741#else
    3742 if ( sepadata->output )
    3743 {
    3744 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3745 }
    3746#endif
    3747 SCIP_CALL( SCIPaddRow(scip, cut, FALSE, cutoff) );
    3748 ++(*ngen);
    3749 }
    3750 else
    3751 {
    3752 SCIPdebugMsg(scip, "Cut already exists.\n");
    3753 /* release the row */
    3754 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3755 }
    3756 }
    3757 }
    3758 else
    3759 {
    3760 SCIPdebugMsg(scip, " -> CG-cut <%s> could not be scaled to integral coefficients: rhs=%f, eff=%f\n",
    3761 name, cutefficacy, cutrhs);
    3762
    3763 /* release the row */
    3764 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3765 }
    3766 }
    3767
    3768 return SCIP_OKAY;
    3769}
    3770
    3771
    3772/** create CG-cut via strong-CG-function */
    3773static
    3775 SCIP* scip, /**< SCIP data structure */
    3776 SCIP_SEPA* sepa, /**< separator */
    3777 SCIP_SEPADATA* sepadata, /**< separator data */
    3778 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    3779 SCIP_SOL* sol, /**< solution of sub-MIP */
    3780 SCIP_AGGRROW* aggrrow, /**< aggregation row to use for creating MIR cut */
    3781 SCIP_Real* cutcoefs, /**< cut coefficients */
    3782 int* cutinds, /**< problem indices of variables appearing in cut */
    3783 SCIP_Real* cutvals, /**< values of variables in cut */
    3784 SCIP_Real* varsolvals, /**< solution value of variables */
    3785 SCIP_Real* weights, /**< weights to compute cmir cut */
    3786 int* nprevrows, /**< number of previously generated rows */
    3787 SCIP_ROW** prevrows, /**< previously generated rows */
    3788 SCIP_Bool* cutoff, /**< whether a cutoff has been detected */
    3789 unsigned int* ngen /**< number of generated cuts */
    3790 )
    3791{
    3792 char name[SCIP_MAXSTRLEN];
    3793 SCIP_Longint maxdnom;
    3794 SCIP_Bool cutislocal;
    3795 SCIP_Real maxscale;
    3796 SCIP_Real cutrhs;
    3797 SCIP_Real cutefficacy;
    3798 SCIP_Bool success;
    3799 SCIP_ROW** rows;
    3800 SCIP_VAR** vars;
    3801 SCIP* subscip;
    3802 int nrows;
    3803 int nvars;
    3804 int k;
    3805 int cutrank;
    3806 int cutnnz;
    3807
    3808 assert( scip != NULL );
    3809 assert( sepadata != NULL );
    3810 assert( mipdata != NULL );
    3811 assert( sol != NULL );
    3812 assert( cutcoefs != NULL );
    3813 assert( cutinds != NULL );
    3814 assert( cutvals != NULL );
    3815 assert( varsolvals != NULL );
    3816 assert( weights != NULL );
    3817 assert( nprevrows != NULL );
    3818 assert( prevrows != NULL );
    3819 assert( cutoff != NULL );
    3820 assert( ngen != NULL );
    3821
    3822 *cutoff = FALSE;
    3823 subscip = mipdata->subscip;
    3824 assert( subscip != NULL );
    3825
    3826 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
    3827 assert( nrows > 0 );
    3828 assert( (int) mipdata->nrows == nrows );
    3829
    3830 /* @todo more advanced settings - compare sepa_gomory.c */
    3831 maxdnom = (SCIP_Longint) sepadata->cutcoefbnd + 1;
    3832 maxscale = 10000.0;
    3833
    3834 /* get variable data */
    3835 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    3836
    3837 /* generate weights */
    3838 for (k = 0; k < nrows; ++k)
    3839 {
    3840 SCIP_Real val;
    3841
    3842 weights[k] = 0;
    3843 if ( mipdata->ylhs[k] != NULL )
    3844 {
    3845 assert( !SCIProwIsModifiable(rows[k]) && (!SCIProwIsLocal(rows[k]) || sepadata->allowlocal) );
    3846
    3847 val = SCIPgetSolVal(subscip, sol, mipdata->ylhs[k]);
    3848 assert( ! SCIPisFeasNegative(subscip, val) );
    3849
    3850 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    3851 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    3852
    3853 if ( SCIPisFeasPositive(subscip, val) )
    3854 weights[k] = -val;
    3855 }
    3856
    3857 if ( mipdata->yrhs[k] != NULL )
    3858 {
    3859 assert( !SCIProwIsModifiable(rows[k]) && (!SCIProwIsLocal(rows[k]) || sepadata->allowlocal) );
    3860
    3861 val = SCIPgetSolVal(subscip, sol, mipdata->yrhs[k]);
    3862 assert( ! SCIPisFeasNegative(subscip, val) );
    3863
    3864 assert( sepadata->skipmultbounds || SCIPisFeasLT(subscip, val, 1.0) );
    3865 val = SCIPfrac(scip, val); /* take fractional value if variable has no upper bounds */
    3866
    3867 /* in a suboptimal solution both values may be positive - take the one with larger absolute value */
    3868 if ( SCIPisFeasGT(scip, val, ABS(weights[k])) )
    3869 weights[k] = val;
    3870 }
    3871 }
    3872
    3873 /* create a strong CG cut out of the weighted LP rows using the B^-1 row as weights */
    3874 cutefficacy = -1.0;
    3875 cutrhs = -1.0;
    3876 SCIP_CALL( SCIPaggrRowSumRows(scip, aggrrow, weights, NULL, -1, FALSE,
    3877 sepadata->allowlocal, 1, (int) MAXAGGRLEN(nvars), &success) );
    3878
    3879 if ( ! success )
    3880 return SCIP_OKAY;
    3881
    3883 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, &cutrank, &cutislocal, &success) );
    3884
    3885 assert( sepadata->allowlocal || !cutislocal );
    3886 SCIPdebugMsg(scip, "Strong-CG: success = %u, cut is%sefficacious (cutefficacy: %g, cutrhs: %g)\n", success,
    3887 SCIPisEfficacious(scip, cutefficacy) ? " " : " not ", cutefficacy, cutrhs);
    3888
    3889 /* If successful, convert dense cut into sparse row, and add the row as a cut only if the cut if violated - if it is
    3890 * not violated we might store non-local cuts in the pool. */
    3891 if ( success && (SCIPisEfficacious(scip, cutefficacy) || (sepadata->usecutpool && ! cutislocal)) )
    3892 {
    3893 SCIP_ROW* cut;
    3894
    3895 /* create the cut */
    3896 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cgcut%" SCIP_LONGINT_FORMAT "_%u", SCIPgetNLPs(scip), *ngen);
    3897 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &cut, sepa, name, -SCIPinfinity(scip), cutrhs, cutislocal, FALSE, sepadata->dynamiccuts) );
    3898
    3900
    3901 for (k = 0; k < cutnnz; ++k)
    3902 {
    3903 SCIP_CALL( SCIPaddVarToRow(scip, cut, vars[cutinds[k]], cutcoefs[k]) );
    3904 }
    3905
    3906 assert( success );
    3907
    3908 /* set cut rank */
    3909 SCIProwChgRank(cut, cutrank);
    3910
    3911#ifdef SCIP_DEBUG
    3912 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3913#else
    3914 if ( sepadata->output )
    3915 {
    3916 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3917 }
    3918#endif
    3919
    3920 /* try to scale the cut to integral values */
    3922 maxdnom, maxscale, MAKECONTINTEGRAL, &success) );
    3923
    3924 /* if the cut could be made integral */
    3925 if ( success )
    3926 {
    3928
    3929 /* add cut to pool */
    3930 if ( ! cutislocal )
    3931 {
    3932 assert( SCIPisEfficacious(scip, cutefficacy) || sepadata->usecutpool );
    3933 SCIP_CALL( SCIPaddPoolCut(scip, cut) );
    3934 }
    3935
    3936 if ( ! SCIPisCutEfficacious(scip, NULL, cut) )
    3937 {
    3938 SCIPdebugMsg(scip, " -> CG-cut <%s> no longer efficacious: act=%f, rhs=%f, norm=%f, eff=%f\n",
    3939 name, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
    3941
    3942 /* release the row */
    3943 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3944 }
    3945 else
    3946 {
    3947 /* check whether cut has been found before - may happend due to projection */
    3948 for (k = 0; k < *nprevrows; ++k)
    3949 {
    3950 SCIP_Real parval;
    3951
    3952 assert( prevrows[k] != NULL );
    3953 parval = SCIProwGetParallelism(cut, prevrows[k], 'e');
    3954 /* exit if row is parallel to existing cut and rhs is not better */
    3955 if ( SCIPisEQ(scip, parval, 1.0) && SCIPisGE(scip, cutrhs, SCIProwGetRhs(prevrows[k])) )
    3956 break;
    3957 }
    3958
    3959 /* if cut is new */
    3960 if ( k >= *nprevrows )
    3961 {
    3962 prevrows[*nprevrows] = cut;
    3963 ++(*nprevrows);
    3964
    3965 SCIPdebugMsg(scip, " -> CG-cut <%s>: act=%f, rhs=%f, norm=%f, eff=%f, rank=%d, min=%f, max=%f (range=%f)\n",
    3966 name, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
    3970#ifdef SCIP_OUTPUT
    3971 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3972#else
    3973 if ( sepadata->output )
    3974 {
    3975 SCIP_CALL( SCIPprintRow(scip, cut, NULL) );
    3976 }
    3977#endif
    3978 SCIP_CALL( SCIPaddRow(scip, cut, FALSE, cutoff) );
    3979 ++(*ngen);
    3980 }
    3981 else
    3982 {
    3983 SCIPdebugMsg(scip, "Cut already exists.\n");
    3984 /* release the row */
    3985 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3986 }
    3987 }
    3988 }
    3989 else
    3990 {
    3991 SCIPdebugMsg(scip, " -> CG-cut <%s> could not be scaled to integral coefficients: rhs=%f, eff=%f\n",
    3992 name, cutefficacy, cutrhs);
    3993
    3994 /* release the row */
    3995 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
    3996 }
    3997 }
    3998
    3999 return SCIP_OKAY;
    4000}
    4001
    4002
    4003/** Create CG-cuts from solutions of sub-MIP */
    4004static
    4006 SCIP* scip, /**< SCIP data structure */
    4007 SCIP_SEPA* sepa, /**< separator */
    4008 SCIP_SEPADATA* sepadata, /**< separator data */
    4009 CGMIP_MIPDATA* mipdata, /**< data for sub-MIP */
    4010 SCIP_Bool* cutoff, /**< whether a cutoff has been detected */
    4011 unsigned int* ngen /**< number of generated cuts */
    4012 )
    4013{
    4014 SCIP_BOUNDTYPE* boundtypesfortrans;
    4015 SCIP_STAGE stage;
    4016 SCIP_AGGRROW* aggrrow = NULL;
    4017 SCIP_Real* varsolvals;
    4018 SCIP_Real* weights;
    4019 int* cutinds;
    4020 SCIP_Real* cutvals;
    4021 SCIP_Real* cutcoefs;
    4022 SCIP_ROW** prevrows;
    4023 SCIP_SOL** sols;
    4024 SCIP_VAR** vars;
    4025 SCIP* subscip;
    4026 int* boundsfortrans;
    4027 int nprevrows;
    4028 int ntotalrows;
    4029 int nsols;
    4030 int nvars;
    4031 int k;
    4032 int s;
    4033
    4034 assert( scip != NULL );
    4035 assert( sepadata != NULL );
    4036 assert( mipdata != NULL );
    4037 assert( cutoff != NULL );
    4038 assert( ngen != NULL );
    4039
    4040 subscip = mipdata->subscip;
    4041 assert( subscip != NULL );
    4042
    4043 *cutoff = FALSE;
    4044 *ngen = 0;
    4045
    4046 /* check if solving was successful and get solutions */
    4047 stage = SCIPgetStage(subscip);
    4048 if ( stage == SCIP_STAGE_SOLVING || stage == SCIP_STAGE_SOLVED )
    4049 nsols = SCIPgetNSols(subscip);
    4050 else
    4051 nsols = 0;
    4052
    4053 /* only if solutions have been found */
    4054 if ( nsols == 0 )
    4055 return SCIP_OKAY;
    4056
    4057 SCIPdebugMsg(scip, "Generating CG-cuts from %d sols (cmir: %u, strong-cg: %u) ...\n", nsols, sepadata->usecmir, sepadata->usestrongcg);
    4058
    4059 sols = SCIPgetSols(subscip);
    4060
    4061 /* get variable data */
    4062 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    4063
    4064 /* allocate temporary memory */
    4065 assert(mipdata->ntotalrows <= INT_MAX);
    4066 ntotalrows = (int)mipdata->ntotalrows;
    4067 assert( ntotalrows >= SCIPgetNLPRows(scip) && ntotalrows <= SCIPgetNLPRows(scip) + 1 );
    4068 SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, nvars) );
    4069 SCIP_CALL( SCIPallocBufferArray(scip, &varsolvals, nvars) );
    4070 SCIP_CALL( SCIPallocBufferArray(scip, &cutinds, nvars) );
    4071 SCIP_CALL( SCIPallocBufferArray(scip, &cutvals, nvars) );
    4072 SCIP_CALL( SCIPallocBufferArray(scip, &weights, ntotalrows) );
    4073 SCIP_CALL( SCIPallocBufferArray(scip, &prevrows, 2 * nsols) );
    4074
    4075 if ( sepadata->usecmir || sepadata->usestrongcg )
    4076 {
    4077 SCIP_CALL( SCIPaggrRowCreate(scip, &aggrrow) );
    4078 }
    4079
    4080 /* prepare arrays for bound information, if requested */
    4081 if ( sepadata->usecmir && sepadata->cmirownbounds )
    4082 {
    4083 SCIP_CALL( SCIPallocBufferArray(scip, &boundsfortrans, nvars) );
    4084 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypesfortrans, nvars) );
    4085 }
    4086 else
    4087 {
    4088 boundsfortrans = NULL;
    4089 boundtypesfortrans = NULL;
    4090 }
    4091
    4092 /* get solution values */
    4093 for (k = 0; k < nvars; ++k)
    4094 {
    4095 if ( SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_COLUMN )
    4096 varsolvals[k] = SCIPvarGetLPSol(vars[k]);
    4097 else
    4098 varsolvals[k] = 0.0;
    4099 }
    4100
    4101 /* loop through solutions found */
    4102 nprevrows = 0;
    4103 for (s = 0; s < nsols; ++s)
    4104 {
    4105 SCIP_SOL* sol;
    4106 sol = sols[s];
    4107
    4108 /* generate cuts by the C-MIR and/or Strong-CG functions */
    4109 if ( sepadata->usecmir )
    4110 {
    4111 SCIP_CALL( createCGCutCMIR(scip, sepa, sepadata, mipdata, sol, aggrrow, cutcoefs, cutinds, cutvals, varsolvals, weights,
    4112 boundsfortrans, boundtypesfortrans, &nprevrows, prevrows, cutoff, ngen) );
    4113 }
    4114
    4115 if ( sepadata->usestrongcg )
    4116 {
    4117 SCIP_CALL( createCGCutStrongCG(scip, sepa, sepadata, mipdata, sol, aggrrow, cutcoefs, cutinds, cutvals, varsolvals, weights,
    4118 &nprevrows, prevrows, cutoff, ngen) );
    4119 }
    4120
    4121 if ( ! sepadata->usecmir && ! sepadata->usestrongcg )
    4122 {
    4123 SCIP_CALL( createCGCutDirect(scip, sepa, sepadata, mipdata, sol, cutcoefs, cutinds, cutvals, varsolvals, weights,
    4124 &nprevrows, prevrows, cutoff, ngen) );
    4125
    4126 assert(! sepadata->usecmir && ! sepadata->usestrongcg);
    4127 }
    4128 }
    4129 assert( nprevrows <= 2 * nsols );
    4130 assert( sepadata->usecmir || nprevrows <= nsols );
    4131 assert( sepadata->usestrongcg || nprevrows <= nsols );
    4132
    4133 /* release rows */
    4134 for (k = 0; k < nprevrows; ++k)
    4135 {
    4136 SCIP_CALL( SCIPreleaseRow(scip, &(prevrows[k])) );
    4137 }
    4138
    4139 if ( sepadata->usecmir || sepadata->usestrongcg )
    4140 SCIPaggrRowFree(scip, &aggrrow);
    4141
    4142 /* free temporary memory */
    4143 SCIPfreeBufferArrayNull(scip, &boundsfortrans);
    4144 SCIPfreeBufferArrayNull(scip, &boundtypesfortrans);
    4145
    4146 SCIPfreeBufferArray(scip, &prevrows);
    4147 SCIPfreeBufferArray(scip, &weights);
    4148 SCIPfreeBufferArray(scip, &cutvals);
    4149 SCIPfreeBufferArray(scip, &cutinds);
    4150 SCIPfreeBufferArray(scip, &varsolvals);
    4151 SCIPfreeBufferArray(scip, &cutcoefs);
    4152
    4153 return SCIP_OKAY;
    4154}
    4155
    4156
    4157/** frees "subscip" data */
    4158static
    4160 SCIP* scip, /**< SCIP data structure */
    4161 SCIP_SEPA* sepa, /**< separator data */
    4162 CGMIP_MIPDATA* mipdata /**< data for sub-MIP */
    4163 )
    4164{
    4165 SCIP_SEPADATA* sepadata;
    4166 unsigned int i, j;
    4167 SCIP* subscip;
    4168
    4169 assert( scip != NULL );
    4170 assert( sepa != NULL );
    4171 assert( mipdata != NULL );
    4172
    4173 /* free separator data */
    4174 sepadata = SCIPsepaGetData(sepa);
    4175 assert( sepadata != NULL );
    4176
    4177 SCIPdebugMsg(scip, "Freeing subscip ...\n");
    4178
    4179 subscip = mipdata->subscip;
    4180 assert( subscip != NULL );
    4181
    4182 for (j = 0; j < mipdata->ncols; ++j)
    4183 {
    4184 if ( mipdata->coltype[j] == colPresent )
    4185 {
    4186 assert( mipdata->alpha[j] != NULL );
    4187 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->alpha[j])) );
    4188 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->fracalpha[j])) );
    4189 }
    4190 }
    4191 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->beta)) );
    4192 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->fracbeta)) );
    4193
    4194 for (i = 0; i < mipdata->nrows; ++i)
    4195 {
    4196 if ( mipdata->ylhs[i] != NULL )
    4197 {
    4198 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->ylhs[i])) );
    4199 }
    4200 if ( mipdata->yrhs[i] != NULL )
    4201 {
    4202 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->yrhs[i])) );
    4203 }
    4204 }
    4205
    4206 if ( sepadata->useobjub || sepadata->useobjlb )
    4207 {
    4208 if ( mipdata->yrhs[mipdata->nrows] )
    4209 {
    4210 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->yrhs[mipdata->nrows])) );
    4211 }
    4212 if ( mipdata->ylhs[mipdata->nrows] )
    4213 {
    4214 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->ylhs[mipdata->nrows])) );
    4215 }
    4216 }
    4217
    4218 for (j = 0; j < mipdata->ncols; ++j)
    4219 {
    4220 if ( mipdata->z[j] != NULL )
    4221 {
    4222 SCIP_CALL( SCIPreleaseVar(subscip, &(mipdata->z[j])) );
    4223 }
    4224 }
    4225
    4226 SCIP_CALL( SCIPfree(&(mipdata->subscip)) );
    4227
    4228 SCIPfreeBlockMemoryArray(scip, &(mipdata->rhs), mipdata->ntotalrows);
    4229 SCIPfreeBlockMemoryArray(scip, &(mipdata->lhs), mipdata->ntotalrows);
    4230 SCIPfreeBlockMemoryArray(scip, &(mipdata->z), 2*mipdata->ncols); /*lint !e647*/
    4231 SCIPfreeBlockMemoryArray(scip, &(mipdata->yrhs), mipdata->ntotalrows);
    4232 SCIPfreeBlockMemoryArray(scip, &(mipdata->ylhs), mipdata->ntotalrows);
    4233 SCIPfreeBlockMemoryArray(scip, &(mipdata->isshifted), mipdata->ncols);
    4234 SCIPfreeBlockMemoryArray(scip, &(mipdata->iscomplemented), mipdata->ncols);
    4235 SCIPfreeBlockMemoryArray(scip, &(mipdata->coltype), mipdata->ncols);
    4236 SCIPfreeBlockMemoryArray(scip, &(mipdata->fracalpha), mipdata->ncols);
    4237 SCIPfreeBlockMemoryArray(scip, &(mipdata->alpha), mipdata->ncols);
    4238
    4239 return SCIP_OKAY;
    4240}
    4241
    4242
    4243/*
    4244 * Callback methods
    4245 */
    4246
    4247
    4248/** initialization method of separator (called after problem was transformed) */
    4249static
    4251{
    4252 SCIP_SEPADATA* sepadata;
    4253
    4254 sepadata = SCIPsepaGetData(sepa);
    4255 assert(sepadata != NULL);
    4256
    4257 /* create and initialize random number generator */
    4258 SCIP_CALL( SCIPcreateRandom(scip, &sepadata->randnumgen, DEFAULT_RANDSEED, TRUE) );
    4259
    4260 return SCIP_OKAY;
    4261}
    4262
    4263/** deinitialization method of separator (called before transformed problem is freed) */
    4264static
    4266{ /*lint --e{715}*/
    4267 SCIP_SEPADATA* sepadata;
    4268
    4269 sepadata = SCIPsepaGetData(sepa);
    4270 assert(sepadata != NULL);
    4271
    4272 SCIPfreeRandom(scip, &sepadata->randnumgen);
    4273
    4274 return SCIP_OKAY;
    4275}
    4276
    4277/** copy method for separator plugins (called when SCIP copies plugins) */
    4278static
    4280{ /*lint --e{715}*/
    4281 assert( scip != NULL );
    4282 assert( sepa != NULL );
    4283 assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
    4284
    4285 /* call inclusion method of constraint handler */
    4287
    4288 return SCIP_OKAY;
    4289}
    4290
    4291
    4292/** destructor of separator to free user data (called when SCIP is exiting) */
    4293static
    4295{ /*lint --e{715}*/
    4296 SCIP_SEPADATA* sepadata;
    4297
    4298 assert( scip != NULL );
    4299 assert( sepa != NULL );
    4300 assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
    4301
    4302 /* free separator data */
    4303 sepadata = SCIPsepaGetData(sepa);
    4304 assert( sepadata != NULL );
    4305
    4306 SCIPfreeBlockMemory(scip, &sepadata);
    4307
    4308 SCIPsepaSetData(sepa, NULL);
    4309
    4310 return SCIP_OKAY;
    4311}
    4312
    4313
    4314/** LP solution separation method of separator */
    4315static
    4316SCIP_DECL_SEPAEXECLP(sepaExeclpCGMIP)
    4317{ /*lint --e{715}*/
    4318 SCIP_SEPADATA* sepadata;
    4319 CGMIP_MIPDATA* mipdata;
    4320
    4321 int ncalls;
    4322 int ncols;
    4323 int nrows;
    4324 unsigned int ngen = 0;
    4325 SCIP_Bool success;
    4326 SCIP_Bool cutoff = FALSE;
    4327
    4328 assert( scip != NULL );
    4329 assert( sepa != NULL );
    4330 assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
    4331 assert( result != NULL );
    4332
    4333 *result = SCIP_DIDNOTRUN;
    4334
    4335 sepadata = SCIPsepaGetData(sepa);
    4336 assert(sepadata != NULL);
    4337
    4338 /* only call separator, if we are not close to terminating */
    4339 if ( SCIPisStopped(scip) )
    4340 return SCIP_OKAY;
    4341
    4342 /* only call separator up to a maximum depth */
    4343 if ( sepadata->maxdepth >= 0 && depth > sepadata->maxdepth )
    4344 return SCIP_OKAY;
    4345
    4346 /* only call separator a given number of times at each node */
    4347 ncalls = SCIPsepaGetNCallsAtNode(sepa);
    4348 if ( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
    4349 || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
    4350 return SCIP_OKAY;
    4351
    4352 /* only call separator, if an optimal LP solution is at hand */
    4354 return SCIP_OKAY;
    4355
    4356 /* skip separation if there are continuous variables, but only integers required */
    4357 if ( SCIPgetNContVars(scip) > 0 && sepadata->onlyintvars )
    4358 return SCIP_OKAY;
    4359
    4360 /* only call separator, if there are fractional variables */
    4361 if ( SCIPgetNLPBranchCands(scip) == 0 )
    4362 return SCIP_OKAY;
    4363
    4364 /* check for parameters */
    4365 if ( ( sepadata->useobjub || sepadata->useobjlb ) && ( sepadata->usecmir || sepadata->usestrongcg ) )
    4366 {
    4368 "WARNING - sepa_cgmip: Using objective function bounds and CMIR or Strong-CG functions is useless. Turning off usage of objective function bounds.\n");
    4369 SCIP_CALL( SCIPsetBoolParam(scip, "separating/cgmip/useobjub", FALSE) );
    4370 SCIP_CALL( SCIPsetBoolParam(scip, "separating/cgmip/useobjlb", FALSE) );
    4371 }
    4372 sepadata->allowlocal = allowlocal;
    4373
    4374 /* get LP data */
    4375 ncols = SCIPgetNLPCols(scip);
    4376 nrows = SCIPgetNLPRows(scip);
    4377 if ( ncols <= NCOLSTOOSMALL || nrows <= NROWSTOOSMALL )
    4378 return SCIP_OKAY;
    4379
    4380 /* determine whether we should run the separation based on a decision tree */
    4381 if ( sepadata->decisiontree )
    4382 {
    4384 SCIP_Real firstlptime;
    4385
    4386 separate = FALSE;
    4387 firstlptime = SCIPgetFirstLPTime(scip);
    4388
    4389 if ( nrows <= 136 && firstlptime <= 0.05 && ncols <= 143 )
    4390 separate = TRUE;
    4391 else if ( nrows <= 136 && 0.05 < firstlptime && firstlptime <= 0.15 && ncols <= 143 )
    4392 separate = TRUE;
    4393 else if ( 136 < nrows && nrows <= 332 && ncols <= 143 )
    4394 separate = TRUE;
    4395 else if ( 136 < nrows && nrows <= 332 && 655 < ncols && ncols <= 1290 )
    4396 separate = TRUE;
    4397 else if ( 333 < nrows && nrows <= 874 && 0.15 < firstlptime && firstlptime <= 0.25 && 2614 < ncols && ncols <= 5141 )
    4398 separate = TRUE;
    4399 else if ( 875 < nrows && nrows <= 1676 && firstlptime <= 0.05 && 143 < ncols && ncols <= 265 )
    4400 separate = TRUE;
    4401 else if ( 875 < nrows && nrows <= 1676 && firstlptime <= 0.05 && 265 < ncols && ncols <= 654 )
    4402 separate = TRUE;
    4403 else if ( 875 < nrows && nrows <= 1676 && 0.05 < firstlptime && firstlptime <= 0.15 )
    4404 separate = TRUE;
    4405 else if ( 875 < nrows && nrows <= 1676 && 0.15 < firstlptime && firstlptime <= 0.25 && 1291 < ncols && ncols <= 2613 )
    4406 separate = TRUE;
    4407 else if ( nrows > 8146 && 0.75 < firstlptime && firstlptime <= 6.25 && 655 < ncols && ncols <= 1290 )
    4408 separate = TRUE;
    4409 else if ( nrows > 8146 && 0.75 < firstlptime && firstlptime <= 6.25 && 1291 < ncols && ncols <= 2613 )
    4410 separate = TRUE;
    4411 else if ( nrows > 8146 && firstlptime > 6.25 )
    4412 separate = TRUE;
    4413
    4414 if ( ! separate )
    4415 {
    4416 return SCIP_OKAY;
    4417 }
    4418 }
    4419
    4420 /* preceed with separation */
    4421 *result = SCIP_DIDNOTFIND;
    4422
    4423 SCIPdebugMsg(scip, "separating CG-cuts via sub-MIPs: %d cols, %d rows\n", ncols, nrows);
    4424
    4425 /* prepare data */
    4426 SCIP_CALL( SCIPallocBlockMemory(scip, &mipdata) );
    4427 mipdata->subscip = NULL;
    4428 mipdata->alpha = NULL;
    4429 mipdata->fracalpha = NULL;
    4430 mipdata->beta = NULL;
    4431 mipdata->fracbeta = NULL;
    4432 mipdata->coltype = NULL;
    4433 mipdata->iscomplemented = NULL;
    4434 mipdata->isshifted = NULL;
    4435 mipdata->ylhs = NULL;
    4436 mipdata->yrhs = NULL;
    4437 mipdata->z = NULL;
    4438 mipdata->lhs = NULL;
    4439 mipdata->rhs = NULL;
    4440 mipdata->normtype = ' ';
    4441
    4442 mipdata->conshdlrfullnorm = CONSHDLRFULLNORM;
    4443 mipdata->scip = scip;
    4444 mipdata->sepa = sepa;
    4445 mipdata->sepadata = sepadata;
    4446
    4447 /* get the type of norm to use for efficacy calculations */
    4448 SCIP_CALL( SCIPgetCharParam(scip, "separating/efficacynorm", &mipdata->normtype) );
    4449
    4450 /* create subscip */
    4451 SCIP_CALL( createSubscip(scip, sepa, sepadata, mipdata) );
    4452
    4453 /* set parameters */
    4454 SCIP_CALL( subscipSetParams(sepadata, mipdata) );
    4455
    4456 if ( ! SCIPisStopped(scip) )
    4457 {
    4458 /* solve subscip */
    4459 SCIP_CALL( solveSubscip(scip, sepadata, mipdata, &success) );
    4460
    4461 /* preceed if solution was successful */
    4462 if ( success && ! SCIPisStopped(scip) )
    4463 {
    4464 SCIP_CALL( createCGCuts(scip, sepa, sepadata, mipdata, &cutoff, &ngen) );
    4465 }
    4466 }
    4467
    4468 SCIP_CALL( freeSubscip(scip, sepa, mipdata) );
    4469 SCIPfreeBlockMemory(scip, &mipdata);
    4470
    4471 SCIPdebugMsg(scip, "Found %u CG-cuts.\n", ngen);
    4472
    4473 if ( cutoff )
    4474 *result = SCIP_CUTOFF;
    4475 else if ( ngen > 0 )
    4476 *result = SCIP_SEPARATED;
    4477
    4478#ifdef SCIP_OUTPUT
    4479 /* SCIP_CALL( SCIPwriteLP(scip, "cuts.lp") ); */
    4480 /* SCIP_CALL( SCIPwriteMIP(scip, "cuts.lp", FALSE, TRUE) ); */
    4481#endif
    4482
    4483 return SCIP_OKAY;
    4484}
    4485
    4486/*
    4487 * separator specific interface methods
    4488 */
    4489
    4490/** creates the CGMIP MIR cut separator and includes it in SCIP */
    4492 SCIP* scip /**< SCIP data structure */
    4493 )
    4494{
    4495 SCIP_SEPADATA* sepadata;
    4496 SCIP_SEPA* sepa = NULL;
    4497
    4498 /* create separator data */
    4499 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
    4500
    4501 /* include separator */
    4503 SEPA_USESSUBSCIP, SEPA_DELAY, sepaExeclpCGMIP, NULL, sepadata) );
    4504 assert(sepa != NULL);
    4505
    4506 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyCGMIP) );
    4507 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeCGMIP) );
    4508 SCIP_CALL( SCIPsetSepaInit(scip, sepa, sepaInitCGMIP) );
    4509 SCIP_CALL( SCIPsetSepaExit(scip, sepa, sepaExitCGMIP) );
    4510
    4511 /* add separator parameters */
    4513 "separating/" SEPA_NAME "/maxrounds",
    4514 "maximal number of cgmip separation rounds per node (-1: unlimited)",
    4515 &sepadata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
    4516
    4518 "separating/" SEPA_NAME "/maxroundsroot",
    4519 "maximal number of cgmip separation rounds in the root node (-1: unlimited)",
    4520 &sepadata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
    4521
    4523 "separating/" SEPA_NAME "/maxdepth",
    4524 "maximal depth at which the separator is applied (-1: unlimited)",
    4525 &sepadata->maxdepth, FALSE, DEFAULT_MAXDEPTH, -1, INT_MAX, NULL, NULL) );
    4526
    4528 "separating/" SEPA_NAME "/decisiontree",
    4529 "Use decision tree to turn separation on/off?",
    4530 &sepadata->decisiontree, FALSE, DEFAULT_DECISIONTREE, NULL, NULL) );
    4531
    4533 "separating/" SEPA_NAME "/timelimit",
    4534 "time limit for sub-MIP",
    4535 &sepadata->timelimit, TRUE, DEFAULT_TIMELIMIT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    4536
    4538 "separating/" SEPA_NAME "/memorylimit",
    4539 "memory limit for sub-MIP",
    4540 &sepadata->memorylimit, TRUE, DEFAULT_MEMORYLIMIT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    4541
    4543 "separating/" SEPA_NAME "/minnodelimit",
    4544 "minimum number of nodes considered for sub-MIP (-1: unlimited)",
    4545 &sepadata->minnodelimit, FALSE, DEFAULT_MINNODELIMIT, -1LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4546
    4548 "separating/" SEPA_NAME "/maxnodelimit",
    4549 "maximum number of nodes considered for sub-MIP (-1: unlimited)",
    4550 &sepadata->maxnodelimit, FALSE, DEFAULT_MAXNODELIMIT, -1LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4551
    4553 "separating/" SEPA_NAME "/cutcoefbnd",
    4554 "bounds on the values of the coefficients in the CG-cut",
    4555 &sepadata->cutcoefbnd, TRUE, DEFAULT_CUTCOEFBND, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    4556
    4558 "separating/" SEPA_NAME "/onlyactiverows",
    4559 "Use only active rows to generate cuts?",
    4560 &sepadata->onlyactiverows, FALSE, DEFAULT_ONLYACTIVEROWS, NULL, NULL) );
    4561
    4563 "separating/" SEPA_NAME "/maxrowage",
    4564 "maximal age of rows to consider if onlyactiverows is false",
    4565 &sepadata->maxrowage, FALSE, DEFAULT_MAXROWAGE, -1, INT_MAX, NULL, NULL) );
    4566
    4568 "separating/" SEPA_NAME "/onlyrankone",
    4569 "Separate only rank 1 inequalities w.r.t. CG-MIP separator?",
    4570 &sepadata->onlyrankone, FALSE, DEFAULT_ONLYRANKONE, NULL, NULL) );
    4571
    4573 "separating/" SEPA_NAME "/onlyintvars",
    4574 "Generate cuts for problems with only integer variables?",
    4575 &sepadata->onlyintvars, FALSE, DEFAULT_ONLYINTVARS, NULL, NULL) );
    4576
    4578 "separating/" SEPA_NAME "/contconvert",
    4579 "Convert some integral variables to be continuous to reduce the size of the sub-MIP?",
    4580 &sepadata->contconvert, FALSE, DEFAULT_CONTCONVERT, NULL, NULL) );
    4581
    4583 "separating/" SEPA_NAME "/contconvfrac",
    4584 "fraction of integral variables converted to be continuous (if contconvert)",
    4585 &sepadata->contconvfrac, FALSE, DEFAULT_CONTCONVFRAC, 0.0, 1.0, NULL, NULL) );
    4586
    4588 "separating/" SEPA_NAME "/contconvmin",
    4589 "minimum number of integral variables before some are converted to be continuous",
    4590 &sepadata->contconvmin, FALSE, DEFAULT_CONTCONVMIN, -1, INT_MAX, NULL, NULL) );
    4591
    4593 "separating/" SEPA_NAME "/intconvert",
    4594 "Convert some integral variables attaining fractional values to have integral value?",
    4595 &sepadata->intconvert, FALSE, DEFAULT_INTCONVERT, NULL, NULL) );
    4596
    4598 "separating/" SEPA_NAME "/intconvfrac",
    4599 "fraction of frac. integral variables converted to have integral value (if intconvert)",
    4600 &sepadata->intconvfrac, FALSE, DEFAULT_INTCONVFRAC, 0.0, 1.0, NULL, NULL) );
    4601
    4603 "separating/" SEPA_NAME "/intconvmin",
    4604 "minimum number of integral variables before some are converted to have integral value",
    4605 &sepadata->intconvmin, FALSE, DEFAULT_INTCONVMIN, -1, INT_MAX, NULL, NULL) );
    4606
    4608 "separating/" SEPA_NAME "/skipmultbounds",
    4609 "Skip the upper bounds on the multipliers in the sub-MIP?",
    4610 &sepadata->skipmultbounds, FALSE, DEFAULT_SKIPMULTBOUNDS, NULL, NULL) );
    4611
    4613 "separating/" SEPA_NAME "/objlone",
    4614 "Should the objective of the sub-MIP minimize the l1-norm of the multipliers?",
    4615 &sepadata->objlone, FALSE, DEFAULT_OBJLONE, NULL, NULL) );
    4616
    4618 "separating/" SEPA_NAME "/objweight",
    4619 "weight used for the row combination coefficient in the sub-MIP objective",
    4620 &sepadata->objweight, TRUE, DEFAULT_OBJWEIGHT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    4621
    4623 "separating/" SEPA_NAME "/objweightsize",
    4624 "Weight each row by its size?",
    4625 &sepadata->objweightsize, FALSE, DEFAULT_OBJWEIGHTSIZE, NULL, NULL) );
    4626
    4628 "separating/" SEPA_NAME "/dynamiccuts",
    4629 "should generated cuts be removed from the LP if they are no longer tight?",
    4630 &sepadata->dynamiccuts, FALSE, DEFAULT_DYNAMICCUTS, NULL, NULL) );
    4631
    4633 "separating/" SEPA_NAME "/usecmir",
    4634 "use CMIR-generator (otherwise add cut directly)?",
    4635 &sepadata->usecmir, FALSE, DEFAULT_USECMIR, NULL, NULL) );
    4636
    4638 "separating/" SEPA_NAME "/usestrongcg",
    4639 "use strong CG-function to strengthen cut?",
    4640 &sepadata->usestrongcg, FALSE, DEFAULT_USESTRONGCG, NULL, NULL) );
    4641
    4643 "separating/" SEPA_NAME "/cmirownbounds",
    4644 "tell CMIR-generator which bounds to used in rounding?",
    4645 &sepadata->cmirownbounds, FALSE, DEFAULT_CMIROWNBOUNDS, NULL, NULL) );
    4646
    4648 "separating/" SEPA_NAME "/usecutpool",
    4649 "use cutpool to store CG-cuts even if the are not efficient?",
    4650 &sepadata->usecutpool, FALSE, DEFAULT_USECUTPOOL, NULL, NULL) );
    4651
    4653 "separating/" SEPA_NAME "/primalseparation",
    4654 "only separate cuts that are tight for the best feasible solution?",
    4655 &sepadata->primalseparation, FALSE, DEFAULT_PRIMALSEPARATION, NULL, NULL) );
    4656
    4658 "separating/" SEPA_NAME "/earlyterm",
    4659 "terminate separation if a violated (but possibly sub-optimal) cut has been found?",
    4660 &sepadata->earlyterm, FALSE, DEFAULT_EARLYTERM, NULL, NULL) );
    4661
    4663 "separating/" SEPA_NAME "/addviolationcons",
    4664 "add constraint to subscip that only allows violated cuts (otherwise add obj. limit)?",
    4665 &sepadata->addviolationcons, FALSE, DEFAULT_ADDVIOLATIONCONS, NULL, NULL) );
    4666
    4668 "separating/" SEPA_NAME "/addviolconshdlr",
    4669 "add constraint handler to filter out violated cuts?",
    4670 &sepadata->addviolconshdlr, FALSE, DEFAULT_ADDVIOLCONSHDLR, NULL, NULL) );
    4671
    4673 "separating/" SEPA_NAME "/conshdlrusenorm",
    4674 "should the violation constraint handler use the norm of a cut to check for feasibility?",
    4675 &sepadata->conshdlrusenorm, FALSE, DEFAULT_CONSHDLRUSENORM, NULL, NULL) );
    4676
    4678 "separating/" SEPA_NAME "/useobjub",
    4679 "Use upper bound on objective function (via primal solution)?",
    4680 &sepadata->useobjub, FALSE, DEFAULT_USEOBJUB, NULL, NULL) );
    4681
    4683 "separating/" SEPA_NAME "/useobjlb",
    4684 "Use lower bound on objective function (via primal solution)?",
    4685 &sepadata->useobjlb, FALSE, DEFAULT_USEOBJLB, NULL, NULL) );
    4686
    4688 "separating/" SEPA_NAME "/subscipfast",
    4689 "Should the settings for the sub-MIP be optimized for speed?",
    4690 &sepadata->subscipfast, FALSE, DEFAULT_SUBSCIPFAST, NULL, NULL) );
    4691
    4693 "separating/" SEPA_NAME "/output",
    4694 "Should information about the sub-MIP and cuts be displayed?",
    4695 &sepadata->output, FALSE, DEFAULT_OUTPUT, NULL, NULL) );
    4696
    4698 "separating/" SEPA_NAME "/genprimalsols",
    4699 "Try to generate primal solutions from Gomory cuts?",
    4700 &sepadata->genprimalsols, FALSE, DEFAULT_GENPRIMALSOLS, NULL, NULL) );
    4701
    4702 return SCIP_OKAY;
    4703}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    SCIP_Real * r
    Definition: circlepacking.c:59
    Constraint handler for linear constraints in their most general form, .
    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_REAL_MAX
    Definition: def.h:158
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define SQR(x)
    Definition: def.h:199
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    void SCIPsetSubscipDepth(SCIP *scip, int newdepth)
    Definition: scip_copy.c:2609
    SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
    Definition: scip_copy.c:3249
    int SCIPgetSubscipDepth(SCIP *scip)
    Definition: scip_copy.c:2588
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNObjVars(SCIP *scip)
    Definition: scip_prob.c:2616
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    int SCIPgetNImplVars(SCIP *scip)
    Definition: scip_prob.c:2387
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
    Definition: scip_prob.c:742
    SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
    Definition: scip_prob.c:1661
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
    Definition: scip_prob.c:1417
    SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
    Definition: scip_prob.c:119
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    SCIP_Bool SCIPisObjIntegral(SCIP *scip)
    Definition: scip_prob.c:1801
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:111
    SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
    Definition: scip_param.c:219
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE 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 SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
    Definition: scip_param.c:904
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPwriteParams(SCIP *scip, const char *filename, SCIP_Bool comments, SCIP_Bool onlychanged)
    Definition: scip_param.c:813
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPsetEmphasis(SCIP *scip, SCIP_PARAMEMPHASIS paramemphasis, SCIP_Bool quiet)
    Definition: scip_param.c:882
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
    Definition: scip_param.c:603
    SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:985
    SCIP_RETCODE SCIPgetCharParam(SCIP *scip, const char *name, char *value)
    Definition: scip_param.c:326
    int SCIPgetNLPBranchCands(SCIP *scip)
    Definition: scip_branch.c:436
    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 SCIPcolGetObj(SCIP_COL *col)
    Definition: lp.c:17336
    SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
    Definition: lp.c:17555
    SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
    Definition: lp.c:17545
    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
    int SCIPcolGetNLPNonz(SCIP_COL *col)
    Definition: lp.c:17534
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4336
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    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 SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:117
    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 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
    int SCIPgetNLPRows(SCIP *scip)
    Definition: scip_lp.c:632
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    int SCIPgetNLPCols(SCIP *scip)
    Definition: scip_lp.c:533
    SCIP_RETCODE SCIPgetLPBInvRow(SCIP *scip, int r, SCIP_Real *coefs, int *inds, int *ninds)
    Definition: scip_lp.c:720
    SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
    Definition: scip_mem.c:126
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    SCIP_Longint SCIPgetMemUsed(SCIP *scip)
    Definition: scip_mem.c:100
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #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_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
    SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
    Definition: lp.c:7970
    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
    int SCIProwGetAge(SCIP_ROW *row)
    Definition: lp.c:17765
    int SCIProwGetNLPNonz(SCIP_ROW *row)
    Definition: lp.c:17621
    SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
    Definition: lp.c:17662
    int SCIProwGetLPPos(SCIP_ROW *row)
    Definition: lp.c:17895
    SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1604
    SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
    Definition: lp.c:17795
    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
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    SCIP_SEPA * SCIProwGetOriginSepa(SCIP_ROW *row)
    Definition: lp.c:17870
    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_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
    Definition: lp.c:17734
    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
    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_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_RETCODE SCIPsetSepaInit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINIT((*sepainit)))
    Definition: scip_sepa.c:189
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2981
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2349
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_SOL ** SCIPgetSols(SCIP *scip)
    Definition: scip_sol.c:2931
    SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4109
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPgetDualbound(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_Real SCIPgetFirstLPTime(SCIP *scip)
    Definition: scip_timing.c:468
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Bool SCIPisSumPositive(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFrac(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(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_Bool SCIPisSumZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPepsilon(SCIP *scip)
    SCIP_Real SCIPsumepsilon(SCIP *scip)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23683
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    SCIP_Real SCIPgetVarSol(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:3051
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
    Definition: scip_var.c:120
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    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 SCIPincludeSepaCGMIP(SCIP *scip)
    Definition: sepa_cgmip.c:4491
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for managing constraints
    public methods for LP management
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public data structures and miscellaneous methods
    public methods for separators
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    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 global and local (sub)problems
    public methods for random numbers
    public methods for separator plugins
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for timing
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
    default SCIP plugins
    #define DEFAULT_CUTCOEFBND
    Definition: sepa_cgmip.c:120
    #define EPSILONVALUE
    Definition: sepa_cgmip.c:158
    #define SEPA_PRIORITY
    Definition: sepa_cgmip.c:108
    #define DEFAULT_USECUTPOOL
    Definition: sepa_cgmip.c:141
    #define DEFAULT_CONSHDLRUSENORM
    Definition: sepa_cgmip.c:146
    #define DEFAULT_ADDVIOLCONSHDLR
    Definition: sepa_cgmip.c:145
    static SCIP_RETCODE createSubscip(SCIP *origscip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata)
    Definition: sepa_cgmip.c:1047
    #define DEFAULT_INTCONVMIN
    Definition: sepa_cgmip.c:132
    #define BOUNDSWITCH
    Definition: sepa_cgmip.c:167
    #define SEPA_DELAY
    Definition: sepa_cgmip.c:112
    #define DEFAULT_ADDVIOLATIONCONS
    Definition: sepa_cgmip.c:144
    static SCIP_RETCODE createCGCutCMIR(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata, SCIP_SOL *sol, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, int *cutinds, SCIP_Real *cutvals, SCIP_Real *varsolvals, SCIP_Real *weights, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, int *nprevrows, SCIP_ROW **prevrows, SCIP_Bool *cutoff, unsigned int *ngen)
    Definition: sepa_cgmip.c:3484
    #define CONSHDLR_DESC
    Definition: sepa_cgmip.c:283
    static SCIP_RETCODE solveSubscip(SCIP *origscip, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata, SCIP_Bool *success)
    Definition: sepa_cgmip.c:2444
    #define DEFAULT_OBJWEIGHT
    Definition: sepa_cgmip.c:135
    #define DEFAULT_SKIPMULTBOUNDS
    Definition: sepa_cgmip.c:133
    #define MAXFRAC
    Definition: sepa_cgmip.c:172
    #define NROWSTOOSMALL
    Definition: sepa_cgmip.c:155
    #define DEFAULT_DYNAMICCUTS
    Definition: sepa_cgmip.c:137
    #define DEFAULT_MINNODELIMIT
    Definition: sepa_cgmip.c:121
    #define DEFAULT_CONTCONVERT
    Definition: sepa_cgmip.c:127
    static SCIP_RETCODE computeCut(SCIP *scip, SCIP_SEPA *sepa, CGMIP_MIPDATA *mipdata, SCIP_SEPADATA *sepadata, SCIP_SOL *sol, SCIP_Bool usefrac, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, SCIP_Bool *localrowsused, SCIP_Bool *localboundsused, int *cutrank, SCIP_Bool *success)
    Definition: sepa_cgmip.c:2744
    #define DEFAULT_USEOBJLB
    Definition: sepa_cgmip.c:148
    #define POSTPROCESS
    Definition: sepa_cgmip.c:170
    #define SEPA_DESC
    Definition: sepa_cgmip.c:107
    static SCIP_RETCODE createCGCutDirect(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata, SCIP_SOL *sol, SCIP_Real *cutcoefs, int *cutinds, SCIP_Real *cutvals, SCIP_Real *varsolvals, SCIP_Real *weights, int *nprevrows, SCIP_ROW **prevrows, SCIP_Bool *cutoff, unsigned int *ngen)
    Definition: sepa_cgmip.c:3261
    static SCIP_DECL_SEPACOPY(sepaCopyCGMIP)
    Definition: sepa_cgmip.c:4279
    static SCIP_DECL_CONSENFOLP(consEnfolpViolatedCuts)
    Definition: sepa_cgmip.c:526
    CGMIP_ColType
    Definition: sepa_cgmip.c:229
    @ colConverted
    Definition: sepa_cgmip.c:232
    @ colContinuous
    Definition: sepa_cgmip.c:231
    @ colPresent
    Definition: sepa_cgmip.c:230
    @ colAtUb
    Definition: sepa_cgmip.c:233
    @ colAtLb
    Definition: sepa_cgmip.c:234
    #define MAKECONTINTEGRAL
    Definition: sepa_cgmip.c:174
    #define NCOLSTOOSMALL
    Definition: sepa_cgmip.c:156
    #define DEFAULT_ONLYINTVARS
    Definition: sepa_cgmip.c:126
    #define DEFAULT_DECISIONTREE
    Definition: sepa_cgmip.c:117
    #define DEFAULT_MAXROUNDSROOT
    Definition: sepa_cgmip.c:115
    #define SEPA_USESSUBSCIP
    Definition: sepa_cgmip.c:111
    #define DEFAULT_GENPRIMALSOLS
    Definition: sepa_cgmip.c:152
    #define DEFAULT_MAXDEPTH
    Definition: sepa_cgmip.c:116
    static SCIP_DECL_SEPAINIT(sepaInitCGMIP)
    Definition: sepa_cgmip.c:4250
    static SCIP_Real computeObjWeightSize(int rowsize, int minrowsize, int maxrowsize)
    Definition: sepa_cgmip.c:889
    static SCIP_RETCODE createCGCutStrongCG(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata, SCIP_SOL *sol, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, int *cutinds, SCIP_Real *cutvals, SCIP_Real *varsolvals, SCIP_Real *weights, int *nprevrows, SCIP_ROW **prevrows, SCIP_Bool *cutoff, unsigned int *ngen)
    Definition: sepa_cgmip.c:3774
    #define DEFAULT_ONLYRANKONE
    Definition: sepa_cgmip.c:125
    #define VARTYPEUSEVBDS
    Definition: sepa_cgmip.c:168
    #define DEFAULT_INTCONVERT
    Definition: sepa_cgmip.c:130
    #define FIXINTEGRALRHS
    Definition: sepa_cgmip.c:173
    #define DEFAULT_CMIROWNBOUNDS
    Definition: sepa_cgmip.c:140
    #define DEFAULT_OUTPUT
    Definition: sepa_cgmip.c:150
    #define DEFAULT_OBJLONE
    Definition: sepa_cgmip.c:134
    static SCIP_DECL_CONSLOCK(consLockViolatedCuts)
    Definition: sepa_cgmip.c:593
    static SCIP_RETCODE createCGMIPprimalsols(SCIP *scip, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata)
    Definition: sepa_cgmip.c:2195
    #define DEFAULT_EARLYTERM
    Definition: sepa_cgmip.c:143
    #define CONSHDLRFULLNORM
    Definition: sepa_cgmip.c:161
    struct CGMIP_MIPData CGMIP_MIPDATA
    Definition: sepa_cgmip.c:274
    static SCIP_RETCODE SCIPincludeConshdlrViolatedCut(SCIP *scip, CGMIP_MIPDATA *mipdata)
    Definition: sepa_cgmip.c:602
    #define DEFAULT_PRIMALSEPARATION
    Definition: sepa_cgmip.c:142
    static SCIP_RETCODE freeSubscip(SCIP *scip, SCIP_SEPA *sepa, CGMIP_MIPDATA *mipdata)
    Definition: sepa_cgmip.c:4159
    #define SEPA_MAXBOUNDDIST
    Definition: sepa_cgmip.c:110
    #define DEFAULT_CONTCONVMIN
    Definition: sepa_cgmip.c:129
    #define MAXNSOLS
    Definition: sepa_cgmip.c:163
    #define BETAEPSILONVALUE
    Definition: sepa_cgmip.c:159
    static SCIP_DECL_CONSENFOPS(consEnfopsViolatedCuts)
    Definition: sepa_cgmip.c:553
    #define SEPA_FREQ
    Definition: sepa_cgmip.c:109
    #define MAXWEIGHTRANGE
    Definition: sepa_cgmip.c:175
    static SCIP_DECL_SEPAEXECLP(sepaExeclpCGMIP)
    Definition: sepa_cgmip.c:4316
    static SCIP_DECL_SEPAEXIT(sepaExitCGMIP)
    Definition: sepa_cgmip.c:4265
    #define MINFRAC
    Definition: sepa_cgmip.c:171
    #define DEFAULT_USEOBJUB
    Definition: sepa_cgmip.c:147
    #define DEFAULT_RANDSEED
    Definition: sepa_cgmip.c:151
    #define MAXAGGRLEN(nvars)
    Definition: sepa_cgmip.c:179
    #define DEFAULT_OBJWEIGHTSIZE
    Definition: sepa_cgmip.c:136
    static SCIP_DECL_CONSCHECK(consCheckViolatedCuts)
    Definition: sepa_cgmip.c:567
    static SCIP_RETCODE storeCutInArrays(SCIP *scip, int nvars, SCIP_Real *cutcoefs, SCIP_Real *varsolvals, char normtype, int *cutinds, SCIP_Real *cutvals, int *cutlen, SCIP_Real *cutact, SCIP_Real *cutnorm)
    Definition: sepa_cgmip.c:638
    #define SEPA_NAME
    Definition: sepa_cgmip.c:106
    static SCIP_DECL_CONSFREE(consFreeViolatedCuts)
    Definition: sepa_cgmip.c:509
    static SCIP_RETCODE transformColumn(SCIP *scip, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata, SCIP_COL *col, SCIP_Real offset, SCIP_Real sigma, SCIP_Real *lhs, SCIP_Real *rhs, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *primsol)
    Definition: sepa_cgmip.c:778
    #define DEFAULT_ONLYACTIVEROWS
    Definition: sepa_cgmip.c:123
    static SCIP_RETCODE subscipSetParams(SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata)
    Definition: sepa_cgmip.c:2051
    #define AWAY
    Definition: sepa_cgmip.c:176
    #define DEFAULT_MAXROUNDS
    Definition: sepa_cgmip.c:114
    #define DEFAULT_MEMORYLIMIT
    Definition: sepa_cgmip.c:119
    #define DEFAULT_MAXROWAGE
    Definition: sepa_cgmip.c:124
    #define DEFAULT_USECMIR
    Definition: sepa_cgmip.c:138
    #define OBJWEIGHTRANGE
    Definition: sepa_cgmip.c:164
    #define CONSHDLR_NAME
    Definition: sepa_cgmip.c:282
    static SCIP_RETCODE solCutIsViolated(SCIP *scip, CGMIP_MIPDATA *mipdata, SCIP_SOL *sol, SCIP_Bool *violated)
    Definition: sepa_cgmip.c:310
    #define DEFAULT_SUBSCIPFAST
    Definition: sepa_cgmip.c:149
    #define MINEFFICACY
    Definition: sepa_cgmip.c:162
    #define STALLNODELIMIT
    Definition: sepa_cgmip.c:160
    #define DEFAULT_MAXNODELIMIT
    Definition: sepa_cgmip.c:122
    #define DEFAULT_CONTCONVFRAC
    Definition: sepa_cgmip.c:128
    static SCIP_RETCODE createCGCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, CGMIP_MIPDATA *mipdata, SCIP_Bool *cutoff, unsigned int *ngen)
    Definition: sepa_cgmip.c:4005
    #define DEFAULT_INTCONVFRAC
    Definition: sepa_cgmip.c:131
    enum CGMIP_ColType CGMIP_COLTYPE
    Definition: sepa_cgmip.c:236
    static SCIP_DECL_SEPAFREE(sepaFreeCGMIP)
    Definition: sepa_cgmip.c:4294
    #define DEFAULT_TIMELIMIT
    Definition: sepa_cgmip.c:118
    #define DEFAULT_USESTRONGCG
    Definition: sepa_cgmip.c:139
    Chvatal-Gomory cuts computed via a sub-MIP.
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1221
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_BASESTAT_UPPER
    Definition: type_lpi.h:93
    @ SCIP_BASESTAT_LOWER
    Definition: type_lpi.h:91
    enum SCIP_BaseStat SCIP_BASESTAT
    Definition: type_lpi.h:96
    @ SCIP_VERBLEVEL_NORMAL
    Definition: type_message.h:60
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    @ SCIP_PARAMEMPHASIS_FEASIBILITY
    Definition: type_paramset.h:74
    @ SCIP_OBJSENSE_MAXIMIZE
    Definition: type_prob.h:47
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    @ SCIP_INFEASIBLE
    Definition: type_result.h:46
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    struct SCIP_SepaData SCIP_SEPADATA
    Definition: type_sepa.h:52
    @ SCIP_STAGE_SOLVED
    Definition: type_set.h:54
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    enum SCIP_Stage SCIP_STAGE
    Definition: type_set.h:59
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_STATUS_BESTSOLLIMIT
    Definition: type_stat.h:60
    @ SCIP_STATUS_USERINTERRUPT
    Definition: type_stat.h:47
    @ SCIP_STATUS_INFORUNBD
    Definition: type_stat.h:46
    @ SCIP_STATUS_STALLNODELIMIT
    Definition: type_stat.h:52
    @ SCIP_STATUS_TIMELIMIT
    Definition: type_stat.h:54
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    @ SCIP_STATUS_NODELIMIT
    Definition: type_stat.h:49
    @ SCIP_STATUS_MEMLIMIT
    Definition: type_stat.h:55
    enum SCIP_Status SCIP_STATUS
    Definition: type_stat.h:64
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53