Scippy

    SCIP

    Solving Constraint Integer Programs

    lpi_highs.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_highs.cpp
    26 * @ingroup LPIS
    27 * @brief LP interface for HiGHS 1.4 and higher
    28 * @author Ambros Gleixner
    29 * @author Julian Hall
    30 * @author Alexander Hoen
    31 * @author Gioni Mexi
    32 *
    33 * This is an implementation of SCIP's LP interface for the open-source solver HiGHS.
    34 *
    35 * The most important open todos are:
    36 * - tune pricing strategy
    37 * - tune and activate primal simplex
    38 * - tune and activate parallel dual simplex
    39 */
    40
    41/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    42
    43#include <cassert>
    44#include <cstdlib>
    45#include <string>
    46#include <vector>
    47
    48#include <Highs.h>
    49
    50#include <lp_data/HighsLpUtils.h>
    51
    52#include "lpi/lpi.h"
    53#include "scip/bitencode.h"
    54#include "scip/pub_message.h"
    55#include "scip/type_lp.h"
    56
    57/* #define HIGHS_DEBUGLEVEL kHighsDebugLevelExpensive */
    58/* #define HIGHS_LOGDEVLEVEL kHighsLogDevLevelVerbose */
    59
    60/*
    61 * Macros, structs, etc.
    62 */
    63
    64#define HIGHS_relDiff(val1, val2) ( ((val1)-(val2))/(MAX3(1.0,REALABS(val1),REALABS(val2))) )
    65
    66/** Macro for a single HiGHS call for which exceptions have to be caught. We make no distinction between different
    67 * exception types, e.g., between memory allocation and other exceptions. Additionally, we check if HiGHS returns kOk
    68 * as status and return an LP error if not.
    69 */
    70#define HIGHS_CALL(x) do \
    71 { \
    72 try \
    73 { \
    74 HighsStatus _restat_; /*lint -e{506,774}*/ \
    75 (_restat_ = (x)); \
    76 if( _restat_ == HighsStatus::kWarning ) \
    77 { \
    78 SCIPerrorMessage("Warning in HiGHS function call\n"); \
    79 return SCIP_LPERROR; \
    80 } \
    81 else if( _restat_ != HighsStatus::kOk ) \
    82 { \
    83 SCIPerrorMessage("Error in HiGHS function call\n"); \
    84 return SCIP_LPERROR; \
    85 } \
    86 } \
    87 catch( std::exception & E ) \
    88 { \
    89 std::string s = E.what(); \
    90 SCIPerrorMessage( "HiGHS threw an exception: %s\n", s.c_str()); \
    91 return SCIP_LPERROR; \
    92 } \
    93 catch( ... ) \
    94 { \
    95 SCIPerrorMessage("HiGHS threw an unidentified exception\n"); \
    96 return SCIP_LPERROR; \
    97 } \
    98 } \
    99 while( FALSE )
    100
    101/** A relaxed version of HIGHS_CALL that accepts status kWarning. */
    102#define HIGHS_CALL_WITH_WARNING(x) do \
    103 { \
    104 try \
    105 { \
    106 HighsStatus _restat_; /*lint -e{506,774}*/ \
    107 (_restat_ = (x)); \
    108 if( _restat_ != HighsStatus::kOk && _restat_ != HighsStatus::kWarning ) \
    109 { \
    110 SCIPerrorMessage("Error in HiGHS in function call (returned %d)\n", \
    111 int(_restat_)); \
    112 return SCIP_LPERROR; \
    113 } \
    114 } \
    115 catch( std::exception & E ) \
    116 { \
    117 std::string s = E.what(); \
    118 SCIPerrorMessage( "HiGHS threw an exception: %s\n", s.c_str()); \
    119 return SCIP_LPERROR; \
    120 } \
    121 catch( ... ) \
    122 { \
    123 SCIPerrorMessage("HiGHS threw an unidentified exception\n"); \
    124 return SCIP_LPERROR; \
    125 } \
    126 } \
    127 while( FALSE )
    128
    129/** SCIP's HiGHS class */
    130class HighsSCIP : public Highs
    131{
    132 bool _lpinfo;
    133 char* _probname;
    134 SCIP_MESSAGEHDLR* _messagehdlr; /**< messagehdlr handler for printing messages, or NULL */
    135
    136public:
    137
    139 SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
    140 const char* probname = NULL /**< name of problem */
    141 )
    142 : _lpinfo(false),
    143 _probname(NULL),
    144 _messagehdlr(messagehdlr)
    145 {
    146 /* TODO set problem name by using an internal function */
    147 }
    148
    149 virtual ~HighsSCIP()
    150 {
    151 /* TODO free problem name */
    152 }
    153};
    154
    155/** LP interface struct for HiGHS */
    156struct SCIP_LPi
    157{
    158 HighsSCIP* highs; /**< HiGHS problem class */
    159 int* cstat; /**< array for storing column basis status */
    160 int* rstat; /**< array for storing row basis status */
    161 int cstatsize; /**< size of cstat array */
    162 int rstatsize; /**< size of rstat array */
    163 int nthreads; /**< number of threads to be used */
    164 SCIP_Bool fromscratch; /**< shall solves be performed from scratch? */
    165 SCIP_Bool solved; /**< was the current LP solved? */
    166 SCIP_Bool presolve; /**< shall the current LP be presolved? */
    167 SCIP_PRICING pricing; /**< SCIP pricing setting */
    168 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler for printing messages, or NULL */
    169};
    170
    171typedef SCIP_DUALPACKET COLPACKET; /** each column needs two bits of information (basic/on_lower/on_upper) */
    172#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
    173typedef SCIP_DUALPACKET ROWPACKET; /** each row needs two bit of information (basic/on_lower/on_upper) */
    174#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
    175
    176/** LPi state stores basis information */
    177struct SCIP_LPiState
    178{
    179 int ncols; /**< number of LP columns */
    180 int nrows; /**< number of LP rows */
    181 COLPACKET* packcstat; /**< column basis status in compressed form */
    182 ROWPACKET* packrstat; /**< row basis status in compressed form */
    183};
    184
    185/*
    186 * dynamic memory arrays
    187 */
    188
    189/** resizes cstat array to have at least num entries */
    190static
    192 SCIP_LPI* lpi, /**< LP interface structure */
    193 int num /**< minimal number of entries in array */
    194 )
    195{
    196 SCIPdebugMessage("calling ensureCstatMem()\n");
    197
    198 assert(lpi != NULL);
    199
    200 if( num > lpi->cstatsize )
    201 {
    202 int newsize;
    203 newsize = MAX( 2 * lpi->cstatsize, num );
    204 SCIP_ALLOC( BMSreallocMemoryArray( &lpi->cstat, newsize ) );
    205 lpi->cstatsize = newsize;
    206 }
    207 assert(num <= lpi->cstatsize);
    208
    209 return SCIP_OKAY;
    210}
    211
    212/** resizes rstat array to have at least num entries */
    213static
    215 SCIP_LPI* lpi, /**< LP interface structure */
    216 int num /**< minimal number of entries in array */
    217 )
    218{
    219 SCIPdebugMessage("calling ensureRstatMem()\n");
    220
    221 assert(lpi != NULL);
    222
    223 if( num > lpi->rstatsize )
    224 {
    225 int newsize;
    226
    227 newsize = MAX( 2 * lpi->rstatsize, num );
    228 SCIP_ALLOC( BMSreallocMemoryArray( &lpi->rstat, newsize ) );
    229 lpi->rstatsize = newsize;
    230 }
    231 assert(num <= lpi->rstatsize);
    232
    233 return SCIP_OKAY;
    234}
    235
    236/*
    237 * LPi state methods
    238 */
    239
    240/** returns the number of packets needed to store column packet information */
    241static
    243 int ncols /**< number of columns to store */
    244 )
    245{
    246 return (ncols + (int)COLS_PER_PACKET - 1) / (int)COLS_PER_PACKET;
    247}
    248
    249/** returns the number of packets needed to store row packet information */
    250static
    252 int nrows /**< number of rows to store */
    253 )
    254{
    255 return (nrows + (int)ROWS_PER_PACKET - 1) / (int)ROWS_PER_PACKET;
    256}
    257
    258/** store row and column basis status in a packed LPi state object */
    259static
    261 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
    262 const int* cstat, /**< basis status of columns in unpacked format */
    263 const int* rstat /**< basis status of rows in unpacked format */
    264 )
    265{
    266 assert(lpistate != NULL);
    267 assert(lpistate->packcstat != NULL);
    268 assert(lpistate->packrstat != NULL);
    269
    270 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
    271 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
    272}
    273
    274/** unpacks row and column basis status from a packed LPi state object */
    275static
    277 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
    278 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
    279 int* rstat /**< buffer for storing basis status of rows in unpacked format */
    280)
    281{
    282 assert(lpistate != NULL);
    283 assert(lpistate->packcstat != NULL);
    284 assert(lpistate->packrstat != NULL);
    285
    286 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
    287 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
    288}
    289
    290/** creates LPi state information object */
    291static
    293 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
    294 BMS_BLKMEM* blkmem, /**< block memory */
    295 int ncols, /**< number of columns to store */
    296 int nrows /**< number of rows to store */
    297 )
    298{
    299 assert(lpistate != NULL);
    300 assert(blkmem != NULL);
    301 assert(ncols >= 0);
    302 assert(nrows >= 0);
    303
    304 int nColPackets = colpacketNum(ncols);
    305 int nRowPackets = rowpacketNum(nrows);
    306
    307 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
    308 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
    309 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
    310
    311 return SCIP_OKAY;
    312}
    313
    314/** frees LPi state information */
    315static
    317 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
    318 BMS_BLKMEM* blkmem /**< block memory */
    319 )
    320{
    321 assert(blkmem != NULL);
    322 assert(lpistate != NULL);
    323 assert(*lpistate != NULL);
    324
    325 int nColPackets = colpacketNum((*lpistate)->ncols);
    326 int nRowPackets = rowpacketNum((*lpistate)->nrows);
    327
    328 BMSfreeBlockMemoryArray( blkmem, &(*lpistate)->packcstat, nColPackets );
    329 BMSfreeBlockMemoryArray( blkmem, &(*lpistate)->packrstat, nRowPackets );
    330 BMSfreeBlockMemory( blkmem, lpistate);
    331}
    332
    333
    334/*
    335 * local methods
    336 */
    337
    338/** marks the current LP to be unsolved */
    339static
    341 SCIP_LPI *lpi /**< LP interface structure */
    342 )
    343{
    344 assert(lpi != NULL);
    345 lpi->solved = FALSE;
    346}
    347
    348/** converts basis statuses */
    349static
    351 const int &stat
    352 )
    353{
    354 switch( stat )
    355 {
    357 return HighsBasisStatus::kLower;
    359 return HighsBasisStatus::kBasic;
    361 return HighsBasisStatus::kUpper;
    363 return HighsBasisStatus::kZero;
    364 default:
    365 assert( false );
    366 SCIPerrorMessage("Unknown Basis Status returned. Please use supported HiGHS version!\n");
    367 return HighsBasisStatus::kZero;
    368 }
    369}
    370
    371/** returns a string representation of the simplex strategy parameter */
    372static
    374 const int &strategy
    375 )
    376{
    377 switch( strategy )
    378 {
    379 case 0:
    380 return "Choose";
    381 case 1:
    382 return "Dual (serial)";
    383 case 2:
    384 return "Dual (PAMI)";
    385 case 3:
    386 return "Dual (SIP)";
    387 case 4:
    388 return "Primal";
    389 default:
    390 return "Unknown";
    391 }
    392}
    393
    394/** checks that matrix values are within range defined by HiGHS parameters */
    395static
    397 SCIP_LPI* lpi, /**< LP interface structure */
    398 SCIP_Real value /**< value of coefficient */
    399 )
    400{
    401#ifndef NDEBUG
    402 SCIP_Real small_matrix_value;
    403 SCIP_Real large_matrix_value;
    404
    405 HIGHS_CALL( lpi->highs->getOptionValue("small_matrix_value", small_matrix_value) );
    406 HIGHS_CALL( lpi->highs->getOptionValue("large_matrix_value", large_matrix_value) );
    407
    408 assert(value == 0.0 || fabs(value) > small_matrix_value);
    409 assert(fabs(value) < large_matrix_value);
    410#endif
    411
    412 return SCIP_OKAY;
    413}
    414
    415/** calls HiGHS to solve the LP with given settings */
    416static
    418 SCIP_LPI* lpi /**< LP interface structure */
    419 )
    420{
    421 std::string presolvestring;
    422
    423 assert(lpi != NULL);
    424 assert(lpi->highs != NULL);
    425
    426 if( lpi->fromscratch )
    427 {
    428 HIGHS_CALL( lpi->highs->clearSolver() );
    429 }
    430
    431 lpi->highs->zeroAllClocks();
    432
    433 HIGHS_CALL( lpi->highs->setOptionValue("presolve", lpi->presolve ? "on" : "off") );
    434 /* the optimization result may be reliable even if HiGHS returns a warning status, e.g., HiGHS always returns with a
    435 * warning status if the iteration limit was hit
    436 */
    437 HIGHS_CALL_WITH_WARNING( lpi->highs->run() );
    438
    439 HighsModelStatus model_status = lpi->highs->getModelStatus();
    440 switch( model_status )
    441 {
    442 /* solved or resource limit reached */
    443 case HighsModelStatus::kModelEmpty:
    444 case HighsModelStatus::kOptimal:
    445 case HighsModelStatus::kInfeasible:
    446 case HighsModelStatus::kUnboundedOrInfeasible:
    447 case HighsModelStatus::kUnbounded:
    448 case HighsModelStatus::kObjectiveBound:
    449 case HighsModelStatus::kTimeLimit:
    450 case HighsModelStatus::kIterationLimit:
    451#ifdef SCIP_DEBUG
    452 {
    453 int simplex_strategy = -1;
    454 HIGHS_CALL( lpi->highs->getOptionValue("simplex_strategy", simplex_strategy) );
    455 SCIPdebugMessage("HiGHS terminated with model status <%s> (%d) after simplex strategy <%s> (%d)\n",
    456 lpi->highs->modelStatusToString(model_status).c_str(), (int)model_status,
    457 simplexStrategyToString(simplex_strategy).c_str(), simplex_strategy);
    458 }
    459#endif
    460 break;
    461 /* errors or cases that should not occur in this LP interface */
    462 case HighsModelStatus::kNotset:
    463 case HighsModelStatus::kLoadError:
    464 case HighsModelStatus::kModelError:
    465 case HighsModelStatus::kPresolveError:
    466 case HighsModelStatus::kSolveError:
    467 case HighsModelStatus::kPostsolveError:
    468 case HighsModelStatus::kSolutionLimit:
    469 case HighsModelStatus::kObjectiveTarget:
    470 case HighsModelStatus::kUnknown:
    471 default:
    472 {
    473 int simplex_strategy = -1;
    474 HIGHS_CALL( lpi->highs->getOptionValue("simplex_strategy", simplex_strategy) );
    475 SCIPerrorMessage("HiGHS terminated with model status <%s> (%d) after simplex strategy <%s> (%d)\n",
    476 lpi->highs->modelStatusToString(model_status).c_str(), (int)model_status,
    477 simplexStrategyToString(simplex_strategy).c_str(), simplex_strategy);
    478 }
    479 return SCIP_LPERROR;
    480 }
    481
    482 /* if basis factorization is unavailable, this may be due to presolving; then solve again without presolve */
    483 HIGHS_CALL( lpi->highs->getOptionValue("presolve", presolvestring) );
    484 assert(presolvestring == "on" || presolvestring == "off"); /* values used in SCIPlpiSetIntpar() */
    485
    486 if( !lpi->highs->hasInvert() && presolvestring == "on" )
    487 {
    488 SCIP_RETCODE retcode;
    489
    490 SCIPdebugMessage("No inverse: running HiGHS again without presolve . . .\n");
    491 lpi->presolve = FALSE;
    492 retcode = lpiSolve(lpi);
    493 if( retcode != SCIP_OKAY )
    494 {
    495 HighsModelStatus model_status2 = lpi->highs->getModelStatus();
    496 SCIPerrorMessage("HiGHS terminated with model status <%s> (%d) after trying to recover inverse\n",
    497 lpi->highs->modelStatusToString(model_status2).c_str(), (int)model_status2);
    498 }
    499 lpi->presolve = TRUE;
    500 SCIP_CALL( retcode );
    501 }
    502
    503#if SCIP_DISABLED_CODE
    504 int highs_iterations;
    505 HIGHS_CALL( lpi->highs->getInfoValue("simplex_iteration_count", highs_iterations) );
    506 SCIPdebugMessage("After call of solve() f=%15g; Iter = %d; Status = %s\n",
    507 lpi->highs->getObjectiveValue(), highs_iterations,
    508 lpi->highs->modelStatusToString(lpi->highs->getModelStatus()).c_str());
    509#endif
    510
    511 lpi->solved = TRUE;
    512 return SCIP_OKAY;
    513}
    514
    515
    516/*
    517 * LP Interface Methods
    518 */
    519
    520/*
    521 * Miscellaneous Methods
    522 */
    523
    524/**@name Miscellaneous Methods */
    525/**@{ */
    526
    527static char highsname[30];
    528static char highsdesc[200];
    529
    530/** gets name and version of LP solver */
    532 void
    533 )
    534{
    535 SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
    536
    537 snprintf(highsname, 30, "HiGHS %d.%d.%d", HIGHS_VERSION_MAJOR, HIGHS_VERSION_MINOR, HIGHS_VERSION_PATCH);
    538 return highsname;
    539}
    540
    541/** gets description of LP solver (developer, webpage, ...) */
    543 void
    544 )
    545{
    546 SCIPdebugMessage("calling SCIPlpiGetSolverDesc()\n");
    547
    548 snprintf(highsdesc, 200, "%s [GitHash: %s]",
    549 "Linear optimization suite written and engineered at the University of Edinburgh",
    550 HIGHS_GITHASH);
    551 return highsdesc;
    552}
    553
    554/** gets pointer for LP solver - use only with great care */
    556 SCIP_LPI* lpi /**< pointer to an LP interface structure */
    557 )
    558{
    559 SCIPdebugMessage("calling SCIPlpiGetSolverPointer()\n");
    560 assert(lpi != NULL);
    561 return (void *) lpi->highs;
    562}
    563
    564/** pass integrality information about variables to the solver */
    566 SCIP_LPI *lpi, /**< pointer to an LP interface structure */
    567 int ncols, /**< length of integrality array */
    568 int *intInfo /**< integrality array (0: continuous, 1: integer) */
    569 )
    570{
    571 SCIPdebugMessage("calling SCIPlpiSetIntegralityInformation()\n");
    572
    573 assert( lpi != NULL );
    574 assert( ncols >= 0 );
    575 assert( ncols == 0 || intInfo != NULL );
    576
    577 SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet\n");
    578
    579 return SCIP_LPERROR;
    580}
    581
    582/** informs about availability of a primal simplex solving method */
    584 void
    585 )
    586{
    587 SCIPdebugMessage("calling SCIPlpiHasPrimalSolve()\n");
    588 return TRUE;
    589}
    590
    591/** informs about availability of a dual simplex solving method */
    593 void
    594)
    595{
    596 SCIPdebugMessage("calling SCIPlpiHasDualSolve()\n");
    597 return TRUE;
    598}
    599
    600/** informs about availability of a barrier solving method */
    602 void
    603 )
    604{
    605 SCIPdebugMessage("calling SCIPlpiHasBarrierSolve()\n");
    606 return FALSE;
    607}
    608
    609/**@} */
    610
    611/*
    612 * LPI Creation and Destruction Methods
    613 */
    614
    615/**@name LPI Creation and Destruction Methods */
    616/**@{ */
    617
    618/** creates an LP problem object */
    620 SCIP_LPI **lpi, /**< pointer to an LP interface structure */
    621 SCIP_MESSAGEHDLR *messagehdlr, /**< message handler to use for printing messages, or NULL */
    622 const char *name, /**< problem name */
    623 SCIP_OBJSEN objsen /**< objective sense */
    624 )
    625{
    626 SCIPdebugMessage("calling SCIPlpiCreate()\n");
    627
    629
    630 (*lpi)->highs = new HighsSCIP();
    631 HIGHS_CALL( (*lpi)->highs->clearModel() );
    632
    633 /* initialize LPI data */
    634 (*lpi)->cstat = NULL;
    635 (*lpi)->rstat = NULL;
    636 (*lpi)->cstatsize = 0;
    637 (*lpi)->rstatsize = 0;
    638 (*lpi)->nthreads = 1;
    639 (*lpi)->fromscratch = FALSE;
    640 (*lpi)->solved = FALSE;
    641 (*lpi)->presolve = TRUE;
    642 (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
    643 (*lpi)->messagehdlr = messagehdlr;
    644
    645 invalidateSolution(*lpi);
    646
    647 /* set objective sense */
    648 SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
    649
    650 /* set output and debug level */
    651 HIGHS_CALL( (*lpi)->highs->setOptionValue("output_flag", false) );
    652#ifdef HIGHS_LOGDEVLEVEL
    653 HIGHS_CALL( (*lpi)->highs->setOptionValue("log_dev_level", HIGHS_LOGDEVLEVEL) );
    654#endif
    655#ifdef HIGHS_DEBUGLEVEL
    656 HIGHS_CALL( (*lpi)->highs->setOptionValue("highs_debug_level", HIGHS_DEBUGLEVEL) );
    657#endif
    658
    659 /* set default scaling */
    661
    662 /* use presolve by default; HiGHS runs without presolving whenever a basis is available */
    664 HIGHS_CALL( (*lpi)->highs->setOptionValue("lp_presolve_requires_basis_postsolve", true) );
    665
    666 /* set default pricing */
    667 SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
    668
    669 return SCIP_OKAY;
    670}
    671
    672/** deletes an LP problem object */
    674 SCIP_LPI** lpi /**< pointer to an LP interface structure */
    675 )
    676{
    677 SCIPdebugMessage("calling SCIPlpiFree()\n");
    678
    679 assert(*lpi != NULL);
    680 assert((*lpi)->highs != NULL);
    681
    682 /* free model and solver using destructor */
    683 (*lpi)->highs->~HighsSCIP();
    684
    685 /* free basis arrays */
    686 BMSfreeMemoryArrayNull(&(*lpi)->cstat);
    687 BMSfreeMemoryArrayNull(&(*lpi)->rstat);
    688
    689 /* free LPI memory */
    690 BMSfreeMemory(lpi);
    691
    692 return SCIP_OKAY;
    693}
    694
    695/**@} */
    696
    697/*
    698 * Modification Methods
    699 */
    700
    701/**@name Modification Methods */
    702/**@{ */
    703
    704/** copies LP data with column matrix into LP solver */
    706 SCIP_LPI* lpi, /**< LP interface structure */
    707 SCIP_OBJSEN objsen, /**< objective sense */
    708 int ncols, /**< number of columns */
    709 const SCIP_Real* obj, /**< objective function values of columns */
    710 const SCIP_Real* lb, /**< lower bounds of columns */
    711 const SCIP_Real* ub, /**< upper bounds of columns */
    712 char** colnames, /**< column names, or NULL */
    713 int nrows, /**< number of rows */
    714 const SCIP_Real* lhs, /**< left hand sides of rows */
    715 const SCIP_Real* rhs, /**< right hand sides of rows */
    716 char** rownames, /**< row names, or NULL */
    717 int nnonz, /**< number of nonzero elements in the constraint matrix */
    718 const int* beg, /**< start index of each column in ind- and val-array */
    719 const int* ind, /**< row indices of constraint matrix entries */
    720 const SCIP_Real* val /**< values of constraint matrix entries */
    721 )
    722{
    723 SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
    724
    725 assert(lpi != NULL);
    726 assert(lpi->highs != NULL);
    727 assert(lhs != NULL);
    728 assert(rhs != NULL);
    729 assert(obj != NULL);
    730 assert(lb != NULL);
    731 assert(ub != NULL);
    732 assert(beg != NULL);
    733 assert(ind != NULL);
    734 assert(val != NULL);
    735
    736 assert(nrows >= 0);
    737 assert(ncols >= 0);
    738
    739 assert(nnonz == 0 || ( nrows > 0 && ncols > 0));
    740#ifndef NDEBUG
    741 for( int j = 0; j < nnonz; ++j )
    742 {
    743 assert(0 <= ind[j] && ind[j] < nrows);
    744 assert(val[j] != 0.0);
    745 SCIP_CALL( checkMatrixValue(lpi, val[j]) );
    746 }
    747#endif
    748
    749 int objectiveSenseInt = objsen == SCIP_OBJSEN_MAXIMIZE ? (int)ObjSense::kMaximize : (int)ObjSense::kMinimize;
    750 HIGHS_CALL( lpi->highs->passModel(ncols, nrows, nnonz, 1, objectiveSenseInt, 0, obj, lb, ub, lhs, rhs, beg, ind, val) );
    751
    752 assert((objsen == SCIP_OBJSEN_MAXIMIZE && lpi->highs->getLp().sense_ == ObjSense::kMaximize)
    753 || (objsen == SCIP_OBJSEN_MINIMIZE && lpi->highs->getLp().sense_ == ObjSense::kMinimize));
    754
    755 return SCIP_OKAY;
    756}
    757
    758/** adds columns to the LP */
    760 SCIP_LPI* lpi, /**< LP interface structure */
    761 int ncols, /**< number of columns to be added */
    762 const SCIP_Real* obj, /**< objective function values of new columns */
    763 const SCIP_Real* lb, /**< lower bounds of new columns */
    764 const SCIP_Real* ub, /**< upper bounds of new columns */
    765 char** colnames, /**< column names, or NULL */
    766 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
    767 const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
    768 const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
    769 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
    770 )
    771{
    772 SCIPdebugMessage("calling SCIPlpiAddCols()\n");
    773
    774 assert(lpi != NULL);
    775 assert(lpi->highs != NULL);
    776 assert(obj != NULL);
    777 assert(lb != NULL);
    778 assert(ub != NULL);
    779 assert(nnonz == 0 || beg != NULL);
    780 assert(nnonz == 0 || ind != NULL);
    781 assert(nnonz == 0 || val != NULL);
    782 assert(nnonz >= 0);
    783 assert(ncols >= 0);
    784 assert(ncols <= 0 || obj != NULL);
    785 assert(ncols <= 0 || lb != NULL);
    786 assert(ncols <= 0 || ub != NULL);
    787
    789
    790#ifndef NDEBUG
    791 if( nnonz > 0 )
    792 {
    793 /* perform check that no new rows are added - this is likely to be a mistake
    794 */
    795 int nrows = lpi->highs->getLp().num_row_;
    796 for( int j = 0; j < nnonz; ++j )
    797 {
    798 assert(0 <= ind[j] && ind[j] < nrows);
    799 assert(val[j] != 0.0);
    800 SCIP_CALL( checkMatrixValue(lpi, val[j]) );
    801 }
    802 }
    803
    804 /* HiGHS returns with a warning if values are within the zero tolerance, but seems to continue safely simply ignoring
    805 * them; in debug mode we stop, in optimized mode we accept this behavior */
    806 HIGHS_CALL( lpi->highs->addCols(ncols, obj, lb, ub, nnonz, beg, ind, val) );
    807#else
    808 HIGHS_CALL_WITH_WARNING( lpi->highs->addCols(ncols, obj, lb, ub, nnonz, beg, ind, val) );
    809#endif
    810
    811 return SCIP_OKAY;
    812}
    813
    814/** deletes all columns in the given range from LP */
    816 SCIP_LPI* lpi, /**< LP interface structure */
    817 int firstcol, /**< first column to be deleted */
    818 int lastcol /**< last column to be deleted */
    819 )
    820{
    821 assert(lpi != NULL);
    822 assert(lpi->highs != NULL);
    823 assert(firstcol >= 0);
    824 assert(lastcol < lpi->highs->getLp().num_col_);
    825 assert(firstcol <= lastcol + 1);
    826
    827 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
    828
    829 // handle empty range
    830 if( firstcol > lastcol )
    831 return SCIP_OKAY;
    832
    834 HIGHS_CALL( lpi->highs->deleteCols(firstcol, lastcol) );
    835
    836 assert(lpi->highs->getLp().num_col_ >= 0);
    837
    838 return SCIP_OKAY;
    839}
    840
    841/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
    843 SCIP_LPI* lpi, /**< LP interface structure */
    844 int* dstat /**< deletion status of columns
    845 * input: 1 if column should be deleted, 0 if not
    846 * output: new position of column, -1 if column was deleted */
    847 )
    848{
    849 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
    850
    851 assert(lpi != NULL);
    852 assert(dstat != NULL);
    853 assert(lpi->highs->getLp().num_col_ >= 0);
    854
    856
    857 HIGHS_CALL( lpi->highs->deleteCols(dstat) );
    858
    859 assert(lpi->highs->getLp().num_col_ >= 0);
    860 return SCIP_OKAY;
    861}
    862
    863/** adds rows to the LP */
    865 SCIP_LPI* lpi, /**< LP interface structure */
    866 int nrows, /**< number of rows to be added */
    867 const SCIP_Real* lhs, /**< left hand sides of new rows */
    868 const SCIP_Real* rhs, /**< right hand sides of new rows */
    869 char** rownames, /**< row names, or NULL */
    870 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
    871 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
    872 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
    873 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
    874 )
    875{
    876 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
    877
    878 assert(lpi != NULL);
    879 assert(lpi->highs != NULL);
    880 assert(nrows >= 0);
    881 assert(nrows <= 0 || lhs != NULL);
    882 assert(nrows <= 0 || rhs != NULL);
    883 assert(nnonz >= 0);
    884 assert(nnonz <= 0 || beg != NULL);
    885 assert(nnonz <= 0 || ind != NULL);
    886 assert(nnonz <= 0 || val != NULL);
    887
    889
    890#ifndef NDEBUG
    891 if( nnonz > 0 )
    892 {
    893 /* Perform check that no new columns are added - this is likely to be a mistake - and that the values are nonzero*/
    894 int ncols = lpi->highs->getLp().num_col_;
    895 for( int j = 0; j < nnonz; ++j )
    896 {
    897 assert(0 <= ind[j] && ind[j] < ncols);
    898 assert(val[j] != 0.0);
    899 SCIP_CALL( checkMatrixValue(lpi, val[j]) );
    900 }
    901 }
    902
    903 /* HiGHS returns with a warning if values are within the zero tolerance, but seems to continue safely simply ignoring
    904 * them; in debug mode we stop, in optimized mode we accept this behavior */
    905 HIGHS_CALL( lpi->highs->addRows(nrows, lhs, rhs, nnonz, beg, ind, val) );
    906#else
    907 HIGHS_CALL_WITH_WARNING( lpi->highs->addRows(nrows, lhs, rhs, nnonz, beg, ind, val) );
    908#endif
    909
    910 return SCIP_OKAY;
    911}
    912
    913/** deletes all rows in the given range from LP */
    915 SCIP_LPI* lpi, /**< LP interface structure */
    916 int firstrow, /**< first row to be deleted */
    917 int lastrow /**< last row to be deleted */
    918 )
    919{
    920 assert(lpi != NULL);
    921 assert(lpi->highs != NULL);
    922 assert(firstrow >= 0);
    923 assert(lastrow < lpi->highs->getLp().num_row_);
    924 assert(firstrow <= lastrow + 1);
    925
    926 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
    927
    928 // handle empty range
    929 if( firstrow > lastrow )
    930 return SCIP_OKAY;
    931
    933 HIGHS_CALL( lpi->highs->deleteRows(firstrow, lastrow) );
    934
    935 assert(lpi->highs->getLp().num_row_ >= 0);
    936 return SCIP_OKAY;
    937}
    938
    939/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
    941 SCIP_LPI* lpi, /**< LP interface structure */
    942 int* dstat /**< deletion status of rows
    943 * input: 1 if row should be deleted, 0 if not
    944 * output: new position of row, -1 if row was deleted */
    945 )
    946{
    947 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
    948
    949 assert(lpi != NULL);
    950 assert(dstat != NULL);
    951 assert(lpi->highs != NULL);
    952 assert(lpi->highs->getLp().num_row_ >= 0);
    953
    955
    956 HIGHS_CALL( lpi->highs->deleteRows(dstat) );
    957
    958 assert(lpi->highs->getLp().num_row_ >= 0);
    959
    960 return SCIP_OKAY;
    961}
    962
    963/** clears the whole LP */
    965 SCIP_LPI* lpi /**< LP interface structure */
    966 )
    967{
    968 SCIPdebugMessage("calling SCIPlpiClear()\n");
    969
    970 assert(lpi != NULL);
    971 assert(lpi->highs != NULL);
    972 assert(lpi->highs->getLp().num_row_ >= 0);
    973 assert(lpi->highs->getLp().num_col_ >= 0);
    974
    976
    977 HIGHS_CALL( lpi->highs->clearModel() );
    978 return SCIP_OKAY;
    979}
    980
    981/** changes lower and upper bounds of columns */
    983 SCIP_LPI* lpi, /**< LP interface structure */
    984 int ncols, /**< number of columns to change bounds for */
    985 const int* ind, /**< column indices or NULL if ncols is zero */
    986 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
    987 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
    988 )
    989{
    990 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
    991
    992 assert(lpi != NULL);
    993 assert(lpi->highs != NULL);
    994 assert(ind != NULL);
    995 assert(lb != NULL);
    996 assert(ub != NULL);
    997
    999
    1000 int i;
    1001
    1002 /* Check validity of data */
    1003 for( i = 0; i < ncols; ++i )
    1004 {
    1005 assert(0 <= ind[i] && ind[i] < lpi->highs->getLp().num_col_);
    1006
    1007 if( SCIPlpiIsInfinity(lpi, lb[i]) )
    1008 {
    1009 SCIPerrorMessage( "LP Error: fixing lower bound for variable %d to infinity\n", ind[i]);
    1010 return SCIP_LPERROR;
    1011 }
    1012 if( SCIPlpiIsInfinity(lpi, -ub[i]) )
    1013 {
    1014 SCIPerrorMessage( "LP Error: fixing upper bound for variable %d to -infinity\n", ind[i]);
    1015 return SCIP_LPERROR;
    1016 }
    1017 }
    1018
    1019 HIGHS_CALL( lpi->highs->changeColsBounds(ncols, ind, lb, ub) );
    1020
    1021 return SCIP_OKAY;
    1022}
    1023
    1024/** changes left and right hand sides of rows */
    1026 SCIP_LPI* lpi, /**< LP interface structure */
    1027 int nrows, /**< number of rows to change sides for */
    1028 const int* ind, /**< row indices */
    1029 const SCIP_Real* lhs, /**< new values for left hand sides */
    1030 const SCIP_Real* rhs /**< new values for right hand sides */
    1031 )
    1032{
    1033 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
    1034
    1035 assert(lpi != NULL);
    1036 assert(lpi->highs != NULL);
    1037 assert(ind != NULL);
    1038 assert(lhs != NULL);
    1039 assert(rhs != NULL);
    1040
    1041 int i;
    1042
    1043 invalidateSolution(lpi);
    1044
    1045 for( i = 0; i < nrows; ++i )
    1046 assert(0 <= ind[i] && ind[i] < lpi->highs->getLp().num_row_);
    1047
    1048 HIGHS_CALL( lpi->highs->changeRowsBounds(nrows, ind, lhs, rhs) );
    1049
    1050 return SCIP_OKAY;
    1051}
    1052
    1053/** changes a single coefficient */
    1055 SCIP_LPI* lpi, /**< LP interface structure */
    1056 int row, /**< row number of coefficient to change */
    1057 int col, /**< column number of coefficient to change */
    1058 SCIP_Real newval /**< new value of coefficient */
    1059 )
    1060{
    1061 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
    1062
    1063 assert(lpi != NULL);
    1064 assert(lpi->highs != NULL);
    1065
    1066 invalidateSolution(lpi);
    1067
    1068 SCIP_CALL( checkMatrixValue(lpi, newval) );
    1069 HIGHS_CALL( lpi->highs->changeCoeff(row, col, newval) );
    1070
    1071 return SCIP_OKAY;
    1072}
    1073
    1074/** changes the objective sense */
    1076 SCIP_LPI* lpi, /**< LP interface structure */
    1077 SCIP_OBJSEN objsen /**< new objective sense */
    1078 )
    1079{
    1080 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
    1081
    1082 assert(lpi != NULL);
    1083 assert(lpi->highs != NULL);
    1084
    1085 invalidateSolution(lpi);
    1086
    1087 HIGHS_CALL( lpi->highs->changeObjectiveSense(objsen == SCIP_OBJSEN_MINIMIZE ? ObjSense::kMinimize : ObjSense::kMaximize) );
    1088
    1089 return SCIP_OKAY;
    1090}
    1091
    1092/** changes objective values of columns in the LP */
    1094 SCIP_LPI* lpi, /**< LP interface structure */
    1095 int ncols, /**< number of columns to change objective value for */
    1096 const int* ind, /**< column indices to change objective value for */
    1097 const SCIP_Real* obj /**< new objective values for columns */
    1098 )
    1099{
    1100 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
    1101
    1102 assert(lpi != NULL);
    1103 assert(lpi->highs != NULL);
    1104 assert(ind != NULL);
    1105 assert(obj != NULL);
    1106
    1107 invalidateSolution(lpi);
    1108
    1109 HIGHS_CALL( lpi->highs->changeColsCost(ncols, ind, obj) );
    1110
    1111 return SCIP_OKAY;
    1112}
    1113
    1114/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
    1116 SCIP_LPI* lpi, /**< LP interface structure */
    1117 int row, /**< row number to scale */
    1118 SCIP_Real scaleval /**< scaling multiplier */
    1119 )
    1120{
    1121 SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
    1122
    1123 assert(lpi != NULL);
    1124 assert(lpi->highs != NULL);
    1125
    1126 invalidateSolution(lpi);
    1127
    1128 HIGHS_CALL( lpi->highs->scaleRow(row, scaleval) );
    1129
    1130 return SCIP_OKAY;
    1131}
    1132
    1133/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
    1134 * are divided by the scalar; for negative scalars, the column's bounds are switched
    1135 */
    1137 SCIP_LPI* lpi, /**< LP interface structure */
    1138 int col, /**< column number to scale */
    1139 SCIP_Real scaleval /**< scaling multiplier */
    1140 )
    1141{
    1142 SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
    1143
    1144 assert(lpi != NULL);
    1145 assert(scaleval != 0.0);
    1146
    1147 invalidateSolution(lpi);
    1148
    1149 HIGHS_CALL( lpi->highs->scaleCol(col, scaleval) );
    1150
    1151 return SCIP_OKAY;
    1152}
    1153
    1154/**@} */
    1155
    1156/*
    1157 * Data Accessing Methods
    1158 */
    1159
    1160/**@name Data Accessing Methods */
    1161/**@{ */
    1162
    1163/** gets the number of rows in the LP */
    1165 SCIP_LPI* lpi, /**< LP interface structure */
    1166 int* nrows /**< pointer to store the number of rows */
    1167 )
    1168{
    1169 SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
    1170
    1171 assert(lpi != NULL);
    1172 assert(lpi->highs != NULL);
    1173 assert(nrows != NULL);
    1174 *nrows = lpi->highs->getNumRow();
    1175 assert(*nrows >= 0);
    1176
    1177 return SCIP_OKAY;
    1178}
    1179
    1180/** gets the number of columns in the LP */
    1182 SCIP_LPI* lpi, /**< LP interface structure */
    1183 int* ncols /**< pointer to store the number of cols */
    1184 )
    1185{
    1186 SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
    1187
    1188 assert(lpi != NULL);
    1189 assert(lpi->highs != NULL);
    1190 assert(ncols != NULL);
    1191 *ncols = lpi->highs->getNumCol();
    1192 assert(*ncols >= 0);
    1193
    1194 return SCIP_OKAY;
    1195}
    1196
    1197/** gets the number of nonzero elements in the LP constraint matrix */
    1199 SCIP_LPI* lpi, /**< LP interface structure */
    1200 int* nnonz /**< pointer to store the number of nonzeros */
    1201 )
    1202{
    1203 SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
    1204
    1205 assert(lpi != NULL);
    1206 assert(lpi->highs != NULL);
    1207 assert(nnonz != NULL);
    1208 *nnonz = lpi->highs->getNumNz();
    1209 assert(*nnonz >= 0);
    1210
    1211 return SCIP_OKAY;
    1212}
    1213
    1214/** gets columns from LP problem object; the arrays have to be large enough to
    1215 * store all values Either both, lb and ub, have to be NULL, or both have to be
    1216 * non-NULL, either nnonz, beg, ind, and val have to be NULL, or all of them
    1217 * have to be non-NULL.
    1218 */
    1220 SCIP_LPI* lpi, /**< LP interface structure */
    1221 int firstcol, /**< first column to get from LP */
    1222 int lastcol, /**< last column to get from LP */
    1223 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
    1224 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
    1225 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
    1226 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
    1227 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
    1228 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
    1229 )
    1230{
    1231 int num_col;
    1232
    1233 assert(lpi != NULL);
    1234 assert(lpi->highs != NULL);
    1235 assert(firstcol >= 0);
    1236 assert(lastcol < lpi->highs->getLp().num_col_);
    1237 assert(firstcol <= lastcol + 1);
    1238
    1239 SCIPdebugMessage("calling SCIPlpiGetCols()\n");
    1240
    1241 HIGHS_CALL( lpi->highs->getCols(firstcol, lastcol, num_col, NULL, lb, ub, *nnonz, beg, ind, val) );
    1242
    1243 return SCIP_OKAY;
    1244}
    1245
    1246/** gets rows from LP problem object; the arrays have to be large enough to store all values.
    1247 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
    1248 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
    1249 */
    1251 SCIP_LPI* lpi, /**< LP interface structure */
    1252 int firstrow, /**< first row to get from LP */
    1253 int lastrow, /**< last row to get from LP */
    1254 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
    1255 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
    1256 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
    1257 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
    1258 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
    1259 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
    1260 )
    1261{
    1262 int num_row;
    1263
    1264 assert(lpi != NULL);
    1265 assert(lpi->highs != NULL);
    1266 assert(firstrow >= 0);
    1267 assert(lastrow < lpi->highs->getLp().num_row_);
    1268 assert(firstrow <= lastrow + 1);
    1269
    1270 SCIPdebugMessage("calling SCIPlpiGetRows()\n");
    1271
    1272 HIGHS_CALL( lpi->highs->getRows(firstrow, lastrow, num_row, lhs, rhs, *nnonz, beg, ind, val) );
    1273
    1274 return SCIP_OKAY;
    1275}
    1276
    1277/** gets column names */
    1279 SCIP_LPI* lpi, /**< LP interface structure */
    1280 int firstcol, /**< first column to get name from LP */
    1281 int lastcol, /**< last column to get name from LP */
    1282 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
    1283 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
    1284 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
    1285 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
    1286 )
    1287{
    1288 assert(lpi != NULL);
    1289 assert(firstcol >= 0);
    1290 assert(lastcol < lpi->highs->getLp().num_col_);
    1291 assert(firstcol <= lastcol + 1);
    1292
    1293 SCIPdebugMessage("calling SCIPlpiGetColNames()\n");
    1294
    1295 SCIPerrorMessage("SCIPlpiGetColNames() has not been implemented yet\n");
    1296
    1297 return SCIP_PLUGINNOTFOUND;
    1298}
    1299
    1300/** gets row names */
    1302 SCIP_LPI* lpi, /**< LP interface structure */
    1303 int firstrow, /**< first row to get name from LP */
    1304 int lastrow, /**< last row to get name from LP */
    1305 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
    1306 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
    1307 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
    1308 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
    1309 )
    1310{
    1311 assert(lpi != NULL);
    1312 assert(firstrow >= 0);
    1313 assert(lastrow < lpi->highs->getLp().num_row_);
    1314 assert(firstrow <= lastrow + 1);
    1315
    1316 SCIPdebugMessage("calling SCIPlpiGetRowNames()\n");
    1317
    1318 SCIPerrorMessage("SCIPlpiGetRowNames() has not been implemented yet\n");
    1319
    1320 return SCIP_PLUGINNOTFOUND;
    1321}
    1322
    1323/** gets the objective sense of the LP */
    1325 SCIP_LPI* lpi, /**< LP interface structure */
    1326 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
    1327 )
    1328{
    1329 SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
    1330
    1331 assert(lpi != NULL);
    1332 assert(lpi->highs != NULL);
    1333
    1334 *objsen = SCIP_OBJSEN_MINIMIZE;
    1335 if( lpi->highs->getLp().sense_ == ObjSense::kMaximize )
    1336 *objsen = SCIP_OBJSEN_MAXIMIZE;
    1337
    1338 return SCIP_OKAY;
    1339}
    1340
    1341/** gets objective coefficients from LP problem object */
    1343 SCIP_LPI* lpi, /**< LP interface structure */
    1344 int firstcol, /**< first column to get objective coefficient for */
    1345 int lastcol, /**< last column to get objective coefficient for */
    1346 SCIP_Real* vals /**< array to store objective coefficients */
    1347 )
    1348{
    1349 assert(lpi != NULL);
    1350 assert(lpi->highs != NULL);
    1351 assert(vals != NULL);
    1352 assert(firstcol >= 0);
    1353 assert(lastcol < lpi->highs->getLp().num_col_);
    1354 assert(firstcol <= lastcol + 1);
    1355
    1356 SCIPdebugMessage("calling SCIPlpiGetObj()\n");
    1357
    1358 for( int i = firstcol; i < lastcol + 1; ++i )
    1359 vals[i - firstcol] = lpi->highs->getLp().col_cost_[i];
    1360
    1361 return SCIP_OKAY;
    1362}
    1363
    1364/** gets current bounds from LP problem object */
    1366 SCIP_LPI* lpi, /**< LP interface structure */
    1367 int firstcol, /**< first column to get objective value for */
    1368 int lastcol, /**< last column to get objective value for */
    1369 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
    1370 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
    1371 )
    1372{
    1373 assert(lpi != NULL);
    1374 assert(lpi->highs != NULL);
    1375 assert(firstcol >= 0);
    1376 assert(lastcol < lpi->highs->getLp().num_col_);
    1377 assert(firstcol <= lastcol + 1);
    1378
    1379 SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
    1380
    1381 for( int i = firstcol; i < lastcol + 1; ++i )
    1382 {
    1383 if( lbs != NULL )
    1384 lbs[i - firstcol] = lpi->highs->getLp().col_lower_[i];
    1385 if( ubs != NULL )
    1386 ubs[i - firstcol] = lpi->highs->getLp().col_upper_[i];
    1387 }
    1388
    1389 return SCIP_OKAY;
    1390}
    1391
    1392/** gets current row sides from LP problem object */
    1394 SCIP_LPI* lpi, /**< LP interface structure */
    1395 int firstrow, /**< first row to get sides for */
    1396 int lastrow, /**< last row to get sides for */
    1397 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
    1398 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
    1399 )
    1400{
    1401 assert(lpi != NULL);
    1402 assert(lpi->highs != NULL);
    1403 assert(firstrow >= 0);
    1404 assert(lastrow < lpi->highs->getLp().num_row_);
    1405 assert(firstrow <= lastrow + 1);
    1406
    1407 SCIPdebugMessage("calling SCIPlpiGetSides()\n");
    1408
    1409 for( int i = firstrow; i < lastrow + 1; ++i )
    1410 {
    1411 if( lhss != NULL )
    1412 lhss[i - firstrow] = lpi->highs->getLp().row_lower_[i];
    1413 if( rhss != NULL )
    1414 rhss[i - firstrow] = lpi->highs->getLp().row_upper_[i];
    1415 }
    1416
    1417 return SCIP_OKAY;
    1418}
    1419
    1420/** gets a single coefficient */
    1422 SCIP_LPI* lpi, /**< LP interface structure */
    1423 int row, /**< row number of coefficient */
    1424 int col, /**< column number of coefficient */
    1425 SCIP_Real* val /**< pointer to store the value of the coefficient */
    1426)
    1427{
    1428 SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
    1429
    1430 assert(lpi != NULL);
    1431 assert(lpi->highs != NULL);
    1432 assert(0 <= col && col < lpi->highs->getNumCol());
    1433 assert(0 <= row && row < lpi->highs->getNumCol());
    1434 assert(val != NULL);
    1435
    1436 HIGHS_CALL( lpi->highs->getCoeff(row, col, *val) );
    1437 return SCIP_OKAY;
    1438}
    1439
    1440/**@} */
    1441
    1442/*
    1443 * Solving Methods
    1444 */
    1445
    1446/**@name Solving Methods */
    1447/**@{ */
    1448
    1449/** calls primal simplex to solve the LP */
    1451 SCIP_LPI* lpi /**< LP interface structure */
    1452 )
    1453{
    1454 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
    1455
    1456 assert(lpi != NULL);
    1457
    1458 /* HiGHS' primal simplex seems to still have performance issues, so we call the dual simplex instead. */
    1459#ifdef SCIP_WITH_HIGHSPRIMAL
    1460 HIGHS_CALL( lpi->highs->setOptionValue("parallel", "off") );
    1461 HIGHS_CALL( lpi->highs->setOptionValue("threads", 1) );
    1462 HIGHS_CALL( lpi->highs->setOptionValue("simplex_strategy", 4) );
    1463 SCIP_CALL( lpiSolve(lpi) );
    1464#else
    1466#endif
    1467
    1468 return SCIP_OKAY;
    1469}
    1470
    1471/** calls dual simplex to solve the LP */
    1473 SCIP_LPI* lpi /**< LP interface structure */
    1474 )
    1475{
    1476 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
    1477
    1478 assert(lpi != NULL);
    1479 assert(lpi->highs != NULL);
    1480
    1481 /* HiGHS still seems to get stuck sometimes in parallel mode, so we ignore nthreads for now. */
    1482#ifdef SCIP_WITH_HIGHSPARALLEL
    1483 if( lpi->nthreads == 0 || lpi->nthreads > 1 )
    1484 {
    1485 SCIPdebugMessage("Running HiGHS dual simplex in parallel with lpi->nthreads=%d\n", lpi->nthreads);
    1486 HIGHS_CALL( lpi->highs->setOptionValue("parallel", "on") );
    1487 HIGHS_CALL( lpi->highs->setOptionValue("threads", lpi->nthreads) ); /* note that also in HiGHS, 0 is the automatic setting */
    1488 HIGHS_CALL( lpi->highs->setOptionValue("simplex_strategy", 2) ); /* PAMI */
    1489 }
    1490 else
    1491#endif
    1492 {
    1493 SCIPdebugMessage("Running HiGHS dual simplex in serial with lpi->nthreads=%d\n", lpi->nthreads);
    1494 HIGHS_CALL( lpi->highs->setOptionValue("parallel", "off") );
    1495 HIGHS_CALL( lpi->highs->setOptionValue("threads", 1) );
    1496 HIGHS_CALL( lpi->highs->setOptionValue("simplex_strategy", 1) );
    1497 }
    1498
    1499 SCIP_CALL( lpiSolve(lpi) );
    1500
    1501 return SCIP_OKAY;
    1502}
    1503
    1504/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
    1506 SCIP_LPI* lpi, /**< LP interface structure */
    1507 SCIP_Bool crossover /**< perform crossover */
    1508 )
    1509{
    1510 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
    1511
    1512 assert(lpi != NULL);
    1513 assert(lpi->highs != NULL);
    1514
    1515 SCIPdebugMessage("HiGHS does not support Barrier - switching to dual simplex\n");
    1516 return SCIPlpiSolveDual(lpi);
    1517}
    1518
    1519/** start strong branching - call before any strong branching */
    1521 SCIP_LPI* lpi /**< LP interface structure */
    1522 )
    1523{
    1524 SCIPdebugMessage("calling SCIPlpiStartStrongbranch()\n");
    1525
    1526 assert(lpi != NULL);
    1527
    1528 /* no work necessary for current dummy implementation */
    1529 return SCIP_OKAY;
    1530}
    1531
    1532/** end strong branching - call after any strong branching */
    1534 SCIP_LPI* lpi /**< LP interface structure */
    1535 )
    1536{
    1537 SCIPdebugMessage("calling SCIPlpiEndStrongbranch()\n");
    1538
    1539 assert(lpi != NULL);
    1540
    1541 /* no work necessary for current dummy implementation */
    1542 return SCIP_OKAY;
    1543}
    1544
    1545/** performs strong branching iterations on one @b fractional candidate */
    1547 SCIP_LPI* lpi, /**< LP interface structure */
    1548 int col, /**< column to apply strong branching on */
    1549 SCIP_Real psol, /**< fractional current primal solution value of column */
    1550 int itlim, /**< iteration limit for strong branchings */
    1551 SCIP_Real* down, /**< stores dual bound after branching column down */
    1552 SCIP_Real* up, /**< stores dual bound after branching column up */
    1553 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
    1554 * otherwise, it can only be used as an estimate value */
    1555 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
    1556 * otherwise, it can only be used as an estimate value */
    1557 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    1558 )
    1559{
    1560 SCIPdebugMessage("calling SCIPlpiStrongbranchFrac()\n");
    1561
    1562 assert(lpi != NULL);
    1563 assert(down != NULL);
    1564 assert(up != NULL);
    1565 assert(downvalid != NULL);
    1566 assert(upvalid != NULL);
    1567
    1568 /* This is a dummy implementation to satisfy the test suite. It does not perform actual strong branching. */
    1569 SCIP_Real dualbound = (lpi->highs->getLp().sense_ == ObjSense::kMinimize
    1570 ? -SCIPlpiInfinity(lpi) : SCIPlpiInfinity(lpi));
    1571
    1572 if( SCIPlpiIsOptimal(lpi) )
    1573 {
    1574 SCIP_CALL( SCIPlpiGetObjval(lpi, &dualbound) );
    1575 }
    1576
    1577 *down = *up = dualbound;
    1578 *downvalid = TRUE;
    1579 *upvalid = TRUE;
    1580
    1581 if( iter != NULL )
    1582 *iter = -1;
    1583
    1584 return SCIP_OKAY;
    1585}
    1586
    1587/** performs strong branching iterations on given @b fractional candidates */
    1589 SCIP_LPI* lpi, /**< LP interface structure */
    1590 int* cols, /**< columns to apply strong branching on */
    1591 int ncols, /**< number of columns */
    1592 SCIP_Real* psols, /**< fractional current primal solution values of columns */
    1593 int itlim, /**< iteration limit for strong branchings */
    1594 SCIP_Real* down, /**< stores dual bounds after branching columns down */
    1595 SCIP_Real* up, /**< stores dual bounds after branching columns up */
    1596 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
    1597 * otherwise, they can only be used as an estimate values */
    1598 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
    1599 * otherwise, they can only be used as an estimate values */
    1600 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    1601 )
    1602{
    1603 SCIPdebugMessage("calling SCIPlpiStrongbranchesFrac()\n");
    1604
    1605 assert(lpi != NULL);
    1606 assert(cols != NULL);
    1607 assert(down != NULL);
    1608 assert(up != NULL);
    1609 assert(downvalid != NULL);
    1610 assert(upvalid != NULL);
    1611
    1612 /* This is a dummy implementation to satisfy the test suite. It does not perform actual strong branching. */
    1613 SCIP_Real dualbound = (lpi->highs->getLp().sense_ == ObjSense::kMinimize
    1614 ? -SCIPlpiInfinity(lpi) : SCIPlpiInfinity(lpi));
    1615
    1616 if( SCIPlpiIsOptimal(lpi) )
    1617 {
    1618 SCIP_CALL( SCIPlpiGetObjval(lpi, &dualbound) );
    1619 }
    1620
    1621 for( int j = 0; j < ncols; ++j )
    1622 {
    1623 down[j] = up[j] = dualbound;
    1624 downvalid[j] = upvalid[j] = TRUE;
    1625 }
    1626
    1627 if( iter != NULL )
    1628 *iter = -1;
    1629
    1630 return SCIP_OKAY;
    1631}
    1632
    1633/** performs strong branching iterations on one candidate with @b integral value */
    1635 SCIP_LPI* lpi, /**< LP interface structure */
    1636 int col, /**< column to apply strong branching on */
    1637 SCIP_Real psol, /**< current integral primal solution value of column */
    1638 int itlim, /**< iteration limit for strong branchings */
    1639 SCIP_Real* down, /**< stores dual bound after branching column down */
    1640 SCIP_Real* up, /**< stores dual bound after branching column up */
    1641 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
    1642 * otherwise, it can only be used as an estimate value */
    1643 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
    1644 * otherwise, it can only be used as an estimate value */
    1645 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    1646 )
    1647{
    1648 SCIPdebugMessage("calling SCIPlpiStrongbranchInt()\n");
    1649
    1650 assert(lpi != NULL);
    1651 assert(down != NULL);
    1652 assert(up != NULL);
    1653 assert(downvalid != NULL);
    1654 assert(upvalid != NULL);
    1655
    1656 /* the dummy implementation works independently of primal values. */
    1657 SCIP_CALL( SCIPlpiStrongbranchFrac(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter) );
    1658 return SCIP_OKAY;
    1659}
    1660
    1661/** performs strong branching iterations on given candidates with @b integral values */
    1663 SCIP_LPI* lpi, /**< LP interface structure */
    1664 int* cols, /**< columns to apply strong branching on */
    1665 int ncols, /**< number of columns */
    1666 SCIP_Real* psols, /**< current integral primal solution values of columns */
    1667 int itlim, /**< iteration limit for strong branchings */
    1668 SCIP_Real* down, /**< stores dual bounds after branching columns down */
    1669 SCIP_Real* up, /**< stores dual bounds after branching columns up */
    1670 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
    1671 * otherwise, they can only be used as an estimate values */
    1672 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
    1673 * otherwise, they can only be used as an estimate values */
    1674 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
    1675 )
    1676{
    1677 SCIPdebugMessage("calling SCIPlpiStrongbranchesInt()\n");
    1678
    1679 assert(lpi != NULL);
    1680 assert(cols != NULL);
    1681 assert(down != NULL);
    1682 assert(up != NULL);
    1683 assert(downvalid != NULL);
    1684 assert(upvalid != NULL);
    1685
    1686 /* the dummy implementation works independently of primal values */
    1687 SCIP_CALL( SCIPlpiStrongbranchesFrac(lpi, cols, ncols, psols, itlim, down, up, downvalid, upvalid, iter) );
    1688 return SCIP_OKAY;
    1689}
    1690
    1691/**@} */
    1692
    1693/*
    1694 * Solution Information Methods
    1695 */
    1696
    1697/**@name Solution Information Methods */
    1698/**@{ */
    1699
    1700/** returns whether a solve method was called after the last modification of the
    1701 * LP */
    1703 SCIP_LPI* lpi /**< LP interface structure */
    1704 )
    1705{
    1706 SCIPdebugMessage("calling SCIPlpiWasSolved()\n");
    1707
    1708 assert(lpi != NULL);
    1709
    1710 return lpi->solved;
    1711}
    1712
    1713/** gets information about primal and dual feasibility of the current LP solution
    1714 *
    1715 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
    1716 * returns true. If the LP is changed, this information might be invalidated.
    1717 *
    1718 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
    1719 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
    1720 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
    1721 * the problem might actually be feasible).
    1722 */
    1724 SCIP_LPI* lpi, /**< LP interface structure */
    1725 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
    1726 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
    1727 )
    1728{
    1729 SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
    1730
    1731 assert(lpi != NULL);
    1732 assert(primalfeasible != NULL);
    1733 assert(dualfeasible != NULL);
    1734
    1735 *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
    1736 *dualfeasible = SCIPlpiIsDualFeasible(lpi);
    1737
    1738 return SCIP_OKAY;
    1739}
    1740
    1741/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
    1742 * this does not necessarily mean, that the solver knows and can return the primal ray
    1743 */
    1745 SCIP_LPI* lpi /**< LP interface structure */
    1746 )
    1747{
    1748 SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
    1749
    1750 assert(lpi != NULL);
    1751 assert(lpi->highs != NULL);
    1752
    1753 HighsModelStatus model_status = lpi->highs->getModelStatus();
    1754
    1755 return model_status == HighsModelStatus::kUnbounded || model_status == HighsModelStatus::kUnboundedOrInfeasible;
    1756}
    1757
    1758/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
    1759 * and the solver knows and can return the primal ray
    1760 */
    1762 SCIP_LPI* lpi /**< LP interface structure */
    1763 )
    1764{
    1765 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
    1766
    1767 assert(lpi != NULL);
    1768 assert(lpi->highs != NULL);
    1769
    1770 if( !SCIPlpiIsPrimalUnbounded(lpi) )
    1771 return FALSE;
    1772
    1773 /* HiGHS method does not work in this case, but we can easily construct an unbounded primal ray */
    1774 if( lpi->highs->getNumRow() == 0 )
    1775 return TRUE;
    1776
    1777 bool has_primal_ray = false;
    1778 HIGHS_CALL( lpi->highs->getPrimalRay(has_primal_ray, NULL) );
    1779 return has_primal_ray;
    1780}
    1781
    1782/** returns TRUE iff LP is proven to be primal unbounded */
    1784 SCIP_LPI* lpi /**< LP interface structure */
    1785 )
    1786{
    1787 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
    1788
    1789 assert(lpi != NULL);
    1790 assert(lpi->highs != NULL);
    1791
    1792 return lpi->highs->getModelStatus() == HighsModelStatus::kUnbounded;
    1793}
    1794
    1795/** returns TRUE iff LP is proven to be primal infeasible */
    1797 SCIP_LPI* lpi /**< LP interface structure */
    1798 )
    1799{
    1800 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
    1801
    1802 assert(lpi != NULL);
    1803 assert(lpi->highs != NULL);
    1804
    1805 HighsModelStatus model_status = lpi->highs->getModelStatus();
    1806
    1807 /* not sure how to query HiGHS in this case, but we can easily decide */
    1808 if( model_status == HighsModelStatus::kModelEmpty )
    1809 {
    1810 int numrow = lpi->highs->getNumRow();
    1811
    1812 assert(lpi->highs->getNumCol() == 0);
    1813
    1814 for( int i = 0; i < numrow; i++ )
    1815 {
    1816 if( lpi->highs->getLp().row_lower_[i] > 0.0 || lpi->highs->getLp().row_upper_[i] < 0.0 )
    1817 return TRUE;
    1818 }
    1819 return FALSE;
    1820 }
    1821
    1822 /* otherwise we rely on the model status */
    1823 const bool primal_infeasible =
    1824 model_status == HighsModelStatus::kInfeasible ||
    1825 model_status == HighsModelStatus::kUnboundedOrInfeasible;
    1826 return primal_infeasible;
    1827}
    1828
    1829/** returns TRUE iff LP is proven to be primal feasible */
    1831 SCIP_LPI* lpi /**< LP interface structure */
    1832 )
    1833{
    1834 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
    1835
    1836 assert(lpi != NULL);
    1837 assert(lpi->highs != NULL);
    1838
    1839 HighsModelStatus model_status = lpi->highs->getModelStatus();
    1840
    1841 /* not sure how to query HiGHS in this case, but we can easily decide */
    1842 if( model_status == HighsModelStatus::kModelEmpty )
    1843 {
    1844 int numrow = lpi->highs->getNumRow();
    1845
    1846 assert(lpi->highs->getNumCol() == 0);
    1847
    1848 for( int i = 0; i < numrow; i++ )
    1849 {
    1850 if( lpi->highs->getLp().row_lower_[i] > 0.0 || lpi->highs->getLp().row_upper_[i] < 0.0 )
    1851 return FALSE;
    1852 }
    1853 return TRUE;
    1854 }
    1855
    1856 /* otherwise we rely on the model status */
    1857 const bool primal_feasible =
    1858 model_status == HighsModelStatus::kOptimal ||
    1859 model_status == HighsModelStatus::kUnbounded;
    1860 return primal_feasible;
    1861}
    1862
    1863/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
    1864 * this does not necessarily mean, that the solver knows and can return the dual ray
    1865 */
    1867 SCIP_LPI* lpi /**< LP interface structure */
    1868 )
    1869{
    1870 SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
    1871
    1872 assert(lpi != NULL);
    1873
    1874 return !SCIPlpiIsPrimalFeasible(lpi);
    1875}
    1876
    1877/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
    1878 * and the solver knows and can return the dual ray
    1879 */
    1881 SCIP_LPI* lpi /**< LP interface structure */
    1882 )
    1883{
    1884 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
    1885
    1886 assert(lpi != NULL);
    1887 assert(lpi->highs != NULL);
    1888
    1889 HighsModelStatus model_status = lpi->highs->getModelStatus();
    1890
    1891 /* HiGHS does not implement this case, but we can easily decide */
    1892 if( model_status == HighsModelStatus::kModelEmpty )
    1893 return !SCIPlpiIsPrimalFeasible(lpi);
    1894
    1895 /* otherwise we rely on the model status */
    1896 bool has_dual_ray = false;
    1897 HIGHS_CALL( lpi->highs->getDualRay(has_dual_ray, NULL) );
    1898 return has_dual_ray;
    1899}
    1900
    1901/** returns TRUE iff LP is proven to be dual unbounded */
    1903 SCIP_LPI* lpi /**< LP interface structure */
    1904 )
    1905{
    1906 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
    1907
    1908 assert(lpi != NULL);
    1909 assert(lpi->highs != NULL);
    1910
    1912}
    1913
    1914/** returns TRUE iff LP is proven to be dual infeasible */
    1916 SCIP_LPI* lpi /**< LP interface structure */
    1917 )
    1918{
    1919 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
    1920
    1921 assert(lpi != NULL);
    1922 assert(lpi->highs != NULL);
    1923
    1924 HighsModelStatus model_status = lpi->highs->getModelStatus();
    1925 const bool dual_infeasible =
    1926 model_status == HighsModelStatus::kUnbounded ||
    1927 model_status == HighsModelStatus::kUnboundedOrInfeasible;
    1928 return dual_infeasible;
    1929}
    1930
    1931/** returns TRUE iff LP is proven to be dual feasible */
    1933 SCIP_LPI* lpi /**< LP interface structure */
    1934 )
    1935{
    1936 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
    1937
    1938 assert(lpi != NULL);
    1939 assert(lpi->highs != NULL);
    1940
    1941 HighsModelStatus model_status = lpi->highs->getModelStatus();
    1942
    1943 if( model_status == HighsModelStatus::kOptimal || model_status == HighsModelStatus::kModelEmpty )
    1944 return TRUE;
    1945 else if( model_status == HighsModelStatus::kUnbounded || model_status == HighsModelStatus::kUnboundedOrInfeasible )
    1946 return FALSE;
    1947
    1948 int num_dual_infeasibilities = 1;
    1949 HighsStatus status = lpi->highs->getInfoValue("num_dual_infeasibilities", num_dual_infeasibilities);
    1950 bool has_dual_feasible_sol = (status == HighsStatus::kOk) && (num_dual_infeasibilities == 0);
    1951 return has_dual_feasible_sol;
    1952}
    1953
    1954/** returns TRUE iff LP was solved to optimality */
    1956 SCIP_LPI* lpi /**< LP interface structure */
    1957 )
    1958{
    1959 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
    1960
    1961 assert(lpi != NULL);
    1962 assert(lpi->highs != NULL);
    1963
    1964 HighsModelStatus model_status = lpi->highs->getModelStatus();
    1965
    1966 if( model_status == HighsModelStatus::kModelEmpty )
    1967 return SCIPlpiIsPrimalFeasible(lpi);
    1968 else
    1969 {
    1970 assert(lpi->highs->getModelStatus() == HighsModelStatus::kOptimal || (!SCIPlpiIsPrimalFeasible(lpi) || !SCIPlpiIsDualFeasible(lpi)));
    1971 assert(lpi->highs->getModelStatus() != HighsModelStatus::kOptimal || (SCIPlpiIsPrimalFeasible(lpi) && SCIPlpiIsDualFeasible(lpi)));
    1972 return lpi->highs->getModelStatus() == HighsModelStatus::kOptimal;
    1973 }
    1974}
    1975
    1976/** returns TRUE iff current LP basis is stable */
    1978 SCIP_LPI* lpi /**< LP interface structure */
    1979 )
    1980{
    1981 SCIPdebugMessage("calling SCIPlpiIsStable()\n");
    1982
    1983 assert(lpi != NULL);
    1984 assert(lpi->highs != NULL);
    1985
    1986 /* if an objective limit is set and HiGHS claims that it is exceeded, we should check that this is indeed the case;
    1987 * if not this points at numerical instability; note that this aligns with an assert in lp.c */
    1988 if( SCIPlpiIsObjlimExc(lpi) )
    1989 {
    1990 SCIP_Real objlimit;
    1991 SCIP_Real objvalue;
    1992
    1993 HIGHS_CALL( lpi->highs->getOptionValue("objective_bound", objlimit) );
    1994 HIGHS_CALL( lpi->highs->getInfoValue("objective_function_value", objvalue) );
    1995
    1996 if( lpi->highs->getLp().sense_ == ObjSense::kMaximize )
    1997 {
    1998 objlimit *= -1.0;
    1999 objvalue *= -1.0;
    2000 }
    2001 if( !SCIPlpiIsInfinity(lpi, objlimit) && HIGHS_relDiff(objvalue, objlimit) < -1e-9 )
    2002 return FALSE;
    2003 }
    2004
    2005 return TRUE;
    2006}
    2007
    2008/** returns TRUE iff the objective limit was reached */
    2010 SCIP_LPI* lpi /**< LP interface structure */
    2011 )
    2012{
    2013 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
    2014
    2015 assert(lpi != NULL);
    2016 assert(lpi->highs != NULL);
    2017
    2018 return lpi->highs->getModelStatus() == HighsModelStatus::kObjectiveBound;
    2019}
    2020
    2021/** returns TRUE iff the iteration limit was reached */
    2023 SCIP_LPI* lpi /**< LP interface structure */
    2024 )
    2025{
    2026 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
    2027
    2028 assert(lpi != NULL);
    2029 assert(lpi->highs != NULL);
    2030
    2031 return lpi->highs->getModelStatus() == HighsModelStatus::kIterationLimit;
    2032}
    2033
    2034/** returns TRUE iff the time limit was reached */
    2036 SCIP_LPI* lpi /**< LP interface structure */
    2037 )
    2038{
    2039 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
    2040
    2041 assert(lpi != NULL);
    2042 assert(lpi->highs != NULL);
    2043
    2044 return lpi->highs->getModelStatus() == HighsModelStatus::kTimeLimit;
    2045}
    2046
    2047/** returns the internal solution status of the solver */
    2049 SCIP_LPI* lpi /**< LP interface structure */
    2050 )
    2051{
    2052 SCIPdebugMessage("calling SCIPlpiGetInternalStatus()\n");
    2053
    2054 assert(lpi != NULL);
    2055 assert(lpi->highs != NULL);
    2056
    2057 return (int) lpi->highs->getModelStatus();
    2058}
    2059
    2060/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
    2062 SCIP_LPI* lpi, /**< LP interface structure */
    2063 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
    2064 )
    2065{
    2066 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
    2067
    2068 assert(lpi != NULL);
    2069 assert(lpi->highs != NULL);
    2070
    2071 assert(success != NULL);
    2072
    2073 *success = TRUE;
    2074 return SCIP_OKAY;
    2075}
    2076
    2077/** gets objective value of solution */
    2079 SCIP_LPI* lpi, /**< LP interface structure */
    2080 SCIP_Real* objval /**< stores the objective value */
    2081 )
    2082{
    2083 SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
    2084
    2085 assert(lpi != NULL);
    2086 assert(lpi->highs != NULL);
    2087 assert(objval != NULL);
    2088
    2089 HIGHS_CALL( lpi->highs->getInfoValue("objective_function_value", *objval) );
    2090 assert(lpi->highs->getModelStatus() != HighsModelStatus::kModelEmpty || *objval == 0.0);
    2091
    2092 return SCIP_OKAY;
    2093}
    2094
    2095/** gets primal and dual solution vectors for feasible LPs
    2096 *
    2097 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
    2098 * SCIPlpiIsOptimal() returns true.
    2099 */
    2101 SCIP_LPI* lpi, /**< LP interface structure */
    2102 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
    2103 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
    2104 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
    2105 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
    2106 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
    2107 )
    2108{
    2109 SCIPdebugMessage("calling SCIPlpiGetSol()\n");
    2110
    2111 assert(lpi != NULL);
    2112 assert(lpi->highs != NULL);
    2113
    2114 int ncols;
    2115 int nrows;
    2116 int i;
    2117
    2118 if( objval != NULL )
    2119 {
    2120 HIGHS_CALL( lpi->highs->getInfoValue("objective_function_value", *objval) );
    2121 assert(lpi->highs->getModelStatus() != HighsModelStatus::kModelEmpty || *objval == 0.0);
    2122 }
    2123
    2124 const std::vector<double> &colValue = lpi->highs->getSolution().col_value;
    2125 const std::vector<double> &colDual = lpi->highs->getSolution().col_dual;
    2126 const std::vector<double> &rowValue = lpi->highs->getSolution().row_value;
    2127 const std::vector<double> &rowDual = lpi->highs->getSolution().row_dual;
    2128
    2129 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
    2130 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
    2131 if( colValue.size() != (size_t) ncols || colDual.size() != (size_t) ncols
    2132 || rowValue.size() != (size_t) nrows || rowDual.size() != (size_t) nrows )
    2133 {
    2134 SCIPmessagePrintWarning( lpi->messagehdlr, "In HiGHS the size of the columns values %d does not fit the number of columns %d\n", (int) colValue.size(), ncols);
    2135 SCIPmessagePrintWarning( lpi->messagehdlr, "In HiGHS the size of the dual values %d does not fit the number of columns %d\n", (int) colDual.size(), ncols);
    2136 SCIPmessagePrintWarning( lpi->messagehdlr, "In HiGHS the size of the rows values %d does not fit the number of rows %d\\n\"", (int) rowValue.size(), nrows);
    2137 SCIPmessagePrintWarning( lpi->messagehdlr, "In HiGHS the size of the dual row values %d does not fit the number of rows %d\\n\"", (int) rowDual.size(), nrows);
    2138 assert((int) rowValue.size() == nrows);
    2139 SCIPmessagePrintWarning( lpi->messagehdlr, "HiGHS returned solution vector of inconsistent dimension\n" );
    2140 return SCIP_LPERROR;
    2141 }
    2142
    2143 if( primsol != NULL )
    2144 for( i = 0; i < ncols; i++ )
    2145 primsol[i] = colValue[i];
    2146 if( dualsol != NULL )
    2147 for( i = 0; i < nrows; i++ )
    2148 dualsol[i] = rowDual[i];
    2149 if( activity != NULL )
    2150 for( i = 0; i < nrows; i++ )
    2151 activity[i] = rowValue[i];
    2152 if( redcost != NULL )
    2153 for( i = 0; i < ncols; i++ )
    2154 redcost[i] = colDual[i];
    2155
    2156 return SCIP_OKAY;
    2157}
    2158
    2159
    2160/** gets primal ray for unbounded LPs */
    2162 SCIP_LPI* lpi, /**< LP interface structure */
    2163 SCIP_Real* ray /**< primal ray */
    2164 )
    2165{
    2166 SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
    2167
    2168 bool success = false;
    2169
    2170 assert(lpi != NULL);
    2171 assert(lpi->highs != NULL);
    2172 assert(SCIPlpiHasPrimalRay(lpi));
    2173
    2174 /* HiGHS does not implement this case, but we can easily construct an unbounded primal ray */
    2175 if( lpi->highs->getNumRow() == 0 )
    2176 {
    2177 int numcol = lpi->highs->getNumCol();
    2178
    2179 for( int i = 0; i < numcol; i++ )
    2180 {
    2181 SCIP_Real minobj = lpi->highs->getLp().col_cost_[i];
    2182 if( lpi->highs->getLp().sense_ == ObjSense::kMaximize )
    2183 minobj = -minobj;
    2184
    2185 if( SCIPlpiIsInfinity(lpi, -lpi->highs->getLp().col_lower_[i]) && minobj > 0.0 )
    2186 {
    2187 ray[i] = -1.0;
    2188 success = true;
    2189 }
    2190 else if( SCIPlpiIsInfinity(lpi, lpi->highs->getLp().col_upper_[i]) && minobj < 0.0 )
    2191 {
    2192 ray[i] = 1.0;
    2193 success = true;
    2194 }
    2195 else
    2196 ray[i] = 0.0;
    2197 }
    2198 }
    2199 else
    2200 {
    2201 HIGHS_CALL( lpi->highs->getPrimalRay(success, ray) );
    2202 }
    2203
    2204 return success ? SCIP_OKAY : SCIP_LPERROR;
    2205}
    2206
    2207/** gets dual Farkas proof for infeasibility */
    2209 SCIP_LPI* lpi, /**< LP interface structure */
    2210 SCIP_Real* dualfarkas /**< dual farkas row multipliers */
    2211 )
    2212{
    2213 SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
    2214
    2215 assert(lpi != NULL);
    2216 assert(lpi->highs != NULL);
    2217 assert(dualfarkas != NULL);
    2218
    2219 HighsModelStatus model_status = lpi->highs->getModelStatus();
    2220
    2221 /* HiGHS does not implement this case, but we can easily construct an unbounded dual ray */
    2222 if( model_status == HighsModelStatus::kModelEmpty )
    2223 {
    2224 SCIP_Real dualdir = lpi->highs->getLp().sense_ == ObjSense::kMinimize ? 1.0 : -1.0;
    2225 int numrow = lpi->highs->getNumRow();
    2226
    2227 assert(lpi->highs->getNumCol() == 0);
    2228
    2229 for( int i = 0; i < numrow; i++ )
    2230 {
    2231 if( lpi->highs->getLp().row_lower_[i] > 0.0 )
    2232 dualfarkas[i] = dualdir;
    2233 else if( lpi->highs->getLp().row_upper_[i] < 0.0 )
    2234 dualfarkas[i] = -dualdir;
    2235 else
    2236 dualfarkas[i] = 0.0;
    2237 }
    2238
    2239 return SCIP_OKAY;
    2240 }
    2241
    2242 bool has_dual_ray = false;
    2243 HIGHS_CALL( lpi->highs->getDualRay(has_dual_ray, dualfarkas) );
    2244
    2245 return has_dual_ray ? SCIP_OKAY : SCIP_LPERROR;
    2246}
    2247
    2248/** gets the number of LP iterations of the last solve call */
    2250 SCIP_LPI* lpi, /**< LP interface structure */
    2251 int* iterations /**< pointer to store the number of iterations of the last solve call */
    2252 )
    2253{
    2254 SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
    2255
    2256 assert(lpi != NULL);
    2257 assert(lpi->highs != NULL);
    2258 assert(iterations != NULL);
    2259
    2260 *iterations = 0;
    2261 /* this may return with a warning if the last solve failed */
    2262 HIGHS_CALL_WITH_WARNING( lpi->highs->getInfoValue("simplex_iteration_count", *iterations) );
    2263 assert(*iterations >= 0);
    2264 return SCIP_OKAY;
    2265}
    2266
    2267/** gets information about the quality of an LP solution
    2268 *
    2269 * Such information is usually only available, if also a (maybe not optimal) solution is available.
    2270 * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
    2271 */
    2273 SCIP_LPI* lpi, /**< LP interface structure */
    2274 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
    2275 SCIP_Real* quality /**< pointer to store quality number */
    2276 )
    2277{
    2278 SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
    2279
    2280 assert(lpi != NULL);
    2281 assert(lpi->highs != NULL);
    2282 assert(quality != NULL);
    2283
    2284 *quality = SCIP_INVALID;
    2285
    2286 return SCIP_OKAY;
    2287}
    2288
    2289/**@} */
    2290
    2291/*
    2292 * LP Basis Methods
    2293 */
    2294
    2295/**@name LP Basis Methods */
    2296/**@{ */
    2297
    2298/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
    2300 SCIP_LPI* lpi, /**< LP interface structure */
    2301 int* cstat, /**< array to store column basis status, or NULL */
    2302 int* rstat /**< array to store row basis status, or NULL */
    2303 )
    2304{
    2305 SCIPdebugMessage("calling SCIPlpiGetBase()\n");
    2306
    2307 assert(lpi != NULL);
    2308 assert(lpi->highs != NULL);
    2309
    2310 if( cstat != NULL )
    2311 {
    2312 for( int i = 0; i < lpi->highs->getLp().num_col_; ++i )
    2313 cstat[i] = (int) lpi->highs->getBasis().col_status[i];
    2314 }
    2315 if( rstat != NULL )
    2316 {
    2317 for( int i = 0; i < lpi->highs->getLp().num_row_; ++i )
    2318 rstat[i] = (int) lpi->highs->getBasis().row_status[i];
    2319 }
    2320
    2321 return SCIP_OKAY;
    2322}
    2323
    2324/** sets current basis status for columns and rows */
    2326 SCIP_LPI* lpi, /**< LP interface structure */
    2327 const int* cstat, /**< array with column basis status */
    2328 const int* rstat /**< array with row basis status */
    2329 )
    2330{
    2331 SCIPdebugMessage("calling SCIPlpiSetBase()\n");
    2332
    2333 assert(lpi != NULL);
    2334 assert(lpi->highs != NULL);
    2335
    2336 HighsBasis local_highs_basis;
    2337
    2338 local_highs_basis.col_status.resize(lpi->highs->getLp().num_col_);
    2339 local_highs_basis.row_status.resize(lpi->highs->getLp().num_row_);
    2340
    2341 if( cstat != NULL )
    2342 {
    2343 for( int i = 0; i < lpi->highs->getLp().num_col_; ++i )
    2344 local_highs_basis.col_status[i] = basestatToHighsBasisStatus(cstat[i]);
    2345 }
    2346 if( rstat != NULL )
    2347 {
    2348 for( int i = 0; i < lpi->highs->getLp().num_row_; ++i )
    2349 local_highs_basis.row_status[i] = basestatToHighsBasisStatus(rstat[i]);
    2350 }
    2351 HIGHS_CALL( lpi->highs->setBasis(local_highs_basis) );
    2352
    2353 return SCIP_OKAY;
    2354}
    2355
    2356/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
    2358 SCIP_LPI* lpi, /**< LP interface structure */
    2359 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
    2360 )
    2361 {
    2362 SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
    2363
    2364 assert(lpi != NULL);
    2365 assert(lpi->highs != NULL);
    2366 assert(bind != NULL);
    2367
    2368 if( !lpi->highs->getBasis().valid )
    2369 {
    2370 SCIPdebugMessage( "HiGHS Basis is not valid in function call SCIPlpiGetBasisInd()\n" );
    2371 return SCIP_ERROR;
    2372 }
    2373 HIGHS_CALL( lpi->highs->getBasicVariables(bind) );
    2374
    2375 return SCIP_OKAY;
    2376}
    2377
    2378/** get row of inverse basis matrix B^-1
    2379 *
    2380 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
    2381 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
    2382 * see also the explanation in lpi.h.
    2383 */
    2385 SCIP_LPI* lpi, /**< LP interface structure */
    2386 int r, /**< row number */
    2387 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
    2388 int* inds, /**< array to store the non-zero indices, or NULL */
    2389 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    2390 * (-1: if we do not store sparsity information) */
    2391)
    2392{
    2393 SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
    2394
    2395 assert(lpi != NULL);
    2396 assert(lpi->highs != NULL);
    2397
    2398 if( lpi->highs->getBasisInverseRow(r, coef, ninds, inds) != HighsStatus::kOk )
    2399 {
    2401 }
    2402
    2403 HIGHS_CALL( lpi->highs->getBasisInverseRow(r, coef, ninds, inds) );
    2404 return SCIP_OKAY;
    2405}
    2406
    2407/** get column of inverse basis matrix B^-1
    2408 *
    2409 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
    2410 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
    2411 * see also the explanation in lpi.h.
    2412 */
    2414 SCIP_LPI* lpi, /**< LP interface structure */
    2415 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
    2416 * you have to call SCIPlpiGetBasisInd() to get the array which links the
    2417 * B^-1 column numbers to the row and column numbers of the LP!
    2418 * c must be between 0 and nrows-1, since the basis has the size
    2419 * nrows * nrows */
    2420 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
    2421 int* inds, /**< array to store the non-zero indices, or NULL */
    2422 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    2423 * (-1: if we do not store sparsity information) */
    2424 )
    2425{
    2426 SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
    2427
    2428 assert(lpi != NULL);
    2429 assert(lpi->highs != NULL);
    2430
    2431 if( lpi->highs->getBasisInverseCol(c, coef, ninds, inds) != HighsStatus::kOk )
    2432 {
    2434 }
    2435
    2436 HIGHS_CALL( lpi->highs->getBasisInverseCol(c, coef, ninds, inds) );
    2437
    2438 return SCIP_OKAY;
    2439}
    2440
    2441/** get row of inverse basis matrix times constraint matrix B^-1 * A
    2442 *
    2443 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
    2444 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
    2445 * see also the explanation in lpi.h.
    2446 */
    2448 SCIP_LPI* lpi, /**< LP interface structure */
    2449 int r, /**< row number */
    2450 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
    2451 SCIP_Real* coef, /**< vector to return coefficients of the row */
    2452 int* inds, /**< array to store the non-zero indices, or NULL */
    2453 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    2454 * (-1: if we do not store sparsity information) */
    2455 )
    2456{
    2457 SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
    2458
    2459 assert(lpi != NULL);
    2460 assert(lpi->highs != NULL);
    2461
    2462 if( lpi->highs->getReducedRow(r, coef, ninds, inds, binvrow) != HighsStatus::kOk )
    2463 {
    2465 }
    2466
    2467 HIGHS_CALL( lpi->highs->getReducedRow(r, coef, ninds, inds, binvrow) );
    2468
    2469 return SCIP_OKAY;
    2470}
    2471
    2472/** get dense column of inverse basis matrix times constraint matrix B^-1 * A
    2473 *
    2474 * @note The LP interface defines slack variables to have coefficient +1. This
    2475 * means that if, internally, the LP solver uses a -1 coefficient, then rows
    2476 * associated with slacks variables whose coefficient is -1, should be negated;
    2477 * see also the explanation in lpi.h.
    2478 */
    2480 SCIP_LPI* lpi, /**< LP interface structure */
    2481 int c, /**< column number */
    2482 SCIP_Real* coef, /**< vector to return coefficients of the column */
    2483 int* inds, /**< array to store the non-zero indices, or NULL */
    2484 int* ninds /**< pointer to store the number of non-zero indices, or NULL
    2485 * (-1: if we do not store sparsity information) */
    2486 )
    2487{
    2488 SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
    2489
    2490 assert(lpi != NULL);
    2491 assert(lpi->highs != NULL);
    2492
    2493 if( lpi->highs->getReducedColumn(c, coef, ninds, inds) != HighsStatus::kOk )
    2494 {
    2496 }
    2497
    2498 HIGHS_CALL( lpi->highs->getReducedColumn(c, coef, ninds, inds) );
    2499 return SCIP_OKAY;
    2500}
    2501
    2502/**@} */
    2503
    2504/*
    2505 * LP State Methods
    2506 */
    2507
    2508/**@name LP State Methods */
    2509/**@{ */
    2510
    2511/** stores LPi state (like basis information) into lpistate object */
    2513 SCIP_LPI* lpi, /**< LP interface structure */
    2514 BMS_BLKMEM* blkmem, /**< block memory */
    2515 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
    2516 )
    2517{
    2518 SCIPdebugMessage("calling SCIPlpiGetState()\n");
    2519
    2520 assert(blkmem != NULL);
    2521
    2522 assert(lpi != NULL);
    2523 assert(lpi->highs != NULL);
    2524 assert(lpistate != NULL);
    2525
    2526 int ncols;
    2527 int nrows;
    2528
    2529 ncols = lpi->highs->getLp().num_col_;
    2530 nrows = lpi->highs->getLp().num_row_;
    2531 assert(ncols >= 0);
    2532 assert(nrows >= 0);
    2533
    2534 /* allocate lpistate data */
    2535 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
    2536
    2537 /* allocate enough memory for storing uncompressed basis information */
    2538 SCIP_CALL( ensureCstatMem(lpi, ncols) );
    2539 SCIP_CALL( ensureRstatMem(lpi, nrows) );
    2540
    2541 /* get unpacked basis information */
    2542 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
    2543
    2544 /* pack LPi state data */
    2545 (*lpistate)->ncols = ncols;
    2546 (*lpistate)->nrows = nrows;
    2547 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
    2548
    2549 return SCIP_OKAY;
    2550}
    2551
    2552/** loads LPi state (like basis information) into solver; note that the LP might
    2553 * have been extended with additional columns and rows since the state was
    2554 * stored with SCIPlpiGetState()
    2555 */
    2557 SCIP_LPI* lpi, /**< LP interface structure */
    2558 BMS_BLKMEM* blkmem, /**< block memory */
    2559 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
    2560 )
    2561{
    2562 SCIPdebugMessage("calling SCIPlpiSetState()\n");
    2563
    2564 assert(lpi != NULL);
    2565 assert(lpi->highs != NULL);
    2566 assert(lpistate != NULL);
    2567
    2568 int lpncols;
    2569 int lpnrows;
    2570 int i;
    2571
    2572 lpncols = lpi->highs->getLp().num_col_;
    2573 lpnrows = lpi->highs->getLp().num_row_;
    2574 assert(lpistate->ncols <= lpncols);
    2575 assert(lpistate->nrows <= lpnrows);
    2576
    2577 /* allocate enough memory for storing uncompressed basis information */
    2578 SCIP_CALL( ensureCstatMem(lpi, lpncols) );
    2579 SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
    2580
    2581 /* unpack LPi state data */
    2582 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
    2583
    2584 /* extend the basis to the current LP beyond the previously existing columns */
    2585 for( i = lpistate->ncols; i < lpncols; ++i )
    2586 {
    2587 if( !SCIPlpiIsInfinity(lpi, -lpi->highs->getLp().col_lower_[i]) )
    2588 /* use finite lower bound */
    2589 lpi->cstat[i] = SCIP_BASESTAT_LOWER;
    2590 else if( !SCIPlpiIsInfinity(lpi, lpi->highs->getLp().col_upper_[i]) )
    2591 /* use finite upper bound */
    2592 lpi->cstat[i] = SCIP_BASESTAT_UPPER;
    2593 else
    2594 /* variable is free */
    2595 lpi->cstat[i] = SCIP_BASESTAT_ZERO;
    2596 }
    2597 for( i = lpistate->nrows; i < lpnrows; ++i )
    2598 lpi->rstat[i] = SCIP_BASESTAT_BASIC;
    2599
    2600 /* load basis information */
    2601 SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
    2602
    2603 return SCIP_OKAY;
    2604}
    2605
    2606/** clears current LPi state (like basis information) of the solver */
    2608 SCIP_LPI* lpi /**< LP interface structure */
    2609)
    2610{
    2611 SCIPdebugMessage("calling SCIPlpiClearState()\n");
    2612
    2613 assert(lpi != NULL);
    2614 assert(lpi->highs != NULL);
    2615
    2616 HIGHS_CALL( lpi->highs->clearSolver() );
    2617 return SCIP_OKAY;
    2618}
    2619
    2620/** frees LPi state information */
    2622 SCIP_LPI* lpi, /**< LP interface structure */
    2623 BMS_BLKMEM* blkmem, /**< block memory */
    2624 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
    2625)
    2626{
    2627 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
    2628
    2629 assert(lpi != NULL);
    2630 assert(lpistate != NULL);
    2631
    2632 if( *lpistate != NULL )
    2633 lpistateFree(lpistate, blkmem);
    2634
    2635 return SCIP_OKAY;
    2636}
    2637
    2638/** checks whether the given LP state contains simplex basis information */
    2640 SCIP_LPI* lpi, /**< LP interface structure */
    2641 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
    2642 )
    2643{
    2644 SCIPdebugMessage("calling SCIPlpiHasStateBasis()\n");
    2645 assert(lpi != NULL);
    2646 return TRUE;
    2647}
    2648
    2649/** reads LP state (like basis information from a file */
    2651 SCIP_LPI* lpi, /**< LP interface structure */
    2652 const char* fname /**< file name */
    2653)
    2654{
    2655 SCIPdebugMessage("calling SCIPlpiReadState()\n");
    2656
    2657 assert(lpi != NULL);
    2658 assert(lpi->highs != NULL);
    2659
    2660 HIGHS_CALL( lpi->highs->readBasis(fname) );
    2661 return SCIP_OKAY;
    2662}
    2663
    2664/** writes LPi state (i.e. basis information) to a file */
    2666 SCIP_LPI* lpi, /**< LP interface structure */
    2667 const char* fname /**< file name */
    2668)
    2669{
    2670 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
    2671
    2672 assert(lpi != NULL);
    2673 assert(lpi->highs != NULL);
    2674
    2675 HIGHS_CALL( lpi->highs->writeBasis(fname) );
    2676 return SCIP_OKAY;
    2677}
    2678
    2679/**@} */
    2680
    2681/*
    2682 * LP Pricing Norms Methods
    2683 */
    2684
    2685/**@name LP Pricing Norms Methods */
    2686/**@{ */
    2687
    2688/** stores LPi pricing norms information
    2689 * @todo Could storing norm information improve warm start performance in HiGHS?
    2690 */
    2692 SCIP_LPI* lpi, /**< LP interface structure */
    2693 BMS_BLKMEM* blkmem, /**< block memory */
    2694 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
    2695)
    2696{
    2697 SCIPdebugMessage("calling SCIPlpiGetNorms()\n");
    2698
    2699 assert(lpi != NULL);
    2700 assert(lpinorms != NULL);
    2701
    2702 (*lpinorms) = NULL;
    2703
    2704 return SCIP_OKAY;
    2705}
    2706
    2707/** loads LPi pricing norms into solver; note that the LP might have been extended with additional
    2708 * columns and rows since the state was stored with SCIPlpiGetNorms()
    2709 */
    2711 SCIP_LPI* lpi, /**< LP interface structure */
    2712 BMS_BLKMEM* blkmem, /**< block memory */
    2713 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
    2714 )
    2715{
    2716 SCIPdebugMessage("calling SCIPlpiSetNorms()\n");
    2717
    2718 assert(lpi != NULL);
    2719 assert(lpinorms == NULL);
    2720
    2721 /* no work necessary */
    2722 return SCIP_OKAY;
    2723}
    2724
    2725/** frees pricing norms information */
    2727 SCIP_LPI* lpi, /**< LP interface structure */
    2728 BMS_BLKMEM* blkmem, /**< block memory */
    2729 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
    2730 )
    2731{
    2732 SCIPdebugMessage("calling SCIPlpiFreeNorms()\n");
    2733
    2734 assert(lpi != NULL);
    2735 assert(lpinorms == NULL);
    2736
    2737 /* no work necessary */
    2738 return SCIP_OKAY;
    2739}
    2740
    2741/**@} */
    2742
    2743/*
    2744 * Parameter Methods
    2745 */
    2746
    2747/**@name Parameter Methods */
    2748/**@{ */
    2749
    2750/** gets integer parameter of LP */
    2752 SCIP_LPI* lpi, /**< LP interface structure */
    2753 SCIP_LPPARAM type, /**< parameter number */
    2754 int* ival /**< buffer to store the parameter value */
    2755 )
    2756{
    2757 SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
    2758
    2759 assert(lpi != NULL);
    2760 assert(lpi->highs != NULL);
    2761 assert(ival != NULL);
    2762
    2763 switch( type )
    2764 {
    2766 *ival = (int) lpi->fromscratch;
    2767 break;
    2768 case SCIP_LPPAR_LPINFO:
    2769 {
    2770 bool bool_ival;
    2771 HIGHS_CALL( lpi->highs->getOptionValue("output_flag", bool_ival) );
    2772 *ival = bool_ival;
    2773 }
    2774 break;
    2775 case SCIP_LPPAR_SCALING:
    2776 HIGHS_CALL( lpi->highs->getOptionValue("simplex_scale_strategy", *ival) );
    2777 assert(*ival == 0 || *ival == 2 || *ival == 4); /* values used in SCIPlpiSetIntpar() */
    2778 if( *ival <= 0 )
    2779 *ival = 0;
    2780 else if( *ival <= 2 )
    2781 *ival = 1;
    2782 else
    2783 *ival = 2;
    2784 break;
    2786 *ival = lpi->presolve;
    2787 break;
    2788 case SCIP_LPPAR_PRICING:
    2789 *ival = (int)lpi->pricing; /* store pricing method in LPI struct */
    2790 break;
    2791 case SCIP_LPPAR_THREADS:
    2792 *ival = lpi->nthreads;
    2793 break;
    2794 case SCIP_LPPAR_LPITLIM:
    2795 HIGHS_CALL( lpi->highs->getOptionValue("simplex_iteration_limit", *ival) );
    2796 break;
    2798 HIGHS_CALL( lpi->highs->getOptionValue("random_seed", *ival) );
    2799 break;
    2800 default:
    2801 return SCIP_PARAMETERUNKNOWN;
    2802 }
    2803
    2804 return SCIP_OKAY;
    2805}
    2806
    2807/** sets integer parameter of LP */
    2809 SCIP_LPI* lpi, /**< LP interface structure */
    2810 SCIP_LPPARAM type, /**< parameter number */
    2811 int ival /**< parameter value */
    2812 )
    2813{
    2814 SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
    2815
    2816 assert(lpi != NULL);
    2817 assert(lpi->highs != NULL);
    2818
    2819 switch( type )
    2820 {
    2822 assert(ival == TRUE || ival == FALSE);
    2823 lpi->fromscratch = (SCIP_Bool) ival;
    2824 break;
    2825 case SCIP_LPPAR_LPINFO:
    2826 assert(ival == TRUE || ival == FALSE);
    2827 HIGHS_CALL( lpi->highs->setOptionValue("output_flag", (bool) ival) );
    2828 break;
    2829 case SCIP_LPPAR_SCALING:
    2830 assert(ival >= 0 && ival <= 2);
    2831 if( ival == 0 )
    2832 /* off */
    2833 HIGHS_CALL( lpi->highs->setOptionValue("simplex_scale_strategy", 0) );
    2834 else if( ival == 1 )
    2835 /* forced equilibration */
    2836 HIGHS_CALL( lpi->highs->setOptionValue("simplex_scale_strategy", 2) );
    2837 else
    2838 /* max. value scaling */
    2839 HIGHS_CALL( lpi->highs->setOptionValue("simplex_scale_strategy", 4) );
    2840 break;
    2842 assert(ival == TRUE || ival == FALSE);
    2843 lpi->presolve = ival;
    2844 HIGHS_CALL( lpi->highs->setOptionValue("presolve", ival ? "on" : "off") );
    2845 break;
    2846 case SCIP_LPPAR_PRICING:
    2847 lpi->pricing = (SCIP_PRICING)ival;
    2848 switch( lpi->pricing )
    2849 {
    2852 case SCIP_PRICING_AUTO:
    2853 HIGHS_CALL( lpi->highs->setOptionValue("simplex_primal_edge_weight_strategy", -1) );
    2854 HIGHS_CALL( lpi->highs->setOptionValue("simplex_dual_edge_weight_strategy", -1) );
    2855 break;
    2856 case SCIP_PRICING_DEVEX:
    2857 HIGHS_CALL( lpi->highs->setOptionValue("simplex_primal_edge_weight_strategy", 1) );
    2858 HIGHS_CALL( lpi->highs->setOptionValue("simplex_dual_edge_weight_strategy", 1) );
    2859 break;
    2860 case SCIP_PRICING_FULL:
    2861 case SCIP_PRICING_STEEP:
    2863 HIGHS_CALL( lpi->highs->setOptionValue("simplex_primal_edge_weight_strategy", 2) );
    2864 HIGHS_CALL( lpi->highs->setOptionValue("simplex_dual_edge_weight_strategy", 2) );
    2865 break;
    2866 default:
    2867 return SCIP_LPERROR;
    2868 }
    2869 break;
    2870 case SCIP_LPPAR_THREADS:
    2871 lpi->nthreads = ival;
    2872 break;
    2873 case SCIP_LPPAR_LPITLIM:
    2874 HIGHS_CALL( lpi->highs->setOptionValue("simplex_iteration_limit", ival) );
    2875 break;
    2877 HIGHS_CALL( lpi->highs->setOptionValue("random_seed", ival) );
    2878 break;
    2879 default:
    2880 return SCIP_PARAMETERUNKNOWN;
    2881 }
    2882
    2883 return SCIP_OKAY;
    2884}
    2885
    2886/** gets floating point parameter of LP */
    2888 SCIP_LPI* lpi, /**< LP interface structure */
    2889 SCIP_LPPARAM type, /**< parameter number */
    2890 SCIP_Real* dval /**< buffer to store the parameter value */
    2891)
    2892{
    2893 SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
    2894
    2895 assert(lpi != NULL);
    2896 assert(lpi->highs != NULL);
    2897 assert(dval != NULL);
    2898
    2899 switch( type )
    2900 {
    2901 case SCIP_LPPAR_FEASTOL:
    2902 HIGHS_CALL( lpi->highs->getOptionValue("primal_feasibility_tolerance", *dval) );
    2903 break;
    2905 HIGHS_CALL( lpi->highs->getOptionValue("dual_feasibility_tolerance", *dval) );
    2906 break;
    2907 case SCIP_LPPAR_LPTILIM:
    2908 HIGHS_CALL( lpi->highs->getOptionValue("time_limit", *dval) );
    2909 break;
    2910 case SCIP_LPPAR_OBJLIM:
    2911 HIGHS_CALL( lpi->highs->getOptionValue("objective_bound", *dval) );
    2912 break;
    2913 default:
    2914 return SCIP_PARAMETERUNKNOWN;
    2915 }
    2916
    2917 return SCIP_OKAY;
    2918}
    2919
    2920/** sets floating point parameter of LP */
    2922 SCIP_LPI* lpi, /**< LP interface structure */
    2923 SCIP_LPPARAM type, /**< parameter number */
    2924 SCIP_Real dval /**< parameter value */
    2925 )
    2926{
    2927 SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
    2928
    2929 assert(lpi != NULL);
    2930 assert(lpi->highs != NULL);
    2931
    2932 switch( type )
    2933 {
    2934 case SCIP_LPPAR_FEASTOL:
    2935 /* Primal feasibility tolerance cannot be smaller than 1e-10 */
    2936 dval = MAX(dval, 1e-10);
    2937 HIGHS_CALL( lpi->highs->setOptionValue("primal_feasibility_tolerance", dval) );
    2938 break;
    2940 /* Dual feasibility tolerance cannot be smaller than 1e-10 */
    2941 dval = MAX(dval, 1e-10);
    2942 HIGHS_CALL( lpi->highs->setOptionValue("dual_feasibility_tolerance", dval) );
    2943 break;
    2944 case SCIP_LPPAR_LPTILIM:
    2945 HIGHS_CALL( lpi->highs->setOptionValue("time_limit", dval) );
    2946 break;
    2947 case SCIP_LPPAR_OBJLIM:
    2948 HIGHS_CALL( lpi->highs->setOptionValue("objective_bound", dval) );
    2949 break;
    2950 default:
    2951 return SCIP_PARAMETERUNKNOWN;
    2952 }
    2953
    2954 return SCIP_OKAY;
    2955}
    2956
    2957/** interrupts the currently ongoing lp solve or disables the interrupt */
    2959 SCIP_LPI* lpi, /**< LP interface structure */
    2960 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
    2961 )
    2962{
    2963 SCIPdebugMessage("calling SCIPlpiInterrupt()\n");
    2964
    2965 assert(lpi != NULL);
    2966 assert(lpi->highs != NULL);
    2967
    2968 /* not implemented */
    2969 return SCIP_OKAY;
    2970}
    2971
    2972
    2973/**@} */
    2974
    2975/*
    2976 * Numerical Methods
    2977 */
    2978
    2979/**@name Numerical Methods */
    2980/**@{ */
    2981
    2982/** returns value treated as infinity in the LP solver */
    2984 SCIP_LPI* lpi /**< LP interface structure */
    2985 )
    2986{
    2987 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
    2988
    2989 assert(lpi != NULL);
    2990
    2991 return kHighsInf;
    2992}
    2993
    2994/** checks if given value is treated as infinity in the LP solver */
    2996 SCIP_LPI* lpi, /**< LP interface structure */
    2997 SCIP_Real val
    2998 )
    2999{
    3000 SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
    3001
    3002 assert(lpi != NULL);
    3003
    3004 return val >= kHighsInf;
    3005}
    3006
    3007/**@} */
    3008
    3009/*
    3010 * File Interface Methods
    3011 */
    3012
    3013/**@name File Interface Methods */
    3014/**@{ */
    3015
    3016/** reads LP from a file */
    3018 SCIP_LPI* lpi, /**< LP interface structure */
    3019 const char* fname /**< file name */
    3020 )
    3021{
    3022 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
    3023
    3024 assert(lpi != NULL);
    3025 assert(lpi->highs != NULL);
    3026 assert(fname != NULL);
    3027
    3028 HIGHS_CALL( lpi->highs->readModel(fname) );
    3029
    3030 return SCIP_OKAY;
    3031}
    3032
    3033/** writes LP to a file */
    3035 SCIP_LPI* lpi, /**< LP interface structure */
    3036 const char* fname /**< file name */
    3037 )
    3038{
    3039 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
    3040 assert(fname != NULL);
    3041
    3042 assert(lpi != NULL);
    3043 assert(lpi->highs != NULL);
    3044
    3045 HIGHS_CALL( lpi->highs->writeModel(fname) );
    3046
    3047 return SCIP_OKAY;
    3048}
    3049
    3050/**@} */
    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
    virtual ~HighsSCIP()
    Definition: lpi_highs.cpp:149
    HighsSCIP(SCIP_MESSAGEHDLR *messagehdlr=NULL, const char *probname=NULL)
    Definition: lpi_highs.cpp:138
    #define NULL
    Definition: def.h:248
    #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 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_highs.cpp:1025
    SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPISTATE *lpistate)
    Definition: lpi_highs.cpp:2556
    SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_highs.cpp:2479
    SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
    Definition: lpi_highs.cpp:2887
    SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:2983
    SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:2009
    SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
    Definition: lpi_highs.cpp:1075
    SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
    Definition: lpi_highs.cpp:2995
    SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:964
    SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:2607
    SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1866
    SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1744
    SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
    Definition: lpi_highs.cpp:2299
    SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_highs.cpp:2650
    SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
    Definition: lpi_highs.cpp:864
    SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
    Definition: lpi_highs.cpp:2161
    SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
    Definition: lpi_highs.cpp:2751
    SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_highs.cpp:3034
    SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
    Definition: lpi_highs.cpp:565
    SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1915
    SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
    Definition: lpi_highs.cpp:2921
    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_highs.cpp:1546
    SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
    Definition: lpi_highs.cpp:2710
    SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
    Definition: lpi_highs.cpp:1198
    SCIP_Bool SCIPlpiHasPrimalSolve(void)
    Definition: lpi_highs.cpp:583
    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_highs.cpp:1634
    SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
    Definition: lpi_highs.cpp:1365
    SCIP_Bool SCIPlpiHasBarrierSolve(void)
    Definition: lpi_highs.cpp:601
    SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
    Definition: lpi_highs.cpp:2208
    SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
    Definition: lpi_highs.cpp:2078
    SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
    Definition: lpi_highs.cpp:1136
    int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:2048
    SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1520
    SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
    Definition: lpi_highs.cpp:1723
    SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
    Definition: lpi_highs.cpp:2726
    SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:2022
    SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
    Definition: lpi_highs.cpp:982
    SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1783
    SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
    Definition: lpi_highs.cpp:2061
    SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_highs.cpp:2665
    SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
    Definition: lpi_highs.cpp:673
    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_highs.cpp:1588
    SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
    Definition: lpi_highs.cpp:1421
    SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1830
    SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
    Definition: lpi_highs.cpp:3017
    SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
    Definition: lpi_highs.cpp:2272
    SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1932
    SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
    Definition: lpi_highs.cpp:2691
    SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:2035
    SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
    Definition: lpi_highs.cpp:2639
    SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
    Definition: lpi_highs.cpp:2808
    const char * SCIPlpiGetSolverName(void)
    Definition: lpi_highs.cpp:531
    SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
    Definition: lpi_highs.cpp:2325
    SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1761
    SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_highs.cpp:2384
    SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
    Definition: lpi_highs.cpp:914
    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_highs.cpp:1219
    SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_highs.cpp:2413
    SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
    Definition: lpi_highs.cpp:1278
    SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
    Definition: lpi_highs.cpp:2447
    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_highs.cpp:1250
    SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1702
    const char * SCIPlpiGetSolverDesc(void)
    Definition: lpi_highs.cpp:542
    SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
    Definition: lpi_highs.cpp:1505
    SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1955
    SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
    Definition: lpi_highs.cpp:1301
    SCIP_Bool SCIPlpiHasDualSolve(void)
    Definition: lpi_highs.cpp:592
    SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1533
    SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
    Definition: lpi_highs.cpp:1393
    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_highs.cpp:1662
    SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
    Definition: lpi_highs.cpp:2100
    SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1880
    SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
    Definition: lpi_highs.cpp:842
    SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
    Definition: lpi_highs.cpp:1342
    SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    Definition: lpi_highs.cpp:2621
    SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1796
    SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1472
    SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
    Definition: lpi_highs.cpp:759
    SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1450
    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 **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
    Definition: lpi_highs.cpp:705
    SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1902
    SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
    Definition: lpi_highs.cpp:2249
    SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
    Definition: lpi_highs.cpp:2357
    SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
    Definition: lpi_highs.cpp:619
    void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:555
    SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
    Definition: lpi_highs.cpp:1093
    SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
    Definition: lpi_highs.cpp:1324
    SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:1977
    SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
    Definition: lpi_highs.cpp:1181
    SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
    Definition: lpi_highs.cpp:2958
    SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
    Definition: lpi_highs.cpp:815
    SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
    Definition: lpi_highs.cpp:940
    SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
    Definition: lpi_highs.cpp:1115
    SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
    Definition: lpi_highs.cpp:1164
    SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
    Definition: lpi_highs.cpp:2512
    SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
    Definition: lpi_highs.cpp:1054
    interface methods for specific LP solvers
    SCIP_DUALPACKET ROWPACKET
    Definition: lpi_clp.cpp:128
    SCIP_DUALPACKET COLPACKET
    Definition: lpi_clp.cpp:126
    static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
    Definition: lpi_highs.cpp:260
    static HighsBasisStatus basestatToHighsBasisStatus(const int &stat)
    Definition: lpi_highs.cpp:350
    static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
    Definition: lpi_highs.cpp:276
    static int rowpacketNum(int nrows)
    Definition: lpi_highs.cpp:251
    SCIP_DUALPACKET ROWPACKET
    Definition: lpi_highs.cpp:173
    static SCIP_RETCODE ensureCstatMem(SCIP_LPI *lpi, int num)
    Definition: lpi_highs.cpp:191
    #define COLS_PER_PACKET
    Definition: lpi_highs.cpp:172
    static std::string simplexStrategyToString(const int &strategy)
    Definition: lpi_highs.cpp:373
    static char highsname[30]
    Definition: lpi_highs.cpp:527
    static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
    Definition: lpi_highs.cpp:316
    SCIP_DUALPACKET COLPACKET
    Definition: lpi_highs.cpp:171
    static SCIP_RETCODE lpiSolve(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:417
    static SCIP_RETCODE ensureRstatMem(SCIP_LPI *lpi, int num)
    Definition: lpi_highs.cpp:214
    static int colpacketNum(int ncols)
    Definition: lpi_highs.cpp:242
    static SCIP_RETCODE checkMatrixValue(SCIP_LPI *lpi, SCIP_Real value)
    Definition: lpi_highs.cpp:396
    #define HIGHS_CALL_WITH_WARNING(x)
    Definition: lpi_highs.cpp:102
    static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
    Definition: lpi_highs.cpp:292
    #define ROWS_PER_PACKET
    Definition: lpi_highs.cpp:174
    #define HIGHS_CALL(x)
    Definition: lpi_highs.cpp:70
    static void invalidateSolution(SCIP_LPI *lpi)
    Definition: lpi_highs.cpp:340
    #define HIGHS_relDiff(val1, val2)
    Definition: lpi_highs.cpp:64
    static char highsdesc[200]
    Definition: lpi_highs.cpp:528
    #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 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
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    COLPACKET * packcstat
    Definition: lpi_clp.cpp:136
    ROWPACKET * packrstat
    Definition: lpi_clp.cpp:137
    SCIP_Bool solved
    Definition: lpi_clp.cpp:114
    HighsSCIP * highs
    Definition: lpi_highs.cpp:158
    int nthreads
    Definition: lpi_highs.cpp:163
    int * cstat
    Definition: lpi_clp.cpp:107
    SCIP_Bool fromscratch
    Definition: lpi_cpx.c:171
    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_Bool presolve
    Definition: lpi_highs.cpp:166
    SCIP_MESSAGEHDLR * messagehdlr
    Definition: lpi_cpx.c:185
    type definitions for LP management
    @ 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_LPPAR_PRICING
    Definition: type_lpi.h:54
    @ SCIP_LPPAR_THREADS
    Definition: type_lpi.h:66
    @ SCIP_LPPAR_LPINFO
    Definition: type_lpi.h:55
    @ SCIP_LPPAR_SCALING
    Definition: type_lpi.h:52
    @ SCIP_LPPAR_LPTILIM
    Definition: type_lpi.h:61
    @ SCIP_LPPAR_PRESOLVING
    Definition: type_lpi.h:53
    @ 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_FEASTOL
    Definition: type_lpi.h:56
    @ SCIP_LPPAR_LPITLIM
    Definition: type_lpi.h:60
    @ SCIP_LPPAR_OBJLIM
    Definition: type_lpi.h:59
    @ SCIP_BASESTAT_BASIC
    Definition: type_lpi.h:92
    @ SCIP_BASESTAT_UPPER
    Definition: type_lpi.h:93
    @ SCIP_BASESTAT_LOWER
    Definition: type_lpi.h:91
    @ SCIP_BASESTAT_ZERO
    Definition: type_lpi.h:94
    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_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_PARAMETERUNKNOWN
    Definition: type_retcode.h:55
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63