SCIP

    Solving Constraint Integer Programs

    heur_shiftandpropagate.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file heur_shiftandpropagate.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief shiftandpropagate primal heuristic
    28 * @author Timo Berthold
    29 * @author Gregor Hendel
    30 */
    31
    32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    33
    36#include "scip/pub_event.h"
    37#include "scip/pub_heur.h"
    38#include "scip/pub_lp.h"
    39#include "scip/pub_message.h"
    40#include "scip/pub_misc.h"
    41#include "scip/pub_misc_sort.h"
    42#include "scip/pub_sol.h"
    43#include "scip/pub_var.h"
    45#include "scip/scip_event.h"
    46#include "scip/scip_exact.h"
    47#include "scip/scip_general.h"
    48#include "scip/scip_heur.h"
    49#include "scip/scip_lp.h"
    50#include "scip/scip_mem.h"
    51#include "scip/scip_message.h"
    52#include "scip/scip_numerics.h"
    53#include "scip/scip_param.h"
    54#include "scip/scip_prob.h"
    55#include "scip/scip_probing.h"
    57#include "scip/scip_sol.h"
    59#include "scip/scip_tree.h"
    60#include "scip/scip_var.h"
    61
    62
    63#define HEUR_NAME "shiftandpropagate"
    64#define HEUR_DESC "Pre-root heuristic to expand an auxiliary branch-and-bound tree and apply propagation techniques"
    65#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_PROP
    66#define HEUR_PRIORITY 1000
    67#define HEUR_FREQ 0
    68#define HEUR_FREQOFS 0
    69#define HEUR_MAXDEPTH -1
    70#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
    71#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    72
    73#define DEFAULT_WEIGHT_INEQUALITY 1 /**< the heuristic row weight for inequalities */
    74#define DEFAULT_WEIGHT_EQUALITY 3 /**< the heuristic row weight for equations */
    75#define DEFAULT_RELAX TRUE /**< Should continuous variables be relaxed from the problem? */
    76#define DEFAULT_PROBING TRUE /**< Is propagation of solution values enabled? */
    77#define DEFAULT_ONLYWITHOUTSOL TRUE /**< Should heuristic only be executed if no primal solution was found, yet? */
    78#define DEFAULT_NPROPROUNDS 10 /**< The default number of propagation rounds for each propagation used */
    79#define DEFAULT_PROPBREAKER 65000 /**< fixed maximum number of propagations */
    80#define DEFAULT_CUTOFFBREAKER 15 /**< fixed maximum number of allowed cutoffs before the heuristic stops */
    81#define DEFAULT_RANDSEED 29 /**< the default random seed for random number generation */
    82#define DEFAULT_SORTKEY 'v' /**< the default key for variable sorting */
    83#define DEFAULT_SORTVARS TRUE /**< should variables be processed in sorted order? */
    84#define DEFAULT_COLLECTSTATS TRUE /**< should variable statistics be collected during probing? */
    85#define DEFAULT_STOPAFTERFEASIBLE TRUE /**< Should the heuristic stop calculating optimal shift values when no more rows are violated? */
    86#define DEFAULT_PREFERBINARIES TRUE /**< Should binary variables be shifted first? */
    87#define DEFAULT_SELECTBEST FALSE /**< should the heuristic choose the best candidate in every round? (set to FALSE for static order)? */
    88#define DEFAULT_MAXCUTOFFQUOT 0.0 /**< maximum percentage of allowed cutoffs before stopping the heuristic */
    89#define SORTKEYS "nrtuv"/**< options sorting key: (n)orms down, norms (u)p, (v)iolated rows decreasing,
    90 * viola(t)ed rows increasing, or (r)andom */
    91#define DEFAULT_NOZEROFIXING FALSE /**< should variables with a zero shifting value be delayed instead of being fixed? */
    92#define DEFAULT_FIXBINLOCKS TRUE /**< should binary variables with no locks in one direction be fixed to that direction? */
    93#define DEFAULT_BINLOCKSFIRST FALSE /**< should binary variables with no locks be preferred in the ordering? */
    94#define DEFAULT_NORMALIZE TRUE /**< should coefficients and left/right hand sides be normalized by max row coeff? */
    95#define DEFAULT_UPDATEWEIGHTS FALSE /**< should row weight be increased every time the row is violated? */
    96#define DEFAULT_IMPLISCONTINUOUS TRUE /**< should implicit integer variables be treated as continuous variables? */
    97#define DEFAULT_MINFIXINGRATELP 0.0 /**< minimum fixing rate over all variables (including continuous) to solve LP */
    98
    99#define EVENTHDLR_NAME "eventhdlrshiftandpropagate"
    100#define EVENTHDLR_DESC "event handler to catch bound changes"
    101#define EVENTTYPE_SHIFTANDPROPAGATE (SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_GBDCHANGED)
    102
    103
    104/*
    105 * Data structures
    106 */
    107
    108/** primal heuristic data */
    109struct SCIP_HeurData
    110{
    111 SCIP_COL** lpcols; /**< stores lp columns with discrete variables before cont. variables */
    112 SCIP_RANDNUMGEN* randnumgen; /**< random number generation */
    113 int* rowweights; /**< row weight storage */
    114 SCIP_Bool relax; /**< should continuous variables be relaxed from the problem */
    115 SCIP_Bool probing; /**< should probing be executed? */
    116 SCIP_Bool onlywithoutsol; /**< Should heuristic only be executed if no primal solution was found, yet? */
    117 int nlpcols; /**< the number of lp columns */
    118 int nproprounds; /**< The default number of propagation rounds for each propagation used */
    119 int cutoffbreaker; /**< the number of cutoffs before heuristic execution is stopped, or -1 for no
    120 * limit */
    121 SCIP_EVENTHDLR* eventhdlr; /**< event handler to register and process variable bound changes */
    122
    123 SCIP_Real maxcutoffquot; /**< maximum percentage of allowed cutoffs before stopping the heuristic */
    124 SCIP_Real minfixingratelp; /**< minimum fixing rate over all variables (including continuous) to solve LP */
    125 char sortkey; /**< the key by which variables are sorted */
    126 SCIP_Bool sortvars; /**< should variables be processed in sorted order? */
    127 SCIP_Bool collectstats; /**< should variable statistics be collected during probing? */
    128 SCIP_Bool stopafterfeasible; /**< Should the heuristic stop calculating optimal shift values when no
    129 * more rows are violated? */
    130 SCIP_Bool preferbinaries; /**< Should binary variables be shifted first? */
    131 SCIP_Bool nozerofixing; /**< should variables with a zero shifting value be delayed instead of being fixed? */
    132 SCIP_Bool fixbinlocks; /**< should binary variables with no locks in one direction be fixed to that direction? */
    133 SCIP_Bool binlocksfirst; /**< should binary variables with no locks be preferred in the ordering? */
    134 SCIP_Bool normalize; /**< should coefficients be normalized by max row coeff for col norm? */
    135 SCIP_Bool updateweights; /**< should row weight be increased every time the row is violated? */
    136 SCIP_Bool impliscontinuous; /**< should implicit integer variables be treated as continuous variables? */
    137 SCIP_Bool selectbest; /**< should the heuristic choose the best candidate in every round? (set to FALSE for static order)? */
    139 SCIP_LPSOLSTAT lpsolstat; /**< the probing status after probing */
    140 SCIP_Longint ntotaldomredsfound; /**< the total number of domain reductions during heuristic */
    141 SCIP_Longint nlpiters; /**< number of LP iterations which the heuristic needed */
    142 int nremainingviols; /**< the number of remaining violations */
    143 int nprobings; /**< how many probings has the heuristic executed? */
    144 int ncutoffs; /**< has the probing node been cutoff? */
    145 )
    146};
    147
    148/** status of a variable in heuristic transformation */
    150{
    151 TRANSFORMSTATUS_NONE = 0, /**< variable has not been transformed yet */
    152 TRANSFORMSTATUS_LB = 1, /**< variable has been shifted by using lower bound (x-lb) */
    153 TRANSFORMSTATUS_NEG = 2, /**< variable has been negated by using upper bound (ub-x) */
    154 TRANSFORMSTATUS_FREE = 3 /**< variable does not have to be shifted */
    157
    158/** information about the matrix after its heuristic transformation */
    159struct ConstraintMatrix
    160{
    161 SCIP_Real* rowmatvals; /**< matrix coefficients row by row */
    162 int* rowmatind; /**< the indices of the corresponding variables */
    163 int* rowmatbegin; /**< the starting indices of each row */
    164 SCIP_Real* colmatvals; /**< matrix coefficients column by column */
    165 int* colmatind; /**< the indices of the corresponding rows for each coefficient */
    166 int* colmatbegin; /**< the starting indices of each column */
    167 int* violrows; /**< the number of violated rows for every variable */
    168 TRANSFORMSTATUS* transformstatus; /**< information about transform status of every discrete variable */
    169 SCIP_Real* lhs; /**< left hand side vector after normalization */
    170 SCIP_Real* rhs; /**< right hand side vector after normalization */
    171 SCIP_Real* colnorms; /**< vector norms of all discrete problem variables after normalization */
    172 SCIP_Real* upperbounds; /**< the upper bounds of every non-continuous variable after transformation*/
    173 SCIP_Real* transformshiftvals; /**< values by which original discrete variable bounds were shifted */
    174 int nnonzs; /**< number of nonzero column entries */
    175 int nrows; /**< number of rows of matrix */
    176 int ncols; /**< the number of columns in matrix (including continuous vars) */
    177 int ndiscvars; /**< number of discrete problem variables */
    178 SCIP_Bool normalized; /**< indicates if the matrix data has already been normalized */
    179};
    180typedef struct ConstraintMatrix CONSTRAINTMATRIX;
    181
    182struct SCIP_EventhdlrData
    183{
    184 CONSTRAINTMATRIX* matrix; /**< the constraint matrix of the heuristic */
    185 SCIP_HEURDATA* heurdata; /**< heuristic data */
    186 int* violatedrows; /**< all currently violated LP rows */
    187 int* violatedrowpos; /**< position in violatedrows array for every row */
    188 int* nviolatedrows; /**< pointer to the total number of currently violated rows */
    189};
    190
    191struct SCIP_EventData
    192{
    193 int colpos; /**< column position of the event-related variable */
    194};
    195/*
    196 * Local methods
    197 */
    198
    199/** returns whether a given variable is counted as discrete, depending on the parameter impliscontinuous */
    200static
    202 SCIP_VAR* var, /**< variable to check for discreteness */
    203 SCIP_Bool impliscontinuous /**< should implicit integer variables be counted as continuous? */
    204 )
    205{
    206 return SCIPvarIsIntegral(var) && ( !impliscontinuous || !SCIPvarIsImpliedIntegral(var) );
    207}
    208
    209/** returns whether a given column is counted as discrete, depending on the parameter impliscontinuous */
    210static
    212 SCIP_COL* col, /**< column to check for discreteness */
    213 SCIP_Bool impliscontinuous /**< should implicit integer variables be counted as continuous? */
    214 )
    215{
    216 return SCIPcolIsIntegral(col) && (!impliscontinuous || !SCIPcolIsImpliedIntegral(col));
    217}
    218
    219/** returns nonzero values and corresponding columns of given row */
    220static
    222 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    223 int rowindex, /**< index of the desired row */
    224 SCIP_Real** valpointer, /**< pointer to store the nonzero coefficients of the row */
    225 SCIP_Real* lhs, /**< lhs of the row */
    226 SCIP_Real* rhs, /**< rhs of the row */
    227 int** indexpointer, /**< pointer to store column indices which belong to the nonzeros */
    228 int* nrowvals /**< pointer to store number of nonzeros in the desired row (or NULL) */
    229 )
    230{
    231 int arrayposition;
    232
    233 assert(matrix != NULL);
    234 assert(0 <= rowindex && rowindex < matrix->nrows);
    235
    236 arrayposition = matrix->rowmatbegin[rowindex];
    237
    238 if ( nrowvals != NULL )
    239 {
    240 if( rowindex == matrix->nrows - 1 )
    241 *nrowvals = matrix->nnonzs - arrayposition;
    242 else
    243 *nrowvals = matrix->rowmatbegin[rowindex + 1] - arrayposition; /*lint !e679*/
    244 }
    245
    246 if( valpointer != NULL )
    247 *valpointer = &(matrix->rowmatvals[arrayposition]);
    248 if( indexpointer != NULL )
    249 *indexpointer = &(matrix->rowmatind[arrayposition]);
    250
    251 if( lhs != NULL )
    252 *lhs = matrix->lhs[rowindex];
    253
    254 if( rhs != NULL )
    255 *rhs = matrix->rhs[rowindex];
    256}
    257
    258/** returns nonzero values and corresponding rows of given column */
    259static
    261 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    262 int colindex, /**< the index of the desired column */
    263 SCIP_Real** valpointer, /**< pointer to store the nonzero coefficients of the column */
    264 int** indexpointer, /**< pointer to store row indices which belong to the nonzeros */
    265 int* ncolvals /**< pointer to store number of nonzeros in the desired column */
    266 )
    267{
    268 int arrayposition;
    269
    270 assert(matrix != NULL);
    271 assert(0 <= colindex && colindex < matrix->ncols);
    272
    273 arrayposition = matrix->colmatbegin[colindex];
    274
    275 if( ncolvals != NULL )
    276 {
    277 if( colindex == matrix->ncols - 1 )
    278 *ncolvals = matrix->nnonzs - arrayposition;
    279 else
    280 *ncolvals = matrix->colmatbegin[colindex + 1] - arrayposition; /*lint !e679*/
    281 }
    282 if( valpointer != NULL )
    283 *valpointer = &(matrix->colmatvals[arrayposition]);
    284
    285 if( indexpointer != NULL )
    286 *indexpointer = &(matrix->colmatind[arrayposition]);
    287}
    288
    289/** relaxes a continuous variable from all its rows, which has influence
    290 * on both the left and right hand side of the constraint.
    291 */
    292static
    294 SCIP* scip, /**< current scip instance */
    295 SCIP_VAR* var, /**< variable which is relaxed from the problem */
    296 CONSTRAINTMATRIX* matrix /**< constraint matrix object */
    297 )
    298{
    299 SCIP_ROW** colrows;
    300 SCIP_COL* varcol;
    301 SCIP_Real* colvals;
    302 SCIP_Real ub;
    303 SCIP_Real lb;
    304 int ncolvals;
    305 int r;
    306
    307 assert(var != NULL);
    309
    310 varcol = SCIPvarGetCol(var);
    311 assert(varcol != NULL);
    312
    313 /* get nonzero values and corresponding rows of variable */
    314 colvals = SCIPcolGetVals(varcol);
    315 ncolvals = SCIPcolGetNLPNonz(varcol);
    316 colrows = SCIPcolGetRows(varcol);
    317
    318 ub = SCIPvarGetUbGlobal(var);
    319 lb = SCIPvarGetLbGlobal(var);
    320
    321 assert(colvals != NULL || ncolvals == 0);
    322
    323 SCIPdebugMsg(scip, "Relaxing variable <%s> with lb <%g> and ub <%g>\n",
    324 SCIPvarGetName(var), lb, ub);
    325
    326 assert(matrix->normalized);
    327 /* relax variable from all its constraints */
    328 for( r = 0; r < ncolvals; ++r )
    329 {
    330 SCIP_ROW* colrow;
    331 SCIP_Real lhs;
    332 SCIP_Real rhs;
    333 SCIP_Real lhsvarbound;
    334 SCIP_Real rhsvarbound;
    335 SCIP_Real colval;
    336 int rowindex;
    337
    338 colrow = colrows[r];
    339 rowindex = SCIProwGetLPPos(colrow);
    340
    341 if( rowindex == -1 )
    342 break;
    343
    344 assert(colvals != NULL); /* to please flexelint */
    345 colval = colvals[r];
    346
    347 assert(0 <= rowindex && rowindex < matrix->nrows);
    348 getRowData(matrix, rowindex, NULL, &lhs, &rhs, NULL, NULL);
    349 /* variables bound influence the lhs and rhs of current row depending on the sign
    350 * of the variables coefficient.
    351 */
    352 if( SCIPisFeasPositive(scip, colval) )
    353 {
    354 lhsvarbound = ub;
    355 rhsvarbound = lb;
    356 }
    357 else if( SCIPisFeasNegative(scip, colval) )
    358 {
    359 lhsvarbound = lb;
    360 rhsvarbound = ub;
    361 }
    362 else
    363 continue;
    364
    365 /* relax variable from the current row */
    366 if( !SCIPisInfinity(scip, -matrix->lhs[rowindex]) && !SCIPisInfinity(scip, ABS(lhsvarbound)) )
    367 matrix->lhs[rowindex] -= colval * lhsvarbound;
    368 else
    369 matrix->lhs[rowindex] = -SCIPinfinity(scip);
    370
    371 if( !SCIPisInfinity(scip, matrix->rhs[rowindex]) && !SCIPisInfinity(scip, ABS(rhsvarbound)) )
    372 matrix->rhs[rowindex] -= colval * rhsvarbound;
    373 else
    374 matrix->rhs[rowindex] = SCIPinfinity(scip);
    375
    376 SCIPdebugMsg(scip, "Row <%s> changed:Coefficient <%g>, LHS <%g> --> <%g>, RHS <%g> --> <%g>\n",
    377 SCIProwGetName(colrow), colval, lhs, matrix->lhs[rowindex], rhs, matrix->rhs[rowindex]);
    378 } /*lint !e438*/
    379}
    380
    381/** transforms bounds of a given variable s.t. its lower bound equals zero afterwards.
    382 * If the variable already has lower bound zero, the variable is not transformed,
    383 * if not, the variable's bounds are changed w.r.t. the smaller absolute value of its
    384 * bounds in order to avoid numerical inaccuracies. If both lower and upper bound
    385 * of the variable differ from infinity, there are two cases. If |lb| <= |ub|,
    386 * the bounds are shifted by -lb, else a new variable ub - x replaces x.
    387 * The transformation is memorized by the transform status of the variable s.t.
    388 * retransformation is possible.
    389 */
    390static
    392 SCIP* scip, /**< current scip instance */
    393 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    394 SCIP_HEURDATA* heurdata, /**< heuristic data */
    395 int colpos /**< position of variable column in matrix */
    396 )
    397{
    398 SCIP_COL* col;
    399 SCIP_VAR* var;
    400 SCIP_Real lb;
    401 SCIP_Real ub;
    402
    403 SCIP_Bool negatecoeffs; /* do the row coefficients need to be negated? */
    404 SCIP_Real deltashift; /* difference from previous transformation */
    405
    406 assert(matrix != NULL);
    407 assert(0 <= colpos && colpos < heurdata->nlpcols);
    408 col = heurdata->lpcols[colpos];
    409 assert(col != NULL);
    410 assert(SCIPcolIsInLP(col));
    411
    412 var = SCIPcolGetVar(col);
    413 assert(var != NULL);
    414 assert(SCIPvarIsIntegral(var));
    415 lb = SCIPvarGetLbLocal(var);
    416 ub = SCIPvarGetUbLocal(var);
    417
    418 negatecoeffs = FALSE;
    419 /* if both lower and upper bound are -infinity and infinity, resp., this is reflected by a free transform status.
    420 * If the lower bound is already zero, this is reflected by identity transform status. In both cases, none of the
    421 * corresponding rows needs to be modified.
    422 */
    423 if( SCIPisInfinity(scip, -lb) && SCIPisInfinity(scip, ub) )
    424 {
    425 if( matrix->transformstatus[colpos] == TRANSFORMSTATUS_NEG )
    426 negatecoeffs = TRUE;
    427
    428 deltashift = matrix->transformshiftvals[colpos];
    429 matrix->transformshiftvals[colpos] = 0.0;
    430 matrix->transformstatus[colpos] = TRANSFORMSTATUS_FREE;
    431 }
    432 else if( SCIPisLE(scip, REALABS(lb), REALABS(ub)) )
    433 {
    434 assert(!SCIPisInfinity(scip, REALABS(lb)));
    435
    436 matrix->transformstatus[colpos] = TRANSFORMSTATUS_LB;
    437 deltashift = lb;
    438 matrix->transformshiftvals[colpos] = lb;
    439 }
    440 else
    441 {
    442 assert(!SCIPisInfinity(scip, ub));
    443 if( matrix->transformstatus[colpos] != TRANSFORMSTATUS_NEG )
    444 negatecoeffs = TRUE;
    445 matrix->transformstatus[colpos] = TRANSFORMSTATUS_NEG;
    446 deltashift = ub;
    447 matrix->transformshiftvals[colpos] = ub;
    448 }
    449
    450 /* determine the upper bound for this variable in heuristic transformation (lower bound is implicit; always 0) */
    451 if( !SCIPisInfinity(scip, ub) && !SCIPisInfinity(scip, lb) )
    452 matrix->upperbounds[colpos] = MIN(ub - lb, SCIPinfinity(scip)); /*lint !e666*/
    453 else
    454 matrix->upperbounds[colpos] = SCIPinfinity(scip);
    455
    456 /* a real transformation is necessary. The variable x is either shifted by -lb or
    457 * replaced by ub - x, depending on the smaller absolute of lb and ub.
    458 */
    459 if( !SCIPisFeasZero(scip, deltashift) || negatecoeffs )
    460 {
    461 SCIP_Real* vals;
    462 int* rows;
    463 int nrows;
    464 int i;
    465
    466 assert(!SCIPisInfinity(scip, deltashift));
    467
    468 /* get nonzero values and corresponding rows of column */
    469 getColumnData(matrix, colpos, &vals, &rows, &nrows);
    470 assert(nrows == 0 ||(vals != NULL && rows != NULL));
    471
    472 /* go through rows and modify its lhs, rhs and the variable coefficient, if necessary */
    473 for( i = 0; i < nrows; ++i )
    474 {
    475 int rowpos = rows[i];
    476 assert(rowpos >= 0);
    477 assert(rowpos < matrix->nrows);
    478
    479 if( !SCIPisInfinity(scip, -(matrix->lhs[rowpos])) )
    480 matrix->lhs[rowpos] -= (vals[i]) * deltashift;
    481
    482 if( !SCIPisInfinity(scip, matrix->rhs[rowpos]) )
    483 matrix->rhs[rowpos] -= (vals[i]) * deltashift;
    484
    485 if( negatecoeffs )
    486 (vals[i]) = -(vals[i]);
    487
    488 assert(SCIPisFeasLE(scip, matrix->lhs[rowpos], matrix->rhs[rowpos]));
    489 }
    490 }
    491 SCIPdebugMsg(scip, "Variable <%s> at colpos %d transformed. Status %d LB <%g> --> <%g>, UB <%g> --> <%g>\n",
    492 SCIPvarGetName(var), colpos, matrix->transformstatus[colpos], lb, 0.0, ub, matrix->upperbounds[colpos]);
    493}
    494
    495/** initializes copy of the original coefficient matrix and applies heuristic specific adjustments: normalizing row
    496 * vectors, transforming variable domains such that lower bound is zero, and relaxing continuous variables.
    497 */
    498static
    500 SCIP* scip, /**< current scip instance */
    501 CONSTRAINTMATRIX* matrix, /**< constraint matrix object to be initialized */
    502 SCIP_HEURDATA* heurdata, /**< heuristic data */
    503 int* colposs, /**< position of columns according to variable type sorting */
    504 int* nmaxrows, /**< maximum number of rows a variable appears in */
    505 SCIP_Bool relax, /**< should continuous variables be relaxed from the problem? */
    506 SCIP_Bool* initialized, /**< was the initialization successful? */
    507 SCIP_Bool* infeasible /**< is the problem infeasible? */
    508 )
    509{
    510 SCIP_ROW** lprows;
    511 SCIP_COL** lpcols;
    512 SCIP_Bool impliscontinuous;
    513 int i;
    514 int j;
    515 int currentpointer;
    516
    517 int nrows;
    518 int ncols;
    519
    520 assert(scip != NULL);
    521 assert(matrix != NULL);
    522 assert(initialized!= NULL);
    523 assert(infeasible != NULL);
    524 assert(nmaxrows != NULL);
    525
    526 SCIPdebugMsg(scip, "entering Matrix Initialization method of SHIFTANDPROPAGATE heuristic!\n");
    527
    528 /* get LP row data; column data is already initialized in heurdata */
    529 SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nrows) );
    530 lpcols = heurdata->lpcols;
    531 ncols = heurdata->nlpcols;
    532
    533 matrix->nrows = nrows;
    534 matrix->nnonzs = 0;
    535 matrix->normalized = FALSE;
    536 matrix->ndiscvars = 0;
    537 *nmaxrows = 0;
    538 impliscontinuous = heurdata->impliscontinuous;
    539
    540 /* count the number of nonzeros of the LP constraint matrix */
    541 for( j = 0; j < ncols; ++j )
    542 {
    543 assert(lpcols[j] != NULL);
    544 assert(SCIPcolGetLPPos(lpcols[j]) >= 0);
    545
    546 if( colIsDiscrete(lpcols[j], impliscontinuous) )
    547 {
    548 matrix->nnonzs += SCIPcolGetNLPNonz(lpcols[j]);
    549 ++matrix->ndiscvars;
    550 }
    551 }
    552
    553 matrix->ncols = matrix->ndiscvars;
    554
    555 if( matrix->nnonzs == 0 )
    556 {
    557 SCIPdebugMsg(scip, "No matrix entries - Terminating initialization of matrix.\n");
    558
    559 *initialized = FALSE;
    560
    561 return SCIP_OKAY;
    562 }
    563
    564 /* allocate memory for the members of heuristic matrix */
    565 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rowmatvals, matrix->nnonzs) );
    566 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rowmatind, matrix->nnonzs) );
    567 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colmatvals, matrix->nnonzs) );
    568 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colmatind, matrix->nnonzs) );
    569 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rowmatbegin, matrix->nrows) );
    570 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colmatbegin, matrix->ncols) );
    571 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->lhs, matrix->nrows) );
    572 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->rhs, matrix->nrows) );
    573 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->colnorms, matrix->ncols) );
    574 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->violrows, matrix->ncols) );
    575 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->transformstatus, matrix->ndiscvars) );
    576 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->upperbounds, matrix->ndiscvars) );
    577 SCIP_CALL( SCIPallocBufferArray(scip, &matrix->transformshiftvals, matrix->ndiscvars) );
    578
    579 /* set transform status of variables */
    580 for( j = 0; j < matrix->ndiscvars; ++j )
    581 matrix->transformstatus[j] = TRANSFORMSTATUS_NONE;
    582
    583 currentpointer = 0;
    584 *infeasible = FALSE;
    585
    586 /* initialize the rows vector of the heuristic matrix together with its corresponding
    587 * lhs, rhs.
    588 */
    589 for( i = 0; i < nrows; ++i )
    590 {
    591 SCIP_COL** cols;
    592 SCIP_ROW* row;
    593 SCIP_Real* rowvals;
    594 SCIP_Real constant;
    595 int nrowlpnonz;
    596
    597 /* get LP row information */
    598 row = lprows[i];
    599 rowvals = SCIProwGetVals(row);
    600 nrowlpnonz = SCIProwGetNLPNonz(row);
    601 cols = SCIProwGetCols(row);
    602 constant = SCIProwGetConstant(row);
    603
    605 assert(!SCIPisInfinity(scip, constant));
    606
    607 matrix->rowmatbegin[i] = currentpointer;
    608
    609 /* modify the lhs and rhs w.r.t to the rows constant */
    610 if( !SCIPisInfinity(scip, -SCIProwGetLhs(row)) )
    611 matrix->lhs[i] = SCIProwGetLhs(row) - constant;
    612 else
    613 matrix->lhs[i] = -SCIPinfinity(scip);
    614
    615 if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) )
    616 matrix->rhs[i] = SCIProwGetRhs(row) - constant;
    617 else
    618 matrix->rhs[i] = SCIPinfinity(scip);
    619
    620 /* in case of empty rows with a 0 < lhs <= 0.0 or 0.0 <= rhs < 0 we deduce the infeasibility of the problem */
    621 if( nrowlpnonz == 0 && (SCIPisFeasPositive(scip, matrix->lhs[i]) || SCIPisFeasNegative(scip, matrix->rhs[i])) )
    622 {
    623 *infeasible = TRUE;
    624 SCIPdebugMsg(scip, " Matrix initialization stopped because of row infeasibility! \n");
    625 break;
    626 }
    627
    628 /* row coefficients are normalized and copied to heuristic matrix */
    629 for( j = 0; j < nrowlpnonz; ++j )
    630 {
    631 if( !colIsDiscrete(cols[j], impliscontinuous) )
    632 continue;
    633 assert(SCIPcolGetLPPos(cols[j]) >= 0);
    634 assert(currentpointer < matrix->nnonzs);
    635
    636 matrix->rowmatvals[currentpointer] = rowvals[j];
    637 matrix->rowmatind[currentpointer] = colposs[SCIPcolGetLPPos(cols[j])];
    638
    639 ++currentpointer;
    640 }
    641 }
    642
    643 matrix->normalized = TRUE;
    644
    645 if( *infeasible )
    646 return SCIP_OKAY;
    647
    648 assert(currentpointer == matrix->nnonzs);
    649
    650 currentpointer = 0;
    651
    652 /* copy the nonzero coefficient data column by column to heuristic matrix */
    653 for( j = 0; j < matrix->ncols; ++j )
    654 {
    655 SCIP_COL* currentcol;
    656 SCIP_ROW** rows;
    657 SCIP_Real* colvals;
    658 int ncolnonz;
    659
    660 assert(SCIPcolGetLPPos(lpcols[j]) >= 0);
    661
    662 currentcol = lpcols[j];
    663 assert(colIsDiscrete(currentcol, impliscontinuous));
    664
    665 colvals = SCIPcolGetVals(currentcol);
    666 rows = SCIPcolGetRows(currentcol);
    667 ncolnonz = SCIPcolGetNLPNonz(currentcol);
    668 matrix->colnorms[j] = ncolnonz;
    669
    670 *nmaxrows = MAX(*nmaxrows, ncolnonz);
    671
    672 /* loop over all rows with nonzero coefficients in the column, transform them and add them to the heuristic matrix */
    673 matrix->colmatbegin[j] = currentpointer;
    674
    675 for( i = 0; i < ncolnonz; ++i )
    676 {
    677 SCIP_Real normval = colvals[i];
    678
    679 assert(rows[i] != NULL);
    680 assert(0 <= SCIProwGetLPPos(rows[i]));
    681 assert(SCIProwGetLPPos(rows[i]) < nrows);
    682 assert(currentpointer < matrix->nnonzs);
    683 matrix->colmatvals[currentpointer] = colvals[i];
    684 matrix->colmatind[currentpointer] = SCIProwGetLPPos(rows[i]);
    685
    686 if( heurdata->normalize )
    687 normval /= SCIPgetRowMaxCoef(scip, rows[i]);
    688
    689 /* update the column norm for maximum normalized rows */
    690 matrix->colnorms[j] += ABS(normval);
    691 ++currentpointer;
    692 }
    693 }
    694 assert(currentpointer == matrix->nnonzs);
    695
    696 /* each variable is either transformed, if it supposed to be integral, or relaxed */
    697 for( j = 0; j < (relax ? ncols : matrix->ndiscvars); ++j )
    698 {
    699 SCIP_COL* col;
    700
    701 col = lpcols[j];
    702 if( colIsDiscrete(col, impliscontinuous) )
    703 {
    704 matrix->transformshiftvals[j] = 0.0;
    705 transformVariable(scip, matrix, heurdata, j);
    706 }
    707 else
    708 {
    709 SCIP_VAR* var;
    710 var = SCIPcolGetVar(col);
    711 assert(!varIsDiscrete(var, impliscontinuous));
    712 relaxVar(scip, var, matrix);
    713 }
    714 }
    715 *initialized = TRUE;
    716
    717 SCIPdebugMsg(scip, "Matrix initialized for %d discrete variables with %d cols, %d rows and %d nonzero entries\n",
    718 matrix->ndiscvars, matrix->ncols, matrix->nrows, matrix->nnonzs);
    719 return SCIP_OKAY;
    720}
    721
    722/** frees all members of the heuristic matrix */
    723static
    725 SCIP* scip, /**< current SCIP instance */
    726 CONSTRAINTMATRIX** matrix /**< constraint matrix object */
    727 )
    728{
    729 assert(scip != NULL);
    730 assert(matrix != NULL);
    731
    732 /* all fields are only allocated, if problem is not empty */
    733 if( (*matrix)->nnonzs > 0 )
    734 {
    735 assert((*matrix) != NULL);
    736 assert((*matrix)->rowmatbegin != NULL);
    737 assert((*matrix)->rowmatvals != NULL);
    738 assert((*matrix)->rowmatind != NULL);
    739 assert((*matrix)->colmatbegin != NULL);
    740 assert((*matrix)->colmatvals!= NULL);
    741 assert((*matrix)->colmatind != NULL);
    742 assert((*matrix)->lhs != NULL);
    743 assert((*matrix)->rhs != NULL);
    744 assert((*matrix)->transformstatus != NULL);
    745 assert((*matrix)->transformshiftvals != NULL);
    746
    747 /* free all fields */
    748 SCIPfreeBufferArray(scip, &((*matrix)->transformshiftvals));
    749 SCIPfreeBufferArray(scip, &((*matrix)->upperbounds));
    750 SCIPfreeBufferArray(scip, &((*matrix)->transformstatus));
    751 SCIPfreeBufferArray(scip, &((*matrix)->violrows));
    752 SCIPfreeBufferArray(scip, &((*matrix)->colnorms));
    753 SCIPfreeBufferArray(scip, &((*matrix)->rhs));
    754 SCIPfreeBufferArray(scip, &((*matrix)->lhs));
    755 SCIPfreeBufferArray(scip, &((*matrix)->colmatbegin));
    756 SCIPfreeBufferArray(scip, &((*matrix)->rowmatbegin));
    757 SCIPfreeBufferArray(scip, &((*matrix)->colmatind));
    758 SCIPfreeBufferArray(scip, &((*matrix)->colmatvals));
    759 SCIPfreeBufferArray(scip, &((*matrix)->rowmatind));
    760 SCIPfreeBufferArray(scip, &((*matrix)->rowmatvals));
    761
    762 (*matrix)->nrows = 0;
    763 (*matrix)->ncols = 0;
    764 }
    765
    766 /* free matrix */
    767 SCIPfreeBuffer(scip, matrix);
    768}
    769
    770/** updates the information about a row whenever violation status changes */
    771static
    773 SCIP* scip, /**< current SCIP instance */
    774 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    775 int rowindex, /**< index of the row */
    776 int* violatedrows, /**< contains all violated rows */
    777 int* violatedrowpos, /**< positions of rows in the violatedrows array */
    778 int* nviolatedrows, /**< pointer to update total number of violated rows */
    779 int* rowweights, /**< row weight storage */
    780 SCIP_Bool updateweights /**< should row weight be increased every time the row is violated? */
    781 )
    782{
    783 int* cols;
    784 int ncols;
    785 int c;
    786 int violadd;
    787 assert(matrix != NULL);
    788 assert(violatedrows != NULL);
    789 assert(violatedrowpos != NULL);
    790 assert(nviolatedrows != NULL);
    791
    792 getRowData(matrix, rowindex, NULL, NULL, NULL, &cols, &ncols);
    793 violadd = 0;
    794
    795 /* row is now violated. Enqueue it in the set of violated rows. */
    796 if( violatedrowpos[rowindex] == -1 && (SCIPisFeasGT(scip, matrix->lhs[rowindex], 0.0) || SCIPisFeasLT(scip, matrix->rhs[rowindex], 0.0)) )
    797 {
    798 assert(*nviolatedrows < matrix->nrows);
    799
    800 violatedrows[*nviolatedrows] = rowindex;
    801 violatedrowpos[rowindex] = *nviolatedrows;
    802 ++(*nviolatedrows);
    803 if( updateweights )
    804 ++rowweights[rowindex];
    805
    806 violadd = 1;
    807 }
    808 /* row is now feasible. Remove it from the set of violated rows. */
    809 else if( violatedrowpos[rowindex] >= 0 && SCIPisFeasLE(scip, matrix->lhs[rowindex], 0.0) && SCIPisFeasGE(scip, matrix->rhs[rowindex], 0.0) )
    810 {
    811 /* swap the row with last violated row */
    812 if( violatedrowpos[rowindex] != *nviolatedrows - 1 )
    813 {
    814 assert(*nviolatedrows - 1 >= 0);
    815 violatedrows[violatedrowpos[rowindex]] = violatedrows[*nviolatedrows - 1];
    816 violatedrowpos[violatedrows[*nviolatedrows - 1]] = violatedrowpos[rowindex];
    817 }
    818
    819 /* unlink the row from its position in the array and decrease number of violated rows */
    820 violatedrowpos[rowindex] = -1;
    821 --(*nviolatedrows);
    822 violadd = -1;
    823 }
    824
    825 /* increase or decrease the column violation counter */
    826 for( c = 0; c < ncols; ++c )
    827 {
    828 matrix->violrows[cols[c]] += violadd;
    829 assert(matrix->violrows[cols[c]] >= 0);
    830 }
    831}
    832
    833/** collects the necessary information about row violations for the zero-solution. That is,
    834 * all solution values in heuristic transformation are zero.
    835 */
    836static
    838 SCIP* scip, /**< current scip instance */
    839 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    840 int colidx, /**< column index for specific column, or -1 for all rows */
    841 int* violatedrows, /**< violated rows */
    842 int* violatedrowpos, /**< row positions of violated rows */
    843 int* nviolatedrows, /**< pointer to store the number of violated rows */
    844 int* rowweights, /**< weight array for every row */
    845 SCIP_Bool updateweights /**< should row weight be increased every time the row is violated? */
    846 )
    847{
    848 int nrows;
    849 int* rowindices;
    850 int i;
    851
    852 assert(matrix != NULL);
    853 assert(violatedrows != NULL);
    854 assert(violatedrowpos != NULL);
    855 assert(nviolatedrows != NULL);
    856 assert(-1 <= colidx && colidx < matrix->ncols);
    857
    858 /* check if we requested an update for a single variable, or if we want to (re)-initialize the whole violation info */
    859 if( colidx >= 0 )
    860 getColumnData(matrix, colidx, NULL, &rowindices, &nrows);
    861 else
    862 {
    863 nrows = matrix->nrows;
    864 rowindices = NULL;
    865 *nviolatedrows = 0;
    866
    867 /* reinitialize the violated rows */
    868 for( i = 0; i < nrows; ++i )
    869 violatedrowpos[i] = -1;
    870
    871 /* clear the violated row counters for all variables */
    872 BMSclearMemoryArray(matrix->violrows, matrix->ndiscvars);
    873 }
    874
    875 assert(colidx < 0 || *nviolatedrows >= 0);
    876 SCIPdebugMsg(scip, "Entering violation check for %d rows! \n", nrows);
    877 /* loop over rows and check if it is violated */
    878 for( i = 0; i < nrows; ++i )
    879 {
    880 int rowpos;
    881 if( colidx >= 0 )
    882 {
    883 assert(rowindices != NULL);
    884 rowpos = rowindices[i];
    885 }
    886 else
    887 rowpos = i;
    888 /* check, if zero solution violates this row */
    889 checkRowViolation(scip, matrix, rowpos, violatedrows, violatedrowpos, nviolatedrows, rowweights, updateweights);
    890
    891 assert((violatedrowpos[rowpos] == -1 && SCIPisFeasGE(scip, matrix->rhs[rowpos], 0.0) && SCIPisFeasLE(scip, matrix->lhs[rowpos], 0.0))
    892 || (violatedrowpos[rowpos] >= 0 &&(SCIPisFeasLT(scip, matrix->rhs[rowpos], 0.0) || SCIPisFeasGT(scip, matrix->lhs[rowpos], 0.0))));
    893 }
    894}
    895
    896/** retransforms solution values of variables according to their transformation status */
    897static
    899 SCIP* scip, /**< current scip instance */
    900 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    901 SCIP_VAR* var, /**< variable whose solution value has to be retransformed */
    902 int varindex, /**< permutation of variable indices according to sorting */
    903 SCIP_Real solvalue /**< solution value of the variable */
    904 )
    905{
    906 TRANSFORMSTATUS status;
    907
    908 assert(matrix != NULL);
    909 assert(var != NULL);
    910
    911 status = matrix->transformstatus[varindex];
    912 assert(status != TRANSFORMSTATUS_NONE);
    913
    914 /* check if original variable has different bounds and transform solution value correspondingly */
    915 if( status == TRANSFORMSTATUS_LB )
    916 {
    917 assert(!SCIPisInfinity(scip, -SCIPvarGetLbLocal(var)));
    918
    919 return solvalue + matrix->transformshiftvals[varindex];
    920 }
    921 else if( status == TRANSFORMSTATUS_NEG )
    922 {
    923 assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
    924 return matrix->transformshiftvals[varindex] - solvalue;
    925 }
    926 return solvalue;
    927}
    928
    929/** determines the best shifting value of a variable
    930 * @todo if there is already an incumbent solution, try considering the objective cutoff as additional constraint */
    931static
    933 SCIP* scip, /**< current scip instance */
    934 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    935 int varindex, /**< index of variable which should be shifted */
    936 int direction, /**< the direction for this variable */
    937 int* rowweights, /**< weighting of rows for best shift calculation */
    938 SCIP_Real* steps, /**< buffer array to store the individual steps for individual rows */
    939 int* violationchange, /**< buffer array to store the individual change of feasibility of row */
    940 SCIP_Real* beststep, /**< pointer to store optimal shifting step */
    941 int* rowviolations /**< pointer to store new weighted sum of row violations, i.e, v - f */
    942 )
    943{
    944 SCIP_Real* vals;
    945 int* rows;
    946
    947 SCIP_Real slacksurplus;
    948 SCIP_Real upperbound;
    949
    950 int nrows;
    951 int sum;
    952 int i;
    953
    954 SCIP_Bool allzero;
    955
    956 assert(beststep != NULL);
    957 assert(rowviolations != NULL);
    958 assert(rowweights != NULL);
    959 assert(steps != NULL);
    960 assert(violationchange != NULL);
    961 assert(direction == 1 || direction == -1);
    962
    963 upperbound = matrix->upperbounds[varindex];
    964
    965 /* get nonzero values and corresponding rows of variable */
    966 getColumnData(matrix, varindex, &vals, &rows, &nrows);
    967
    968 /* loop over rows and calculate, which is the minimum shift to make this row feasible
    969 * or the minimum shift to violate this row
    970 */
    971 allzero = TRUE;
    972 slacksurplus = 0.0;
    973 for( i = 0; i < nrows; ++i )
    974 {
    975 SCIP_Real lhs;
    976 SCIP_Real rhs;
    977 SCIP_Real val;
    978 int rowpos;
    979 SCIP_Bool rowisviolated;
    980 int rowweight;
    981
    982 /* get the row data */
    983 rowpos = rows[i];
    984 assert(rowpos >= 0);
    985 lhs = matrix->lhs[rowpos];
    986 rhs = matrix->rhs[rowpos];
    987 rowweight = rowweights[rowpos];
    988 val = direction * vals[i];
    989 assert(!SCIPisZero(scip, val));
    990
    991 /* determine if current row is violated or not */
    992 rowisviolated = (SCIPisFeasLT(scip, rhs, 0.0) || SCIPisFeasLT(scip, -lhs, 0.0));
    993
    994 /* for a feasible row, determine the minimum integer value within the bounds of the variable by which it has to be
    995 * shifted to make row infeasible.
    996 */
    997 if( !rowisviolated )
    998 {
    999 SCIP_Real maxfeasshift;
    1000
    1001 maxfeasshift = SCIPinfinity(scip);
    1002
    1003 /* feasibility can only be violated if the variable has a lock in the corresponding direction,
    1004 * i.e. a positive coefficient for a "<="-constraint, a negative coefficient for a ">="-constraint.
    1005 * if the variable has no lock in the current row, it can still help to increase the slack of this row;
    1006 * we measure slack increase for shifting by one
    1007 */
    1008 if( val < 0.0 )
    1009 {
    1010 if( !SCIPisInfinity(scip, -lhs) )
    1011 maxfeasshift = SCIPfeasFloor(scip, MIN(lhs, 0.0) / val);
    1012 else
    1013 slacksurplus -= val;
    1014 }
    1015 else
    1016 {
    1017 if( !SCIPisInfinity(scip, rhs) )
    1018 maxfeasshift = SCIPfeasFloor(scip, MAX(rhs, 0.0) / val);
    1019 else
    1020 slacksurplus += val;
    1021 }
    1022
    1023 /* check if the least violating shift lies within variable bounds and set corresponding array values */
    1024 if( !SCIPisInfinity(scip, maxfeasshift) && SCIPisFeasLE(scip, maxfeasshift + 1.0, upperbound) )
    1025 {
    1026 steps[i] = maxfeasshift + 1.0;
    1027 violationchange[i] = rowweight;
    1028 allzero = FALSE;
    1029 }
    1030 else
    1031 {
    1032 steps[i] = upperbound;
    1033 violationchange[i] = 0;
    1034 }
    1035 }
    1036 /* for a violated row, determine the minimum integral value within the bounds of the variable by which it has to be
    1037 * shifted to make row feasible.
    1038 */
    1039 else
    1040 {
    1041 SCIP_Real minfeasshift;
    1042
    1043 minfeasshift = SCIPinfinity(scip);
    1044
    1045 /* if coefficient has the right sign to make row feasible, determine the minimum integer to shift variable
    1046 * to obtain feasibility
    1047 */
    1048 if( val < 0.0 )
    1049 {
    1050 if( SCIPisFeasLT(scip, rhs, 0.0) )
    1051 minfeasshift = SCIPfeasCeil(scip, MIN(rhs, val) / val);
    1052 }
    1053 else
    1054 {
    1055 if( SCIPisFeasLT(scip, -lhs, 0.0) )
    1056 minfeasshift = SCIPfeasCeil(scip, MAX(lhs, val) / val);
    1057 }
    1058
    1059 /* check if the minimum feasibility recovery shift lies within variable bounds and set corresponding array
    1060 * values
    1061 */
    1062 if( !SCIPisInfinity(scip, minfeasshift) && SCIPisFeasLE(scip, minfeasshift, upperbound) )
    1063 {
    1064 steps[i] = minfeasshift;
    1065 violationchange[i] = -rowweight;
    1066 allzero = FALSE;
    1067 }
    1068 else
    1069 {
    1070 steps[i] = upperbound;
    1071 violationchange[i] = 0;
    1072 }
    1073 }
    1074 }
    1075
    1076 /* in case that the variable cannot affect the feasibility of any row, in particular it cannot violate
    1077 * a single row, but we can add slack to already feasible rows, we will do this
    1078 */
    1079 if( allzero )
    1080 {
    1081 if( ! SCIPisInfinity(scip, upperbound) && SCIPisGT(scip, slacksurplus, 0.0) )
    1082 *beststep = direction * upperbound;
    1083 else
    1084 *beststep = 0.0;
    1085
    1086 return SCIP_OKAY;
    1087 }
    1088
    1089 /* sorts rows by increasing value of steps */
    1090 SCIPsortRealInt(steps, violationchange, nrows);
    1091
    1092 *beststep = 0.0;
    1093 *rowviolations = 0;
    1094 sum = 0;
    1095
    1096 /* best shifting step is calculated by summing up the violation changes for each relevant step and
    1097 * taking the one which leads to the minimum sum. This sum measures the balance of feasibility recovering and
    1098 * violating changes which will be obtained by shifting the variable by this step
    1099 * note, the sums for smaller steps have to be taken into account for all bigger steps, i.e., the sums can be
    1100 * computed iteratively
    1101 */
    1102 for( i = 0; i < nrows && !SCIPisInfinity(scip, steps[i]); ++i )
    1103 {
    1104 sum += violationchange[i];
    1105
    1106 /* if we reached the last entry for the current step value, we have finished computing its sum and
    1107 * update the step defining the minimum sum
    1108 */
    1109 if( (i == nrows-1 || steps[i+1] > steps[i]) && sum < *rowviolations ) /*lint !e679*/
    1110 {
    1111 *rowviolations = sum;
    1112 *beststep = direction * steps[i];
    1113 }
    1114 }
    1115 assert(*rowviolations <= 0);
    1116 assert(!SCIPisInfinity(scip, *beststep));
    1117
    1118 return SCIP_OKAY;
    1119}
    1120
    1121/** updates transformation of a given variable by taking into account current local bounds. if the bounds have changed
    1122 * since last update, updating the heuristic specific upper bound of the variable, its current transformed solution value
    1123 * and all affected rows is necessary.
    1124 */
    1125static
    1127 SCIP* scip, /**< current scip */
    1128 CONSTRAINTMATRIX* matrix, /**< constraint matrix object */
    1129 SCIP_HEURDATA* heurdata, /**< heuristic data */
    1130 int varindex, /**< index of variable in matrix */
    1131 SCIP_Real lb, /**< local lower bound of the variable */
    1132 SCIP_Real ub, /**< local upper bound of the variable */
    1133 int* violatedrows, /**< violated rows */
    1134 int* violatedrowpos, /**< violated row positions */
    1135 int* nviolatedrows /**< pointer to store number of violated rows */
    1136 )
    1137{
    1138 TRANSFORMSTATUS status;
    1139 SCIP_Real deltashift;
    1140 SCIP_Bool checkviolations;
    1141
    1142 assert(scip != NULL);
    1143 assert(matrix != NULL);
    1144 assert(0 <= varindex && varindex < matrix->ndiscvars);
    1145
    1146 /* deltashift is the difference between the old and new transformation value. */
    1147 deltashift = 0.0;
    1148 status = matrix->transformstatus[varindex];
    1149
    1150 SCIPdebugMsg(scip, " Variable <%d> [%g,%g], status %d(%g), ub %g \n", varindex, lb, ub, status,
    1151 matrix->transformshiftvals[varindex], matrix->upperbounds[varindex]);
    1152
    1153 checkviolations = FALSE;
    1154 /* depending on the variable status, deltashift is calculated differently. */
    1155 switch( status )
    1156 {
    1157 case TRANSFORMSTATUS_LB:
    1158 if( SCIPisInfinity(scip, -lb) )
    1159 {
    1160 transformVariable(scip, matrix, heurdata, varindex);
    1161 checkviolations = TRUE;
    1162 }
    1163 else
    1164 {
    1165 deltashift = lb - (matrix->transformshiftvals[varindex]);
    1166 matrix->transformshiftvals[varindex] = lb;
    1167 if( !SCIPisInfinity(scip, ub) )
    1168 matrix->upperbounds[varindex] = ub - lb;
    1169 else
    1170 matrix->upperbounds[varindex] = SCIPinfinity(scip);
    1171 }
    1172 break;
    1174 if( SCIPisInfinity(scip, ub) )
    1175 {
    1176 transformVariable(scip, matrix, heurdata, varindex);
    1177 checkviolations = TRUE;
    1178 }
    1179 else
    1180 {
    1181 deltashift = (matrix->transformshiftvals[varindex]) - ub;
    1182 matrix->transformshiftvals[varindex] = ub;
    1183
    1184 if( !SCIPisInfinity(scip, -lb) )
    1185 matrix->upperbounds[varindex] = MIN(ub - lb, SCIPinfinity(scip)); /*lint !e666*/
    1186 else
    1187 matrix->upperbounds[varindex] = SCIPinfinity(scip);
    1188 }
    1189 break;
    1191 /* in case of a free transform status, if one of the bounds has become finite, we want
    1192 * to transform this variable to a variable with a lowerbound or a negated transform status */
    1193 if( !SCIPisInfinity(scip, -lb) || !SCIPisInfinity(scip, ub) )
    1194 {
    1195 transformVariable(scip, matrix, heurdata, varindex);
    1196
    1197 /* violations have to be rechecked for rows in which variable appears */
    1198 checkviolations = TRUE;
    1199
    1200 assert(matrix->transformstatus[varindex] == TRANSFORMSTATUS_LB || matrix->transformstatus[varindex] == TRANSFORMSTATUS_NEG);
    1201 assert(SCIPisLE(scip, ABS(lb), ABS(ub)) || matrix->transformstatus[varindex] == TRANSFORMSTATUS_NEG);
    1202 }
    1203 break;
    1204
    1206 default:
    1207 SCIPerrorMessage("Error: Invalid variable status <%d> in shift and propagagate heuristic, aborting!\n", status);
    1208 SCIPABORT();
    1209 return SCIP_INVALIDDATA; /*lint !e527*/
    1210 }
    1211 /* if the bound, by which the variable was shifted, has changed, deltashift is different from zero, which requires
    1212 * an update of all affected rows
    1213 */
    1214 if( !SCIPisFeasZero(scip, deltashift) )
    1215 {
    1216 int i;
    1217 int* rows;
    1218 SCIP_Real* vals;
    1219 int nrows;
    1220
    1221 /* get nonzero values and corresponding rows of variable */
    1222 getColumnData(matrix, varindex, &vals, &rows, &nrows);
    1223
    1224 /* go through rows, update the rows w.r.t. the influence of the changed transformation of the variable */
    1225 for( i = 0; i < nrows; ++i )
    1226 {
    1227 SCIPdebugMsg(scip, " update slacks of row<%d>: coefficient <%g>, %g <= 0 <= %g \n",
    1228 rows[i], vals[i], matrix->lhs[rows[i]], matrix->rhs[rows[i]]);
    1229
    1230 if( !SCIPisInfinity(scip, -(matrix->lhs[rows[i]])) )
    1231 matrix->lhs[rows[i]] -= (vals[i]) * deltashift;
    1232
    1233 if( !SCIPisInfinity(scip, matrix->rhs[rows[i]]) )
    1234 matrix->rhs[rows[i]] -= (vals[i]) * deltashift;
    1235 }
    1236 checkviolations = TRUE;
    1237 }
    1238
    1239 /* check and update information about violated rows, if necessary */
    1240 if( checkviolations )
    1241 checkViolations(scip, matrix, varindex, violatedrows, violatedrowpos, nviolatedrows, heurdata->rowweights, heurdata->updateweights);
    1242
    1243 SCIPdebugMsg(scip, " Variable <%d> [%g,%g], status %d(%g), ub %g \n", varindex, lb, ub, status,
    1244 matrix->transformshiftvals[varindex], matrix->upperbounds[varindex]);
    1245
    1246 return SCIP_OKAY;
    1247}
    1248
    1249/** comparison method for columns; binary < integer < implicit < continuous variables */
    1250static
    1251SCIP_DECL_SORTPTRCOMP(heurSortColsShiftandpropagate)
    1252{
    1253 SCIP_COL* col1;
    1254 SCIP_COL* col2;
    1255 SCIP_VAR* var1;
    1256 SCIP_VAR* var2;
    1257 SCIP_VARTYPE vartype1;
    1258 SCIP_VARTYPE vartype2;
    1259
    1260 col1 = (SCIP_COL*)elem1;
    1261 col2 = (SCIP_COL*)elem2;
    1262 var1 = SCIPcolGetVar(col1);
    1263 var2 = SCIPcolGetVar(col2);
    1264 assert(var1 != NULL);
    1265 assert(var2 != NULL);
    1266
    1269
    1270 if( vartype1 < vartype2 )
    1271 return -1;
    1272 if( vartype1 > vartype2 )
    1273 return +1;
    1274
    1275 assert(vartype1 == vartype2);
    1276 return 0;
    1277}
    1278
    1279/*
    1280 * Callback methods of primal heuristic
    1281 */
    1282
    1283/** deinitialization method of primal heuristic(called before transformed problem is freed) */
    1284static
    1285SCIP_DECL_HEUREXIT(heurExitShiftandpropagate)
    1286{ /*lint --e{715}*/
    1287 SCIP_HEURDATA* heurdata;
    1288
    1289 heurdata = SCIPheurGetData(heur);
    1290 assert(heurdata != NULL);
    1291
    1292 /* free random number generator */
    1293 SCIPfreeRandom(scip, &heurdata->randnumgen);
    1294
    1295 /* if statistic mode is enabled, statistics are printed to console */
    1298 " DETAILS : %d violations left, %d probing status\n",
    1299 heurdata->nremainingviols,
    1300 heurdata->lpsolstat
    1301 );
    1303 " SHIFTANDPROPAGATE PROBING : %d probings, %" SCIP_LONGINT_FORMAT " domain reductions, ncutoffs: %d , LP iterations: %" SCIP_LONGINT_FORMAT " \n ",
    1304 heurdata->nprobings,
    1305 heurdata->ntotaldomredsfound,
    1306 heurdata->ncutoffs,
    1307 heurdata->nlpiters);
    1308 );
    1309
    1310 return SCIP_OKAY;
    1311}
    1312
    1313/** initialization method of primal heuristic(called after problem was transformed). We only need this method for
    1314 * statistic mode of heuristic.
    1315 */
    1316static
    1317SCIP_DECL_HEURINIT(heurInitShiftandpropagate)
    1318{ /*lint --e{715}*/
    1319 SCIP_HEURDATA* heurdata;
    1320
    1321 heurdata = SCIPheurGetData(heur);
    1322
    1323 assert(heurdata != NULL);
    1324
    1325 /* create random number generator */
    1326 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
    1328
    1330 heurdata->lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
    1331 heurdata->nremainingviols = 0;
    1332 heurdata->nprobings = 0;
    1333 heurdata->ntotaldomredsfound = 0;
    1334 heurdata->ncutoffs = 0;
    1335 heurdata->nlpiters = 0;
    1336 )
    1337 return SCIP_OKAY;
    1338}
    1339
    1340/** destructor of primal heuristic to free user data(called when SCIP is exiting) */
    1341static
    1342SCIP_DECL_HEURFREE(heurFreeShiftandpropagate)
    1343{ /*lint --e{715}*/
    1344 SCIP_HEURDATA* heurdata;
    1345 SCIP_EVENTHDLR* eventhdlr;
    1346 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1347
    1348 heurdata = SCIPheurGetData(heur);
    1349 assert(heurdata != NULL);
    1350 eventhdlr = heurdata->eventhdlr;
    1351 assert(eventhdlr != NULL);
    1352 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1353
    1354 SCIPfreeBlockMemoryNull(scip, &eventhdlrdata);
    1355
    1356 /* free heuristic data */
    1357 SCIPfreeBlockMemory(scip, &heurdata);
    1358
    1359 SCIPheurSetData(heur, NULL);
    1360
    1361 return SCIP_OKAY;
    1362}
    1363
    1364
    1365/** copy method for primal heuristic plugins(called when SCIP copies plugins) */
    1366static
    1367SCIP_DECL_HEURCOPY(heurCopyShiftandpropagate)
    1368{ /*lint --e{715}*/
    1369 assert(scip != NULL);
    1370 assert(heur != NULL);
    1371
    1373
    1374 /* call inclusion method of primal heuristic */
    1376
    1377 return SCIP_OKAY;
    1378}
    1379
    1380/** execution method of primal heuristic */
    1381static
    1382SCIP_DECL_HEUREXEC(heurExecShiftandpropagate)
    1383{ /*lint --e{715}*/
    1384 SCIP_HEURDATA* heurdata; /* heuristic data */
    1385 SCIP_EVENTHDLR* eventhdlr; /* shiftandpropagate event handler */
    1386 SCIP_EVENTHDLRDATA* eventhdlrdata; /* event handler data */
    1387 SCIP_EVENTDATA** eventdatas; /* event data for every variable */
    1388
    1389 CONSTRAINTMATRIX* matrix; /* constraint matrix object */
    1390 SCIP_COL** lpcols; /* lp columns */
    1391 SCIP_SOL* sol; /* solution pointer */
    1392 SCIP_Real* colnorms; /* contains Euclidean norms of column vectors */
    1393
    1394 SCIP_Real* steps; /* buffer arrays for best shift selection in main loop */
    1395 int* violationchange;
    1396
    1397 int* violatedrows; /* the violated rows */
    1398 int* violatedrowpos; /* the array position of a violated row, or -1 */
    1399 int* permutation; /* reflects the position of the variables after sorting */
    1400 int* violatedvarrows; /* number of violated rows for each variable */
    1401 int* colposs; /* position of columns according to variable type sorting */
    1402 int nlpcols; /* number of lp columns */
    1403 int nviolatedrows; /* number of violated rows */
    1404 int ndiscvars; /* number of non-continuous variables of the problem */
    1405 int lastindexofsusp; /* last variable which has been swapped due to a cutoff */
    1406 int nbinvars; /* number of binary variables */
    1407#ifndef NDEBUG
    1408 int nintvars = 0; /* number of integer variables */
    1409#endif
    1410 int i;
    1411 int r;
    1412 int v;
    1413 int c;
    1414 int ncutoffs; /* counts the number of cutoffs for this execution */
    1415 int nprobings; /* counts the number of probings */
    1416 int nlprows; /* the number LP rows */
    1417 int nmaxrows; /* maximum number of LP rows of a variable */
    1418
    1419 SCIP_Bool initialized; /* has the matrix been initialized? */
    1420 SCIP_Bool cutoff; /* has current probing node been cutoff? */
    1421 SCIP_Bool probing; /* should probing be applied or not? */
    1422 SCIP_Bool infeasible; /* FALSE as long as currently infeasible rows have variables left */
    1423 SCIP_Bool impliscontinuous;
    1424
    1425 heurdata = SCIPheurGetData(heur);
    1426 assert(heurdata != NULL);
    1427
    1428 eventhdlr = heurdata->eventhdlr;
    1429 assert(eventhdlr != NULL);
    1430
    1431 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1432 assert(eventhdlrdata != NULL);
    1433
    1434 *result = SCIP_DIDNOTRUN;
    1435 SCIPdebugMsg(scip, "entering execution method of shift and propagate heuristic\n");
    1436
    1437 /* heuristic is obsolete if there are only continuous variables */
    1438 if( SCIPgetNVars(scip) - SCIPgetNContVars(scip) == 0 )
    1439 return SCIP_OKAY;
    1440
    1441 /* stop execution method if there is already a primarily feasible solution at hand */
    1442 if( SCIPgetBestSol(scip) != NULL && heurdata->onlywithoutsol )
    1443 return SCIP_OKAY;
    1444
    1445 /* stop if there is no LP available */
    1446 if ( ! SCIPhasCurrentNodeLP(scip) )
    1447 return SCIP_OKAY;
    1448
    1450 {
    1451 /* note that this call can have the side effect that variables are created */
    1452 SCIP_CALL( SCIPconstructLP(scip, &cutoff) );
    1453
    1454 /* manually cut off the node if the LP construction detected infeasibility (heuristics cannot return such a
    1455 * result); the cutoff result is safe to use in exact solving mode, but we don't have enough information to
    1456 * give a certificate for the cutoff
    1457 */
    1458 if( cutoff && !SCIPisCertified(scip) )
    1459 {
    1461 return SCIP_OKAY;
    1462 }
    1463
    1465 }
    1466
    1467 SCIPstatistic( heurdata->nlpiters = SCIPgetNLPIterations(scip) );
    1468
    1469 nlprows = SCIPgetNLPRows(scip);
    1470
    1471 SCIP_CALL( SCIPgetLPColsData(scip, &lpcols, &nlpcols) );
    1472 assert(nlpcols == 0 || lpcols != NULL);
    1473
    1474 /* we need an LP */
    1475 if( nlprows == 0 || nlpcols == 0 )
    1476 return SCIP_OKAY;
    1477
    1478 *result = SCIP_DIDNOTFIND;
    1479 initialized = FALSE;
    1480
    1481 /* allocate lp column array */
    1482 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->lpcols, nlpcols) );
    1483 heurdata->nlpcols = nlpcols;
    1484
    1485 impliscontinuous = heurdata->impliscontinuous;
    1486
    1487#ifndef NDEBUG
    1488 BMSclearMemoryArray(heurdata->lpcols, nlpcols);
    1489#endif
    1490
    1491 /* copy and sort the columns by their variable types (binary before integer before implicit integer before continuous) */
    1492 BMScopyMemoryArray(heurdata->lpcols, lpcols, nlpcols);
    1493
    1494 SCIPsortPtr((void**)heurdata->lpcols, heurSortColsShiftandpropagate, nlpcols);
    1495
    1496 SCIP_CALL( SCIPallocBufferArray(scip, &colposs, nlpcols) );
    1497
    1498 /* we have to collect the number of different variable types before we start probing since during probing variable
    1499 * can be created (e.g., cons_xor.c)
    1500 */
    1501 ndiscvars = 0;
    1502 nbinvars = 0;
    1503 for( c = 0; c < nlpcols; ++c )
    1504 {
    1505 SCIP_COL* col;
    1506 SCIP_VAR* colvar;
    1507
    1508 col = heurdata->lpcols[c];
    1509 assert(col != NULL);
    1510 colvar = SCIPcolGetVar(col);
    1511 assert(colvar != NULL);
    1512
    1513 if( varIsDiscrete(colvar, impliscontinuous) )
    1514 ++ndiscvars;
    1516 ++nbinvars;
    1517#ifndef NDEBUG
    1518 else if( SCIPvarGetType(colvar) == SCIP_VARTYPE_INTEGER && !SCIPvarIsImpliedIntegral(colvar) )
    1519 ++nintvars;
    1520#endif
    1521
    1522 /* save the position of this column in the array such that it can be accessed as the "true" column position */
    1523 assert(SCIPcolGetLPPos(col) >= 0);
    1524 colposs[SCIPcolGetLPPos(col)] = c;
    1525 }
    1526 assert(nbinvars + nintvars <= ndiscvars);
    1527
    1528 /* start probing mode */
    1530
    1531 /* enables collection of variable statistics during probing */
    1532 if( heurdata->collectstats )
    1534 else
    1536
    1537 /* this should always be fulfilled because we perform shift and propagate only at the root node */
    1539
    1540 /* @todo check if this node is necessary (I don't think so) */
    1542 ncutoffs = 0;
    1543 nprobings = 0;
    1544 nmaxrows = 0;
    1545 infeasible = FALSE;
    1546
    1547 /* initialize heuristic matrix and working solution */
    1548 SCIP_CALL( SCIPallocBuffer(scip, &matrix) );
    1549 SCIP_CALL( initMatrix(scip, matrix, heurdata, colposs, &nmaxrows, heurdata->relax, &initialized, &infeasible) );
    1550
    1551 /* could not initialize matrix */
    1552 if( !initialized || infeasible )
    1553 {
    1554 SCIPdebugMsg(scip, " MATRIX not initialized -> Execution of heuristic stopped! \n");
    1555 goto TERMINATE;
    1556 }
    1557
    1558 /* the number of discrete LP column variables can be less than the actual number of variables, if, e.g., there
    1559 * are nonlinearities in the problem. The heuristic execution can be terminated in that case.
    1560 */
    1561 if( matrix->ndiscvars < ndiscvars )
    1562 {
    1563 SCIPdebugMsg(scip, "Not all discrete variables are in the current LP. Shiftandpropagate execution terminated.\n");
    1564 goto TERMINATE;
    1565 }
    1566
    1567 assert(nmaxrows > 0);
    1568
    1569 eventhdlrdata->matrix = matrix;
    1570 eventhdlrdata->heurdata = heurdata;
    1571
    1572 SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
    1573 SCIPsolSetHeur(sol, heur);
    1574
    1575 /* allocate arrays for execution method */
    1576 SCIP_CALL( SCIPallocBufferArray(scip, &permutation, ndiscvars) );
    1577 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowweights, matrix->nrows) );
    1578
    1579 /* allocate necessary memory for best shift search */
    1580 SCIP_CALL( SCIPallocBufferArray(scip, &steps, nmaxrows) );
    1581 SCIP_CALL( SCIPallocBufferArray(scip, &violationchange, nmaxrows) );
    1582
    1583 /* allocate arrays to store information about infeasible rows */
    1584 SCIP_CALL( SCIPallocBufferArray(scip, &violatedrows, matrix->nrows) );
    1585 SCIP_CALL( SCIPallocBufferArray(scip, &violatedrowpos, matrix->nrows) );
    1586
    1587 eventhdlrdata->violatedrows = violatedrows;
    1588 eventhdlrdata->violatedrowpos = violatedrowpos;
    1589 eventhdlrdata->nviolatedrows = &nviolatedrows;
    1590
    1591 /* initialize arrays. Before sorting, permutation is the identity permutation */
    1592 for( i = 0; i < ndiscvars; ++i )
    1593 permutation[i] = i;
    1594
    1595 /* initialize row weights */
    1596 for( r = 0; r < matrix->nrows; ++r )
    1597 {
    1598 if( !SCIPisInfinity(scip, -(matrix->lhs[r])) && !SCIPisInfinity(scip, matrix->rhs[r]) )
    1599 heurdata->rowweights[r] = DEFAULT_WEIGHT_EQUALITY;
    1600 else
    1601 heurdata->rowweights[r] = DEFAULT_WEIGHT_INEQUALITY;
    1602 }
    1603 colnorms = matrix->colnorms;
    1604
    1605 assert(nbinvars >= 0);
    1606 assert(nintvars >= 0);
    1607
    1608 /* check rows for infeasibility */
    1609 checkViolations(scip, matrix, -1, violatedrows, violatedrowpos, &nviolatedrows, heurdata->rowweights, heurdata->updateweights);
    1610
    1611 /* allocate memory for violatedvarrows array only if variable ordering relies on it */
    1612 if( heurdata->sortvars && (heurdata->sortkey == 't' || heurdata->sortkey == 'v') )
    1613 {
    1614 SCIP_CALL( SCIPallocBufferArray(scip, &violatedvarrows, ndiscvars) );
    1615 BMScopyMemoryArray(violatedvarrows, matrix->violrows, ndiscvars);
    1616 }
    1617 else
    1618 violatedvarrows = NULL;
    1619
    1620 /* sort variables w.r.t. the sorting key parameter. Sorting is indirect, all matrix column data
    1621 * stays in place, but permutation array gives access to the sorted order of variables
    1622 */
    1623 if( heurdata->sortvars )
    1624 {
    1625 switch (heurdata->sortkey)
    1626 {
    1627 case 'n':
    1628 /* variable ordering w.r.t. column norms nonincreasing */
    1629 if( heurdata->preferbinaries )
    1630 {
    1631 if( nbinvars > 0 )
    1632 SCIPsortDownRealInt(colnorms, permutation, nbinvars);
    1633 if( nbinvars < ndiscvars )
    1634 SCIPsortDownRealInt(&colnorms[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
    1635 }
    1636 else
    1637 {
    1638 SCIPsortDownRealInt(colnorms, permutation, ndiscvars);
    1639 }
    1640 SCIPdebugMsg(scip, "Variables sorted down w.r.t their normalized columns!\n");
    1641 break;
    1642 case 'u':
    1643 /* variable ordering w.r.t. column norms nondecreasing */
    1644 if( heurdata->preferbinaries )
    1645 {
    1646 if( nbinvars > 0 )
    1647 SCIPsortRealInt(colnorms, permutation, nbinvars);
    1648 if( nbinvars < ndiscvars )
    1649 SCIPsortRealInt(&colnorms[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
    1650 }
    1651 else
    1652 {
    1653 SCIPsortRealInt(colnorms, permutation, ndiscvars);
    1654 }
    1655 SCIPdebugMsg(scip, "Variables sorted w.r.t their normalized columns!\n");
    1656 break;
    1657 case 'v':
    1658 /* variable ordering w.r.t. nonincreasing number of violated rows */
    1659 assert(violatedvarrows != NULL);
    1660 if( heurdata->preferbinaries )
    1661 {
    1662 if( nbinvars > 0 )
    1663 SCIPsortDownIntInt(violatedvarrows, permutation, nbinvars);
    1664 if( nbinvars < ndiscvars )
    1665 SCIPsortDownIntInt(&violatedvarrows[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
    1666 }
    1667 else
    1668 {
    1669 SCIPsortDownIntInt(violatedvarrows, permutation, ndiscvars);
    1670 }
    1671
    1672 SCIPdebugMsg(scip, "Variables sorted down w.r.t their number of currently infeasible rows!\n");
    1673 break;
    1674 case 't':
    1675 /* variable ordering w.r.t. nondecreasing number of violated rows */
    1676 assert(violatedvarrows != NULL);
    1677 if( heurdata->preferbinaries )
    1678 {
    1679 if( nbinvars > 0 )
    1680 SCIPsortIntInt(violatedvarrows, permutation, nbinvars);
    1681 if( nbinvars < ndiscvars )
    1682 SCIPsortIntInt(&violatedvarrows[nbinvars], &permutation[nbinvars], ndiscvars - nbinvars);
    1683 }
    1684 else
    1685 {
    1686 SCIPsortIntInt(violatedvarrows, permutation, ndiscvars);
    1687 }
    1688
    1689 SCIPdebugMsg(scip, "Variables sorted (upwards) w.r.t their number of currently infeasible rows!\n");
    1690 break;
    1691 case 'r':
    1692 /* random sorting */
    1693 if( heurdata->preferbinaries )
    1694 {
    1695 if( nbinvars > 0 )
    1696 SCIPrandomPermuteIntArray(heurdata->randnumgen, permutation, 0, nbinvars - 1);
    1697 if( nbinvars < ndiscvars )
    1698 SCIPrandomPermuteIntArray(heurdata->randnumgen, &permutation[nbinvars], nbinvars - 1,
    1699 ndiscvars - nbinvars - 1);
    1700 }
    1701 else
    1702 {
    1703 SCIPrandomPermuteIntArray(heurdata->randnumgen, permutation, 0, ndiscvars - 1);
    1704 }
    1705 SCIPdebugMsg(scip, "Variables permuted randomly!\n");
    1706 break;
    1707 default:
    1708 SCIPdebugMsg(scip, "No variable permutation applied\n");
    1709 break;
    1710 }
    1711 }
    1712
    1713 /* should binary variables without locks be treated first? */
    1714 if( heurdata->binlocksfirst )
    1715 {
    1716 SCIP_VAR* var;
    1717 int nbinwithoutlocks = 0;
    1718
    1719 /* count number of binaries without locks */
    1720 if( heurdata->preferbinaries )
    1721 {
    1722 for( c = 0; c < nbinvars; ++c )
    1723 {
    1724 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
    1727 ++nbinwithoutlocks;
    1728 }
    1729 }
    1730 else
    1731 {
    1732 for( c = 0; c < ndiscvars; ++c )
    1733 {
    1734 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
    1735 if( SCIPvarIsBinary(var) )
    1736 {
    1739 ++nbinwithoutlocks;
    1740 }
    1741 }
    1742 }
    1743
    1744 if( nbinwithoutlocks > 0 )
    1745 {
    1746 SCIP_VAR* binvar;
    1747 int b = 1;
    1748 int tmp;
    1749 c = 0;
    1750
    1751 /* if c reaches nbinwithoutlocks, then all binary variables without locks were sorted to the beginning of the array */
    1752 while( c < nbinwithoutlocks && b < ndiscvars )
    1753 {
    1754 assert(c < b);
    1755 assert(c < ndiscvars);
    1756 assert(b < ndiscvars);
    1757 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
    1758 binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
    1759
    1760 /* search for next variable which is not a binary variable without locks */
    1763 {
    1764 ++c;
    1765 if( c >= nbinwithoutlocks )
    1766 break;
    1767 var = SCIPcolGetVar(heurdata->lpcols[permutation[c]]);
    1768 }
    1769 if( c >= nbinwithoutlocks )
    1770 break;
    1771
    1772 /* search for next binary variable without locks (with position > c) */
    1773 if( b <= c )
    1774 {
    1775 b = c + 1;
    1776 binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
    1777 }
    1778 while( !SCIPvarIsBinary(binvar) || (SCIPvarGetNLocksUpType(binvar, SCIP_LOCKTYPE_MODEL) > 0
    1780 {
    1781 ++b;
    1782 assert(b < ndiscvars);
    1783 binvar = SCIPcolGetVar(heurdata->lpcols[permutation[b]]);
    1784 }
    1785
    1786 /* swap the two variables */
    1787 tmp = permutation[b];
    1788 permutation[b] = permutation[c];
    1789 permutation[c] = tmp;
    1790
    1791 /* increase counters */
    1792 ++c;
    1793 ++b;
    1794 }
    1795 }
    1796
    1797#ifndef NDEBUG
    1798 for( c = 0; c < ndiscvars; ++c )
    1799 {
    1800 assert((c < nbinwithoutlocks) == (SCIPvarIsBinary(SCIPcolGetVar(heurdata->lpcols[permutation[c]]))
    1801 && (SCIPvarGetNLocksUpType(SCIPcolGetVar(heurdata->lpcols[permutation[c]]), SCIP_LOCKTYPE_MODEL) == 0
    1802 || SCIPvarGetNLocksDownType(SCIPcolGetVar(heurdata->lpcols[permutation[c]]), SCIP_LOCKTYPE_MODEL) == 0)));
    1803 }
    1804#endif
    1805 }
    1806
    1807 SCIP_CALL( SCIPallocBufferArray(scip, &eventdatas, matrix->ndiscvars) );
    1808 BMSclearMemoryArray(eventdatas, matrix->ndiscvars);
    1809
    1810 /* initialize variable events to catch bound changes during propagation */
    1811 for( c = 0; c < matrix->ndiscvars; ++c )
    1812 {
    1813 SCIP_VAR* var;
    1814
    1815 var = SCIPcolGetVar(heurdata->lpcols[c]);
    1816 assert(var != NULL);
    1817 assert(SCIPvarIsIntegral(var));
    1818 assert(eventdatas[c] == NULL);
    1819
    1820 SCIP_CALL( SCIPallocBuffer(scip, &(eventdatas[c])) ); /*lint !e866*/
    1821
    1822 eventdatas[c]->colpos = c;
    1823
    1824 SCIP_CALL( SCIPcatchVarEvent(scip, var, EVENTTYPE_SHIFTANDPROPAGATE, eventhdlr, eventdatas[c], NULL) );
    1825 }
    1826
    1827 cutoff = FALSE;
    1828
    1829 lastindexofsusp = -1;
    1830 probing = heurdata->probing;
    1831 infeasible = FALSE;
    1832
    1833 SCIPdebugMsg(scip, "SHIFT_AND_PROPAGATE heuristic starts main loop with %d violations and %d remaining variables!\n",
    1834 nviolatedrows, ndiscvars);
    1835
    1836 assert(matrix->ndiscvars == ndiscvars);
    1837
    1838 /* loop over variables, shift them according to shifting criteria and try to reduce the global infeasibility */
    1839 for( c = 0; c < ndiscvars; ++c )
    1840 {
    1841 SCIP_VAR* var;
    1842 SCIP_Longint ndomredsfound;
    1843 SCIP_Real optimalshiftvalue;
    1844 SCIP_Real origsolval;
    1845 SCIP_Real lb;
    1846 SCIP_Real ub;
    1847 int nviolations;
    1848 int permutedvarindex;
    1849 int j;
    1850 SCIP_Bool marksuspicious;
    1851
    1852 if( heurdata->selectbest )
    1853 { /* search for best candidate */
    1854 j = c + 1;
    1855 while( j < ndiscvars )
    1856 {
    1857 /* run through remaining variables and search for best candidate */
    1858 if( matrix->violrows[permutation[c]] < matrix->violrows[permutation[j]] )
    1859 {
    1860 int tmp;
    1861 tmp = permutation[c];
    1862 permutation[c] = permutation[j];
    1863 permutation[j] = tmp;
    1864 }
    1865 ++j;
    1866 }
    1867 }
    1868 permutedvarindex = permutation[c];
    1869 optimalshiftvalue = 0.0;
    1870 nviolations = 0;
    1871 var = SCIPcolGetVar(heurdata->lpcols[permutedvarindex]);
    1872 lb = SCIPvarGetLbLocal(var);
    1873 ub = SCIPvarGetUbLocal(var);
    1874 assert(SCIPcolGetLPPos(SCIPvarGetCol(var)) >= 0);
    1875 assert(SCIPvarIsIntegral(var));
    1876
    1877 /* check whether we hit some limit, e.g. the time limit, in between
    1878 * since the check itself consumes some time, we only do it every tenth iteration
    1879 */
    1880 if( c % 10 == 0 && SCIPisStopped(scip) )
    1881 goto TERMINATE2;
    1882
    1883 /* if propagation is enabled, check if propagation has changed the variables bounds
    1884 * and update the transformed upper bound correspondingly
    1885 * @todo this should not be necessary
    1886 */
    1887 if( heurdata->probing )
    1888 {
    1889 SCIP_CALL( updateTransformation(scip, matrix, heurdata, permutedvarindex,lb, ub, violatedrows, violatedrowpos,
    1890 &nviolatedrows) );
    1891 }
    1892
    1893 SCIPdebugMsg(scip, "Variable %s with local bounds [%g,%g], status <%d>, matrix bound <%g>\n",
    1894 SCIPvarGetName(var), lb, ub, matrix->transformstatus[permutedvarindex], matrix->upperbounds[permutedvarindex]);
    1895
    1896 /* ignore variable if propagation fixed it (lb and ub will be zero) */
    1897 if( SCIPisFeasZero(scip, matrix->upperbounds[permutedvarindex]) )
    1898 {
    1899 assert(!SCIPisInfinity(scip, ub));
    1900 assert(SCIPisFeasEQ(scip, lb, ub));
    1901
    1902 SCIP_CALL( SCIPsetSolVal(scip, sol, var, ub) );
    1903
    1904 continue;
    1905 }
    1906
    1907 marksuspicious = FALSE;
    1908
    1909 /* check whether the variable is binary and has no locks in one direction, so that we want to fix it to the
    1910 * respective bound (only enabled by parameter)
    1911 */
    1912 if( heurdata->fixbinlocks && SCIPvarIsBinary(var)
    1915 {
    1917 origsolval = SCIPvarGetUbLocal(var);
    1918 else
    1919 {
    1921 origsolval = SCIPvarGetLbLocal(var);
    1922 }
    1923 }
    1924 else
    1925 {
    1926 /* only apply the computationally expensive best shift selection, if there is a violated row left */
    1927 if( !heurdata->stopafterfeasible || nviolatedrows > 0 )
    1928 {
    1929 /* compute optimal shift value for variable */
    1930 SCIP_CALL( getOptimalShiftingValue(scip, matrix, permutedvarindex, 1, heurdata->rowweights, steps, violationchange,
    1931 &optimalshiftvalue, &nviolations) );
    1932 assert(SCIPisFeasGE(scip, optimalshiftvalue, 0.0));
    1933
    1934 /* Variables with FREE transform have to be dealt with twice */
    1935 if( matrix->transformstatus[permutedvarindex] == TRANSFORMSTATUS_FREE )
    1936 {
    1937 SCIP_Real downshiftvalue;
    1938 int ndownviolations;
    1939
    1940 downshiftvalue = 0.0;
    1941 ndownviolations = 0;
    1942 SCIP_CALL( getOptimalShiftingValue(scip, matrix, permutedvarindex, -1, heurdata->rowweights, steps, violationchange,
    1943 &downshiftvalue, &ndownviolations) );
    1944
    1945 assert(SCIPisLE(scip, downshiftvalue, 0.0));
    1946
    1947 /* compare to positive direction and select the direction which makes more rows feasible */
    1948 if( ndownviolations < nviolations )
    1949 {
    1950 optimalshiftvalue = downshiftvalue;
    1951 }
    1952 }
    1953 }
    1954 else
    1955 optimalshiftvalue = 0.0;
    1956
    1957 /* if zero optimal shift values are forbidden by the user parameter, delay the variable by marking it suspicious */
    1958 if( heurdata->nozerofixing && nviolations > 0 && SCIPisFeasZero(scip, optimalshiftvalue) )
    1959 marksuspicious = TRUE;
    1960
    1961 /* retransform the solution value from the heuristic transformation space */
    1962 assert(varIsDiscrete(var, impliscontinuous));
    1963 origsolval = retransformVariable(scip, matrix, var, permutedvarindex, optimalshiftvalue);
    1964 }
    1965 assert(SCIPisFeasGE(scip, origsolval, lb) && SCIPisFeasLE(scip, origsolval, ub));
    1966
    1967 /* check if propagation should still be performed
    1968 * @todo do we need the hard coded value? we could use SCIP_MAXTREEDEPTH
    1969 */
    1970 if( nprobings > DEFAULT_PROPBREAKER )
    1971 probing = FALSE;
    1972
    1973 /* if propagation is enabled, fix the variable to the new solution value and propagate the fixation
    1974 * (to fix other variables and to find out early whether solution is already infeasible)
    1975 */
    1976 if( !marksuspicious && probing )
    1977 {
    1978 /* this assert should be always fulfilled because we run this heuristic at the root node only and do not
    1979 * perform probing if nprobings is less than DEFAULT_PROPBREAKER (currently: 65000)
    1980 */
    1982
    1984 SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) );
    1985 ndomredsfound = 0;
    1986
    1987 SCIPdebugMsg(scip, " Shift %g(%g originally) is optimal, propagate solution\n", optimalshiftvalue, origsolval);
    1988 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
    1989
    1990 ++nprobings;
    1991 SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
    1992 SCIPdebugMsg(scip, "Propagation finished! <%" SCIP_LONGINT_FORMAT "> domain reductions %s, <%d> probing depth\n", ndomredsfound, cutoff ? "CUTOFF" : "",
    1994 }
    1995 assert(!cutoff || probing);
    1996
    1997 /* propagation led to an empty domain, hence we backtrack and postpone the variable */
    1998 if( cutoff )
    1999 {
    2000 assert(probing);
    2001
    2002 ++ncutoffs;
    2003
    2004 /* only continue heuristic if number of cutoffs occurred so far is reasonably small */
    2005 if( heurdata->cutoffbreaker >= 0 && ncutoffs >= ((heurdata->maxcutoffquot * SCIPgetProbingDepth(scip)) + heurdata->cutoffbreaker) )
    2006 break;
    2007
    2008 cutoff = FALSE;
    2009
    2010 /* backtrack to the parent of the current node */
    2011 assert(SCIPgetProbingDepth(scip) >= 1);
    2013
    2014 /* this assert should be always fulfilled because we run this heuristic at the root node only and do not
    2015 * perform probing if nprobings is less than DEFAULT_PROPBREAKER (currently: 65000)
    2016 */
    2018
    2019 /* if the variable upper and lower bound are equal to the solution value to which we tried to fix the variable,
    2020 * we are trapped at an infeasible node and break; this can only happen due to an intermediate global bound change of the variable,
    2021 * I guess
    2022 */
    2023 if( SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), origsolval) && SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), origsolval) )
    2024 {
    2025 cutoff = TRUE;
    2026 break;
    2027 }
    2028 else if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), origsolval) && REALABS( origsolval ) < 1.0 / SCIPepsilon(scip) )
    2029 {
    2030 /* if the variable was set to one of its bounds, repropagate by tightening this bound by 1.0 into the
    2031 * direction of the other bound, if possible; if the bound is too large (in abs value) do not even bother
    2032 */
    2033 assert(SCIPisFeasGE(scip, SCIPvarGetUbLocal(var), origsolval + 1.0));
    2034
    2035 ndomredsfound = 0;
    2037 SCIP_CALL( SCIPchgVarLbProbing(scip, var, origsolval + 1.0) );
    2038 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
    2039
    2040 SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
    2041 }
    2042 else if( SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), origsolval) && REALABS( origsolval ) < 1.0 / SCIPepsilon(scip) )
    2043 {
    2044 /* if the variable was set to one of its bounds, repropagate by tightening this bound by 1.0 into the
    2045 * direction of the other bound, if possible; if the bound is too large (in abs value) do not even bother
    2046 */
    2047 assert(SCIPisFeasLE(scip, SCIPvarGetLbLocal(var), origsolval - 1.0));
    2048
    2049 ndomredsfound = 0;
    2050
    2052 SCIP_CALL( SCIPchgVarUbProbing(scip, var, origsolval - 1.0) );
    2053 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->nproprounds, &cutoff, &ndomredsfound) );
    2054
    2055 SCIPstatistic( heurdata->ntotaldomredsfound += ndomredsfound );
    2056 }
    2057
    2058 /* if the tightened bound again leads to a cutoff, both subproblems are proven infeasible and the heuristic
    2059 * can be stopped */
    2060 if( cutoff )
    2061 {
    2062 break;
    2063 }
    2064 else
    2065 {
    2066 /* since repropagation was successful, we indicate that this variable led to a cutoff in one direction */
    2067 marksuspicious = TRUE;
    2068 }
    2069 }
    2070
    2071 if( marksuspicious )
    2072 {
    2073 /* mark the variable as suspicious */
    2074 assert(permutedvarindex == permutation[c]);
    2075
    2076 ++lastindexofsusp;
    2077 assert(lastindexofsusp >= 0 && lastindexofsusp <= c);
    2078
    2079 permutation[c] = permutation[lastindexofsusp];
    2080 permutation[lastindexofsusp] = permutedvarindex;
    2081
    2082 SCIPdebugMsg(scip, " Suspicious variable! Postponed from pos <%d> to position <%d>\n", c, lastindexofsusp);
    2083 }
    2084 else
    2085 {
    2086 SCIPdebugMsg(scip, "Variable <%d><%s> successfully shifted by value <%g>!\n", permutedvarindex,
    2087 SCIPvarGetName(var), optimalshiftvalue);
    2088
    2089 /* update solution */
    2090 SCIP_CALL( SCIPsetSolVal(scip, sol, var, origsolval) );
    2091
    2092 /* only to ensure that some assertions can be made later on */
    2093 if( !probing )
    2094 {
    2095 SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) );
    2096 }
    2097 }
    2098 }
    2099 SCIPdebugMsg(scip, "Heuristic finished with %d remaining violations and %d remaining variables!\n",
    2100 nviolatedrows, lastindexofsusp + 1);
    2101
    2102 /* if constructed solution might be feasible, go through the queue of suspicious variables and set the solution
    2103 * values
    2104 */
    2105 if( nviolatedrows == 0 && !cutoff )
    2106 {
    2107 SCIP_Bool stored;
    2108 SCIP_Bool trysol;
    2109 SCIP_Bool solvelp;
    2110
    2111 for( v = 0; v <= lastindexofsusp; ++v )
    2112 {
    2113 SCIP_VAR* var;
    2114 SCIP_Real origsolval;
    2115 int permutedvarindex;
    2116
    2117 /* get the column position of the variable */
    2118 permutedvarindex = permutation[v];
    2119 var = SCIPcolGetVar(heurdata->lpcols[permutedvarindex]);
    2120 assert(varIsDiscrete(var, impliscontinuous));
    2121
    2122 /* update the transformation of the variable, since the bound might have changed after the last update. */
    2123 if( heurdata->probing )
    2124 SCIP_CALL( updateTransformation(scip, matrix, heurdata, permutedvarindex, SCIPvarGetLbLocal(var),
    2125 SCIPvarGetUbLocal(var), violatedrows, violatedrowpos, &nviolatedrows) );
    2126
    2127 /* retransform the solution value from the heuristic transformed space, set the solution value accordingly */
    2128 assert(varIsDiscrete(var, impliscontinuous));
    2129 origsolval = retransformVariable(scip, matrix, var, permutedvarindex, 0.0);
    2130 assert(SCIPisFeasGE(scip, origsolval, SCIPvarGetLbLocal(var))
    2131 && SCIPisFeasLE(scip, origsolval, SCIPvarGetUbLocal(var)));
    2132 SCIP_CALL( SCIPsetSolVal(scip, sol, var, origsolval) );
    2133 SCIP_CALL( SCIPfixVarProbing(scip, var, origsolval) ); /* only to ensure that some assertions can be made later */
    2134
    2135 SCIPdebugMsg(scip, " Remaining variable <%s> set to <%g>; %d Violations\n", SCIPvarGetName(var), origsolval,
    2136 nviolatedrows);
    2137 }
    2138
    2139 /* Fixing of remaining variables led to infeasibility */
    2140 if( nviolatedrows > 0 )
    2141 goto TERMINATE2;
    2142
    2143 trysol = TRUE;
    2144
    2145 /* check if enough variables have been fixed (including continuous) to solve the remaining LP */
    2146 if( nlpcols != matrix->ndiscvars )
    2147 {
    2148 SCIP_VAR** vars;
    2149 int nvars = SCIPgetNVars(scip);
    2150 int nminfixings = (int)(SCIPceil(scip, heurdata->minfixingratelp * nvars));
    2151 int nfixedvars = ndiscvars;
    2152
    2153 vars = SCIPgetVars(scip);
    2154
    2155 /* count fixed variables */
    2156 for( v = ndiscvars; v < nvars && nfixedvars < nminfixings; ++v )
    2157 {
    2158 if( SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v])) )
    2159 ++nfixedvars;
    2160 }
    2161
    2162 solvelp = (nfixedvars >= nminfixings);
    2163 trysol = solvelp;
    2164 SCIPdebugMsg(scip, "Fixed %d of %d (%.1f %%) variables after probing -> %s\n",
    2165 nfixedvars, nvars, (100.0 * nfixedvars / (SCIP_Real)nvars),
    2166 solvelp ? "continue and solve LP for remaining variables" : "terminate without LP");
    2167 }
    2168 else /* no need to solve an LP */
    2169 solvelp = FALSE;
    2170
    2171 /* if the constructed solution might still be extendable to a feasible solution, try this by
    2172 * solving the remaining LP
    2173 */
    2174 if( solvelp )
    2175 {
    2176 char strbuf[SCIP_MAXSTRLEN];
    2177 /* case that remaining LP has to be solved */
    2178 SCIP_Bool lperror;
    2179 int ncols;
    2180
    2181#ifndef NDEBUG
    2182 {
    2183 SCIP_VAR** vars;
    2184
    2185 vars = SCIPgetVars(scip);
    2186 assert(vars != NULL);
    2187 /* ensure that all discrete variables in the remaining LP are fixed */
    2188 for( v = 0; v < ndiscvars; ++v )
    2189 {
    2190 if( SCIPvarIsInLP(vars[v]) )
    2191 {
    2192 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v])));
    2193 }
    2194 }
    2195 }
    2196#endif
    2197
    2198 /* print message if relatively large LP is solved from scratch, since this could lead to a longer period during
    2199 * which the user sees no output; more detailed probing stats only in debug mode */
    2200 ncols = SCIPgetNLPCols(scip);
    2201 if( !SCIPisLPSolBasic(scip) && ncols > 1000 )
    2202 {
    2203 int nunfixedcols = SCIPgetNUnfixedLPCols(scip);
    2204
    2205 if( nunfixedcols > 0.5 * ncols )
    2206 {
    2208 "Heuristic " HEUR_NAME " solving LP from scratch with %.1f %% unfixed columns (%d of %d) ...\n",
    2209 100.0 * (nunfixedcols / (SCIP_Real)ncols), nunfixedcols, ncols);
    2210 }
    2211 }
    2212 SCIPdebugMsg(scip, "Heuristic " HEUR_NAME " probing LP: %s\n",
    2214 SCIPdebugMsg(scip, " -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    2215
    2216#ifdef SCIP_DEBUG
    2217 SCIP_CALL( SCIPwriteLP(scip, "shiftandpropagatelp.mps") );
    2218#endif
    2219 /* solve LP;
    2220 * errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
    2221 * hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    2222 */
    2223#ifdef NDEBUG
    2224 {
    2225 SCIP_RETCODE retstat;
    2226 retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
    2227 if( retstat != SCIP_OKAY )
    2228 {
    2229 SCIPwarningMessage(scip, "Error while solving LP in SHIFTANDPROPAGATE heuristic; LP solve terminated with code <%d>\n",
    2230 retstat);
    2231 }
    2232 }
    2233#else
    2234 SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, NULL) );
    2235#endif
    2236
    2237 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
    2238 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
    2239
    2240 /* check if this is a feasible solution */
    2241 if( !lperror && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
    2242 {
    2243 /* copy the current LP solution to the working solution */
    2244 SCIP_CALL( SCIPlinkLPSol(scip, sol) );
    2245 }
    2246 else
    2247 trysol = FALSE;
    2248
    2249 SCIPstatistic( heurdata->lpsolstat = SCIPgetLPSolstat(scip) );
    2250 }
    2251
    2252 /* check solution for feasibility, and add it to solution store if possible.
    2253 * None of integrality, feasibility of LP rows, variable bounds have to be checked, because they
    2254 * are guaranteed by the heuristic at this stage.
    2255 */
    2256 if( trysol )
    2257 {
    2258 SCIP_Bool printreason;
    2259 SCIP_Bool completely;
    2260#ifdef SCIP_DEBUG
    2261 printreason = TRUE;
    2262#else
    2263 printreason = FALSE;
    2264#endif
    2265#ifndef NDEBUG
    2266 completely = TRUE; /*lint !e838*/
    2267#else
    2268 completely = FALSE;
    2269#endif
    2270
    2271 /* we once also checked the variable bounds which should not be necessary */
    2272 SCIP_CALL( SCIPtrySol(scip, sol, printreason, completely, FALSE, FALSE, FALSE, &stored) );
    2273
    2274 if( stored )
    2275 {
    2276 SCIPdebugMsg(scip, "found feasible shifted solution:\n");
    2278 *result = SCIP_FOUNDSOL;
    2279
    2280 SCIPstatisticMessage(" Shiftandpropagate solution value: %16.9g \n", SCIPgetSolOrigObj(scip, sol));
    2281 }
    2282 }
    2283 }
    2284 else
    2285 {
    2286 SCIPdebugMsg(scip, "Solution constructed by heuristic is already known to be infeasible\n");
    2287 }
    2288
    2289 SCIPstatistic( heurdata->nremainingviols = nviolatedrows; );
    2290
    2291 TERMINATE2:
    2292 /* free allocated memory in reverse order of allocation */
    2293 for( c = matrix->ndiscvars - 1; c >= 0; --c )
    2294 {
    2295 SCIP_VAR* var;
    2296
    2297 var = SCIPcolGetVar(heurdata->lpcols[c]);
    2298 assert(var != NULL);
    2299 assert(eventdatas[c] != NULL);
    2300
    2301 SCIP_CALL( SCIPdropVarEvent(scip, var, EVENTTYPE_SHIFTANDPROPAGATE, eventhdlr, eventdatas[c], -1) );
    2302 SCIPfreeBuffer(scip, &(eventdatas[c]));
    2303 }
    2304 SCIPfreeBufferArray(scip, &eventdatas);
    2305
    2306 if( violatedvarrows != NULL )
    2307 {
    2308 assert(heurdata->sortkey == 'v' || heurdata->sortkey == 't');
    2309 SCIPfreeBufferArray(scip, &violatedvarrows);
    2310 }
    2311 /* free all allocated memory */
    2312 SCIPfreeBufferArray(scip, &violatedrowpos);
    2313 SCIPfreeBufferArray(scip, &violatedrows);
    2314 SCIPfreeBufferArray(scip, &violationchange);
    2315 SCIPfreeBufferArray(scip, &steps);
    2316 SCIPfreeBufferArray(scip, &heurdata->rowweights);
    2317 SCIPfreeBufferArray(scip, &permutation);
    2318 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    2319
    2320 eventhdlrdata->nviolatedrows = NULL;
    2321 eventhdlrdata->violatedrowpos = NULL;
    2322 eventhdlrdata->violatedrows = NULL;
    2323
    2324 TERMINATE:
    2325 /* terminate probing mode and free the remaining memory */
    2327 heurdata->ncutoffs += ncutoffs;
    2328 heurdata->nprobings += nprobings;
    2329 heurdata->nlpiters = SCIPgetNLPIterations(scip) - heurdata->nlpiters;
    2330 );
    2331
    2333 freeMatrix(scip, &matrix);
    2334 SCIPfreeBufferArray(scip, &colposs);
    2335 SCIPfreeBufferArray(scip, &heurdata->lpcols);
    2336 eventhdlrdata->matrix = NULL;
    2337
    2338 return SCIP_OKAY;
    2339}
    2340
    2341/** event handler execution method for the heuristic which catches all
    2342 * events in which a lower or upper bound were tightened */
    2343static
    2344SCIP_DECL_EVENTEXEC(eventExecShiftandpropagate)
    2345{ /*lint --e{715}*/
    2346 SCIP_EVENTHDLRDATA* eventhdlrdata;
    2347 SCIP_VAR* var;
    2348 SCIP_COL* col;
    2349 SCIP_Real lb;
    2350 SCIP_Real ub;
    2351 int colpos;
    2352 CONSTRAINTMATRIX* matrix;
    2353 SCIP_HEURDATA* heurdata;
    2354
    2355 assert(scip != NULL);
    2356 assert(eventhdlr != NULL);
    2357
    2359
    2360 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    2361 assert(eventhdlrdata != NULL);
    2362
    2363 matrix = eventhdlrdata->matrix;
    2364
    2365 heurdata = eventhdlrdata->heurdata;
    2366 assert(heurdata != NULL && heurdata->lpcols != NULL);
    2367
    2368 colpos = eventdata->colpos;
    2369
    2370 assert(0 <= colpos && colpos < matrix->ndiscvars);
    2371
    2372 col = heurdata->lpcols[colpos];
    2373 var = SCIPcolGetVar(col);
    2374
    2375 lb = SCIPvarGetLbLocal(var);
    2376 ub = SCIPvarGetUbLocal(var);
    2377
    2378 SCIP_CALL( updateTransformation(scip, matrix, eventhdlrdata->heurdata, colpos, lb, ub, eventhdlrdata->violatedrows,
    2379 eventhdlrdata->violatedrowpos, eventhdlrdata->nviolatedrows) );
    2380
    2381 return SCIP_OKAY;
    2382}
    2383
    2384/*
    2385 * primal heuristic specific interface methods
    2386 */
    2387
    2388/** creates the shiftandpropagate primal heuristic and includes it in SCIP */
    2390 SCIP* scip /**< SCIP data structure */
    2391 )
    2392{
    2393 SCIP_HEURDATA* heurdata;
    2394 SCIP_HEUR* heur;
    2395 SCIP_EVENTHDLRDATA* eventhandlerdata;
    2396 SCIP_EVENTHDLR* eventhdlr;
    2397
    2398 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhandlerdata) );
    2399 eventhandlerdata->matrix = NULL;
    2400
    2401 eventhdlr = NULL;
    2403 eventExecShiftandpropagate, eventhandlerdata) );
    2404 assert(eventhdlr != NULL);
    2405
    2406 /* create Shiftandpropagate primal heuristic data */
    2407 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    2408 heurdata->rowweights = NULL;
    2409 heurdata->nlpcols = 0;
    2410 heurdata->eventhdlr = eventhdlr;
    2411
    2412 /* include primal heuristic */
    2415 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecShiftandpropagate, heurdata) );
    2416
    2417 assert(heur != NULL);
    2418
    2419 /* primal heuristic is safe to use in exact solving mode */
    2420 SCIPheurMarkExact(heur);
    2421
    2422 /* set non-NULL pointers to callback methods */
    2423 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyShiftandpropagate) );
    2424 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeShiftandpropagate) );
    2425 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitShiftandpropagate) );
    2426 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitShiftandpropagate) );
    2427
    2428 /* add shiftandpropagate primal heuristic parameters */
    2429 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nproprounds",
    2430 "The number of propagation rounds used for each propagation",
    2431 &heurdata->nproprounds, TRUE, DEFAULT_NPROPROUNDS, -1, 1000, NULL, NULL) );
    2432 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/relax", "Should continuous variables be relaxed?",
    2433 &heurdata->relax, TRUE, DEFAULT_RELAX, NULL, NULL) );
    2434 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/probing", "Should domains be reduced by probing?",
    2435 &heurdata->probing, TRUE, DEFAULT_PROBING, NULL, NULL) );
    2436 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/onlywithoutsol",
    2437 "Should heuristic only be executed if no primal solution was found, yet?",
    2438 &heurdata->onlywithoutsol, TRUE, DEFAULT_ONLYWITHOUTSOL, NULL, NULL) );
    2439 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/cutoffbreaker", "The number of cutoffs before heuristic stops",
    2440 &heurdata->cutoffbreaker, TRUE, DEFAULT_CUTOFFBREAKER, -1, 1000000, NULL, NULL) );
    2441 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/sortkey",
    2442 "the key for variable sorting: (n)orms down, norms (u)p, (v)iolations down, viola(t)ions up, or (r)andom",
    2443 &heurdata->sortkey, TRUE, DEFAULT_SORTKEY, SORTKEYS, NULL, NULL) );
    2444 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/sortvars", "Should variables be sorted for the heuristic?",
    2445 &heurdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL));
    2446 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/collectstats", "should variable statistics be collected during probing?",
    2447 &heurdata->collectstats, TRUE, DEFAULT_COLLECTSTATS, NULL, NULL) );
    2448 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/stopafterfeasible",
    2449 "Should the heuristic stop calculating optimal shift values when no more rows are violated?",
    2450 &heurdata->stopafterfeasible, TRUE, DEFAULT_STOPAFTERFEASIBLE, NULL, NULL) );
    2451 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/preferbinaries",
    2452 "Should binary variables be shifted first?",
    2453 &heurdata->preferbinaries, TRUE, DEFAULT_PREFERBINARIES, NULL, NULL) );
    2454 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/nozerofixing",
    2455 "should variables with a zero shifting value be delayed instead of being fixed?",
    2456 &heurdata->nozerofixing, TRUE, DEFAULT_NOZEROFIXING, NULL, NULL) );
    2457 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/fixbinlocks",
    2458 "should binary variables with no locks in one direction be fixed to that direction?",
    2459 &heurdata->fixbinlocks, TRUE, DEFAULT_FIXBINLOCKS, NULL, NULL) );
    2460 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/binlocksfirst",
    2461 "should binary variables with no locks be preferred in the ordering?",
    2462 &heurdata->binlocksfirst, TRUE, DEFAULT_BINLOCKSFIRST, NULL, NULL) );
    2463 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/normalize",
    2464 "should coefficients be normalized by max row coeff for col norm?",
    2465 &heurdata->normalize, TRUE, DEFAULT_NORMALIZE, NULL, NULL) );
    2466 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/updateweights",
    2467 "should row weight be increased every time the row is violated?",
    2468 &heurdata->updateweights, TRUE, DEFAULT_UPDATEWEIGHTS, NULL, NULL) );
    2469 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/impliscontinuous",
    2470 "should implicit integer variables be treated as continuous variables?",
    2471 &heurdata->impliscontinuous, TRUE, DEFAULT_IMPLISCONTINUOUS, NULL, NULL) );
    2472 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/shiftandpropagate/selectbest",
    2473 "should the heuristic choose the best candidate in every round? (set to FALSE for static order)?",
    2474 &heurdata->selectbest, TRUE, DEFAULT_SELECTBEST, NULL, NULL) );
    2475 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxcutoffquot",
    2476 "maximum percentage of allowed cutoffs before stopping the heuristic",
    2477 &heurdata->maxcutoffquot, TRUE, DEFAULT_MAXCUTOFFQUOT, 0.0, 2.0, NULL, NULL) );
    2478 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingratelp",
    2479 "minimum fixing rate over all variables (including continuous) to solve LP",
    2480 &heurdata->minfixingratelp, TRUE, DEFAULT_MINFIXINGRATELP, 0.0, 1.0, NULL, NULL) );
    2481
    2482 return SCIP_OKAY;
    2483}
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    SCIP_Real * r
    Definition: circlepacking.c:59
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_MAXTREEDEPTH
    Definition: def.h:306
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define ABS(x)
    Definition: def.h:225
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIPABORT()
    Definition: def.h:336
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    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 SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:167
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
    Definition: misc.c:10264
    SCIP_RETCODE SCIPincludeHeurShiftandpropagate(SCIP *scip)
    SCIP_Bool SCIPisCertified(SCIP *scip)
    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_Bool SCIPcolIsImpliedIntegral(SCIP_COL *col)
    Definition: lp.c:17466
    SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
    Definition: lp.c:17555
    SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
    Definition: lp.c:17545
    int SCIPcolGetNLPNonz(SCIP_COL *col)
    Definition: lp.c:17534
    SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
    Definition: lp.c:17509
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:406
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:122
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_RETCODE SCIPflushLP(SCIP *scip)
    Definition: scip_lp.c:154
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
    Definition: scip_lp.c:130
    SCIP_Bool SCIPisLPConstructed(SCIP *scip)
    Definition: scip_lp.c:105
    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 SCIPgetNUnfixedLPCols(SCIP *scip)
    Definition: scip_lp.c:554
    int SCIPgetNLPCols(SCIP *scip)
    Definition: scip_lp.c:533
    SCIP_RETCODE SCIPwriteLP(SCIP *scip, const char *filename)
    Definition: scip_lp.c:907
    SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
    Definition: scip_lp.c:673
    #define SCIPfreeBuffer(scip, ptr)
    Definition: scip_mem.h:134
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBuffer(scip, ptr)
    Definition: scip_mem.h:122
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryNull(scip, ptr)
    Definition: scip_mem.h:109
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    int SCIPgetProbingDepth(SCIP *scip)
    Definition: scip_probing.c:199
    SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_probing.c:346
    char * SCIPsnprintfProbingStats(SCIP *scip, char *strbuf, int len)
    SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_probing.c:302
    SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
    Definition: scip_probing.c:581
    SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
    Definition: scip_probing.c:226
    SCIP_RETCODE SCIPstartProbing(SCIP *scip)
    Definition: scip_probing.c:120
    SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
    Definition: scip_probing.c:166
    SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
    Definition: scip_probing.c:825
    SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
    Definition: scip_probing.c:419
    SCIP_RETCODE SCIPendProbing(SCIP *scip)
    Definition: scip_probing.c:261
    SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1886
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    int SCIProwGetNLPNonz(SCIP_ROW *row)
    Definition: lp.c:17621
    int SCIProwGetLPPos(SCIP_ROW *row)
    Definition: lp.c:17895
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2351
    SCIP_RETCODE SCIPtrySol(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:4017
    SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1293
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1890
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1569
    void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
    Definition: sol.c:4319
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_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 SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPepsilon(SCIP *scip)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
    Definition: scip_tree.c:436
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23715
    void SCIPdisableVarHistory(SCIP *scip)
    Definition: scip_var.c:11102
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    void SCIPenableVarHistory(SCIP *scip)
    Definition: scip_var.c:11083
    SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
    Definition: var.c:23738
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    void SCIPsortDownIntInt(int *intarray1, int *intarray2, int len)
    void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
    void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
    void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
    #define DEFAULT_ONLYWITHOUTSOL
    #define DEFAULT_NORMALIZE
    static void relaxVar(SCIP *scip, SCIP_VAR *var, CONSTRAINTMATRIX *matrix)
    #define DEFAULT_RELAX
    static void transformVariable(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int colpos)
    static SCIP_RETCODE getOptimalShiftingValue(SCIP *scip, CONSTRAINTMATRIX *matrix, int varindex, int direction, int *rowweights, SCIP_Real *steps, int *violationchange, SCIP_Real *beststep, int *rowviolations)
    static void getRowData(CONSTRAINTMATRIX *matrix, int rowindex, SCIP_Real **valpointer, SCIP_Real *lhs, SCIP_Real *rhs, int **indexpointer, int *nrowvals)
    static SCIP_DECL_SORTPTRCOMP(heurSortColsShiftandpropagate)
    static void checkRowViolation(SCIP *scip, CONSTRAINTMATRIX *matrix, int rowindex, int *violatedrows, int *violatedrowpos, int *nviolatedrows, int *rowweights, SCIP_Bool updateweights)
    #define DEFAULT_MINFIXINGRATELP
    static SCIP_Bool colIsDiscrete(SCIP_COL *col, SCIP_Bool impliscontinuous)
    #define HEUR_TIMING
    #define DEFAULT_PROPBREAKER
    #define DEFAULT_IMPLISCONTINUOUS
    #define DEFAULT_PREFERBINARIES
    #define HEUR_FREQOFS
    #define DEFAULT_NPROPROUNDS
    static SCIP_DECL_HEUREXEC(heurExecShiftandpropagate)
    #define HEUR_DESC
    #define DEFAULT_FIXBINLOCKS
    @ TRANSFORMSTATUS_NONE
    @ TRANSFORMSTATUS_FREE
    @ TRANSFORMSTATUS_NEG
    @ TRANSFORMSTATUS_LB
    static SCIP_DECL_EVENTEXEC(eventExecShiftandpropagate)
    static void freeMatrix(SCIP *scip, CONSTRAINTMATRIX **matrix)
    #define DEFAULT_SELECTBEST
    #define DEFAULT_BINLOCKSFIRST
    static SCIP_RETCODE updateTransformation(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int varindex, SCIP_Real lb, SCIP_Real ub, int *violatedrows, int *violatedrowpos, int *nviolatedrows)
    static SCIP_DECL_HEUREXIT(heurExitShiftandpropagate)
    #define DEFAULT_SORTVARS
    #define SORTKEYS
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    #define DEFAULT_MAXCUTOFFQUOT
    #define DEFAULT_CUTOFFBREAKER
    enum TransformStatus TRANSFORMSTATUS
    #define DEFAULT_WEIGHT_INEQUALITY
    #define HEUR_NAME
    #define DEFAULT_NOZEROFIXING
    static SCIP_DECL_HEURCOPY(heurCopyShiftandpropagate)
    #define DEFAULT_RANDSEED
    static SCIP_DECL_HEURINIT(heurInitShiftandpropagate)
    #define DEFAULT_SORTKEY
    static void checkViolations(SCIP *scip, CONSTRAINTMATRIX *matrix, int colidx, int *violatedrows, int *violatedrowpos, int *nviolatedrows, int *rowweights, SCIP_Bool updateweights)
    #define DEFAULT_UPDATEWEIGHTS
    #define DEFAULT_COLLECTSTATS
    #define EVENTHDLR_DESC
    static SCIP_Real retransformVariable(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_VAR *var, int varindex, SCIP_Real solvalue)
    static SCIP_Bool varIsDiscrete(SCIP_VAR *var, SCIP_Bool impliscontinuous)
    struct ConstraintMatrix CONSTRAINTMATRIX
    #define HEUR_FREQ
    #define DEFAULT_WEIGHT_EQUALITY
    static void getColumnData(CONSTRAINTMATRIX *matrix, int colindex, SCIP_Real **valpointer, int **indexpointer, int *ncolvals)
    #define HEUR_USESSUBSCIP
    #define EVENTHDLR_NAME
    #define DEFAULT_STOPAFTERFEASIBLE
    static SCIP_DECL_HEURFREE(heurFreeShiftandpropagate)
    #define DEFAULT_PROBING
    static SCIP_RETCODE initMatrix(SCIP *scip, CONSTRAINTMATRIX *matrix, SCIP_HEURDATA *heurdata, int *colposs, int *nmaxrows, SCIP_Bool relax, SCIP_Bool *initialized, SCIP_Bool *infeasible)
    #define EVENTTYPE_SHIFTANDPROPAGATE
    preroot heuristic that alternatingly fixes variables and propagates domains
    memory allocation routines
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    public methods for managing events
    public methods for primal heuristics
    public methods for LP management
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPstatisticMessage
    Definition: pub_message.h:123
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPstatistic(x)
    Definition: pub_message.h:120
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for primal CIP solutions
    public methods for problem variables
    public methods for certified solving
    public methods for event handler plugins and event handlers
    public methods for exact solving
    general public methods
    public methods for primal heuristic plugins and divesets
    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 the probing mode
    public methods for random numbers
    public methods for solutions
    public methods for querying solving statistics
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
    Definition: type_event.h:160
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    enum SCIP_LPSolStat SCIP_LPSOLSTAT
    Definition: type_lp.h:52
    @ SCIP_LPSOLSTAT_NOTSOLVED
    Definition: type_lp.h:43
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_VERBLEVEL_FULL
    Definition: type_message.h:62
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    #define SCIP_DEPRECATED_VARTYPE_IMPLINT
    Definition: type_var.h:79
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73