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