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