Scippy

    SCIP

    Solving Constraint Integer Programs

    lpiexact_qsoex.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 lpiexact_qsoex.c
    26 * @ingroup LPIEXACTS
    27 * @brief exact LP interface for QSopt_ex version >= 2.5.4 (r239)
    28 * @author Leon Eifler
    29 * @author Daniel Espinoza
    30 * @author Marc Pfetsch
    31 * @author Kati Wolter
    32*/
    33
    34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    35/* #define VERIFY_OUT */ /* uncomment to get info of QSopt_ex about verifying dual feasibility of the basis */
    36
    37/* #define USEOBJLIM */ /* uncomment to pass objlimit to exact lp solver; same as in cons_exactlinear.c; warning: QSopt_ex allows objlimits but the support is buggy; if the limit is reached, QSopt_ex does not stop but increasess the precision */
    38
    39#include "scip/def.h"
    40
    41#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EGLIB)
    42#include "EGlib.h"
    43#include "QSopt_ex.h"
    44#endif
    45
    46#include <string.h>
    47
    48#include "scip/bitencode.h"
    49#include "scip/scip_mem.h"
    51#include "lpiexact/lpiexact.h"
    52#include "scip/pub_message.h"
    53#include "scip/rationalgmp.h"
    54
    55
    56/** solver name */
    57static char __qsstr[1024];
    58static char __egstr[1024];
    59
    60#ifdef SCIP_WITH_GMP
    61
    62typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
    63#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
    64typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
    65#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
    66
    67/** LP interface */
    68struct SCIP_LPiExact
    69{
    70#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EGLIB)
    71 mpq_QSprob prob; /**< LP struct pointer */
    72 mpq_factor_work* factor; /**< factorized matrix */
    73 int solstat; /**< solution status of last optimization call */
    74 int previt; /**< previous number of simplex iterations performed */
    75 int pricing; /**< SCIP pricing option */
    76#endif
    77 int rowspace; /**< current size of internal row-related arrays */
    78 char* isen; /**< array of length rowspace */
    79 mpq_t* irhs; /**< array of rhs rowspace */
    80 mpq_t* irng; /**< array of range rowspace */
    81 int* ircnt; /**< array of count rowspace */
    82 int* irbeg; /**< array of begining index rowspace */
    83 int colspace; /**< current size of internal column-related arrays */
    84 int* iccnt; /**< array of length colspace */
    85 char* iccha; /**< array of type colspace */
    86 int tbsz; /**< current size of tableau-related arrays */
    87 mpq_t* itab; /**< array of length tbsz */
    88 char* ibas; /**< array of length tbsz */
    89};
    90
    91
    92
    93/*
    94 * local defines
    95 */
    96
    97/*lint --e{750} */
    98/** print location of the calling line */
    99#define __QS_PRINTLOC__ fprintf(stderr,", in (%s:%d)\n", __FILE__, __LINE__);
    100
    101/** This macro is to print error messages and jump to the given point in the code, it also print the
    102 * file and line where this happend */
    103#define QS_TESTG(A,B,...) do { { \
    104 if (A){ \
    105 fprintf(stderr,__VA_ARGS__); \
    106 __QS_PRINTLOC__; \
    107 goto B; } } } while(0)
    108
    109/** This macro is to print error messages and to exit with SCIP_LPERROR */
    110#define QS_ERROR(A,...) do { { \
    111 if (A){ \
    112 fprintf(stderr,__VA_ARGS__); \
    113 __QS_PRINTLOC__; \
    114 return SCIP_LPERROR; } } } while(0)
    115
    116/** return value macro, if the value is non-zero, write to standard error the returning code and
    117 * where this happened, and return SCIP_ERROR, otherwise return normal SCIP_OKAY termination code. */
    118#define QS_RETURN(A) do { \
    119 const int __RVAL__ = (A); \
    120 if (__RVAL__){ \
    121 fprintf(stderr,"LP Error: QSopt_ex returned %d",__RVAL__); \
    122 __QS_PRINTLOC__; \
    123 return SCIP_ERROR; } \
    124 return SCIP_OKAY; } while(0)
    125
    126/** return value macro, if the value is non-zero, write to standard error the returning code and
    127 * where this happened, and return SCIP_ERROR, otherwise do nothing. */
    128#define QS_CONDRET(A) do { \
    129 const int __RVAL__ = (A); \
    130 if (__RVAL__){ \
    131 fprintf(stderr,"LP Error: QSopt_ex returned %d",__RVAL__); \
    132 __QS_PRINTLOC__; \
    133 return SCIP_LPERROR; } \
    134 } while(0)
    135
    136
    137
    138/*
    139 * LPi state methods
    140 */
    141
    142
    143/** LPi state stores basis information */
    144struct SCIP_LPiState
    145{
    146 int ncols; /**< number of LP columns */
    147 int nrows; /**< number of LP rows */
    148 COLPACKET* packcstat; /**< column basis status in compressed form */
    149 ROWPACKET* packrstat; /**< row basis status in compressed form */
    150};
    151
    152static
    153void printGMP(
    154 const mpq_t val
    155 )
    156{
    157 char* buffer;
    158 buffer = (char*) malloc(mpz_sizeinbase(mpq_numref(val), 10) + mpz_sizeinbase(mpq_denref(val), 10) + 3);
    159 (void)mpq_get_str(buffer, 10, val);
    160 printf("%s \n", buffer);
    161 free(buffer);
    162}
    163
    164/** returns the number of packets needed to store column packet information */
    165static
    166int colpacketNum(
    167 int ncols /**< number of columns to store */
    168 )
    169{
    170 return (ncols + (int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
    171}
    172
    173/** returns the number of packets needed to store row packet information */
    174static
    175int rowpacketNum(
    176 int nrows /**< number of rows to store */
    177 )
    178{
    179 return (nrows + (int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
    180}
    181
    182/** store row and column basis status in a packed LPi state object */
    183static
    184void lpistatePack(
    185 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
    186 const int* cstat, /**< basis status of columns in unpacked format */
    187 const int* rstat /**< basis status of rows in unpacked format */
    188 )
    189{
    190 assert(lpistate != NULL);
    191 assert(lpistate->packcstat != NULL);
    192 assert(lpistate->packrstat != NULL);
    193
    194 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
    195 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
    196}
    197
    198/** unpacks row and column basis status from a packed LPi state object */
    199static
    200void lpistateUnpack(
    201 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
    202 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
    203 int* rstat /**< buffer for storing basis status of rows in unpacked format */
    204 )
    205{
    206 assert(lpistate != NULL);
    207 assert(lpistate->packcstat != NULL);
    208 assert(lpistate->packrstat != NULL);
    209
    210 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
    211 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
    212}
    213
    214/** creates LPi state information object */
    215static
    217 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
    218 BMS_BLKMEM* blkmem, /**< block memory */
    219 int ncols, /**< number of columns to store */
    220 int nrows /**< number of rows to store */
    221 )
    222{
    223 assert(lpistate != NULL);
    224 assert(blkmem != NULL);
    225 assert(ncols >= 0);
    226 assert(nrows >= 0);
    227
    228 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
    229 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, colpacketNum(ncols)) );
    230 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, rowpacketNum(nrows)) );
    231
    232 return SCIP_OKAY;
    233}
    234
    235/** frees LPi state information */
    236static
    237void lpistateFree(
    238 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
    239 BMS_BLKMEM* blkmem /**< block memory */
    240 )
    241{
    242 assert(blkmem != NULL);
    243 assert(lpistate != NULL);
    244 assert(*lpistate != NULL);
    245
    246 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, colpacketNum((*lpistate)->ncols));
    247 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, rowpacketNum((*lpistate)->nrows));
    248 BMSfreeBlockMemory(blkmem, lpistate);
    249}
    250
    251
    252/*
    253 * local functions
    254 */
    255
    256/** ensure size of column-related arrays */
    257static inline
    259 SCIP_LPIEXACT* lpi,
    260 int const sz
    261 )
    262{ /*lint --e{647}*/
    263 register int i;
    264 if( lpi->tbsz < sz )
    265 {
    266 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->itab), sz*2) );
    267 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->ibas), sz*2) );
    268 for( i = lpi->tbsz ; i < sz * 2 ; i++ )
    269 mpq_init(lpi->itab[i]);
    270 lpi->tbsz = sz*2;
    271 }
    272 return SCIP_OKAY;
    273}
    274
    275/** ensure size of column-related arrays */
    276static inline
    278 SCIP_LPIEXACT* lpi,
    279 int const ncols
    280 )
    281{
    282 if( lpi->colspace < ncols )
    283 {
    284 lpi->colspace = ncols * 2;
    285 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->iccnt), lpi->colspace) );
    286 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->iccha), lpi->colspace) );
    287 }
    288 return SCIP_OKAY;
    289}
    290
    291/** ensure size of row-related arrays */
    292static inline
    294 SCIP_LPIEXACT* lpi,
    295 int const nrows
    296 )
    297{ /*lint --e{647}*/
    298 register int i;
    299 if( lpi->rowspace < nrows )
    300 {
    301 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->isen), nrows * 2) );
    302 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->irhs), nrows * 2) );
    303 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->irng), nrows * 2) );
    304 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->ircnt), nrows * 2) );
    305 SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->irbeg), nrows * 2) );
    306 for (i = lpi->rowspace ; i < nrows * 2; i++)
    307 {
    308 mpq_init(lpi->irhs[i]);
    309 mpq_init(lpi->irng[i]);
    310 }
    311 lpi->rowspace = nrows * 2;
    312 }
    313 return SCIP_OKAY;
    314}
    315
    316/** transform lhs/rhs into qsopt format */
    317static inline
    319 SCIP_LPIEXACT* const lpi,
    320 int const nrows,
    321 SCIP_RATIONAL** lhs,
    322 SCIP_RATIONAL** rhs
    323 )
    324{ /*lint --e{663, 550, 438, 528}*/
    325 int state;
    326 register int i;
    327
    328 for( i = 0; i < nrows; ++i )
    329 {
    330 mpq_t* lhsg;
    331 mpq_t* rhsg;
    332 int state1;
    333 int state2;
    334
    335 lhsg = SCIPrationalGetGMP(lhs[i]);
    336 rhsg = SCIPrationalGetGMP(rhs[i]);
    337#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EGLIB)
    338 state1 = ((mpq_cmp(*lhsg, mpq_ILL_MINDOUBLE) <= 0) ? 1U : 0U);
    339 state2 = ((mpq_cmp(*rhsg, mpq_ILL_MAXDOUBLE) >= 0) ? 2U : 0U);
    340 state = state1 | state2;
    341#else
    342 state1 = 0;
    343 state2 = 0;
    344 state = 0;
    345#endif
    346 /* state = (((mpq_cmp(*lhsg, mpq_ILL_MINDOUBLE) <= 0) ? 1U : 0U) | ((mpq_cmp(*rhsg, mpq_ILL_MAXDOUBLE) >= 0) ? 2U : 0U)); */
    347 lpi->ircnt[i] = 0;
    348 lpi->irbeg[i] = 0;
    349 switch( state )
    350 {
    351 case 0:
    352 if( SCIPrationalIsEQ(lhs[i], rhs[i]) )
    353 {
    354 lpi->isen[i] = 'E';
    355 mpq_set(lpi->irhs[i], *lhsg);
    356 mpq_set_ui(lpi->irng[i], 0UL, 1UL);
    357 }
    358 else
    359 {
    360 lpi->isen[i] = 'R';
    361 mpq_set(lpi->irhs[i], *lhsg);
    362 mpq_sub(lpi->irng[i], *rhsg, *lhsg);
    363 assert( mpq_sgn(lpi->irng[i]) >=0 );
    364 }
    365 break;
    366 case 1:
    367 lpi->isen[i] = 'L';
    368 mpq_set(lpi->irhs[i], *rhsg);
    369 mpq_set_ui(lpi->irng[i], 0UL, 1UL);
    370 break;
    371 case 2:
    372 lpi->isen[i] = 'G';
    373 mpq_set(lpi->irhs[i], *lhsg);
    374 mpq_set_ui(lpi->irng[i], 0UL, 1UL);
    375 break;
    376 default:
    377 SCIPerrorMessage("Error, constraint %d has no bounds!",i);
    378 SCIPABORT();
    379 }
    380 }
    381 return SCIP_OKAY;
    382 } /*lint --e{528}*/
    383
    384
    385/*
    386 * Miscellaneous Methods
    387 */
    388
    389/**@name Miscellaneous Methods */
    390/**@{ */
    391
    392
    393#endif
    394/** gets name and version of LP solver */
    396 void
    397 )
    398{
    399#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EGLIB)
    400 sprintf(__qsstr, "QSopt_ex %s", string_QSopt_ex);
    401#else
    402 sprintf(__qsstr, "QSopt_ex");
    403#endif
    404
    405 return __qsstr;
    406}
    407
    408/** gets description of LP solver (developer, webpage, ...) */
    410 void
    411 )
    412{
    413 return "Exact Linear Programming Solver by D. Espinoza, W. Cook, S. Dash, and D. Applegate (dii.uchile.cl/~daespino/QSoptExact_doc/main.html)";
    414}
    415
    416/** gets name and version of external package required for LP solver */
    418 void
    419 )
    420{
    421#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EGLIB)
    422 sprintf(__egstr, "EGlib %s", string_EGlib);
    423#else
    424 sprintf(__egstr, "EGlib");
    425#endif
    426
    427 return __egstr;
    428}
    429
    430/** gets description of external package required for LP solver (developer, webpage, ...) */
    432 void
    433 )
    434{
    435 return "Library for basic structures and utilities by D. Espinoza and M. Goycoolea (dii.uchile.cl/~daespino/EGlib_doc/main.html)";
    436}
    437
    438#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EGLIB)
    439
    440/** gets pointer for LP solver - use only with great care */
    442 SCIP_LPIEXACT* lpi /**< pointer to an LP interface structure */
    443 )
    444{
    445 return (void*) lpi->prob;
    446}
    447
    448/**@} */
    449
    450
    451/*
    452 * LPI Creation and Destruction Methods
    453 */
    454
    455/**@name LPI Creation and Destruction Methods */
    456/**@{ */
    457
    458/** calls initializator of LP solver (if this did not already happen); this is mainly needed for defining constants in extended and rational precision */
    460 void
    461 )
    462{
    463 if( !__QSexact_setup )
    464 QSexactStart();
    465}
    466
    467/** calls deinitializator of LP solver; this is needed for freeing all internal data of the solver, like constants in
    468 * extended and rational precision
    469 */
    470void SCIPlpiExactEnd(
    471 void
    472 )
    473{
    474 if( __QSexact_setup )
    475 QSexactClear();
    476}
    477
    478/** creates an LP problem object
    479 *
    480 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
    481 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
    482 */
    484 SCIP_LPIEXACT** lpi, /**< pointer to an LP interface structure */
    485 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
    486 const char* name, /**< problem name */
    487 SCIP_OBJSEN objsen /**< objective sense */
    488 )
    489{
    490 register int i;
    491
    492 /* QSopt_ex only works with bools as integers */
    493 assert(sizeof (SCIP_Bool) == sizeof (int));
    494 assert(lpi != NULL);
    495
    496 SCIPdebugMessage("SCIPlpiExactCreate()\n");
    497
    498 /* create LP */
    501 memset(*lpi, 0, sizeof(struct SCIP_LPiExact));
    502
    503 /* factor work is NULL unless used */
    504 (*lpi)->factor = (mpq_factor_work*) NULL;
    505
    506 (*lpi)->prob = mpq_QScreate_prob(name, (int) objsen);
    507 if( (*lpi)->prob == NULL )
    508 {
    509 SCIPerrorMessage("No memory\n");
    510 return SCIP_LPERROR;
    511 }
    512
    513 (*lpi)->rowspace = 1024;
    514 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->isen), 1024) );
    515 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->irhs), 1024) );
    516 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->irng), 1024) );
    517 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->irbeg), 1024) );
    518 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->ircnt), 1024) );
    519
    520 (*lpi)->colspace = 1024;
    521 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->iccnt), 1024) );
    522 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->iccha), 1024) );
    523
    524 (*lpi)->tbsz = 1024;
    525 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->itab), 1024) );
    526 SCIP_ALLOC( BMSallocMemoryArray(&((*lpi)->ibas), 1024) );
    527 for( i = 0; i < 1024; i++ )
    528 {
    529 mpq_init((*lpi)->irhs[i]);
    530 mpq_init((*lpi)->irng[i]);
    531 mpq_init((*lpi)->itab[i]);
    532 }
    533
    534 return SCIP_OKAY;
    535}
    536
    537/** deletes an LP problem object */
    539 SCIP_LPIEXACT** lpi /**< pointer to an LP interface structure */
    540 )
    541{
    542 register int i;
    543
    544 assert(lpi != NULL);
    545 assert(*lpi != NULL);
    546
    547 SCIPdebugMessage("SCIPlpiExactFree()\n");
    548
    549 /* free factor work */
    550 if( (*lpi)->factor != NULL )
    551 {
    552 mpq_ILLfactor_free_factor_work((*lpi)->factor);
    553 BMSfreeMemoryArray( &((*lpi)->factor) );
    554 }
    555
    556 /* free LP */
    557 mpq_QSfree_prob((*lpi)->prob);
    558 for( i = 0; i < (*lpi)->tbsz; ++i )
    559 mpq_clear((*lpi)->itab[i]);
    560 for( i = 0; i < (*lpi)->rowspace; ++i )
    561 {
    562 mpq_clear((*lpi)->irng[i]);
    563 mpq_clear((*lpi)->irhs[i]);
    564 }
    565 BMSfreeMemoryArray(&((*lpi)->isen));
    566 BMSfreeMemoryArray(&((*lpi)->irhs));
    567 BMSfreeMemoryArray(&((*lpi)->irng));
    568 BMSfreeMemoryArray(&((*lpi)->ircnt));
    569 BMSfreeMemoryArray(&((*lpi)->irbeg));
    570 BMSfreeMemoryArray(&((*lpi)->iccnt));
    571 BMSfreeMemoryArray(&((*lpi)->iccha));
    572 BMSfreeMemoryArray(&((*lpi)->itab));
    573 BMSfreeMemoryArray(&((*lpi)->ibas));
    574
    575 /* free memory */
    576 BMSfreeMemory(lpi);
    577
    578 return SCIP_OKAY;
    579}
    580/**@} */
    581
    582
    583/*
    584 * Modification Methods
    585 */
    586
    587/**@name Modification Methods */
    588/**@{ */
    589
    590
    591/** copies LP data with column matrix into LP solver */
    593 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    594 SCIP_OBJSEN objsen, /**< objective sense */
    595 int ncols, /**< number of columns */
    596 SCIP_RATIONAL** obj, /**< objective function values of columns */
    597 SCIP_RATIONAL** lb, /**< lower bounds of columns */
    598 SCIP_RATIONAL** ub, /**< upper bounds of columns */
    599 char** colnames, /**< column names, or NULL */
    600 int nrows, /**< number of rows */
    601 SCIP_RATIONAL** lhs, /**< left hand sides of rows */
    602 SCIP_RATIONAL** rhs, /**< right hand sides of rows */
    603 char** rownames, /**< row names, or NULL */
    604 int nnonz, /**< number of nonzero elements in the constraint matrix */
    605 int* beg, /**< start index of each column in ind- and val-array */
    606 int* ind, /**< row indices of constraint matrix entries */
    607 SCIP_RATIONAL** val /**< values of constraint matrix entries */
    608 )
    609{
    610 int rval = 0;
    611
    612 assert(lpi != NULL);
    613 assert(lpi->prob != NULL);
    614
    615 lpi->solstat = 0;
    616 SCIPdebugMessage("loading LP in column format into QSopt_ex: %d cols, %d rows\n", ncols, nrows);
    617
    618 /* delete old LP */
    620
    621 /* set sense */
    622 if( objsen == SCIP_OBJSEN_MAXIMIZE )
    623 {
    624 rval = mpq_QSchange_objsense(lpi->prob, QS_MAX);
    625 QS_CONDRET(rval);
    626 }
    627 else
    628 {
    629 rval = mpq_QSchange_objsense(lpi->prob, QS_MIN);
    630 QS_CONDRET(rval);
    631 }
    632
    633 /* add rows with no matrix, and then the columns, first ensure space */
    634 SCIP_CALL( ensureRowMem(lpi, nrows) );
    635
    636 /* convert lhs/rhs into sen/rhs/range tuples */
    637 SCIP_CALL( convertSides(lpi, nrows, lhs, rhs) );
    638
    639 /* now we add the rows */
    640 rval = mpq_QSadd_ranged_rows(lpi->prob, nrows, lpi->ircnt, lpi->irbeg, 0, (const mpq_t*) 0, (const mpq_t*) lpi->irhs,
    641 lpi->isen, (const mpq_t*) lpi->irng, (const char**)rownames);
    642 QS_CONDRET(rval);
    643
    644 SCIPlpiExactAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val);
    645
    646 QS_RETURN(rval);
    647}
    648
    649/** adds columns to the LP */
    651 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    652 int ncols, /**< number of columns to be added */
    653 SCIP_RATIONAL** obj, /**< objective function values of new columns */
    654 SCIP_RATIONAL** lb, /**< lower bounds of new columns */
    655 SCIP_RATIONAL** ub, /**< upper bounds of new columns */
    656 char** colnames, /**< column names, or NULL */
    657 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
    658 int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
    659 int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
    660 SCIP_RATIONAL** val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
    661 )
    662{
    663 mpq_t* valgmp;
    664 int rval = 0;
    665 register int i;
    666
    667 assert(lpi != NULL);
    668 assert(lpi->prob != NULL);
    669
    670 SCIPdebugMessage("adding %d columns with %d nonzeros to QSopt_ex\n", ncols, nnonz);
    671
    672 lpi->solstat = 0;
    673
    674 /* ensure column size */
    675 SCIP_CALL( ensureColMem(lpi, ncols) );
    676
    677 if( nnonz > 0 )
    678 {
    679 /* compute column lengths */
    680 for( i = 0; i < ncols - 1; ++i )
    681 {
    682 lpi->iccnt[i] = beg[i+1] - beg[i];
    683 assert(lpi->iccnt[i] >= 0);
    684 }
    685 if( ncols > 0 )
    686 {
    687 lpi->iccnt[ncols-1] = nnonz - beg[ncols-1];
    688 assert( lpi->iccnt[ncols-1] >= 0 );
    689 }
    690
    691 SCIP_ALLOC( BMSallocMemoryArray(&valgmp, nnonz) );
    692 SCIPrationalSetGMPArray(valgmp, val, nnonz);
    693
    694 /* and add the columns */
    695 for( i = 0; i < ncols; ++i )
    696 {
    697 mpq_QSadd_col(lpi->prob, lpi->iccnt[i], &ind[beg[i]], &(valgmp[beg[i]]),
    698 *SCIPrationalGetGMP(obj[i]), *SCIPrationalGetGMP(lb[i]), *SCIPrationalGetGMP(ub[i]), (const char*) colnames[i]);
    699 }
    700
    701 SCIPrationalClearArrayGMP(valgmp, nnonz);
    702 BMSfreeMemoryArray(&valgmp);
    703 }
    704 else
    705 {
    706 for( i = 0; i < ncols; ++i )
    707 {
    708 rval = mpq_QSnew_col(lpi->prob, *SCIPrationalGetGMP(obj[i]), *SCIPrationalGetGMP(lb[i]), *SCIPrationalGetGMP(ub[i]), (const char*) colnames[i]);
    709 }
    710 }
    711
    712 QS_RETURN(rval);
    713}
    714
    715/** deletes all columns in the given range from LP */
    717 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    718 int firstcol, /**< first column to be deleted */
    719 int lastcol /**< last column to be deleted */
    720 )
    721{
    722 const int len = lastcol - firstcol +1;
    723 int rval = 0;
    724 register int i;
    725
    726 assert(lpi != NULL);
    727 assert(lpi->prob != NULL);
    728
    729 lpi->solstat = 0;
    730 assert(0 <= firstcol && len > 0 && lastcol < mpq_QSget_colcount (lpi->prob));
    731
    732 SCIPdebugMessage("deleting %d columns from QSopt_ex\n", len);
    733
    734 SCIP_CALL( ensureColMem(lpi, len) );
    735 for( i = firstcol ; i <= lastcol ; i++ )
    736 lpi->iccnt[i-firstcol] = i;
    737
    738 rval = mpq_QSdelete_cols(lpi->prob, len, lpi->iccnt);
    739
    740 QS_RETURN(rval);
    741}
    742
    743/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
    745 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    746 int* dstat /**< deletion status of columns
    747 * input: 1 if column should be deleted, 0 if not
    748 * output: new position of column, -1 if column was deleted */
    749 )
    750{
    751 int rval = 0, ncols, ccnt;
    752 register int i;
    753
    754 assert(lpi != NULL);
    755 assert(lpi->prob != NULL);
    756
    757 ncols = mpq_QSget_colcount(lpi->prob);
    758 lpi->solstat = 0;
    759
    760 SCIPdebugMessage("deleting a column set from QSopt_ex\n");
    761
    762 rval = mpq_QSdelete_setcols(lpi->prob,dstat);
    763 QS_CONDRET(rval);
    764
    765 for( i = 0, ccnt = 0; i < ncols; i++ )
    766 {
    767 if( dstat[i] )
    768 dstat[i] = -1;
    769 else
    770 dstat[i] = ccnt++;
    771 }
    772 return SCIP_OKAY;
    773}
    774
    775/** adds rows to the LP */
    776SCIP_EXPORT
    778 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    779 int nrows, /**< number of rows to be added */
    780 SCIP_RATIONAL** lhs, /**< left hand sides of new rows */
    781 SCIP_RATIONAL** rhs, /**< right hand sides of new rows */
    782 char** rownames, /**< row names, or NULL */
    783 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
    784 int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
    785 int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
    786 SCIP_RATIONAL** val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
    787 )
    788{
    789 register int i;
    790 int rval = 0;
    791 mpq_t* valgmp;
    792
    793 assert(lpi != NULL);
    794 assert(lpi->prob != NULL);
    795
    796 lpi->solstat = 0;
    797 SCIPdebugMessage("adding %d rows with %d nonzeros to QSopt_ex\n", nrows, nnonz);
    798
    799 /* add rows with no matrix, and then the columns, first ensure space */
    800 SCIP_CALL( ensureRowMem (lpi, nrows) );
    801
    802 /* convert lhs/rhs into sen/rhs/range tuples */
    803 SCIP_CALL( convertSides(lpi, nrows, lhs, rhs) );
    804
    805 /* compute row count */
    806 for( i = 0; i < nrows - 1; i++ )
    807 {
    808 lpi->ircnt[i] = beg[i + 1] - beg[i];
    809 assert(lpi->ircnt[i] >= 0);
    810 }
    811 if( nrows > 0 )
    812 {
    813 lpi->ircnt[nrows - 1] = nnonz - beg[nrows - 1];
    814 assert(lpi->ircnt[nrows - 1] >= 0);
    815 }
    816
    817 SCIP_ALLOC( BMSallocMemoryArray(&valgmp, nnonz) );
    818 SCIPrationalSetGMPArray(valgmp, val, nnonz);
    819
    820 rval = mpq_QSadd_ranged_rows(lpi->prob, nrows, lpi->ircnt, beg, ind, (const mpq_t*) valgmp, (const mpq_t*) lpi->irhs,
    821 lpi->isen, (const mpq_t*) lpi->irng, (const char**) rownames);
    822 QS_CONDRET(rval);
    823
    824 SCIPrationalClearArrayGMP(valgmp, nnonz);
    825 BMSfreeMemoryArray(&valgmp);
    826
    827 return SCIP_OKAY;
    828}
    829
    830
    831/** deletes all rows in the given range from LP */
    833 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    834 int firstrow, /**< first row to be deleted */
    835 int lastrow /**< last row to be deleted */
    836 )
    837{
    838 const int len = lastrow - firstrow +1;
    839 int rval = 0;
    840 register int i;
    841
    842 assert(lpi != NULL);
    843 assert(lpi->prob != NULL);
    844
    845 lpi->solstat = 0;
    846 assert(0 <= firstrow && len > 0 && lastrow < mpq_QSget_rowcount (lpi->prob));
    847
    848 SCIPdebugMessage("deleting %d rows from QSopt_ex\n", len);
    849
    850 SCIP_CALL( ensureRowMem(lpi, len) );
    851 for( i = firstrow; i <= lastrow; i++ )
    852 lpi->ircnt[i - firstrow] = i;
    853 rval = mpq_QSdelete_rows(lpi->prob, len, lpi->ircnt);
    854
    855 QS_RETURN(rval);
    856}
    857
    858
    859/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
    861 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    862 int* dstat /**< deletion status of rows
    863 * input: 1 if row should be deleted, 0 if not
    864 * output: new position of row, -1 if row was deleted */
    865 )
    866{
    867 int rval = 0, nrows, ccnt, ndel=0;
    868 register int i;
    869
    870 assert(lpi != NULL);
    871 assert(lpi->prob != NULL);
    872
    873 nrows = mpq_QSget_rowcount(lpi->prob);
    874 lpi->solstat = 0;
    875
    876 for( i = 0; i < nrows; ++i )
    877 {
    878 if( dstat[i] == 1 )
    879 ndel++;
    880 }
    881
    882 SCIPdebugMessage("deleting a row set from QSopt_ex (%d)\n",ndel);
    883
    884 rval = mpq_QSdelete_setrows(lpi->prob,dstat);
    885 QS_CONDRET(rval);
    886
    887 for( i = 0, ccnt = 0; i < nrows; ++i )
    888 {
    889 if( dstat[i] )
    890 dstat[i] = -1;
    891 else
    892 dstat[i] = ccnt++;
    893 }
    894 return SCIP_OKAY;
    895}
    896
    897/** clears the whole LP */
    899 SCIP_LPIEXACT* lpi /**< LP interface structure */
    900 )
    901{
    902 register int i;
    903 int ncols, nrows, rval = 0;
    904
    905 assert(lpi != NULL);
    906 assert(lpi->prob != NULL);
    907
    908 SCIPdebugMessage("clearing QSopt_ex LP\n");
    909 lpi->solstat = 0;
    910
    911 ncols = mpq_QSget_colcount(lpi->prob);
    912 nrows = mpq_QSget_rowcount(lpi->prob);
    913 if( ncols >= 1 )
    914 {
    915 SCIP_CALL( ensureColMem(lpi,ncols) );
    916 for (i = 0; i < ncols; ++i)
    917 lpi->iccnt[i] = i;
    918 rval = mpq_QSdelete_cols(lpi->prob, ncols, lpi->iccnt);
    919 QS_CONDRET(rval);
    920 }
    921
    922 if( nrows >= 1 )
    923 {
    924 SCIP_CALL( ensureRowMem(lpi, nrows) );
    925 for (i = 0; i < nrows; ++i)
    926 lpi->ircnt[i] = i;
    927 rval = mpq_QSdelete_rows(lpi->prob, nrows, lpi->ircnt);
    928 QS_CONDRET(rval);
    929 }
    930 QS_RETURN(rval);
    931}
    932
    933
    934/** changes lower and upper bounds of columns */
    936 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    937 int ncols, /**< number of columns to change bounds for */
    938 int* ind, /**< column indices */
    939 SCIP_RATIONAL** lb, /**< values for the new lower bounds, or NULL */
    940 SCIP_RATIONAL** ub /**< values for the new upper bounds, or NULL */
    941 )
    942{
    943 register int i;
    944 int rval = 0;
    945
    946 assert(lpi != NULL);
    947 assert(lpi->prob != NULL);
    948 assert(lb != NULL || ub != NULL);
    949
    950 lpi->solstat = 0;
    951
    952 SCIPdebugMessage("changing %d bounds in QSopt_ex\n", ncols);
    953#ifdef SCIP_DEBUG
    954 {
    955 int j;
    956 char s[SCIP_MAXSTRLEN];
    957
    958 for( j = 0; j < ncols; ++j )
    959 {
    960 if( lb == NULL)
    961 gmp_snprintf(s, SCIP_MAXSTRLEN, " col %d: [--,%Qd]\n", ind[j], *SCIPrationalGetGMP(ub[j]));
    962 else if( ub == NULL )
    963 gmp_snprintf(s, SCIP_MAXSTRLEN, " col %d: [%Qd,--]\n", ind[j], *SCIPrationalGetGMP(lb[j]));
    964 else
    965 gmp_snprintf(s, SCIP_MAXSTRLEN, " col %d: [%Qd,%Qd]\n", ind[j], *SCIPrationalGetGMP(lb[j]), *SCIPrationalGetGMP(ub[j]));
    967 }
    968 }
    969#endif
    970
    971 SCIP_CALL( ensureColMem(lpi, ncols) );
    972
    973 if( lb != NULL )
    974 {
    975 for( i = 0; i < ncols; i++ )
    976 {
    977 lpi->iccha[i] = 'L';
    978 rval = mpq_QSchange_bound(lpi->prob, ind[i], lpi->iccha[i], *SCIPrationalGetGMP(lb[i]));
    979 QS_CONDRET(rval);
    980 }
    981 }
    982
    983 if( ub != NULL )
    984 {
    985 for( i = 0; i < ncols; i++ )
    986 {
    987 lpi->iccha[i] = 'U';
    988 rval = mpq_QSchange_bound(lpi->prob, ind[i], lpi->iccha[i], *SCIPrationalGetGMP(ub[i]));
    989 QS_CONDRET(rval);
    990 }
    991 }
    992 QS_RETURN(rval);
    993}
    994
    995/** changes left and right hand sides of rows */
    997 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    998 int nrows, /**< number of rows to change sides for */
    999 int* ind, /**< row indices */
    1000 SCIP_RATIONAL** lhs, /**< new values for left hand sides */
    1001 SCIP_RATIONAL** rhs /**< new values for right hand sides */
    1002 )
    1003{
    1004 register int i;
    1005 int rval = 0;
    1006
    1007 assert(lpi != NULL);
    1008 assert(lpi->prob != NULL);
    1009
    1010 lpi->solstat = 0;
    1011 SCIPdebugMessage("changing %d sides in QSopt_ex\n", nrows);
    1012
    1013 SCIP_CALL( ensureRowMem(lpi, nrows) );
    1014
    1015 /* convert lhs/rhs into sen/rhs/range tuples */
    1016 SCIP_CALL( convertSides(lpi, nrows, lhs, rhs) );
    1017
    1018 /* now we change all rows */
    1019 for( i = 0; i < nrows; ++i )
    1020 {
    1021 rval = mpq_QSchange_sense(lpi->prob, ind[i], lpi->isen[i]);
    1022 QS_CONDRET(rval);
    1023
    1024 rval = mpq_QSchange_rhscoef(lpi->prob, ind[i], lpi->irhs[i]);
    1025 QS_CONDRET(rval);
    1026
    1027 if (lpi->isen[i] == 'R')
    1028 {
    1029 rval = mpq_QSchange_range(lpi->prob, ind[i], lpi->irng[i]);
    1030 QS_CONDRET(rval);
    1031 }
    1032 }
    1033
    1034 QS_RETURN(rval);
    1035}
    1036
    1037/** changes a single coefficient */
    1039 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1040 int row, /**< row number of coefficient to change */
    1041 int col, /**< column number of coefficient to change */
    1042 SCIP_RATIONAL* newval /**< new value of coefficient */
    1043 )
    1044{
    1045 int rval = 0;
    1046
    1047 assert(lpi != NULL);
    1048 assert(lpi->prob != NULL);
    1049
    1050 lpi->solstat = 0;
    1051
    1052 SCIPdebugMessage("changing coefficient row %d, column %d in QSopt_ex to %g\n", row, col, SCIPrationalGetReal(newval));
    1053
    1054 rval = mpq_QSchange_coef(lpi->prob, row, col, *SCIPrationalGetGMP(newval));
    1055
    1056 QS_RETURN(rval);
    1057}
    1058
    1059/** changes the objective sense */
    1061 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1062 SCIP_OBJSEN objsen /**< new objective sense */
    1063 )
    1064{
    1065 int rval = 0;
    1066
    1067 assert(lpi != NULL);
    1068 assert(lpi->prob != NULL);
    1069
    1070 lpi->solstat = 0;
    1071 SCIPdebugMessage("changing objective sense in QSopt_ex to %d\n", objsen);
    1072
    1073 /* set sense */
    1074 if( objsen == SCIP_OBJSEN_MAXIMIZE )
    1075 {
    1076 rval = mpq_QSchange_objsense(lpi->prob, QS_MAX);
    1077 QS_CONDRET(rval);
    1078 }
    1079 else
    1080 {
    1081 rval = mpq_QSchange_objsense(lpi->prob, QS_MIN);
    1082 QS_CONDRET(rval);
    1083 }
    1084
    1085 QS_RETURN(rval);
    1086}
    1087
    1088/** changes objective values of columns in the LP */
    1090 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1091 int ncols, /**< number of columns to change objective value for */
    1092 int* ind, /**< column indices to change objective value for */
    1093 SCIP_RATIONAL** obj /**< new objective values for columns */
    1094 )
    1095{
    1096 register int i;
    1097 int rval = 0;
    1098
    1099 assert(lpi != NULL);
    1100 assert(lpi->prob != NULL);
    1101
    1102 lpi->solstat = 0;
    1103 SCIPdebugMessage("changing %d objective values in QSopt_ex\n", ncols);
    1104
    1105 for( i = 0; i < ncols; ++i )
    1106 {
    1107 rval = mpq_QSchange_objcoef(lpi->prob, ind[i], *SCIPrationalGetGMP(obj[i]));
    1108 QS_CONDRET(rval);
    1109 }
    1110 QS_RETURN(rval);
    1111}
    1112
    1113/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
    1115 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1116 int row, /**< row number to scale */
    1117 SCIP_RATIONAL* scaleval /**< scaling multiplier */
    1118 )
    1119{
    1120 register int i;
    1121 int rowlist[1];
    1122 int* rowcnt = NULL, *rowbeg = NULL, *rowind = NULL;
    1123 mpq_t* rowval = NULL, *rhs = NULL, *range = NULL;
    1124 char* sense = NULL;
    1125 int rval = 0;
    1126 mpq_t svl;
    1127
    1128 assert(lpi != NULL);
    1129 assert(lpi->prob != NULL);
    1130
    1131 mpq_init(svl);
    1132 lpi->solstat = 0;
    1133 SCIPrationalDebugMessage("scaling row %d with factor %g in QSopt_ex\n", row, scaleval);
    1134
    1135 rowlist[0] = row;
    1136 /* get row */
    1137 rval = mpq_QSget_ranged_rows_list(lpi->prob, 1, rowlist, &rowcnt, &rowbeg, &rowind, &rowval, &rhs, &sense, &range, 0);
    1138 QS_TESTG(rval, CLEANUP, " ");
    1139
    1140 /* change all coefficients in the constraint */
    1141 for( i = 0; i < rowcnt[0]; ++i )
    1142 {
    1143 mpq_mul(svl, rowval[i], *SCIPrationalGetGMP(scaleval));
    1144 rval = mpq_QSchange_coef(lpi->prob, row, rowind[i], svl);
    1145 QS_TESTG(rval, CLEANUP, " ");
    1146 }
    1147
    1148 /* if we have a positive scalar, we just scale rhs and range */
    1149 if( SCIPrationalGetSign(scaleval) >= 0 )
    1150 {
    1151 mpq_mul(svl, *SCIPrationalGetGMP(scaleval), rhs[0]);
    1152 rval = mpq_QSchange_rhscoef(lpi->prob, row, svl);
    1153 QS_TESTG(rval, CLEANUP, " ");
    1154 if (sense[0] == 'R')
    1155 {
    1156 mpq_mul(svl, range[0], *SCIPrationalGetGMP(scaleval));
    1157 rval = mpq_QSchange_range(lpi->prob, row, svl);
    1158 QS_TESTG(rval, CLEANUP, " ");
    1159 }
    1160 }
    1161 /* otherwise, we must change everything */
    1162 else
    1163 {
    1164 switch( sense[0] )
    1165 {
    1166 case 'E':
    1167 mpq_mul(svl, rhs[0], *SCIPrationalGetGMP(scaleval));
    1168 rval = mpq_QSchange_rhscoef(lpi->prob, row, svl);
    1169 QS_TESTG(rval, CLEANUP, " ");
    1170 break;
    1171 case 'L':
    1172 mpq_mul(svl, rhs[0], *SCIPrationalGetGMP(scaleval));
    1173 rval = mpq_QSchange_rhscoef(lpi->prob, row, svl);
    1174 QS_TESTG(rval, CLEANUP, " ");
    1175 rval = mpq_QSchange_sense(lpi->prob, row, 'G');
    1176 QS_TESTG(rval, CLEANUP, " ");
    1177 break;
    1178 case 'G':
    1179 mpq_mul(svl, rhs[0], *SCIPrationalGetGMP(scaleval));
    1180 rval = mpq_QSchange_rhscoef(lpi->prob, row, svl);
    1181 QS_TESTG(rval, CLEANUP, " ");
    1182 rval = mpq_QSchange_sense(lpi->prob, row, 'L');
    1183 QS_TESTG(rval, CLEANUP, " ");
    1184 break;
    1185 case 'R':
    1186 mpq_add(svl, rhs[0], range[0]);
    1187 mpq_mul(svl, svl, *SCIPrationalGetGMP(scaleval));
    1188 rval = mpq_QSchange_rhscoef(lpi->prob, row, svl);
    1189 QS_TESTG(rval, CLEANUP, " ");
    1190 mpq_abs(svl,*SCIPrationalGetGMP(scaleval));
    1191 mpq_mul(svl, svl, range[0]);
    1192 rval = mpq_QSchange_range(lpi->prob, row, svl);
    1193 QS_TESTG(rval, CLEANUP, " ");
    1194 break;
    1195 default:
    1196 SCIPerrorMessage("Imposible! received sense %c (not E L G R)", sense[0]);
    1197 rval = 1;
    1198 goto CLEANUP;
    1199 }
    1200 }
    1201 /* now we must free all received arrays */
    1202 /* ending */
    1203 CLEANUP:
    1204 if (rowcnt) mpq_QSfree(rowcnt);
    1205 if (rowbeg) mpq_QSfree(rowbeg);
    1206 if (rowind) mpq_QSfree(rowind);
    1207 if (rowval) mpq_EGlpNumFreeArray(rowval);
    1208 if (rhs) mpq_EGlpNumFreeArray(rhs);
    1209 if (sense) mpq_QSfree(sense);
    1210 if (range) mpq_EGlpNumFreeArray(range);
    1211 mpq_clear(svl);
    1212
    1213 QS_RETURN(rval);
    1214}
    1215
    1216/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
    1217 * are divided by the scalar; for negative scalars, the column's bounds are switched
    1218 */
    1220 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1221 int col, /**< column number to scale */
    1222 SCIP_RATIONAL* scaleval /**< scaling multiplier */
    1223 )
    1224{
    1225 register int i;
    1226 int collist[1];
    1227 int* colcnt=0, *colbeg=0, *colind=0;
    1228 mpq_t* colval=0, *lb=0, *ub=0, *obj=0;
    1229 int rval = 0;
    1230 mpq_t svl;
    1231
    1232 assert(lpi != NULL);
    1233 assert(lpi->prob != NULL);
    1234
    1235 mpq_init(svl);
    1236 lpi->solstat = 0;
    1237 SCIPdebugMessage("scaling column %d with factor %g in QSopt_ex\n",
    1238 col, SCIPrationalGetReal(scaleval));
    1239
    1240 /* get the column */
    1241 collist[0] = col;
    1242 rval = mpq_QSget_columns_list(lpi->prob, 1, collist, &colcnt, &colbeg, &colind, &colval, &obj, &lb, &ub, 0);
    1243 QS_TESTG(rval,CLEANUP," ");
    1244
    1245 /* scale column coefficients */
    1246 for( i = 0; i < colcnt[0]; ++i )
    1247 {
    1248 mpq_mul(svl, colval[i], *SCIPrationalGetGMP(scaleval));
    1249 rval = mpq_QSchange_coef(lpi->prob, colind[i], col, svl);
    1250 QS_TESTG(rval,CLEANUP," ");
    1251 }
    1252
    1253 /* scale objective value */
    1254 mpq_mul(svl, obj[0], *SCIPrationalGetGMP(scaleval));
    1255 rval = mpq_QSchange_objcoef(lpi->prob, col, svl);
    1256 QS_TESTG(rval,CLEANUP," ");
    1257
    1258 /* scale column bounds */
    1259 if( mpq_sgn(*SCIPrationalGetGMP(scaleval)) < 0 )
    1260 {
    1261 mpq_set(obj[0], lb[0]);
    1262 mpq_neg(lb[0], ub[0]);
    1263 mpq_neg(ub[0], obj[0]);
    1264 }
    1265 if( mpq_cmp(lb[0],mpq_ILL_MINDOUBLE) > 0 )
    1266 {
    1267 mpq_abs(svl,*SCIPrationalGetGMP(scaleval));
    1268 mpq_mul(lb[0], lb[0], svl);
    1269 }
    1270 if( mpq_cmp(ub[0], mpq_ILL_MAXDOUBLE) < 0 )
    1271 {
    1272 mpq_abs(svl, *SCIPrationalGetGMP(scaleval));
    1273 mpq_mul(ub[0], ub[0], svl);
    1274 }
    1275
    1276 if( mpq_cmp(lb[0], mpq_ILL_MINDOUBLE) < 0 )
    1277 mpq_set(lb[0], mpq_ILL_MINDOUBLE);
    1278 if( mpq_cmp(ub[0], mpq_ILL_MAXDOUBLE) > 0 )
    1279 mpq_set(ub[0], mpq_ILL_MAXDOUBLE);
    1280
    1281 rval = mpq_QSchange_bound(lpi->prob, col, 'L', lb[0]);
    1282 QS_TESTG(rval, CLEANUP, " ");
    1283 rval = mpq_QSchange_bound(lpi->prob, col, 'U', ub[0]);
    1284 QS_TESTG(rval, CLEANUP, " ");
    1285
    1286 /* ending */
    1287 CLEANUP:
    1288 if (colcnt) mpq_QSfree(colcnt);
    1289 if (colbeg) mpq_QSfree(colbeg);
    1290 if (colind) mpq_QSfree(colind);
    1291 if (colval) mpq_EGlpNumFreeArray(colval);
    1292 if (obj) mpq_EGlpNumFreeArray(obj);
    1293 if (lb) mpq_EGlpNumFreeArray(lb);
    1294 if (ub) mpq_EGlpNumFreeArray(ub);
    1295 mpq_clear(svl);
    1296
    1297 QS_RETURN(rval);
    1298}
    1299/**@} */
    1300
    1301/*
    1302 * Data Accessing Methods
    1303 */
    1304
    1305/**@name Data Accessing Methods */
    1306/**@{ */
    1307
    1308/** gets the number of rows in the LP */
    1310 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1311 int* nrows /**< pointer to store the number of rows */
    1312 )
    1313{
    1314 assert(lpi != NULL);
    1315 assert(lpi->prob != NULL);
    1316 assert(nrows != NULL);
    1317
    1318 SCIPdebugMessage("getting number of rows\n");
    1319
    1320 *nrows = mpq_QSget_rowcount(lpi->prob);
    1321
    1322 return SCIP_OKAY;
    1323}
    1324
    1325/** gets the number of columns in the LP */
    1327 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1328 int* ncols /**< pointer to store the number of cols */
    1329 )
    1330{
    1331 assert(lpi != NULL);
    1332 assert(lpi->prob != NULL);
    1333 assert(ncols != NULL);
    1334
    1335 SCIPdebugMessage("getting number of columns\n");
    1336
    1337 *ncols = mpq_QSget_colcount(lpi->prob);
    1338
    1339 return SCIP_OKAY;
    1340}
    1341
    1342/** gets the number of nonzero elements in the LP constraint matrix */
    1344 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1345 int* nnonz /**< pointer to store the number of nonzeros */
    1346 )
    1347{
    1348 assert(lpi != NULL);
    1349 assert(lpi->prob != NULL);
    1350
    1351 SCIPdebugMessage("getting number of columns\n");
    1352
    1353 *nnonz = mpq_QSget_nzcount(lpi->prob);
    1354
    1355 return SCIP_OKAY;
    1356}
    1357
    1358/** gets columns from LP problem object; the arrays have to be large enough to store all values
    1359 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
    1360 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
    1361 */
    1363 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1364 int firstcol, /**< first column to get from LP */
    1365 int lastcol, /**< last column to get from LP */
    1366 SCIP_RATIONAL** lb, /**< buffer to store the lower bound vector, or NULL */
    1367 SCIP_RATIONAL** ub, /**< buffer to store the upper bound vector, or NULL */
    1368 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
    1369 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
    1370 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
    1371 SCIP_RATIONAL** val /**< buffer to store values of constraint matrix entries, or NULL */
    1372 )
    1373{
    1374 int len;
    1375 register int i;
    1376 mpq_t* lval = NULL;
    1377 mpq_t* llb = NULL;
    1378 mpq_t* lub = NULL;
    1379 int rval = 0;
    1380 int* lcnt = NULL;
    1381 int* lbeg = NULL;
    1382 int* lind = NULL;
    1383
    1384 assert(lpi != NULL);
    1385 assert(lpi->prob != NULL);
    1386 assert( 0 <= firstcol && firstcol <= lastcol && lastcol < mpq_QSget_colcount (lpi->prob) );
    1387 assert( (lb == 0 && ub == 0) || (lb != 0 && ub != 0));
    1388 assert( (nnonz != 0 && beg != 0 && ind != 0 && val != 0) || (nnonz == 0 && beg == 0 && ind == 0 && val == 0) );
    1389
    1390 SCIPdebugMessage("getting columns %d to %d\n", firstcol, lastcol);
    1391
    1392 /* build col-list */
    1393 len = lastcol - firstcol + 1;
    1394 SCIP_CALL( ensureColMem(lpi,len) );
    1395 for( i = 0; i < len; ++i )
    1396 lpi->iccnt[i] = i + firstcol;
    1397
    1398 /* get data from qsopt */
    1399 rval = mpq_QSget_columns_list(lpi->prob, len, lpi->iccnt, nnonz ? (&lcnt) : 0, nnonz ? (&lbeg) : 0, nnonz ? (&lind) : 0,
    1400 nnonz ? (&lval) : 0, 0, lb ? (&llb) : 0, lb ? (&lub) : 0, 0);
    1401
    1402 QS_TESTG(rval, CLEANUP, " ");
    1403
    1404 /* store in the user-provided data */
    1405 if( nnonz )
    1406 {
    1407 assert( lbeg != NULL );
    1408 assert( lcnt != NULL );
    1409 assert( lind != NULL );
    1410 assert( lval != NULL );
    1411
    1412 *nnonz = lbeg[len-1] + lcnt[len-1];
    1413 for( i = 0 ; i < len ; i++ )
    1414 beg[i] = lbeg[i]; /*lint !e613*/
    1415 for( i = 0; i < *nnonz; ++i )
    1416 {
    1417 ind[i] = lind[i]; /*lint !e613*/
    1418 SCIPrationalSetGMP(val[i], lval[i]);
    1419 }
    1420 }
    1421 if( lb )
    1422 {
    1423 assert(llb != NULL);
    1424 assert(lub != NULL);
    1425
    1426 for( i = 0; i < len; ++i )
    1427 {
    1428 SCIPrationalSetGMP(lb[i], llb[i]);
    1429 SCIPrationalSetGMP(ub[i], lub[i]); /*lint !e613*/
    1430 }
    1431 }
    1432
    1433 CLEANUP:
    1434 if (lval) mpq_EGlpNumFreeArray(lval);
    1435 if (lub) mpq_EGlpNumFreeArray(lub);
    1436 if (llb) mpq_EGlpNumFreeArray(llb);
    1437 if (lind) mpq_QSfree(lind);
    1438 if (lbeg) mpq_QSfree(lbeg);
    1439 if (lcnt) mpq_QSfree(lcnt);
    1440
    1441 QS_RETURN(rval);
    1442}
    1443
    1444/** gets rows from LP problem object; the arrays have to be large enough to store all values.
    1445 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
    1446 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
    1447 */
    1449 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1450 int firstrow, /**< first row to get from LP */
    1451 int lastrow, /**< last row to get from LP */
    1452 SCIP_RATIONAL** lhs, /**< buffer to store left hand side vector, or NULL */
    1453 SCIP_RATIONAL** rhs, /**< buffer to store right hand side vector, or NULL */
    1454 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
    1455 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
    1456 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
    1457 SCIP_RATIONAL** val /**< buffer to store values of constraint matrix entries, or NULL */
    1458 )
    1459{
    1460 const int len = lastrow - firstrow + 1;
    1461 register int i;
    1462 mpq_t* lval = NULL;
    1463 mpq_t* lrhs = NULL;
    1464 mpq_t* lrng = NULL;
    1465 int rval = 0;
    1466 int* lcnt = NULL;
    1467 int* lbeg = NULL;
    1468 int* lind = NULL;
    1469 char* lsense = NULL;
    1470
    1471 assert(lpi != NULL);
    1472 assert(lpi->prob != NULL);
    1473 assert(0 <= firstrow && firstrow <= lastrow && lastrow < mpq_QSget_rowcount (lpi->prob));
    1474 assert( (lhs == 0 && rhs == 0) || (rhs != 0 && lhs != 0));
    1475 assert( (nnonz != 0 && beg != 0 && ind != 0 && val != 0) || (nnonz == 0 && beg == 0 && ind == 0 && val == 0));
    1476
    1477 SCIPdebugMessage("getting rows %d to %d\n", firstrow, lastrow);
    1478
    1479 /* build row-list */
    1480 SCIP_CALL( ensureRowMem(lpi, len) );
    1481 for( i = 0; i < len; ++i )
    1482 lpi->ircnt[i] = i + firstrow;
    1483
    1484 /* get data from qsopt */
    1485 rval = mpq_QSget_ranged_rows_list(lpi->prob, len, lpi->ircnt, nnonz ? (&lcnt) : 0, nnonz ? (&lbeg) : 0, nnonz ? (&lind) : 0,
    1486 nnonz ? (&lval) : 0, rhs ? (&lrhs) : 0, rhs ? (&lsense) : 0, rhs ? (&lrng) : 0, 0);
    1487 QS_TESTG(rval, CLEANUP, " ");
    1488
    1489 /* store in the user-provided data */
    1490 if( nnonz )
    1491 {
    1492 assert(lbeg != NULL);
    1493 assert(lcnt != NULL);
    1494 assert(lind != NULL);
    1495 assert(lval != NULL);
    1496
    1497 *nnonz = lbeg[len-1] + lcnt[len-1];
    1498 for( i = 0; i < len; i++ )
    1499 beg[i] = lbeg[i]; /*lint !e613*/
    1500 for( i = 0; i < *nnonz; ++i )
    1501 {
    1502 ind[i] = lind[i]; /*lint !e613*/
    1503 SCIPrationalSetGMP(val[i], lval[i]); /*lint !e613*/
    1504 }
    1505 }
    1506 if( rhs )
    1507 {
    1508 assert(lrhs != NULL);
    1509 assert(lrng != NULL);
    1510 assert(lsense != NULL);
    1511
    1512 for( i = 0; i < len; ++i )
    1513 {
    1514 switch( lsense[i] )
    1515 {
    1516 case 'R':
    1517 SCIPrationalSetGMP(lhs[i], lrhs[i]);
    1518 SCIPrationalSetGMP(rhs[i], lrng[i]);
    1519 SCIPrationalAdd(rhs[i], rhs[i], lhs[i]);
    1520 break;
    1521 case 'E':
    1522 SCIPrationalSetGMP(lhs[i], lrhs[i]);
    1523 SCIPrationalSetGMP(rhs[i], lrhs[i]);
    1524 break;
    1525 case 'L':
    1526 SCIPrationalSetGMP(rhs[i], lrhs[i]);
    1527 SCIPrationalSetGMP(lhs[i], mpq_ILL_MINDOUBLE); /*lint !e613*/
    1528 break;
    1529 case 'G':
    1530 SCIPrationalSetGMP(lhs[i], lrhs[i]);
    1531 SCIPrationalSetGMP(rhs[i], mpq_ILL_MAXDOUBLE);
    1532 break;
    1533 default:
    1534 SCIPerrorMessage("Unknown sense %c from QSopt_ex", lsense[i]);
    1535 SCIPABORT();
    1536 }
    1537 }
    1538 }
    1539
    1540 CLEANUP:
    1541 if (lsense) mpq_QSfree(lsense);
    1542 if (lrng) mpq_EGlpNumFreeArray(lrng);
    1543 if (lrhs) mpq_EGlpNumFreeArray(lrhs);
    1544 if (lval) mpq_EGlpNumFreeArray(lval);
    1545 if (lind) mpq_QSfree(lind);
    1546 if (lbeg) mpq_QSfree(lbeg);
    1547 if (lcnt) mpq_QSfree(lcnt);
    1548
    1549 QS_RETURN(rval);
    1550}
    1551
    1552/** gets objective coefficients from LP problem object */
    1554 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1555 int firstcol, /**< first column to get objective coefficient for */
    1556 int lastcol, /**< last column to get objective coefficient for */
    1557 SCIP_RATIONAL** vals /**< array to store objective coefficients */
    1558 )
    1559{
    1560 const int len = lastcol - firstcol + 1;
    1561 int rval = 0;
    1562 register int i;
    1563 mpq_t* valgmp;
    1564
    1565 assert(lpi != NULL);
    1566 assert(lpi->prob != NULL);
    1567 assert(0 <= firstcol && firstcol <= lastcol && lastcol < mpq_QSget_colcount (lpi->prob));
    1568
    1569 SCIPdebugMessage("getting objective values %d to %d\n", firstcol, lastcol);
    1570
    1571 /* build col-list */
    1572 SCIP_CALL( ensureColMem(lpi,len) );
    1573 for( i = 0; i < len; ++i )
    1574 lpi->iccnt[i] = i + firstcol;
    1575
    1576 SCIP_ALLOC( BMSallocMemoryArray(&valgmp, len) );
    1577 SCIPrationalSetGMPArray(valgmp, vals, len);
    1578 /* get data from qsopt */
    1579 rval = mpq_QSget_obj_list(lpi->prob, len, lpi->iccnt, valgmp);
    1580 SCIPrationalSetArrayGMP(vals, valgmp, len);
    1581
    1582 SCIPrationalClearArrayGMP(valgmp, len);
    1583 BMSfreeMemoryArray(&valgmp);
    1584
    1585 QS_RETURN(rval);
    1586}
    1587
    1588/** gets current bounds from LP problem object */
    1590 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1591 int firstcol, /**< first column to get objective value for */
    1592 int lastcol, /**< last column to get objective value for */
    1593 SCIP_RATIONAL** lbs, /**< array to store lower bound values, or NULL */
    1594 SCIP_RATIONAL** ubs /**< array to store upper bound values, or NULL */
    1595 )
    1596{
    1597 const int len = lastcol - firstcol + 1;
    1598 int rval = 0;
    1599 register int i;
    1600
    1601 assert(lpi != NULL);
    1602 assert(lpi->prob != NULL);
    1603 assert(0 <= firstcol && firstcol <= lastcol&& lastcol < mpq_QSget_colcount (lpi->prob));
    1604
    1605 SCIPdebugMessage("getting bound values %d to %d\n", firstcol, lastcol);
    1606
    1607 /* build col-list */
    1608 SCIP_CALL( ensureColMem(lpi,len) );
    1609 for( i = 0; i < len; ++i )
    1610 {
    1611 if( lbs != NULL )
    1612 {
    1613 QS_CONDRET( mpq_QSget_bound(lpi->prob, i + firstcol, 'L', SCIPrationalGetGMP(lbs[i])) );
    1616 }
    1617 if( ubs != NULL )
    1618 {
    1619 QS_CONDRET( mpq_QSget_bound(lpi->prob, i + firstcol, 'U', SCIPrationalGetGMP(ubs[i])) );
    1622 }
    1623 }
    1624
    1625 QS_RETURN(rval);
    1626}
    1627
    1628/** gets current row sides from LP problem object */
    1630 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1631 int firstrow, /**< first row to get sides for */
    1632 int lastrow, /**< last row to get sides for */
    1633 SCIP_RATIONAL** lhss, /**< array to store left hand side values, or NULL */
    1634 SCIP_RATIONAL** rhss /**< array to store right hand side values, or NULL */
    1635 )
    1636{
    1637 const int len = lastrow - firstrow + 1;
    1638 register int i;
    1639 mpq_t* lrhs = 0;
    1640 mpq_t* lrng = 0;
    1641 int rval = 0;
    1642 char* lsense=0;
    1643
    1644 assert(lpi != NULL);
    1645 assert(lpi->prob != NULL);
    1646 assert(0 <= firstrow && firstrow <= lastrow && lastrow < mpq_QSget_rowcount (lpi->prob));
    1647 assert(rhss != 0 && lhss != 0);
    1648
    1649 SCIPdebugMessage("getting row sides %d to %d\n", firstrow, lastrow);
    1650
    1651 /* build row-list */
    1652 SCIP_CALL( ensureRowMem(lpi, len) );
    1653 for( i = 0; i < len; ++i )
    1654 lpi->ircnt[i] = i + firstrow;
    1655
    1656 /* get data from qsopt */
    1657 rval = mpq_QSget_ranged_rows_list(lpi->prob, len, lpi->ircnt, 0, 0, 0, 0, &lrhs, &lsense, &lrng, 0);
    1658 QS_TESTG(rval, CLEANUP, " ");
    1659
    1660 /* store in the user-provided data */
    1661 for( i = 0; i < len; ++i )
    1662 {
    1663 switch (lsense[i])
    1664 {
    1665 case 'R':
    1666 SCIPrationalSetGMP(lhss[i], lrhs[i]);
    1667 SCIPrationalSetGMP(rhss[i], lrng[i]);
    1668 SCIPrationalAdd(rhss[i], rhss[i], lhss[i]);
    1669 break;
    1670 case 'E':
    1671 SCIPrationalSetGMP(lhss[i], lrhs[i]);
    1672 SCIPrationalSetGMP(rhss[i], lrhs[i]);
    1673 break;
    1674 case 'L':
    1675 SCIPrationalSetGMP(rhss[i], lrhs[i]);
    1676 SCIPrationalSetGMP(lhss[i], mpq_ILL_MINDOUBLE);
    1677 break;
    1678 case 'G':
    1679 SCIPrationalSetGMP(lhss[i], lrhs[i]);
    1680 SCIPrationalSetGMP(rhss[i], mpq_ILL_MAXDOUBLE);
    1681 break;
    1682 default:
    1683 SCIPerrorMessage("Unknown sense %c from QSopt_ex", lsense[i]);
    1684 SCIPABORT();
    1685 }
    1686 }
    1687
    1688 CLEANUP:
    1689 if (lsense)
    1690 mpq_QSfree(lsense);
    1691 if (lrng)
    1692 mpq_EGlpNumFreeArray(lrng);
    1693 if (lrhs)
    1694 mpq_EGlpNumFreeArray(lrhs);
    1695
    1696 QS_RETURN(rval);
    1697}
    1698
    1699/** gets a single coefficient */
    1701 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1702 int row, /**< row number of coefficient */
    1703 int col, /**< column number of coefficient */
    1704 SCIP_RATIONAL* val /**< pointer to store the value of the coefficient */
    1705 )
    1706{
    1707 int rval = 0;
    1708
    1709 assert(lpi != NULL);
    1710 assert(lpi->prob != NULL);
    1711
    1712 SCIPdebugMessage("getting coefficient of row %d col %d\n", row, col);
    1713
    1714 rval = mpq_QSget_coef(lpi->prob, row, col, SCIPrationalGetGMP(val));
    1717
    1718 QS_RETURN(rval);
    1719}
    1720
    1721/**@} */
    1722
    1723/*
    1724 * Solving Methods
    1725 */
    1726
    1727/**@name Solving Methods */
    1728/**@{ */
    1729
    1730/** calls primal simplex to solve the LP */
    1732 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1733 )
    1734{
    1735 int rval = 0;
    1736 QSbasis* B;
    1737
    1738 assert(lpi != NULL);
    1739 assert(lpi->prob != NULL);
    1740
    1741 SCIPdebugMessage("calling QSopt_ex primal simplex: %d cols, %d rows, %d nz\n", mpq_QSget_colcount(lpi->prob),
    1742 mpq_QSget_rowcount(lpi->prob), mpq_QSget_nzcount(lpi->prob));
    1743
    1744 B = mpq_QSget_basis(lpi->prob);
    1745 rval = QSexact_solver(lpi->prob, 0, 0, B, PRIMAL_SIMPLEX, &(lpi->solstat));
    1746 if( B )
    1747 mpq_QSfree_basis(B);
    1748
    1749 QS_RETURN(rval);
    1750}
    1751
    1752/** calls dual simplex to solve the LP */
    1754 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1755 )
    1756{
    1757 int rval = 0;
    1758 QSbasis* B;
    1759
    1760 assert(lpi != NULL);
    1761 assert(lpi->prob != NULL);
    1762
    1763 SCIPdebugMessage("calling QSopt_ex dual simplex: %d cols, %d rows, %d nz\n", mpq_QSget_colcount(lpi->prob),
    1764 mpq_QSget_rowcount(lpi->prob), mpq_QSget_nzcount(lpi->prob));
    1765
    1766 B = mpq_QSget_basis(lpi->prob);
    1767 rval = QSexact_solver(lpi->prob, 0, 0, B, DUAL_SIMPLEX, &(lpi->solstat));
    1768 if( B )
    1769 mpq_QSfree_basis(B);
    1770
    1771 QS_RETURN(rval);
    1772}
    1773
    1774/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
    1776 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1777 SCIP_Bool crossover /**< perform crossover */
    1778 )
    1779{ /*lint --e{715}*/
    1780 return SCIPlpiExactSolveDual(lpi);
    1781}
    1782
    1783/**@} */
    1784
    1785/*
    1786 * Solution Information Methods
    1787 */
    1788
    1789/**@name Solution Information Methods */
    1790/**@{ */
    1791
    1792/** returns whether a solve method was called after the last modification of the LP */
    1794 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1795 )
    1796{
    1797 assert(lpi!=NULL);
    1798 assert(lpi->prob!=NULL);
    1799
    1800 return (lpi->solstat != 0 && lpi->solstat != QS_LP_MODIFIED && lpi->solstat != QS_LP_CHANGE_PREC);
    1801}
    1802
    1803/** gets information about primal and dual feasibility of the current LP solution */
    1805 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    1806 SCIP_Bool* primalfeasible, /**< stores primal feasibility status */
    1807 SCIP_Bool* dualfeasible /**< stores dual feasibility status */
    1808 )
    1809{
    1810 assert(lpi != NULL);
    1811 assert(lpi->prob != NULL);
    1812
    1813 SCIPdebugMessage("getting solution feasibility\n");
    1814
    1815 *primalfeasible = FALSE;
    1816 *dualfeasible = FALSE;
    1817
    1818 if( lpi->solstat == QS_LP_OPTIMAL || lpi->solstat == QS_LP_UNBOUNDED )
    1819 *primalfeasible = TRUE;
    1820
    1821 /* @todo: check why we can conclude dual feasibility from primal infeasibility. in theory, the LP could be primal and
    1822 * dual infeasible as well; see also SCIPlpiExactIsDualFeasible() and SCIPlpiExactIsDualInfeasible()
    1823 */
    1824#ifdef USEOBJLIM
    1825 if( lpi->solstat == QS_LP_OPTIMAL || lpi->solstat == QS_LP_INFEASIBLE || lpi->solstat == QS_LP_OBJ_LIMIT )
    1826#else
    1827 if( lpi->solstat == QS_LP_OPTIMAL || lpi->solstat == QS_LP_INFEASIBLE )
    1828#endif
    1829 *dualfeasible = TRUE;
    1830
    1831 return SCIP_OKAY;
    1832}
    1833
    1834/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
    1835 * this does not necessarily mean, that the solver knows and can return the primal ray
    1836 */
    1838 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1839 )
    1840{
    1841 assert(lpi != NULL);
    1842 assert(lpi->prob != NULL);
    1843
    1844 SCIPdebugMessage("checking primal ray existance\n");
    1845
    1846 return (lpi->solstat == QS_LP_UNBOUNDED);
    1847}
    1848
    1849/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
    1850 * and the solver knows and can return the primal ray
    1851 */
    1853 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1854 )
    1855{
    1856 assert(lpi != NULL);
    1857 assert(lpi->prob != NULL);
    1858
    1859 SCIPdebugMessage("checking for primal ray\n");
    1860
    1861 /* the current version of QSopt_ex can not give a primal certificate of unboundness */
    1862 return FALSE;
    1863}
    1864
    1865/** returns TRUE iff LP is proven to be primal unbounded */
    1867 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1868 )
    1869{
    1870 assert(lpi != NULL);
    1871 assert(lpi->prob != NULL);
    1872
    1873 SCIPdebugMessage("checking for primal unboundness\n");
    1874
    1875 return (lpi->solstat == QS_LP_UNBOUNDED);
    1876}
    1877
    1878/** returns TRUE iff LP is proven to be primal infeasible */
    1880 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1881 )
    1882{
    1883 assert(lpi != NULL);
    1884 assert(lpi->prob != NULL);
    1885
    1886 SCIPdebugMessage("checking for primal infeasibility\n");
    1887
    1888 return (lpi->solstat == QS_LP_INFEASIBLE);
    1889}
    1890
    1891/** returns TRUE iff LP is proven to be primal feasible */
    1893 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1894 )
    1895{
    1896 assert(lpi != NULL);
    1897 assert(lpi->prob != NULL);
    1898
    1899 SCIPdebugMessage("checking for primal feasibility\n");
    1900
    1901 return (lpi->solstat == QS_LP_OPTIMAL || lpi->solstat == QS_LP_UNBOUNDED);
    1902}
    1903
    1904/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
    1905 * this does not necessarily mean, that the solver knows and can return the dual ray
    1906 */
    1908 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1909 )
    1910{
    1911 assert(lpi != NULL);
    1912 assert(lpi->prob != NULL);
    1913
    1914 SCIPdebugMessage("checking for dual ray availability\n");
    1915
    1916 return (lpi->solstat == QS_LP_INFEASIBLE);
    1917}
    1918
    1919/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
    1920 * and the solver knows and can return the dual ray
    1921 */
    1923 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1924 )
    1925{
    1926 assert(lpi != NULL);
    1927 assert(lpi->prob != NULL);
    1928
    1929 SCIPdebugMessage("checking for dual ray availability\n");
    1930
    1931 return (lpi->solstat == QS_LP_INFEASIBLE);
    1932}
    1933
    1934/** returns TRUE iff LP is dual unbounded */
    1936 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1937 )
    1938{
    1939 assert(lpi != NULL);
    1940 assert(lpi->prob != NULL);
    1941
    1942 SCIPdebugMessage("checking for dual unboundness\n");
    1943
    1944 return (lpi->solstat == QS_LP_INFEASIBLE);
    1945}
    1946
    1947/** returns TRUE iff LP is dual infeasible */
    1949 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1950 )
    1951{
    1952 assert(lpi != NULL);
    1953 assert(lpi->prob != NULL);
    1954
    1955 SCIPdebugMessage("checking for dual infeasibility\n");
    1956
    1957 return (lpi->solstat == QS_LP_UNBOUNDED);
    1958}
    1959
    1960/** returns TRUE iff LP is proven to be dual feasible */
    1962 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1963 )
    1964{
    1965 assert(lpi != NULL);
    1966 assert(lpi->prob != NULL);
    1967
    1968 SCIPdebugMessage("checking for dual feasibility\n");
    1969
    1970#ifdef USEOBJLIM
    1971 return (lpi->solstat == QS_LP_OPTIMAL || lpi->solstat == QS_LP_OBJ_LIMIT );
    1972#else
    1973 return (lpi->solstat == QS_LP_OPTIMAL);
    1974#endif
    1975}
    1976
    1977/** returns TRUE iff LP was solved to optimality */
    1979 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1980 )
    1981{
    1982 assert(lpi != NULL);
    1983 assert(lpi->prob != NULL);
    1984
    1985 SCIPdebugMessage("checking for optimality\n");
    1986
    1987 return (lpi->solstat == QS_LP_OPTIMAL);
    1988}
    1989
    1990/** returns TRUE iff current LP basis is stable */
    1992 SCIP_LPIEXACT* lpi /**< LP interface structure */
    1993 )
    1994{
    1995 assert(lpi != NULL);
    1996 assert(lpi->prob != NULL);
    1997
    1998 SCIPdebugMessage("checking for numerical stability\n");
    1999
    2000 return (lpi->solstat != QS_LP_NUMERR);
    2001}
    2002
    2003/** returns TRUE iff the objective limit was reached */
    2005 SCIP_LPIEXACT* lpi /**< LP interface structure */
    2006 )
    2007{
    2008 assert(lpi != NULL);
    2009 assert(lpi->prob != NULL);
    2010
    2011 SCIPdebugMessage("checking for objective limit exceeded\n");
    2012
    2013#ifdef USEOBJLIM
    2014 return (lpi->solstat == QS_LP_OBJ_LIMIT);
    2015#else
    2016 return FALSE;
    2017#endif
    2018}
    2019
    2020/** returns TRUE iff the iteration limit was reached */
    2022 SCIP_LPIEXACT* lpi /**< LP interface structure */
    2023 )
    2024{
    2025 assert(lpi != NULL);
    2026 assert(lpi->prob != NULL);
    2027
    2028 SCIPdebugMessage("checking for iteration limit exceeded\n");
    2029
    2030 return (lpi->solstat == QS_LP_ITER_LIMIT);
    2031}
    2032
    2033/** returns TRUE iff the time limit was reached */
    2035 SCIP_LPIEXACT* lpi /**< LP interface structure */
    2036 )
    2037{
    2038 assert(lpi != NULL);
    2039 assert(lpi->prob != NULL);
    2040
    2041 SCIPdebugMessage("checking for time limit exceeded\n");
    2042
    2043 return (lpi->solstat == QS_LP_TIME_LIMIT);
    2044}
    2045
    2046/** returns the internal solution status of the solver */
    2048 SCIP_LPIEXACT* lpi /**< LP interface structure */
    2049 )
    2050{
    2051 assert(lpi != NULL);
    2052 assert(lpi->prob != NULL);
    2053
    2054 SCIPdebugMessage("getting internal solution status\n");
    2055
    2056 return lpi->solstat;
    2057}
    2058
    2059/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
    2061 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2062 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
    2063 )
    2064{
    2065 assert(lpi != NULL);
    2066 assert(lpi->prob != NULL);
    2067
    2068 SCIPdebugMessage("ignore instability (will fail)\n");
    2069
    2070 /* it seems that in QSopt_ex this does not make much sense */
    2071 *success = FALSE;
    2072
    2073 return SCIP_OKAY;
    2074}
    2075
    2076/** gets objective value of solution */
    2078 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2079 SCIP_RATIONAL* objval /**< stores the objective value */
    2080 )
    2081{
    2082 int rval = 0;
    2083
    2084 assert(lpi != NULL);
    2085 assert(lpi->prob != NULL);
    2086
    2087 SCIPdebugMessage("getting solution's objective value\n");
    2088
    2089 rval = mpq_QSget_objval(lpi->prob, SCIPrationalGetGMP(objval));
    2092
    2093 QS_RETURN(rval);
    2094}
    2095
    2096/** gets primal and dual solution vectors */
    2098 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2099 SCIP_RATIONAL* objval, /**< stores the objective value, may be NULL if not needed */
    2100 SCIP_RATIONAL** primsol, /**< primal solution vector, may be NULL if not needed */
    2101 SCIP_RATIONAL** dualsol, /**< dual solution vector, may be NULL if not needed */
    2102 SCIP_RATIONAL** activity, /**< row activity vector, may be NULL if not needed */
    2103 SCIP_RATIONAL** redcost /**< reduced cost vector, may be NULL if not needed */
    2104 )
    2105{
    2106 int rval = 0, nrows, ncols;
    2107 register int i;
    2108 mpq_t* primsolgmp, *dualsolgmp, *redcostgmp, *objvalgmp;
    2109
    2110 assert(lpi != NULL);
    2111 assert(lpi->prob != NULL);
    2112
    2113 SCIPdebugMessage("getting solution\n");
    2114
    2115 nrows = mpq_QSget_rowcount(lpi->prob);
    2116 ncols = mpq_QSget_colcount(lpi->prob);
    2117 SCIP_CALL( ensureRowMem(lpi, nrows) );
    2118
    2119 if( primsol == NULL )
    2120 primsolgmp = NULL;
    2121 else
    2122 {
    2123 SCIP_ALLOC( BMSallocMemoryArray(&primsolgmp, ncols) );
    2124 SCIPrationalSetGMPArray(primsolgmp, primsol, ncols);
    2125 }
    2126 if( redcost == NULL )
    2127 redcostgmp = NULL;
    2128 else
    2129 {
    2130 SCIP_ALLOC( BMSallocMemoryArray(&redcostgmp, ncols) );
    2131 SCIPrationalSetGMPArray(redcostgmp, redcost, ncols);
    2132 }
    2133 if( dualsol == NULL )
    2134 dualsolgmp = NULL;
    2135 else
    2136 {
    2137 SCIP_ALLOC( BMSallocMemoryArray(&dualsolgmp, nrows) );
    2138 SCIPrationalSetGMPArray(dualsolgmp, dualsol, nrows);
    2139 }
    2140 if( objval != NULL )
    2141 {
    2142 objvalgmp = SCIPrationalGetGMP(objval);
    2144 }
    2145 else
    2146 objvalgmp = NULL;
    2147
    2148 rval = mpq_QSget_solution(lpi->prob, objvalgmp, primsolgmp, dualsolgmp, lpi->irng, redcostgmp);
    2149
    2150 if( objval != NULL )
    2152
    2153 if( redcost != NULL )
    2154 {
    2155 SCIPrationalSetArrayGMP(redcost, redcostgmp, ncols);
    2156 SCIPrationalClearArrayGMP(redcostgmp, ncols);
    2157 BMSfreeMemoryArray(&redcostgmp);
    2158 }
    2159 if( primsol != NULL )
    2160 {
    2161 SCIPrationalSetArrayGMP(primsol, primsolgmp, ncols);
    2162 SCIPrationalClearArrayGMP(primsolgmp, ncols);
    2163 BMSfreeMemoryArray(&primsolgmp);
    2164 }
    2165 if( dualsol != NULL )
    2166 {
    2167 SCIPrationalSetArrayGMP(dualsol, dualsolgmp, nrows);
    2168 SCIPrationalClearArrayGMP(dualsolgmp, nrows);
    2169 BMSfreeMemoryArray(&dualsolgmp);
    2170 }
    2171
    2172 QS_CONDRET(rval);
    2173
    2174 rval = mpq_QSget_rhs(lpi->prob, lpi->irhs);
    2175 QS_CONDRET(rval);
    2176 rval = mpq_QSget_senses(lpi->prob, lpi->isen);
    2177 QS_CONDRET(rval);
    2178
    2179 /* build back the activity */
    2180 if( activity != NULL )
    2181 {
    2182 for( i = 0; i < nrows; ++i )
    2183 {
    2184 switch (lpi->isen[i])
    2185 {
    2186 case 'R':
    2187 case 'E':
    2188 case 'G':
    2189 mpq_add(*SCIPrationalGetGMP(activity[i]), lpi->irhs[i], lpi->irng[i]);
    2191 SCIPrationalCheckInfByValue(activity[i]);
    2192 break;
    2193 case 'L':
    2194 mpq_sub(*SCIPrationalGetGMP(activity[i]), lpi->irhs[i], lpi->irng[i]);
    2196 SCIPrationalCheckInfByValue(activity[i]);
    2197 break;
    2198 default:
    2199 SCIPerrorMessage("unknown sense %c\n", lpi->isen[i]);
    2200 SCIPABORT();
    2201 }
    2202 }
    2203 }
    2204
    2205 return SCIP_OKAY;
    2206}
    2207
    2208/** gets primal ray for unbounded LPs */
    2210 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2211 SCIP_RATIONAL** ray /**< primal ray */
    2212 )
    2213{ /*lint --e{715}*/
    2214 assert(lpi != NULL);
    2215 assert(lpi->prob != NULL);
    2216
    2217 SCIPerrorMessage("SCIPlpiExactGetPrimalRay() not supported by QSopt_ex.\n");
    2218
    2219 return SCIP_ERROR;
    2220}
    2221
    2222/** gets dual farkas proof for infeasibility */
    2224 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2225 SCIP_RATIONAL** dualfarkas /**< dual farkas row multipliers */
    2226 )
    2227{
    2228 int rval = 0;
    2229 int nrows;
    2230 mpq_t* dualfarkasgmp;
    2231
    2232 assert(lpi != NULL);
    2233 assert(lpi->prob != NULL);
    2234 assert(dualfarkas != NULL);
    2235
    2236 SCIPdebugMessage("calling QSopt_ex dual farkas: %d cols, %d rows, %d non zeros\n", mpq_QSget_colcount (lpi->prob),
    2237 mpq_QSget_rowcount(lpi->prob), mpq_QSget_nzcount(lpi->prob));
    2238
    2239 nrows = mpq_QSget_rowcount(lpi->prob);\
    2240 SCIP_ALLOC( BMSallocMemoryArray(&dualfarkasgmp, nrows) );
    2241 SCIPrationalSetGMPArray(dualfarkasgmp, dualfarkas, nrows);
    2242
    2243 rval = mpq_QSget_infeas_array(lpi->prob, dualfarkasgmp);
    2244
    2245 SCIPrationalSetArrayGMP(dualfarkas, dualfarkasgmp, nrows);
    2246 SCIPrationalClearArrayGMP(dualfarkasgmp, nrows);
    2247 BMSfreeMemoryArray(&dualfarkasgmp);
    2248
    2249 QS_RETURN(rval);
    2250}
    2251
    2252/** gets the number of LP iterations of the last solve call */
    2254 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2255 int* iterations /**< pointer to store the number of iterations of the last solve call */
    2256 )
    2257{
    2258 int rval = 0, nit;
    2259
    2260 assert(lpi != NULL);
    2261 assert(lpi->prob != NULL);
    2262
    2263 rval = mpq_QSget_itcnt(lpi->prob, 0, 0, 0, 0, &nit);
    2264 QS_CONDRET(rval);
    2265
    2266 *iterations = nit - lpi->previt;
    2267 lpi->previt = nit;
    2268
    2269 QS_RETURN(rval);
    2270}
    2271
    2272/**@} */
    2273
    2274/*
    2275 * LP Basis Methods
    2276 */
    2277
    2278/**@name LP Basis Methods */
    2279/**@{ */
    2280
    2281/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
    2283 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2284 int* cstat, /**< array to store column basis status, or NULL */
    2285 int* rstat /**< array to store row basis status, or NULL */
    2286 )
    2287{
    2288 int rval = 0, ncols, nrows;
    2289 char* icstat = NULL;
    2290 char* irstat = NULL;
    2291 register int i;
    2292
    2293 assert(lpi != NULL);
    2294 assert(lpi->prob != NULL);
    2295
    2296 SCIPdebugMessage("saving QSopt_ex basis into %p/%p\n", (void *) cstat, (void *) rstat);
    2297
    2298 ncols = mpq_QSget_colcount(lpi->prob);
    2299 nrows = mpq_QSget_rowcount(lpi->prob);
    2300
    2301 SCIP_CALL( ensureTabMem(lpi, nrows + ncols) );
    2302
    2303 icstat = lpi->ibas;
    2304 irstat = lpi->ibas+ncols;
    2305 rval = mpq_QSget_basis_array(lpi->prob, icstat, irstat);
    2306 QS_CONDRET(rval);
    2307
    2308 /* now we must transform QSopt_ex codes into SCIP codes */
    2309 for( i = 0; i < nrows; ++i )
    2310 {
    2311 switch (irstat[i])
    2312 {
    2313 case QS_ROW_BSTAT_LOWER:
    2314 rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
    2315 break;
    2316 case QS_ROW_BSTAT_BASIC:
    2317 rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
    2318 break;
    2319 case QS_ROW_BSTAT_UPPER:
    2320 rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
    2321 break;
    2322 default:
    2323 SCIPerrorMessage("Unknown row basic status %c", rstat[i]);
    2324 SCIPABORT();
    2325 }
    2326 }
    2327 for( i = 0; i < ncols; ++i )
    2328 {
    2329 switch(icstat[i])
    2330 {
    2331 case QS_COL_BSTAT_LOWER:
    2332 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
    2333 break;
    2334 case QS_COL_BSTAT_BASIC:
    2335 cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
    2336 break;
    2337 case QS_COL_BSTAT_UPPER:
    2338 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
    2339 break;
    2340 case QS_COL_BSTAT_FREE:
    2341 cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
    2342 break;
    2343 default:
    2344 SCIPerrorMessage("Unknown column basic status %c", cstat[i]);
    2345 SCIPABORT();
    2346 }
    2347 }
    2348 QS_RETURN(rval);
    2349}
    2350
    2351/** sets current basis status for columns and rows */
    2353 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2354 int* cstat, /**< array with column basis status */
    2355 int* rstat /**< array with row basis status */
    2356 )
    2357{
    2358 int rval = 0, ncols, nrows;
    2359 register int i;
    2360 char* icstat=0, *irstat = 0;
    2361
    2362 assert(lpi != NULL);
    2363 assert(lpi->prob != NULL);
    2364
    2365 SCIPdebugMessage("loading basis %p/%p into QSopt_ex\n", (void *) cstat, (void *) rstat);
    2366
    2367 ncols = mpq_QSget_colcount(lpi->prob);
    2368 nrows = mpq_QSget_rowcount(lpi->prob);
    2369
    2370 /* allocate enough memory for storing uncompressed basis information */
    2371 SCIP_CALL( ensureColMem(lpi, ncols) );
    2372 SCIP_CALL( ensureRowMem(lpi, nrows) );
    2373 SCIP_CALL( ensureTabMem(lpi, nrows+ncols) );
    2374
    2375 icstat = lpi->ibas;
    2376 irstat = lpi->ibas + ncols;
    2377
    2378 /* now we must transform QSopt_ex codes into SCIP codes */
    2379 for( i = 0; i < nrows; ++i )
    2380 {
    2381 switch(rstat[i])
    2382 {
    2384 irstat[i] = QS_ROW_BSTAT_LOWER; /*lint !e641*/
    2385 break;
    2387 irstat[i] = QS_ROW_BSTAT_BASIC; /*lint !e641*/
    2388 break;
    2390 /* sense of inexact LP row is R (ranged row) since this is the only case where the basis status of the
    2391 * slack variable is allowed to be UPPER
    2392 */
    2393 if( lpi->isen[i] == 'R' )
    2394 /* sense of LPEX row is R, too */
    2395 irstat[i] = QS_ROW_BSTAT_UPPER; /*lint !e641*/
    2396 else
    2397 /* sense of LPEX row is L, G or E, thus, basis status must be LOWER/BASIC. we use non-basic status LOWER
    2398 * instead of non-basic status UPPER for slack variable in LPEX. this might happen when the inexact LP
    2399 * is an FP relaxation of the exact LP
    2400 */
    2401 irstat[i] = QS_ROW_BSTAT_LOWER;
    2402 break;
    2403 default:
    2404 SCIPerrorMessage("Unknown row basic status %d", rstat[i]);
    2405 SCIPABORT();
    2406 }
    2407 }
    2408 for( i = 0; i < ncols; ++i )
    2409 {
    2410 switch(cstat[i])
    2411 {
    2413 icstat[i] = QS_COL_BSTAT_LOWER; /*lint !e641*/
    2414 break;
    2416 icstat[i] = QS_COL_BSTAT_BASIC; /*lint !e641*/
    2417 break;
    2419 icstat[i] = QS_COL_BSTAT_UPPER; /*lint !e641*/
    2420 break;
    2421 case SCIP_BASESTAT_ZERO:
    2422 icstat[i] = QS_COL_BSTAT_FREE; /*lint !e641*/
    2423 break;
    2424 default:
    2425 SCIPerrorMessage("Unknown column basic status %d", cstat[i]);
    2426 SCIPABORT();
    2427 }
    2428 }
    2429
    2430 /* set the basis */
    2431 rval = mpq_QSload_basis_array(lpi->prob, icstat, irstat);
    2432 QS_RETURN(rval);
    2433}
    2434
    2435/** returns the indices of the basic columns and rows */
    2437 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2438 int* bind /**< basic column n gives value n, basic row m gives value -1-m */
    2439 )
    2440{
    2441 int rval = 0, nrows, ncols;
    2442 register int i;
    2443
    2444 assert(lpi!=NULL);
    2445 assert(lpi->prob!=NULL);
    2446
    2447 SCIPdebugMessage("getting basis information\n");
    2448
    2449 nrows = mpq_QSget_rowcount(lpi->prob);
    2450 ncols = mpq_QSget_colcount(lpi->prob);
    2451 rval = mpq_QSget_basis_order(lpi->prob, bind);
    2452 QS_CONDRET(rval);
    2453
    2454 /* transform QSopt_ex basis header into SCIP format */
    2455 for( i = 0; i < nrows; ++i )
    2456 {
    2457 if( bind[i] >= ncols )
    2458 bind[i] = -(bind[i] - ncols - 1);
    2459 }
    2460
    2461 return SCIP_OKAY;
    2462}
    2463
    2464/**@} */
    2465
    2466/*
    2467 * LP State Methods
    2468 */
    2469
    2470/**@name LP State Methods */
    2471/**@{ */
    2472
    2473/** stores LPi state (like basis information) into lpistate object */
    2475 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2476 BMS_BLKMEM* blkmem, /**< block memory */
    2477 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
    2478 )
    2479{
    2480 int ncols;
    2481 int nrows;
    2482
    2483 assert(lpi != NULL);
    2484 assert(lpi->prob != NULL);
    2485 assert(blkmem != NULL);
    2486 assert(lpistate != NULL);
    2487
    2488 ncols = mpq_QSget_colcount(lpi->prob);
    2489 nrows = mpq_QSget_rowcount(lpi->prob);
    2490
    2491 assert(ncols >= 0);
    2492 assert(nrows >= 0);
    2493
    2494 /* allocate lpistate data */
    2495 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows));
    2496 SCIPdebugMessage("storing QSopt_ex LPI state in %p (%d cols, %d rows)\n", (void *) *lpistate, ncols, nrows);
    2497
    2498 /* get unpacked basis information from QSopt_ex */
    2499 SCIP_CALL( ensureColMem(lpi, ncols) );
    2500 SCIP_CALL( ensureRowMem(lpi, nrows) );
    2501 SCIP_CALL( SCIPlpiExactGetBase(lpi, lpi->iccnt, lpi->ircnt) );
    2502
    2503 /* pack LPi state data */
    2504 (*lpistate)->ncols = ncols;
    2505 (*lpistate)->nrows = nrows;
    2506 lpistatePack(*lpistate, lpi->iccnt, lpi->ircnt);
    2507
    2508 return SCIP_OKAY;
    2509}
    2510
    2511/** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
    2512 * columns and rows since the state was stored with SCIPlpiExactGetState()
    2513 */
    2515 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2516 BMS_BLKMEM* blkmem, /**< block memory */
    2517 SCIP_LPISTATE* lpistate /**< LPi state information (like basis information) */
    2518 )
    2519{ /*lint --e{715} */
    2520 register int i;
    2521 int rval = 0;
    2522 int ncols;
    2523 int nrows;
    2524 char* icstat = 0;
    2525 char* irstat = 0;
    2526
    2527 assert(lpi != NULL);
    2528 assert(lpi->prob != NULL);
    2529
    2530 /* if there was no basis information available, LPI state was not stored */
    2531 if (lpistate == NULL)
    2532 QS_RETURN(rval);
    2533
    2534 /* continue test */
    2535 ncols = mpq_QSget_colcount(lpi->prob);
    2536 nrows = mpq_QSget_rowcount(lpi->prob);
    2537
    2538 assert(ncols >= 0);
    2539 assert(nrows >= 0);
    2540 assert(lpistate->ncols <= ncols);
    2541 assert(lpistate->nrows <= nrows);
    2542
    2543 SCIPdebugMessage("loading LPI state %p (%d cols, %d rows) into QSopt_ex LP (%d cols and %d rows)\n", (void*) lpistate,
    2544 lpistate->ncols, lpistate->nrows, ncols, nrows);
    2545
    2546 if( lpistate->ncols == 0 || lpistate->nrows == 0 )
    2547 QS_RETURN(rval);
    2548
    2549 /* allocate enough memory for storing uncompressed basis information */
    2550 SCIP_CALL( ensureColMem(lpi, ncols) );
    2551 SCIP_CALL( ensureRowMem(lpi, nrows) );
    2552 SCIP_CALL( ensureTabMem(lpi, nrows+ncols) );
    2553
    2554 icstat = lpi->ibas;
    2555 irstat = lpi->ibas + ncols;
    2556
    2557 /* unpack LPi state data */
    2558 lpistateUnpack(lpistate, lpi->iccnt, lpi->ircnt);
    2559
    2560 /* extend the basis to the current LP */
    2561 for( i = lpistate->ncols; i < ncols; ++i )
    2562 lpi->iccnt[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/ /**@todo this has to be corrected for lb = -infinity */
    2563 for( i = lpistate->nrows; i < nrows; ++i )
    2564 lpi->ircnt[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
    2565
    2566 /* convert the loaded basis into QSopt_ex format */
    2567 SCIPdebugMessage("basis status of SCIP lpistate rows (nrows=%d):\n", lpistate->nrows);
    2568 for( i = 0; i < nrows; ++i )
    2569 {
    2570 SCIPdebugMessage("row_%d: %d (%s)\n", i, lpi->ircnt[i],
    2571 lpi->ircnt[i] == SCIP_BASESTAT_LOWER ? "lower" : lpi->ircnt[i] == SCIP_BASESTAT_BASIC ? "basic" : "upper");
    2572
    2573 switch( lpi->ircnt[i] )
    2574 {
    2576 irstat[i] = QS_ROW_BSTAT_LOWER;
    2577 break;
    2579 irstat[i] = QS_ROW_BSTAT_BASIC;
    2580 break;
    2582 /* sense of inexact LP row is R (ranged row) since this is the only case where the basis status of the
    2583 * slack variable is allowed to be UPPER
    2584 */
    2585 if( lpi->isen[i] == 'R' )
    2586 /* sense of LPEX row is R, too */
    2587 irstat[i] = QS_ROW_BSTAT_UPPER;
    2588 else
    2589 /* sense of LPEX row is L, G or E, thus, basis status must be LOWER/BASIC. we use non-basic status LOWER
    2590 * instead of non-basic status UPPER for slack variable in LPEX. this might happen when the inexact LP
    2591 * is an FP relaxation of the exact LP
    2592 */
    2593 irstat[i] = QS_ROW_BSTAT_LOWER;
    2594 break;
    2595 default:
    2596 SCIPerrorMessage("Unknown row basic status %d", lpi->ircnt[i]);
    2597 SCIPABORT();
    2598 break;
    2599 }
    2600 }
    2601 for( i = 0; i < ncols; ++i )
    2602 {
    2603 switch(lpi->iccnt[i])
    2604 {
    2606 icstat[i] = QS_COL_BSTAT_LOWER;
    2607 break;
    2609 icstat[i] = QS_COL_BSTAT_BASIC;
    2610 break;
    2612 icstat[i] = QS_COL_BSTAT_UPPER;
    2613 break;
    2614 case SCIP_BASESTAT_ZERO:
    2615 icstat[i] = QS_COL_BSTAT_FREE;
    2616 break;
    2617 default:
    2618 SCIPerrorMessage("Unknown column basic status %d", lpi->iccnt[i]);
    2619 SCIPABORT();
    2620 break;
    2621 }
    2622 }
    2623
    2624 /* set the basis */
    2625 rval = mpq_QSload_basis_array(lpi->prob, icstat, irstat);
    2626 QS_RETURN(rval);
    2627}
    2628
    2629/** frees LPi state information */
    2631 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2632 BMS_BLKMEM* blkmem, /**< block memory */
    2633 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
    2634 )
    2635{
    2636 assert(lpi != NULL);
    2637 assert(lpistate != NULL);
    2638
    2639 if( *lpistate != NULL )
    2640 lpistateFree(lpistate, blkmem);
    2641
    2642 return SCIP_OKAY;
    2643}
    2644
    2645/** checks, whether the given LP state contains simplex basis information */
    2647 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2648 SCIP_LPISTATE* lpistate /**< LP state information (like basis information) */
    2649 )
    2650{ /*lint --e{715} */
    2651 return (lpistate != NULL);
    2652}
    2653
    2654/** reads LP state (like basis information from a file */
    2656 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2657 const char* fname /**< file name */
    2658 )
    2659{
    2660 int rval = 0;
    2661
    2662 assert(lpi != NULL);
    2663 assert(lpi->prob != NULL);
    2664
    2665 SCIPdebugMessage("reading QSopt_ex LP state from file <%s>\n", fname);
    2666
    2667 rval = mpq_QSread_and_load_basis(lpi->prob, fname);
    2668 if( rval )
    2669 {
    2670 SCIPerrorMessage("Error while loading basis from file <%s>.\n", fname);
    2671 return SCIP_READERROR;
    2672 }
    2673
    2674 return SCIP_OKAY;
    2675}
    2676
    2677/** writes LP state (like basis information) to a file */
    2679 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2680 const char* fname /**< file name */
    2681 )
    2682{
    2683 QSbasis* bas = 0;
    2684 int rval = 0;
    2685
    2686 assert(lpi != NULL);
    2687 assert(lpi->prob != NULL);
    2688
    2689 SCIPdebugMessage("writing QSopt_ex LP state to file <%s>\n", fname);
    2690
    2691 bas = mpq_QSget_basis(lpi->prob);
    2692 QS_ERROR(bas == 0, "Could not get basis from problem."); /*lint !e820*/
    2693 assert( bas );
    2694
    2695 rval = mpq_QSwrite_basis(lpi->prob, bas, fname);
    2696 mpq_QSfree(bas);
    2697 if( rval )
    2698 {
    2699 SCIPerrorMessage("Could not write basis to file <%s>.\n", fname);
    2700 return SCIP_WRITEERROR;
    2701 }
    2702
    2703 return SCIP_OKAY;
    2704}
    2705
    2706#ifdef SCIP_DISABLED_CODE
    2707/** checks whether LPi state (i.e. basis information) is dual feasible and returns corresponding dual objective value.
    2708 * if wanted it will first directly test the corresponding approximate dual and primal solution
    2709 * (corrected via dual variables for bounds and primal variables for slacks if possible) for optimality
    2710 * before performing the dual feasibility test on the more expensive exact basic solution.
    2711 */
    2713 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2714 BMS_BLKMEM* blkmem, /**< block memory */
    2715 SCIP_LPISTATE* lpistate, /**< LPi state information (like basis information) */
    2716 SCIP_Bool useprestep, /**< should approximate primal and dual solution first */
    2717 SCIP_Real* primalsol, /**< approximate primal solution; or NULL to compute by exact LP solver */
    2718 SCIP_Real* dualsol, /**< approximate dual solution; or NULL to compute by exact LP solver */
    2719 SCIP_Bool* result, /**< pointer to store whether given LPi state is dual feasible */
    2720 mpq_t* dualobjval /**< pointer to store dual objective value in case of dual feasibility */
    2721 )
    2722{ /*lint --e{715} */
    2723 int rval = 0;
    2724 QSbasis* B;
    2725
    2726 *result = FALSE;
    2727
    2728 /* loads LPi state (like basis information) into solver */
    2729 SCIP_CALL( SCIPlpiExactSetState(lpi, blkmem, lpistate) );
    2730
    2731 /* checks whether basis just loaded into the solver is dual feasible */
    2732 B = mpq_QSget_basis(lpi->prob);
    2733
    2734#ifdef VERIFY_OUT
    2735 rval = QSexact_verify(lpi->prob, B, (int) useprestep, primalsol, dualsol, (char*) result, dualobjval, 0);
    2736#else
    2737 rval = QSexact_verify(lpi->prob, B, (int) useprestep, primalsol, dualsol, (char*) result, dualobjval, 1);
    2738#endif
    2739
    2740 if( B )
    2741 mpq_QSfree_basis(B);
    2742
    2743 QS_RETURN(rval);
    2744}
    2745#endif
    2746
    2747/**@} */
    2748
    2749/*
    2750 * Parameter Methods
    2751 */
    2752
    2753/**@name Parameter Methods */
    2754/**@{ */
    2755
    2756/** gets integer parameter of LP */
    2758 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2759 SCIP_LPPARAM type, /**< parameter number */
    2760 int* ival /**< buffer to store the parameter value */
    2761 )
    2762{
    2763 int rval = 0;
    2764
    2765 assert(lpi != NULL);
    2766 assert(lpi->prob != NULL);
    2767 assert(ival != NULL);
    2768
    2769 SCIPdebugMessage("getting int parameter %d\n", type);
    2770
    2771 switch( type )
    2772 {
    2774 case SCIP_LPPAR_FASTMIP:
    2776 return SCIP_PARAMETERUNKNOWN;
    2777 case SCIP_LPPAR_SCALING:
    2778 rval = mpq_QSget_param(lpi->prob, QS_PARAM_SIMPLEX_SCALING, ival);
    2779 if( *ival )
    2780 *ival = TRUE;
    2781 else
    2782 *ival = FALSE;
    2783 break;
    2784 case SCIP_LPPAR_PRICING:
    2785 *ival = lpi->pricing;
    2786 break;
    2787 case SCIP_LPPAR_LPINFO:
    2788 rval = mpq_QSget_param(lpi->prob, QS_PARAM_SIMPLEX_DISPLAY, ival);
    2789 if( *ival )
    2790 *ival = TRUE;
    2791 else
    2792 *ival = FALSE;
    2793 break;
    2794 case SCIP_LPPAR_LPITLIM:
    2795 rval = mpq_QSget_param(lpi->prob, QS_PARAM_SIMPLEX_MAX_ITERATIONS, ival);
    2796 break;
    2797 default:
    2798 return SCIP_PARAMETERUNKNOWN;
    2799 } /*lint !e788*/
    2800
    2801 QS_RETURN(rval);
    2802}
    2803
    2804/** sets integer parameter of LP */
    2806 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2807 SCIP_LPPARAM type, /**< parameter number */
    2808 int ival /**< parameter value */
    2809 )
    2810{
    2811 int rval = 0;
    2812
    2813 assert(lpi != NULL);
    2814 assert(lpi->prob != NULL);
    2815
    2816 SCIPdebugMessage("setting int parameter %d to %d\n", type, ival);
    2817
    2818 switch (type)
    2819 {
    2820 case SCIP_LPPAR_SCALING:
    2821 if( ival == TRUE )
    2822 rval = mpq_QSset_param(lpi->prob, QS_PARAM_SIMPLEX_SCALING, 1);
    2823 else
    2824 rval = mpq_QSset_param(lpi->prob, QS_PARAM_SIMPLEX_SCALING, 0);
    2825 break;
    2826 case SCIP_LPPAR_PRICING:
    2827 lpi->pricing = ival;
    2828 switch( ival )
    2829 {
    2830 case SCIP_PRICING_AUTO:
    2832 case SCIP_PRICING_FULL:
    2833 case SCIP_PRICING_STEEP:
    2835 rval = mpq_QSset_param(lpi->prob, QS_PARAM_PRIMAL_PRICING, QS_PRICE_PSTEEP);
    2836 rval += mpq_QSset_param(lpi->prob, QS_PARAM_DUAL_PRICING, QS_PRICE_DSTEEP);
    2837 break;
    2839 rval = mpq_QSset_param(lpi->prob,QS_PARAM_PRIMAL_PRICING,QS_PRICE_PMULTPARTIAL);
    2840 rval += mpq_QSset_param(lpi->prob,QS_PARAM_DUAL_PRICING,QS_PRICE_DMULTPARTIAL);
    2841 break;
    2842 case SCIP_PRICING_DEVEX:
    2843 rval = mpq_QSset_param(lpi->prob,QS_PARAM_PRIMAL_PRICING,QS_PRICE_PDEVEX);
    2844 rval += mpq_QSset_param(lpi->prob,QS_PARAM_DUAL_PRICING,QS_PRICE_DDEVEX);
    2845 break;
    2846 default:
    2847 return SCIP_LPERROR;
    2848 }
    2849 break;
    2850 case SCIP_LPPAR_LPINFO:
    2851 if( ival == TRUE )
    2852 rval = mpq_QSset_param(lpi->prob, QS_PARAM_SIMPLEX_DISPLAY, 1);
    2853 else
    2854 rval = mpq_QSset_param(lpi->prob, QS_PARAM_SIMPLEX_DISPLAY, 0);
    2855 break;
    2856 case SCIP_LPPAR_LPITLIM:
    2857 rval = mpq_QSset_param(lpi->prob, QS_PARAM_SIMPLEX_MAX_ITERATIONS, ival);
    2858 break;
    2859 default:
    2860 return SCIP_PARAMETERUNKNOWN;
    2861 } /*lint !e788*/
    2862
    2863 QS_RETURN(rval);
    2864}
    2865
    2866/** gets floating point parameter of LP */
    2868 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2869 SCIP_LPPARAM type, /**< parameter number */
    2870 SCIP_Real* dval /**< buffer to store the parameter value */
    2871 )
    2872{
    2873 int rval = 0;
    2874 mpq_t tmpval;
    2875 mpq_init(tmpval);
    2876
    2877 assert(lpi != NULL);
    2878 assert(lpi->prob != NULL);
    2879 assert(dval != NULL);
    2880
    2881 SCIPdebugMessage("getting real parameter %d\n", type);
    2882
    2883 switch( type )
    2884 {
    2885 case SCIP_LPPAR_OBJLIM:
    2886 rval = mpq_QSget_param_EGlpNum(lpi->prob, QS_PARAM_OBJLLIM, &tmpval);
    2887 break;
    2888 case SCIP_LPPAR_LPTILIM:
    2889 rval = mpq_QSget_param_EGlpNum(lpi->prob, QS_PARAM_SIMPLEX_MAX_TIME, &tmpval);
    2890 break;
    2891 default:
    2895 case SCIP_LPPAR_FEASTOL:
    2896 return SCIP_PARAMETERUNKNOWN;
    2897 } /*lint !e788*/
    2898
    2899 *dval = mpq_get_d(tmpval);
    2900 mpq_clear(tmpval);
    2901
    2902 QS_RETURN(rval);
    2903}
    2904
    2905/** sets floating point parameter of LP */
    2907 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2908 SCIP_LPPARAM type, /**< parameter number */
    2909 SCIP_Real dval /**< parameter value */
    2910 )
    2911{
    2912 int rval = 0;
    2913 mpq_t tmpval;
    2914 mpq_init(tmpval);
    2915 mpq_set_d(tmpval, dval);
    2916
    2917 assert(lpi != NULL);
    2918 assert(lpi->prob != NULL);
    2919
    2920 SCIPdebugMessage("setting real parameter %d to %g\n", type, dval);
    2921
    2922 switch( type )
    2923 {
    2924 case SCIP_LPPAR_LPTILIM:
    2925 rval = mpq_QSset_param_EGlpNum(lpi->prob, QS_PARAM_SIMPLEX_MAX_TIME, tmpval);
    2926 break;
    2927 case SCIP_LPPAR_OBJLIM:
    2928 rval = mpq_QSset_param_EGlpNum(lpi->prob, QS_PARAM_OBJLLIM, tmpval);
    2929 break;
    2930 case SCIP_LPPAR_FEASTOL:
    2934 default:
    2935 return SCIP_PARAMETERUNKNOWN;
    2936 } /*lint !e788*/
    2937
    2938 mpq_clear(tmpval);
    2939
    2940 QS_RETURN(rval);
    2941}
    2942
    2943/**@} */
    2944
    2945/*
    2946 * Numerical Methods
    2947 */
    2948
    2949/**@name Numerical Methods */
    2950/**@{ */
    2951
    2952/** returns value treated as positive infinity in the LP solver */
    2954 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2955 SCIP_RATIONAL* infval /**< pointer to store positive infinity value of LP solver */
    2956 )
    2957{
    2958 assert(infval != NULL);
    2959
    2960 SCIPrationalSetGMP(infval, mpq_ILL_MAXDOUBLE);
    2961}
    2962
    2963/** checks if given value is treated as positive infinity in the LP solver */
    2965 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2966 SCIP_RATIONAL* val /**< given value */
    2967 )
    2968{ /*lint --e{715} */
    2969 return (mpq_cmp(*SCIPrationalGetGMP(val), mpq_ILL_MAXDOUBLE) >= 0);
    2970}
    2971
    2972/** returns value treated as negative infinity in the LP solver */
    2974 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2975 SCIP_RATIONAL* infval /**< pointer to store negative infinity value of LP solver */
    2976 )
    2977{ /*lint --e{715} */
    2978 assert(infval != NULL);
    2979
    2980 SCIPrationalSetGMP(infval, mpq_ILL_MINDOUBLE);
    2981}
    2982
    2983/** checks if given value is treated as negative infinity in the LP solver */
    2985 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    2986 SCIP_RATIONAL* val /**< given value */
    2987 )
    2988{ /*lint --e{715} */
    2989 return (mpq_cmp(*SCIPrationalGetGMP(val), mpq_ILL_MINDOUBLE) <= 0);
    2990}
    2991
    2992/** returns value treated as negative infinity in the LP solver */
    2994 SCIP_LPIEXACT* lpi /**< LP interface structure */
    2995 )
    2996{ /*lint --e{715} */
    2997 assert(lpi != NULL);
    2998
    2999 return mpq_get_d(mpq_ILL_MAXDOUBLE);
    3000}
    3001
    3002/** checks if given value is treated as negative infinity in the LP solver */
    3004 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    3005 SCIP_Real val /**< given value */
    3006 )
    3007{ /*lint --e{715} */
    3008 return val >= mpq_get_d(mpq_ILL_MAXDOUBLE);
    3009}
    3010
    3011/**@} */
    3012
    3013/*
    3014 * File Interface Methods
    3015 */
    3016
    3017/**@name File Interface Methods */
    3018/**@{ */
    3019
    3020/** reads LP from a file */
    3022 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    3023 const char* fname /**< file name */
    3024 )
    3025{
    3026 int j;
    3027
    3028 assert(lpi != NULL);
    3029 assert(lpi->prob != NULL);
    3030
    3031 SCIPdebugMessage("reading LP from file <%s>\n", fname);
    3032
    3033 if( lpi->prob )
    3034 mpq_QSfree_prob(lpi->prob);
    3035
    3036 lpi->solstat = 0;
    3037 lpi->previt = 0;
    3038
    3039 /* try to extract file type */
    3040 j = strlen(fname)-1;
    3041 while( j >= 0 && fname[j] != '.' )
    3042 --j;
    3043 if( fname[j] == '.' )
    3044 ++j;
    3045
    3046 /* load problem */
    3047 lpi->prob = mpq_QSread_prob(fname, &(fname[j]));
    3048 if( lpi->prob == 0 )
    3049 return SCIP_READERROR;
    3050
    3051 return SCIP_OKAY;
    3052}
    3053
    3054/** writes LP to a file */
    3056 SCIP_LPIEXACT* lpi, /**< LP interface structure */
    3057 const char* fname /**< file name */
    3058 )
    3059{
    3060 int j;
    3061
    3062 assert(lpi != NULL);
    3063 assert(lpi->prob != NULL);
    3064
    3065 SCIPdebugMessage("writing LP to file <%s>\n", fname);
    3066
    3067 /* try to extract file type */
    3068 j = strlen(fname) - 1;
    3069 while( j >= 0 && fname[j] != '.' )
    3070 --j;
    3071 if( fname[j] == '.' )
    3072 ++j;
    3073
    3074 /* write problem */
    3075 if( mpq_QSwrite_prob(lpi->prob, fname, &(fname[j])) )
    3076 return SCIP_WRITEERROR;
    3077
    3078 return SCIP_OKAY;
    3079}
    3080
    3081/** prints additional lpiex internal info */
    3083 SCIP_LPIEXACT* lpi /**< pointer to an LP interface structure */
    3084 )
    3085{
    3086 mpq_lpinfo* lp;
    3087 lp = lpi->prob->lp;
    3088 SCIPerrorMessage("solstat= %d\n (solstat values: QS_LP_OPTIMAL=1, QS_LP_INFEASIBLE=2, QS_LP_UNBOUNDED=3, QS_LP_ITER_LIMIT=4, QS_LP_TIME_LIMIT=5, QS_LP_UNSOLVED=6, QS_LP_ABORTED=7, QS_LP_NUMERR=8, QS_LP_OBJ_LIMIT=9, QS_MODIFIED=100)\n", lpi->solstat );
    3089 SCIPerrorMessage("probstat.optimal= %d\n", lp->probstat.optimal );
    3090 SCIPerrorMessage("probstat.primal_feasible= %d\n", lp->probstat.primal_feasible );
    3091 SCIPerrorMessage("probstat.primal_infeasible= %d\n", lp->probstat.primal_infeasible );
    3092 SCIPerrorMessage("probstat.primal_unbounded= %d\n", lp->probstat.primal_unbounded );
    3093 SCIPerrorMessage("probstat.dual_feasible= %d\n", lp->probstat.dual_feasible );
    3094 SCIPerrorMessage("probstat.dual_infeasible= %d\n", lp->probstat.dual_infeasible );
    3095 SCIPerrorMessage("probstat.dual_unbounded= %d\n", lp->probstat.dual_unbounded );
    3096 SCIPerrorMessage("basisstat.primal_feasible= %d\n", lp->basisstat.primal_feasible );
    3097 SCIPerrorMessage("basisstat.primal_infeasible= %d\n", lp->basisstat.primal_infeasible );
    3098 SCIPerrorMessage("basisstat.dual_feasible= %d\n", lp->basisstat.dual_feasible );
    3099 SCIPerrorMessage("basisstat.dual_infeasible= %d\n", lp->basisstat.dual_infeasible );
    3100}
    3101/**@} */
    3102#endif
    void SCIPdecodeDualBit(const SCIP_DUALPACKET *inp, int *out, int count)
    Definition: bitencode.c:308
    void SCIPencodeDualBit(const int *inp, SCIP_DUALPACKET *out, int count)
    Definition: bitencode.c:238
    packing single and dual bit values
    unsigned int SCIP_DUALPACKET
    Definition: bitencode.h:42
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #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 SCIP_CALL(x)
    Definition: def.h:355
    void * SCIPlpiExactGetSolverPointer(SCIP_LPIEXACT *lpi)
    SCIP_Bool SCIPlpiExactHasDualRay(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactSetRealpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, SCIP_Real dval)
    SCIP_RETCODE SCIPlpiExactSetBase(SCIP_LPIEXACT *lpi, int *cstat, int *rstat)
    SCIP_RETCODE SCIPlpiExactReadState(SCIP_LPIEXACT *lpi, const char *fname)
    SCIP_Bool SCIPlpiExactHasStateBasis(SCIP_LPIEXACT *lpi, SCIP_LPISTATE *lpistate)
    SCIP_RETCODE SCIPlpiExactGetObj(SCIP_LPIEXACT *lpi, int firstcol, int lastcol, SCIP_RATIONAL **vals)
    SCIP_RETCODE SCIPlpiExactIgnoreInstability(SCIP_LPIEXACT *lpi, SCIP_Bool *success)
    SCIP_RETCODE SCIPlpiExactGetObjval(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *objval)
    void SCIPlpiExactEnd(void)
    SCIP_RETCODE SCIPlpiExactScaleRow(SCIP_LPIEXACT *lpi, int row, SCIP_RATIONAL *scaleval)
    const char * SCIPlpiExactGetExternalCodeDesc(void)
    SCIP_Bool SCIPlpiExactIsPosInfinity(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *val)
    SCIP_Bool SCIPlpiExactIsDualUnbounded(SCIP_LPIEXACT *lpi)
    void SCIPlpiExactPrintInfo(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactWriteLP(SCIP_LPIEXACT *lpi, const char *fname)
    SCIP_Bool SCIPlpiExactHasPrimalRay(SCIP_LPIEXACT *lpi)
    SCIP_Bool SCIPlpiExactExistsDualRay(SCIP_LPIEXACT *lpi)
    SCIP_Bool SCIPlpiExactIsStable(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactGetDualfarkas(SCIP_LPIEXACT *lpi, SCIP_RATIONAL **dualfarkas)
    SCIP_RETCODE SCIPlpiExactSolveDual(SCIP_LPIEXACT *lpi)
    const char * SCIPlpiExactGetSolverDesc(void)
    SCIP_RETCODE SCIPlpiExactChgObjsen(SCIP_LPIEXACT *lpi, SCIP_OBJSEN objsen)
    SCIP_RETCODE SCIPlpiExactSetIntpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, int ival)
    SCIP_RETCODE SCIPlpiExactWriteState(SCIP_LPIEXACT *lpi, const char *fname)
    SCIP_RETCODE SCIPlpiExactScaleCol(SCIP_LPIEXACT *lpi, int col, SCIP_RATIONAL *scaleval)
    SCIP_RETCODE SCIPlpiExactChgCoef(SCIP_LPIEXACT *lpi, int row, int col, SCIP_RATIONAL *newval)
    SCIP_Bool SCIPlpiExactWasSolved(SCIP_LPIEXACT *lpi)
    SCIP_Bool SCIPlpiExactIsPrimalUnbounded(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactGetSides(SCIP_LPIEXACT *lpi, int firstrow, int lastrow, SCIP_RATIONAL **lhss, SCIP_RATIONAL **rhss)
    const char * SCIPlpiExactGetSolverName(void)
    SCIP_RETCODE SCIPlpiExactGetCols(SCIP_LPIEXACT *lpi, int firstcol, int lastcol, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub, int *nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
    SCIP_Bool SCIPlpiExactIsPrimalInfeasible(SCIP_LPIEXACT *lpi)
    SCIP_Real SCIPlpiExactInfinity(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactGetRows(SCIP_LPIEXACT *lpi, int firstrow, int lastrow, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs, int *nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
    SCIP_RETCODE SCIPlpiExactGetSolFeasibility(SCIP_LPIEXACT *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
    SCIP_Bool SCIPlpiExactExistsPrimalRay(SCIP_LPIEXACT *lpi)
    SCIP_Bool SCIPlpiExactIsInfinity(SCIP_LPIEXACT *lpi, SCIP_Real val)
    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 SCIPlpiExactIsIterlimExc(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactLoadColLP(SCIP_LPIEXACT *lpi, SCIP_OBJSEN objsen, int ncols, SCIP_RATIONAL **obj, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub, char **colnames, int nrows, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs, char **rownames, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
    SCIP_Bool SCIPlpiExactIsPrimalFeasible(SCIP_LPIEXACT *lpi)
    SCIP_Bool SCIPlpiExactIsNegInfinity(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *val)
    SCIP_Bool SCIPlpiExactIsDualFeasible(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactReadLP(SCIP_LPIEXACT *lpi, const char *fname)
    SCIP_RETCODE SCIPlpiExactGetBasisInd(SCIP_LPIEXACT *lpi, int *bind)
    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)
    void SCIPlpiExactStart(void)
    SCIP_RETCODE SCIPlpiExactGetBase(SCIP_LPIEXACT *lpi, int *cstat, int *rstat)
    SCIP_RETCODE SCIPlpiExactDelColset(SCIP_LPIEXACT *lpi, int *dstat)
    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 SCIPlpiExactGetPrimalRay(SCIP_LPIEXACT *lpi, SCIP_RATIONAL **ray)
    SCIP_RETCODE SCIPlpiExactGetBounds(SCIP_LPIEXACT *lpi, int firstcol, int lastcol, SCIP_RATIONAL **lbs, SCIP_RATIONAL **ubs)
    int SCIPlpiExactGetInternalStatus(SCIP_LPIEXACT *lpi)
    const char * SCIPlpiExactGetExternalCodeName(void)
    void SCIPlpiExactPosInfinity(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *infval)
    SCIP_RETCODE SCIPlpiExactGetCoef(SCIP_LPIEXACT *lpi, int row, int col, SCIP_RATIONAL *val)
    SCIP_RETCODE SCIPlpiExactClear(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactGetNNonz(SCIP_LPIEXACT *lpi, int *nnonz)
    SCIP_RETCODE SCIPlpiExactFree(SCIP_LPIEXACT **lpi)
    SCIP_Bool SCIPlpiExactIsDualInfeasible(SCIP_LPIEXACT *lpi)
    SCIP_Bool SCIPlpiExactIsObjlimExc(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactGetNCols(SCIP_LPIEXACT *lpi, int *ncols)
    SCIP_RETCODE SCIPlpiExactSolveBarrier(SCIP_LPIEXACT *lpi, SCIP_Bool crossover)
    void SCIPlpiExactNegInfinity(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *infval)
    SCIP_RETCODE SCIPlpiExactChgSides(SCIP_LPIEXACT *lpi, int nrows, int *ind, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs)
    SCIP_RETCODE SCIPlpiExactGetState(SCIP_LPIEXACT *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    SCIP_RETCODE SCIPlpiExactDelRows(SCIP_LPIEXACT *lpi, int firstrow, int lastrow)
    SCIP_RETCODE SCIPlpiExactGetNRows(SCIP_LPIEXACT *lpi, int *nrows)
    SCIP_Bool SCIPlpiExactIsTimelimExc(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactGetRealpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
    SCIP_RETCODE SCIPlpiExactChgBounds(SCIP_LPIEXACT *lpi, int ncols, int *ind, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub)
    SCIP_RETCODE SCIPlpiExactStateDualFeasible(SCIP_LPIEXACT *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE *lpistate, SCIP_Bool useprestep, SCIP_Real *primalsol, SCIP_Real *dualsol, SCIP_Bool *result, SCIP_RATIONAL **dualobjval)
    SCIP_RETCODE SCIPlpiExactFreeState(SCIP_LPIEXACT *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    SCIP_RETCODE SCIPlpiExactDelRowset(SCIP_LPIEXACT *lpi, int *dstat)
    SCIP_RETCODE SCIPlpiExactGetSol(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *objval, SCIP_RATIONAL **primsol, SCIP_RATIONAL **dualsol, SCIP_RATIONAL **activity, SCIP_RATIONAL **redcost)
    SCIP_RETCODE SCIPlpiExactSolvePrimal(SCIP_LPIEXACT *lpi)
    SCIP_RETCODE SCIPlpiExactGetIntpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, int *ival)
    SCIP_RETCODE SCIPlpiExactSetState(SCIP_LPIEXACT *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE *lpistate)
    SCIP_RETCODE SCIPlpiExactGetIterations(SCIP_LPIEXACT *lpi, int *iterations)
    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 SCIPrationalResetFloatingPointRepresentable(SCIP_RATIONAL *rat)
    Definition: rational.cpp:642
    #define SCIPrationalDebugMessage
    Definition: rational.h:641
    void SCIPrationalCheckInfByValue(SCIP_RATIONAL *rational)
    Definition: rational.cpp:552
    int SCIPrationalGetSign(const SCIP_RATIONAL *rational)
    Definition: rational.cpp:2048
    SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
    Definition: rational.cpp:1404
    static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
    Definition: lpi_clp.cpp:218
    static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
    Definition: lpi_clp.cpp:234
    static int rowpacketNum(int nrows)
    Definition: lpi_clp.cpp:209
    SCIP_DUALPACKET ROWPACKET
    Definition: lpi_clp.cpp:128
    #define COLS_PER_PACKET
    Definition: lpi_clp.cpp:127
    static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
    Definition: lpi_clp.cpp:271
    SCIP_DUALPACKET COLPACKET
    Definition: lpi_clp.cpp:126
    static int colpacketNum(int ncols)
    Definition: lpi_clp.cpp:200
    static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
    Definition: lpi_clp.cpp:250
    #define ROWS_PER_PACKET
    Definition: lpi_clp.cpp:129
    static void convertSides(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, int indoffset, int *rngcount)
    Definition: lpi_cpx.c:740
    static SCIP_RETCODE ensureTabMem(SCIP_LPI *const lpi, int sz)
    Definition: lpi_qso.c:253
    #define QS_TESTG(A, B, C)
    Definition: lpi_qso.c:109
    #define QS_CONDRET(A)
    Definition: lpi_qso.c:134
    static SCIP_RETCODE ensureRowMem(SCIP_LPI *const lpi, int nrows)
    Definition: lpi_qso.c:287
    #define QS_RETURN(A)
    Definition: lpi_qso.c:124
    static SCIP_RETCODE ensureColMem(SCIP_LPI *const lpi, int ncols)
    Definition: lpi_qso.c:270
    #define QS_ERROR(A,...)
    Definition: lpi_qso.c:116
    interface methods for specific exact LP solvers
    #define BMSfreeMemory(ptr)
    Definition: memory.h:145
    #define BMSfreeBlockMemory(mem, ptr)
    Definition: memory.h:465
    #define BMSallocBlockMemory(mem, ptr)
    Definition: memory.h:451
    #define BMSreallocMemoryArray(ptr, num)
    Definition: memory.h:127
    #define BMSallocMemoryArray(ptr, num)
    Definition: memory.h:123
    #define BMSfreeMemoryArray(ptr)
    Definition: memory.h:147
    #define BMSallocBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:454
    #define BMSfreeBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:467
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    #define BMSallocMemory(ptr)
    Definition: memory.h:118
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    #define SCIPdebugPrintf
    Definition: pub_message.h:99
    wrapper for rational number arithmetic that interacts with GMP
    public methods for memory management
    SCIP_PRICING pricing
    COLPACKET * packcstat
    Definition: lpi_clp.cpp:136
    ROWPACKET * packrstat
    Definition: lpi_clp.cpp:137
    @ SCIP_PRICING_STEEPQSTART
    Definition: type_lpi.h:83
    @ SCIP_PRICING_AUTO
    Definition: type_lpi.h:79
    @ SCIP_PRICING_DEVEX
    Definition: type_lpi.h:84
    @ SCIP_PRICING_STEEP
    Definition: type_lpi.h:82
    @ SCIP_PRICING_FULL
    Definition: type_lpi.h:80
    @ SCIP_PRICING_LPIDEFAULT
    Definition: type_lpi.h:78
    @ SCIP_PRICING_PARTIAL
    Definition: type_lpi.h:81
    enum SCIP_LPParam SCIP_LPPARAM
    Definition: type_lpi.h:73
    @ SCIP_LPPAR_PRICING
    Definition: type_lpi.h:54
    @ SCIP_LPPAR_LPINFO
    Definition: type_lpi.h:55
    @ SCIP_LPPAR_SCALING
    Definition: type_lpi.h:52
    @ SCIP_LPPAR_LPTILIM
    Definition: type_lpi.h:61
    @ SCIP_LPPAR_BARRIERCONVTOL
    Definition: type_lpi.h:58
    @ SCIP_LPPAR_PRESOLVING
    Definition: type_lpi.h:53
    @ SCIP_LPPAR_FASTMIP
    Definition: type_lpi.h:51
    @ SCIP_LPPAR_DUALFEASTOL
    Definition: type_lpi.h:57
    @ SCIP_LPPAR_FROMSCRATCH
    Definition: type_lpi.h:50
    @ SCIP_LPPAR_MARKOWITZ
    Definition: type_lpi.h:62
    @ SCIP_LPPAR_FEASTOL
    Definition: type_lpi.h:56
    @ SCIP_LPPAR_LPITLIM
    Definition: type_lpi.h:60
    @ SCIP_LPPAR_OBJLIM
    Definition: type_lpi.h:59
    @ SCIP_BASESTAT_BASIC
    Definition: type_lpi.h:92
    @ SCIP_BASESTAT_UPPER
    Definition: type_lpi.h:93
    @ SCIP_BASESTAT_LOWER
    Definition: type_lpi.h:91
    @ SCIP_BASESTAT_ZERO
    Definition: type_lpi.h:94
    @ SCIP_OBJSEN_MAXIMIZE
    Definition: type_lpi.h:42
    enum SCIP_ObjSen SCIP_OBJSEN
    Definition: type_lpi.h:45
    type definitions for specific exact LP solvers interface
    @ SCIP_LPERROR
    Definition: type_retcode.h:49
    @ SCIP_READERROR
    Definition: type_retcode.h:45
    @ SCIP_PARAMETERUNKNOWN
    Definition: type_retcode.h:55
    @ SCIP_WRITEERROR
    Definition: type_retcode.h:46
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63