Scippy

SCIP

Solving Constraint Integer Programs

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