Scippy

    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-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file 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#include <string.h>
    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 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
    516
    517 /* call inclusion method of presolver */
    519
    520 return SCIP_OKAY;
    521}
    522
    523/** execution method of presolver */
    524static
    525SCIP_DECL_PRESOLEXEC(presolExecDualcomp)
    526{ /*lint --e{715}*/
    527 SCIP_PRESOLDATA* presoldata;
    528 SCIP_MATRIX* matrix;
    529 SCIP_Bool initialized;
    530 SCIP_Bool complete;
    531 SCIP_Bool infeasible;
    532
    533 assert(result != NULL);
    534 *result = SCIP_DIDNOTRUN;
    535
    537 return SCIP_OKAY;
    538
    540 return SCIP_OKAY;
    541
    542 /* don't run if no compensation variables are present */
    543 if( SCIPgetNContVars(scip) == 0 )
    544 return SCIP_OKAY;
    545
    547 return SCIP_OKAY;
    548
    549 *result = SCIP_DIDNOTFIND;
    550
    551 presoldata = SCIPpresolGetData(presol);
    552 assert(presoldata != NULL);
    553
    554 matrix = NULL;
    555
    556 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
    557 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
    558
    559 /* if infeasibility was detected during matrix creation, return here */
    560 if( infeasible )
    561 {
    562 if( initialized )
    563 SCIPmatrixFree(scip, &matrix);
    564
    565 *result = SCIP_CUTOFF;
    566 return SCIP_OKAY;
    567 }
    568
    569 /* we only work on pure MIPs currently */
    570 if( initialized && complete )
    571 {
    572 int ncols;
    573 int i;
    574 SCIP_Real* valpnt;
    575 int* colpnt;
    576 int* colend;
    577 int row;
    578 SCIP_VAR* var;
    579 SCIP_Bool inspect;
    580 SCIP_Real val;
    581 FIXINGDIRECTION* varstofix;
    582 int nfixings;
    583 SCIP_Real lhs;
    584 SCIP_Real rhs;
    585 SCIP_Bool twosides;
    586
    587 ncols = SCIPmatrixGetNColumns(matrix);
    588 nfixings = 0;
    589
    590 SCIP_CALL( SCIPallocBufferArray(scip, &varstofix, ncols) );
    591 BMSclearMemoryArray(varstofix, ncols);
    592
    593 for(i = 0; i < ncols; i++)
    594 {
    595 var = SCIPmatrixGetVar(matrix, i);
    596
    597 /* exclude compensation variables itself for compensation */
    598 if( !SCIPvarIsIntegral(var) && SCIPmatrixGetColNNonzs(matrix, i) == 1 )
    599 continue;
    600
    601 /* if requested exclude continuous variables for compensation */
    602 if( presoldata->componlydisvars && !SCIPvarIsIntegral(var) )
    603 continue;
    604
    605 /* verifiy that this variable has one uplock and that the uplocks are consistent */
    607 SCIPmatrixGetColNUplocks(matrix, i) == 1 &&
    608 SCIPisLE(scip, SCIPvarGetObj(var), 0.0) )
    609 {
    610 row = -1;
    611 val = 0.0;
    612 inspect = FALSE;
    613 twosides = FALSE;
    614 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
    615 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
    616 valpnt = SCIPmatrixGetColValPtr(matrix, i);
    617
    618 /* search row which causes the uplock */
    619 for( ; (colpnt < colend); colpnt++, valpnt++ )
    620 {
    621 row = *colpnt;
    622 val = *valpnt;
    623 lhs = SCIPmatrixGetRowLhs(matrix, row);
    624 rhs = SCIPmatrixGetRowRhs(matrix, row);
    625
    626 if( SCIPisEQ(scip, lhs, rhs) )
    627 {
    628 /* equation */
    629 inspect = TRUE;
    630 twosides = TRUE;
    631 break;
    632 }
    633 else if( SCIPmatrixIsRowRhsInfinity(matrix, row) )
    634 {
    635 /* >= */
    636 if( SCIPisLT(scip, val, 0.0) )
    637 {
    638 inspect = TRUE;
    639 break;
    640 }
    641 }
    642 else if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) )
    643 {
    644 /* ranged row */
    645 inspect = TRUE;
    646 twosides = TRUE;
    647 break;
    648 }
    649 }
    650
    651 assert(inspect);
    652
    653 if( inspect ) /*lint !e774*/
    654 {
    655 assert(row >= 0);
    656 assert(!SCIPisZero(scip, val));
    657
    658 /* try to fix variable i at the upper bound */
    659 SCIP_CALL( compensateVarLock(scip, matrix, i, row, val,
    660 twosides, COMPENSATE_UPLOCK, varstofix, &nfixings) );
    661 }
    662 }
    663 /* verifiy that this variable has one downlock and that the downlocks are consistent */
    664 else if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1 &&
    665 SCIPmatrixGetColNDownlocks(matrix, i) == 1 &&
    666 SCIPisGE(scip, SCIPvarGetObj(var), 0.0) )
    667 {
    668 row = -1;
    669 val = 0.0;
    670 inspect = FALSE;
    671 twosides = FALSE;
    672 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
    673 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
    674 valpnt = SCIPmatrixGetColValPtr(matrix, i);
    675
    676 /* search row which causes the downlock */
    677 for( ; (colpnt < colend); colpnt++, valpnt++ )
    678 {
    679 row = *colpnt;
    680 val = *valpnt;
    681 lhs = SCIPmatrixGetRowLhs(matrix, row);
    682 rhs = SCIPmatrixGetRowRhs(matrix, row);
    683
    684 if( SCIPisEQ(scip, lhs, rhs) )
    685 {
    686 /* equation */
    687 inspect = TRUE;
    688 twosides = TRUE;
    689 break;
    690 }
    691 else if( SCIPmatrixIsRowRhsInfinity(matrix, row) )
    692 {
    693 /* >= */
    694 if( SCIPisGT(scip, val, 0.0) )
    695 {
    696 inspect = TRUE;
    697 break;
    698 }
    699 }
    700 else if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) )
    701 {
    702 /* ranged row */
    703 inspect = TRUE;
    704 twosides = TRUE;
    705 break;
    706 }
    707 }
    708
    709 assert(inspect);
    710
    711 if( inspect ) /*lint !e774*/
    712 {
    713 assert(row >= 0);
    714 assert(!SCIPisZero(scip, val));
    715
    716 /* try to fix variable i at the lower bound */
    717 SCIP_CALL( compensateVarLock(scip, matrix, i, row, val,
    718 twosides, COMPENSATE_DOWNLOCK, varstofix, &nfixings) );
    719 }
    720 }
    721 }
    722
    723 if( nfixings > 0 )
    724 {
    725 int v;
    726 int oldnfixedvars;
    727 int numupperboundfixings;
    728 int numlowerboundfixings;
    729 int numcontinuousfixings;
    730 int numdiscretefixings;
    731
    732 oldnfixedvars = *nfixedvars;
    733 numupperboundfixings = 0;
    734 numlowerboundfixings = 0;
    735 numcontinuousfixings = 0;
    736 numdiscretefixings = 0;
    737
    738 /* look for fixable variables */
    739 for( v = ncols - 1; v >= 0; --v )
    740 {
    741 SCIP_Bool fixed;
    742
    743 var = SCIPmatrixGetVar(matrix, v);
    744
    745 if( varstofix[v] == FIXATLB )
    746 {
    747 SCIP_Real lb;
    748
    749 lb = SCIPvarGetLbGlobal(var);
    750
    751 /* avoid fixings to infinite values */
    752 assert(!SCIPisInfinity(scip, -lb));
    753
    754 SCIPdebugMsg(scip, "Fix variable %s at lower bound %.15g\n", SCIPvarGetName(var), lb);
    755
    756 /* fix at lower bound */
    757 SCIP_CALL( SCIPfixVar(scip, var, lb, &infeasible, &fixed) );
    758 if( infeasible )
    759 {
    760 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    761 *result = SCIP_CUTOFF;
    762
    763 break;
    764 }
    765 assert(fixed);
    766 (*nfixedvars)++;
    767 numlowerboundfixings++;
    768
    769 if( !SCIPvarIsIntegral(var) )
    770 numcontinuousfixings++;
    771 else
    772 numdiscretefixings++;
    773 }
    774 else if( varstofix[v] == FIXATUB )
    775 {
    776 SCIP_Real ub;
    777
    778 ub = SCIPvarGetUbGlobal(var);
    779
    780 /* avoid fixings to infinite values */
    781 assert(!SCIPisInfinity(scip, ub));
    782
    783 SCIPdebugMsg(scip, "Fix variable %s at upper bound %.15g\n", SCIPvarGetName(var), ub);
    784
    785 /* fix at upper bound */
    786 SCIP_CALL( SCIPfixVar(scip, var, ub, &infeasible, &fixed) );
    787 if( infeasible )
    788 {
    789 SCIPdebugMsg(scip, " -> infeasible fixing\n");
    790 *result = SCIP_CUTOFF;
    791
    792 break;
    793 }
    794 assert(fixed);
    795 (*nfixedvars)++;
    796 numupperboundfixings++;
    797
    798 if( !SCIPvarIsIntegral(var) )
    799 numcontinuousfixings++;
    800 else
    801 numdiscretefixings++;
    802 }
    803 }
    804
    805 if( *result != SCIP_CUTOFF && *nfixedvars > oldnfixedvars )
    806 *result = SCIP_SUCCESS;
    807
    808 SCIPdebugMsg(scip, "### lbfixes: %d, ubfixes: %d, con: %d, dis: %d\n",
    809 numlowerboundfixings, numupperboundfixings,
    810 numcontinuousfixings, numdiscretefixings);
    811 }
    812
    813 SCIPfreeBufferArray(scip, &varstofix);
    814 }
    815
    816 SCIPmatrixFree(scip, &matrix);
    817
    818 return SCIP_OKAY;
    819}
    820
    821/*
    822 * presolver specific interface methods
    823 */
    824
    825/** destructor of presolver to free user data (called when SCIP is exiting) */
    826static
    827SCIP_DECL_PRESOLFREE(presolFreeDualcomp)
    828{ /*lint --e{715}*/
    829 SCIP_PRESOLDATA* presoldata;
    830
    831 /* free presolver data */
    832 presoldata = SCIPpresolGetData(presol);
    833 assert(presoldata != NULL);
    834
    835 SCIPfreeBlockMemory(scip, &presoldata);
    836 SCIPpresolSetData(presol, NULL);
    837
    838 return SCIP_OKAY;
    839}
    840
    841/** creates the dualcomp presolver and includes it in SCIP */
    843 SCIP* scip /**< SCIP data structure */
    844 )
    845{
    846 SCIP_PRESOLDATA* presoldata;
    847 SCIP_PRESOL* presol;
    848
    849 /* create dualcomp presolver data */
    850 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
    851
    852 /* include presolver */
    854 PRESOL_TIMING, presolExecDualcomp, presoldata) );
    855 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyDualcomp) );
    856 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeDualcomp) );
    857
    859 "presolving/dualcomp/componlydisvars",
    860 "should only discrete variables be compensated?",
    861 &presoldata->componlydisvars, FALSE, DEFAULT_COMP_ONLY_DIS_VARS, NULL, NULL) );
    862
    863 return SCIP_OKAY;
    864}
    #define NULL
    Definition: def.h:248
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    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:4386
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23490
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    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:4328
    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
    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