Scippy

    SCIP

    Solving Constraint Integer Programs

    lpi_spx.cpp
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file lpi_spx.cpp
    26 * @ingroup LPIS
    27 * @brief LP interface for SoPlex
    28 * @author Matthias Miltenberger
    29 * @author Ambros Gleixner
    30 *
    31 * This is an implementation of SCIP's LP interface for SoPlex.
    32 *
    33 * For debugging purposes, the SoPlex results can be double checked with CPLEX if SCIP_WITH_LPSCHECK is defined. This may
    34 * yield false positives, since the LP is dumped to a file for transferring it to CPLEX, hence, precision may be lost.
    35 */
    36
    37/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    38
    39#define STRONGBRANCH_RESTOREBASIS /**< if defined then in SCIPlpiStrongbranch() we restore the basis after the
    40 * down branch and after the up branch; if false only after the end of a
    41 * strong branching phase, which however seems to mostly increase strong
    42 * branching time and iterations */
    43
    44/*
    45 * include build configuration flags
    46 */
    47#include "scip/config.h"
    48
    49/* in this case the SoPlex results are double checked using CPLEX */
    50#ifdef SCIP_WITH_LPSCHECK
    51#include <cplex.h>
    52
    53#define CHECK_SPXSOLVE true /**< shall the SoPlex results in spxSolve() be double checked using CPLEX? */
    54#define CHECK_SPXSTRONGBRANCH true /**< shall the SoPlex results in SCIPlpStrongbranch() be double checked using CPLEX? */
    55#define CHECK_START 0 /**< skip first CHECK_START number of checks */
    56#define EXIT_AT_WRONG_RESULT false/**< shall program be exited if CPLEX returns different result than SoPlex? */
    57#define EXIT_AT_CPXERROR false/**< shall program be exited if CPLEX returns an error? */
    58
    59#define CPX_CALL(x) do \
    60 { \
    61 int _cpxstat_; \
    62 if( (_cpxstat_ = (x)) != 0 ) \
    63 { \
    64 SCIPmessagePrintWarning(_messagehdlr, "CPLEX error <%d>; SoPlex result unchecked\n", _cpxstat_); \
    65 if( EXIT_AT_CPXERROR ) \
    66 { \
    67 exit(1); \
    68 } \
    69 else \
    70 { \
    71 goto ENDCHECK; \
    72 } \
    73 } \
    74 } \
    75 while( false )
    76#endif
    77
    78/* check the return value of setParam methods */
    79#define CHECK_SOPLEX_PARAM(x) \
    80 if( !x ) \
    81 { \
    82 SCIPmessagePrintWarning(_messagehdlr, "SoPlex: unsupported parameter value\n"); \
    83 }
    84
    85/* remember the original value of the SCIP_DEBUG define and undefine it */
    86#ifdef SCIP_DEBUG
    87#define ___DEBUG
    88#undef SCIP_DEBUG
    89#endif
    90
    91/* compile the SoPlex header with visibility=default because the SoPlex lib has been compiled that way */
    92#ifdef __GNUC__
    93#pragma GCC visibility push(default)
    94#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
    95#endif
    96
    97/* include SoPlex solver */
    98#include "soplex.h"
    99
    100/* define subversion for versions <= 1.5.0.1 */
    101#ifndef SOPLEX_SUBVERSION
    102#define SOPLEX_SUBVERSION 0
    103#endif
    104/* define API version for versions <= 3.0.0 */
    105#ifndef SOPLEX_APIVERSION
    106#define SOPLEX_APIVERSION 0
    107#endif
    108
    109/* check version */
    110#if (SOPLEX_VERSION < 200 || (SOPLEX_VERSION == 200 && SOPLEX_SUBVERSION < 2) || (SOPLEX_VERSION > 200 && SOPLEX_VERSION < 201))
    111#error "This interface is not compatible with SoPlex versions prior to 2.0.0.2"
    112#endif
    113
    114#if (SOPLEX_APIVERSION <= 5)
    115#include "spxgithash.h"
    116#endif
    117
    118/* reset the SCIP_DEBUG define to its original SCIP value */
    119#undef SCIP_DEBUG
    120#ifdef ___DEBUG
    121#define SCIP_DEBUG
    122#undef ___DEBUG
    123#endif
    124
    125/* define snprintf when using a too old MSVC version */
    126#if defined(_MSC_VER) && _MSC_VER < 1900
    127#ifndef snprintf
    128#define snprintf _snprintf
    129#endif
    130#endif
    131
    132#define SOPLEX_VERBLEVEL 5 /**< verbosity level for LPINFO */
    133
    134#include "scip/pub_message.h"
    135
    136/********************************************************************/
    137/*----------------------------- C++ --------------------------------*/
    138/********************************************************************/
    139
    140/* in C++ we have to use "0" instead of "(void*)0" */
    141#undef NULL
    142#define NULL 0
    143
    144#include <cassert>
    145using namespace soplex;
    146
    147
    148/** Macro for a single SoPlex call for which exceptions have to be catched - return an LP error. We
    149 * make no distinction between different exception types, e.g., between memory allocation and other
    150 * exceptions.
    151 */
    152#ifndef NDEBUG
    153#define SOPLEX_TRY(messagehdlr, x) do \
    154 { \
    155 try \
    156 { \
    157 (x); \
    158 } \
    159 catch( const SPxMemoryException& E ) \
    160 { \
    161 std::string s = E.what(); \
    162 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
    163 return SCIP_ERROR; \
    164 } \
    165 catch( const SPxException& E ) \
    166 { \
    167 std::string s = E.what(); \
    168 SCIPmessagePrintWarning((messagehdlr), "SoPlex threw an exception: %s\n", s.c_str()); \
    169 return SCIP_LPERROR; \
    170 } \
    171 } \
    172 while( FALSE )
    173
    174#else
    175#define SOPLEX_TRY(messagehdlr, x) do \
    176 { \
    177 try \
    178 { \
    179 (x); \
    180 } \
    181 catch( const SPxMemoryException& E ) \
    182 { \
    183 std::string s = E.what(); \
    184 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
    185 return SCIP_ERROR; \
    186 } \
    187 catch( const SPxException& ) \
    188 { \
    189 return SCIP_LPERROR; \
    190 } \
    191 } \
    192 while( FALSE )
    193#endif
    194
    195/* Macro for a single SoPlex call for which exceptions have to be catched - abort if they
    196 * arise. SCIP_ABORT() is not accessible here.
    197 */
    198#define SOPLEX_TRY_ABORT(x) do \
    199 { \
    200 try \
    201 { \
    202 (x); \
    203 } \
    204 catch( const SPxException& E ) \
    205 { \
    206 std::string s = E.what(); \
    207 SCIPerrorMessage("SoPlex threw an exception: %s\n", s.c_str()); \
    208 abort(); \
    209 } \
    210 } \
    211 while( FALSE )
    212
    213
    214
    215/** SCIP's SoPlex class */
    216class SPxSCIP : public SoPlex
    217{/*lint !e1790*/
    218 bool _lpinfo;
    219 bool _fromscratch;
    220 bool _interrupt;
    221 char* _probname;
    222 DataArray<SPxSolver::VarStatus> _colStat; /**< column basis status used for strong branching */
    223 DataArray<SPxSolver::VarStatus> _rowStat; /**< row basis status used for strong branching */
    224#ifdef SCIP_WITH_LPSCHECK
    225 int _checknum;
    226 bool _doublecheck;
    227 CPXENVptr _cpxenv; /**< CPLEX memory environment */
    228 CPXLPptr _cpxlp; /**< CPLEX lp structure */
    229#endif
    230 SCIP_MESSAGEHDLR* _messagehdlr; /**< messagehdlr handler for printing messages, or NULL */
    231
    232public:
    233 SPxSCIP(
    234 SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
    235 const char* probname = NULL /**< name of problem */
    236 )
    237 : _lpinfo(false),
    238 _fromscratch(false),
    239 _probname(NULL),
    240 _colStat(0),
    241 _rowStat(0),
    242 _messagehdlr(messagehdlr)
    243 {
    244 if ( probname != NULL )
    245 SOPLEX_TRY_ABORT( setProbname(probname) );
    246
    247#if SOPLEX_APIVERSION >= 2
    248 (void)setBoolParam(SoPlex::ENSURERAY, true);
    249#endif
    250
    251#ifdef SCIP_WITH_LPSCHECK
    252 int cpxstat;
    253 _checknum = 0;
    254 _doublecheck = false;
    255 _cpxenv = CPXopenCPLEX(&cpxstat);
    256 assert(_cpxenv != NULL);
    257 _cpxlp = CPXcreateprob(_cpxenv, &cpxstat, probname != NULL ? probname : "spxcheck");
    258 (void) CPXsetintparam(_cpxenv, CPX_PARAM_SCRIND, 0);
    259#endif
    260 }
    261
    262 virtual ~SPxSCIP()
    263 {
    264 if( _probname != NULL )
    265 spx_free(_probname); /*lint !e1551*/
    266
    267 freePreStrongbranchingBasis(); /*lint !e1551*/
    268
    269#ifdef SCIP_WITH_LPSCHECK
    270 (void) CPXfreeprob(_cpxenv, &_cpxlp);
    271 (void) CPXcloseCPLEX(&_cpxenv);
    272#endif
    273 }/*lint -e1579*/
    274
    275 // we might need these methods to return the original values SCIP provided, even if they could not be set
    276 /** return feastol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
    277 Real feastol() const
    278 {
    279 return realParam(FEASTOL);
    280 }
    281
    282 /** set feastol and store value in case SoPlex only accepts a larger tolerance */
    283 void setFeastol(
    284 const Real d
    285 )
    286 {
    287 CHECK_SOPLEX_PARAM(setRealParam(FEASTOL, d));
    288 }
    289
    290 /** return opttol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
    291 Real opttol() const
    292 {
    293 return realParam(OPTTOL);
    294 }
    295
    296 /** set opttol and store value in case SoPlex only accepts a larger tolerance */
    297 void setOpttol(
    298 const Real d
    299 )
    300 {
    301 CHECK_SOPLEX_PARAM(setRealParam(OPTTOL, d));
    302 }
    303
    304 /** get objective limit according to objective sense */
    305 Real getObjLimit() const
    306 {
    307 return (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE)
    308 ? realParam(SoPlex::OBJLIMIT_UPPER)
    309 : realParam(SoPlex::OBJLIMIT_LOWER);
    310 }
    311
    312 // @todo realize this with a member variable as before
    313 bool getFromScratch() const
    314 {
    315 return _fromscratch;
    316 }
    317
    318 void setFromScratch(bool fs)
    319 {
    320 _fromscratch = fs;
    321 }
    322
    323 void setInterrupt(bool interrupt)
    324 {
    325 _interrupt = interrupt;
    326 }
    327
    328 bool* getInterrupt()
    329 {
    330 return &_interrupt;
    331 }
    332
    333 // @todo member variable?
    334 bool getLpInfo() const
    335 {
    336 return _lpinfo;
    337 }
    338
    339 void setLpInfo(bool lpinfo)
    340 {
    341 _lpinfo = lpinfo;
    342 }
    343
    344 // @todo member variable?
    345 void setProbname(const char* probname)
    346 {
    347 size_t len;
    348
    349 assert(probname != NULL);
    350 if( _probname != NULL )
    351 spx_free(_probname);
    352
    353 len = strlen(probname);
    354 spx_alloc(_probname, len + 1);
    355 memcpy(_probname, probname, len + 1);
    356 }
    357
    358 void setRep(SPxSolver::Representation p_rep)
    359 {
    360 if( p_rep == SPxSolver::COLUMN && intParam(REPRESENTATION) == REPRESENTATION_ROW )
    361 {
    362 SCIPdebugMessage("switching to column representation of the basis\n");
    363 CHECK_SOPLEX_PARAM(setIntParam(REPRESENTATION, REPRESENTATION_COLUMN));
    364 }
    365 else if( (p_rep == SPxSolver::ROW && intParam(REPRESENTATION) == REPRESENTATION_COLUMN) )
    366 {
    367 SCIPdebugMessage("switching to row representation of the basis\n");
    368 CHECK_SOPLEX_PARAM(setIntParam(REPRESENTATION, REPRESENTATION_ROW));
    369 }
    370 }
    371
    372#ifdef SCIP_WITH_LPSCHECK
    373 bool getDoubleCheck()
    374 {
    375 _checknum++;
    376 return _doublecheck && _checknum + 1 >= CHECK_START;
    377 }
    378
    379 void setDoubleCheck(bool dc)
    380 {
    381 _doublecheck = dc;
    382 }
    383
    384 const char* spxStatusString(const SPxSolver::Status stat) const
    385 {
    386 switch( stat )
    387 {
    388 case SPxSolver::ABORT_TIME:
    389 return "ABORT_TIME";
    390 case SPxSolver::ABORT_ITER:
    391 return "ABORT_ITER";
    392 case SPxSolver::ABORT_VALUE:
    393 return "ABORT_VALUE";
    394 case SPxSolver::SINGULAR:
    395 return "SINGULAR";
    396 case SPxSolver::REGULAR:
    397 return "REGULAR";
    399 return "UNKNOWN";
    400 case SPxSolver::OPTIMAL:
    401 return "OPTIMAL";
    402#if SOPLEX_APIVERSION >= 3
    403 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
    404 return "OPTIMAL_UNSCALED_VIOLATIONS";
    405#endif
    406 case SPxSolver::UNBOUNDED:
    407 return "UNBOUNDED";
    408 case SPxSolver::INFEASIBLE:
    409 return "INFEASIBLE";
    410 default:
    411 return "UNKNOWN";
    412 } /*lint !e788*/
    413 }
    414
    415 const char* cpxStatusString(const int stat) const
    416 {
    417 switch( stat )
    418 {
    419 case CPX_STAT_ABORT_TIME_LIM:
    420 return "ABORT_TIME";
    421 case CPX_STAT_ABORT_IT_LIM:
    422 return "ABORT_ITER";
    423 case CPX_STAT_ABORT_OBJ_LIM:
    424 return "ABORT_VALUE";
    425 case CPX_STAT_OPTIMAL:
    426 return "OPTIMAL";
    427 case CPX_STAT_OPTIMAL_INFEAS:
    428 return "CPX_STAT_OPTIMAL_INFEAS: OPT SOL INFEASIBLE AFTER UNSCALING";
    429 case CPX_STAT_UNBOUNDED:
    430 return "UNBOUNDED";
    431 case CPX_STAT_INFEASIBLE:
    432 return "INFEASIBLE";
    433 case CPX_STAT_INForUNBD:
    434 return "INFEASIBLE or UNBOUNDED";
    435 case CPX_STAT_NUM_BEST:
    436 return "CPX_STAT_NUM_BEST: SOL AVAILABLE BUT NOT PROVEN OPTIMAL DUE TO NUM TROUBLE";
    437 default:
    438 return "UNKNOWN";
    439 } /*lint !e788*/
    440 }
    441#endif
    442
    443#ifndef NDEBUG
    444 bool checkConsistentBounds() const
    445 {
    446 for( int i = 0; i < numColsReal(); ++i )
    447 {
    448 if( lowerReal(i) > upperReal(i) + realParam(SoPlex::EPSILON_ZERO) )
    449 {
    450 SCIPerrorMessage("inconsistent bounds on column %d: lower=%.17g, upper=%.17g\n",
    451 i, lowerReal(i), upperReal(i));
    452 return false;
    453 }
    454 }
    455
    456 return true;
    457 }
    458
    459 bool checkConsistentSides() const
    460 {
    461 for( int i = 0; i < numRowsReal(); ++i )
    462 {
    463 if( lhsReal(i) > rhsReal(i) + realParam(SoPlex::EPSILON_ZERO) )
    464 {
    465 SCIPerrorMessage("inconsistent sides on row %d: lhs=%.17g, rhs=%.17g\n",
    466 i, lhsReal(i), rhsReal(i));
    467 return false;
    468 }
    469 }
    470
    471 return true;
    472 }
    473#endif
    474
    475 void trySolve(bool printwarning = true)
    476 {
    477 Real timespent;
    478 Real timelimit;
    479
    480 try
    481 {
    482#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    483#if SOPLEX_APIVERSION > 11
    484 (void) optimize(&_interrupt);
    485#else
    486 (void) optimize();
    487#endif
    488#else
    489 (void) solve();
    490#endif
    491 }
    492 catch(const SPxException& x)
    493 {
    494 std::string s = x.what();
    495 if( printwarning )
    496 {
    497 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    498 }
    499
    500 /* since it is not clear if the status in SoPlex are set correctly
    501 * we want to make sure that if an error is thrown the status is
    502 * not OPTIMAL anymore.
    503 */
    504 assert(status() != SPxSolver::OPTIMAL);
    505 }
    506
    507 assert(intParam(ITERLIMIT) < 0 || numIterations() <= intParam(ITERLIMIT));
    508
    509 /* update time limit */
    510 timespent = solveTime();
    511 if( timespent > 0 )
    512 {
    513 /* get current time limit */
    514 timelimit = realParam(TIMELIMIT);
    515 if( timelimit > timespent )
    516 timelimit -= timespent;
    517 else
    518 timelimit = 0;
    519 /* set new time limit */
    520 assert(timelimit >= 0);
    521 CHECK_SOPLEX_PARAM(setRealParam(TIMELIMIT, timelimit));
    522 }
    523 }
    524
    525 SPxSolver::Status doSolve(bool printwarning = true)
    526 {
    527 SPxOut::Verbosity verbosity;
    528
    529 SPxSolver::Status spxStatus;
    530
    531 /* store and set verbosity */
    532 verbosity = spxout.getVerbosity();
    533 spxout.setVerbosity((SPxOut::Verbosity)(getLpInfo() ? SOPLEX_VERBLEVEL : 0));
    534
    535 assert(checkConsistentBounds());
    536 assert(checkConsistentSides());
    537
    538#ifdef SCIP_WITH_LPSCHECK
    539 /* dump LP with current basis and settings saved in SoPlex */
    540 if( getDoubleCheck() )
    541 writeStateReal("spxcheck", NULL, NULL);
    542#endif
    543
    544 trySolve(printwarning);
    545 spxStatus = status();
    546
    547 /* for safety reset iteration limit */
    548// setTerminationIter(_itlim);
    549
    550#ifdef SCIP_WITH_LPSCHECK
    551 bool minimize = intParam(OBJSENSE) == OBJSENSE_MINIMIZE;
    552 Real objLimitUpper = realParam(OBJLIMIT_UPPER);
    553 Real objLimitLower = realParam(OBJLIMIT_LOWER);
    554
    555 /* if SoPlex gave a definite answer, we double check if it is consistent with CPLEX's answer */
    556 if( getDoubleCheck() && (spxStatus == SPxSolver::OPTIMAL || spxStatus == SPxSolver::UNBOUNDED || spxStatus == SPxSolver::INFEASIBLE || spxStatus == SPxSolver::ABORT_VALUE) )
    557 {
    558 SCIP_Real cpxobj;
    559 int cpxstat;
    560
    561 /* read LP with basis */
    562 CPX_CALL( CPXreadcopyprob(_cpxenv, _cpxlp, "spxcheck.mps", NULL) );
    563 CPX_CALL( CPXreadcopybase(_cpxenv, _cpxlp, "spxcheck.bas") );
    564
    565 /* set tolerances */
    566 CPX_CALL( CPXsetdblparam(_cpxenv, CPX_PARAM_EPOPT, MAX(opttol(), 1e-9)) );
    567 CPX_CALL( CPXsetdblparam(_cpxenv, CPX_PARAM_EPRHS, MAX(feastol(), 1e-9)) );
    568
    569 /* solve LP */
    570 CPX_CALL( CPXlpopt(_cpxenv, _cpxlp) );
    571
    572 /* get solution status and objective value */
    573 CPX_CALL( CPXsolution(_cpxenv, _cpxlp, &cpxstat, &cpxobj, NULL, NULL, NULL, NULL) );
    574 if( !minimize )
    575 cpxobj *= -1.0;
    576
    577 /* check for inconsistent statuses */
    578 if( cpxstat == CPX_STAT_OPTIMAL_INFEAS )
    579 {
    580 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s)\n",
    581 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat));
    582 if( EXIT_AT_CPXERROR )
    583 exit(1);
    584 }
    585 else if( (spxStatus == SPxSolver::OPTIMAL && cpxstat != CPX_STAT_OPTIMAL)
    586 || (spxStatus == SPxSolver::UNBOUNDED && cpxstat != CPX_STAT_UNBOUNDED)
    587 || (spxStatus == SPxSolver::INFEASIBLE && cpxstat != CPX_STAT_INFEASIBLE) )
    588 {
    589 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
    590 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
    591 if( EXIT_AT_WRONG_RESULT )
    592 exit(1);
    593 }
    594 else if( spxStatus == SPxSolver::ABORT_VALUE )
    595 {
    596 switch( cpxstat )
    597 {
    598 case CPX_STAT_OPTIMAL:
    599 if( (minimize && LTrel(cpxobj, objLimitUpper, 2*opttol()))
    600 || (!minimize && GTrel(cpxobj, objLimitLower, 2*opttol())) )
    601 {
    602 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
    603 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize ? "<" : ">",
    604 minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
    605 if( EXIT_AT_WRONG_RESULT )
    606 exit(1);
    607 }
    608 else if( (minimize && cpxobj < objLimitUpper) || (!minimize && cpxobj > objLimitLower) )
    609 {
    610 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
    611 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize? "<" : ">",
    612 minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
    613 }
    614 break;
    615 case CPX_STAT_OPTIMAL_INFEAS:
    616 case CPX_STAT_NUM_BEST:
    617 if( (minimize && cpxobj < objLimitUpper) || (!minimize && cpxobj > objLimitLower) )
    618 {
    619 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
    620 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize ? "<" : ">",
    621 minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
    622 }
    623 break;
    624 case CPX_STAT_INFEASIBLE:
    625 break;
    626 case CPX_STAT_UNBOUNDED:
    627 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
    628 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
    629 if( EXIT_AT_WRONG_RESULT )
    630 exit(1);
    631 break;
    632 case CPX_STAT_INForUNBD:
    633 default:
    634 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
    635 _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
    636 break;
    637 } /*lint !e788*/
    638 }
    639 /* check for same objective values */
    640 else if( spxStatus == SPxSolver::OPTIMAL )
    641 {
    642 if( (minimize && LTrel(objValueReal(), cpxobj, 2*opttol()))
    643 || (!minimize && GTrel(objValueReal(), cpxobj, 2*opttol())) )
    644 {
    645 /* SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f too good (checknum=%d)\n", value(),
    646 _probname, getSense() == SPxSolver::MINIMIZE ? "<" : ">", cpxobj, _checknum); */
    647 }
    648 else if( (minimize && GTrel(objValueReal(), cpxobj, 2*opttol()))
    649 || (!minimize && LTrel(objValueReal(), cpxobj, 2*opttol())) )
    650 {
    651 SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f suboptimal (checknum=%d)\n", _probname, objValueReal(),
    652 minimize ? ">" : "<", cpxobj, _checknum);
    653 if( EXIT_AT_WRONG_RESULT )
    654 exit(1);
    655 }
    656 }
    657 }
    658
    659 ENDCHECK:
    660#endif
    661
    662 /* restore verbosity */
    663 spxout.setVerbosity(verbosity);
    664
    665 return spxStatus;
    666 }
    667
    668 /** save the current basis */
    669 void savePreStrongbranchingBasis()
    670 {
    671 _rowStat.reSize(numRowsReal());
    672 _colStat.reSize(numColsReal());
    673
    674 try
    675 {
    676 getBasis(_rowStat.get_ptr(), _colStat.get_ptr());
    677 }
    678#ifndef NDEBUG
    679 catch(const SPxException& x)
    680 {
    681 std::string s = x.what();
    682 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    683
    684 /* since it is not clear if the status in SoPlex are set correctly
    685 * we want to make sure that if an error is thrown the status is
    686 * not OPTIMAL anymore.
    687 */
    688 assert(status() != SPxSolver::OPTIMAL);
    689 }
    690#else
    691 catch(const SPxException&)
    692 { }
    693#endif
    694 }
    695
    696 /** restore basis */
    697 void restorePreStrongbranchingBasis()
    698 {
    699 assert(_rowStat.size() == numRowsReal());
    700 assert(_colStat.size() == numColsReal());
    701
    702 try
    703 {
    704 setBasis(_rowStat.get_ptr(), _colStat.get_ptr());
    705 }
    706#ifndef NDEBUG
    707 catch(const SPxException& x)
    708 {
    709 std::string s = x.what();
    710 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    711#else
    712 catch(const SPxException&)
    713 {
    714#endif
    715 /* since it is not clear if the status in SoPlex are set correctly
    716 * we want to make sure that if an error is thrown the status is
    717 * not OPTIMAL anymore.
    718 */
    719 assert(status() != SPxSolver::OPTIMAL);
    720 }
    721 }
    722
    723 /** if basis is in store, delete it without restoring it */
    724 void freePreStrongbranchingBasis()
    725 {
    726 _rowStat.clear();
    727 _colStat.clear();
    728 }
    729
    730 /** is pre-strong-branching basis freed? */
    731 bool preStrongbranchingBasisFreed() const
    732 {
    733 return ((_rowStat.size() == 0 ) && (_colStat.size() == 0));
    734 }
    735
    736 /** provides access for temporary storage of basis status of rows */
    737 DataArray<SPxSolver::VarStatus>& rowStat()
    738 {
    739 return _rowStat; /*lint !e1536*/
    740 }
    741
    742 /** provides access for temporary storage of basis status or columns */
    743 DataArray<SPxSolver::VarStatus>& colStat()
    744 {
    745 return _colStat; /*lint !e1536*/
    746 }
    747
    748}; /*lint !e1748*/
    749
    750
    751
    752
    753/********************************************************************/
    754/*----------------------------- C --------------------------------*/
    755/********************************************************************/
    756
    757#include "lpi/lpi.h"
    758#include "scip/bitencode.h"
    759
    760typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
    761#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
    762typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
    763#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
    764
    765
    766
    767/** LP interface */
    768struct SCIP_LPi
    769{
    770 SPxSCIP* spx; /**< our SoPlex implementation */
    771 int* cstat; /**< array for storing column basis status */
    772 int* rstat; /**< array for storing row basis status */
    773 int cstatsize; /**< size of cstat array */
    774 int rstatsize; /**< size of rstat array */
    775 SCIP_PRICING pricing; /**< current pricing strategy */
    776 SCIP_Bool solved; /**< was the current LP solved? */
    777 SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
    778 SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
    779 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
    780};
    781
    782/** LPi state stores basis information */
    783struct SCIP_LPiState
    784{
    785 int ncols; /**< number of LP columns */
    786 int nrows; /**< number of LP rows */
    787 COLPACKET* packcstat; /**< column basis status in compressed form */
    788 ROWPACKET* packrstat; /**< row basis status in compressed form */
    789};
    790
    791/** LPi norms to store dual steepest edge */
    792struct SCIP_LPiNorms
    793{
    794 int nrows; /**< number of stored norms corresponding to rows */
    795 int ncols; /**< number of stored norms corresponding to cols */
    796 SCIP_Real* norms; /**< norms to be (re)stored */
    797};
    798
    799
    800
    801/*
    802 * dynamic memory arrays
    803 */
    804
    805/** resizes cstat array to have at least num entries */
    806static
    808 SCIP_LPI* lpi, /**< LP interface structure */
    809 int num /**< minimal number of entries in array */
    810 )
    811{
    812 assert(lpi != NULL);
    813
    814 if( num > lpi->cstatsize )
    815 {
    816 int newsize;
    817
    818 newsize = MAX(2*lpi->cstatsize, num);
    819 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->cstat, newsize) );
    820 lpi->cstatsize = newsize;
    821 }
    822 assert(num <= lpi->cstatsize);
    823
    824 return SCIP_OKAY;
    825}
    826
    827/** resizes rstat array to have at least num entries */
    828static
    830 SCIP_LPI* lpi, /**< LP interface structure */
    831 int num /**< minimal number of entries in array */
    832 )
    833{
    834 assert(lpi != NULL);
    835
    836 if( num > lpi->rstatsize )
    837 {
    838 int newsize;
    839
    840 newsize = MAX(2*lpi->rstatsize, num);
    841 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->rstat, newsize) );
    842 lpi->rstatsize = newsize;
    843 }
    844 assert(num <= lpi->rstatsize);
    845
    846 return SCIP_OKAY;
    847}
    848
    849
    850
    851
    852/*
    853 * LPi state methods
    854 */
    855
    856/** returns the number of packets needed to store column packet information */
    857static
    859 int ncols /**< number of columns to store */
    860 )
    861{
    862 return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
    863}
    864
    865/** returns the number of packets needed to store row packet information */
    866static
    868 int nrows /**< number of rows to store */
    869 )
    870{
    871 return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
    872}
    873
    874/** store row and column basis status in a packed LPi state object */
    875static
    877 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
    878 const int* cstat, /**< basis status of columns in unpacked format */
    879 const int* rstat /**< basis status of rows in unpacked format */
    880 )
    881{
    882 assert(lpistate != NULL);
    883 assert(lpistate->packcstat != NULL);
    884 assert(lpistate->packrstat != NULL);
    885
    886 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
    887 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
    888}
    889
    890/** unpacks row and column basis status from a packed LPi state object */
    891static
    893 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
    894 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
    895 int* rstat /**< buffer for storing basis status of rows in unpacked format */
    896 )
    897{
    898 assert(lpistate != NULL);
    899 assert(lpistate->packcstat != NULL);
    900 assert(lpistate->packrstat != NULL);
    901
    902 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
    903 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
    904}
    905
    906/** creates LPi state information object */
    907static
    909 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
    910 BMS_BLKMEM* blkmem, /**< block memory */
    911 int ncols, /**< number of columns to store */
    912 int nrows /**< number of rows to store */
    913 )
    914{
    915 assert(lpistate != NULL);
    916 assert(blkmem != NULL);
    917 assert(ncols >= 0);
    918 assert(nrows >= 0);
    919
    920 int nColPackets = colpacketNum(ncols);
    921 int nRowPackets = rowpacketNum(nrows);
    922
    923 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
    924 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
    925 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
    926
    927 return SCIP_OKAY;
    928}
    929
    930/** frees LPi state information */
    931static
    933 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
    934 BMS_BLKMEM* blkmem /**< block memory */
    935 )
    936{
    937 assert(blkmem != NULL);
    938 assert(lpistate != NULL);
    939 assert(*lpistate != NULL);
    940
    941 int nColPackets = colpacketNum((*lpistate)->ncols);
    942 int nRowPackets = rowpacketNum((*lpistate)->nrows);
    943
    944 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
    945 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
    946 BMSfreeBlockMemory(blkmem, lpistate);
    947}
    948
    949
    950
    951
    952/*
    953 * local methods
    954 */
    955
    956
    957/** marks the current LP to be unsolved */
    958static
    960{
    961 assert(lpi != NULL);
    962 lpi->solved = FALSE;
    963}
    964
    965
    966
    967/*
    968 * LP Interface Methods
    969 */
    970
    971
    972/*
    973 * Miscellaneous Methods
    974 */
    975
    976#if (SOPLEX_SUBVERSION > 0)
    977 const static char spxname[20] = {'S', 'o', 'P', 'l', 'e', 'x', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '.', SOPLEX_SUBVERSION + '0', '\0'};
    978#else
    979 const static char spxname[20] = {'S', 'o', 'P', 'l', 'e', 'x', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '\0'};
    980#endif
    981const static char spxdesc[200] = {'L', 'i', 'n', 'e', 'a', 'r', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g',
    982 ' ', 's', 'o', 'l', 'v', 'e', 'r', ' ' , 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'e', 'd',
    983 ' ', 'a', 't', ' ', 'Z', 'u', 's', 'e', ' ', 'I', 'n', 's', 't', 'i', 't', 'u', 't', 'e',
    984 ' ', 'B', 'e', 'r', 'l', 'i', 'n', ' ', '(', 's', 'o', 'p', 'l', 'e', 'x', '.', 'z', 'i', 'b', '.', 'd', 'e', ')',
    985#ifdef SCIP_WITH_LPSCHECK
    986 ' ', '-', ' ', 'i', 'n', 'c', 'l', 'u', 'd', 'i', 'n', 'g', ' ', 'C','P','L', 'E', 'X',
    987 ' ', 'd', 'o', 'u', 'b', 'l', 'e', ' ', 'c', 'h', 'e', 'c', 'k',
    988#endif
    989 ' ', '[', 'G', 'i', 't', 'H', 'a', 's', 'h', ':', ' ',
    990 getGitHash()[0], getGitHash()[1], getGitHash()[2], getGitHash()[3],
    991 getGitHash()[4], getGitHash()[5], getGitHash()[6], getGitHash()[7],
    992 ']', '\0'};
    993
    994/**@name Miscellaneous Methods */
    995/**@{ */
    996
    997/** gets name and version of LP solver */
    999 void
    1000 )
    1001{
    1002 SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
    1003 return spxname;
    1004}
    1005
    1006/** gets description of LP solver (developer, webpage, ...) */
    1008 void
    1009 )
    1010{
    1011 return spxdesc;
    1012}
    1013
    1014/** gets pointer for LP solver - use only with great care */
    1016 SCIP_LPI* lpi /**< pointer to an LP interface structure */
    1017 )
    1018{
    1019 return (void*) lpi->spx;
    1020}
    1021
    1022/** pass integrality information about variables to the solver */
    1024 SCIP_LPI* lpi, /**< pointer to an LP interface structure */
    1025 int ncols, /**< length of integrality array */
    1026 int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
    1027 )
    1028{
    1029 assert( lpi != NULL );
    1030 assert( ncols >= 0 );
    1031 assert( ncols == 0 || intInfo != NULL );
    1032
    1033#if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
    1034 assert(ncols == lpi->spx->numColsReal() || (ncols == 0 && intInfo == NULL));
    1035 lpi->spx->setIntegralityInformation(ncols, intInfo);
    1036 return SCIP_OKAY;
    1037#else
    1038 SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
    1039 return SCIP_LPERROR;
    1040#endif
    1041}
    1042
    1043/** informs about availability of a primal simplex solving method */
    1045 void
    1046 )
    1047{
    1048 return TRUE;
    1049}
    1050
    1051/** informs about availability of a dual simplex solving method */
    1053 void
    1054 )
    1055{
    1056 return TRUE;
    1057}
    1058
    1059/** informs about availability of a barrier solving method */
    1061 void
    1062 )
    1063{
    1064 return FALSE;
    1065}
    1066
    1067/**@} */
    1068
    1069
    1070
    1071
    1072/*
    1073 * LPI Creation and Destruction Methods
    1074 */
    1075
    1076/**@name LPI Creation and Destruction Methods */
    1077/**@{ */
    1078
    1079/** creates an LP problem object */
    1081 SCIP_LPI** lpi, /**< pointer to an LP interface structure */
    1082 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
    1083 const char* name, /**< problem name */
    1084 SCIP_OBJSEN objsen /**< objective sense */
    1085 )
    1086{
    1087 assert(lpi != NULL);
    1088 assert(name != NULL);
    1089
    1090 /* create SoPlex object */
    1091 SCIP_ALLOC( BMSallocMemory(lpi) );
    1092
    1093 /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
    1094 (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
    1095 SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
    1096 (void) (*lpi)->spx->setIntParam(SoPlex::SYNCMODE, SoPlex::SYNCMODE_ONLYREAL);
    1097 (void) (*lpi)->spx->setIntParam(SoPlex::SOLVEMODE, SoPlex::SOLVEMODE_REAL);
    1098 (void) (*lpi)->spx->setIntParam(SoPlex::REPRESENTATION, SoPlex::REPRESENTATION_AUTO);
    1099
    1100 /* disable time-measurement for statistics */
    1101#if SOPLEX_APIVERSION >= 10
    1102 (void) (*lpi)->spx->setIntParam(SoPlex::STATTIMER, 0);
    1103#endif
    1104
    1105 (*lpi)->cstat = NULL;
    1106 (*lpi)->rstat = NULL;
    1107 (*lpi)->cstatsize = 0;
    1108 (*lpi)->rstatsize = 0;
    1109 (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
    1110 (*lpi)->conditionlimit = -1.0;
    1111 (*lpi)->checkcondition = FALSE;
    1112 (*lpi)->messagehdlr = messagehdlr;
    1113
    1114 invalidateSolution(*lpi);
    1115
    1116 /* set objective sense */
    1117 SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
    1118
    1119 /* set default pricing */
    1120 SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
    1121
    1122 {
    1123 (*lpi)->spx->setInterrupt(FALSE);
    1124 SPxOut::Verbosity verbosity = (*lpi)->spx->spxout.getVerbosity();
    1125 (*lpi)->spx->spxout.setVerbosity((SPxOut::Verbosity)((*lpi)->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
    1126 (*lpi)->spx->printVersion();
    1127 (*lpi)->spx->spxout.setVerbosity(verbosity);
    1128 }
    1129
    1130 return SCIP_OKAY;
    1131}
    1132
    1133/** deletes an LP problem object */
    1135 SCIP_LPI** lpi /**< pointer to an LP interface structure */
    1136 )
    1137{
    1138 assert(lpi != NULL);
    1139 assert(*lpi != NULL);
    1140 assert((*lpi)->spx != NULL);
    1141
    1142 /* free LP using destructor and free memory via blockmemshell */
    1143 (*lpi)->spx->~SPxSCIP();
    1144 BMSfreeMemory(&((*lpi)->spx));
    1145
    1146 /* free memory */
    1147 BMSfreeMemoryArrayNull(&(*lpi)->cstat);
    1148 BMSfreeMemoryArrayNull(&(*lpi)->rstat);
    1149 BMSfreeMemory(lpi);
    1150
    1151 return SCIP_OKAY;
    1152}
    1153
    1154/**@} */
    1155
    1156
    1157
    1158
    1159/*
    1160 * Modification Methods
    1161 */
    1162
    1163/**@name Modification Methods */
    1164/**@{ */
    1165
    1166/** copies LP data with column matrix into LP solver */
    1168 SCIP_LPI* lpi, /**< LP interface structure */
    1169 SCIP_OBJSEN objsen, /**< objective sense */
    1170 int ncols, /**< number of columns */
    1171 const SCIP_Real* obj, /**< objective function values of columns */
    1172 const SCIP_Real* lb, /**< lower bounds of columns */
    1173 const SCIP_Real* ub, /**< upper bounds of columns */
    1174 char** colnames, /**< column names, or NULL */
    1175 int nrows, /**< number of rows */
    1176 const SCIP_Real* lhs, /**< left hand sides of rows */
    1177 const SCIP_Real* rhs, /**< right hand sides of rows */
    1178 char** /*rownames*/, /**< row names, or NULL */
    1179 int nnonz, /**< number of nonzero elements in the constraint matrix */
    1180 const int* beg, /**< start index of each column in ind- and val-array */
    1181 const int* ind, /**< row indices of constraint matrix entries */
    1182 const SCIP_Real* val /**< values of constraint matrix entries */
    1183 )
    1184{
    1185#ifndef NDEBUG
    1186 {
    1187 int j;
    1188 for( j = 0; j < nnonz; j++ )
    1189 assert( val[j] != 0 );
    1190 }
    1191#endif
    1192
    1193 SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
    1194
    1195 assert(lpi != NULL);
    1196 assert(lpi->spx != NULL);
    1197 assert(lhs != NULL);
    1198 assert(rhs != NULL);
    1199 assert(obj != NULL);
    1200 assert(lb != NULL);
    1201 assert(ub != NULL);
    1202 assert(beg != NULL);
    1203 assert(ind != NULL);
    1204 assert(val != NULL);
    1205
    1206 invalidateSolution(lpi);
    1207 assert(lpi->spx->preStrongbranchingBasisFreed());
    1208
    1209 try
    1210 {
    1211 SPxSCIP* spx = lpi->spx;
    1212 LPRowSet rows(nrows);
    1213 DSVector emptyVector(0);
    1214 int i;
    1215
    1216 spx->clearLPReal();
    1217
    1218 /* set objective sense */
    1219 (void) spx->setIntParam(SoPlex::OBJSENSE, (objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE));
    1220
    1221 /* create empty rows with given sides */
    1222 for( i = 0; i < nrows; ++i )
    1223 rows.add(lhs[i], emptyVector, rhs[i]);
    1224 spx->addRowsReal(rows);
    1225
    1226 /* create column vectors with coefficients and bounds */
    1227 SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
    1228 }
    1229#ifndef NDEBUG
    1230 catch( const SPxException& x )
    1231 {
    1232 std::string s = x.what();
    1233 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1234#else
    1235 catch( const SPxException& )
    1236 {
    1237#endif
    1238 return SCIP_LPERROR;
    1239 }
    1240
    1241 return SCIP_OKAY;
    1242}
    1243
    1244/** adds columns to the LP */
    1246 SCIP_LPI* lpi, /**< LP interface structure */
    1247 int ncols, /**< number of columns to be added */
    1248 const SCIP_Real* obj, /**< objective function values of new columns */
    1249 const SCIP_Real* lb, /**< lower bounds of new columns */
    1250 const SCIP_Real* ub, /**< upper bounds of new columns */
    1251 char** /*colnames*/, /**< column names, or NULL */
    1252 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
    1253 const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
    1254 const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
    1255 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
    1256 )
    1257{
    1258 SCIPdebugMessage("calling SCIPlpiAddCols()\n");
    1259
    1260 assert(lpi != NULL);
    1261 assert(lpi->spx != NULL);
    1262 assert(obj != NULL);
    1263 assert(lb != NULL);
    1264 assert(ub != NULL);
    1265 assert(nnonz == 0 || beg != NULL);
    1266 assert(nnonz == 0 || ind != NULL);
    1267 assert(nnonz == 0 || val != NULL);
    1268 assert(nnonz >= 0);
    1269 assert(ncols >= 0);
    1270
    1271 invalidateSolution(lpi);
    1272
    1273 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1274
    1275#ifndef NDEBUG
    1276 if ( nnonz > 0 )
    1277 {
    1278 /* perform check that no new rows are added - this is likely to be a mistake */
    1279 int nrows = lpi->spx->numRowsReal();
    1280 for (int j = 0; j < nnonz; ++j)
    1281 {
    1282 assert( 0 <= ind[j] && ind[j] < nrows );
    1283 assert( val[j] != 0.0 );
    1284 }
    1285 }
    1286#endif
    1287
    1288 SPxSCIP* spx = lpi->spx;
    1289 try
    1290 {
    1291 LPColSet cols(ncols);
    1292 DSVector colVector(ncols);
    1293 int start;
    1294 int last;
    1295 int i;
    1296
    1297 /* create column vectors with coefficients and bounds */
    1298 for( i = 0; i < ncols; ++i )
    1299 {
    1300 colVector.clear();
    1301 if( nnonz > 0 )
    1302 {
    1303 start = beg[i];
    1304 last = (i == ncols-1 ? nnonz : beg[i+1]);
    1305 colVector.add( last-start, &ind[start], &val[start] );
    1306 }
    1307 cols.add(obj[i], lb[i], colVector, ub[i]);
    1308 }
    1309 spx->addColsReal(cols);
    1310 }
    1311#ifndef NDEBUG
    1312 catch( const SPxException& x )
    1313 {
    1314 std::string s = x.what();
    1315 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1316#else
    1317 catch( const SPxException& )
    1318 {
    1319#endif
    1320 return SCIP_LPERROR;
    1321 }
    1322
    1323 return SCIP_OKAY;
    1324}
    1325
    1326/** deletes all columns in the given range from LP */
    1328 SCIP_LPI* lpi, /**< LP interface structure */
    1329 int firstcol, /**< first column to be deleted */
    1330 int lastcol /**< last column to be deleted */
    1331 )
    1332{
    1333 assert(lpi != NULL);
    1334 assert(lpi->spx != NULL);
    1335 assert(firstcol >= 0);
    1336 assert(lastcol < lpi->spx->numColsReal());
    1337 assert(firstcol <= lastcol + 1);
    1338
    1339 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
    1340
    1341 // handle empty range
    1342 if( firstcol > lastcol )
    1343 return SCIP_OKAY;
    1344
    1345 invalidateSolution(lpi);
    1346
    1347 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1348
    1349 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRangeReal(firstcol, lastcol) );
    1350
    1351 return SCIP_OKAY;
    1352}
    1353
    1354/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
    1356 SCIP_LPI* lpi, /**< LP interface structure */
    1357 int* dstat /**< deletion status of columns
    1358 * input: 1 if column should be deleted, 0 if not
    1359 * output: new position of column, -1 if column was deleted */
    1360 )
    1361{
    1362 int ncols;
    1363 int i;
    1364
    1365 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
    1366
    1367 assert(lpi != NULL);
    1368 assert(lpi->spx != NULL);
    1369 assert(dstat != NULL);
    1370
    1371 invalidateSolution(lpi);
    1372
    1373 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1374
    1375 ncols = lpi->spx->numColsReal();
    1376
    1377 /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
    1378 for( i = 0; i < ncols; ++i )
    1379 dstat[i] *= -1;
    1380
    1381 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColsReal(dstat) );
    1382
    1383 return SCIP_OKAY;
    1384}
    1385
    1386/** adds rows to the LP */
    1388 SCIP_LPI* lpi, /**< LP interface structure */
    1389 int nrows, /**< number of rows to be added */
    1390 const SCIP_Real* lhs, /**< left hand sides of new rows */
    1391 const SCIP_Real* rhs, /**< right hand sides of new rows */
    1392 char** /*rownames*/, /**< row names, or NULL */
    1393 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
    1394 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
    1395 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
    1396 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
    1397 )
    1398{
    1399 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
    1400
    1401 assert(lpi != NULL);
    1402 assert(lpi->spx != NULL);
    1403 assert(lhs != NULL);
    1404 assert(rhs != NULL);
    1405 assert(nnonz == 0 || beg != NULL);
    1406 assert(nnonz == 0 || ind != NULL);
    1407 assert(nnonz == 0 || val != NULL);
    1408
    1409 invalidateSolution(lpi);
    1410
    1411 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1412
    1413#ifndef NDEBUG
    1414 if ( nnonz > 0 )
    1415 {
    1416 /* perform check that no new columns are added - this is likely to be a mistake */
    1417 int ncols = lpi->spx->numColsReal();
    1418 for (int j = 0; j < nnonz; ++j)
    1419 {
    1420 assert( val[j] != 0.0 );
    1421 assert( 0 <= ind[j] && ind[j] < ncols );
    1422 }
    1423 }
    1424#endif
    1425
    1426 try
    1427 {
    1428 SPxSCIP* spx = lpi->spx;
    1429 LPRowSet rows(nrows);
    1430 DSVector rowVector;
    1431 int start;
    1432 int last;
    1433 int i;
    1434
    1435 /* create row vectors with given sides */
    1436 for( i = 0; i < nrows; ++i )
    1437 {
    1438 rowVector.clear();
    1439 if( nnonz > 0 )
    1440 {
    1441 start = beg[i];
    1442 last = (i == nrows-1 ? nnonz : beg[i+1]);
    1443 rowVector.add( last-start, &ind[start], &val[start] );
    1444 }
    1445 rows.add(lhs[i], rowVector, rhs[i]);
    1446 }
    1447 spx->addRowsReal(rows);
    1448 }
    1449#ifndef NDEBUG
    1450 catch( const SPxException& x )
    1451 {
    1452 std::string s = x.what();
    1453 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1454#else
    1455 catch( const SPxException& )
    1456 {
    1457#endif
    1458 return SCIP_LPERROR;
    1459 }
    1460
    1461 return SCIP_OKAY;
    1462}
    1463
    1464/** deletes all rows in the given range from LP */
    1466 SCIP_LPI* lpi, /**< LP interface structure */
    1467 int firstrow, /**< first row to be deleted */
    1468 int lastrow /**< last row to be deleted */
    1469 )
    1470{
    1471 assert(lpi != NULL);
    1472 assert(lpi->spx != NULL);
    1473 assert(firstrow >= 0);
    1474 assert(lastrow < lpi->spx->numRowsReal());
    1475 assert(firstrow <= lastrow + 1);
    1476
    1477 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
    1478
    1479 // handle empty range
    1480 if( firstrow > lastrow )
    1481 return SCIP_OKAY;
    1482
    1483 invalidateSolution(lpi);
    1484
    1485 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1486
    1487 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRangeReal(firstrow, lastrow) );
    1488
    1489 return SCIP_OKAY;
    1490}
    1491
    1492/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
    1494 SCIP_LPI* lpi, /**< LP interface structure */
    1495 int* dstat /**< deletion status of rows
    1496 * input: 1 if row should be deleted, 0 if not
    1497 * output: new position of row, -1 if row was deleted */
    1498 )
    1499{
    1500 int nrows;
    1501 int i;
    1502
    1503 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
    1504
    1505 assert(lpi != NULL);
    1506 assert(lpi->spx != NULL);
    1507
    1508 invalidateSolution(lpi);
    1509
    1510 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1511
    1512 nrows = lpi->spx->numRowsReal();
    1513
    1514 /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
    1515 for( i = 0; i < nrows; ++i )
    1516 dstat[i] *= -1;
    1517
    1518 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowsReal(dstat) );
    1519
    1520 return SCIP_OKAY;
    1521}
    1522
    1523/** clears the whole LP */
    1525 SCIP_LPI* lpi /**< LP interface structure */
    1526 )
    1527{
    1528 SCIPdebugMessage("calling SCIPlpiClear()\n");
    1529
    1530 assert(lpi != NULL);
    1531 assert(lpi->spx != NULL);
    1532
    1533 invalidateSolution(lpi);
    1534
    1535 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1536 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clearLPReal() );
    1537
    1538 return SCIP_OKAY;
    1539}
    1540
    1541/** changes lower and upper bounds of columns */
    1543 SCIP_LPI* lpi, /**< LP interface structure */
    1544 int ncols, /**< number of columns to change bounds for */
    1545 const int* ind, /**< column indices or NULL if ncols is zero */
    1546 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
    1547 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
    1548 )
    1549{
    1550 int i;
    1551
    1552 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
    1553
    1554 assert(lpi != NULL);
    1555 assert(lpi->spx != NULL);
    1556 assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
    1557 if( ncols <= 0 )
    1558 return SCIP_OKAY;
    1559
    1560 invalidateSolution(lpi);
    1561
    1562 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1563
    1564 try
    1565 {
    1566 for( i = 0; i < ncols; ++i )
    1567 {
    1568 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
    1569
    1570 if ( SCIPlpiIsInfinity(lpi, lb[i]) )
    1571 {
    1572 SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
    1573 return SCIP_LPERROR;
    1574 }
    1575 if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
    1576 {
    1577 SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
    1578 return SCIP_LPERROR;
    1579 }
    1580
    1581 lpi->spx->changeBoundsReal(ind[i], lb[i], ub[i]);
    1582 assert(lpi->spx->lowerReal(ind[i]) <= lpi->spx->upperReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
    1583 }
    1584 }
    1585#ifndef NDEBUG
    1586 catch( const SPxException& x )
    1587 {
    1588 std::string s = x.what();
    1589 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1590#else
    1591 catch( const SPxException& )
    1592 {
    1593#endif
    1594 return SCIP_LPERROR;
    1595 }
    1596
    1597 return SCIP_OKAY;
    1598}
    1599
    1600/** changes left and right hand sides of rows */
    1602 SCIP_LPI* lpi, /**< LP interface structure */
    1603 int nrows, /**< number of rows to change sides for */
    1604 const int* ind, /**< row indices */
    1605 const SCIP_Real* lhs, /**< new values for left hand sides */
    1606 const SCIP_Real* rhs /**< new values for right hand sides */
    1607 )
    1608{
    1609 int i;
    1610
    1611 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
    1612
    1613 assert(lpi != NULL);
    1614 assert(lpi->spx != NULL);
    1615 assert(ind != NULL);
    1616 assert(lhs != NULL);
    1617 assert(rhs != NULL);
    1618 if( nrows <= 0 )
    1619 return SCIP_OKAY;
    1620
    1621 invalidateSolution(lpi);
    1622
    1623 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1624
    1625 try
    1626 {
    1627 for( i = 0; i < nrows; ++i )
    1628 {
    1629 assert(0 <= ind[i] && ind[i] < lpi->spx->numRowsReal());
    1630 lpi->spx->changeRangeReal(ind[i], lhs[i], rhs[i]);
    1631 assert(lpi->spx->lhsReal(ind[i]) <= lpi->spx->rhsReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
    1632 }
    1633 }
    1634#ifndef NDEBUG
    1635 catch( const SPxException& x )
    1636 {
    1637 std::string s = x.what();
    1638 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1639#else
    1640 catch( const SPxException& )
    1641 {
    1642#endif
    1643 return SCIP_LPERROR;
    1644 }
    1645
    1646 return SCIP_OKAY;
    1647}
    1648
    1649/** changes a single coefficient */
    1651 SCIP_LPI* lpi, /**< LP interface structure */
    1652 int row, /**< row number of coefficient to change */
    1653 int col, /**< column number of coefficient to change */
    1654 SCIP_Real newval /**< new value of coefficient */
    1655 )
    1656{
    1657 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
    1658
    1659 assert(lpi != NULL);
    1660 assert(lpi->spx != NULL);
    1661 assert(0 <= row && row < lpi->spx->numRowsReal());
    1662 assert(0 <= col && col < lpi->spx->numColsReal());
    1663
    1664 invalidateSolution(lpi);
    1665
    1666 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1667
    1668 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElementReal(row, col, newval) );
    1669
    1670 return SCIP_OKAY;
    1671}
    1672
    1673/** changes the objective sense */
    1675 SCIP_LPI* lpi, /**< LP interface structure */
    1676 SCIP_OBJSEN objsen /**< new objective sense */
    1677 )
    1678{
    1679 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
    1680
    1681 assert(lpi != NULL);
    1682 assert(lpi->spx != NULL);
    1683
    1684 invalidateSolution(lpi);
    1685
    1686 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1687
    1688 SOPLEX_TRY( lpi->messagehdlr, (void) lpi->spx->setIntParam(SoPlex::OBJSENSE, objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE ) );
    1689
    1690 return SCIP_OKAY;
    1691}
    1692
    1693/** changes objective values of columns in the LP */
    1695 SCIP_LPI* lpi, /**< LP interface structure */
    1696 int ncols, /**< number of columns to change objective value for */
    1697 const int* ind, /**< column indices to change objective value for */
    1698 const SCIP_Real* obj /**< new objective values for columns */
    1699 )
    1700{
    1701 int i;
    1702
    1703 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
    1704
    1705 assert(lpi != NULL);
    1706 assert(lpi->spx != NULL);
    1707 assert(ind != NULL);
    1708 assert(obj != NULL);
    1709
    1710 invalidateSolution(lpi);
    1711
    1712 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1713
    1714 try
    1715 {
    1716 for( i = 0; i < ncols; ++i )
    1717 {
    1718 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
    1719 lpi->spx->changeObjReal(ind[i], obj[i]);
    1720 }
    1721 }
    1722#ifndef NDEBUG
    1723 catch( const SPxException& x )
    1724 {
    1725 std::string s = x.what();
    1726 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1727#else
    1728 catch( const SPxException& )
    1729 {
    1730#endif
    1731 return SCIP_LPERROR;
    1732 }
    1733
    1734 return SCIP_OKAY;
    1735}
    1736
    1737/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
    1739 SCIP_LPI* lpi, /**< LP interface structure */
    1740 int row, /**< row number to scale */
    1741 SCIP_Real scaleval /**< scaling multiplier */
    1742 )
    1743{
    1744 SCIP_Real lhs;
    1745 SCIP_Real rhs;
    1746
    1747 SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
    1748
    1749 assert(lpi != NULL);
    1750 assert(lpi->spx != NULL);
    1751 assert(scaleval != 0.0);
    1752
    1753 try
    1754 {
    1755 invalidateSolution(lpi);
    1756
    1757 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1758
    1759 /* get the row vector and the row's sides */
    1760#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    1761 SVector rowvec = lpi->spx->rowVectorRealInternal(row);
    1762#else
    1763 SVector rowvec = lpi->spx->rowVectorReal(row);
    1764#endif
    1765 lhs = lpi->spx->lhsReal(row);
    1766 rhs = lpi->spx->rhsReal(row);
    1767
    1768 /* scale the row vector */
    1769 rowvec *= scaleval;
    1770
    1771 /* adjust the sides */
    1772 if( lhs > -lpi->spx->realParam(SoPlex::INFTY) )
    1773 lhs *= scaleval;
    1774 else if( scaleval < 0.0 )
    1775 lhs = lpi->spx->realParam(SoPlex::INFTY);
    1776 if( rhs < lpi->spx->realParam(SoPlex::INFTY) )
    1777 rhs *= scaleval;
    1778 else if( scaleval < 0.0 )
    1779 rhs = -lpi->spx->realParam(SoPlex::INFTY);
    1780 if( scaleval < 0.0 )
    1781 {
    1782 SCIP_Real oldlhs = lhs;
    1783 lhs = rhs;
    1784 rhs = oldlhs;
    1785 }
    1786
    1787 /* create the new row */
    1788 LPRow lprow(lhs, rowvec, rhs);
    1789
    1790 /* change the row in the LP */
    1791 lpi->spx->changeRowReal(row, lprow);
    1792 assert(lpi->spx->lhsReal(row) <= lpi->spx->rhsReal(row));
    1793 }
    1794#ifndef NDEBUG
    1795 catch( const SPxException& x )
    1796 {
    1797 std::string s = x.what();
    1798 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1799#else
    1800 catch( const SPxException& )
    1801 {
    1802#endif
    1803 return SCIP_LPERROR;
    1804 }
    1805
    1806 return SCIP_OKAY;
    1807}
    1808
    1809/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
    1810 * are divided by the scalar; for negative scalars, the column's bounds are switched
    1811 */
    1813 SCIP_LPI* lpi, /**< LP interface structure */
    1814 int col, /**< column number to scale */
    1815 SCIP_Real scaleval /**< scaling multiplier */
    1816 )
    1817{
    1818 SCIP_Real obj;
    1819 SCIP_Real lb;
    1820 SCIP_Real ub;
    1821
    1822 SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
    1823
    1824 assert(lpi != NULL);
    1825 assert(lpi->spx != NULL);
    1826 assert(scaleval != 0.0);
    1827
    1828 try
    1829 {
    1830 invalidateSolution(lpi);
    1831
    1832 assert( lpi->spx->preStrongbranchingBasisFreed() );
    1833
    1834 /* get the col vector and the col's bounds and objective value */
    1835#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    1836 SVector colvec = lpi->spx->colVectorRealInternal(col);
    1837#else
    1838 SVector colvec = lpi->spx->colVectorReal(col);
    1839#endif
    1840 obj = lpi->spx->objReal(col);
    1841 lb = lpi->spx->lowerReal(col);
    1842 ub = lpi->spx->upperReal(col);
    1843
    1844 /* scale the col vector */
    1845 colvec *= scaleval;
    1846
    1847 /* scale the objective value */
    1848 obj *= scaleval;
    1849
    1850 /* adjust the bounds */
    1851 if( lb > -lpi->spx->realParam(SoPlex::INFTY) )
    1852 lb /= scaleval;
    1853 else if( scaleval < 0.0 )
    1854 lb = lpi->spx->realParam(SoPlex::INFTY);
    1855 if( ub < lpi->spx->realParam(SoPlex::INFTY) )
    1856 ub /= scaleval;
    1857 else if( scaleval < 0.0 )
    1858 ub = -lpi->spx->realParam(SoPlex::INFTY);
    1859 if( scaleval < 0.0 )
    1860 {
    1861 SCIP_Real oldlb = lb;
    1862 lb = ub;
    1863 ub = oldlb;
    1864 }
    1865
    1866 /* create the new col (in LPCol's constructor, the upper bound is given first!) */
    1867 LPCol lpcol(obj, colvec, ub, lb);
    1868
    1869 /* change the col in the LP */
    1870 lpi->spx->changeColReal(col, lpcol);
    1871 assert(lpi->spx->lowerReal(col) <= lpi->spx->upperReal(col));
    1872 }
    1873#ifndef NDEBUG
    1874 catch( const SPxException& x )
    1875 {
    1876 std::string s = x.what();
    1877 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    1878#else
    1879 catch( const SPxException& )
    1880 {
    1881#endif
    1882 return SCIP_LPERROR;
    1883 }
    1884
    1885 return SCIP_OKAY;
    1886}
    1887
    1888/**@} */
    1889
    1890
    1891
    1892
    1893/*
    1894 * Data Accessing Methods
    1895 */
    1896
    1897/**@name Data Accessing Methods */
    1898/**@{ */
    1899
    1900/** gets the number of rows in the LP */
    1902 SCIP_LPI* lpi, /**< LP interface structure */
    1903 int* nrows /**< pointer to store the number of rows */
    1904 )
    1905{
    1906 SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
    1907
    1908 assert(lpi != NULL);
    1909 assert(lpi->spx != NULL);
    1910 assert(nrows != NULL);
    1911
    1912 *nrows = lpi->spx->numRowsReal();
    1913
    1914 return SCIP_OKAY;
    1915}
    1916
    1917/** gets the number of columns in the LP */
    1919 SCIP_LPI* lpi, /**< LP interface structure */
    1920 int* ncols /**< pointer to store the number of cols */
    1921 )
    1922{
    1923 SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
    1924
    1925 assert(lpi != NULL);
    1926 assert(lpi->spx != NULL);
    1927 assert(ncols != NULL);
    1928
    1929 *ncols = lpi->spx->numColsReal();
    1930
    1931 return SCIP_OKAY;
    1932}
    1933
    1934/** gets the number of nonzero elements in the LP constraint matrix */
    1936 SCIP_LPI* lpi, /**< LP interface structure */
    1937 int* nnonz /**< pointer to store the number of nonzeros */
    1938 )
    1939{
    1940 int i;
    1941
    1942 SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
    1943
    1944 assert(lpi != NULL);
    1945 assert(lpi->spx != NULL);
    1946 assert(nnonz != NULL);
    1947
    1948 /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
    1949 *nnonz = 0;
    1950 if( lpi->spx->numRowsReal() < lpi->spx->numColsReal() )
    1951 {
    1952 for( i = 0; i < lpi->spx->numRowsReal(); ++i )
    1953#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    1954 (*nnonz) += lpi->spx->rowVectorRealInternal(i).size();
    1955#else
    1956 (*nnonz) += lpi->spx->rowVectorReal(i).size();
    1957#endif
    1958 }
    1959 else
    1960 {
    1961 for( i = 0; i < lpi->spx->numColsReal(); ++i )
    1962#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    1963 (*nnonz) += lpi->spx->colVectorRealInternal(i).size();
    1964#else
    1965 (*nnonz) += lpi->spx->colVectorReal(i).size();
    1966#endif
    1967 }
    1968
    1969 return SCIP_OKAY;
    1970}
    1971
    1972/** gets columns from LP problem object; the arrays have to be large enough to store all values
    1973 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
    1974 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
    1975 */
    1977 SCIP_LPI* lpi, /**< LP interface structure */
    1978 int firstcol, /**< first column to get from LP */
    1979 int lastcol, /**< last column to get from LP */
    1980 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
    1981 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
    1982 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
    1983 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
    1984 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
    1985 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
    1986 )
    1987{
    1988 int i;
    1989 int j;
    1990
    1991 assert(lpi != NULL);
    1992 assert(lpi->spx != NULL);
    1993 assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
    1994 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
    1995 assert(firstcol >= 0);
    1996 assert(lastcol < lpi->spx->numColsReal());
    1997 assert(firstcol <= lastcol + 1);
    1998
    1999 SCIPdebugMessage("calling SCIPlpiGetCols()\n");
    2000
    2001 if( lb != NULL )
    2002 {
    2003#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    2004 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
    2005 {
    2006 DVector lbvec(lpi->spx->numColsReal());
    2007 DVector ubvec(lpi->spx->numColsReal());
    2008 lpi->spx->getLowerReal(lbvec);
    2009 lpi->spx->getUpperReal(ubvec);
    2010 for( i = firstcol; i <= lastcol; ++i )
    2011 {
    2012 lb[i-firstcol] = lbvec[i];
    2013 ub[i-firstcol] = ubvec[i];
    2014 }
    2015 }
    2016 else
    2017 {
    2018 const Vector& lbvec = lpi->spx->lowerRealInternal();
    2019 const Vector& ubvec = lpi->spx->upperRealInternal();
    2020 for( i = firstcol; i <= lastcol; ++i )
    2021 {
    2022 lb[i-firstcol] = lbvec[i];
    2023 ub[i-firstcol] = ubvec[i];
    2024 }
    2025 }
    2026#else
    2027 const Vector& lbvec = lpi->spx->lowerReal();
    2028 const Vector& ubvec = lpi->spx->upperReal();
    2029
    2030 for( i = firstcol; i <= lastcol; ++i )
    2031 {
    2032 lb[i-firstcol] = lbvec[i];
    2033 ub[i-firstcol] = ubvec[i];
    2034 }
    2035#endif
    2036 }
    2037
    2038 if( nnonz != NULL )
    2039 {
    2040 *nnonz = 0;
    2041 for( i = firstcol; i <= lastcol; ++i )
    2042 {
    2043 beg[i-firstcol] = *nnonz;
    2044
    2045#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    2046 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
    2047 {
    2048 DSVector cvec;
    2049 lpi->spx->getColVectorReal(i, cvec);
    2050 for( j = 0; j < cvec.size(); ++j )
    2051 {
    2052 ind[*nnonz] = cvec.index(j);
    2053 val[*nnonz] = cvec.value(j);
    2054 (*nnonz)++;
    2055 }
    2056 }
    2057 else
    2058 {
    2059 const SVector& cvec = lpi->spx->colVectorRealInternal(i);
    2060 for( j = 0; j < cvec.size(); ++j )
    2061 {
    2062 ind[*nnonz] = cvec.index(j);
    2063 val[*nnonz] = cvec.value(j);
    2064 (*nnonz)++;
    2065 }
    2066 }
    2067#else
    2068 const SVector& cvec = lpi->spx->colVectorReal(i);
    2069 for( j = 0; j < cvec.size(); ++j )
    2070 {
    2071 ind[*nnonz] = cvec.index(j);
    2072 val[*nnonz] = cvec.value(j);
    2073 (*nnonz)++;
    2074 }
    2075#endif
    2076 }
    2077 }
    2078
    2079 return SCIP_OKAY;
    2080}
    2081
    2082/** gets rows from LP problem object; the arrays have to be large enough to store all values.
    2083 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
    2084 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
    2085 */
    2087 SCIP_LPI* lpi, /**< LP interface structure */
    2088 int firstrow, /**< first row to get from LP */
    2089 int lastrow, /**< last row to get from LP */
    2090 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
    2091 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
    2092 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
    2093 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
    2094 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
    2095 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
    2096 )
    2097{
    2098 int i;
    2099 int j;
    2100
    2101 assert(lpi != NULL);
    2102 assert(lpi->spx != NULL);
    2103 assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
    2104 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
    2105 assert(firstrow >= 0);
    2106 assert(lastrow < lpi->spx->numRowsReal());
    2107 assert(firstrow <= lastrow + 1);
    2108
    2109 SCIPdebugMessage("calling SCIPlpiGetRows()\n");
    2110
    2111 if( lhs != NULL )
    2112 {
    2113#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    2114 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
    2115 {
    2116 DVector lhsvec(lpi->spx->numRowsReal());
    2117 DVector rhsvec(lpi->spx->numRowsReal());
    2118 lpi->spx->getLhsReal(lhsvec);
    2119 lpi->spx->getRhsReal(rhsvec);
    2120 for( i = firstrow; i <= lastrow; ++i )
    2121 {
    2122 lhs[i-firstrow] = lhsvec[i];
    2123 rhs[i-firstrow] = rhsvec[i];
    2124 }
    2125 }
    2126 else
    2127 {
    2128 const Vector& lhsvec = lpi->spx->lhsRealInternal();
    2129 const Vector& rhsvec = lpi->spx->rhsRealInternal();
    2130 for( i = firstrow; i <= lastrow; ++i )
    2131 {
    2132 lhs[i-firstrow] = lhsvec[i];
    2133 rhs[i-firstrow] = rhsvec[i];
    2134 }
    2135 }
    2136#else
    2137 const Vector& lhsvec = lpi->spx->lhsReal();
    2138 const Vector& rhsvec = lpi->spx->rhsReal();
    2139 for( i = firstrow; i <= lastrow; ++i )
    2140 {
    2141 lhs[i-firstrow] = lhsvec[i];
    2142 rhs[i-firstrow] = rhsvec[i];
    2143 }
    2144#endif
    2145 }
    2146
    2147 if( nnonz != NULL )
    2148 {
    2149 *nnonz = 0;
    2150 for( i = firstrow; i <= lastrow; ++i )
    2151 {
    2152 beg[i-firstrow] = *nnonz;
    2153
    2154#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    2155 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
    2156 {
    2157 DSVector rvec;
    2158 lpi->spx->getRowVectorReal(i, rvec);
    2159 for( j = 0; j < rvec.size(); ++j )
    2160 {
    2161 ind[*nnonz] = rvec.index(j);
    2162 val[*nnonz] = rvec.value(j);
    2163 (*nnonz)++;
    2164 }
    2165 }
    2166 else
    2167 {
    2168 const SVector& rvec = lpi->spx->rowVectorRealInternal(i);
    2169 for( j = 0; j < rvec.size(); ++j )
    2170 {
    2171 ind[*nnonz] = rvec.index(j);
    2172 val[*nnonz] = rvec.value(j);
    2173 (*nnonz)++;
    2174 }
    2175 }
    2176#else
    2177 const SVector& rvec = lpi->spx->rowVectorReal(i);
    2178 for( j = 0; j < rvec.size(); ++j )
    2179 {
    2180 ind[*nnonz] = rvec.index(j);
    2181 val[*nnonz] = rvec.value(j);
    2182 (*nnonz)++;
    2183 }
    2184#endif
    2185 }
    2186 }
    2187
    2188 return SCIP_OKAY;
    2189}
    2190
    2191/** gets column names */
    2193 SCIP_LPI* lpi, /**< LP interface structure */
    2194 int firstcol, /**< first column to get name from LP */
    2195 int lastcol, /**< last column to get name from LP */
    2196 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
    2197 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
    2198 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
    2199 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
    2200 )
    2201{
    2202 assert(lpi != NULL);
    2203 assert(lpi->spx != NULL);
    2204 assert(colnames != NULL || namestoragesize == 0);
    2205 assert(namestorage != NULL || namestoragesize == 0);
    2206 assert(namestoragesize >= 0);
    2207 assert(storageleft != NULL);
    2208 assert(firstcol >= 0);
    2209 assert(lastcol < lpi->spx->numColsReal());
    2210 assert(firstcol <= lastcol + 1);
    2211
    2212 SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
    2213
    2214// lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
    2215
    2216 return SCIP_OKAY;
    2217}
    2218
    2219/** gets row names */
    2221 SCIP_LPI* lpi, /**< LP interface structure */
    2222 int firstrow, /**< first row to get name from LP */
    2223 int lastrow, /**< last row to get name from LP */
    2224 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
    2225 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
    2226 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
    2227 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
    2228 )
    2229{
    2230 assert(lpi != NULL);
    2231 assert(lpi->spx != NULL);
    2232 assert(rownames != NULL || namestoragesize == 0);
    2233 assert(namestorage != NULL || namestoragesize == 0);
    2234 assert(namestoragesize >= 0);
    2235 assert(storageleft != NULL);
    2236 assert(firstrow >= 0);
    2237 assert(lastrow < lpi->spx->numRowsReal());
    2238 assert(firstrow <= lastrow + 1);
    2239
    2240 SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
    2241
    2242// lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
    2243
    2244 return SCIP_OKAY;
    2245}
    2246
    2247/** gets objective sense of the LP */
    2249 SCIP_LPI* lpi, /**< LP interface structure */
    2250 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
    2251 )
    2252{
    2253 SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
    2254
    2255 assert(lpi != NULL);
    2256 assert(lpi->spx != NULL);
    2257 assert(objsen != NULL);
    2258
    2259 *objsen = (lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
    2260
    2261 return SCIP_OKAY;
    2262}
    2263
    2264/** gets objective coefficients from LP problem object */
    2266 SCIP_LPI* lpi, /**< LP interface structure */
    2267 int firstcol, /**< first column to get objective coefficient for */
    2268 int lastcol, /**< last column to get objective coefficient for */
    2269 SCIP_Real* vals /**< array to store objective coefficients */
    2270 )
    2271{
    2272 int i;
    2273
    2274 assert(lpi != NULL);
    2275 assert(lpi->spx != NULL);
    2276 assert(vals != NULL);
    2277 assert(firstcol >= 0);
    2278 assert(lastcol < lpi->spx->numColsReal());
    2279 assert(firstcol <= lastcol + 1);
    2280
    2281 SCIPdebugMessage("calling SCIPlpiGetObj()\n");
    2282
    2283 for( i = firstcol; i <= lastcol; ++i )
    2284 vals[i-firstcol] = lpi->spx->objReal(i);
    2285
    2286 return SCIP_OKAY;
    2287}
    2288
    2289/** gets current bounds from LP problem object */
    2291 SCIP_LPI* lpi, /**< LP interface structure */
    2292 int firstcol, /**< first column to get objective value for */
    2293 int lastcol, /**< last column to get objective value for */
    2294 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
    2295 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
    2296 )
    2297{
    2298 int i;
    2299
    2300 assert(lpi != NULL);
    2301 assert(lpi->spx != NULL);
    2302 assert(firstcol >= 0);
    2303 assert(lastcol < lpi->spx->numColsReal());
    2304 assert(firstcol <= lastcol + 1);
    2305
    2306 SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
    2307
    2308 for( i = firstcol; i <= lastcol; ++i )
    2309 {
    2310 if( lbs != NULL )
    2311 lbs[i-firstcol] = lpi->spx->lowerReal(i);
    2312 if( ubs != NULL )
    2313 ubs[i-firstcol] = lpi->spx->upperReal(i);
    2314 }
    2315
    2316 return SCIP_OKAY;
    2317}
    2318
    2319/** gets current row sides from LP problem object */
    2321 SCIP_LPI* lpi, /**< LP interface structure */
    2322 int firstrow, /**< first row to get sides for */
    2323 int lastrow, /**< last row to get sides for */
    2324 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
    2325 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
    2326 )
    2327{
    2328 int i;
    2329
    2330 assert(lpi != NULL);
    2331 assert(lpi->spx != NULL);
    2332 assert(firstrow >= 0);
    2333 assert(lastrow < lpi->spx->numRowsReal());
    2334 assert(firstrow <= lastrow + 1);
    2335
    2336 SCIPdebugMessage("calling SCIPlpiGetSides()\n");
    2337
    2338 for( i = firstrow; i <= lastrow; ++i )
    2339 {
    2340 if( lhss != NULL )
    2341 lhss[i-firstrow] = lpi->spx->lhsReal(i);
    2342 if( rhss != NULL )
    2343 rhss[i-firstrow] = lpi->spx->rhsReal(i);
    2344 }
    2345
    2346 return SCIP_OKAY;
    2347}
    2348
    2349/** gets a single coefficient */
    2351 SCIP_LPI* lpi, /**< LP interface structure */
    2352 int row, /**< row number of coefficient */
    2353 int col, /**< column number of coefficient */
    2354 SCIP_Real* val /**< pointer to store the value of the coefficient */
    2355 )
    2356{
    2357 SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
    2358
    2359 assert(lpi != NULL);
    2360 assert(lpi->spx != NULL);
    2361 assert(0 <= col && col < lpi->spx->numColsReal());
    2362 assert(0 <= row && row < lpi->spx->numRowsReal());
    2363 assert(val != NULL);
    2364
    2365#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    2366 *val = lpi->spx->coefReal(row, col);
    2367#else
    2368 *val = lpi->spx->colVectorReal(col)[row];
    2369#endif
    2370
    2371 return SCIP_OKAY;
    2372}
    2373
    2374/**@} */
    2375
    2376
    2377
    2378
    2379/*
    2380 * Solving Methods
    2381 */
    2382
    2383/**@name Solving Methods */
    2384/**@{ */
    2385
    2386/** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
    2387static
    2389 SCIP_LPI* lpi /**< LP interface structure */
    2390 )
    2391{
    2392 assert( lpi != NULL );
    2393 assert( lpi->spx != NULL );
    2394
    2395 SPxOut::Verbosity verbosity;
    2396 /* store and set verbosity */
    2397 verbosity = lpi->spx->spxout.getVerbosity();
    2398 lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
    2399
    2400 SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows\n", lpi->spx->numColsReal(), lpi->spx->numRowsReal());
    2401
    2402 invalidateSolution(lpi);
    2403
    2404 assert( lpi->spx->preStrongbranchingBasisFreed() );
    2405
    2406#ifdef SCIP_WITH_LPSCHECK
    2407 lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
    2408#endif
    2409
    2410 /* delete starting basis if solving from scratch */
    2411 if( lpi->spx->getFromScratch() )
    2412 {
    2413 try
    2414 {
    2415 lpi->spx->clearBasis();
    2416 }
    2417#ifndef NDEBUG
    2418 catch(const SPxException& x)
    2419 {
    2420 std::string s = x.what();
    2421 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    2422#else
    2423 catch(const SPxException&)
    2424 {
    2425#endif
    2426 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
    2427 return SCIP_LPERROR;
    2428 }
    2429 }
    2430 assert(!lpi->spx->getFromScratch() || lpi->spx->status() == SPxSolver::NO_PROBLEM);
    2431
    2432 SPxSolver::Status status = lpi->spx->doSolve();
    2433 SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->status(), lpi->spx->basisStatus());
    2434 lpi->solved = TRUE;
    2435
    2436 /* restore verbosity */
    2437 lpi->spx->spxout.setVerbosity(verbosity);
    2438
    2439 switch( status )
    2440 {
    2441 case SPxSolver::ABORT_TIME:
    2442 case SPxSolver::ABORT_ITER:
    2443 case SPxSolver::ABORT_VALUE:
    2444 case SPxSolver::SINGULAR:
    2445 case SPxSolver::REGULAR:
    2446 case SPxSolver::UNKNOWN:
    2447 case SPxSolver::OPTIMAL:
    2448#if SOPLEX_APIVERSION >= 3
    2449 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
    2450#endif
    2451 case SPxSolver::UNBOUNDED:
    2452 case SPxSolver::INFEASIBLE:
    2453 return SCIP_OKAY;
    2454 default:
    2455 return SCIP_LPERROR;
    2456 } /*lint !e788*/
    2457}
    2458
    2459/** calls primal simplex to solve the LP */
    2461 SCIP_LPI* lpi /**< LP interface structure */
    2462 )
    2463{
    2464 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
    2465
    2466 assert(lpi != NULL);
    2467 assert(lpi->spx != NULL);
    2468
    2469 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_PRIMAL);
    2470 return spxSolve(lpi);
    2471}
    2472
    2473/** calls dual simplex to solve the LP */
    2475 SCIP_LPI* lpi /**< LP interface structure */
    2476 )
    2477{
    2478 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
    2479
    2480 assert(lpi != NULL);
    2481 assert(lpi->spx != NULL);
    2482
    2483 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
    2484 return spxSolve(lpi);
    2485}
    2486
    2487/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
    2489 SCIP_LPI* lpi, /**< LP interface structure */
    2490 SCIP_Bool crossover /**< perform crossover */
    2491 )
    2492{ /*lint --e{715}*/
    2493 assert(lpi != NULL);
    2494 assert(lpi->spx != NULL);
    2495
    2496 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
    2497
    2498 /* Since SoPlex does not support barrier we switch to DUAL */
    2499 return SCIPlpiSolveDual(lpi);
    2500}
    2501
    2502/** start strong branching - call before any strongbranching */
    2504 SCIP_LPI* lpi /**< LP interface structure */
    2505 )
    2506{
    2507 assert(lpi != NULL);
    2508 assert(lpi->spx != NULL);
    2509
    2510 assert( lpi->spx->preStrongbranchingBasisFreed() );
    2511 lpi->spx->savePreStrongbranchingBasis();
    2512
    2513 return SCIP_OKAY;
    2514}
    2515
    2516/** end strong branching - call after any strongbranching */
    2518 SCIP_LPI* lpi /**< LP interface structure */
    2519 )
    2520{
    2521 assert(lpi != NULL);
    2522 assert(lpi->spx != NULL);
    2523
    2524 assert( ! lpi->spx->preStrongbranchingBasisFreed() );
    2525 lpi->spx->restorePreStrongbranchingBasis();
    2526 lpi->spx->freePreStrongbranchingBasis();
    2527
    2528 return SCIP_OKAY;
    2529}
    2530
    2531/** performs strong branching iterations on one arbitrary candidate */
    2532static
    2534 SCIP_LPI* lpi, /**< LP interface structure */
    2535 int col, /**< column to apply strong branching on */
    2536 SCIP_Real psol, /**< current primal solution value of column */
    2537 int itlim, /**< iteration limit for strong branchings */
    2538 SCIP_Real* down, /**< stores dual bound after branching column down */
    2539 SCIP_Real* up, /**< stores dual bound after branching column up */
    2540 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
    2541 * otherwise, it can only be used as an estimate value */
    2542 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
    2543 * otherwise, it can only be used as an estimate value */
    2544 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    2545 )
    2546{
    2547 assert(lpi != NULL);
    2548 assert(lpi->spx != NULL);
    2549
    2550 SPxSCIP* spx;
    2551 SPxSolver::Status status;
    2552 SCIP_Real oldlb;
    2553 SCIP_Real oldub;
    2554 SCIP_Real newlb;
    2555 SCIP_Real newub;
    2556 bool fromparentbasis;
    2557 bool error;
    2558 int oldItlim;
    2559 SPxOut::Verbosity verbosity;
    2560
    2561 /* store and set verbosity */
    2562 verbosity = lpi->spx->spxout.getVerbosity();
    2563 lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
    2564
    2565 SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
    2566
    2567 assert(lpi != NULL);
    2568 assert(lpi->spx != NULL);
    2569 /* assert(down != NULL);
    2570 * assert(up != NULL); temporary hack for cloud branching */
    2571 assert(downvalid != NULL);
    2572 assert(upvalid != NULL);
    2573
    2574 spx = lpi->spx;
    2575#ifndef STRONGBRANCH_RESTOREBASIS
    2576 fromparentbasis = false;
    2577#endif
    2578 error = false;
    2579 oldItlim = spx->intParam(SoPlex::ITERLIMIT);
    2580
    2581 /* get current bounds of column */
    2582 oldlb = spx->lowerReal(col);
    2583 oldub = spx->upperReal(col);
    2584
    2585 *downvalid = FALSE;
    2586 *upvalid = FALSE;
    2587
    2588 if( iter != NULL )
    2589 *iter = 0;
    2590
    2591 /* set the algorithm type to use dual simplex */
    2592 (void) spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
    2593
    2594 /* down branch */
    2595 newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
    2596 if( newub >= oldlb - 0.5 && down != NULL )
    2597 {
    2598 SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
    2599
    2600 spx->changeUpperReal(col, newub);
    2601 assert(spx->lowerReal(col) <= spx->upperReal(col));
    2602
    2603 (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
    2604 do
    2605 {
    2606#ifndef STRONGBRANCH_RESTOREBASIS
    2607 SCIP_Bool repeatstrongbranching;
    2608#endif
    2609#ifdef SCIP_WITH_LPSCHECK
    2610 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
    2611#endif
    2612#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    2613#if SOPLEX_APIVERSION > 11
    2614 status = spx->optimize(spx->getInterrupt());
    2615#else
    2616 status = spx->optimize();
    2617#endif
    2618#else
    2619 status = spx->solve();
    2620#endif
    2621 SCIPdebugMessage(" --> Terminate with status %d\n", status);
    2622 switch( status )
    2623 {
    2624 case SPxSolver::OPTIMAL:
    2625 *down = spx->objValueReal();
    2626 *downvalid = TRUE;
    2627 SCIPdebugMessage(" --> Terminate with value %f\n", *down);
    2628 break;
    2629 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
    2630 case SPxSolver::ABORT_ITER:
    2631 case SPxSolver::ABORT_CYCLING:
    2632#if SOPLEX_APIVERSION >= 3
    2633 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
    2634#endif
    2635 *down = spx->objValueReal();
    2636 break;
    2637 case SPxSolver::ABORT_VALUE:
    2638 case SPxSolver::INFEASIBLE:
    2639 *down = spx->getObjLimit();
    2640 *downvalid = TRUE;
    2641 break;
    2642 default:
    2643 error = true;
    2644 break;
    2645 } /*lint !e788*/
    2646 if( iter != NULL )
    2647 (*iter) += spx->numIterations();
    2648
    2649#ifdef STRONGBRANCH_RESTOREBASIS
    2650 /* we restore the pre-strong-branching basis by default (and don't solve again) */
    2651 assert( ! spx->preStrongbranchingBasisFreed() );
    2652 spx->restorePreStrongbranchingBasis();
    2653 fromparentbasis = false;
    2654#else
    2655 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
    2656 * pre-strong-branching basis and try again with reduced iteration limit */
    2657#if SOPLEX_APIVERSION >= 3
    2658 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
    2659 || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
    2660#else
    2661 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
    2662 && !fromparentbasis && spx->numIterations() < itlim);
    2663#endif
    2664 if( repeatstrongbranching )
    2665 {
    2666 SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n",
    2667 itlim - spx->numIterations());
    2668 spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
    2669 spx->restorePreStrongbranchingBasis();
    2670 fromparentbasis = true;
    2671 error = false;
    2672 }
    2673 /* otherwise don't solve again */
    2674 else
    2675 fromparentbasis = false;
    2676#endif
    2677 }
    2678 while( fromparentbasis );
    2679
    2680 spx->changeUpperReal(col, oldub);
    2681 assert(spx->lowerReal(col) <= spx->upperReal(col));
    2682 }
    2683 else if( down != NULL )
    2684 {
    2685 *down = spx->getObjLimit();
    2686 *downvalid = TRUE;
    2687 }
    2688 else
    2689 *downvalid = TRUE;
    2690
    2691 /* up branch */
    2692 if( !error )
    2693 {
    2694 newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
    2695 if( newlb <= oldub + 0.5 && up != NULL )
    2696 {
    2697 SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
    2698
    2699 spx->changeLowerReal(col, newlb);
    2700 assert(spx->lowerReal(col) <= spx->upperReal(col));
    2701
    2702 (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
    2703 do
    2704 {
    2705#ifndef STRONGBRANCH_RESTOREBASIS
    2706 SCIP_Bool repeatstrongbranching;
    2707#endif
    2708#ifdef SCIP_WITH_LPSCHECK
    2709 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
    2710#endif
    2711#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    2712#if SOPLEX_APIVERSION > 11
    2713 status = spx->optimize(spx->getInterrupt());
    2714#else
    2715 status = spx->optimize();
    2716#endif
    2717#else
    2718 status = spx->solve();
    2719#endif
    2720 SCIPdebugMessage(" --> Terminate with status %d\n", status);
    2721 switch( status )
    2722 {
    2723 case SPxSolver::OPTIMAL:
    2724 *up = spx->objValueReal();
    2725 *upvalid = TRUE;
    2726 SCIPdebugMessage(" --> Terminate with value %f\n", spx->objValueReal());
    2727 break;
    2728 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
    2729 case SPxSolver::ABORT_ITER:
    2730 case SPxSolver::ABORT_CYCLING:
    2731#if SOPLEX_APIVERSION >= 3
    2732 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
    2733#endif
    2734 *up = spx->objValueReal();
    2735 break;
    2736 case SPxSolver::ABORT_VALUE:
    2737 case SPxSolver::INFEASIBLE:
    2738 *up = spx->getObjLimit();
    2739 *upvalid = TRUE;
    2740 break;
    2741 default:
    2742 error = true;
    2743 break;
    2744 } /*lint !e788*/
    2745 if( iter != NULL )
    2746 (*iter) += spx->numIterations();
    2747
    2748#ifdef STRONGBRANCH_RESTOREBASIS
    2749 /* we restore the pre-strong-branching basis by default (and don't solve again) */
    2750 assert( ! spx->preStrongbranchingBasisFreed() );
    2751 spx->restorePreStrongbranchingBasis();
    2752 fromparentbasis = false;
    2753#else
    2754 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
    2755 * pre-strong-branching basis and try again with reduced iteration limit */
    2756#if SOPLEX_APIVERSION >= 3
    2757 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
    2758 || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
    2759#else
    2760 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
    2761 && !fromparentbasis && spx->numIterations() < itlim);
    2762#endif
    2763 if( repeatstrongbranching )
    2764 {
    2765 SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->numIterations());
    2766 spx->restorePreStrongbranchingBasis();
    2767 spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
    2768 error = false;
    2769 fromparentbasis = true;
    2770 }
    2771 /* otherwise don't solve again */
    2772 else
    2773 fromparentbasis = false;
    2774#endif
    2775 }
    2776 while( fromparentbasis );
    2777
    2778 spx->changeLowerReal(col, oldlb);
    2779 assert(spx->lowerReal(col) <= spx->upperReal(col));
    2780 }
    2781 else if( up != NULL )
    2782 {
    2783 *up = spx->getObjLimit();
    2784 *upvalid = TRUE;
    2785 }
    2786 else
    2787 *upvalid = TRUE;
    2788 }
    2789
    2790 /* reset old iteration limit */
    2791 (void) spx->setIntParam(SoPlex::ITERLIMIT, oldItlim);
    2792
    2793 /* restore verbosity */
    2794 lpi->spx->spxout.setVerbosity(verbosity);
    2795
    2796 if( error )
    2797 {
    2798 SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status)); /*lint !e644*/
    2799 return SCIP_LPERROR;
    2800 }
    2801
    2802 return SCIP_OKAY;
    2803}
    2804
    2805/** performs strong branching iterations on one @b fractional candidate */
    2807 SCIP_LPI* lpi, /**< LP interface structure */
    2808 int col, /**< column to apply strong branching on */
    2809 SCIP_Real psol, /**< fractional current primal solution value of column */
    2810 int itlim, /**< iteration limit for strong branchings */
    2811 SCIP_Real* down, /**< stores dual bound after branching column down */
    2812 SCIP_Real* up, /**< stores dual bound after branching column up */
    2813 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
    2814 * otherwise, it can only be used as an estimate value */
    2815 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
    2816 * otherwise, it can only be used as an estimate value */
    2817 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    2818 )
    2819{
    2820 SCIP_RETCODE retcode;
    2821
    2822 /* pass call on to lpiStrongbranch() */
    2823 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
    2824
    2825 /* pass SCIP_LPERROR to SCIP without a back trace */
    2826 if( retcode == SCIP_LPERROR )
    2827 return SCIP_LPERROR;
    2828
    2829 /* evaluate retcode */
    2830 SCIP_CALL( retcode );
    2831
    2832 return SCIP_OKAY;
    2833}
    2834
    2835/** performs strong branching iterations on given @b fractional candidates */
    2837 SCIP_LPI* lpi, /**< LP interface structure */
    2838 int* cols, /**< columns to apply strong branching on */
    2839 int ncols, /**< number of columns */
    2840 SCIP_Real* psols, /**< fractional current primal solution values of columns */
    2841 int itlim, /**< iteration limit for strong branchings */
    2842 SCIP_Real* down, /**< stores dual bounds after branching columns down */
    2843 SCIP_Real* up, /**< stores dual bounds after branching columns up */
    2844 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
    2845 * otherwise, they can only be used as an estimate values */
    2846 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
    2847 * otherwise, they can only be used as an estimate values */
    2848 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    2849 )
    2850{
    2851 SCIP_RETCODE retcode;
    2852
    2853 assert( cols != NULL );
    2854 assert( psols != NULL );
    2855 assert( down != NULL );
    2856 assert( up != NULL );
    2857 assert( downvalid != NULL );
    2858 assert( upvalid != NULL );
    2859 assert( down != NULL );
    2860
    2861 if ( iter != NULL )
    2862 *iter = 0;
    2863
    2864 for (int j = 0; j < ncols; ++j)
    2865 {
    2866 /* pass call on to lpiStrongbranch() */
    2867 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
    2868
    2869 /* pass SCIP_LPERROR to SCIP without a back trace */
    2870 if( retcode == SCIP_LPERROR )
    2871 return SCIP_LPERROR;
    2872
    2873 /* evaluate retcode */
    2874 SCIP_CALL( retcode );
    2875 }
    2876 return SCIP_OKAY;
    2877}
    2878
    2879/** performs strong branching iterations on one candidate with @b integral value */
    2881 SCIP_LPI* lpi, /**< LP interface structure */
    2882 int col, /**< column to apply strong branching on */
    2883 SCIP_Real psol, /**< current integral primal solution value of column */
    2884 int itlim, /**< iteration limit for strong branchings */
    2885 SCIP_Real* down, /**< stores dual bound after branching column down */
    2886 SCIP_Real* up, /**< stores dual bound after branching column up */
    2887 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
    2888 * otherwise, it can only be used as an estimate value */
    2889 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
    2890 * otherwise, it can only be used as an estimate value */
    2891 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    2892 )
    2893{
    2894 SCIP_RETCODE retcode;
    2895
    2896 /* pass call on to lpiStrongbranch() */
    2897 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
    2898
    2899 /* pass SCIP_LPERROR to SCIP without a back trace */
    2900 if( retcode == SCIP_LPERROR )
    2901 return SCIP_LPERROR;
    2902
    2903 /* evaluate retcode */
    2904 SCIP_CALL( retcode );
    2905
    2906 return SCIP_OKAY;
    2907}
    2908
    2909/** performs strong branching iterations on given candidates with @b integral values */
    2911 SCIP_LPI* lpi, /**< LP interface structure */
    2912 int* cols, /**< columns to apply strong branching on */
    2913 int ncols, /**< number of columns */
    2914 SCIP_Real* psols, /**< current integral primal solution values of columns */
    2915 int itlim, /**< iteration limit for strong branchings */
    2916 SCIP_Real* down, /**< stores dual bounds after branching columns down */
    2917 SCIP_Real* up, /**< stores dual bounds after branching columns up */
    2918 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
    2919 * otherwise, they can only be used as an estimate values */
    2920 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
    2921 * otherwise, they can only be used as an estimate values */
    2922 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    2923 )
    2924{
    2925 SCIP_RETCODE retcode;
    2926
    2927 assert( cols != NULL );
    2928 assert( psols != NULL );
    2929 assert( down != NULL );
    2930 assert( up != NULL );
    2931 assert( downvalid != NULL );
    2932 assert( upvalid != NULL );
    2933 assert( down != NULL );
    2934
    2935 if ( iter != NULL )
    2936 *iter = 0;
    2937
    2938 for (int j = 0; j < ncols; ++j)
    2939 {
    2940 /* pass call on to lpiStrongbranch() */
    2941 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
    2942
    2943 /* pass SCIP_LPERROR to SCIP without a back trace */
    2944 if( retcode == SCIP_LPERROR )
    2945 return SCIP_LPERROR;
    2946
    2947 /* evaluate retcode */
    2948 SCIP_CALL( retcode );
    2949 }
    2950
    2951 return SCIP_OKAY;
    2952}
    2953/**@} */
    2954
    2955
    2956
    2957
    2958/*
    2959 * Solution Information Methods
    2960 */
    2961
    2962/**@name Solution Information Methods */
    2963/**@{ */
    2964
    2965/** returns whether a solve method was called after the last modification of the LP */
    2967 SCIP_LPI* lpi /**< LP interface structure */
    2968 )
    2969{
    2970 assert(lpi != NULL);
    2971
    2972 return lpi->solved;
    2973}
    2974
    2975/** gets information about primal and dual feasibility of the current LP solution
    2976 *
    2977 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
    2978 * returns true. If the LP is changed, this information might be invalidated.
    2979 *
    2980 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
    2981 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
    2982 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
    2983 * the problem might actually be feasible).
    2984 */
    2986 SCIP_LPI* lpi, /**< LP interface structure */
    2987 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
    2988 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
    2989 )
    2990{
    2991 SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
    2992
    2993 assert(lpi != NULL);
    2994 assert(primalfeasible != NULL);
    2995 assert(dualfeasible != NULL);
    2996
    2997 *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
    2998 *dualfeasible = SCIPlpiIsDualFeasible(lpi);
    2999
    3000 return SCIP_OKAY;
    3001}
    3002
    3003/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
    3004 * this does not necessarily mean, that the solver knows and can return the primal ray
    3005 */
    3007 SCIP_LPI* lpi /**< LP interface structure */
    3008 )
    3009{
    3010 SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
    3011
    3012 assert(lpi != NULL);
    3013 assert(lpi->spx != NULL);
    3014
    3015 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
    3016}
    3017
    3018/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
    3019 * and the solver knows and can return the primal ray
    3020 */
    3022 SCIP_LPI* lpi /**< LP interface structure */
    3023 )
    3024{
    3025 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
    3026
    3027 assert(lpi != NULL);
    3028 assert(lpi->spx != NULL);
    3029
    3030 return lpi->spx->hasPrimalRay();
    3031}
    3032
    3033/** returns TRUE iff LP is proven to be primal unbounded */
    3035 SCIP_LPI* lpi /**< LP interface structure */
    3036 )
    3037{
    3038 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
    3039
    3040 assert(lpi != NULL);
    3041 assert(lpi->spx != NULL);
    3042
    3043 assert(lpi->spx->status() != SPxSolver::UNBOUNDED || lpi->spx->basisStatus() == SPxBasis::UNBOUNDED);
    3044
    3045 /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
    3046 * feasible point; hence we have to check the perturbation
    3047 */
    3048 return lpi->spx->status() == SPxSolver::UNBOUNDED;
    3049}
    3050
    3051/** returns TRUE iff LP is proven to be primal infeasible */
    3053 SCIP_LPI* lpi /**< LP interface structure */
    3054 )
    3055{
    3056 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
    3057
    3058 assert(lpi != NULL);
    3059 assert(lpi->spx != NULL);
    3060
    3061 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
    3062}
    3063
    3064/** returns TRUE iff LP is proven to be primal feasible */
    3066 SCIP_LPI* lpi /**< LP interface structure */
    3067 )
    3068{
    3069 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
    3070
    3071 assert(lpi != NULL);
    3072 assert(lpi->spx != NULL);
    3073
    3074 return lpi->spx->basisStatus() == SPxBasis::OPTIMAL || lpi->spx->basisStatus() == SPxBasis::PRIMAL;
    3075}
    3076
    3077/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
    3078 * this does not necessarily mean, that the solver knows and can return the dual ray
    3079 */
    3081 SCIP_LPI* lpi /**< LP interface structure */
    3082 )
    3083{
    3084 SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
    3085
    3086 assert(lpi != NULL);
    3087 assert(lpi->spx != NULL);
    3088
    3089 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
    3090}
    3091
    3092/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
    3093 * and the solver knows and can return the dual ray
    3094 */
    3096 SCIP_LPI* lpi /**< LP interface structure */
    3097 )
    3098{
    3099 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
    3100
    3101 assert(lpi != NULL);
    3102 assert(lpi->spx != NULL);
    3103
    3104 return lpi->spx->hasDualFarkas();
    3105}
    3106
    3107/** returns TRUE iff LP is dual unbounded */
    3109 SCIP_LPI* lpi /**< LP interface structure */
    3110 )
    3111{
    3112 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
    3113
    3114 assert(lpi != NULL);
    3115 assert(lpi->spx != NULL);
    3116
    3117 return lpi->spx->status() == SPxSolver::INFEASIBLE && lpi->spx->basisStatus() == SPxBasis::DUAL;
    3118}
    3119
    3120/** returns TRUE iff LP is dual infeasible */
    3122 SCIP_LPI* lpi /**< LP interface structure */
    3123 )
    3124{
    3125 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
    3126
    3127 assert(lpi != NULL);
    3128 assert(lpi->spx != NULL);
    3129
    3130 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
    3131}
    3132
    3133/** returns TRUE iff LP is proven to be dual feasible */
    3135 SCIP_LPI* lpi /**< LP interface structure */
    3136 )
    3137{
    3138 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
    3139
    3140 assert(lpi != NULL);
    3141 assert(lpi->spx != NULL);
    3142
    3143 return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL) || lpi->spx->basisStatus() == SPxBasis::DUAL;
    3144}
    3145
    3146/** returns TRUE iff LP was solved to optimality */
    3148 SCIP_LPI* lpi /**< LP interface structure */
    3149 )
    3150{
    3151 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
    3152
    3153 assert(lpi != NULL);
    3154 assert(lpi->spx != NULL);
    3155 assert((lpi->spx->basisStatus() == SPxBasis::OPTIMAL)
    3157
    3158 return (lpi->spx->status() == SPxSolver::OPTIMAL);
    3159}
    3160
    3161/** returns TRUE iff current LP solution is stable
    3162 *
    3163 * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
    3164 * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
    3165 * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
    3166 * SCIPlpiIsStable() should return false.
    3167 */
    3169 SCIP_LPI* lpi /**< LP interface structure */
    3170 )
    3171{
    3172 SCIPdebugMessage("calling SCIPlpiIsStable()\n");
    3173
    3174 assert(lpi != NULL);
    3175 assert(lpi->spx != NULL);
    3176
    3177 if( lpi->spx->status() == SPxSolver::ERROR || lpi->spx->status() == SPxSolver::SINGULAR )
    3178 return FALSE;
    3179#if SOPLEX_APIVERSION >= 3
    3180 if( lpi->spx->status() == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS )
    3181 return FALSE;
    3182#endif
    3183 /* only if we have a regular basis and the condition limit is set, we compute the condition number of the basis;
    3184 * everything above the specified threshold is then counted as instable
    3185 */
    3186 if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
    3187 {
    3188 SCIP_RETCODE retcode;
    3189 SCIP_Real kappa;
    3190
    3192 if( retcode != SCIP_OKAY )
    3193 {
    3194 SCIPABORT();
    3195 }
    3196 assert(kappa != SCIP_INVALID); /*lint !e777*/
    3197
    3198 if( kappa > lpi->conditionlimit )
    3199 return FALSE;
    3200 }
    3201 /* if an objective limit is set and SoPlex claims that it is exceeded, we should check that this is indeed the case;
    3202 * if not this points at numerical instability; note that this aligns with an assert in lp.c */
    3203 if( SCIPlpiIsObjlimExc(lpi) )
    3204 {
    3205 SCIP_Real objlimit = lpi->spx->getObjLimit();
    3206 SCIP_Real objvalue = lpi->spx->objValueReal();
    3207
    3208 if( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE )
    3209 {
    3210 objlimit *= -1.0;
    3211 objvalue *= -1.0;
    3212 }
    3213 if( !SCIPlpiIsInfinity(lpi, objlimit) && LTrel(objvalue, objlimit, 2*lpi->spx->opttol()) )
    3214 return FALSE;
    3215 }
    3216 return TRUE;
    3217}
    3218
    3219/** returns TRUE iff the objective limit was reached */
    3221 SCIP_LPI* lpi /**< LP interface structure */
    3222 )
    3223{
    3224 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
    3225
    3226 assert(lpi != NULL);
    3227 assert(lpi->spx != NULL);
    3228
    3229 return (lpi->spx->status() == SPxSolver::ABORT_VALUE);
    3230}
    3231
    3232/** returns TRUE iff the iteration limit was reached */
    3234 SCIP_LPI* lpi /**< LP interface structure */
    3235 )
    3236{
    3237 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
    3238
    3239 assert(lpi != NULL);
    3240 assert(lpi->spx != NULL);
    3241
    3242 return (lpi->spx->status() == SPxSolver::ABORT_ITER);
    3243}
    3244
    3245/** returns TRUE iff the time limit was reached */
    3247 SCIP_LPI* lpi /**< LP interface structure */
    3248 )
    3249{
    3250 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
    3251
    3252 assert(lpi != NULL);
    3253 assert(lpi->spx != NULL);
    3254
    3255 return (lpi->spx->status() == SPxSolver::ABORT_TIME);
    3256}
    3257
    3258/** returns the internal solution status of the solver */
    3260 SCIP_LPI* lpi /**< LP interface structure */
    3261 )
    3262{
    3263 SCIPdebugMessage("calling SCIPlpiGetInternalStatus()\n");
    3264
    3265 assert(lpi != NULL);
    3266 assert(lpi->spx != NULL);
    3267
    3268 return static_cast<int>(lpi->spx->status());
    3269}
    3270
    3271/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
    3273 SCIP_LPI* lpi, /**< LP interface structure */
    3274 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
    3275 )
    3276{ /*lint --e{715}*/
    3277 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
    3278
    3279 assert(lpi != NULL);
    3280 assert(lpi->spx != NULL);
    3281 assert(success != NULL);
    3282
    3283#if SOPLEX_APIVERSION >= 4
    3284 *success = lpi->spx->ignoreUnscaledViolations();
    3285#else
    3286 *success = FALSE;
    3287#endif
    3288
    3289 return SCIP_OKAY;
    3290}
    3291
    3292/** gets objective value of solution */
    3294 SCIP_LPI* lpi, /**< LP interface structure */
    3295 SCIP_Real* objval /**< stores the objective value */
    3296 )
    3297{
    3298 SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
    3299
    3300 assert(lpi != NULL);
    3301 assert(lpi->spx != NULL);
    3302 assert(objval != NULL);
    3303
    3304 *objval = lpi->spx->objValueReal();
    3305
    3306 return SCIP_OKAY;
    3307}
    3308
    3309/** gets primal and dual solution vectors for feasible LPs
    3310 *
    3311 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
    3312 * SCIPlpiIsOptimal() returns true.
    3313 */
    3315 SCIP_LPI* lpi, /**< LP interface structure */
    3316 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
    3317 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
    3318 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
    3319 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
    3320 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
    3321 )
    3322{
    3323 SCIPdebugMessage("calling SCIPlpiGetSol()\n");
    3324
    3325 assert(lpi != NULL);
    3326 assert(lpi->spx != NULL);
    3327
    3328 if( objval != NULL )
    3329 *objval = lpi->spx->objValueReal();
    3330
    3331 try
    3332 {
    3333 if( primsol != NULL )
    3334 {
    3335#if SOPLEX_APIVERSION > 10
    3336 (void)lpi->spx->getPrimalReal(primsol, lpi->spx->numColsReal());
    3337#else
    3338 Vector tmp(lpi->spx->numColsReal(), primsol);
    3339 (void)lpi->spx->getPrimalReal(tmp);
    3340#endif
    3341 }
    3342 if( dualsol != NULL )
    3343 {
    3344#if SOPLEX_APIVERSION > 10
    3345 (void)lpi->spx->getDualReal(dualsol, lpi->spx->numRowsReal());
    3346#else
    3347 Vector tmp(lpi->spx->numRowsReal(), dualsol);
    3348 (void)lpi->spx->getDualReal(tmp);
    3349#endif
    3350 }
    3351 if( activity != NULL )
    3352 {
    3353#if SOPLEX_APIVERSION > 10
    3354 (void)lpi->spx->getSlacksReal(activity, lpi->spx->numRowsReal()); /* in SoPlex, the activities are called "slacks" */
    3355#else
    3356 Vector tmp(lpi->spx->numRowsReal(), activity);
    3357 (void)lpi->spx->getSlacksReal(tmp); /* in SoPlex, the activities are called "slacks" */
    3358#endif
    3359 }
    3360 if( redcost != NULL )
    3361 {
    3362#if SOPLEX_APIVERSION > 10
    3363 (void)lpi->spx->getRedCostReal(redcost, lpi->spx->numColsReal());
    3364#else
    3365 Vector tmp(lpi->spx->numColsReal(), redcost);
    3366 (void)lpi->spx->getRedCostReal(tmp);
    3367#endif
    3368 }
    3369 }
    3370#ifndef NDEBUG
    3371 catch( const SPxException& x )
    3372 {
    3373 std::string s = x.what();
    3374 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    3375#else
    3376 catch( const SPxException& )
    3377 {
    3378#endif
    3379 return SCIP_LPERROR;
    3380 }
    3381
    3382 return SCIP_OKAY;
    3383}
    3384
    3385/** gets primal ray for unbounded LPs */
    3387 SCIP_LPI* lpi, /**< LP interface structure */
    3388 SCIP_Real* ray /**< primal ray */
    3389 )
    3390{ /*lint --e{715}*/
    3391 SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
    3392
    3393 assert(lpi != NULL);
    3394 assert(lpi->spx != NULL);
    3395 assert(lpi->spx->hasPrimalRay());
    3396 assert(ray != NULL);
    3397
    3398 try
    3399 {
    3400#if SOPLEX_APIVERSION > 10
    3401 (void)lpi->spx->getPrimalRayReal(ray, lpi->spx->numColsReal());
    3402#else
    3403 Vector tmp(lpi->spx->numColsReal(), ray);
    3404 (void)lpi->spx->getPrimalRayReal(tmp);
    3405#endif
    3406 }
    3407#ifndef NDEBUG
    3408 catch( const SPxException& x )
    3409 {
    3410 std::string s = x.what();
    3411 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    3412#else
    3413 catch( const SPxException& )
    3414 {
    3415#endif
    3416 return SCIP_LPERROR;
    3417 }
    3418
    3419 return SCIP_OKAY;
    3420}
    3421
    3422/** gets dual farkas proof for infeasibility */
    3424 SCIP_LPI* lpi, /**< LP interface structure */
    3425 SCIP_Real* dualfarkas /**< dual farkas row multipliers */
    3426 )
    3427{
    3428 SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
    3429
    3430 assert(lpi != NULL);
    3431 assert(lpi->spx != NULL);
    3432 assert(lpi->spx->hasDualFarkas());
    3433 assert(dualfarkas != NULL);
    3434
    3435 try
    3436 {
    3437#if SOPLEX_APIVERSION > 10
    3438 (void)lpi->spx->getDualFarkasReal(dualfarkas, lpi->spx->numRowsReal());
    3439#else
    3440 Vector tmp(lpi->spx->numRowsReal(), dualfarkas);
    3441 (void)lpi->spx->getDualFarkasReal(tmp);
    3442#endif
    3443 }
    3444#ifndef NDEBUG
    3445 catch( const SPxException& x )
    3446 {
    3447 std::string s = x.what();
    3448 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    3449#else
    3450 catch( const SPxException& )
    3451 {
    3452#endif
    3453 return SCIP_LPERROR;
    3454 }
    3455
    3456 return SCIP_OKAY;
    3457}
    3458
    3459/** gets the number of LP iterations of the last solve call */
    3461 SCIP_LPI* lpi, /**< LP interface structure */
    3462 int* iterations /**< pointer to store the number of iterations of the last solve call */
    3463 )
    3464{
    3465 SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
    3466
    3467 assert(lpi != NULL);
    3468 assert(lpi->spx != NULL);
    3469 assert(iterations != NULL);
    3470
    3471 *iterations = lpi->spx->numIterations();
    3472
    3473 return SCIP_OKAY;
    3474}
    3475
    3476/** gets information about the quality of an LP solution
    3477 *
    3478 * Such information is usually only available, if also a (maybe not optimal) solution is available.
    3479 * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
    3480 */
    3482 SCIP_LPI* lpi, /**< LP interface structure */
    3483 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
    3484 SCIP_Real* quality /**< pointer to store quality number */
    3485 )
    3486{
    3487 SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
    3488
    3489 assert(lpi != NULL);
    3490 assert(quality != NULL);
    3491
    3492 bool success;
    3493
    3494 SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
    3495
    3496 switch( qualityindicator )
    3497 {
    3499 success = lpi->spx->getEstimatedCondition(*quality);
    3500 break;
    3501
    3503 success = lpi->spx->getExactCondition(*quality);
    3504 break;
    3505
    3506 default:
    3507 SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
    3508 return SCIP_INVALIDDATA;
    3509 }
    3510
    3511 if( !success )
    3512 {
    3513 SCIPdebugMessage("problem computing condition number\n");
    3514 *quality = SCIP_INVALID;
    3515 }
    3516
    3517 return SCIP_OKAY;
    3518}
    3519
    3520/**@} */
    3521
    3522
    3523
    3524
    3525/*
    3526 * LP Basis Methods
    3527 */
    3528
    3529/**@name LP Basis Methods */
    3530/**@{ */
    3531
    3532
    3533/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
    3535 SCIP_LPI* lpi, /**< LP interface structure */
    3536 int* cstat, /**< array to store column basis status, or NULL */
    3537 int* rstat /**< array to store row basis status, or NULL */
    3538 )
    3539{
    3540 int i;
    3541
    3542 SCIPdebugMessage("calling SCIPlpiGetBase()\n");
    3543
    3544 assert(lpi != NULL);
    3545 assert(lpi->spx != NULL);
    3546
    3547 assert( lpi->spx->preStrongbranchingBasisFreed() );
    3548
    3549 if( rstat != NULL )
    3550 {
    3551 for( i = 0; i < lpi->spx->numRowsReal(); ++i )
    3552 {
    3553 switch( lpi->spx->basisRowStatus(i) )
    3554 {
    3555 case SPxSolver::BASIC:
    3556 rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
    3557 break;
    3558 case SPxSolver::FIXED:
    3559 case SPxSolver::ON_LOWER:
    3560 rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
    3561 break;
    3562 case SPxSolver::ON_UPPER:
    3563 rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
    3564 break;
    3565 case SPxSolver::ZERO:
    3566 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
    3567 return SCIP_LPERROR;
    3568 case SPxSolver::UNDEFINED:
    3569 default:
    3570 SCIPerrorMessage("invalid basis status\n");
    3571 SCIPABORT();
    3572 return SCIP_INVALIDDATA; /*lint !e527*/
    3573 }
    3574 }
    3575 }
    3576
    3577 if( cstat != NULL )
    3578 {
    3579 for( i = 0; i < lpi->spx->numColsReal(); ++i )
    3580 {
    3581// SCIP_Real val = 0.0;
    3582 switch( lpi->spx->basisColStatus(i) )
    3583 {
    3584 case SPxSolver::BASIC:
    3585 cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
    3586 break;
    3587 case SPxSolver::FIXED:
    3588 /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
    3589 * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
    3590 * this case there is no problem at all. If the basis is saved and/or used in some other
    3591 * solver, it usually is very cheap to perform the pivots necessary to get an optimal
    3592 * basis.
    3593 * @todo implement getRedCostEst()
    3594 * */
    3595// SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
    3596// if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
    3597// cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
    3598// else
    3599 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
    3600 break;
    3601 case SPxSolver::ON_LOWER:
    3602 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
    3603 break;
    3604 case SPxSolver::ON_UPPER:
    3605 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
    3606 break;
    3607 case SPxSolver::ZERO:
    3608 cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
    3609 break;
    3610 case SPxSolver::UNDEFINED:
    3611 default:
    3612 SCIPerrorMessage("invalid basis status\n");
    3613 SCIPABORT();
    3614 return SCIP_INVALIDDATA; /*lint !e527*/
    3615 }
    3616 }
    3617 }
    3618
    3619 return SCIP_OKAY;
    3620}
    3621
    3622/** sets current basis status for columns and rows */
    3624 SCIP_LPI* lpi, /**< LP interface structure */
    3625 const int* cstat, /**< array with column basis status */
    3626 const int* rstat /**< array with row basis status */
    3627 )
    3628{
    3629 int i;
    3630 int ncols;
    3631 int nrows;
    3632
    3633 SCIPdebugMessage("calling SCIPlpiSetBase()\n");
    3634
    3635 assert(lpi != NULL);
    3636 assert(lpi->spx != NULL);
    3637
    3638 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
    3639 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
    3640
    3641 assert(cstat != NULL || ncols == 0);
    3642 assert(rstat != NULL || nrows == 0);
    3643
    3644 assert( lpi->spx->preStrongbranchingBasisFreed() );
    3645 invalidateSolution(lpi);
    3646
    3647 DataArray<SPxSolver::VarStatus>& _colstat = lpi->spx->colStat();
    3648 DataArray<SPxSolver::VarStatus>& _rowstat = lpi->spx->rowStat();
    3649
    3650 _colstat.reSize(ncols);
    3651 _rowstat.reSize(nrows);
    3652
    3653 for( i = 0; i < nrows; ++i )
    3654 {
    3655 switch( rstat[i] ) /*lint !e613*/
    3656 {
    3658 _rowstat[i] = SPxSolver::ON_LOWER;
    3659 break;
    3661 _rowstat[i] = SPxSolver::BASIC;
    3662 break;
    3664 _rowstat[i] = SPxSolver::ON_UPPER;
    3665 break;
    3666 case SCIP_BASESTAT_ZERO:
    3667 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
    3668 return SCIP_LPERROR; /*lint !e429*/
    3669 default:
    3670 SCIPerrorMessage("invalid basis status\n");
    3671 SCIPABORT();
    3672 return SCIP_INVALIDDATA; /*lint !e527*/
    3673 }
    3674 }
    3675
    3676 for( i = 0; i < ncols; ++i )
    3677 {
    3678 switch( cstat[i] ) /*lint !e613*/
    3679 {
    3681 _colstat[i] = SPxSolver::ON_LOWER;
    3682 break;
    3684 _colstat[i] = SPxSolver::BASIC;
    3685 break;
    3687 _colstat[i] = SPxSolver::ON_UPPER;
    3688 break;
    3689 case SCIP_BASESTAT_ZERO:
    3690 _colstat[i] = SPxSolver::ZERO;
    3691 break;
    3692 default:
    3693 SCIPerrorMessage("invalid basis status\n");
    3694 SCIPABORT();
    3695 return SCIP_INVALIDDATA; /*lint !e527*/
    3696 }
    3697 }
    3698
    3699 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(_rowstat.get_ptr(), _colstat.get_ptr()) );
    3700 lpi->spx->freePreStrongbranchingBasis();
    3701
    3702 return SCIP_OKAY;
    3703}
    3704
    3705/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
    3707 SCIP_LPI* lpi, /**< LP interface structure */
    3708 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
    3709 )
    3710{
    3711 SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
    3712
    3713 assert(lpi != NULL);
    3714 assert(lpi->spx != NULL);
    3715 assert(bind != NULL);
    3716
    3717 assert(lpi->spx->preStrongbranchingBasisFreed());
    3718
    3719 lpi->spx->getBasisInd(bind);
    3720
    3721 return SCIP_OKAY;
    3722}
    3723
    3724
    3725/** get row of inverse basis matrix B^-1
    3726 *
    3727 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
    3728 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
    3729 * see also the explanation in lpi.h.
    3730 */
    3732 SCIP_LPI* lpi, /**< LP interface structure */
    3733 int r, /**< row number */
    3734 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
    3735 int* inds, /**< array to store the non-zero indices, or NULL */
    3736 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    3737 * (-1: if we do not store sparsity information) */
    3738 )
    3739{
    3740 SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
    3741
    3742 assert(lpi != NULL);
    3743 assert(lpi->spx != NULL);
    3744 assert(lpi->spx->preStrongbranchingBasisFreed());
    3745 assert(coef != NULL);
    3746
    3747 assert(r >= 0);
    3748 assert(r < lpi->spx->numRowsReal());
    3749
    3750 if( ! lpi->spx->getBasisInverseRowReal(r, coef, inds, ninds) )
    3751 return SCIP_LPERROR;
    3752
    3753 return SCIP_OKAY;
    3754}
    3755
    3756/** get column of inverse basis matrix B^-1
    3757 *
    3758 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
    3759 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
    3760 * see also the explanation in lpi.h.
    3761 */
    3763 SCIP_LPI* lpi, /**< LP interface structure */
    3764 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
    3765 * you have to call SCIPlpiGetBasisInd() to get the array which links the
    3766 * B^-1 column numbers to the row and column numbers of the LP!
    3767 * c must be between 0 and nrows-1, since the basis has the size
    3768 * nrows * nrows */
    3769 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
    3770 int* inds, /**< array to store the non-zero indices, or NULL */
    3771 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    3772 * (-1: if we do not store sparsity information) */
    3773 )
    3774{
    3775 SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
    3776
    3777 assert( lpi != NULL );
    3778 assert( lpi->spx != NULL );
    3779 assert( lpi->spx->preStrongbranchingBasisFreed() );
    3780 assert(coef != NULL);
    3781
    3782 if( ! lpi->spx->getBasisInverseColReal(c, coef, inds, ninds) )
    3783 return SCIP_LPERROR;
    3784
    3785 return SCIP_OKAY;
    3786}
    3787
    3788/** get row of inverse basis matrix times constraint matrix B^-1 * A
    3789 *
    3790 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
    3791 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
    3792 * see also the explanation in lpi.h.
    3793 */
    3795 SCIP_LPI* lpi, /**< LP interface structure */
    3796 int r, /**< row number */
    3797 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
    3798 SCIP_Real* coef, /**< vector to return coefficients of the row */
    3799 int* inds, /**< array to store the non-zero indices, or NULL */
    3800 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    3801 * (-1: if we do not store sparsity information) */
    3802 )
    3803{
    3804 SCIP_Real* buf;
    3805 SCIP_Real* binv;
    3806 int nrows;
    3807 int ncols;
    3808 int c;
    3809
    3810 SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
    3811
    3812 assert(lpi != NULL);
    3813 assert(lpi->spx != NULL);
    3814 assert( lpi->spx->preStrongbranchingBasisFreed() );
    3815 assert(coef != NULL);
    3816
    3817 nrows = lpi->spx->numRowsReal();
    3818 ncols = lpi->spx->numColsReal();
    3819 buf = NULL;
    3820
    3821 /* get (or calculate) the row in B^-1 */
    3822 if( binvrow == NULL )
    3823 {
    3824 SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
    3825 SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
    3826 binv = buf;
    3827 }
    3828 else
    3829 binv = const_cast<SCIP_Real*>(binvrow);
    3830
    3831 assert(binv != NULL);
    3832
    3833 /* mark sparsity pattern as invalid */
    3834 if( ninds != NULL )
    3835 *ninds = -1;
    3836
    3837 // @todo exploit sparsity in binv by looping over nrows
    3838 /* calculate the scalar product of the row in B^-1 and A */
    3839 Vector binvvec(nrows, binv);
    3840
    3841#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    3842 /* temporary unscaled column of A */
    3843 DSVector acol;
    3844#endif
    3845
    3846 for( c = 0; c < ncols; ++c )
    3847 {
    3848#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    3849 lpi->spx->getColVectorReal(c, acol);
    3850 coef[c] = binvvec * acol; /* scalar product */ /*lint !e1702*/
    3851#else
    3852 coef[c] = binvvec * lpi->spx->colVectorReal(c); /* scalar product */ /*lint !e1702*/
    3853#endif
    3854 }
    3855
    3856 /* free memory if it was temporarily allocated */
    3858
    3859 return SCIP_OKAY;
    3860}
    3861
    3862/** get column of inverse basis matrix times constraint matrix B^-1 * A
    3863 *
    3864 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
    3865 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
    3866 * see also the explanation in lpi.h.
    3867 */
    3869 SCIP_LPI* lpi, /**< LP interface structure */
    3870 int c, /**< column number */
    3871 SCIP_Real* coef, /**< vector to return coefficients of the column */
    3872 int* inds, /**< array to store the non-zero indices, or NULL */
    3873 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    3874 * (-1: if we do not store sparsity information) */
    3875 )
    3876{ /*lint --e{715}*/
    3877 /* create a new uninitialized full vector */
    3878 DVector col(lpi->spx->numRowsReal());
    3879
    3880#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    3881 /* temporary sparse vector used for unscaling (memory is automatically enlarged) */
    3882 DSVector colsparse;
    3883#endif
    3884
    3885 SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
    3886
    3887 assert( lpi != NULL );
    3888 assert( lpi->spx != NULL );
    3889 assert( lpi->spx->preStrongbranchingBasisFreed() );
    3890 assert(coef != NULL);
    3891
    3892 /* extract column c of A */
    3893 assert(c >= 0);
    3894 assert(c < lpi->spx->numColsReal());
    3895
    3896 /* @todo implement this with sparse vectors */
    3897 /* mark sparsity pattern as invalid */
    3898 if( ninds != NULL )
    3899 *ninds = -1;
    3900
    3901 /* col needs to be cleared because copying colVectorReal only regards nonzeros */
    3902 col.clear();
    3903
    3904#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
    3905 lpi->spx->getColVectorReal(c, colsparse);
    3906 /* the copy is necessary to transform the sparse column into a dense vector */
    3907 col = colsparse;
    3908#else
    3909 col = lpi->spx->colVectorReal(c);
    3910#endif
    3911
    3912 /* solve */
    3913 if( ! lpi->spx->getBasisInverseTimesVecReal(col.get_ptr(), coef) )
    3914 return SCIP_LPERROR;
    3915
    3916 return SCIP_OKAY;
    3917}
    3918
    3919/**@} */
    3920
    3921
    3922
    3923
    3924/*
    3925 * LP State Methods
    3926 */
    3927
    3928/**@name LP State Methods */
    3929/**@{ */
    3930
    3931/** stores LPi state (like basis information) into lpistate object */
    3933 SCIP_LPI* lpi, /**< LP interface structure */
    3934 BMS_BLKMEM* blkmem, /**< block memory */
    3935 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
    3936 )
    3937{
    3938 int ncols;
    3939 int nrows;
    3940
    3941 SCIPdebugMessage("calling SCIPlpiGetState()\n");
    3942
    3943 assert(blkmem != NULL);
    3944 assert(lpi != NULL);
    3945 assert(lpi->spx != NULL);
    3946 assert(lpistate != NULL);
    3947
    3948 assert( lpi->spx->preStrongbranchingBasisFreed() );
    3949
    3950 ncols = lpi->spx->numColsReal();
    3951 nrows = lpi->spx->numRowsReal();
    3952 assert(ncols >= 0);
    3953 assert(nrows >= 0);
    3954
    3955 /* allocate lpistate data */
    3956 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
    3957
    3958 /* allocate enough memory for storing uncompressed basis information */
    3959 SCIP_CALL( ensureCstatMem(lpi, ncols) );
    3960 SCIP_CALL( ensureRstatMem(lpi, nrows) );
    3961
    3962 /* get unpacked basis information */
    3963 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
    3964
    3965 /* pack LPi state data */
    3966 (*lpistate)->ncols = ncols;
    3967 (*lpistate)->nrows = nrows;
    3968 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
    3969
    3970 return SCIP_OKAY;
    3971}
    3972
    3973/** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
    3974 * columns and rows since the state was stored with SCIPlpiGetState()
    3975 */
    3977 SCIP_LPI* lpi, /**< LP interface structure */
    3978 BMS_BLKMEM* /*blkmem*/, /**< block memory */
    3979 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
    3980 )
    3981{
    3982 int lpncols;
    3983 int lpnrows;
    3984 int i;
    3985
    3986 SCIPdebugMessage("calling SCIPlpiSetState()\n");
    3987
    3988 assert(lpi != NULL);
    3989 assert(lpi->spx != NULL);
    3990 assert(lpistate != NULL);
    3991 /* assert(blkmem != NULL); */
    3992
    3993 assert( lpi->spx->preStrongbranchingBasisFreed() );
    3994
    3995 lpncols = lpi->spx->numColsReal();
    3996 lpnrows = lpi->spx->numRowsReal();
    3997 assert(lpistate->ncols <= lpncols);
    3998 assert(lpistate->nrows <= lpnrows);
    3999
    4000 /* allocate enough memory for storing uncompressed basis information */
    4001 SCIP_CALL( ensureCstatMem(lpi, lpncols) );
    4002 SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
    4003
    4004 /* unpack LPi state data */
    4005 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
    4006
    4007 /* extend the basis to the current LP beyond the previously existing columns */
    4008 for( i = lpistate->ncols; i < lpncols; ++i )
    4009 {
    4010 SCIP_Real bnd = lpi->spx->lowerReal(i);
    4011 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
    4012 {
    4013 /* if lower bound is +/- infinity -> try upper bound */
    4014 bnd = lpi->spx->lowerReal(i);
    4015 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
    4016 /* variable is free */
    4017 lpi->cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
    4018 else
    4019 /* use finite upper bound */
    4020 lpi->cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
    4021 }
    4022 else
    4023 /* use finite lower bound */
    4024 lpi->cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
    4025 }
    4026 for( i = lpistate->nrows; i < lpnrows; ++i )
    4027 lpi->rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
    4028
    4029 /* load basis information */
    4030 SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
    4031
    4032 return SCIP_OKAY;
    4033}
    4034
    4035/** clears current LPi state (like basis information) of the solver */
    4037 SCIP_LPI* lpi /**< LP interface structure */
    4038 )
    4039{ /*lint --e{715}*/
    4040 SCIPdebugMessage("calling SCIPlpiClearState()\n");
    4041
    4042 assert(lpi != NULL);
    4043 assert(lpi->spx != NULL);
    4044
    4045 try
    4046 {
    4047 lpi->spx->clearBasis();
    4048 }
    4049#ifndef NDEBUG
    4050 catch( const SPxException& x )
    4051 {
    4052 std::string s = x.what();
    4053 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    4054#else
    4055 catch( const SPxException& )
    4056 {
    4057#endif
    4058 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
    4059 return SCIP_LPERROR;
    4060 }
    4061
    4062 return SCIP_OKAY;
    4063}
    4064
    4065/** frees LPi state information */
    4067 SCIP_LPI* lpi, /**< LP interface structure */
    4068 BMS_BLKMEM* blkmem, /**< block memory */
    4069 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
    4070 )
    4071{ /*lint --e{715}*/
    4072 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
    4073
    4074 assert(lpi != NULL);
    4075 assert(lpistate != NULL);
    4076 assert(blkmem != NULL);
    4077
    4078 if ( *lpistate != NULL )
    4079 lpistateFree(lpistate, blkmem);
    4080
    4081 return SCIP_OKAY;
    4082}
    4083
    4084/** checks whether the given LP state contains simplex basis information */
    4086 SCIP_LPI* lpi, /**< LP interface structure */
    4087 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
    4088 )
    4089{ /*lint --e{715}*/
    4090 assert(lpi != NULL);
    4091 return TRUE;
    4092}
    4093
    4094/** reads LP state (like basis information from a file */
    4096 SCIP_LPI* lpi, /**< LP interface structure */
    4097 const char* fname /**< file name */
    4098 )
    4099{
    4100 SCIPdebugMessage("calling SCIPlpiReadState()\n");
    4101 assert(lpi != NULL);
    4102 assert(lpi->spx != NULL);
    4103 assert(fname != NULL);
    4104
    4105 assert( lpi->spx->preStrongbranchingBasisFreed() );
    4106
    4107 bool success;
    4108 SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
    4109
    4110 return success ? SCIP_OKAY : SCIP_LPERROR;
    4111}
    4112
    4113/** writes LPi state (i.e. basis information) to a file */
    4115 SCIP_LPI* lpi, /**< LP interface structure */
    4116 const char* fname /**< file name */
    4117 )
    4118{
    4119 assert(lpi != NULL);
    4120 assert(lpi->spx != NULL);
    4121 assert(fname != NULL);
    4122 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
    4123
    4124 assert( lpi->spx->preStrongbranchingBasisFreed() );
    4125
    4126 bool res;
    4127 SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
    4128
    4129 if ( ! res )
    4130 return SCIP_LPERROR;
    4131
    4132 return SCIP_OKAY;
    4133}
    4134
    4135/**@} */
    4136
    4137
    4138
    4139
    4140/*
    4141 * LP Pricing Norms Methods
    4142 */
    4143
    4144/**@name LP Pricing Norms Methods */
    4145/**@{ */
    4146
    4147/** stores LPi pricing norms information
    4148 * @todo should we store norm information?
    4149 */
    4151 SCIP_LPI* lpi, /**< LP interface structure */
    4152 BMS_BLKMEM* blkmem, /**< block memory */
    4153 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
    4154 )
    4155{ /*lint --e{715}*/
    4156#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
    4157 int nrows;
    4158 int ncols;
    4159
    4160 assert(blkmem != NULL);
    4161 assert(lpi != NULL);
    4162 assert(lpi->spx != NULL);
    4163 assert(lpinorms != NULL);
    4164
    4165 lpi->spx->getNdualNorms(nrows, ncols);
    4166
    4167 if( nrows == 0 && ncols == 0)
    4168 {
    4169 (*lpinorms = NULL);
    4170 return SCIP_OKAY;
    4171 }
    4172
    4173 /* allocate lpinorms data */
    4174 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
    4175 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
    4176 (*lpinorms)->nrows = 0;
    4177 (*lpinorms)->ncols = 0;
    4178
    4179 SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
    4180
    4181 if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
    4182 {
    4183 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
    4184 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
    4185 BMSfreeBlockMemory(blkmem, lpinorms);
    4186 assert(*lpinorms == NULL);
    4187 }
    4188#ifndef NDEBUG
    4189 else
    4190 {
    4191 assert(nrows == (*lpinorms)->nrows);
    4192 assert(ncols == (*lpinorms)->ncols);
    4193 }
    4194#endif
    4195#else
    4196 (*lpinorms) = NULL;
    4197#endif
    4198
    4199 return SCIP_OKAY;
    4200}
    4201
    4202/** loads LPi pricing norms into solver; note that the LP might have been extended with additional
    4203 * columns and rows since the state was stored with SCIPlpiGetNorms()
    4204 */
    4206 SCIP_LPI* lpi, /**< LP interface structure */
    4207 BMS_BLKMEM* blkmem, /**< block memory */
    4208 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
    4209 )
    4210{ /*lint --e{715}*/
    4211#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
    4212 assert(blkmem != NULL);
    4213 assert(lpi != NULL);
    4214 assert(lpi->spx != NULL);
    4215
    4216 /* if there was no pricing norms information available, the LPi norms were not stored */
    4217 if( lpinorms == NULL )
    4218 return SCIP_OKAY;
    4219
    4220 assert(lpinorms->nrows <= lpi->spx->numRowsReal());
    4221 assert(lpinorms->ncols <= lpi->spx->numColsReal());
    4222
    4223 if( lpinorms->nrows == 0 )
    4224 return SCIP_OKAY;
    4225
    4226 SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
    4227 (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->numRowsReal(), lpi->spx->numColsReal());
    4228
    4229 (void) lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms);
    4230#endif
    4231
    4232 return SCIP_OKAY;
    4233}
    4234
    4235/** frees pricing norms information */
    4237 SCIP_LPI* lpi, /**< LP interface structure */
    4238 BMS_BLKMEM* blkmem, /**< block memory */
    4239 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
    4240 )
    4241{ /*lint --e{715}*/
    4242#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
    4243 assert(lpi != NULL);
    4244 assert(lpinorms != NULL);
    4245
    4246 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
    4247
    4248 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
    4249 BMSfreeBlockMemory(blkmem, lpinorms);
    4250 assert(*lpinorms == NULL);
    4251#endif
    4252
    4253 return SCIP_OKAY;
    4254}
    4255
    4256/**@} */
    4257
    4258
    4259
    4260
    4261/*
    4262 * Parameter Methods
    4263 */
    4264
    4265/**@name Parameter Methods */
    4266/**@{ */
    4267
    4268/** gets integer parameter of LP */
    4270 SCIP_LPI* lpi, /**< LP interface structure */
    4271 SCIP_LPPARAM type, /**< parameter number */
    4272 int* ival /**< buffer to store the parameter value */
    4273 )
    4274{
    4275 int scaleparam;
    4276
    4277 SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
    4278
    4279 assert(lpi != NULL);
    4280 assert(lpi->spx != NULL);
    4281 assert(ival != NULL);
    4282
    4283 switch( type )
    4284 {
    4286 *ival = lpi->spx->getFromScratch();
    4287 break;
    4288 case SCIP_LPPAR_LPINFO:
    4289 *ival = lpi->spx->getLpInfo();
    4290 break;
    4291 case SCIP_LPPAR_LPITLIM:
    4292 *ival = lpi->spx->intParam(SoPlex::ITERLIMIT);
    4293 if( *ival == -1 )
    4294 *ival = INT_MAX;
    4295 break;
    4297 *ival = lpi->spx->intParam(SoPlex::SIMPLIFIER);
    4298 break;
    4299 case SCIP_LPPAR_PRICING:
    4300 *ival = (int) lpi->pricing;
    4301 break;
    4302 case SCIP_LPPAR_SCALING:
    4303 scaleparam = lpi->spx->intParam(SoPlex::SCALER);
    4304
    4305 if( scaleparam == SoPlex::SCALER_OFF )
    4306 *ival = 0;
    4307 else if( scaleparam == SoPlex::SCALER_BIEQUI )
    4308 *ival = 1;
    4309#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
    4310 else
    4311 {
    4312 assert(scaleparam == SoPlex::SCALER_LEASTSQ);
    4313 *ival = 2;
    4314 }
    4315#else
    4316 else
    4317 {
    4318 assert(scaleparam == SoPlex::SCALER_GEO8);
    4319 *ival = 2;
    4320 }
    4321#endif
    4322 break;
    4323#if SOPLEX_VERSION >= 201
    4324 case SCIP_LPPAR_TIMING:
    4325 *ival = (int) (lpi->spx->intParam(SoPlex::TIMER));
    4326 break;
    4327#endif
    4328#if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
    4330 *ival = (int) lpi->spx->randomSeed();
    4331 break;
    4332#endif
    4333#if SOPLEX_APIVERSION >= 1
    4335 *ival = (int) lpi->spx->intParam(SoPlex::FACTOR_UPDATE_MAX);
    4336 break;
    4337#endif
    4338 default:
    4339 return SCIP_PARAMETERUNKNOWN;
    4340 } /*lint !e788*/
    4341
    4342 return SCIP_OKAY;
    4343}
    4344
    4345/** sets integer parameter of LP */
    4347 SCIP_LPI* lpi, /**< LP interface structure */
    4348 SCIP_LPPARAM type, /**< parameter number */
    4349 int ival /**< parameter value */
    4350 )
    4351{
    4352 SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
    4353
    4354 assert(lpi != NULL);
    4355 assert(lpi->spx != NULL);
    4356
    4357 switch( type )
    4358 {
    4360 assert(ival == TRUE || ival == FALSE);
    4361 lpi->spx->setFromScratch(bool(ival));
    4362 break;
    4363 case SCIP_LPPAR_LPINFO:
    4364 assert(ival == TRUE || ival == FALSE);
    4365 lpi->spx->setLpInfo(bool(ival));
    4366 break;
    4367 case SCIP_LPPAR_LPITLIM:
    4368 assert( ival >= 0 );
    4369 /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
    4370 if( ival >= INT_MAX )
    4371 ival = -1;
    4372 (void) lpi->spx->setIntParam(SoPlex::ITERLIMIT, ival);
    4373 break;
    4375 assert(ival == TRUE || ival == FALSE);
    4376#if SOPLEX_APIVERSION < 13
    4377 assert(ival == TRUE || ival == FALSE);
    4378#else
    4379 assert(ival == 1 || ival == 0 || ival == 2);
    4380#endif
    4381 (void) lpi->spx->setIntParam(SoPlex::SIMPLIFIER, ival);
    4382 break;
    4383 case SCIP_LPPAR_PRICING:
    4384 lpi->pricing = (SCIP_PRICING)ival;
    4385 switch( lpi->pricing )
    4386 {
    4388 case SCIP_PRICING_AUTO:
    4389 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_AUTO);
    4390 break;
    4391 case SCIP_PRICING_FULL:
    4392 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
    4393 break;
    4395 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_PARMULT);
    4396 break;
    4397 case SCIP_PRICING_STEEP:
    4398 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
    4399 break;
    4401 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_QUICKSTEEP);
    4402 break;
    4403 case SCIP_PRICING_DEVEX:
    4404 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_DEVEX);
    4405 break;
    4406 default:
    4407 return SCIP_LPERROR;
    4408 }
    4409 break;
    4410 case SCIP_LPPAR_SCALING:
    4411 assert(ival >= 0 && ival <= 2);
    4412 if( ival == 0 )
    4413 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_OFF);
    4414 else if( ival == 1 )
    4415 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_BIEQUI);
    4416 else
    4417#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
    4418 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_LEASTSQ);
    4419#else
    4420 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_GEO8);
    4421#endif
    4422
    4423 break;
    4424#if SOPLEX_VERSION >= 201
    4425 case SCIP_LPPAR_TIMING:
    4426 assert(ival >= 0 && ival < 3);
    4427 (void) lpi->spx->setIntParam(SoPlex::TIMER, ival);
    4428 break;
    4429#endif
    4430#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
    4432 lpi->spx->setRandomSeed((unsigned long)(long)ival);
    4433 break;
    4434#endif
    4435#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION >= 221 && SOPLEX_SUBVERSION >= 3)
    4437 assert(ival >= 0 && ival < 3);
    4438 (void) lpi->spx->setIntParam(SoPlex::SOLUTION_POLISHING, ival);
    4439 break;
    4440#endif
    4441#if SOPLEX_APIVERSION >= 1
    4443 assert(ival >= 0);
    4444 (void) lpi->spx->setIntParam(SoPlex::FACTOR_UPDATE_MAX, ival);
    4445 break;
    4446#endif
    4447
    4448 default:
    4449 return SCIP_PARAMETERUNKNOWN;
    4450 } /*lint !e788*/
    4451
    4452 return SCIP_OKAY;
    4453}
    4454
    4455/** gets floating point parameter of LP */
    4457 SCIP_LPI* lpi, /**< LP interface structure */
    4458 SCIP_LPPARAM type, /**< parameter number */
    4459 SCIP_Real* dval /**< buffer to store the parameter value */
    4460 )
    4461{
    4462 SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
    4463
    4464 assert(lpi != NULL);
    4465 assert(lpi->spx != NULL);
    4466 assert(dval != NULL);
    4467
    4468 switch( type )
    4469 {
    4470 case SCIP_LPPAR_FEASTOL:
    4471 *dval = lpi->spx->feastol();
    4472 break;
    4474 *dval = lpi->spx->opttol();
    4475 break;
    4476 case SCIP_LPPAR_OBJLIM:
    4477 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
    4478 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_UPPER);
    4479 else
    4480 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_LOWER);
    4481 break;
    4482 case SCIP_LPPAR_LPTILIM:
    4483 *dval = lpi->spx->realParam(SoPlex::TIMELIMIT);
    4484 break;
    4486 *dval = lpi->spx->realParam(SoPlex::REPRESENTATION_SWITCH);
    4487 if( *dval >= SCIPlpiInfinity(lpi) )
    4488 *dval = -1.0;
    4489 break;
    4491 *dval = lpi->conditionlimit;
    4492 break;
    4494#if (SOPLEX_APIVERSION >= 9)
    4495 *dval = lpi->spx->realParam(SoPlex::MIN_MARKOWITZ);
    4496 break;
    4497#endif
    4498 default:
    4499 return SCIP_PARAMETERUNKNOWN;
    4500 } /*lint !e788*/
    4501
    4502 return SCIP_OKAY;
    4503}
    4504
    4505/** sets floating point parameter of LP */
    4507 SCIP_LPI* lpi, /**< LP interface structure */
    4508 SCIP_LPPARAM type, /**< parameter number */
    4509 SCIP_Real dval /**< parameter value */
    4510 )
    4511{
    4512 SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
    4513
    4514 assert(lpi != NULL);
    4515 assert(lpi->spx != NULL);
    4516
    4517 switch( type )
    4518 {
    4519 case SCIP_LPPAR_FEASTOL:
    4520 /* 0 < dval */
    4521 assert( dval > 0.0 );
    4522 lpi->spx->setFeastol(dval);
    4523 break;
    4525 /* 0 < dval */
    4526 assert( dval > 0.0 );
    4527 lpi->spx->setOpttol(dval);
    4528 break;
    4529 case SCIP_LPPAR_OBJLIM:
    4530 /* no restrictions on dval */
    4531 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
    4532 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_UPPER, dval);
    4533 else
    4534 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_LOWER, dval);
    4535 break;
    4536 case SCIP_LPPAR_LPTILIM:
    4537 assert( dval > 0.0 );
    4538 /* soplex requires 0 < dval < DEFAULT_INFINITY (= 1e100), -1 means unlimited */
    4539 (void) lpi->spx->setRealParam(SoPlex::TIMELIMIT, dval);
    4540 break;
    4542 /* 0 <= dval <= inf */
    4543 assert( dval >= 0.0 || dval == -1.0 );
    4544 if( dval == -1 )
    4545 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, SCIPlpiInfinity(lpi));
    4546 else
    4547 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, dval);
    4548 break;
    4550 lpi->conditionlimit = dval;
    4551 lpi->checkcondition = (dval >= 0.0);
    4552 break;
    4554#if (SOPLEX_APIVERSION >= 9)
    4555 /* 1e-4 <= dval <= 0.999 */
    4556 if( dval < 1e-4 )
    4557 dval = 1e-4;
    4558 else if( dval > 0.9999 )
    4559 dval = 0.9999;
    4560
    4561 (void) lpi->spx->setRealParam(SoPlex::MIN_MARKOWITZ, dval);
    4562 break;
    4563#endif
    4564 default:
    4565 return SCIP_PARAMETERUNKNOWN;
    4566 } /*lint !e788*/
    4567
    4568 return SCIP_OKAY;
    4569}
    4570
    4571/** interrupts the currently ongoing lp solve or disables the interrupt */
    4573 SCIP_LPI* lpi, /**< LP interface structure */
    4574 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
    4575 )
    4576{
    4577 assert(lpi != NULL);
    4578 assert(lpi->spx != NULL);
    4579
    4580 lpi->spx->setInterrupt(interrupt);
    4581
    4582 return SCIP_OKAY;
    4583}
    4584
    4585/**@} */
    4586
    4587
    4588
    4589
    4590/*
    4591 * Numerical Methods
    4592 */
    4593
    4594/**@name Numerical Methods */
    4595/**@{ */
    4596
    4597/** returns value treated as infinity in the LP solver */
    4599 SCIP_LPI* lpi /**< LP interface structure */
    4600 )
    4601{
    4602 assert(lpi != NULL);
    4603 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
    4604
    4605 return lpi->spx->realParam(SoPlex::INFTY);
    4606}
    4607
    4608/** checks if given value is treated as infinity in the LP solver */
    4610 SCIP_LPI* lpi, /**< LP interface structure */
    4611 SCIP_Real val
    4612 )
    4613{
    4614 assert(lpi != NULL);
    4615 SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
    4616
    4617 return (val >= lpi->spx->realParam(SoPlex::INFTY));
    4618}
    4619
    4620/**@} */
    4621
    4622
    4623
    4624
    4625/*
    4626 * File Interface Methods
    4627 */
    4628
    4629/**@name File Interface Methods */
    4630/**@{ */
    4631
    4632/** returns whether the given file exists */
    4633static
    4635 const char* filename /**< file name */
    4636 )
    4637{
    4638 FILE* f;
    4639
    4640 f = fopen(filename, "r");
    4641 if( f == NULL )
    4642 return FALSE;
    4643
    4644 fclose(f);
    4645
    4646 return TRUE;
    4647}
    4648
    4649/** reads LP from a file */
    4651 SCIP_LPI* lpi, /**< LP interface structure */
    4652 const char* fname /**< file name */
    4653 )
    4654{
    4655 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
    4656
    4657 assert(lpi != NULL);
    4658 assert(lpi->spx != NULL);
    4659 assert(fname != NULL);
    4660
    4661 assert( lpi->spx->preStrongbranchingBasisFreed() );
    4662
    4663 if( !fileExists(fname) )
    4664 return SCIP_NOFILE;
    4665
    4666 try
    4667 {
    4668 assert(lpi->spx->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL);
    4669 if( !lpi->spx->readFile(fname) )
    4670 return SCIP_READERROR;
    4671 }
    4672#ifndef NDEBUG
    4673 catch( const SPxException& x )
    4674 {
    4675 std::string s = x.what();
    4676 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    4677#else
    4678 catch( const SPxException& )
    4679 {
    4680#endif
    4681 return SCIP_READERROR;
    4682 }
    4683
    4684 return SCIP_OKAY;
    4685}
    4686
    4687/** writes LP to a file */
    4689 SCIP_LPI* lpi, /**< LP interface structure */
    4690 const char* fname /**< file name */
    4691 )
    4692{
    4693 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
    4694
    4695 assert(lpi != NULL);
    4696 assert(lpi->spx != NULL);
    4697 assert(fname != NULL);
    4698
    4699 try
    4700 {
    4701 (void) lpi->spx->writeFileReal(fname);
    4702 }
    4703#ifndef NDEBUG
    4704 catch( const SPxException& x )
    4705 {
    4706 std::string s = x.what();
    4707 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
    4708#else
    4709 catch( const SPxException& )
    4710 {
    4711#endif
    4712 return SCIP_WRITEERROR;
    4713 }
    4714
    4715 return SCIP_OKAY;
    4716}
    4717
    4718/**@} */
    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
    SCIP_Real * r
    Definition: circlepacking.c:59
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define EPSCEIL(x, eps)
    Definition: def.h:192
    #define SCIPABORT()
    Definition: def.h:327
    #define EPSFLOOR(x, eps)
    Definition: def.h:191
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
    Definition: lpi_spx.cpp:1601
    SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
    Definition: lpi_spx.cpp:3976
    SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_spx.cpp:3868
    SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
    Definition: lpi_spx.cpp:4456
    SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:4598
    SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3220
    SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
    Definition: lpi_spx.cpp:1674
    SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
    Definition: lpi_spx.cpp:4609
    SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:1524
    SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:4036
    SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3080
    SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3006
    SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
    Definition: lpi_spx.cpp:3534
    SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_spx.cpp:4095
    SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
    Definition: lpi_spx.cpp:1387
    SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
    Definition: lpi_spx.cpp:3386
    SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
    Definition: lpi_spx.cpp:4269
    SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_spx.cpp:4688
    SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
    Definition: lpi_spx.cpp:1023
    SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3121
    SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
    Definition: lpi_spx.cpp:4506
    SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
    Definition: lpi_spx.cpp:2806
    SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
    Definition: lpi_spx.cpp:4205
    SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
    Definition: lpi_spx.cpp:1935
    SCIP_Bool SCIPlpiHasPrimalSolve(void)
    Definition: lpi_spx.cpp:1044
    SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
    Definition: lpi_spx.cpp:2880
    SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
    Definition: lpi_spx.cpp:2290
    SCIP_Bool SCIPlpiHasBarrierSolve(void)
    Definition: lpi_spx.cpp:1060
    SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
    Definition: lpi_spx.cpp:3423
    SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
    Definition: lpi_spx.cpp:3293
    SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
    Definition: lpi_spx.cpp:1812
    int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3259
    SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:2503
    SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
    Definition: lpi_spx.cpp:2985
    SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
    Definition: lpi_spx.cpp:4236
    SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3233
    SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
    Definition: lpi_spx.cpp:1542
    SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3034
    SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
    Definition: lpi_spx.cpp:3272
    SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_spx.cpp:4114
    SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
    Definition: lpi_spx.cpp:1134
    SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
    Definition: lpi_spx.cpp:2836
    SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
    Definition: lpi_spx.cpp:2350
    SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3065
    SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_spx.cpp:4650
    SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
    Definition: lpi_spx.cpp:3481
    SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3134
    SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
    Definition: lpi_spx.cpp:4150
    SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3246
    SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
    Definition: lpi_spx.cpp:4085
    SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
    Definition: lpi_spx.cpp:4346
    const char * SCIPlpiGetSolverName(void)
    Definition: lpi_spx.cpp:998
    SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
    Definition: lpi_spx.cpp:3623
    SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3021
    SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_spx.cpp:3731
    SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
    Definition: lpi_spx.cpp:1465
    SCIP_RETCODE SCIPlpiGetCols(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lb, SCIP_Real *ub, int *nnonz, int *beg, int *ind, SCIP_Real *val)
    Definition: lpi_spx.cpp:1976
    SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_spx.cpp:3762
    SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
    Definition: lpi_spx.cpp:2192
    SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_spx.cpp:3794
    SCIP_RETCODE SCIPlpiGetRows(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhs, SCIP_Real *rhs, int *nnonz, int *beg, int *ind, SCIP_Real *val)
    Definition: lpi_spx.cpp:2086
    SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:2966
    const char * SCIPlpiGetSolverDesc(void)
    Definition: lpi_spx.cpp:1007
    SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
    Definition: lpi_spx.cpp:2488
    SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3147
    SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
    Definition: lpi_spx.cpp:2220
    SCIP_Bool SCIPlpiHasDualSolve(void)
    Definition: lpi_spx.cpp:1052
    SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:2517
    SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
    Definition: lpi_spx.cpp:2320
    SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
    Definition: lpi_spx.cpp:2910
    SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
    Definition: lpi_spx.cpp:3314
    SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3095
    SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
    Definition: lpi_spx.cpp:1355
    SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
    Definition: lpi_spx.cpp:2265
    SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    Definition: lpi_spx.cpp:4066
    SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3052
    SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:2474
    SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
    Definition: lpi_spx.cpp:1245
    SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:2460
    SCIP_RETCODE SCIPlpiLoadColLP(SCIP_LPI *lpi, SCIP_OBJSEN objsen, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
    Definition: lpi_spx.cpp:1167
    SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3108
    SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
    Definition: lpi_spx.cpp:3460
    SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
    Definition: lpi_spx.cpp:3706
    SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
    Definition: lpi_spx.cpp:1080
    void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:1015
    SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
    Definition: lpi_spx.cpp:1694
    SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
    Definition: lpi_spx.cpp:2248
    SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:3168
    SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
    Definition: lpi_spx.cpp:1918
    SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
    Definition: lpi_spx.cpp:4572
    SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
    Definition: lpi_spx.cpp:1327
    SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
    Definition: lpi_spx.cpp:1493
    SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
    Definition: lpi_spx.cpp:1738
    SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
    Definition: lpi_spx.cpp:1901
    SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    Definition: lpi_spx.cpp:3932
    SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
    Definition: lpi_spx.cpp:1650
    static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
    Definition: heur_twoopt.c:967
    interface methods for specific LP solvers
    SCIP_DUALPACKET ROWPACKET
    Definition: lpi_clp.cpp:128
    SCIP_DUALPACKET COLPACKET
    Definition: lpi_clp.cpp:126
    static void setIntParam(SCIP_LPI *lpi, int const param, int const parval)
    Definition: lpi_cpx.c:654
    #define FEASTOL
    Definition: lpi_qso.c:99
    static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
    Definition: lpi_spx.cpp:876
    #define NULL
    Definition: lpi_spx.cpp:142
    static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
    Definition: lpi_spx.cpp:892
    static SCIP_Bool fileExists(const char *filename)
    Definition: lpi_spx.cpp:4634
    #define SOPLEX_TRY(messagehdlr, x)
    Definition: lpi_spx.cpp:153
    static int rowpacketNum(int nrows)
    Definition: lpi_spx.cpp:867
    static SCIP_RETCODE spxSolve(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:2388
    SCIP_DUALPACKET ROWPACKET
    Definition: lpi_spx.cpp:762
    #define SOPLEX_VERBLEVEL
    Definition: lpi_spx.cpp:132
    static SCIP_RETCODE ensureCstatMem(SCIP_LPI *lpi, int num)
    Definition: lpi_spx.cpp:807
    static const char spxdesc[200]
    Definition: lpi_spx.cpp:981
    #define COLS_PER_PACKET
    Definition: lpi_spx.cpp:761
    static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
    Definition: lpi_spx.cpp:932
    SCIP_DUALPACKET COLPACKET
    Definition: lpi_spx.cpp:760
    static SCIP_RETCODE lpiStrongbranch(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
    Definition: lpi_spx.cpp:2533
    static SCIP_RETCODE ensureRstatMem(SCIP_LPI *lpi, int num)
    Definition: lpi_spx.cpp:829
    static int colpacketNum(int ncols)
    Definition: lpi_spx.cpp:858
    #define CHECK_SOPLEX_PARAM(x)
    Definition: lpi_spx.cpp:79
    #define SOPLEX_SUBVERSION
    Definition: lpi_spx.cpp:102
    static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
    Definition: lpi_spx.cpp:908
    #define SOPLEX_TRY_ABORT(x)
    Definition: lpi_spx.cpp:198
    #define ROWS_PER_PACKET
    Definition: lpi_spx.cpp:763
    static const char spxname[20]
    Definition: lpi_spx.cpp:979
    static void invalidateSolution(SCIP_LPI *lpi)
    Definition: lpi_spx.cpp:959
    #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 BMSallocMemoryCPP(size)
    Definition: memory.h:121
    #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 BMSfreeMemoryArrayNull(ptr)
    Definition: memory.h:148
    #define BMSallocMemory(ptr)
    Definition: memory.h:118
    void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
    Definition: message.c:427
    static int COI_CALLCONV Status(int MODSTA, int SOLSTA, int ITER, double OBJVAL, void *USRMEM)
    Definition: nlpi_conopt.c:551
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    @ ERROR
    Definition: reader_sm.c:68
    #define UNKNOWN
    Definition: sepa_mcf.c:4110
    SCIP_Real * norms
    Definition: lpi_qso.c:85
    COLPACKET * packcstat
    Definition: lpi_clp.cpp:136
    ROWPACKET * packrstat
    Definition: lpi_clp.cpp:137
    SCIP_Bool solved
    Definition: lpi_clp.cpp:114
    SPxSCIP * spx
    Definition: lpi_spx.cpp:770
    SCIP_Real conditionlimit
    Definition: lpi_cpx.c:174
    int * cstat
    Definition: lpi_clp.cpp:107
    int rstatsize
    Definition: lpi_clp.cpp:110
    int * rstat
    Definition: lpi_clp.cpp:108
    SCIP_PRICING pricing
    Definition: lpi_clp.cpp:112
    int cstatsize
    Definition: lpi_clp.cpp:109
    SCIP_MESSAGEHDLR * messagehdlr
    Definition: lpi_cpx.c:185
    SCIP_Bool checkcondition
    Definition: lpi_cpx.c:175
    @ 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_Pricing SCIP_PRICING
    Definition: type_lpi.h:86
    enum SCIP_LPParam SCIP_LPPARAM
    Definition: type_lpi.h:73
    @ SCIP_LPSOLQUALITY_EXACTCONDITION
    Definition: type_lpi.h:102
    @ SCIP_LPSOLQUALITY_ESTIMCONDITION
    Definition: type_lpi.h:101
    @ SCIP_LPPAR_PRICING
    Definition: type_lpi.h:54
    @ SCIP_LPPAR_REFACTOR
    Definition: type_lpi.h:71
    @ SCIP_LPPAR_LPINFO
    Definition: type_lpi.h:55
    @ SCIP_LPPAR_POLISHING
    Definition: type_lpi.h:70
    @ SCIP_LPPAR_SCALING
    Definition: type_lpi.h:52
    @ SCIP_LPPAR_TIMING
    Definition: type_lpi.h:68
    @ SCIP_LPPAR_LPTILIM
    Definition: type_lpi.h:61
    @ SCIP_LPPAR_PRESOLVING
    Definition: type_lpi.h:53
    @ SCIP_LPPAR_CONDITIONLIMIT
    Definition: type_lpi.h:67
    @ SCIP_LPPAR_RANDOMSEED
    Definition: type_lpi.h:69
    @ 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_ROWREPSWITCH
    Definition: type_lpi.h:63
    @ 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
    enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
    Definition: type_lpi.h:104
    @ SCIP_OBJSEN_MAXIMIZE
    Definition: type_lpi.h:42
    @ SCIP_OBJSEN_MINIMIZE
    Definition: type_lpi.h:43
    enum SCIP_ObjSen SCIP_OBJSEN
    Definition: type_lpi.h:45
    @ SCIP_LPERROR
    Definition: type_retcode.h:49
    @ SCIP_NOFILE
    Definition: type_retcode.h:47
    @ SCIP_READERROR
    Definition: type_retcode.h:45
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_PARAMETERUNKNOWN
    Definition: type_retcode.h:55
    @ SCIP_WRITEERROR
    Definition: type_retcode.h:46
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63