SCIP

    Solving Constraint Integer Programs

    presol_dualcomp.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 presol_dualcomp.c
    26 * @ingroup DEFPLUGINS_PRESOL
    27 * @brief dual compensation presolver
    28 * @author Dieter Weninger
    29 *
    30 * This presolver looks for variables with
    31 * i) objcoef >= 0 and exactly one downlock
    32 * ii) objcoef <= 0 and exactly one uplock
    33 * and fixes the variable in case i) at the lower bound and in case ii) at the
    34 * upper bound if a combination of singleton continuous variables can compensate
    35 * the downlock in case i) and the uplock in case ii).
    36 */
    37
    38/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    39
    42#include "scip/pub_matrix.h"
    43#include "scip/pub_message.h"
    44#include "scip/pub_presol.h"
    45#include "scip/pub_var.h"
    46#include "scip/scip_general.h"
    47#include "scip/scip_mem.h"
    48#include "scip/scip_message.h"
    49#include "scip/scip_nlp.h"
    50#include "scip/scip_numerics.h"
    51#include "scip/scip_param.h"
    52#include "scip/scip_presol.h"
    53#include "scip/scip_pricer.h"
    54#include "scip/scip_prob.h"
    55#include "scip/scip_probing.h"
    56#include "scip/scip_var.h"
    57
    58
    59#define PRESOL_NAME "dualcomp"
    60#define PRESOL_DESC "compensate single up-/downlocks by singleton continuous variables"
    61
    62/* we need singleton continuous variables for the lock compensation,
    63 * thus it is presumably a good idea to call this presolver before stuffing, which
    64 * fixes singleton continuous variables
    65 */
    66#define PRESOL_PRIORITY -50 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
    67#define PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
    68#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
    69
    70#define DEFAULT_COMP_ONLY_DIS_VARS FALSE /**< should only discrete variables be compensated? */
    71
    72/*
    73 * Data structures
    74 */
    75
    76/** control parameters */
    77struct SCIP_PresolData
    78{
    79 SCIP_Bool componlydisvars; /**< flag indicating if only discrete variables should be compensated */
    80};
    81
    82/** type of fixing direction */
    84{
    85 FIXATLB = -1, /**< fix variable at lower bound */
    86 NOFIX = 0, /**< do not fix variable */
    87 FIXATUB = 1 /**< fix variable at upper bound */
    88};
    90
    91/** type of variable lock compensation */
    93{
    96};
    98
    99/*
    100 * Local methods
    101 */
    102
    103/** try to compensate a variable with a single opposite lock
    104 by using singleton continuous variables */
    105static
    107 SCIP* scip, /**< SCIP main data structure */
    108 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
    109 int col, /**< variable fixing candidate */
    110 int row, /**< row index with opposite lock */
    111 SCIP_Real val, /**< value of fixing candidate in the opposite lock constraint */
    112 SCIP_Bool twosides, /**< flag indicating that two sides are present */
    113 LOCKCOMPENSATION compensation, /**< type of lock compensation */
    114 FIXINGDIRECTION* varstofix, /**< array holding fixing information */
    115 int* nfixings /**< number of possible fixings */
    116 )
    117{
    118 SCIP_Real* valpnt;
    119 int* rowpnt;
    120 int* rowend;
    121 SCIP_VAR* var;
    122 int colidx;
    123 SCIP_Real coef;
    124 SCIP_Real lhs;
    125 SCIP_Real delta;
    126 SCIP_Bool trytofix;
    127 SCIP_Real lb;
    128 SCIP_Real ub;
    129 SCIP_Bool deltaisinf;
    130 SCIP_Real ratio;
    131 SCIP_Bool multrowbyminusone;
    132 SCIP_Bool singleton;
    133 SCIP_Real offset;
    134
    135 assert(scip != NULL);
    136 assert(matrix != NULL);
    137 assert(0 <= col && col < SCIPmatrixGetNColumns(matrix));
    138 assert(0 <= row && row < SCIPmatrixGetNRows(matrix));
    139 assert(compensation == COMPENSATE_DOWNLOCK || compensation == COMPENSATE_UPLOCK);
    140 assert(varstofix != NULL);
    141 assert(nfixings != NULL);
    142
    143 /* the variable for compensation should not be a compensation variable itself */
    144 assert(SCIPmatrixGetColNNonzs(matrix, col) != 1 || SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, col)));
    145
    146 /* try lock compensation only if minimum one singleton continuous variable is present */
    147 singleton = FALSE;
    148 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    149 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
    150 for( ; rowpnt < rowend; rowpnt++ )
    151 {
    152 var = SCIPmatrixGetVar(matrix, *rowpnt);
    153
    154 if( SCIPmatrixGetColNNonzs(matrix, *rowpnt) == 1 && !SCIPvarIsIntegral(var)
    157 {
    158 /* minimal one valid compensation variable is present in this row */
    159 singleton = TRUE;
    160 break;
    161 }
    162 }
    163
    164 /* return if no compensation variable is available */
    165 if( !singleton )
    166 return SCIP_OKAY;
    167
    168 /* we perform the following transformations afterwards:
    169 *
    170 * lhs <= a1 x1 + a2 x2 + ... an xn <= rhs
    171 * with a1, a2, ..., an >= 0.
    172 *
    173 * for the downlock case we multiply the constraint in thought by (-1)
    174 * if the corresponding coefficient is negative.
    175 *
    176 * we attribute the uplock case to the downlock case by multiplying
    177 * in thought the corresponding column by (-1).
    178 */
    179 multrowbyminusone = FALSE;
    180 if( compensation == COMPENSATE_DOWNLOCK )
    181 {
    182 if( SCIPisLT(scip,val,0.0) )
    183 multrowbyminusone = TRUE;
    184 }
    185 else
    186 {
    187 assert(compensation == COMPENSATE_UPLOCK);
    188
    189 /* in the uplock case we multiply the column in thought by (-1) and
    190 * thus we need to multiply the constraint by (-1) to get a positive coefficient
    191 */
    192 if( SCIPisGT(scip,val,0.0) )
    193 multrowbyminusone = TRUE;
    194 }
    195
    196 /* we need the objective coefficient and constraint coefficient ratio
    197 * to later preserve optimality.
    198 * further we need to consider multiplications of the constraint by (-1).
    199 * for ranged rows and equalities we switch to the rhs.
    200 */
    201 lhs = SCIPmatrixGetRowLhs(matrix, row);
    202 ratio = SCIPvarGetObj( SCIPmatrixGetVar(matrix,col) ) / val;
    203 if( multrowbyminusone )
    204 {
    205 if( twosides )
    206 lhs = -SCIPmatrixGetRowRhs(matrix, row);
    207 else
    208 lhs = -lhs;
    209
    210 ratio = -ratio;
    211 }
    212
    213 offset = 0.0;
    214 trytofix = TRUE;
    215 delta = 0;
    216 deltaisinf = FALSE;
    217
    218 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
    219 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
    220 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
    221
    222 for( ; rowpnt < rowend; rowpnt++, valpnt++ )
    223 {
    224 colidx = *rowpnt;
    225 coef = *valpnt;
    226 var = SCIPmatrixGetVar(matrix, colidx);
    227 lb = SCIPvarGetLbGlobal(var);
    228 ub = SCIPvarGetUbGlobal(var);
    229
    230 if( colidx == col )
    231 {
    232 /* this is the variable which we want to compensate */
    233
    234 if( compensation == COMPENSATE_DOWNLOCK )
    235 {
    236 if( SCIPisInfinity(scip, -lb) )
    237 {
    238 trytofix = FALSE;
    239 break;
    240 }
    241 else
    242 {
    243 if( multrowbyminusone )
    244 offset += (-coef) * lb;
    245 else
    246 offset += coef * lb;
    247 }
    248 }
    249 else
    250 {
    251 if( SCIPisInfinity(scip, ub) )
    252 {
    253 trytofix = FALSE;
    254 break;
    255 }
    256 else
    257 {
    258 /* for the uplock case we have opposed sign for the coefficient as
    259 * in the downlock case.
    260 * the multiplication of the column results in swapping the negative bounds.
    261 */
    262 if( multrowbyminusone )
    263 offset += coef * (-ub);
    264 else
    265 offset += (-coef) * (-ub);
    266 }
    267 }
    268 }
    269 else if( SCIPmatrixGetColNNonzs(matrix, colidx) == 1 && !SCIPvarIsIntegral(var)
    272 {
    273 /* this is singleton continuous variable and
    274 * thus a valid compensation candidate
    275 */
    276
    277 if( SCIPisLT(scip,coef,0.0) )
    278 {
    279 /* coef < 0 */
    280
    281 if( multrowbyminusone )
    282 {
    283 if( SCIPisInfinity(scip, -lb) )
    284 {
    285 trytofix = FALSE;
    286 break;
    287 }
    288
    289 /* we have a negative coefficient and the row is multiplied by (-1)
    290 * thus actually we have a positive coefficient
    291 */
    292 offset += (-coef) * lb;
    293
    294 /* only consider singleton continuous variables with a better or the same
    295 * obj/coef ratio for preserving optimality
    296 */
    297 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/(-coef), ratio) )
    298 {
    299 if( SCIPisInfinity(scip, ub) )
    300 {
    301 deltaisinf = TRUE;
    302 break;
    303 }
    304
    305 /* calculate the contribution to the compensation value */
    306 delta += (-coef) * (ub - lb);
    307 }
    308 }
    309 else
    310 {
    311 if( SCIPisInfinity(scip, ub) )
    312 {
    313 trytofix = FALSE;
    314 break;
    315 }
    316
    317 /* we have a negative coefficient and hence need to multiply the column by (-1).
    318 * this means the bounds swap and change the sign
    319 */
    320 offset += (-coef) * (-ub);
    321
    322 /* only consider singleton continuous variables with a better or the same
    323 * obj/coef ratio for preserving optimality
    324 */
    325 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/coef, ratio) )
    326 {
    327 if( SCIPisInfinity(scip, -lb) )
    328 {
    329 deltaisinf = TRUE;
    330 break;
    331 }
    332
    333 /* calculate the contribution to the compensation value */
    334 delta += (-coef) * (ub - lb);
    335 }
    336 }
    337 }
    338 else
    339 {
    340 /* coef >= 0 */
    341
    342 if( multrowbyminusone )
    343 {
    344 /* we have a positive or zero coefficient and the row is multiplied by (-1) */
    345 if( SCIPisInfinity(scip, ub) )
    346 {
    347 trytofix = FALSE;
    348 break;
    349 }
    350
    351 /* we have a positive or zero coefficient and multiply in thought the constraint
    352 * by (-1) thus we have actually a negative coefficient and multiply the column by (-1).
    353 * therefore the sign of the coefficient does not change but the bounds swap and change
    354 * the sign.
    355 */
    356 offset += coef * (-ub);
    357
    358 /* we have a positive or zero coefficient and multiply in thought the constraint
    359 * by (-1) which delivers the ratio.
    360 * a further multiplication of the column does not change anything.
    361 */
    362 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/(-coef), ratio) )
    363 {
    364 if( SCIPisInfinity(scip, -lb) )
    365 {
    366 deltaisinf = TRUE;
    367 break;
    368 }
    369
    370 /* calculate the contribution to the compensation value */
    371 delta += coef * (ub - lb);
    372 }
    373 }
    374 else
    375 {
    376 if( SCIPisInfinity(scip, -lb) )
    377 {
    378 trytofix = FALSE;
    379 break;
    380 }
    381
    382 /* we have positive coefficient and do not need to multiply anything by (-1) */
    383 offset += coef * lb;
    384
    385 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/coef, ratio) )
    386 {
    387 if( SCIPisInfinity(scip, ub) )
    388 {
    389 deltaisinf = TRUE;
    390 break;
    391 }
    392
    393 /* calculate the contribution to the compensation value */
    394 delta += coef * (ub - lb);
    395 }
    396 }
    397 }
    398 }
    399 else
    400 {
    401 /* remaining variables */
    402
    403 /* the reasons for the following signs are the same as for the singleton
    404 * continuous variables
    405 */
    406 if( SCIPisLT(scip,coef,0.0) )
    407 {
    408 if( multrowbyminusone )
    409 {
    410 if( SCIPisInfinity(scip, -lb) )
    411 {
    412 trytofix = FALSE;
    413 break;
    414 }
    415
    416 offset += (-coef) * lb;
    417 }
    418 else
    419 {
    420 if( SCIPisInfinity(scip, ub) )
    421 {
    422 trytofix = FALSE;
    423 break;
    424 }
    425
    426 offset += (-coef) * (-ub);
    427 }
    428 }
    429 else
    430 {
    431 if( multrowbyminusone )
    432 {
    433 if( SCIPisInfinity(scip, ub) )
    434 {
    435 trytofix = FALSE;
    436 break;
    437 }
    438
    439 offset += coef * (-ub);
    440 }
    441 else
    442 {
    443 if( SCIPisInfinity(scip, -lb) )
    444 {
    445 trytofix = FALSE;
    446 break;
    447 }
    448
    449 offset += coef * lb;
    450 }
    451 }
    452 }
    453 }
    454
    455 /* avoid fixings to infinite values or fixings of already fixed variables */
    456 if( trytofix && varstofix[col] == NOFIX)
    457 {
    458 /* feasibility is secured if the compensation value delta
    459 * is large enough to compensate the value lhs-offset
    460 */
    461 if( deltaisinf || SCIPisLE(scip, lhs-offset, delta) )
    462 {
    463 if( compensation == COMPENSATE_UPLOCK )
    464 {
    466 {
    467 varstofix[col] = FIXATUB;
    468 (*nfixings)++;
    469
    470#ifdef SCIP_MORE_DEBUG
    471 SCIPmatrixPrintRow(scip, matrix, row);
    472 SCIPdebugMsg(scip, "%s, bds=[%.2f,%.2f], obj=%.2f, nnonzs=%d, type=%s, fix=ub, %.1f <= %.1f\n",
    475 SCIPmatrixGetColNNonzs(matrix, col),
    476 SCIPvarGetType(SCIPmatrixGetVar(matrix, col))==SCIP_VARTYPE_CONTINUOUS ? "con" : "dis",
    477 lhs-offset, delta);
    478#endif
    479 }
    480 }
    481 else
    482 {
    484 {
    485 varstofix[col] = FIXATLB;
    486 (*nfixings)++;
    487
    488#ifdef SCIP_MORE_DEBUG
    489 SCIPmatrixPrintRow(scip, matrix, row);
    490 SCIPdebugMsg(scip, "%s, bds=[%.2f,%.2f], obj=%.2f, nnonzs=%d, type=%s, fix=lb, %.1f <= %.1f\n",
    493 SCIPmatrixGetColNNonzs(matrix, col),
    494 SCIPvarGetType(SCIPmatrixGetVar(matrix, col))==SCIP_VARTYPE_CONTINUOUS ? "con" : "dis",
    495 lhs-offset, delta);
    496#endif
    497 }
    498 }
    499 }
    500 }
    501
    502 return SCIP_OKAY;
    503}
    504
    505/*
    506 * Callback methods of presolver
    507 */
    508
    509/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    510static
    511SCIP_DECL_PRESOLCOPY(presolCopyDualcomp)
    512{ /*lint --e{715}*/
    513 assert(scip != NULL);
    514 assert(presol != NULL);
    515
    517
    518 /* call inclusion method of presolver */
    520
    521 return SCIP_OKAY;
    522}
    523
    524/** execution method of presolver */
    525static
    526SCIP_DECL_PRESOLEXEC(presolExecDualcomp)
    527{ /*lint --e{715}*/
    528 SCIP_PRESOLDATA* presoldata;
    529 SCIP_MATRIX* matrix;
    530 SCIP_Bool initialized;
    531 SCIP_Bool complete;
    532 SCIP_Bool infeasible;
    533
    534 assert(result != NULL);
    535 *result = SCIP_DIDNOTRUN;
    536
    538 return SCIP_OKAY;
    539
    541 return SCIP_OKAY;
    542
    543 /* don't run if no compensation variables are present */
    544 if( SCIPgetNContVars(scip) == 0 )
    545 return SCIP_OKAY;
    546
    548 return SCIP_OKAY;
    549
    550 *result = SCIP_DIDNOTFIND;
    551
    552 presoldata = SCIPpresolGetData(presol);
    553 assert(presoldata != NULL);
    554
    555 matrix = NULL;
    556
    557 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
    558 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
    559
    560 /* if infeasibility was detected during matrix creation, return here */
    561 if( infeasible )
    562 {
    563 if( initialized )
    564 SCIPmatrixFree(scip, &matrix);
    565
    566 *result = SCIP_CUTOFF;
    567 return SCIP_OKAY;
    568 }
    569
    570 /* we only work on pure MIPs currently */
    571 if( initialized && complete )
    572 {
    573 int ncols;
    574 int i;
    575 SCIP_Real* valpnt;
    576 int* colpnt;
    577 int* colend;
    578 int row;
    579 SCIP_VAR* var;
    580 SCIP_Bool inspect;
    581 SCIP_Real val;
    582 FIXINGDIRECTION* varstofix;
    583 int nfixings;
    584 SCIP_Real lhs;
    585 SCIP_Real rhs;
    586 SCIP_Bool twosides;
    587
    588 ncols = SCIPmatrixGetNColumns(matrix);
    589 nfixings = 0;
    590
    591 SCIP_CALL( SCIPallocBufferArray(scip, &varstofix, ncols) );
    592 BMSclearMemoryArray(varstofix, ncols);
    593
    594 for(i = 0; i < ncols; i++)
    595 {
    596 var = SCIPmatrixGetVar(matrix, i);
    597
    598 /* exclude compensation variables itself for compensation */
    599 if( !SCIPvarIsIntegral(var) && SCIPmatrixGetColNNonzs(matrix, i) == 1 )
    600 continue;
    601
    602 /* if requested exclude continuous variables for compensation */
    603 if( presoldata->componlydisvars && !SCIPvarIsIntegral(var) )
    604 continue;
    605
    606 /* verifiy that this variable has one uplock and that the uplocks are consistent */
    608 SCIPmatrixGetColNUplocks(matrix, i) == 1 &&
    609 SCIPisLE(scip, SCIPvarGetObj(var), 0.0) )
    610 {
    611 row = -1;
    612 val = 0.0;
    613 inspect = FALSE;
    614 twosides = FALSE;
    615 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
    616 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
    617 valpnt = SCIPmatrixGetColValPtr(matrix, i);
    618
    619 /* search row which causes the uplock */
    620 for( ; (colpnt < colend); colpnt++, valpnt++ )
    621 {
    622 row = *colpnt;
    623 val = *valpnt;
    624 lhs = SCIPmatrixGetRowLhs(matrix, row);
    625 rhs = SCIPmatrixGetRowRhs(matrix, row);
    626
    627 if( SCIPisEQ(scip, lhs, rhs) )
    628 {
    629 /* equation */
    630 inspect = TRUE;
    631 twosides = TRUE;
    632 break;
    633 }
    634 else if( SCIPmatrixIsRowRhsInfinity(matrix, row) )
    635 {
    636 /* >= */
    637 if( SCIPisLT(scip, val, 0.0) )
    638 {
    639 inspect = TRUE;
    640 break;
    641 }
    642 }
    643 else if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) )
    644 {
    645 /* ranged row */
    646 inspect = TRUE;
    647 twosides = TRUE;
    648 break;
    649 }
    650 }
    651
    652 assert(inspect);
    653
    654 if( inspect ) /*lint !e774*/
    655 {
    656 assert(row >= 0);
    657 assert(!SCIPisZero(scip, val));
    658
    659 /* try to fix variable i at the upper bound */
    660 SCIP_CALL( compensateVarLock(scip, matrix, i, row, val,
    661 twosides, COMPENSATE_UPLOCK, varstofix, &nfixings) );
    662 }
    663 }
    664 /* verifiy that this variable has one downlock and that the downlocks are consistent */
    665 else if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1 &&
    666 SCIPmatrixGetColNDownlocks(matrix, i) == 1 &&
    667 SCIPisGE(scip, SCIPvarGetObj(var), 0.0) )
    668 {
    669 row = -1;
    670 val = 0.0;
    671 inspect = FALSE;
    672 twosides = FALSE;
    673 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
    674 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
    675 valpnt = SCIPmatrixGetColValPtr(matrix, i);
    676
    677 /* search row which causes the downlock */
    678 for( ; (colpnt < colend); colpnt++, valpnt++ )
    679 {
    680 row = *colpnt;
    681 val = *valpnt;
    682 lhs = SCIPmatrixGetRowLhs(matrix, row);
    683 rhs = SCIPmatrixGetRowRhs(matrix, row);
    684
    685 if( SCIPisEQ(scip, lhs, rhs) )
    686 {
    687 /* equation */
    688 inspect = TRUE;
    689 twosides = TRUE;
    690 break;
    691 }
    692 else if( SCIPmatrixIsRowRhsInfinity(matrix, row) )
    693 {
    694 /* >= */
    695 if( SCIPisGT(scip, val, 0.0) )
    696 {
    697 inspect = TRUE;
    698 break;
    699 }
    700 }
    701 else if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) )
    702 {
    703 /* ranged row */
    704 inspect = TRUE;
    705 twosides = TRUE;
    706 break;
    707 }
    708 }
    709
    710 assert(inspect);
    711
    712 if( inspect ) /*lint !e774*/
    713 {
    714 assert(row >= 0);
    715 assert(!SCIPisZero(scip, val));
    716
    717 /* try to fix variable i at the lower bound */
    718 SCIP_CALL( compensateVarLock(scip, matrix, i, row, val,
    719 twosides, COMPENSATE_DOWNLOCK, varstofix, &nfixings) );
    720 }
    721 }
    722 }
    723
    724 if( nfixings > 0 )
    725 {
    726 int v;
    727 int oldnfixedvars;
    728 int numupperboundfixings;
    729 int numlowerboundfixings;
    730 int numcontinuousfixings;
    731 int numdiscretefixings;
    732
    733 oldnfixedvars = *nfixedvars;
    734 numupperboundfixings = 0;
    735 numlowerboundfixings = 0;
    736 numcontinuousfixings = 0;
    737 numdiscretefixings = 0;
    738
    739 /* look for fixable variables */
    740 for( v = ncols - 1; v >= 0; --v )
    741 {
    742 SCIP_Bool fixed;
    743
    744 var = SCIPmatrixGetVar(matrix, v);
    745
    746 if( varstofix[v] == FIXATLB )
    747 {
    748 SCIP_Real lb;
    749
    750 lb = SCIPvarGetLbGlobal(var);
    751
    752 /* avoid fixings to infinite values */
    753 assert(!SCIPisInfinity(scip, -lb));
    754
    755 SCIPdebugMsg(scip, "Fix variable %s at lower bound %.15g\n", SCIPvarGetName(var), lb);
    756
    757 /* fix at lower bound */
    758 SCIP_CALL( SCIPfixVar(scip, var, lb, &infeasible, &fixed) );
    759 if( infeasible )
    760 {
    761 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    762 *result = SCIP_CUTOFF;
    763
    764 break;
    765 }
    766 assert(fixed);
    767 (*nfixedvars)++;
    768 numlowerboundfixings++;
    769
    770 if( !SCIPvarIsIntegral(var) )
    771 numcontinuousfixings++;
    772 else
    773 numdiscretefixings++;
    774 }
    775 else if( varstofix[v] == FIXATUB )
    776 {
    777 SCIP_Real ub;
    778
    779 ub = SCIPvarGetUbGlobal(var);
    780
    781 /* avoid fixings to infinite values */
    782 assert(!SCIPisInfinity(scip, ub));
    783
    784 SCIPdebugMsg(scip, "Fix variable %s at upper bound %.15g\n", SCIPvarGetName(var), ub);
    785
    786 /* fix at upper bound */
    787 SCIP_CALL( SCIPfixVar(scip, var, ub, &infeasible, &fixed) );
    788 if( infeasible )
    789 {
    790 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    791 *result = SCIP_CUTOFF;
    792
    793 break;
    794 }
    795 assert(fixed);
    796 (*nfixedvars)++;
    797 numupperboundfixings++;
    798
    799 if( !SCIPvarIsIntegral(var) )
    800 numcontinuousfixings++;
    801 else
    802 numdiscretefixings++;
    803 }
    804 }
    805
    806 if( *result != SCIP_CUTOFF && *nfixedvars > oldnfixedvars )
    807 *result = SCIP_SUCCESS;
    808
    809 SCIPdebugMsg(scip, "### lbfixes: %d, ubfixes: %d, con: %d, dis: %d\n",
    810 numlowerboundfixings, numupperboundfixings,
    811 numcontinuousfixings, numdiscretefixings);
    812 }
    813
    814 SCIPfreeBufferArray(scip, &varstofix);
    815 }
    816
    817 SCIPmatrixFree(scip, &matrix);
    818
    819 return SCIP_OKAY;
    820}
    821
    822/*
    823 * presolver specific interface methods
    824 */
    825
    826/** destructor of presolver to free user data (called when SCIP is exiting) */
    827static
    828SCIP_DECL_PRESOLFREE(presolFreeDualcomp)
    829{ /*lint --e{715}*/
    830 SCIP_PRESOLDATA* presoldata;
    831
    832 /* free presolver data */
    833 presoldata = SCIPpresolGetData(presol);
    834 assert(presoldata != NULL);
    835
    836 SCIPfreeBlockMemory(scip, &presoldata);
    837 SCIPpresolSetData(presol, NULL);
    838
    839 return SCIP_OKAY;
    840}
    841
    842/** creates the dualcomp presolver and includes it in SCIP */
    844 SCIP* scip /**< SCIP data structure */
    845 )
    846{
    847 SCIP_PRESOLDATA* presoldata;
    848 SCIP_PRESOL* presol;
    849
    850 /* create dualcomp presolver data */
    851 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
    852
    853 /* include presolver */
    855 PRESOL_TIMING, presolExecDualcomp, presoldata) );
    856 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyDualcomp) );
    857 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeDualcomp) );
    858
    860 "presolving/dualcomp/componlydisvars",
    861 "should only discrete variables be compensated?",
    862 &presoldata->componlydisvars, FALSE, DEFAULT_COMP_ONLY_DIS_VARS, NULL, NULL) );
    863
    864 return SCIP_OKAY;
    865}
    #define NULL
    Definition: def.h:257
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPincludePresolDualcomp(SCIP *scip)
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Bool SCIPisNLPEnabled(SCIP *scip)
    Definition: scip_nlp.c:74
    void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
    Definition: presol.c:538
    SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
    Definition: presol.c:528
    SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLFREE((*presolfree)))
    Definition: scip_presol.c:164
    SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
    Definition: scip_presol.c:148
    SCIP_RETCODE SCIPincludePresolBasic(SCIP *scip, SCIP_PRESOL **presolptr, const char *name, const char *desc, int priority, int maxrounds, SCIP_PRESOLTIMING timing, SCIP_DECL_PRESOLEXEC((*presolexec)), SCIP_PRESOLDATA *presoldata)
    Definition: scip_presol.c:113
    const char * SCIPpresolGetName(SCIP_PRESOL *presol)
    Definition: presol.c:625
    int SCIPgetNActivePricers(SCIP *scip)
    Definition: scip_pricer.c:348
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(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_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4380
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    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 SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
    Definition: var.c:4322
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    int * SCIPmatrixGetColIdxPtr(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1873
    int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2013
    int SCIPmatrixGetColNDownlocks(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1941
    int SCIPmatrixGetColNNonzs(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1885
    SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2095
    int SCIPmatrixGetColNUplocks(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1929
    SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2047
    SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:1977
    SCIP_Real SCIPmatrixGetRowRhs(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2059
    SCIP_Real * SCIPmatrixGetColValPtr(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1861
    SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIP_MATRIX **matrixptr, SCIP_Bool onlyifcomplete, SCIP_Bool *initialized, SCIP_Bool *complete, SCIP_Bool *infeasible, int *naddconss, int *ndelconss, int *nchgcoefs, int *nchgbds, int *nfixedvars)
    Definition: matrix.c:703
    int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
    Definition: matrix.c:1897
    void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
    Definition: matrix.c:1348
    SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
    Definition: matrix.c:1953
    int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:2001
    void SCIPmatrixPrintRow(SCIP *scip, SCIP_MATRIX *matrix, int row)
    Definition: matrix.c:1425
    int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
    Definition: matrix.c:2037
    memory allocation routines
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    Fixingdirection
    enum Fixingdirection FIXINGDIRECTION
    #define DEFAULT_COMP_ONLY_DIS_VARS
    enum Lockcompensation LOCKCOMPENSATION
    Lockcompensation
    @ COMPENSATE_UPLOCK
    @ COMPENSATE_DOWNLOCK
    #define PRESOL_NAME
    @ FIXATUB
    @ FIXATLB
    @ NOFIX
    enum Fixingdirection FIXINGDIRECTION
    static SCIP_DECL_PRESOLEXEC(presolExecDualcomp)
    #define PRESOL_PRIORITY
    static SCIP_DECL_PRESOLCOPY(presolCopyDualcomp)
    static SCIP_DECL_PRESOLFREE(presolFreeDualcomp)
    #define PRESOL_MAXROUNDS
    #define PRESOL_TIMING
    static SCIP_RETCODE compensateVarLock(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Bool twosides, LOCKCOMPENSATION compensation, FIXINGDIRECTION *varstofix, int *nfixings)
    #define PRESOL_DESC
    dual compensation presolver
    public methods for matrix
    public methods for message output
    public methods for presolvers
    public methods for problem variables
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for nonlinear relaxation
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for presolving plugins
    public methods for variable pricer plugins
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for SCIP variables
    struct SCIP_PresolData SCIP_PRESOLDATA
    Definition: type_presol.h:51
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141