Scippy

    SCIP

    Solving Constraint Integer Programs

    lpexact_bounding.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 lpexact_bounding.c
    26 * @brief safe exact rational bounding methods
    27 * @author Leon Eifler
    28 * @author Kati Wolter
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32#include <stdio.h>
    33#include <assert.h>
    34
    35#include "lpi/lpi.h"
    36#include "lpiexact/lpiexact.h"
    37#ifdef SCIP_WITH_EXACTSOLVE
    38#include "rectlu/rectlu.h"
    39#endif
    41#include "scip/pub_message.h"
    42#include "scip/pub_misc.h"
    43#include "scip/pub_var.h"
    44#include "scip/clock.h"
    45#include "scip/lp.h"
    46#include "scip/lpexact.h"
    47#include "scip/prob.h"
    48#include "scip/rational.h"
    49#include "scip/rationalgmp.h"
    51#include "scip/scip_message.h"
    52#include "scip/scip_prob.h"
    53#include "scip/scip_tree.h"
    54#include "scip/sepastoreexact.h"
    55#include "scip/set.h"
    56#include "scip/stat.h"
    57#include "scip/struct_lpexact.h"
    58#include "scip/struct_scip.h"
    59#include "scip/struct_set.h"
    60#include "scip/primal.h"
    61
    62#ifdef SCIP_WITH_BOOST
    63
    64#define PSBIGM 100LL
    65
    66/** checks if number is a power of two (negative numbers are reported as false);
    67 *
    68 * Explanation: any number that is a power of two is 1000...00 in binary representation.
    69 * That means that n & (n - 1) is 10000 % 01111 == 0. It is easy to prove that this does
    70 * not hold for any other number.
    71 */
    72static
    73bool isPowerOfTwo(
    74 int n /**< the number to check */
    75 )
    76{
    77 return (n > 0) && ((n & (n - 1)) == 0);
    78}
    79
    80/** checks if floating point lp is integer feasible */
    81static
    82SCIP_Bool fpLPisIntFeasible(
    83 SCIP_LP* lp, /**< LP data structure */
    84 SCIP_SET* set /**< global SCIP settings */
    85 )
    86{
    87 SCIP_Real primsol;
    88 SCIP_Bool feasible;
    89 SCIP_Real frac;
    90 int i;
    91
    92 assert(SCIPlpIsSolved(lp));
    93
    94 feasible = TRUE;
    95 for( i = 0; i < lp->ncols && feasible; i++ )
    96 {
    97 SCIP_COL* col;
    98 col = lp->cols[i];
    100 continue;
    101
    102 /* we can't use SCIPsetIsIntegral since we have to check here in the same way as in SCIPcalcBranchCands() */
    103 primsol = SCIPcolGetPrimsol(col);
    104 frac = SCIPsetFeasFrac(set, primsol);
    105 if( !SCIPsetIsFeasFracIntegral(set, frac) )
    106 {
    107 feasible = FALSE;
    108 break;
    109 }
    110 }
    111
    112 return feasible;
    113}
    114
    115#ifdef SCIP_WITH_GMP
    116#ifdef SCIP_WITH_EXACTSOLVE
    117/** helper method, compute number of nonzeros in lp */
    118static
    119int getNNonz(
    120 SCIP_LPEXACT* lpexact /**< the exact lp */
    121 )
    122{
    123 int ret = 0;
    124
    125 assert(lpexact != NULL);
    126
    127 for( int i = 0; i < lpexact->nrows; ++i )
    128 ret+= lpexact->rows[i]->len;
    129
    130 return ret;
    131}
    132#endif
    133
    134/** subroutine of constructProjectShiftData(); chooses which columns of the dual matrix are designated as set S, used
    135 * for projections
    136 */
    137static
    138SCIP_RETCODE projectShiftChooseDualSubmatrix(
    139 SCIP_LP* lp, /**< LP data */
    140 SCIP_LPEXACT* lpexact, /**< exact LP data */
    141 SCIP_SET* set, /**< scip settings */
    142 SCIP_STAT* stat, /**< statistics pointer */
    143 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    144 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    145 SCIP_PROB* prob, /**< problem data */
    146 BMS_BLKMEM* blkmem /**< block memory struct */
    147 )
    148{
    149 int i;
    150 int nrows;
    151 int ncols;
    152 int nextendedrows;
    153
    154 /* solution information for exact root LP */
    155 SCIP_RATIONAL** rootactivity;
    156 SCIP_RATIONAL** rootprimal;
    157 SCIP_Bool lperror;
    158 SCIP_PROJSHIFTDATA* projshiftdata;
    159
    160 nrows = lpexact->nrows;
    161 ncols = lpexact->ncols;
    162 projshiftdata = lpexact->projshiftdata;
    163
    164 assert(projshiftdata != NULL);
    165
    166 nextendedrows = projshiftdata->nextendedrows;
    167
    168 /* build includedrows vector based on psfpdualcolwiseselection, this determines the matrix D */
    169 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &projshiftdata->includedrows, nextendedrows) );
    170 for( i = 0; i < nextendedrows; i++ )
    171 projshiftdata->includedrows[i] = 0;
    172 /* no selection -> include all possible dual columns */
    173 if( set->exact_psdualcolselection == (int) PS_DUALCOSTSEL_NO || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE )
    174 {
    175 /* determine which dual variables to included in the problem
    176 * (ones with finite dual objective coef. in [lhs',-rhs',lb',-ub'])
    177 */
    178 for( i = 0; i < nrows; i++ )
    179 {
    180 if( !SCIPrationalIsNegInfinity(lpexact->rows[i]->lhs) )
    181 projshiftdata->includedrows[i] = 1;
    182 if( !SCIPrationalIsInfinity(lpexact->rows[i]->rhs) )
    183 projshiftdata->includedrows[nrows + i] = 1;
    184 }
    185 for( i = 0; i < ncols; i++ )
    186 {
    187 if( !SCIPrationalIsNegInfinity(lpexact->cols[i]->lb) )
    188 projshiftdata->includedrows[2*nrows + i] = 1;
    189 if( !SCIPrationalIsInfinity(lpexact->cols[i]->ub) )
    190 projshiftdata->includedrows[2*nrows + ncols + i] = 1;
    191 }
    192 }
    193 else if( set->exact_psdualcolselection == (int) PS_DUALCOSTSEL_ACTIVE_EXLP )
    194 {
    195 /* determine which dual variables to include in the problem (in this case we choose dual variables whose primal
    196 * constraints are active at the solution of the exact LP at the root node)
    197 */
    198
    199 SCIP_CALL( SCIPlpExactSolveAndEval(lpexact, lp, set, messagehdlr, blkmem, stat, eventqueue, prob, 100LL,
    200 &lperror, FALSE) );
    201
    202 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &rootprimal, ncols) );
    203 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &rootactivity, nrows) );
    204
    205 /* get the primal solution and activity */
    206 SCIP_CALL( SCIPlpiExactGetSol(lpexact->lpiexact, NULL, rootprimal, NULL, rootactivity, NULL) );
    207
    208 /* determine which dual variables to include in the problem
    209 * (primal constraints active at optimal solution found at root node)
    210 */
    211 for( i = 0; i < nrows; i++ )
    212 {
    213 if( SCIPrationalIsEQ(rootactivity[i], lpexact->rows[i]->lhs) )
    214 projshiftdata->includedrows[i] = 1;
    215 if( SCIPrationalIsEQ(rootactivity[i], lpexact->rows[i]->rhs) )
    216 projshiftdata->includedrows[nrows + i] = 1;
    217 }
    218 for( i = 0; i < ncols; i++ )
    219 {
    220 if( SCIPrationalIsEQ(rootprimal[i], lpexact->cols[i]->lb) )
    221 projshiftdata->includedrows[2*nrows + i] = 1;
    222 if( SCIPrationalIsEQ(rootprimal[i], lpexact->cols[i]->ub) )
    223 projshiftdata->includedrows[2*nrows + ncols + i] = 1;
    224 }
    225
    226 SCIPrationalFreeBufferArray(set->buffer, &rootactivity, nrows);
    227 SCIPrationalFreeBufferArray(set->buffer, &rootprimal, ncols);
    228 }
    229 else if( set->exact_psdualcolselection == (int) PS_DUALCOSTSEL_ACTIVE_FPLP )
    230 {
    231 /* determine which dual variables to include in the problem (in this case we choose dual variables whose primal
    232 * constraints are active at the solution of the exact LP at the root node)
    233 */
    234
    235 assert(lp->nrows == nrows);
    236 for( i = 0; i < nrows; i++ )
    237 {
    238 if( SCIPsetIsFeasEQ(set, SCIProwGetLPActivity(lp->rows[i], set, stat, lp), SCIProwGetLhs(lp->rows[i])) )
    239 projshiftdata->includedrows[i] = 1;
    240 if( SCIPsetIsFeasEQ(set, SCIProwGetLPActivity(lp->rows[i], set, stat, lp), SCIProwGetRhs(lp->rows[i])) )
    241 projshiftdata->includedrows[nrows + i] = 1;
    242 }
    243
    244 assert(ncols == lp->ncols);
    245 for( i = 0; i < ncols; i++ )
    246 {
    248 projshiftdata->includedrows[2*nrows + i] = 1;
    250 projshiftdata->includedrows[2*nrows + ncols + i] = 1;
    251 }
    252 }
    253 else
    254 {
    255 SCIPerrorMessage("Invalid value for parameter psfpdualcolwiseselection \n");
    256 }
    257 return SCIP_OKAY;
    258}
    259
    260/** subroutine of constructProjectShiftData(); computes the LU factorization used by the project-and-shift method */
    261static
    262SCIP_RETCODE projectShiftFactorizeDualSubmatrix(
    263 SCIP_LPEXACT* lpexact, /**< exact LP data */
    264 SCIP_SET* set, /**< scip settings */
    265 BMS_BLKMEM* blkmem /**< block memory */
    266 )
    267{
    268#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EXACTSOLVE)
    269 int i;
    270 int j;
    271 int pos;
    272 int nrows;
    273 int ncols;
    274 int nextendedrows;
    275 int nnonz;
    276 mpq_t* projvalgmp;
    277
    278 /* sparse representation of the matrix used for the LU factorization */
    279 int* projbeg;
    280 int* projlen;
    281 int* projind;
    282 SCIP_RATIONAL** projval;
    283 SCIP_PROJSHIFTDATA* projshiftdata;
    284 int projindsize;
    285
    286 projshiftdata = lpexact->projshiftdata;
    287
    288 nrows = lpexact->nrows;
    289 ncols = lpexact->ncols;
    290 nextendedrows = projshiftdata->nextendedrows;
    291 nnonz = getNNonz(lpexact);
    292 projindsize = 2*nnonz + 2*ncols;
    293
    294 /* allocate memory for the projection factorization */
    295 SCIP_CALL( SCIPsetAllocBufferArray(set, &projbeg, nextendedrows) );
    296 SCIP_CALL( SCIPsetAllocBufferArray(set, &projlen, nextendedrows) );
    297 SCIP_CALL( SCIPsetAllocBufferArray(set, &projind, projindsize) );
    298 BMSclearMemoryArray(projind, projindsize);
    299 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &projval, projindsize) );
    300 SCIP_CALL( SCIPsetAllocBufferArray(set, &projvalgmp, projindsize) );
    301
    302 /* allocate memory for the basis mapping */
    303 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &projshiftdata->projshiftbasis, nextendedrows) );
    304
    305 /* use includedrows to construct projshiftbasis, a description/mapping for D; it has length projshiftbasisdim and
    306 * projshiftbasis[i] tells what column (out of the original nextendedrows) the ith column in D is
    307 */
    308 pos = 0;
    309 for( i = 0; i < nextendedrows; i++ )
    310 {
    311 if( projshiftdata->includedrows[i] )
    312 {
    313 projshiftdata->projshiftbasis[pos] = i;
    314 pos++;
    315 }
    316 }
    317 projshiftdata->projshiftbasisdim = pos;
    318
    319 /* build the sparse representation of D that will be passed to the RECTLU code for factorization */
    320 pos = 0;
    321 for( i = 0; i < nextendedrows; i++ )
    322 {
    323 /* A part (lhs constraints) */
    324 if( i < nrows )
    325 {
    326 projlen[i] = lpexact->rows[i]->len;
    327 projbeg[i] = pos;
    328 for( j = 0; j < projlen[i]; j++ )
    329 {
    330 projind[ projbeg[i] + j ] = lpexact->rows[i]->cols_index[j];
    331 SCIPrationalSetRational( projval[ projbeg[i] + j], lpexact->rows[i]->vals[j]);
    332 }
    333 pos += projlen[i];
    334 }
    335 /* -A part (rhs constraints) */
    336 else if( i < 2 * nrows )
    337 {
    338 projlen[i] = lpexact->rows[i - nrows]->len;
    339 projbeg[i] = pos;
    340 for(j = 0; j < projlen[i]; j++)
    341 {
    342 projind[ projbeg[i] + j ] = lpexact->rows[i - nrows]->cols_index[j];
    343 SCIPrationalNegate( projval[ projbeg[i] + j], lpexact->rows[i - nrows]->vals[j]);
    344 }
    345 pos += projlen[i];
    346 }
    347 /* I part (lb constraints) */
    348 else if( i < 2*nrows + ncols )
    349 {
    350 projbeg[i] = pos;
    351 projlen[i] = 1;
    352 projind[pos] = i - 2*nrows;
    353 SCIPrationalSetFraction(projval[pos], 1LL, 1LL);
    354 pos ++;
    355 }
    356 /* -I part (ub constraints) */
    357 else
    358 {
    359 projbeg[i] = pos;
    360 projlen[i] = 1;
    361 projind[pos] = i - (2*nrows + ncols);
    362 SCIPrationalSetFraction(projval[pos], -1LL, 1LL);
    363 pos ++;
    364 }
    365 }
    366
    367#ifdef SCIP_DEBUG_PS_OUT
    368 printf("factoring matrix: ncols=%d, projshiftbasisdim=%d\n", ncols, projshiftdata->projshiftbasisdim);
    369 for( i = 0; i < nextendedrows; i++ )
    370 printf(" j=%d:\t projbeg=<%d>,\t projlen=<%d>\n", i, projbeg[i], projlen[i]);
    371
    372 for( i = 0; i < projindsize; i++ )
    373 {
    374 printf(" i=%d:\t projind=<%d>,\t projval=<", i, projind[i]);
    375 SCIPrationalPrint(projval[i]);
    376 printf(">\n");
    377 }
    378#endif
    379
    380 /* factorize projection matrix D
    381 * - projshiftbasis stores a mapping to tell us what D is, i.e. the dual columns corresponding to dual valuse that have a
    382 * strictly positive value in the relative interior point
    383 * - D is equal to a subset of [A',-A',I,-I] and is given to the factor code in sparse column representation
    384 */
    385 SCIPrationalSetGMPArray(projvalgmp, projval, projindsize);
    386
    387 /* if RECTLUbuildFactorization has failed, the project-and-shift method will not work and we will return failure */
    388 if( RECTLUbuildFactorization(&projshiftdata->rectfactor, ncols, projshiftdata->projshiftbasisdim,
    389 projshiftdata->projshiftbasis, projvalgmp, projind, projbeg, projlen) != 0 )
    390 {
    391 projshiftdata->projshiftdatafail = TRUE;
    392 SCIPdebugMessage("factorization of matrix for project-and-shift method failed.\n");
    393#ifdef SCIP_DEBUG_PS_OUT
    394 printf(" matrix factorization complete: failed\n");
    395#endif
    396 }
    397 else
    398 {
    399#ifdef SCIP_DEBUG_PS_OUT
    400 printf(" matrix factorization complete: correct termination\n");
    401#endif
    402 }
    403
    404 SCIPrationalClearArrayGMP(projvalgmp, projindsize);
    405 SCIPsetFreeBufferArray(set, &projvalgmp);
    406 SCIPrationalFreeBufferArray(set->buffer, &projval, projindsize);
    407 SCIPsetFreeBufferArray(set, &projind);
    408 SCIPsetFreeBufferArray(set, &projlen);
    409 SCIPsetFreeBufferArray(set, &projbeg);
    410
    411#else /* SCIP_WITH_GMP or SCIP_WITH_EXACTSOLVE not defined */
    412 lpexact->projshiftdata->projshiftdatafail = TRUE;
    413#ifdef SCIP_DEBUG_PS_OUT
    414 printf(" matrix factorization skipped: no GMP or EXACTSOLVE\n");
    415#endif
    416#endif
    417
    418 return SCIP_OKAY;
    419}
    420
    421/** setup the data for ps in optimal version */
    422static
    423SCIP_RETCODE setupProjectShiftOpt(
    424 SCIP_LP* lp, /**< LP data */
    425 SCIP_LPEXACT* lpexact, /**< exact LP data */
    426 SCIP_SET* set, /**< scip settings */
    427 SCIP_PROB* prob, /**< problem data */
    428 SCIP_RATIONAL** psobj, /**< obj function */
    429 SCIP_RATIONAL** psub, /**< upper bounds */
    430 SCIP_RATIONAL** pslb, /**< lower bounds */
    431 SCIP_RATIONAL** pslhs, /**< left hand sides */
    432 SCIP_RATIONAL** psrhs, /**< right hand sides */
    433 SCIP_RATIONAL** psval, /**< matrix values */
    434 int* pslen, /**< lengths of rows */
    435 int* psind, /**< indices of vals */
    436 int* psbeg, /**< beginning of rows in vals */
    437 int* dvarincidence, /**< indicates cols with bounds */
    438 int* dvarmap, /**< mapping between red-sized prob and original one */
    439 SCIP_RATIONAL* alpha, /**< scale obj */
    440 SCIP_RATIONAL* beta, /**< scale obj */
    441 SCIP_RATIONAL* tmp, /**< helper rational */
    442 int psnrows, /**< numer of rows */
    443 int psnnonz, /**< numer of non-zeros */
    444 int psncols, /**< numer of columns */
    445 int ndvarmap, /**< numer of cols with bounds in extended prob */
    446 int nrows, /**< numer of rows */
    447 int ncols /**< numer of cols */
    448 )
    449{
    450 SCIP_PROJSHIFTDATA* projshiftdata;
    451 int pos;
    452 int i;
    453 int j;
    454 int indx;
    455
    456 projshiftdata = lpexact->projshiftdata;
    457
    458 /* set up the objective */
    459 pos = 0;
    460 for( i = 0; i < nrows; i++ )
    461 {
    462 if( dvarincidence[i] )
    463 {
    464 SCIPrationalSetRational(psobj[pos], lpexact->rows[i]->lhs);
    465 pos++;
    466 }
    467 }
    468 for( i = 0; i < nrows; i++ )
    469 {
    470 if( dvarincidence[nrows + i] )
    471 {
    472 SCIPrationalNegate(psobj[pos], lpexact->rows[i]->rhs);
    473 pos++;
    474 }
    475 }
    476 for( i = 0; i < ncols; i++ )
    477 {
    478 if( dvarincidence[2*nrows + i] )
    479 {
    480 SCIPrationalSetRational(psobj[pos], lpexact->cols[i]->lb);
    481 pos++;
    482 }
    483 }
    484 for( i = 0; i < ncols; i++ )
    485 {
    486 if( dvarincidence[2*nrows + ncols + i])
    487 {
    488 SCIPrationalNegate(psobj[pos], lpexact->cols[i]->ub);
    489 pos++;
    490 }
    491 }
    492 assert(pos == ndvarmap);
    493
    494 /* set alpha and beta; note that in the current implementation projshiftobjweight can only be 0 or 1 */
    495 SCIPrationalSetFraction(alpha, (SCIP_Longint) projshiftdata->projshiftobjweight, 1LL);
    496 SCIPrationalSetFraction(beta, 1LL, 1LL);
    497
    498 if( SCIPrationalIsPositive(alpha) )
    499 {
    500 SCIPrationalDiff(beta, beta, alpha);
    501
    502 /* beta = (1-alpha)*|OBJ| Where OBJ = optimal objective value of root LP, if |OBJ|<1 use 1 instead */
    503 if( REALABS(SCIPlpGetObjval(lp, set, prob)) > 1 )
    504 {
    506 SCIPrationalMult(beta, beta, tmp);
    507 }
    508 /* divide through by alpha and round beta to be a power of 2 */
    509 SCIPrationalDiv(beta, beta, alpha);
    510 SCIPrationalSetFraction(alpha, 1LL, 1LL);
    511 SCIPrationalSetReal(beta, pow(2.0, log(SCIPrationalGetReal(beta))/log(2.0)));
    512 }
    513
    514 /* set objective to normalized value */
    515 for( i = 0; i < ndvarmap; i ++ )
    516 SCIPrationalMult(psobj[i], psobj[i], alpha);
    517 SCIPrationalSetRational(psobj[ndvarmap], beta);
    518
    519 /* set variable bounds */
    520 for( i = 0; i < ndvarmap; i++ )
    521 {
    523 SCIPrationalSetFraction(pslb[i], 0LL, 1LL);
    524 }
    525 SCIPrationalSetFraction(psub[ndvarmap], PSBIGM, 1LL);
    526 SCIPrationalSetFraction(pslb[ndvarmap], 0LL, 1LL);
    527
    528 /* set up constraint bounds */
    529 for( i = 0; i < ncols; i++ )
    530 {
    531 SCIPrationalSetRational(pslhs[i], lpexact->cols[i]->obj);
    532 SCIPrationalSetRational(psrhs[i], lpexact->cols[i]->obj);
    533 }
    534 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    535 {
    536 SCIPrationalSetFraction(pslhs[ncols + i], 0LL, 1LL);
    537 SCIPrationalSetInfinity(psrhs[ncols + i]);
    538 }
    539
    540 /* set up constraint matrix: this involves transposing the constraint matrix */
    541
    542 /* count the length of each constraint */
    543 for( i = 0; i < psnrows; i++ )
    544 pslen[i] = 0;
    545 for( i = 0; i < ndvarmap; i++ )
    546 {
    547 indx = dvarmap[i];
    548 if( indx < 2*nrows )
    549 {
    550 if( indx >= nrows )
    551 indx -= nrows;
    552 for( j = 0; j < lpexact->rows[indx]->len; j++ )
    553 {
    554 pslen[lpexact->rows[indx]->cols_index[j]]++;
    555 }
    556 }
    557 else
    558 {
    559 if ( indx < 2*nrows + ncols )
    560 indx -= 2 * nrows;
    561 else
    562 indx -= (2*nrows + ncols);
    563 pslen[indx]++;
    564 }
    565 }
    566 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    567 {
    568 pslen[ncols + i] = 2;
    569 }
    570 /* set up the beg array */
    571 pos = 0;
    572 for( i = 0; i < psnrows; i++ )
    573 {
    574 psbeg[i] = pos;
    575 pos += pslen[i];
    576 }
    577 assert(pos == psnnonz);
    578
    579 /* reset the length array and build it up as entries are added one by one by scanning through matrix. */
    580 for( i = 0; i < ncols; i++ )
    581 pslen[i] = 0;
    582 for( i = 0; i < ndvarmap; i++ )
    583 {
    584 indx = dvarmap[i];
    585 if( indx < 2*nrows )
    586 {
    587 if( indx >= nrows )
    588 indx -= nrows;
    589 for(j = 0; j < lpexact->rows[indx]->len; j++)
    590 {
    591 pos = psbeg[lpexact->rows[indx]->cols_index[j]] + pslen[lpexact->rows[indx]->cols_index[j]];
    592 psind[pos] = i;
    593 if(dvarmap[i]<nrows)
    594 SCIPrationalSetRational(psval[pos], lpexact->rows[indx]->vals[j]);
    595 else
    596 SCIPrationalNegate(psval[pos], lpexact->rows[indx]->vals[j]);
    597 pslen[lpexact->rows[indx]->cols_index[j]]++;
    598 }
    599 }
    600 else
    601 {
    602 if ( indx < 2*nrows + ncols )
    603 indx -= 2 * nrows;
    604 else
    605 indx -= (2*nrows + ncols);
    606 pos = psbeg[indx] + pslen[indx];
    607 psind[pos] = i;
    608 if( dvarmap[i] < 2*nrows + ncols)
    609 SCIPrationalSetFraction(psval[pos], 1LL, 1LL);
    610 else
    611 SCIPrationalSetFraction(psval[pos], -1LL, 1LL);
    612 pslen[indx]++;
    613 }
    614 }
    615 /* set up the last projshiftbasisdim rows */
    616 pos = ncols;
    617 for( i = 0; i < ndvarmap; i++ )
    618 {
    619 indx = dvarmap[i];
    620 if( projshiftdata->includedrows[indx] )
    621 {
    622 psind[psbeg[pos]] = i;
    623 SCIPrationalSetFraction(psval[psbeg[pos]], 1LL, 1LL);
    624 psind[psbeg[pos] + 1] = psncols - 1;
    625 SCIPrationalSetFraction(psval[psbeg[pos] + 1], -1LL, 1LL);
    626 pos++;
    627 }
    628 }
    629 assert(pos == psnrows);
    630
    631 return SCIP_OKAY;
    632}
    633
    634/** subroutine to compute number of nonzeros in lp-matrix */
    635static
    636int computeProjectShiftNnonz(
    637 SCIP_LPEXACT* lpexact, /**< the exact lp */
    638 int* dvarincidence /**< the columns with existing bounds */
    639 )
    640{
    641 int ret = 0;
    642 int i;
    643 int nrows = lpexact->nrows;
    644 int ncols = lpexact->ncols;
    645
    646 for( i = 0; i < nrows; i++ )
    647 {
    648 if( dvarincidence[i] )
    649 ret += lpexact->rows[i]->len;
    650 if( dvarincidence[nrows + i] )
    651 ret += lpexact->rows[i]->len;
    652 }
    653 for( i = 0; i < ncols; i++ )
    654 {
    655 if( dvarincidence[2*nrows + i] )
    656 ret++;
    657 if( dvarincidence[2*nrows + ncols + i] )
    658 ret++;
    659 }
    660
    661 return ret;
    662}
    663
    664/** subroutine of constructProjectShiftData(); computes S-interior point or ray which is used to do the shifting step */
    665static
    666SCIP_RETCODE projectShiftComputeSintPointRay(
    667 SCIP_LPEXACT* lpexact, /**< exact LP data */
    668 SCIP_SET* set, /**< scip settings */
    669 SCIP_STAT* stat, /**< statistics pointer */
    670 BMS_BLKMEM* blkmem, /**< block memory */
    671 SCIP_Bool findintpoint /**< TRUE, if we search int point, FALSE if we search for ray */
    672 )
    673{
    674 int ncols;
    675 int psncols;
    676 SCIP_Real lptimelimit;
    677 SCIP_RETCODE retcode;
    678
    679 /* lpiexact and data used for the aux. problem */
    680 SCIP_LPIEXACT* pslpiexact;
    681 SCIP_PROJSHIFTDATA* projshiftdata;
    682
    683 SCIP_RATIONAL** sol = NULL; /* either primal or dualsol */
    684 SCIP_RATIONAL* objval;
    685
    686 /* mapping between variables used in the aux. problem and the original problem */
    687 int ndvarmap;
    688 int* dvarmap;
    689
    690 projshiftdata = lpexact->projshiftdata;
    691 assert(projshiftdata != NULL);
    692 pslpiexact = projshiftdata->lpiexact;
    693 if( pslpiexact == NULL )
    694 {
    695 projshiftdata->projshiftdatafail = TRUE;
    696 return SCIP_OKAY;
    697 }
    698
    699 ncols = lpexact->ncols;
    700
    701 dvarmap = projshiftdata->dvarmap;
    702 ndvarmap = projshiftdata->ndvarmap;
    703 SCIP_CALL( SCIPlpiExactGetNCols(pslpiexact, &psncols) );
    704 assert(psncols == ndvarmap + 1);
    705
    706 if( !findintpoint )
    707 {
    708 /* in this case we want to find an interior ray instead of an interior point
    709 * the problem will be modified to the following problem:
    710 * max: [OBJ, 0]*[y,d]'
    711 * s.t.: [0] <= [ A~ | 0] [y] <= [ 0 ]
    712 * [0] <= [ I* | -1] * [d] <= [\infty] <-- only for dual vars from includecons
    713 * bounds: 0 <= y <= \infty
    714 * 1 <= d <= \infty
    715 * y is a vector of length (ndvarmap) and d is a single variable
    716 * and A~ is the submatrix of [A',-A',I,-I] using columns in dvarmap
    717 * and OBJ is the subvector of [lhs,-rhs,lb,-ub] using columns in dvarmap
    718 *
    719 * the parts that change are the objective function, the RHS/LHS of the first constraint set
    720 * and the lower bound for d
    721 */
    722 SCIP_RATIONAL* auxval1;
    723 SCIP_RATIONAL* auxval2;
    724 int i;
    725
    726 assert(projshiftdata->projshifthasray == FALSE);
    727
    728 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &auxval1) );
    729 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &auxval2) );
    730
    731 /* update the objective on d */
    732 SCIPrationalSetFraction(auxval1, 0LL, 1LL);
    733 SCIP_CALL( SCIPlpiExactChgObj(pslpiexact, 1, &ndvarmap, &auxval1) );
    734
    735 /* update the rhs/lhs */
    736 for( i = 0; i < ncols; i++ )
    737 {
    738 SCIP_CALL( SCIPlpiExactChgSides(pslpiexact, 1, &i, &auxval1, &auxval1) );
    739 }
    740
    741 /* update bounds on d */
    742 SCIPrationalSetFraction(auxval1, 1LL, 1LL); /*lint !e850*/ /* lint exception for &i in above for loop */
    744 SCIP_CALL( SCIPlpiExactChgBounds(pslpiexact, 1, &ndvarmap, &auxval1, &auxval2) );
    745
    746 SCIPrationalFreeBlock(blkmem, &auxval2);
    747 SCIPrationalFreeBlock(blkmem, &auxval1);
    748 }
    749
    750 /* set the display informatino */
    751 SCIP_CALL( SCIPlpiExactSetIntpar(pslpiexact, SCIP_LPPAR_LPINFO, (int) set->exact_lpinfo) );
    752 /* check if a time limit is set, and set time limit for LP solver accordingly */
    753 lptimelimit = SCIPlpiExactInfinity(pslpiexact);
    754 if( set->istimelimitfinite )
    755 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
    756 if( lptimelimit > 0.0 )
    757 {
    758 SCIP_CALL( SCIPlpiExactSetRealpar(pslpiexact, SCIP_LPPAR_LPTILIM, lptimelimit) );
    759 }
    760 /* solve the LP */
    761 retcode = SCIPlpiExactSolveDual(pslpiexact);
    762 if( retcode == SCIP_LPERROR )
    763 {
    764 projshiftdata->projshiftdatafail = TRUE;
    765 SCIPwarningMessage(set->scip, "lperror in construction of projshift-data \n");
    766 }
    767
    768 /* recover the optimal solution and set interior point and slack in constraint handler data */
    769 if( SCIPlpiExactIsOptimal(pslpiexact) )
    770 {
    771 int i;
    772
    773 SCIPdebugMessage(" exact LP solved to optimality\n");
    774
    775 /* get optimal dual solution */
    776 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &sol, psncols) );
    777 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &objval) );
    778 SCIP_CALL( SCIPlpiExactGetSol(pslpiexact, objval, sol, NULL, NULL, NULL) );
    779
    780 SCIPrationalSetRational(projshiftdata->commonslack, sol[psncols - 1]);
    781 if( SCIPrationalIsZero(projshiftdata->commonslack) )
    782 {
    783 /* if commonslack == 0, point/ray is not interior */
    784 SCIPdebugMessage(" --> project-and-shift failed to find interior point/ray\n");
    785 }
    786 else
    787 {
    788 /* assign interior point solution to constraint handler data */
    789 for( i = 0; i < ndvarmap; i++ )
    790 {
    791 if( findintpoint )
    792 SCIPrationalSetRational( projshiftdata->interiorpoint[dvarmap[i]], sol[i]);
    793 else
    794 SCIPrationalSetRational( projshiftdata->interiorray[dvarmap[i]], sol[i]);
    795 }
    796 if( findintpoint )
    797 projshiftdata->projshifthaspoint = TRUE;
    798 else
    799 projshiftdata->projshifthasray = TRUE;
    800 }
    801
    802 SCIPrationalFreeBuffer(set->buffer, &objval);
    803 SCIPrationalFreeBufferArray(set->buffer, &sol, psncols);
    804 }
    805 else
    806 projshiftdata->projshiftdatafail = TRUE;
    807
    808 if( findintpoint && projshiftdata->projshifthaspoint )
    809 {
    810 int i;
    811
    812 for( i = 0; i < ndvarmap; i++ )
    813 SCIPrationalCanonicalize(projshiftdata->interiorpoint[i]);
    814 }
    815 else if( !findintpoint && projshiftdata->projshifthasray )
    816 {
    817 int i;
    818
    819 for( i = 0; i < ndvarmap; i++ )
    820 SCIPrationalCanonicalize(projshiftdata->interiorray[i]);
    821 }
    822
    823 /* free memory for exact LPI if not needed anymore */
    824 assert(pslpiexact != NULL);
    825 if( projshiftdata->projshiftdatafail || (projshiftdata->projshifthaspoint && projshiftdata->projshifthasray) )
    826 {
    827 int nlpirows;
    828 int nlpicols;
    829
    830 SCIP_CALL( SCIPlpiExactGetNRows(pslpiexact, &nlpirows) );
    831 SCIP_CALL( SCIPlpiExactDelRows(pslpiexact, 0, nlpirows - 1) );
    832
    833 SCIP_CALL( SCIPlpiExactGetNCols(pslpiexact, &nlpicols) );
    834 SCIP_CALL( SCIPlpiExactDelCols(pslpiexact, 0, nlpicols - 1) );
    835
    836 SCIP_CALL( SCIPlpiExactClear(pslpiexact) );
    837 SCIP_CALL( SCIPlpiExactFree(&pslpiexact) );
    838
    839 projshiftdata->lpiexact = NULL;
    840
    841 assert(projshiftdata->dvarmap != NULL);
    842 BMSfreeBlockMemoryArrayNull(blkmem, &projshiftdata->dvarmap, projshiftdata->ndvarmap);
    843 }
    844
    845 return SCIP_OKAY;
    846}
    847
    848/** subroutine of constructProjectShiftData(); computes S-interior point or ray which is used to do the shifting step */
    849static
    850SCIP_RETCODE projectShiftConstructLP(
    851 SCIP_LP* lp, /**< LP data */
    852 SCIP_LPEXACT* lpexact, /**< exact LP data */
    853 SCIP_SET* set, /**< scip settings */
    854 SCIP_PROB* prob, /**< problem data */
    855 BMS_BLKMEM* blkmem /**< block memory */
    856 )
    857{
    858 /* we will find an optimized interior point for which we will try to push it interior and
    859 * optimize over its objective value. To do this we will solve the following problem
    860 * max \alpha * [lhs,-rhs,lb,ub] * y + \beta d
    861 * s.t. [A,-A,I,-I] * y = c
    862 * y_i - d >= 0 for each i \in S
    863 * y >= 0
    864 * M >= d >= 0
    865 * M is a bound on how interior we will let the point be, S is the set of dual columns chosen earlier
    866 * which could have nonzero values for the S-interior point.
    867 *
    868 * After solving this y will be the S-interior point and d will be the common slack.
    869 * Here we actually construct the dual in row representation so it can be solved directly.
    870 */
    871
    872 int pos;
    873 int nrows;
    874 int ncols;
    875 int nextendedrows; /* number of extended constraints, # of cols in [A',-A',I,-I] */
    876 int psncols;
    877
    878 /* lpiexact and data used for the aux. problem */
    879 SCIP_LPIEXACT* pslpiexact;
    880 SCIP_PROJSHIFTDATA* projshiftdata;
    881 SCIP_ROWEXACT** lprows;
    882 SCIP_COLEXACT** lpcols;
    883
    884 /* mapping between variables used in the aux. problem and the original problem */
    885 int ndvarmap;
    886 int* dvarmap;
    887
    888 SCIP_RATIONAL** psobj = NULL;
    889 SCIP_RATIONAL** pslb = NULL;
    890 SCIP_RATIONAL** psub = NULL;
    891 SCIP_RATIONAL** pslhs = NULL;
    892 SCIP_RATIONAL** psrhs = NULL;
    893 int* psbeg;
    894 int* pslen;
    895 int* psind;
    896 SCIP_RATIONAL** psval = NULL;
    897 char ** colnames = NULL;
    898 int psnrows;
    899 int psnnonz;
    900 int i;
    901
    902 SCIP_RATIONAL* tmp;
    903 SCIP_RATIONAL* alpha;
    904 SCIP_RATIONAL* beta;
    905 int* dvarincidence;
    906
    907 assert(lpexact != NULL);
    908
    909 projshiftdata = lpexact->projshiftdata;
    910 assert(projshiftdata != NULL);
    911
    912 if( projshiftdata->lpiexact != NULL )
    913 return SCIP_OKAY;
    914
    915 lprows = lpexact->rows;
    916 lpcols = lpexact->cols;
    917 nrows = lpexact->nrows;
    918 ncols = lpexact->ncols;
    919
    920 nextendedrows = projshiftdata->nextendedrows;
    921
    922 /* set up dvarmap - mapping between variables and original problem
    923 * - use the rows that are used for aux. problem
    924 * - dvarmap[i] is the index in the original problem of the i^th constraint in the reduced size problem
    925 * (reduced from nextendedrows to ndvarmap)
    926 * - dvarincidence gives the incidence vector of variables used in aux problem
    927 */
    928 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
    929 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &alpha) );
    930 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &beta) );
    931 SCIP_CALL( SCIPsetAllocBufferArray(set, &dvarincidence, nextendedrows) );
    932 {
    933 /* if the aux. lp is not reduced then expand the selection for dvarmap to include all dual vars with finite cost */
    934 for( i = 0; i < nextendedrows; i++ )
    935 dvarincidence[i] = 0;
    936 for( i = 0; i < nrows; i++ )
    937 {
    938 if( !SCIPrationalIsNegInfinity(lprows[i]->lhs) )
    939 dvarincidence[i] = 1;
    940 if( !SCIPrationalIsInfinity(lprows[i]->rhs) )
    941 dvarincidence[nrows + i] = 1;
    942 }
    943 for( i = 0; i < ncols; i++ )
    944 {
    945 if( !SCIPrationalIsNegInfinity(lpcols[i]->lb) )
    946 dvarincidence[2*nrows + i] = 1;
    947 if( !SCIPrationalIsInfinity(lpcols[i]->ub) )
    948 dvarincidence[2*nrows + ncols + i] = 1;
    949 }
    950 }
    951
    952 ndvarmap = 0;
    953 for( i = 0; i < nextendedrows; i++ )
    954 {
    955 if(dvarincidence[i])
    956 ndvarmap++;
    957 }
    958 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &dvarmap, ndvarmap) );
    959 pos = 0;
    960 for( i = 0; i < nextendedrows; i++ )
    961 {
    962 if(dvarincidence[i])
    963 {
    964 assert(pos < ndvarmap);
    965 dvarmap[pos] = i;
    966 pos++;
    967 }
    968 }
    969 projshiftdata->dvarmap = dvarmap;
    970 projshiftdata->ndvarmap = ndvarmap;
    971
    972 /* allocate memory for auxiliary problem */
    973 psncols = ndvarmap + 1;
    974 psnrows = ncols + projshiftdata->projshiftbasisdim;
    975 psnnonz = computeProjectShiftNnonz(lpexact, dvarincidence);
    976 psnnonz += 2*projshiftdata->projshiftbasisdim;
    977
    978 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psobj, psncols) );
    979 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &pslb, psncols) );
    980 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psub, psncols) );
    981 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &pslhs, psnrows) );
    982 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psrhs, psnrows) );
    983 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psval, psnnonz) );
    984
    985 SCIP_CALL( SCIPsetAllocBufferArray(set, &psbeg, psnrows) );
    986 SCIP_CALL( SCIPsetAllocBufferArray(set, &pslen, psnrows) );
    987 SCIP_CALL( SCIPsetAllocBufferArray(set, &psind, psnnonz) );
    988
    989 SCIP_CALL( SCIPsetAllocBufferArray(set, &colnames, psncols) );
    990 for( i = 0; i < psncols; i++ )
    991 {
    992 SCIP_CALL( SCIPsetAllocBufferArray(set, &colnames[i], SCIP_MAXSTRLEN) ); /*lint !e866*/
    993 (void) SCIPsnprintf( (colnames)[i] , SCIP_MAXSTRLEN, "var%d", i);
    994 }
    995
    996 /* the representation of the problem will be:
    997 * max: [\alpha*OBJ, \beta]*[y,d]'
    998 * s.t.: [c] <= [ A~ | 0] [y] <= [ c ]
    999 * [0] <= [ I* | -1] * [d] <= [\infty] <-- only for dual vars from includecons
    1000 * bounds: 0 <= y <= \infty
    1001 * 0 <= d <= M
    1002 * y is a vector of length (ndvarmap) and d is a single variable
    1003 * and A~ is the submatrix of [A',-A',I,-I] using columns in dvarmap
    1004 * and OBJ is the subvector of [lhs,-rhs,lb,-ub] using columns in dvarmap
    1005 *
    1006 * alpha is set equal to the param projshiftobjweight and beta is set equal to
    1007 * beta := 1-alpha
    1008 */
    1009 SCIP_CALL( setupProjectShiftOpt(lp, lpexact, set, prob, psobj, psub, pslb, pslhs, psrhs, psval,
    1010 pslen, psind, psbeg, dvarincidence, dvarmap, alpha, beta, tmp, psnrows, psnnonz,
    1011 psncols, ndvarmap, nrows, ncols) );
    1012
    1013 /* build aux LP using the exact LP interface and store it in the global data */
    1014 SCIP_CALL( SCIPlpiExactCreate(&pslpiexact, NULL, "pslpiexact", SCIP_OBJSEN_MAXIMIZE) );
    1015 projshiftdata->lpiexact = pslpiexact;
    1016
    1017 /* add all columns to the exact LP */
    1018 SCIP_CALL( SCIPlpiExactAddCols(pslpiexact, psncols, psobj, pslb, psub, colnames, 0, NULL, NULL, NULL) );
    1019
    1020 /* add all constraints to the exact LP */
    1021 SCIP_CALL( SCIPlpiExactAddRows(pslpiexact, psnrows, pslhs, psrhs, NULL, psnnonz, psbeg, psind, psval) );
    1022
    1023 /* free memory */
    1024 for( i = psncols - 1; i >= 0; i-- )
    1025 SCIPsetFreeBufferArray(set, &colnames[i] );
    1026 SCIPsetFreeBufferArray(set, &colnames);
    1027
    1028 SCIPsetFreeBufferArray(set, &psind);
    1029 SCIPsetFreeBufferArray(set, &pslen);
    1030 SCIPsetFreeBufferArray(set, &psbeg);
    1031
    1032 SCIPrationalFreeBufferArray(set->buffer, &psval, psnnonz);
    1033 SCIPrationalFreeBufferArray(set->buffer, &psrhs, psnrows);
    1034 SCIPrationalFreeBufferArray(set->buffer, &pslhs, psnrows);
    1035 SCIPrationalFreeBufferArray(set->buffer, &psub, psncols);
    1036 SCIPrationalFreeBufferArray(set->buffer, &pslb, psncols);
    1037 SCIPrationalFreeBufferArray(set->buffer, &psobj, psncols);
    1038
    1039 SCIPsetFreeBufferArray(set, &dvarincidence);
    1040
    1041 SCIPrationalFreeBuffer(set->buffer, &beta);
    1042 SCIPrationalFreeBuffer(set->buffer, &alpha);
    1043 SCIPrationalFreeBuffer(set->buffer, &tmp);
    1044
    1045 return SCIP_OKAY;
    1046}
    1047
    1048/** constructs exact LP that needs to be solved to compute data for the project-and-shift method */
    1049static
    1050SCIP_RETCODE constructProjectShiftDataLPIExact(
    1051 SCIP_LP* lp, /**< LP data */
    1052 SCIP_LPEXACT* lpexact, /**< exact LP data */
    1053 SCIP_SET* set, /**< scip settings */
    1054 SCIP_STAT* stat, /**< statistics pointer */
    1055 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    1056 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1057 SCIP_PROB* prob, /**< problem data */
    1058 BMS_BLKMEM* blkmem
    1059 )
    1060{
    1061 SCIP_PROJSHIFTDATA* projshiftdata;
    1062
    1063 assert(lpexact != NULL);
    1064 assert(lpexact->projshiftdata != NULL);
    1065 assert(SCIPgetDepth(set->scip) <= 0);
    1066
    1067 projshiftdata = lpexact->projshiftdata;
    1068
    1069 /* if the LP was already constructed, exit */
    1070 if( projshiftdata->lpiexact != NULL )
    1071 return SCIP_OKAY;
    1072
    1073 SCIPdebugMessage("calling constructProjectShiftDataLPIExact()\n");
    1075
    1076 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &projshiftdata->commonslack) );
    1077
    1078 /* process the bound changes */
    1079 SCIP_CALL( SCIPlpExactSyncLPs(lpexact, blkmem, set) );
    1080 SCIP_CALL( SCIPlpExactFlush(lp->lpexact, blkmem, set, eventqueue) );
    1081
    1082 projshiftdata->nextendedrows = 2*lpexact->nrows + 2*lpexact->ncols;
    1083 assert(projshiftdata->nextendedrows > 1);
    1084
    1085 /* call function to select the set S */
    1086 SCIP_CALL( projectShiftChooseDualSubmatrix(lp, lpexact, set, stat, messagehdlr, eventqueue, prob, blkmem) );
    1087
    1088 /* compute LU factorization of D == A|_S */
    1089 SCIP_CALL( projectShiftFactorizeDualSubmatrix(lpexact, set, blkmem) );
    1090
    1091 SCIP_CALL( projectShiftConstructLP(lp, lpexact, set, prob, blkmem) );
    1092
    1094 SCIPdebugMessage("exiting constructProjectShiftDataLPIExact()\n");
    1095
    1096 return SCIP_OKAY;
    1097}
    1098
    1099/** constructs data used to compute dual bounds by the project-and-shift method */
    1100static
    1101SCIP_RETCODE constructProjectShiftData(
    1102 SCIP_LPEXACT* lpexact, /**< exact LP data */
    1103 SCIP_SET* set, /**< scip settings */
    1104 SCIP_STAT* stat, /**< statistics pointer */
    1105 BMS_BLKMEM* blkmem
    1106 )
    1107{
    1108 SCIP_PROJSHIFTDATA* projshiftdata;
    1109
    1110 assert(lpexact != NULL);
    1111 assert(lpexact->projshiftdata != NULL);
    1112
    1113 projshiftdata = lpexact->projshiftdata;
    1114
    1115 /* consider the primal problem as
    1116 * min c'x
    1117 * lhs <= Ax <= rhs
    1118 * lb <= x <= ub
    1119 *
    1120 * and the dual of the form
    1121 * [ A', -A', I, -I] y = c
    1122 * y >= 0
    1123 *
    1124 * A subset S of the dual columns are chosen to give a submatrix D of [A',-A',I,-I], which is then LU factorized using
    1125 * rectlu code then an S-interior point is found (a dual solution that is strictly positive for each column in S).
    1126 * this data is then reused throughout the tree where the LU factorization can be used to correct feasibility of
    1127 * the equality constraints of the dual, and a convex combination with the S-interior point can correct any
    1128 * infeasibility coming from negative variables.
    1129 */
    1130
    1131 /* if the ps data was already constructed, exit */
    1132 if( projshiftdata->projshiftdatacon )
    1133 return SCIP_OKAY;
    1134
    1135 /* now mark that this function has been called */
    1136 projshiftdata->projshiftdatacon = TRUE;
    1137
    1138 /* ensure that the exact LP exists that needs to be solved for obtaining the interior ray and point */
    1139
    1140 SCIPdebugMessage("calling constructProjectShiftData()\n");
    1142
    1143 /* if no fail in LU factorization, compute S-interior point and/or ray */
    1144 if( !projshiftdata->projshiftdatafail )
    1145 {
    1146 if( projshiftdata->projshiftuseintpoint )
    1147 {
    1148 /* compute S-interior point if we need it */
    1149 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->interiorpoint, projshiftdata->nextendedrows) );
    1150 SCIP_CALL( projectShiftComputeSintPointRay(lpexact, set, stat, blkmem, TRUE) );
    1151 }
    1152
    1153 /* always try to compute the S-interior ray (for infeasibility proofs) */
    1154 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->interiorray, projshiftdata->nextendedrows) );
    1155 SCIP_CALL( projectShiftComputeSintPointRay(lpexact, set, stat, blkmem, FALSE) );
    1156 }
    1157
    1158 /* if construction of both point and ray has failed, mark projshiftdatafail as true. */
    1159 if( !projshiftdata->projshifthaspoint && !projshiftdata->projshifthasray )
    1160 projshiftdata->projshiftdatafail = TRUE;
    1161 else
    1162 projshiftdata->projshiftdatafail = FALSE;
    1163
    1164 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->violation, lpexact->ncols) );
    1165 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->correction, projshiftdata->nextendedrows) );
    1166 projshiftdata->violationsize = lpexact->ncols;
    1167
    1169 SCIPdebugMessage("exiting constructProjectShiftData()\n");
    1170
    1171 return SCIP_OKAY;
    1172}
    1173
    1174/** computes safe dual bound by project-and-shift method or corrects dual ray for infeasibility proof */
    1175static
    1176SCIP_RETCODE projectShift(
    1177 SCIP_LP* lp, /**< LP data */
    1178 SCIP_LPEXACT* lpexact, /**< exact LP data */
    1179 SCIP_SET* set, /**< scip settings */
    1180 SCIP_STAT* stat, /**< statistics pointer */
    1181 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    1182 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    1183 SCIP_PROB* prob, /**< problem data */
    1184 BMS_BLKMEM* blkmem, /**< block memory */
    1185 SCIP_Bool usefarkas, /**< do we aim to prove infeasibility? */
    1186 SCIP_Real* safebound /**< store the calculated safebound here */
    1187 )
    1188{ /*lint --e{715}*/
    1189 SCIP_COL** cols;
    1190 SCIP_RATIONAL** dualsol;
    1191 SCIP_RATIONAL** violation;
    1192 SCIP_RATIONAL** correction;
    1193 SCIP_Bool useinteriorpoint;
    1194 SCIP_RATIONAL* tmp;
    1195 SCIP_RATIONAL* tmp2;
    1196 SCIP_RATIONAL* lambda1;
    1197 SCIP_RATIONAL* lambda2;
    1198 SCIP_RATIONAL* maxv;
    1199 SCIP_RATIONAL* dualbound;
    1200 SCIP_PROJSHIFTDATA* projshiftdata;
    1201 mpq_t* violationgmp = NULL;
    1202 mpq_t* correctiongmp = NULL;
    1203 SCIP_Real computedbound;
    1204 SCIP_Bool* isupper;
    1205 int i;
    1206 int j;
    1207 int rval;
    1208 int nextendedrows;
    1209 int nrows;
    1210 int nrowsps; /* number of rows used for ps. this can be lower than nrows, if e.g. cuts were added */
    1211 int ncols;
    1212 int currentrow;
    1213 int shift;
    1214 SCIP_Bool isfeas;
    1215
    1216 assert(lp != NULL);
    1217 assert(lp->solved);
    1218 assert(lpexact != NULL);
    1219 assert(set != NULL);
    1220 assert(safebound != NULL);
    1221
    1222 /* project-and-shift method:
    1223 * 1. projection step (to ensure that equalities are satisfied):
    1224 * - compute error in equalities: r=c-Ay^
    1225 * - backsolve system of equations to find correction of error: z with Dz=r
    1226 * - add corretion to approximate dual solution: bold(y)=y^+[z 0]
    1227 * 2. shifting step (to ensure that inequalities are satisfied):
    1228 * - take convex combination of projected approximate point bold(y) with interior point y*
    1229 * 3. compute dual objective value of feasible dual solution and set bound
    1230 */
    1231 projshiftdata = lpexact->projshiftdata;
    1232
    1233 /* if data has not been constructed, construct it */
    1234 if( !projshiftdata->projshiftdatacon )
    1235 {
    1236 SCIP_CALL( constructProjectShiftData(lpexact, set, stat, blkmem) );
    1237 }
    1238
    1239 assert(projshiftdata->projshiftdatacon);
    1240
    1241 /* if constructing the data failed, then exit */
    1242 if( projshiftdata->projshiftdatafail || (usefarkas && !projshiftdata->projshifthasray) )
    1243 {
    1244 lp->hasprovedbound = FALSE;
    1245 return SCIP_OKAY;
    1246 }
    1247
    1248 /* start the timer */
    1249 if( usefarkas )
    1250 {
    1251 stat->nprojshiftinf++;
    1253 }
    1254 else
    1255 {
    1256 stat->nprojshift++;
    1258 stat->nprojshiftobjlim++;
    1260 }
    1261
    1262 SCIPdebugMessage("calling projectShift()\n");
    1263
    1264 /* decide if we should use ray or point to compute bound */
    1265 if( !usefarkas && projshiftdata->projshiftuseintpoint && projshiftdata->projshifthaspoint )
    1266 useinteriorpoint = TRUE;
    1267 else if( projshiftdata->projshifthasray )
    1268 {
    1269 useinteriorpoint = FALSE;
    1270 }
    1271 /* we either dont have a ray and want to prove infeasibility or we have neither point nor ray -> can't run */
    1272 else
    1273 {
    1274 lp->hasprovedbound = FALSE;
    1275 return SCIP_OKAY;
    1276 }
    1277
    1278 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
    1279 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp2) );
    1280 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lambda1) );
    1281 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lambda2) );
    1282 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &maxv) );
    1283 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &dualbound) );
    1284
    1285 /* set up the exact lpi for the current node and flush exact lp */
    1286 SCIP_CALL( SCIPlpExactSyncLPs(lpexact, blkmem, set) );
    1287 SCIP_CALL( SCIPlpExactFlush(lp->lpexact, blkmem, set, eventqueue) );
    1288
    1289 nextendedrows = projshiftdata->nextendedrows;
    1290 nrows = lpexact->nrows;
    1291 ncols = lpexact->ncols;
    1292 nrowsps = projshiftdata->nextendedrows/2 - ncols;
    1293 shift = nrows - nrowsps;
    1294
    1295 assert(ncols == projshiftdata->violationsize);
    1296
    1297 /* allocate memory for approximate dual solution, dual cost vector, violation and correction */
    1298 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nrows + ncols) );
    1299 violation = projshiftdata->violation;
    1300 correction = projshiftdata->correction;
    1301
    1302 for( i = 0; i < nrows + ncols; ++i )
    1303 {
    1304 if( i < nrows )
    1305 dualsol[i] = usefarkas ? lpexact->rows[i]->dualfarkas : lpexact->rows[i]->dualsol;
    1306 else
    1307 dualsol[i] = usefarkas ? lpexact->cols[i - nrows]->farkascoef : lpexact->cols[i - nrows]->redcost;
    1308
    1309 SCIPrationalSetFraction(dualsol[i], 0LL, 1LL);
    1310 if( i < ncols )
    1311 SCIPrationalSetFraction(violation[i], 0LL, 1LL);
    1312 }
    1313 for( i = 0; i < nextendedrows; ++i )
    1314 {
    1315 SCIPrationalSetFraction(correction[i], 0LL, 1LL);
    1316 }
    1317
    1318 SCIP_CALL( SCIPsetAllocBufferArray(set, &isupper, nrows + ncols) );
    1319
    1320 /* recover the objective coefs and approximate solution value of dual solution;
    1321 * dual vars of lhs constraints (including -inf) and rhs constraints (including +inf),
    1322 * dual vars of lb constraint (including -inf) and ub constraints (including +inf)
    1323 */
    1324 for( i = 0; i < nrows; i++ )
    1325 {
    1326 if( !usefarkas )
    1327 SCIPrationalSetReal(dualsol[i], SCIProwGetDualsol(lp->rows[i]));
    1328 else
    1329 SCIPrationalSetReal(dualsol[i], SCIProwGetDualfarkas(lp->rows[i]));
    1330
    1331 /* terminate in case of infinity solution */
    1332 if( SCIPrationalIsAbsInfinity(dualsol[i]) )
    1333 {
    1334 SCIPdebugMessage(" no valid unbounded approx dual sol given\n");
    1335 lp->hasprovedbound = FALSE;
    1336 if( usefarkas )
    1337 stat->nfailprojshiftinf++;
    1338 else
    1339 stat->nfailprojshift++;
    1340
    1341 goto TERMINATE;
    1342 }
    1343
    1344 /* positive dual coef -> lhs, negative -> rhs */
    1345 if( SCIPrationalIsPositive(dualsol[i]) )
    1346 isupper[i] = FALSE;
    1347 else
    1348 isupper[i] = TRUE;
    1349 }
    1350
    1351 cols = SCIPlpGetCols(lp);
    1352 for( i = 0; i < ncols; i++ )
    1353 {
    1354 if( !usefarkas )
    1355 SCIPrationalSetReal(dualsol[i+nrows], SCIPcolGetRedcost(cols[i], stat, lp));
    1356 else
    1357 SCIPrationalSetReal(dualsol[i+nrows], -SCIPcolGetFarkasCoef(cols[i], stat, lp));
    1358
    1359 /* terminate in case of infinite redcost */
    1360 if( SCIPrationalIsAbsInfinity(dualsol[i + nrows]) )
    1361 {
    1362 SCIPdebugMessage(" no valid unbounded approx dual sol given\n");
    1363 lp->hasprovedbound = FALSE;
    1364 if( usefarkas )
    1365 stat->nfailprojshiftinf++;
    1366 else
    1367 stat->nfailprojshift++;
    1368
    1369 goto TERMINATE;
    1370 }
    1371
    1372 /* positive redcost -> lb, negative -> ub */
    1373 if( SCIPrationalIsPositive(dualsol[i+nrows]) )
    1374 isupper[i+nrows] = FALSE;
    1375 else
    1376 isupper[i+nrows] = TRUE;
    1377 }
    1378
    1379 /* first, fix artificial dual variables (with infinity bound) to zero */
    1380 for( i = 0; i < nrows + ncols; i++ )
    1381 {
    1382 SCIP_RATIONAL* val;
    1383
    1384 if( !isupper[i] )
    1385 val = i < nrows ? lpexact->rows[i]->lhs : lpexact->cols[i - nrows]->lb;
    1386 else
    1387 val = i < nrows ? lpexact->rows[i]->rhs : lpexact->cols[i - nrows]->ub;
    1388
    1389 if( SCIPrationalIsAbsInfinity(val) )
    1390 SCIPrationalSetFraction(dualsol[i], 0LL, 1LL);
    1391 }
    1392
    1393#ifdef SCIP_DEBUG_PS_OUT
    1394 printf("approximate dual solution:\n");
    1395
    1396 SCIPrationalSetFraction(dualbound, 0LL, 1LL);
    1397 for( i = 0; i < nrows + ncols; i++ )
    1398 {
    1399 SCIP_RATIONAL* val;
    1400
    1401 if( !isupper[i] )
    1402 val = i < nrows ? lpexact->rows[i]->lhs : lpexact->cols[i - nrows]->lb;
    1403 else
    1404 val = i < nrows ? lpexact->rows[i]->rhs : lpexact->cols[i - nrows]->ub;
    1405
    1406 SCIPrationalPrintf(" i=%d: %q * %q \n", i, dualsol[i], val);
    1407 if( SCIPrationalIsAbsInfinity(val) )
    1408 assert(SCIPrationalIsZero(dualsol[i]));
    1409 else
    1410 {
    1411 if( i < nrows )
    1412 SCIPrationalDiff(tmp, val, lpexact->rows[i]->constant);
    1413 else
    1414 SCIPrationalSetRational(tmp, val);
    1415 SCIPrationalMult(tmp, dualsol[i], tmp);
    1416 SCIPrationalAdd(dualbound, dualbound, tmp);
    1417 }
    1418 }
    1419
    1420 SCIPrationalPrintf(" objective value=%f (%q) \n", SCIPrationalGetReal(dualbound), dualbound);
    1421#endif
    1422
    1423 /* calculate violation of equality constraints r=c-A^ty */
    1424 for( i = 0; i < ncols; i++ )
    1425 {
    1426 /* instead of setting and then subtracting the A^ty corresponding to bound constraints, we can do this directly */
    1427 if( !usefarkas )
    1428 {
    1429 /* set to obj - bound-redcost */
    1430 SCIPrationalDiff(violation[i], lpexact->cols[i]->obj, dualsol[i + nrows]);
    1431 }
    1432 else
    1433 {
    1434 /* set to 0 - bound-redcost */
    1435 SCIPrationalNegate(violation[i], dualsol[i+nrows]);
    1436 }
    1437 }
    1438
    1439 /* A^ty for y corresponding to primal constraints */
    1440 for( i = 0; i < nrows; i++ )
    1441 {
    1442 for( j = 0; j < lpexact->rows[i]->len; j++)
    1443 {
    1444 currentrow = lpexact->rows[i]->cols_index[j];
    1445 SCIPrationalMult(tmp, dualsol[i], lpexact->rows[i]->vals[j]);
    1446 SCIPrationalDiff(violation[currentrow], violation[currentrow], tmp);
    1447 }
    1448 }
    1449
    1450 /* project solution */
    1451#ifdef SCIP_DEBUG_PS_OUT
    1452 printf("violation of solution:\n");
    1453 for( i = 0; i < ncols; i++ )
    1454 {
    1455 printf(" i=%d: ", i);
    1456 SCIPrationalPrint(violation[i]);
    1457 printf("\n");
    1458 }
    1459#endif
    1460
    1461 /* if there is no violation of the constraints, then skip the projection */
    1462 isfeas = TRUE;
    1463 for( i = 0; i < ncols && isfeas; i++ )
    1464 {
    1465 if( !SCIPrationalIsZero(violation[i]) )
    1466 isfeas = FALSE;
    1467 }
    1468
    1469 /* isfeas is equal to one only if approximate dual solution is already feasible for the dual */
    1470 if( !isfeas )
    1471 {
    1472 /* compute projection [z] with Dz=r (D is pre-determined submatrix of extended dual matrix [A', -A', I, -I]) */
    1473 SCIP_CALL( SCIPsetAllocBufferArray(set, &violationgmp, ncols) );
    1474 SCIP_CALL( SCIPsetAllocBufferArray(set, &correctiongmp, nextendedrows) );
    1475 SCIPrationalSetGMPArray(violationgmp, violation, ncols);
    1476
    1477 for ( i = 0; i < nextendedrows; i++)
    1478 {
    1479 mpq_init(correctiongmp[i]);
    1480 }
    1481
    1482#if defined SCIP_WITH_GMP && defined SCIP_WITH_EXACTSOLVE
    1483 rval = RECTLUsolveSystem(projshiftdata->rectfactor, ncols, nextendedrows, violationgmp, correctiongmp);
    1484#else
    1485 rval = 1;
    1486#endif
    1487
    1488 /* rval = 0 -> fail */
    1489 if( rval ) /* cppcheck-suppress knownConditionTrueFalse */
    1490 {
    1491 lp->hasprovedbound = FALSE;
    1492 if( usefarkas )
    1493 stat->nfailprojshiftinf++;
    1494 else
    1495 stat->nfailprojshift++;
    1496
    1497 goto TERMINATE;
    1498 }
    1499
    1500 SCIPrationalSetArrayGMP(correction, correctiongmp, nextendedrows);
    1501
    1502#ifdef SCIP_DEBUG_PS_OUT
    1503 printf("correction of solution:\n");
    1504 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    1505 {
    1506 printf(" i=%d: ", i);
    1507 SCIPrationalPrint(correction[i]);
    1508 printf(", position=%d\n", projshiftdata->projshiftbasis[i]);
    1509 }
    1510#endif
    1511
    1512 /* projection step: compute bold(y)=y^+[z 0];
    1513 * save the corrected components in the correction vector; reset the dualsol-vector to 0
    1514 */
    1515 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    1516 {
    1517 /* map is the point in the extended space (A', -A', I, -I)-dual-matrix -> transform it back to the original space */
    1518 int map = projshiftdata->projshiftbasis[i];
    1519 /* [0, ..., nrows] is a lhs-row of A */
    1520 if( map < nrowsps )
    1521 {
    1522 if( !isupper[map] )
    1523 {
    1524 SCIPrationalAdd(correction[i], correction[i], dualsol[map]);
    1525 SCIPrationalSetFraction(dualsol[map], 0LL, 1LL);
    1526 }
    1527 }
    1528 /* [nrows, ..., 2*nrows] is a rhs-row of A */
    1529 else if( map < 2 * nrowsps )
    1530 {
    1531 if( isupper[map - nrowsps] )
    1532 {
    1533 SCIPrationalDiff(correction[i], correction[i], dualsol[map - nrowsps]);
    1534 SCIPrationalSetFraction(dualsol[map - nrowsps], 0LL, 1LL);
    1535 }
    1536 }
    1537 /* [2*nrows, ..., 2*nrows+ncols] is a lb-col */
    1538 else if( map < 2 * nrowsps + ncols )
    1539 {
    1540 if( !isupper[map - nrowsps + shift] )
    1541 {
    1542 SCIPrationalAdd(correction[i], correction[i], dualsol[map - nrowsps + shift]);
    1543 SCIPrationalSetFraction(dualsol[map - nrowsps + shift], 0LL, 1LL);
    1544 }
    1545 }
    1546 /* [2*nrows+ncols, ..., 2*nrows+2*ncols] is a ub-col */
    1547 else
    1548 {
    1549 if( isupper[map - nrowsps - ncols + shift] )
    1550 {
    1551 SCIPrationalDiff(correction[i], correction[i], dualsol[map - nrowsps - ncols + shift]);
    1552 SCIPrationalSetFraction(dualsol[map - nrowsps - ncols + shift], 0LL, 1LL);
    1553 }
    1554 }
    1555 }
    1556
    1557#ifdef SCIP_DEBUG_PS_OUT
    1558 printf("updated dual solution:\n");
    1559 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    1560 {
    1561 printf(" i=%d: ", i);
    1562 SCIPrationalPrint(correction[i]);
    1563 printf(", position=%d\n", projshiftdata->projshiftbasis[i]);
    1564 }
    1565#endif
    1566
    1567 if( useinteriorpoint )
    1568 {
    1569 assert(!usefarkas);
    1570 /* shifting step (scale solution with interior point to be dual feasible):
    1571 * y' = lambda1 bold(y) + lambda2 y*, where
    1572 * lambda1 = MIN{( slack of int point)/ (slack of int point + max violation) = d/m+d}
    1573 * lambda2 = 1 - lambda1
    1574 */
    1575
    1576 /* compute lambda1 componentwise (set lambda1 = 1 and lower it if necessary) */
    1577 SCIPrationalSetFraction(lambda1, 1LL, 1LL);
    1578 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    1579 {
    1580 if( SCIPrationalIsNegative(correction[i]) )
    1581 {
    1582 int map = projshiftdata->projshiftbasis[i];
    1583
    1584 SCIPrationalSetRational(tmp2, projshiftdata->interiorpoint[map]);
    1585 SCIPrationalDiff(tmp, projshiftdata->interiorpoint[map], correction[i]);
    1586 SCIPrationalDiv(tmp2, tmp2, tmp);
    1587 SCIPrationalMin(lambda1, lambda1, tmp2);
    1588 }
    1589 }
    1590 SCIPrationalSetFraction(lambda2, 1LL, 1LL);
    1591 SCIPrationalDiff(lambda2, lambda2, lambda1);
    1592 }
    1593 else
    1594 {
    1595 /* in this case we are using an interior ray that can be added freely to the solution */
    1596 /* compute lambda values: compute lambda1 componentwise (set lambda1 = 1 and lower it if necessary) */
    1597 SCIPrationalSetFraction(lambda1, 1LL, 1LL);
    1598 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    1599 {
    1600 int map = projshiftdata->projshiftbasis[i];
    1601 if( SCIPrationalIsNegative(correction[i]) && projshiftdata->includedrows[map] )
    1602 {
    1603 SCIPrationalDiv(tmp, correction[i], projshiftdata->interiorray[map]);
    1604 SCIPrationalNegate(tmp, tmp);
    1605 SCIPrationalMax(lambda2, lambda2, tmp);
    1606 }
    1607 }
    1608 }
    1609
    1610#ifdef SCIP_DEBUG_PS_OUT
    1611 printf("transformed projected dual solution:\n");
    1612
    1613 for( i = 0; i < nrows + ncols; i++ )
    1614 {
    1615 printf(" i=%d: ", i);
    1616 SCIPrationalPrint(dualsol[i]);
    1617 printf("\n");
    1618 }
    1619
    1620 printf(" lambda1: ");
    1621 SCIPrationalPrint(lambda1);
    1622 printf(")\n");
    1623#endif
    1624
    1625 /* tranfsorm correction back to dualsol */
    1626 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
    1627 {
    1628 int map = projshiftdata->projshiftbasis[i];
    1629 if( map < nrowsps )
    1630 SCIPrationalAdd(dualsol[map], dualsol[map], correction[i]);
    1631 else if( map < 2 * nrowsps )
    1632 SCIPrationalDiff(dualsol[map - nrowsps], dualsol[map - nrowsps], correction[i]);
    1633 else if ( map < 2 * nrowsps + ncols )
    1634 SCIPrationalAdd(dualsol[map - nrowsps + shift], dualsol[map - nrowsps + shift], correction[i]);
    1635 else
    1636 SCIPrationalDiff(dualsol[map - nrowsps - ncols + shift], dualsol[map - nrowsps - ncols + shift], correction[i]);
    1637 }
    1638
    1639#ifdef SCIP_DEBUG_PS_OUT
    1640 printf("transformed projected dual solution:\n");
    1641
    1642 for( i = 0; i < nrows + ncols; i++ )
    1643 {
    1644 printf(" i=%d: ", i);
    1645 SCIPrationalPrint(dualsol[i]);
    1646 printf("\n");
    1647 }
    1648
    1649 printf(" lambda1: ");
    1650 SCIPrationalPrint(lambda1);
    1651 printf(")\n");
    1652#endif
    1653
    1654 /* perform shift */
    1655 if( !SCIPrationalIsZero(lambda2) )
    1656 {
    1657 for( i = 0; i < nrows + ncols; i++ )
    1658 {
    1659 SCIPrationalMult(dualsol[i], dualsol[i], lambda1);
    1660 }
    1661 for( i = 0; i < nrows + ncols; i++ )
    1662 {
    1663 /* explanation: when the number of lp-rows increased the number of rows in the ps-data does not.
    1664 * Therefore, we have [1,...,nrows, ... extrarows ..., 1, ... ncols]
    1665 * so if we map to the column part in the extended space, we have to subtract the difference */
    1666 int map;
    1667 if( i < nrows && i >= nrowsps )
    1668 continue;
    1669 map = (i < nrowsps) ? i + nrowsps : i + nrowsps + ncols - shift;
    1670 SCIPrationalMult(tmp, useinteriorpoint ? projshiftdata->interiorpoint[map] : projshiftdata->interiorray[map], lambda2);
    1671 SCIPrationalDiff(dualsol[i], dualsol[i], tmp);
    1672 map = (i < nrowsps) ? i : i + nrowsps - shift;
    1673 SCIPrationalMult(tmp, useinteriorpoint ? projshiftdata->interiorpoint[map] : projshiftdata->interiorray[map], lambda2);
    1674 SCIPrationalAdd(dualsol[i], dualsol[i], tmp);
    1675 }
    1676 }
    1677
    1678#ifdef SCIP_DEBUG_PS_OUT
    1679 printf("projected and shifted dual solution (should be an exact dual feasible solution)\n");
    1680 for( i = 0; i < nrows+ncols; i++ )
    1681 {
    1682 SCIPrationalPrintf(" i=%d: %f.20 (%q) \n", i, SCIPrationalGetReal(dualsol[i]), dualsol[i]);
    1683 }
    1684#endif
    1685 }
    1686
    1687#ifndef NDEBUG
    1688 SCIPdebugMessage("debug test: verifying feasibility of dual solution:\n");
    1689
    1690 /* calculate violation of equality constraints: subtract Ax to get violation b-Ax, subtract A(dualsol) */
    1691 rval = 0;
    1692 for( i = 0; i < ncols; i++ )
    1693 {
    1694 if( !usefarkas )
    1695 SCIPrationalSetRational(violation[i], lpexact->cols[i]->obj);
    1696 else
    1697 SCIPrationalSetFraction(violation[i], 0LL, 1LL);
    1698 }
    1699 for( i = 0; i < nrows; i++ )
    1700 {
    1701 if( !SCIPrationalIsZero(dualsol[i]) )
    1702 {
    1703 SCIPrationalDebugMessage("row %s has multiplier %q: ", lpexact->rows[i]->fprow->name, dualsol[i]);
    1704 SCIPdebug(SCIProwExactPrint(lpexact->rows[i], messagehdlr, NULL));
    1705 }
    1706 for( j = 0; j < lpexact->rows[i]->len; j++ )
    1707 {
    1708 currentrow = lpexact->rows[i]->cols_index[j];
    1709 SCIPrationalMult(tmp, dualsol[i], lpexact->rows[i]->vals[j]);
    1710 SCIPrationalDiff(violation[currentrow], violation[currentrow], tmp);
    1711 }
    1712 }
    1713 for( i = 0; i < ncols; i++ )
    1714 {
    1715 if( !SCIPrationalIsZero(lpexact->cols[i]->farkascoef) )
    1716 {
    1717 SCIPrationalDebugMessage("variable %q <= %s <= %q has farkas coefficient %q \n", lpexact->cols[i]->lb,
    1718 SCIPvarGetName(lpexact->cols[i]->var), lpexact->cols[i]->ub, lpexact->cols[i]->farkascoef);
    1719 }
    1720 SCIPrationalDiff(violation[i], violation[i], dualsol[i + nrows]);
    1721 }
    1722
    1723 for( i = 0; i < ncols && rval == 0; i++ )
    1724 {
    1725 if( !SCIPrationalIsZero(violation[i]) )
    1726 {
    1727 SCIPdebugMessage(" dual solution incorrect, violates equalities\n");
    1728 rval = 1;
    1729 }
    1730 }
    1731 if( !rval )
    1732 SCIPdebugMessage(" dual solution verified\n");
    1733 assert(!rval);
    1734#endif
    1735
    1736 SCIPrationalSetFraction(dualbound, 0LL, 1LL);
    1737 for( i = 0; i < nrows + ncols; i++ )
    1738 {
    1739 SCIP_RATIONAL* val;
    1740 if( SCIPrationalIsPositive(dualsol[i]) )
    1741 val = i < nrows ? lpexact->rows[i]->lhs : lpexact->cols[i - nrows]->lb;
    1742 else
    1743 val = i < nrows ? lpexact->rows[i]->rhs : lpexact->cols[i - nrows]->ub;
    1744
    1745 if( i < nrows )
    1746 SCIPrationalDiff(tmp, val, lpexact->rows[i]->constant);
    1747 else
    1748 SCIPrationalSetRational(tmp, val);
    1749 SCIPrationalMult(tmp, dualsol[i], tmp);
    1750 SCIPrationalAdd(dualbound, dualbound, tmp);
    1751 }
    1752
    1753 /* since we negate the farkas-coef for the project-shift representation, it has to be negated again here for saving */
    1754 if( usefarkas )
    1755 {
    1756 for( i = nrows; i < ncols + nrows; i++ )
    1757 {
    1758 SCIPrationalNegate(dualsol[i], dualsol[i]);
    1759 }
    1760 }
    1761
    1762 computedbound = SCIPrationalRoundReal(dualbound, SCIP_R_ROUND_DOWNWARDS);
    1763
    1764 if( !usefarkas )
    1765 {
    1767 && computedbound < SCIPlpGetCutoffbound(lp) - SCIPlpGetLooseObjval(lp, set, prob) )
    1768 {
    1769 *safebound = computedbound;
    1770 stat->nfailprojshift++;
    1771 stat->nprojshiftobjlimfail++;
    1772 assert(!lp->hasprovedbound);
    1773 }
    1774 else if( SCIPrationalIsGTReal(dualbound, -SCIPsetInfinity(set)) )
    1775 {
    1776 stat->boundingerrorps += REALABS(lp->lpobjval - computedbound);
    1777 SCIPrationalSetRational(lpexact->lpobjval, dualbound);
    1778 *safebound = computedbound;
    1779 lp->lpobjval = *safebound;
    1780 lp->hasprovedbound = TRUE;
    1781 }
    1782 else
    1783 {
    1784 lp->hasprovedbound = FALSE;
    1785 stat->nfailprojshift++;
    1786 }
    1787 }
    1788 else
    1789 {
    1790 /* if the objective value of the corrected ray is positive we can prune node, otherwise not */
    1791 if( SCIPrationalIsPositive(dualbound) )
    1792 {
    1795 lp->hasprovedbound = TRUE;
    1796 }
    1797 else
    1798 {
    1799 stat->nfailprojshiftinf++;
    1800 lp->hasprovedbound = FALSE;
    1801 }
    1802 }
    1803
    1804#ifdef SCIP_DEBUG_PS_OUT
    1805 printf(" common slack=%.20f (", SCIPrationalGetReal(projshiftdata->commonslack));
    1806 SCIPrationalPrint(projshiftdata->commonslack);
    1807 printf(")\n");
    1808
    1809 printf(" max violation=%.20f (", SCIPrationalGetReal(maxv));
    1810 SCIPrationalPrint(maxv);
    1811 printf(")\n");
    1812
    1813 printf(" lambda (use of interior point)=%.20f (", SCIPrationalGetReal(lambda2));
    1814 SCIPrationalPrint(lambda2);
    1815 printf(")\n");
    1816
    1817 printf(" dual objective value=%.20f (", SCIPrationalGetReal(dualbound));
    1818 SCIPrationalPrint(dualbound);
    1819 printf(")\n");
    1820#endif
    1821
    1822 TERMINATE:
    1823 /* free memory */
    1824 if( correctiongmp != NULL )
    1825 {
    1826 SCIPrationalClearArrayGMP(correctiongmp, nextendedrows);
    1827 SCIPsetFreeBufferArray(set, &correctiongmp);
    1828 }
    1829 if( violationgmp != NULL )
    1830 {
    1831 SCIPrationalClearArrayGMP(violationgmp, ncols);
    1832 SCIPsetFreeBufferArray(set, &violationgmp);
    1833 }
    1834
    1835 SCIPsetFreeBufferArray(set, &isupper);
    1836 SCIPsetFreeBufferArray(set, &dualsol);
    1837
    1838 SCIPrationalFreeBuffer(set->buffer, &dualbound);
    1839 SCIPrationalFreeBuffer(set->buffer, &maxv);
    1840 SCIPrationalFreeBuffer(set->buffer, &lambda2);
    1841 SCIPrationalFreeBuffer(set->buffer, &lambda1);
    1842 SCIPrationalFreeBuffer(set->buffer, &tmp2);
    1843 SCIPrationalFreeBuffer(set->buffer, &tmp);
    1844
    1845 if( usefarkas )
    1847 else
    1849
    1850 return SCIP_OKAY;
    1851}
    1852#endif
    1853
    1854/** chooses which bounding method to use at first attempt to provide safe bound for current lp */
    1855static
    1856char chooseInitialBoundingMethod(
    1857 SCIP_LPEXACT* lpexact, /**< exact LP data */
    1858 SCIP_SET* set, /**< global SCIP settings */
    1859 SCIP_STAT* stat, /**< SCIP statistics */
    1860 SCIP_PROB* prob /**< problem data */
    1861 )
    1862{
    1863 char dualboundmethod;
    1864 SCIP_Bool interleavedepth;
    1865 SCIP_Bool interleavecutoff;
    1866
    1867 assert(lpexact != NULL);
    1868 assert(set != NULL);
    1869
    1870 /* at the root node always call exact LP solve if allowed, i.e., after separation */
    1871 if( set->scip->stat->nnodes == 1 && lpexact->allowexactsolve )
    1872 dualboundmethod = 'e';
    1873 /* check for other reasons to solve exactly */
    1874 else if( lpexact->forceexactsolve || SCIPlpGetSolstat(lpexact->fplp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
    1875 dualboundmethod = 'e';
    1876 /* if the LP was solved to optimality and there are no fractional variables we solve exactly to generate a feasible
    1877 * solution
    1878 */
    1879 else if( (SCIPlpGetSolstat(lpexact->fplp) == SCIP_LPSOLSTAT_OPTIMAL && fpLPisIntFeasible(lpexact->fplp, set)) && lpexact->allowexactsolve )
    1880 {
    1881 dualboundmethod = 'e';
    1882 stat->nexlpintfeas++;
    1883 }
    1884 /* if we are not in automatic mode, try an iteration with the static method */
    1885 else if( set->exact_safedbmethod != 'a' )
    1886 {
    1887 dualboundmethod = set->exact_safedbmethod;
    1888 }
    1889 /* select automatically which bounding method to apply */
    1890 else
    1891 {
    1892 /* decide whether we want to interleave with exact LP call given freq: we do this if we are
    1893 * a) at depth levels 2, 4, 8, 16, ..., or
    1894 * b) almost at cutoffbound
    1895 */
    1896 interleavedepth = set->exact_interleavedbstrat >= 2 && SCIPgetDepth(set->scip) > 1 && isPowerOfTwo(SCIPgetDepth(set->scip));
    1897 interleavecutoff = (set->exact_interleavedbstrat == 1 || set->exact_interleavedbstrat == 3)
    1898 && SCIPsetIsGE(set, SCIPlpGetObjval(lpexact->fplp, set, prob), SCIPlpGetCutoffbound(lpexact->fplp))
    1899 && SCIPlpGetObjval(lpexact->fplp, set, prob) < SCIPlpGetCutoffbound(lpexact->fplp);
    1900 if( (interleavedepth || interleavecutoff) && lpexact->allowexactsolve )
    1901 {
    1902 if( interleavedepth )
    1903 stat->nexlpinter++;
    1904 else
    1905 stat->nexlpboundexc++;
    1906 dualboundmethod = 'e';
    1907 }
    1908 else
    1909 {
    1910 /* check if Neumaier-Shcherbina is possible */
    1911 if( SCIPlpExactBoundShiftUseful(lpexact) )
    1912 dualboundmethod = 'n';
    1913 /* check if project and shift is possible */
    1914 else if( SCIPlpExactProjectShiftPossible(lpexact) )
    1915 dualboundmethod = 'p';
    1916 /* otherwise solve exactly */
    1917 else
    1918 dualboundmethod = 'e';
    1919 }
    1920 }
    1921
    1922 assert(dualboundmethod != 'u');
    1923
    1924 return dualboundmethod;
    1925}
    1926
    1927/** chooses which bounding method to use after failed attempt to provide safe bound for current lp */
    1928static
    1929char chooseFallbackBoundingMethod(
    1930 SCIP_LPEXACT* lpexact, /**< exact LP data */
    1931 SCIP_SET* set, /**< global SCIP settings */
    1932 char lastboundmethod /**< last attempted dual bounding method */
    1933 )
    1934{
    1935 char dualboundmethod;
    1936
    1937 assert(lpexact != NULL);
    1938 assert(set != NULL);
    1939
    1940 switch( lastboundmethod )
    1941 {
    1942 case 'n':
    1943 /* bound-shift -> try project shift next if possible, otherwise exactlp */
    1944 dualboundmethod = SCIPlpExactProjectShiftPossible(lpexact) ? 'p' : 'e';
    1945 break;
    1946 case 'p':
    1947 /* project-shift -> try exactlp next */
    1948 dualboundmethod = 'e';
    1949 break;
    1950 case 'e':
    1951 /* exactlp -> try bound shift next, if possible, otherwise project-shift, if possible,
    1952 * otherwise try exactlp again
    1953 */
    1954 if( SCIPlpExactBoundShiftUseful(lpexact) )
    1955 dualboundmethod = 'n';
    1956 else
    1957 dualboundmethod = SCIPlpExactProjectShiftPossible(lpexact) ? 'p' : 't';
    1958 break;
    1959 default:
    1960 /* else -> return unknown */
    1961 SCIPerrorMessage("unknown bounding method in chooseBoundingMethod \n");
    1962 SCIPABORT();
    1963 dualboundmethod = 't';
    1964 break;
    1965 }
    1966
    1967 return dualboundmethod;
    1968}
    1969
    1970/* choose the next bounding method for safe dual bounding */
    1971static
    1972char chooseBoundingMethod(
    1973 SCIP_LPEXACT* lpexact, /**< exact LP data */
    1974 SCIP_SET* set, /**< global SCIP settings */
    1975 SCIP_STAT* stat, /**< SCIP statistics */
    1976 SCIP_PROB* prob, /**< problem data */
    1977 char lastboundmethod /**< the last method that was chosen */
    1978 )
    1979{
    1980 assert(!lpexact->fplp->hasprovedbound);
    1981
    1982 /* choose which bounding method to use */
    1983 if( lastboundmethod == 'u' )
    1984 return chooseInitialBoundingMethod(lpexact, set, stat, prob);
    1985 else
    1986 return chooseFallbackBoundingMethod(lpexact, set, lastboundmethod);
    1987}
    1988
    1989/** calculates a valid dual bound/farkas proof if all variables have lower and upper bounds
    1990 * Let (y,z) be the dual variables, y corresponding to primal rows, z to variable bounds.
    1991 * An exactly feasible dual solution is computed with y' = max{0,y}, z'=max{0,(c-A^Ty')}.
    1992 * The bound is then computed as b^Ty'+s^Tz', with b being the lhs/rhs and s the lb/ub depending on the
    1993 * sign of the dual value.
    1994 * To avoid rational computations everything is done in interval arithmetic.
    1995 */
    1996static
    1997SCIP_RETCODE boundShift(
    1998 SCIP_LP* lp, /**< LP data */
    1999 SCIP_LPEXACT* lpexact, /**< exact LP data */
    2000 SCIP_SET* set, /**< global SCIP settings */
    2001 BMS_BLKMEM* blkmem, /**< block memory buffers */
    2002 SCIP_STAT* stat, /**< problem statistics */
    2003 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2004 SCIP_PROB* prob, /**< problem data */
    2005 SCIP_Bool usefarkas, /**< should an infeasibility proof be computed? */
    2006 SCIP_Real* safebound /**< pointer to store the computed safe bound (usually lpobj) */
    2007 )
    2008{
    2009 SCIP_INTERVAL* rhslhsrow;
    2010 SCIP_INTERVAL* ublbcol;
    2011 SCIP_INTERVAL* constantinter;
    2012 SCIP_INTERVAL* lpcolvals;
    2013 SCIP_INTERVAL* productcoldualval;
    2014 SCIP_INTERVAL* obj;
    2015 SCIP_INTERVAL productsidedualval;
    2016 SCIP_INTERVAL safeboundinterval;
    2017 SCIP_ROW* row;
    2018 SCIP_COL* col;
    2019 SCIP_COLEXACT* colexact;
    2020 SCIP_Real* fpdual;
    2021 SCIP_Real* fpdualcolwise;
    2022 SCIP_Real computedbound;
    2023 int i;
    2024 int j;
    2025
    2026 assert(lp != NULL);
    2027 assert(lp->solved);
    2028 assert(lpexact != NULL);
    2029 assert(set != NULL);
    2030 assert(safebound != NULL);
    2031
    2032 if( !SCIPlpExactBoundShiftUseful(lpexact) )
    2033 return SCIP_OKAY;
    2034
    2035 /* start timing */
    2036 if ( usefarkas )
    2038 else
    2040
    2041 /* allocate temporarfpdual memory */
    2042 SCIP_CALL( SCIPsetAllocBufferArray(set, &fpdual, lp->nrows) );
    2043 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhslhsrow, lp->nrows) );
    2044 SCIP_CALL( SCIPsetAllocBufferArray(set, &constantinter, lp->nrows) );
    2045 SCIP_CALL( SCIPsetAllocBufferArray(set, &fpdualcolwise, lp->nrows) );
    2046 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpcolvals, lp->nrows) );
    2047 SCIP_CALL( SCIPsetAllocBufferArray(set, &productcoldualval, lp->ncols) );
    2049 SCIP_CALL( SCIPsetAllocBufferArray(set, &ublbcol, lp->ncols) );
    2050
    2051 SCIPdebugMessage("calling proved bound for %s LP\n", usefarkas ? "infeasible" : "feasible");
    2052
    2053 SCIP_CALL( SCIPlpExactSyncLPs(lpexact, blkmem, set) );
    2054 SCIP_CALL( SCIPlpExactLink(lpexact, blkmem, set, eventqueue) );
    2055
    2056 /* reset proved bound status */
    2057 lp->hasprovedbound = FALSE;
    2058
    2059 /* calculate y^Tb */
    2060 SCIPintervalSet(&productsidedualval, 0.0);
    2061 SCIPdebugMessage("productsidedualval interval computation with vectors:\n");
    2062
    2063 /* create dual vector, sides and constant vector in interval arithmetic */
    2064 for( j = 0; j < lp->nrows; ++j )
    2065 {
    2066 row = lp->rows[j];
    2067 assert(row != NULL);
    2068
    2069 /* create dual vector in interval arithmetic, setting near zeros to zero */
    2070 fpdual[j] = (usefarkas ? row->dualfarkas : row->dualsol);
    2071
    2072 if( SCIPlpiIsInfinity(lp->lpi, fpdual[j]) )
    2073 fpdual[j] = SCIPsetInfinity(set);
    2074
    2075 if( SCIPlpiIsInfinity(lp->lpi, -fpdual[j]) )
    2076 fpdual[j] = -SCIPsetInfinity(set);
    2077
    2078 /** @todo test whether safe dual bounding in exact solving mode can be improved by setting nonzero values of y to
    2079 * zero if corresponding lhs/rhs is not finite (do such situations come up?)
    2080 */
    2081 /* create sides and constant vectors in interval arithmetic */
    2082 if( SCIPsetIsFeasPositive(set, fpdual[j]) )
    2083 {
    2084 SCIPintervalSet(&rhslhsrow[j], row->lhs);
    2085 SCIPintervalSet(&constantinter[j], -1.0 * row->constant);
    2086 }
    2087 else if( SCIPsetIsFeasNegative(set, fpdual[j]) )
    2088 {
    2089 SCIPintervalSet(&rhslhsrow[j], row->rhs);
    2090 SCIPintervalSet(&constantinter[j], -1.0 * row->constant);
    2091 }
    2092 else
    2093 {
    2094 fpdual[j] = 0.0;
    2095 SCIPintervalSet(&rhslhsrow[j], 0.0);
    2096 SCIPintervalSet(&constantinter[j], 0.0);
    2097 }
    2098
    2099 SCIPdebugMessage(" j=%d: b=[%g,%g] (lhs=%g, rhs=%g, const=%g, fpdual=%g)\n", j, rhslhsrow[j].inf, rhslhsrow[j].sup, row->lhs,
    2100 row->rhs, row->constant, fpdual[j]);
    2101 }
    2102 /* subtract constant from sides in interval arithmetic and calculate fpdual * side */
    2103 SCIPintervalAddVectors(SCIPsetInfinity(set), rhslhsrow, lp->nrows, rhslhsrow, constantinter);
    2104 SCIPintervalScalprodScalars(SCIPsetInfinity(set), &productsidedualval, lp->nrows, rhslhsrow, fpdual);
    2105
    2106 SCIPdebugMessage(" resulting scalar product=[%g,%g]\n", SCIPintervalGetInf(productsidedualval), SCIPintervalGetSup(productsidedualval));
    2107
    2108 /* calculate min{(obj - dual^TMatrix)redcost} */
    2109 for( j = 0; j < lp->ncols; ++j )
    2110 {
    2111 col = lp->cols[j];
    2112 assert(col != NULL);
    2113 assert(col->nunlinked == 0);
    2114
    2115 colexact = SCIPcolGetColExact(col);
    2116
    2117 assert(colexact != NULL);
    2118
    2119 /* create -Matrix.j vector in interval arithmetic and corresponding dual vector and compute infimum of vector -Matrix.j^Tdual */
    2120 for( i = 0; i < colexact->nlprows; ++i )
    2121 {
    2122 SCIP_INTERVAL val;
    2123 SCIP_ROWEXACT* rowexact;
    2124
    2125 assert(colexact->rows[i] != NULL);
    2126 assert(colexact->rows[i]->lppos >= 0);
    2127 assert(colexact->linkpos[i] >= 0);
    2128
    2129 rowexact = colexact->rows[i];
    2130
    2131 val = rowexact->valsinterval[colexact->linkpos[i]];
    2132 assert(SCIPrationalIsGEReal(colexact->vals[i], val.inf) && SCIPrationalIsLEReal(colexact->vals[i], val.sup));
    2133
    2134 SCIPintervalSetBounds(&lpcolvals[i], -val.sup, -val.inf);
    2135 fpdualcolwise[i] = fpdual[colexact->rows[i]->lppos];
    2136 }
    2137 productcoldualval[j].inf = 0.0;
    2138 productcoldualval[j].sup = 0.0;
    2139 SCIPintervalScalprodScalars(SCIPsetInfinity(set), &productcoldualval[j], colexact->nlprows, lpcolvals, fpdualcolwise);
    2140
    2141#ifndef NDEBUG
    2142 for( i = colexact->nlprows; i < colexact->len; ++i )
    2143 {
    2144 assert(colexact->rows[i] != NULL);
    2145 assert(colexact->rows[i]->lppos == -1);
    2146 assert(colexact->linkpos[i] >= 0);
    2147 }
    2148#endif
    2149 }
    2150
    2151 /* create objective vector and lb/ub vector in interval arithmetic and compute min{(obj^T - dual^TMatrix)lb/ub} */
    2152 for( j = 0; j < lp->ncols; ++j )
    2153 {
    2154 col = lp->cols[j];
    2155 assert(col != NULL);
    2156 assert(col->nunlinked == 0);
    2157
    2158 if( usefarkas )
    2159 SCIPintervalSet(&obj[j], 0.0);
    2160 else
    2161 {
    2162 obj[j] = SCIPvarGetObjInterval(SCIPcolGetVar(col));
    2165 }
    2166
    2169 SCIPintervalSetBounds(&ublbcol[j], SCIPcolGetLb(col), SCIPcolGetUb(col));
    2170
    2171 /* opt out if there are infinity bounds and a non-infinity value */
    2173 {
    2174 if( productcoldualval[j].inf + obj[j].inf != 0 || productcoldualval[j].sup + obj[j].sup != 0 )
    2175 {
    2176 SCIPdebugMessage("trying bound shift with unbounded column variable. Column %d, lb: %e, ub %e \n",
    2177 SCIPcolGetIndex(col), SCIPcolGetLb(col) ,SCIPcolGetUb(col) );
    2178 SCIPdebugMessage("Multiplied with interval: min %e, max %e \n",
    2179 productcoldualval[j].inf + obj[j].inf, productcoldualval[j].sup + obj[j].sup);
    2180
    2181 lp->hasprovedbound = FALSE;
    2182 if( usefarkas )
    2183 {
    2184 stat->nboundshiftinf++;
    2185 stat->nfailboundshiftinf++;
    2187 }
    2188 else
    2189 {
    2190 stat->nboundshift++;
    2191 stat->nfailboundshift++;
    2193 }
    2194 goto CLEANUP;
    2195 }
    2196 }
    2197 }
    2198
    2199 SCIPintervalAddVectors(SCIPsetInfinity(set), productcoldualval, lp->ncols, productcoldualval, obj);
    2200 SCIPintervalScalprod(SCIPsetInfinity(set), &safeboundinterval, lp->ncols, productcoldualval, ublbcol);
    2201
    2202 /* add dualsol * rhs/lhs (or farkas * rhs/lhs) */
    2203 SCIPintervalAdd(SCIPsetInfinity(set), &safeboundinterval, safeboundinterval, productsidedualval);
    2204
    2205 computedbound = SCIPintervalGetInf(safeboundinterval);
    2206 SCIPdebugMessage("safebound computed: %e, previous fp-bound: %e, difference %e \n", computedbound, lp->lpobjval, computedbound - lp->lpobjval);
    2207
    2208 /* stop timing and update number of calls and fails, and proved bound status */
    2209 if ( usefarkas )
    2210 {
    2212 stat->nboundshiftinf++;
    2213 *safebound = computedbound;
    2214 if( computedbound <= 0.0 )
    2215 {
    2216 stat->nfailboundshiftinf++;
    2217 assert(!lp->hasprovedbound);
    2218 }
    2219 else
    2220 {
    2222 lp->hasprovedbound = TRUE;
    2223 SCIPdebugMessage("succesfully proved infeasibility \n");
    2224 }
    2226 }
    2227 else
    2228 {
    2230 stat->nboundshift++;
    2232 stat->nboundshiftobjlim++;
    2233 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && computedbound < SCIPlpGetCutoffbound(lp) - SCIPlpGetLooseObjval(lp, set, prob) )
    2234 {
    2235 *safebound = computedbound;
    2236 stat->nfailboundshift++;
    2237 stat->nboundshiftobjlimfail++;
    2238 assert(!lp->hasprovedbound);
    2239 SCIPrationalSetReal(lpexact->lpobjval, SCIPintervalGetInf(safeboundinterval));
    2240 }
    2241 else if( !SCIPsetIsInfinity(set, -1.0 * (computedbound)) )
    2242 {
    2243 stat->boundingerrorbs += REALABS(lp->lpobjval - computedbound);
    2244 *safebound = computedbound;
    2245 lp->hasprovedbound = TRUE;
    2246 SCIPrationalSetReal(lpexact->lpobjval, SCIPintervalGetInf(safeboundinterval));
    2247 }
    2248 else
    2249 {
    2250 stat->nfailboundshift++;
    2251 assert(!lp->hasprovedbound);
    2252 }
    2253 }
    2254
    2255 /* if certificate is active, save the corrected dual solution into the lpexact data */
    2256 if( SCIPisCertified(set->scip) && lp->hasprovedbound )
    2257 {
    2258 /* set up the exact lpi for the current node */
    2259 for( j = 0; j < lpexact->nrows; j++ )
    2260 {
    2261 if( usefarkas )
    2262 SCIPrationalSetReal(lpexact->rows[j]->dualfarkas, fpdual[j]);
    2263 else
    2264 SCIPrationalSetReal(lpexact->rows[j]->dualsol, fpdual[j]);
    2265 }
    2266
    2267 for( j = 0; j < lpexact->ncols; j++ )
    2268 {
    2269 colexact = lpexact->cols[j];
    2270 /* Since VIPR only detects that a constraint cTx>=b dominates some other constraint c'Tx>=b' if c==c', we
    2271 * recompute the exact coefficients for the bound constraints here.
    2272 */
    2273 /** @todo Avoid recomputation by using weak completion in VIPR. */
    2274 if( usefarkas )
    2275 SCIP_CALL( SCIPcolExactCalcFarkasRedcostCoef(colexact, set, colexact->farkascoef, NULL, usefarkas) );
    2276 else
    2277 SCIP_CALL( SCIPcolExactCalcFarkasRedcostCoef(colexact, set, colexact->redcost, NULL, usefarkas) );
    2278 }
    2279 }
    2280
    2281CLEANUP:
    2282
    2283 /* if the fail percentage is higher than 20 % we do not want to waste time trying bound shift again and again */
    2284 if( stat->nboundshift + stat->nboundshiftinf > 10
    2285 && (1.0 * stat->nfailboundshift + stat->nfailboundshiftinf) / (stat->nboundshift + stat->nboundshiftinf) > 0.8 )
    2286 {
    2287 lpexact->boundshiftuseful = FALSE;
    2288 }
    2289 /* free buffer for storing y in interval arithmetic */
    2290 SCIPsetFreeBufferArray(set, &ublbcol);
    2292 SCIPsetFreeBufferArray(set, &productcoldualval);
    2293 SCIPsetFreeBufferArray(set, &lpcolvals);
    2294 SCIPsetFreeBufferArray(set, &fpdualcolwise);
    2295 SCIPsetFreeBufferArray(set, &constantinter);
    2296 SCIPsetFreeBufferArray(set, &rhslhsrow);
    2297 SCIPsetFreeBufferArray(set, &fpdual);
    2298
    2299 return SCIP_OKAY;
    2300}
    2301#endif
    2302
    2303/** computes a safe bound for the current floating point LP */
    2305 SCIP_LP* lp, /**< LP data */
    2306 SCIP_LPEXACT* lpexact, /**< exact LP data */
    2307 SCIP_SET* set, /**< global SCIP settings */
    2308 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    2309 BMS_BLKMEM* blkmem, /**< block memory buffers */
    2310 SCIP_STAT* stat, /**< problem statistics */
    2311 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
    2312 SCIP_PROB* prob, /**< problem data */
    2313 SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occurred */
    2314 SCIP_Bool usefarkas, /**< should infeasibility be proven? */
    2315 SCIP_Real* safebound, /**< pointer to store the calculated safe bound */
    2316 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
    2317 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
    2318 ) /*lint --e{715}*/
    2319{ /*lint --e{715}*/
    2320#ifdef SCIP_WITH_BOOST
    2321 char dualboundmethod;
    2322 char lastboundmethod;
    2323 SCIP_Bool shouldabort;
    2324 int nattempts;
    2325
    2326 /* if we are not in exact solving mode, just return */
    2327 if( !set->exact_enable )
    2328 return SCIP_OKAY;
    2329
    2330 if( !lpexact->forcesafebound && (lp->diving || lp->probing || lp->strongbranchprobing) )
    2331 return SCIP_OKAY;
    2332
    2333 lastboundmethod = 'u';
    2334 shouldabort = FALSE;
    2335 nattempts = 0;
    2336
    2337 assert(set->exact_enable);
    2338 assert(!lp->hasprovedbound);
    2339
    2340 /* we need to construct projshiftdata at the root node */
    2341 if( SCIPgetDepth(set->scip) <= 0 && lpexact->projshiftdata->lpiexact == NULL
    2342 && !lpexact->projshiftdata->projshiftdatacon && !lpexact->projshiftdata->projshiftdatafail )
    2343 {
    2344#ifdef SCIP_WITH_GMP
    2345 SCIP_CALL( constructProjectShiftDataLPIExact(lp, lpexact, set, stat, messagehdlr, eventqueue, prob,
    2346 blkmem) );
    2347#endif
    2348 }
    2349
    2350 while( (!lp->hasprovedbound && !shouldabort) || lpexact->allowexactsolve )
    2351 {
    2352 dualboundmethod = chooseBoundingMethod(lpexact, set, stat, prob, lastboundmethod);
    2353 SCIPdebugMessage("Computing safe bound for LP with status %d using bounding method %c\n",
    2354 SCIPlpGetSolstat(lp), dualboundmethod);
    2355
    2356 /* reset the allow exact solve status */
    2358 nattempts++;
    2359
    2360 /*
    2361 * For the methods used please refer to
    2362 * "Valid Linear Programming Bounds for Exact Mixed-Integer Programming" from Steffy and Wolter (2011)
    2363 */
    2364 switch( dualboundmethod )
    2365 {
    2366 case 'n':
    2367 /* Safe Bounding introduced by Neumaier and Shcherbina (Chapter 2)*/
    2368 *lperror = FALSE;
    2369 SCIP_CALL( boundShift(lp, lpexact, set, blkmem, stat, eventqueue,
    2370 prob, usefarkas, safebound) );
    2371 break;
    2372 #ifdef SCIP_WITH_GMP
    2373 case 'p':
    2374 /* Project-and-Shift (Chapter 3)*/
    2375 *lperror = FALSE;
    2376 SCIP_CALL( projectShift(lp, lpexact, set, stat, messagehdlr, eventqueue,
    2377 prob, blkmem, usefarkas, safebound) );
    2378 break;
    2379 #endif
    2380 case 'e':
    2381 /* exact LP */
    2382 SCIP_CALL( SCIPlpExactSolveAndEval(lpexact, lp, set, messagehdlr, blkmem, stat, eventqueue,
    2383 prob, set->lp_iterlim, lperror, usefarkas) );
    2384 if( *lperror )
    2385 {
    2386 if( !usefarkas )
    2387 stat->nfailexlp++;
    2388 else
    2389 stat->nfailexlpinf++;
    2390 }
    2391 *primalfeasible = lpexact->primalfeasible;
    2392 *dualfeasible = lpexact->dualfeasible;
    2393 break;
    2394 case 't':
    2395 /* terminate */
    2396 SCIPdebugMessage("could not find suitable bounding method \n");
    2397 break;
    2398 default:
    2399 SCIPerrorMessage("bounding method %c not implemented yet \n", dualboundmethod);
    2400 SCIPABORT();
    2401 break;
    2402 }
    2403
    2404 lastboundmethod = dualboundmethod;
    2405
    2406 /* we fail if we tried all available methods, or if we had to solve the lp exactly but could not */
    2407 if( (lpexact->forceexactsolve && (*lperror)) || (nattempts >= 3 && !lp->hasprovedbound) || (lastboundmethod == 't') )
    2408 {
    2409 SCIPdebugMessage("failed safe bounding call after %d attempts to compute safe bound\n", nattempts);
    2410 shouldabort = TRUE;
    2411 *lperror = TRUE;
    2412 }
    2413 if( lpexact->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT )
    2414 shouldabort = TRUE;
    2415 }
    2416#endif
    2417 if( *lperror && lp->lpsolstat != SCIP_LPSOLSTAT_TIMELIMIT && lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT )
    2418 {
    2419 lp->solved = FALSE;
    2421 }
    2422
    2423 /* reset the forceexactsolve flag */
    2424 lpexact->forceexactsolve = FALSE;
    2425 lpexact->wasforcedsafebound = lpexact->forcesafebound;
    2426 lpexact->forcesafebound = FALSE;
    2427 if( lp->hasprovedbound )
    2428 *dualfeasible = TRUE;
    2429
    2430 return SCIP_OKAY;
    2431}
    void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:360
    void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
    Definition: clock.c:290
    SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
    Definition: clock.c:438
    internal methods for clocks and timing issues
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIPABORT()
    Definition: def.h:327
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPlpiExactSetRealpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, SCIP_Real dval)
    SCIP_RETCODE SCIPlpiExactSolveDual(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactSetIntpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, int ival)
    SCIP_Real SCIPlpiExactInfinity(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactAddRows(SCIP_LPIEXACT *lpi, int nrows, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs, char **rownames, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
    SCIP_RETCODE SCIPlpiExactCreate(SCIP_LPIEXACT **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
    SCIP_Bool SCIPlpiExactIsOptimal(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactAddCols(SCIP_LPIEXACT *lpi, int ncols, SCIP_RATIONAL **obj, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub, char **colnames, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
    SCIP_RETCODE SCIPlpiExactDelCols(SCIP_LPIEXACT *lpi, int firstcol, int lastcol)
    SCIP_RETCODE SCIPlpiExactChgObj(SCIP_LPIEXACT *lpi, int ncols, int *ind, SCIP_RATIONAL **obj)
    SCIP_RETCODE SCIPlpiExactClear(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactFree(SCIP_LPIEXACT **lpi)
    SCIP_RETCODE SCIPlpiExactGetNCols(SCIP_LPIEXACT *lpi, int *ncols)
    SCIP_RETCODE SCIPlpiExactChgSides(SCIP_LPIEXACT *lpi, int nrows, int *ind, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs)
    SCIP_RETCODE SCIPlpiExactDelRows(SCIP_LPIEXACT *lpi, int firstrow, int lastrow)
    SCIP_RETCODE SCIPlpiExactGetNRows(SCIP_LPIEXACT *lpi, int *nrows)
    SCIP_RETCODE SCIPlpiExactChgBounds(SCIP_LPIEXACT *lpi, int ncols, int *ind, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub)
    SCIP_RETCODE SCIPlpiExactGetSol(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *objval, SCIP_RATIONAL **primsol, SCIP_RATIONAL **dualsol, SCIP_RATIONAL **activity, SCIP_RATIONAL **redcost)
    SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
    Definition: lpi_clp.cpp:3959
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_Bool SCIPisCertified(SCIP *scip)
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    int SCIPcolGetIndex(SCIP_COL *col)
    Definition: lp.c:17435
    SCIP_Real SCIPcolGetLb(SCIP_COL *col)
    Definition: lp.c:17346
    SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
    Definition: lp.c:17379
    SCIP_Real SCIPcolGetUb(SCIP_COL *col)
    Definition: lp.c:17356
    SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
    void SCIPintervalScalprodScalars(SCIP_Real infinity, SCIP_INTERVAL *resultant, int length, SCIP_INTERVAL *operand1, SCIP_Real *operand2)
    void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
    void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
    void SCIPintervalAddVectors(SCIP_Real infinity, SCIP_INTERVAL *resultant, int length, SCIP_INTERVAL *operand1, SCIP_INTERVAL *operand2)
    SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
    void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    void SCIPintervalScalprod(SCIP_Real infinity, SCIP_INTERVAL *resultant, int length, SCIP_INTERVAL *operand1, SCIP_INTERVAL *operand2)
    void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:1342
    SCIP_RETCODE SCIPrationalCreateBlock(BMS_BLKMEM *blkmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:108
    void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:1066
    void SCIPrationalPrint(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1831
    void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
    Definition: rational.cpp:618
    void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:935
    SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
    Definition: rational.cpp:2085
    void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:461
    SCIP_RETCODE SCIPrationalCreateBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***rational, int size)
    Definition: rational.cpp:196
    #define SCIPrationalDebugMessage
    Definition: rational.h:641
    void SCIPrationalDiv(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:1132
    SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1680
    void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
    Definition: rational.cpp:603
    void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:473
    void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:983
    SCIP_Bool SCIPrationalIsLEReal(SCIP_RATIONAL *rat, SCIP_Real real)
    Definition: rational.cpp:1615
    SCIP_Bool SCIPrationalIsPositive(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1640
    SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:123
    SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1624
    void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
    Definition: rational.cpp:569
    SCIP_Bool SCIPrationalIsGEReal(SCIP_RATIONAL *rat, SCIP_Real real)
    Definition: rational.cpp:1606
    void SCIPrationalMax(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:1373
    void SCIPrationalCanonicalize(SCIP_RATIONAL *rational)
    Definition: rational.cpp:538
    void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
    Definition: rational.cpp:582
    void SCIPrationalNegate(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
    Definition: rational.cpp:1297
    SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1650
    SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1660
    SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
    Definition: rational.cpp:2110
    SCIP_RETCODE SCIPrationalCreateBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***rational, int size)
    Definition: rational.cpp:214
    SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1670
    SCIP_Bool SCIPrationalIsGTReal(SCIP_RATIONAL *rat, SCIP_Real real)
    Definition: rational.cpp:1546
    SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
    Definition: rational.cpp:1404
    void SCIPrationalPrintf(const char *formatstr,...)
    Definition: rational.cpp:1923
    void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
    Definition: rational.cpp:518
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
    Definition: lp.c:17719
    SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
    Definition: lp.c:17706
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_INTERVAL SCIPvarGetObjInterval(SCIP_VAR *var)
    Definition: var.c:23921
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
    Definition: var.c:24278
    SCIP_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
    Definition: var.c:24244
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_Real SCIPlpGetLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
    Definition: lp.c:13475
    SCIP_Real SCIProwGetLPActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
    Definition: lp.c:6454
    SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
    Definition: lp.c:13420
    SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
    Definition: lp.c:13436
    SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
    Definition: lp.c:4147
    SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
    Definition: lp.c:18211
    SCIP_Real SCIPcolGetFarkasCoef(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
    Definition: lp.c:4330
    SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
    Definition: lp.c:17969
    SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
    Definition: lp.c:10441
    internal methods for LP management
    SCIP_Bool SCIPlpExactProjectShiftPossible(SCIP_LPEXACT *lpexact)
    Definition: lpexact.c:3909
    SCIP_RETCODE SCIPlpExactLink(SCIP_LPEXACT *lpexact, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
    Definition: lpexact.c:3711
    SCIP_RETCODE SCIPlpExactSolveAndEval(SCIP_LPEXACT *lpexact, SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool *lperror, SCIP_Bool usefarkas)
    Definition: lpexact.c:4477
    void SCIProwExactPrint(SCIP_ROWEXACT *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
    Definition: lpexact.c:4953
    SCIP_RETCODE SCIPlpExactSyncLPs(SCIP_LPEXACT *lpexact, BMS_BLKMEM *blkmem, SCIP_SET *set)
    Definition: lpexact.c:8474
    SCIP_COLEXACT * SCIPcolGetColExact(SCIP_COL *col)
    Definition: lpexact.c:5099
    SCIP_RETCODE SCIPcolExactCalcFarkasRedcostCoef(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_RATIONAL *result, SCIP_RATIONAL **dual, SCIP_Bool usefarkas)
    Definition: lpexact.c:5111
    SCIP_Bool SCIPlpExactBoundShiftUseful(SCIP_LPEXACT *lpexact)
    Definition: lpexact.c:3899
    void SCIPlpExactAllowExactSolve(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_Bool allowexact)
    Definition: lpexact.c:7630
    SCIP_RATIONAL * SCIPcolExactGetObj(SCIP_COLEXACT *col)
    Definition: lpexact.c:5996
    SCIP_RETCODE SCIPlpExactFlush(SCIP_LPEXACT *lpexact, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
    Definition: lpexact.c:3651
    internal methods for exact LP management
    SCIP_RETCODE SCIPlpExactComputeSafeBound(SCIP_LP *lp, SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_Bool *lperror, SCIP_Bool usefarkas, SCIP_Real *safebound, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
    safe exact rational bounding methods
    interface methods for specific LP solvers
    interface methods for specific exact LP solvers
    #define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
    Definition: memory.h:468
    #define BMSallocBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:454
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    internal methods for collecting primal CIP solutions and primal informations
    internal methods for storing and manipulating the main problem
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    public data structures and miscellaneous methods
    public methods for problem variables
    wrapper for rational number arithmetic
    wrapper for rational number arithmetic that interacts with GMP
    public methods for certified solving
    public methods for message handling
    public methods for global and local (sub)problems
    public methods for the branch-and-bound tree
    internal methods for storing separated exact cuts
    SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7076
    SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6617
    SCIP_Bool SCIPsetIsFeasFracIntegral(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7110
    SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7087
    SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
    Definition: set.c:6945
    SCIP_Real SCIPsetInfinity(SCIP_SET *set)
    Definition: set.c:6380
    SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6515
    SCIP_Real SCIPsetFeasFrac(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:7160
    internal methods for global SCIP settings
    #define SCIPsetFreeBufferArray(set, ptr)
    Definition: set.h:1782
    #define SCIPsetAllocBufferArray(set, ptr, num)
    Definition: set.h:1775
    internal methods for problem statistics
    SCIP_RATIONAL * farkascoef
    SCIP_ROWEXACT ** rows
    SCIP_RATIONAL * obj
    SCIP_RATIONAL ** vals
    SCIP_RATIONAL * ub
    SCIP_RATIONAL * redcost
    SCIP_VAR * var
    SCIP_RATIONAL * lb
    int nunlinked
    Definition: struct_lp.h:173
    SCIP_VAR * var
    Definition: struct_lp.h:162
    SCIP_Real sup
    Definition: intervalarith.h:57
    SCIP_Real inf
    Definition: intervalarith.h:56
    SCIP_Bool primalfeasible
    SCIP_PROJSHIFTDATA * projshiftdata
    SCIP_Bool wasforcedsafebound
    SCIP_COLEXACT ** cols
    SCIP_LPIEXACT * lpiexact
    SCIP_LPSOLSTAT lpsolstat
    SCIP_ROWEXACT ** rows
    SCIP_Bool boundshiftuseful
    SCIP_LP * fplp
    SCIP_Bool forcesafebound
    SCIP_Bool dualfeasible
    SCIP_Bool allowexactsolve
    SCIP_RATIONAL * lpobjval
    SCIP_Bool forceexactsolve
    SCIP_ROW ** rows
    Definition: struct_lp.h:308
    SCIP_Bool probing
    Definition: struct_lp.h:384
    SCIP_COL ** cols
    Definition: struct_lp.h:306
    int ncols
    Definition: struct_lp.h:334
    SCIP_Bool strongbranchprobing
    Definition: struct_lp.h:385
    SCIP_LPEXACT * lpexact
    Definition: struct_lp.h:309
    int nrows
    Definition: struct_lp.h:340
    SCIP_LPSOLSTAT lpsolstat
    Definition: struct_lp.h:359
    SCIP_Real lpobjval
    Definition: struct_lp.h:276
    SCIP_Bool solved
    Definition: struct_lp.h:373
    SCIP_Bool diving
    Definition: struct_lp.h:386
    SCIP_Bool hasprovedbound
    Definition: struct_lp.h:409
    SCIP_LPI * lpi
    Definition: struct_lp.h:301
    SCIP_ROW * fprow
    SCIP_RATIONAL ** vals
    SCIP_RATIONAL * dualfarkas
    SCIP_RATIONAL * lhs
    SCIP_RATIONAL * rhs
    SCIP_RATIONAL * dualsol
    SCIP_INTERVAL * valsinterval
    SCIP_RATIONAL * constant
    SCIP_Real rhs
    Definition: struct_lp.h:208
    SCIP_Real dualfarkas
    Definition: struct_lp.h:218
    char * name
    Definition: struct_lp.h:229
    SCIP_Real lhs
    Definition: struct_lp.h:207
    SCIP_Real constant
    Definition: struct_lp.h:206
    SCIP_Real dualsol
    Definition: struct_lp.h:216
    SCIP_Longint nexlpinter
    Definition: struct_stat.h:232
    SCIP_Longint nfailboundshiftinf
    Definition: struct_stat.h:239
    SCIP_Longint nboundshiftinf
    Definition: struct_stat.h:238
    SCIP_Longint nprojshiftinf
    Definition: struct_stat.h:244
    SCIP_Real boundingerrorps
    Definition: struct_stat.h:164
    SCIP_Longint nboundshift
    Definition: struct_stat.h:236
    SCIP_Longint nfailprojshiftinf
    Definition: struct_stat.h:245
    SCIP_Longint nboundshiftobjlimfail
    Definition: struct_stat.h:241
    SCIP_CLOCK * provedinfeaspstime
    Definition: struct_stat.h:185
    SCIP_Longint nprojshiftobjlimfail
    Definition: struct_stat.h:247
    SCIP_Longint nprojshiftobjlim
    Definition: struct_stat.h:246
    SCIP_CLOCK * provedinfeasbstime
    Definition: struct_stat.h:183
    SCIP_Longint nexlpintfeas
    Definition: struct_stat.h:233
    SCIP_Real boundingerrorbs
    Definition: struct_stat.h:163
    SCIP_Longint nprojshift
    Definition: struct_stat.h:242
    SCIP_Longint nboundshiftobjlim
    Definition: struct_stat.h:240
    SCIP_CLOCK * provedfeaspstime
    Definition: struct_stat.h:184
    SCIP_Longint nfailexlp
    Definition: struct_stat.h:235
    SCIP_Longint nfailboundshift
    Definition: struct_stat.h:237
    SCIP_Longint nexlpboundexc
    Definition: struct_stat.h:234
    SCIP_Longint nfailexlpinf
    Definition: struct_stat.h:230
    SCIP_Longint nfailprojshift
    Definition: struct_stat.h:243
    SCIP_CLOCK * provedfeasbstime
    Definition: struct_stat.h:182
    SCIP_CLOCK * solvingtime
    Definition: struct_stat.h:168
    data structures for exact LP management
    SCIP main data structure.
    datastructures for global SCIP settings
    Definition: heur_padm.c:135
    @ SCIP_LPSOLSTAT_NOTSOLVED
    Definition: type_lp.h:43
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_LPSOLSTAT_TIMELIMIT
    Definition: type_lp.h:49
    @ SCIP_LPSOLSTAT_UNBOUNDEDRAY
    Definition: type_lp.h:46
    @ SCIP_LPSOLSTAT_INFEASIBLE
    Definition: type_lp.h:45
    @ SCIP_LPSOLSTAT_OBJLIMIT
    Definition: type_lp.h:47
    @ SCIP_LPSOLSTAT_ITERLIMIT
    Definition: type_lp.h:48
    @ PS_DUALCOSTSEL_ACTIVE_EXLP
    Definition: type_lpexact.h:70
    @ PS_DUALCOSTSEL_NO
    Definition: type_lpexact.h:68
    @ PS_DUALCOSTSEL_ACTIVE_FPLP
    Definition: type_lpexact.h:69
    struct SCIP_ProjShiftData SCIP_PROJSHIFTDATA
    Definition: type_lpexact.h:58
    @ SCIP_LPPAR_LPINFO
    Definition: type_lpi.h:55
    @ SCIP_LPPAR_LPTILIM
    Definition: type_lpi.h:61
    @ SCIP_OBJSEN_MAXIMIZE
    Definition: type_lpi.h:42
    @ SCIP_R_ROUND_UPWARDS
    Definition: type_rational.h:58
    @ SCIP_R_ROUND_DOWNWARDS
    Definition: type_rational.h:57
    @ SCIP_LPERROR
    Definition: type_retcode.h:49
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71