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 assert(lpi != NULL);
836 assert(lpi->highs != NULL);
837 assert(firstcol >= 0);
838 assert(lastcol < lpi->highs->getLp().num_col_);
839 assert(firstcol <= lastcol + 1);
840
841 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
842
843 // handle empty range
844 if( firstcol > lastcol )
845 return SCIP_OKAY;
846
848 HIGHS_CALL( lpi->highs->deleteCols(firstcol, lastcol) );
849
850 assert(lpi->highs->getLp().num_col_ >= 0);
851
852 return SCIP_OKAY;
853}
854
855/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
857 SCIP_LPI* lpi, /**< LP interface structure */
858 int* dstat /**< deletion status of columns
859 * input: 1 if column should be deleted, 0 if not
860 * output: new position of column, -1 if column was deleted */
861 )
862{
863 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
864
865 assert(lpi != NULL);
866 assert(dstat != NULL);
867 assert(lpi->highs->getLp().num_col_ >= 0);
868
870
871 HIGHS_CALL( lpi->highs->deleteCols(dstat) );
872
873 assert(lpi->highs->getLp().num_col_ >= 0);
874 return SCIP_OKAY;
875}
876
877/** adds rows to the LP */
879 SCIP_LPI* lpi, /**< LP interface structure */
880 int nrows, /**< number of rows to be added */
881 const SCIP_Real* lhs, /**< left hand sides of new rows */
882 const SCIP_Real* rhs, /**< right hand sides of new rows */
883 char** rownames, /**< row names, or NULL */
884 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
885 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
886 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
887 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
888 )
889{
890 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
891
892 assert(lpi != NULL);
893 assert(lpi->highs != NULL);
894 assert(nrows >= 0);
895 assert(nrows <= 0 || lhs != NULL);
896 assert(nrows <= 0 || rhs != NULL);
897 assert(nnonz >= 0);
898 assert(nnonz <= 0 || beg != NULL);
899 assert(nnonz <= 0 || ind != NULL);
900 assert(nnonz <= 0 || val != NULL);
901
903
904#ifndef NDEBUG
905 if( nnonz > 0 )
906 {
907 /* Perform check that no new columns are added - this is likely to be a mistake - and that the values are nonzero*/
908 int ncols = lpi->highs->getLp().num_col_;
909 for( int j = 0; j < nnonz; ++j )
910 {
911 assert(0 <= ind[j] && ind[j] < ncols);
912 assert(val[j] != 0.0);
913 SCIP_CALL( checkMatrixValue(lpi, val[j]) );
914 }
915 }
916
917 /* HiGHS returns with a warning if values are within the zero tolerance, but seems to continue safely simply ignoring
918 * them; in debug mode we stop, in optimized mode we accept this behavior */
919 HIGHS_CALL( lpi->highs->addRows(nrows, lhs, rhs, nnonz, beg, ind, val) );
920#else
921 HIGHS_CALL_WITH_WARNING( lpi->highs->addRows(nrows, lhs, rhs, nnonz, beg, ind, val) );
922#endif
923
924 return SCIP_OKAY;
925}
926
927/** deletes all rows in the given range from LP */
929 SCIP_LPI* lpi, /**< LP interface structure */
930 int firstrow, /**< first row to be deleted */
931 int lastrow /**< last row to be deleted */
932 )
933{
934 assert(lpi != NULL);
935 assert(lpi->highs != NULL);
936 assert(firstrow >= 0);
937 assert(lastrow < lpi->highs->getLp().num_row_);
938 assert(firstrow <= lastrow + 1);
939
940 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
941
942 // handle empty range
943 if( firstrow > lastrow )
944 return SCIP_OKAY;
945
947 HIGHS_CALL( lpi->highs->deleteRows(firstrow, lastrow) );
948
949 assert(lpi->highs->getLp().num_row_ >= 0);
950 return SCIP_OKAY;
951}
952
953/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
955 SCIP_LPI* lpi, /**< LP interface structure */
956 int* dstat /**< deletion status of rows
957 * input: 1 if row should be deleted, 0 if not
958 * output: new position of row, -1 if row was deleted */
959 )
960{
961 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
962
963 assert(lpi != NULL);
964 assert(dstat != NULL);
965 assert(lpi->highs != NULL);
966 assert(lpi->highs->getLp().num_row_ >= 0);
967
969
970 HIGHS_CALL( lpi->highs->deleteRows(dstat) );
971
972 assert(lpi->highs->getLp().num_row_ >= 0);
973
974 return SCIP_OKAY;
975}
976
977/** clears the whole LP */
979 SCIP_LPI* lpi /**< LP interface structure */
980 )
981{
982 SCIPdebugMessage("calling SCIPlpiClear()\n");
983
984 assert(lpi != NULL);
985 assert(lpi->highs != NULL);
986 assert(lpi->highs->getLp().num_row_ >= 0);
987 assert(lpi->highs->getLp().num_col_ >= 0);
988
990
991 HIGHS_CALL( lpi->highs->clearModel() );
992 return SCIP_OKAY;
993}
994
995/** changes lower and upper bounds of columns */
997 SCIP_LPI* lpi, /**< LP interface structure */
998 int ncols, /**< number of columns to change bounds for */
999 const int* ind, /**< column indices or NULL if ncols is zero */
1000 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
1001 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
1002 )
1003{
1004 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
1005
1006 assert(lpi != NULL);
1007 assert(lpi->highs != NULL);
1008 assert(ind != NULL);
1009 assert(lb != NULL);
1010 assert(ub != NULL);
1011
1012 invalidateSolution(lpi);
1013
1014 int i;
1015
1016 /* Check validity of data */
1017 for( i = 0; i < ncols; ++i )
1018 {
1019 assert(0 <= ind[i] && ind[i] < lpi->highs->getLp().num_col_);
1020
1021 if( SCIPlpiIsInfinity(lpi, lb[i]) )
1022 {
1023 SCIPerrorMessage( "LP Error: fixing lower bound for variable %d to infinity\n", ind[i]);
1024 return SCIP_LPERROR;
1025 }
1026 if( SCIPlpiIsInfinity(lpi, -ub[i]) )
1027 {
1028 SCIPerrorMessage( "LP Error: fixing upper bound for variable %d to -infinity\n", ind[i]);
1029 return SCIP_LPERROR;
1030 }
1031 }
1032
1033 HIGHS_CALL( lpi->highs->changeColsBounds(ncols, ind, lb, ub) );
1034
1035 return SCIP_OKAY;
1036}
1037
1038/** changes left and right hand sides of rows */
1040 SCIP_LPI* lpi, /**< LP interface structure */
1041 int nrows, /**< number of rows to change sides for */
1042 const int* ind, /**< row indices */
1043 const SCIP_Real* lhs, /**< new values for left hand sides */
1044 const SCIP_Real* rhs /**< new values for right hand sides */
1045 )
1046{
1047 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
1048
1049 assert(lpi != NULL);
1050 assert(lpi->highs != NULL);
1051 assert(ind != NULL);
1052 assert(lhs != NULL);
1053 assert(rhs != NULL);
1054
1055 int i;
1056
1057 invalidateSolution(lpi);
1058
1059 for( i = 0; i < nrows; ++i )
1060 assert(0 <= ind[i] && ind[i] < lpi->highs->getLp().num_row_);
1061
1062 HIGHS_CALL( lpi->highs->changeRowsBounds(nrows, ind, lhs, rhs) );
1063
1064 return SCIP_OKAY;
1065}
1066
1067/** changes a single coefficient */
1069 SCIP_LPI* lpi, /**< LP interface structure */
1070 int row, /**< row number of coefficient to change */
1071 int col, /**< column number of coefficient to change */
1072 SCIP_Real newval /**< new value of coefficient */
1073 )
1074{
1075 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
1076
1077 assert(lpi != NULL);
1078 assert(lpi->highs != NULL);
1079
1080 invalidateSolution(lpi);
1081
1082 SCIP_CALL( checkMatrixValue(lpi, newval) );
1083 HIGHS_CALL( lpi->highs->changeCoeff(row, col, newval) );
1084
1085 return SCIP_OKAY;
1086}
1087
1088/** changes the objective sense */
1090 SCIP_LPI* lpi, /**< LP interface structure */
1091 SCIP_OBJSEN objsen /**< new objective sense */
1092 )
1093{
1094 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
1095
1096 assert(lpi != NULL);
1097 assert(lpi->highs != NULL);
1098
1099 invalidateSolution(lpi);
1100
1101 HIGHS_CALL( lpi->highs->changeObjectiveSense(objsen == SCIP_OBJSEN_MINIMIZE ? ObjSense::kMinimize : ObjSense::kMaximize) );
1102
1103 return SCIP_OKAY;
1104}
1105
1106/** changes objective values of columns in the LP */
1108 SCIP_LPI* lpi, /**< LP interface structure */
1109 int ncols, /**< number of columns to change objective value for */
1110 const int* ind, /**< column indices to change objective value for */
1111 const SCIP_Real* obj /**< new objective values for columns */
1112 )
1113{
1114 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
1115
1116 assert(lpi != NULL);
1117 assert(lpi->highs != NULL);
1118 assert(ind != NULL);
1119 assert(obj != NULL);
1120
1121 invalidateSolution(lpi);
1122
1123 HIGHS_CALL( lpi->highs->changeColsCost(ncols, ind, obj) );
1124
1125 return SCIP_OKAY;
1126}
1127
1128/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
1130 SCIP_LPI* lpi, /**< LP interface structure */
1131 int row, /**< row number to scale */
1132 SCIP_Real scaleval /**< scaling multiplier */
1133 )
1134{
1135 SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
1136
1137 assert(lpi != NULL);
1138 assert(lpi->highs != NULL);
1139
1140 invalidateSolution(lpi);
1141
1142 HIGHS_CALL( lpi->highs->scaleRow(row, scaleval) );
1143
1144 return SCIP_OKAY;
1145}
1146
1147/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
1148 * are divided by the scalar; for negative scalars, the column's bounds are switched
1149 */
1151 SCIP_LPI* lpi, /**< LP interface structure */
1152 int col, /**< column number to scale */
1153 SCIP_Real scaleval /**< scaling multiplier */
1154 )
1155{
1156 SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
1157
1158 assert(lpi != NULL);
1159 assert(scaleval != 0.0);
1160
1161 invalidateSolution(lpi);
1162
1163 HIGHS_CALL( lpi->highs->scaleCol(col, scaleval) );
1164
1165 return SCIP_OKAY;
1166}
1167
1168/**@} */
1169
1170/*
1171 * Data Accessing Methods
1172 */
1173
1174/**@name Data Accessing Methods */
1175/**@{ */
1176
1177/** gets the number of rows in the LP */
1179 SCIP_LPI* lpi, /**< LP interface structure */
1180 int* nrows /**< pointer to store the number of rows */
1181 )
1182{
1183 SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
1184
1185 assert(lpi != NULL);
1186 assert(lpi->highs != NULL);
1187 assert(nrows != NULL);
1188 *nrows = lpi->highs->getNumRow();
1189 assert(*nrows >= 0);
1190
1191 return SCIP_OKAY;
1192}
1193
1194/** gets the number of columns in the LP */
1196 SCIP_LPI* lpi, /**< LP interface structure */
1197 int* ncols /**< pointer to store the number of cols */
1198 )
1199{
1200 SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
1201
1202 assert(lpi != NULL);
1203 assert(lpi->highs != NULL);
1204 assert(ncols != NULL);
1205 *ncols = lpi->highs->getNumCol();
1206 assert(*ncols >= 0);
1207
1208 return SCIP_OKAY;
1209}
1210
1211/** gets the number of nonzero elements in the LP constraint matrix */
1213 SCIP_LPI* lpi, /**< LP interface structure */
1214 int* nnonz /**< pointer to store the number of nonzeros */
1215 )
1216{
1217 SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
1218
1219 assert(lpi != NULL);
1220 assert(lpi->highs != NULL);
1221 assert(nnonz != NULL);
1222 *nnonz = lpi->highs->getNumNz();
1223 assert(*nnonz >= 0);
1224
1225 return SCIP_OKAY;
1226}
1227
1228/** gets columns from LP problem object; the arrays have to be large enough to
1229 * store all values Either both, lb and ub, have to be NULL, or both have to be
1230 * non-NULL, either nnonz, beg, ind, and val have to be NULL, or all of them
1231 * have to be non-NULL.
1232 */
1234 SCIP_LPI* lpi, /**< LP interface structure */
1235 int firstcol, /**< first column to get from LP */
1236 int lastcol, /**< last column to get from LP */
1237 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
1238 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
1239 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1240 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1241 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1242 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1243 )
1244{
1245 int num_col;
1246
1247 assert(lpi != NULL);
1248 assert(lpi->highs != NULL);
1249 assert(firstcol >= 0);
1250 assert(lastcol < lpi->highs->getLp().num_col_);
1251 assert(firstcol <= lastcol + 1);
1252
1253 SCIPdebugMessage("calling SCIPlpiGetCols()\n");
1254
1255 HIGHS_CALL( lpi->highs->getCols(firstcol, lastcol, num_col, NULL, lb, ub, *nnonz, beg, ind, val) );
1256
1257 return SCIP_OKAY;
1258}
1259
1260/** gets rows from LP problem object; the arrays have to be large enough to store all values.
1261 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
1262 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1263 */
1265 SCIP_LPI* lpi, /**< LP interface structure */
1266 int firstrow, /**< first row to get from LP */
1267 int lastrow, /**< last row to get from LP */
1268 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
1269 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
1270 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1271 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
1272 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
1273 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1274 )
1275{
1276 int num_row;
1277
1278 assert(lpi != NULL);
1279 assert(lpi->highs != NULL);
1280 assert(firstrow >= 0);
1281 assert(lastrow < lpi->highs->getLp().num_row_);
1282 assert(firstrow <= lastrow + 1);
1283
1284 SCIPdebugMessage("calling SCIPlpiGetRows()\n");
1285
1286 HIGHS_CALL( lpi->highs->getRows(firstrow, lastrow, num_row, lhs, rhs, *nnonz, beg, ind, val) );
1287
1288 return SCIP_OKAY;
1289}
1290
1291/** gets column names */
1293 SCIP_LPI* lpi, /**< LP interface structure */
1294 int firstcol, /**< first column to get name from LP */
1295 int lastcol, /**< last column to get name from LP */
1296 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
1297 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
1298 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
1299 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1300 )
1301{
1302 assert(lpi != NULL);
1303 assert(firstcol >= 0);
1304 assert(lastcol < lpi->highs->getLp().num_col_);
1305 assert(firstcol <= lastcol + 1);
1306
1307 SCIPdebugMessage("calling SCIPlpiGetColNames()\n");
1308
1309 SCIPerrorMessage("SCIPlpiGetColNames() has not been implemented yet\n");
1310
1311 return SCIP_PLUGINNOTFOUND;
1312}
1313
1314/** gets row names */
1316 SCIP_LPI* lpi, /**< LP interface structure */
1317 int firstrow, /**< first row to get name from LP */
1318 int lastrow, /**< last row to get name from LP */
1319 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
1320 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
1321 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
1322 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1323 )
1324{
1325 assert(lpi != NULL);
1326 assert(firstrow >= 0);
1327 assert(lastrow < lpi->highs->getLp().num_row_);
1328 assert(firstrow <= lastrow + 1);
1329
1330 SCIPdebugMessage("calling SCIPlpiGetRowNames()\n");
1331
1332 SCIPerrorMessage("SCIPlpiGetRowNames() has not been implemented yet\n");
1333
1334 return SCIP_PLUGINNOTFOUND;
1335}
1336
1337/** gets the objective sense of the LP */
1339 SCIP_LPI* lpi, /**< LP interface structure */
1340 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
1341 )
1342{
1343 SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
1344
1345 assert(lpi != NULL);
1346 assert(lpi->highs != NULL);
1347
1348 *objsen = SCIP_OBJSEN_MINIMIZE;
1349 if( lpi->highs->getLp().sense_ == ObjSense::kMaximize )
1350 *objsen = SCIP_OBJSEN_MAXIMIZE;
1351
1352 return SCIP_OKAY;
1353}
1354
1355/** gets objective coefficients from LP problem object */
1357 SCIP_LPI* lpi, /**< LP interface structure */
1358 int firstcol, /**< first column to get objective coefficient for */
1359 int lastcol, /**< last column to get objective coefficient for */
1360 SCIP_Real* vals /**< array to store objective coefficients */
1361 )
1362{
1363 assert(lpi != NULL);
1364 assert(lpi->highs != NULL);
1365 assert(vals != NULL);
1366 assert(firstcol >= 0);
1367 assert(lastcol < lpi->highs->getLp().num_col_);
1368 assert(firstcol <= lastcol + 1);
1369
1370 SCIPdebugMessage("calling SCIPlpiGetObj()\n");
1371
1372 for( int i = firstcol; i < lastcol + 1; ++i )
1373 vals[i - firstcol] = lpi->highs->getLp().col_cost_[i];
1374
1375 return SCIP_OKAY;
1376}
1377
1378/** gets current bounds from LP problem object */
1380 SCIP_LPI* lpi, /**< LP interface structure */
1381 int firstcol, /**< first column to get objective value for */
1382 int lastcol, /**< last column to get objective value for */
1383 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
1384 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
1385 )
1386{
1387 assert(lpi != NULL);
1388 assert(lpi->highs != NULL);
1389 assert(firstcol >= 0);
1390 assert(lastcol < lpi->highs->getLp().num_col_);
1391 assert(firstcol <= lastcol + 1);
1392
1393 SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
1394
1395 for( int i = firstcol; i < lastcol + 1; ++i )
1396 {
1397 if( lbs != NULL )
1398 lbs[i - firstcol] = lpi->highs->getLp().col_lower_[i];
1399 if( ubs != NULL )
1400 ubs[i - firstcol] = lpi->highs->getLp().col_upper_[i];
1401 }
1402
1403 return SCIP_OKAY;
1404}
1405
1406/** gets current row sides from LP problem object */
1408 SCIP_LPI* lpi, /**< LP interface structure */
1409 int firstrow, /**< first row to get sides for */
1410 int lastrow, /**< last row to get sides for */
1411 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
1412 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
1413 )
1414{
1415 assert(lpi != NULL);
1416 assert(lpi->highs != NULL);
1417 assert(firstrow >= 0);
1418 assert(lastrow < lpi->highs->getLp().num_row_);
1419 assert(firstrow <= lastrow + 1);
1420
1421 SCIPdebugMessage("calling SCIPlpiGetSides()\n");
1422
1423 for( int i = firstrow; i < lastrow + 1; ++i )
1424 {
1425 if( lhss != NULL )
1426 lhss[i - firstrow] = lpi->highs->getLp().row_lower_[i];
1427 if( rhss != NULL )
1428 rhss[i - firstrow] = lpi->highs->getLp().row_upper_[i];
1429 }
1430
1431 return SCIP_OKAY;
1432}
1433
1434/** gets a single coefficient */
1436 SCIP_LPI* lpi, /**< LP interface structure */
1437 int row, /**< row number of coefficient */
1438 int col, /**< column number of coefficient */
1439 SCIP_Real* val /**< pointer to store the value of the coefficient */
1440)
1441{
1442 SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
1443
1444 assert(lpi != NULL);
1445 assert(lpi->highs != NULL);
1446 assert(0 <= col && col < lpi->highs->getNumCol());
1447 assert(0 <= row && row < lpi->highs->getNumCol());
1448 assert(val != NULL);
1449
1450 HIGHS_CALL( lpi->highs->getCoeff(row, col, *val) );
1451 return SCIP_OKAY;
1452}
1453
1454/**@} */
1455
1456/*
1457 * Solving Methods
1458 */
1459
1460/**@name Solving Methods */
1461/**@{ */
1462
1463/** calls primal simplex to solve the LP */
1465 SCIP_LPI* lpi /**< LP interface structure */
1466 )
1467{
1468 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
1469
1470 assert(lpi != NULL);
1471
1472 /* HiGHS' primal simplex seems to still have performance issues, so we call the dual simplex instead. */
1473#ifdef SCIP_WITH_HIGHSPRIMAL
1474 HIGHS_CALL( lpi->highs->setOptionValue("parallel", "off") );
1475 HIGHS_CALL( lpi->highs->setOptionValue("threads", 1) );
1476 HIGHS_CALL( lpi->highs->setOptionValue("simplex_strategy", 4) );
1477 SCIP_CALL( lpiSolve(lpi) );
1478#else
1480#endif
1481
1482 return SCIP_OKAY;
1483}
1484
1485/** calls dual simplex to solve the LP */
1487 SCIP_LPI* lpi /**< LP interface structure */
1488 )
1489{
1490 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
1491
1492 assert(lpi != NULL);
1493 assert(lpi->highs != NULL);
1494
1495 /* HiGHS still seems to get stuck sometimes in parallel mode, so we ignore nthreads for now. */
1496#ifdef SCIP_WITH_HIGHSPARALLEL
1497 if( lpi->nthreads == 0 || lpi->nthreads > 1 )
1498 {
1499 SCIPdebugMessage("Running HiGHS dual simplex in parallel with lpi->nthreads=%d\n", lpi->nthreads);
1500 HIGHS_CALL( lpi->highs->setOptionValue("parallel", "on") );
1501 HIGHS_CALL( lpi->highs->setOptionValue("threads", lpi->nthreads) ); /* note that also in HiGHS, 0 is the automatic setting */
1502 HIGHS_CALL( lpi->highs->setOptionValue("simplex_strategy", 2) ); /* PAMI */
1503 }
1504 else
1505#endif
1506 {
1507 SCIPdebugMessage("Running HiGHS dual simplex in serial with lpi->nthreads=%d\n", lpi->nthreads);
1508 HIGHS_CALL( lpi->highs->setOptionValue("parallel", "off") );
1509 HIGHS_CALL( lpi->highs->setOptionValue("threads", 1) );
1510 HIGHS_CALL( lpi->highs->setOptionValue("simplex_strategy", 1) );
1511 }
1512
1513 SCIP_CALL( lpiSolve(lpi) );
1514
1515 return SCIP_OKAY;
1516}
1517
1518/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
1520 SCIP_LPI* lpi, /**< LP interface structure */
1521 SCIP_Bool crossover /**< perform crossover */
1522 )
1523{
1524 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
1525
1526 assert(lpi != NULL);
1527 assert(lpi->highs != NULL);
1528
1529 SCIPdebugMessage("HiGHS does not support Barrier - switching to dual simplex\n");
1530 return SCIPlpiSolveDual(lpi);
1531}
1532
1533/** start strong branching - call before any strong branching */
1535 SCIP_LPI* lpi /**< LP interface structure */
1536 )
1537{
1538 SCIPdebugMessage("calling SCIPlpiStartStrongbranch()\n");
1539
1540 assert(lpi != NULL);
1541
1542 /* no work necessary for current dummy implementation */
1543 return SCIP_OKAY;
1544}
1545
1546/** end strong branching - call after any strong branching */
1548 SCIP_LPI* lpi /**< LP interface structure */
1549 )
1550{
1551 SCIPdebugMessage("calling SCIPlpiEndStrongbranch()\n");
1552
1553 assert(lpi != NULL);
1554
1555 /* no work necessary for current dummy implementation */
1556 return SCIP_OKAY;
1557}
1558
1559/** performs strong branching iterations on one @b fractional candidate */
1561 SCIP_LPI* lpi, /**< LP interface structure */
1562 int col, /**< column to apply strong branching on */
1563 SCIP_Real psol, /**< fractional current primal solution value of column */
1564 int itlim, /**< iteration limit for strong branchings */
1565 SCIP_Real* down, /**< stores dual bound after branching column down */
1566 SCIP_Real* up, /**< stores dual bound after branching column up */
1567 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
1568 * otherwise, it can only be used as an estimate value */
1569 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
1570 * otherwise, it can only be used as an estimate value */
1571 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1572 )
1573{
1574 SCIPdebugMessage("calling SCIPlpiStrongbranchFrac()\n");
1575
1576 assert(lpi != NULL);
1577 assert(down != NULL);
1578 assert(up != NULL);
1579 assert(downvalid != NULL);
1580 assert(upvalid != NULL);
1581
1582 /* This is a dummy implementation to satisfy the test suite. It does not perform actual strong branching. */
1583 SCIP_Real dualbound = (lpi->highs->getLp().sense_ == ObjSense::kMinimize
1584 ? -SCIPlpiInfinity(lpi) : SCIPlpiInfinity(lpi));
1585
1586 if( SCIPlpiIsOptimal(lpi) )
1587 {
1588 SCIP_CALL( SCIPlpiGetObjval(lpi, &dualbound) );
1589 }
1590
1591 *down = *up = dualbound;
1592 *downvalid = TRUE;
1593 *upvalid = TRUE;
1594
1595 if( iter != NULL )
1596 *iter = -1;
1597
1598 return SCIP_OKAY;
1599}
1600
1601/** performs strong branching iterations on given @b fractional candidates */
1603 SCIP_LPI* lpi, /**< LP interface structure */
1604 int* cols, /**< columns to apply strong branching on */
1605 int ncols, /**< number of columns */
1606 SCIP_Real* psols, /**< fractional current primal solution values of columns */
1607 int itlim, /**< iteration limit for strong branchings */
1608 SCIP_Real* down, /**< stores dual bounds after branching columns down */
1609 SCIP_Real* up, /**< stores dual bounds after branching columns up */
1610 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
1611 * otherwise, they can only be used as an estimate values */
1612 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
1613 * otherwise, they can only be used as an estimate values */
1614 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1615 )
1616{
1617 SCIPdebugMessage("calling SCIPlpiStrongbranchesFrac()\n");
1618
1619 assert(lpi != NULL);
1620 assert(cols != NULL);
1621 assert(down != NULL);
1622 assert(up != NULL);
1623 assert(downvalid != NULL);
1624 assert(upvalid != NULL);
1625
1626 /* This is a dummy implementation to satisfy the test suite. It does not perform actual strong branching. */
1627 SCIP_Real dualbound = (lpi->highs->getLp().sense_ == ObjSense::kMinimize
1628 ? -SCIPlpiInfinity(lpi) : SCIPlpiInfinity(lpi));
1629
1630 if( SCIPlpiIsOptimal(lpi) )
1631 {
1632 SCIP_CALL( SCIPlpiGetObjval(lpi, &dualbound) );
1633 }
1634
1635 for( int j = 0; j < ncols; ++j )
1636 {
1637 down[j] = up[j] = dualbound;
1638 downvalid[j] = upvalid[j] = TRUE;
1639 }
1640
1641 if( iter != NULL )
1642 *iter = -1;
1643
1644 return SCIP_OKAY;
1645}
1646
1647/** performs strong branching iterations on one candidate with @b integral value */
1649 SCIP_LPI* lpi, /**< LP interface structure */
1650 int col, /**< column to apply strong branching on */
1651 SCIP_Real psol, /**< current integral primal solution value of column */
1652 int itlim, /**< iteration limit for strong branchings */
1653 SCIP_Real* down, /**< stores dual bound after branching column down */
1654 SCIP_Real* up, /**< stores dual bound after branching column up */
1655 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
1656 * otherwise, it can only be used as an estimate value */
1657 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
1658 * otherwise, it can only be used as an estimate value */
1659 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1660 )
1661{
1662 SCIPdebugMessage("calling SCIPlpiStrongbranchInt()\n");
1663
1664 assert(lpi != NULL);
1665 assert(down != NULL);
1666 assert(up != NULL);
1667 assert(downvalid != NULL);
1668 assert(upvalid != NULL);
1669
1670 /* the dummy implementation works independently of primal values. */
1671 SCIP_CALL( SCIPlpiStrongbranchFrac(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter) );
1672 return SCIP_OKAY;
1673}
1674
1675/** performs strong branching iterations on given candidates with @b integral values */
1677 SCIP_LPI* lpi, /**< LP interface structure */
1678 int* cols, /**< columns to apply strong branching on */
1679 int ncols, /**< number of columns */
1680 SCIP_Real* psols, /**< current integral primal solution values of columns */
1681 int itlim, /**< iteration limit for strong branchings */
1682 SCIP_Real* down, /**< stores dual bounds after branching columns down */
1683 SCIP_Real* up, /**< stores dual bounds after branching columns up */
1684 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
1685 * otherwise, they can only be used as an estimate values */
1686 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
1687 * otherwise, they can only be used as an estimate values */
1688 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
1689 )
1690{
1691 SCIPdebugMessage("calling SCIPlpiStrongbranchesInt()\n");
1692
1693 assert(lpi != NULL);
1694 assert(cols != NULL);
1695 assert(down != NULL);
1696 assert(up != NULL);
1697 assert(downvalid != NULL);
1698 assert(upvalid != NULL);
1699
1700 /* the dummy implementation works independently of primal values */
1701 SCIP_CALL( SCIPlpiStrongbranchesFrac(lpi, cols, ncols, psols, itlim, down, up, downvalid, upvalid, iter) );
1702 return SCIP_OKAY;
1703}
1704
1705/**@} */
1706
1707/*
1708 * Solution Information Methods
1709 */
1710
1711/**@name Solution Information Methods */
1712/**@{ */
1713
1714/** returns whether a solve method was called after the last modification of the
1715 * LP */
1717 SCIP_LPI* lpi /**< LP interface structure */
1718 )
1719{
1720 SCIPdebugMessage("calling SCIPlpiWasSolved()\n");
1721
1722 assert(lpi != NULL);
1723
1724 return lpi->solved;
1725}
1726
1727/** gets information about primal and dual feasibility of the current LP solution
1728 *
1729 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
1730 * returns true. If the LP is changed, this information might be invalidated.
1731 *
1732 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
1733 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
1734 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
1735 * the problem might actually be feasible).
1736 */
1738 SCIP_LPI* lpi, /**< LP interface structure */
1739 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
1740 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
1741 )
1742{
1743 SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
1744
1745 assert(lpi != NULL);
1746 assert(primalfeasible != NULL);
1747 assert(dualfeasible != NULL);
1748
1749 *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
1750 *dualfeasible = SCIPlpiIsDualFeasible(lpi);
1751
1752 return SCIP_OKAY;
1753}
1754
1755/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
1756 * this does not necessarily mean, that the solver knows and can return the primal ray
1757 */
1759 SCIP_LPI* lpi /**< LP interface structure */
1760 )
1761{
1762 SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
1763
1764 assert(lpi != NULL);
1765 assert(lpi->highs != NULL);
1766
1767 HighsModelStatus model_status = lpi->highs->getModelStatus();
1768
1769 return model_status == HighsModelStatus::kUnbounded || model_status == HighsModelStatus::kUnboundedOrInfeasible;
1770}
1771
1772/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
1773 * and the solver knows and can return the primal ray
1774 */
1776 SCIP_LPI* lpi /**< LP interface structure */
1777 )
1778{
1779 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
1780
1781 assert(lpi != NULL);
1782 assert(lpi->highs != NULL);
1783
1784 if( !SCIPlpiIsPrimalUnbounded(lpi) )
1785 return FALSE;
1786
1787 /* HiGHS method does not work in this case, but we can easily construct an unbounded primal ray */
1788 if( lpi->highs->getNumRow() == 0 )
1789 return TRUE;
1790
1791 bool has_primal_ray = false;
1792 HIGHS_CALL( lpi->highs->getPrimalRay(has_primal_ray, NULL) );
1793 return has_primal_ray;
1794}
1795
1796/** returns TRUE iff LP is proven to be primal unbounded */
1798 SCIP_LPI* lpi /**< LP interface structure */
1799 )
1800{
1801 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
1802
1803 assert(lpi != NULL);
1804 assert(lpi->highs != NULL);
1805
1806 return lpi->highs->getModelStatus() == HighsModelStatus::kUnbounded;
1807}
1808
1809/** returns TRUE iff LP is proven to be primal infeasible */
1811 SCIP_LPI* lpi /**< LP interface structure */
1812 )
1813{
1814 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
1815
1816 assert(lpi != NULL);
1817 assert(lpi->highs != NULL);
1818
1819 HighsModelStatus model_status = lpi->highs->getModelStatus();
1820
1821 /* not sure how to query HiGHS in this case, but we can easily decide */
1822 if( model_status == HighsModelStatus::kModelEmpty )
1823 {
1824 int numrow = lpi->highs->getNumRow();
1825
1826 assert(lpi->highs->getNumCol() == 0);
1827
1828 for( int i = 0; i < numrow; i++ )
1829 {
1830 if( lpi->highs->getLp().row_lower_[i] > 0.0 || lpi->highs->getLp().row_upper_[i] < 0.0 )
1831 return TRUE;
1832 }
1833 return FALSE;
1834 }
1835
1836 /* otherwise we rely on the model status */
1837 const bool primal_infeasible =
1838 model_status == HighsModelStatus::kInfeasible ||
1839 model_status == HighsModelStatus::kUnboundedOrInfeasible;
1840 return primal_infeasible;
1841}
1842
1843/** returns TRUE iff LP is proven to be primal feasible */
1845 SCIP_LPI* lpi /**< LP interface structure */
1846 )
1847{
1848 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
1849
1850 assert(lpi != NULL);
1851 assert(lpi->highs != NULL);
1852
1853 HighsModelStatus model_status = lpi->highs->getModelStatus();
1854
1855 /* not sure how to query HiGHS in this case, but we can easily decide */
1856 if( model_status == HighsModelStatus::kModelEmpty )
1857 {
1858 int numrow = lpi->highs->getNumRow();
1859
1860 assert(lpi->highs->getNumCol() == 0);
1861
1862 for( int i = 0; i < numrow; i++ )
1863 {
1864 if( lpi->highs->getLp().row_lower_[i] > 0.0 || lpi->highs->getLp().row_upper_[i] < 0.0 )
1865 return FALSE;
1866 }
1867 return TRUE;
1868 }
1869
1870 /* otherwise we rely on the model status */
1871 const bool primal_feasible =
1872 model_status == HighsModelStatus::kOptimal ||
1873 model_status == HighsModelStatus::kUnbounded;
1874 return primal_feasible;
1875}
1876
1877/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
1878 * this does not necessarily mean, that the solver knows and can return the dual ray
1879 */
1881 SCIP_LPI* lpi /**< LP interface structure */
1882 )
1883{
1884 SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
1885
1886 assert(lpi != NULL);
1887
1888 return !SCIPlpiIsPrimalFeasible(lpi);
1889}
1890
1891/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
1892 * and the solver knows and can return the dual ray
1893 */
1895 SCIP_LPI* lpi /**< LP interface structure */
1896 )
1897{
1898 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
1899
1900 assert(lpi != NULL);
1901 assert(lpi->highs != NULL);
1902
1903 HighsModelStatus model_status = lpi->highs->getModelStatus();
1904
1905 /* HiGHS does not implement this case, but we can easily decide */
1906 if( model_status == HighsModelStatus::kModelEmpty )
1907 return !SCIPlpiIsPrimalFeasible(lpi);
1908
1909 /* otherwise we rely on the model status */
1910 bool has_dual_ray = false;
1911 HIGHS_CALL( lpi->highs->getDualRay(has_dual_ray, NULL) );
1912 return has_dual_ray;
1913}
1914
1915/** returns TRUE iff LP is proven to be dual unbounded */
1917 SCIP_LPI* lpi /**< LP interface structure */
1918 )
1919{
1920 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
1921
1922 assert(lpi != NULL);
1923 assert(lpi->highs != NULL);
1924
1926}
1927
1928/** returns TRUE iff LP is proven to be dual infeasible */
1930 SCIP_LPI* lpi /**< LP interface structure */
1931 )
1932{
1933 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
1934
1935 assert(lpi != NULL);
1936 assert(lpi->highs != NULL);
1937
1938 HighsModelStatus model_status = lpi->highs->getModelStatus();
1939 const bool dual_infeasible =
1940 model_status == HighsModelStatus::kUnbounded ||
1941 model_status == HighsModelStatus::kUnboundedOrInfeasible;
1942 return dual_infeasible;
1943}
1944
1945/** returns TRUE iff LP is proven to be dual feasible */
1947 SCIP_LPI* lpi /**< LP interface structure */
1948 )
1949{
1950 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
1951
1952 assert(lpi != NULL);
1953 assert(lpi->highs != NULL);
1954
1955 HighsModelStatus model_status = lpi->highs->getModelStatus();
1956
1957 if( model_status == HighsModelStatus::kOptimal || model_status == HighsModelStatus::kModelEmpty )
1958 return TRUE;
1959 else if( model_status == HighsModelStatus::kUnbounded || model_status == HighsModelStatus::kUnboundedOrInfeasible )
1960 return FALSE;
1961
1962 int num_dual_infeasibilities = 1;
1963 HighsStatus status = lpi->highs->getInfoValue("num_dual_infeasibilities", num_dual_infeasibilities);
1964 bool has_dual_feasible_sol = (status == HighsStatus::kOk) && (num_dual_infeasibilities == 0);
1965 return has_dual_feasible_sol;
1966}
1967
1968/** returns TRUE iff LP was solved to optimality */
1970 SCIP_LPI* lpi /**< LP interface structure */
1971 )
1972{
1973 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
1974
1975 assert(lpi != NULL);
1976 assert(lpi->highs != NULL);
1977
1978 HighsModelStatus model_status = lpi->highs->getModelStatus();
1979
1980 if( model_status == HighsModelStatus::kModelEmpty )
1981 return SCIPlpiIsPrimalFeasible(lpi);
1982 else
1983 {
1984 assert(lpi->highs->getModelStatus() == HighsModelStatus::kOptimal || (!SCIPlpiIsPrimalFeasible(lpi) || !SCIPlpiIsDualFeasible(lpi)));
1985 assert(lpi->highs->getModelStatus() != HighsModelStatus::kOptimal || (SCIPlpiIsPrimalFeasible(lpi) && SCIPlpiIsDualFeasible(lpi)));
1986 return lpi->highs->getModelStatus() == HighsModelStatus::kOptimal;
1987 }
1988}
1989
1990/** returns TRUE iff current LP basis is stable */
1992 SCIP_LPI* lpi /**< LP interface structure */
1993 )
1994{
1995 SCIPdebugMessage("calling SCIPlpiIsStable()\n");
1996
1997 assert(lpi != NULL);
1998 assert(lpi->highs != NULL);
1999
2000 /* if an objective limit is set and HiGHS claims that it is exceeded, we should check that this is indeed the case;
2001 * if not this points at numerical instability; note that this aligns with an assert in lp.c */
2002 if( SCIPlpiIsObjlimExc(lpi) )
2003 {
2004 SCIP_Real objlimit;
2005 SCIP_Real objvalue;
2006
2007 HIGHS_CALL( lpi->highs->getOptionValue("objective_bound", objlimit) );
2008 HIGHS_CALL( lpi->highs->getInfoValue("objective_function_value", objvalue) );
2009
2010 if( lpi->highs->getLp().sense_ == ObjSense::kMaximize )
2011 {
2012 objlimit *= -1.0;
2013 objvalue *= -1.0;
2014 }
2015 if( !SCIPlpiIsInfinity(lpi, objlimit) && HIGHS_relDiff(objvalue, objlimit) < -1e-9 )
2016 return FALSE;
2017 }
2018
2019 return TRUE;
2020}
2021
2022/** returns TRUE iff the objective limit was reached */
2024 SCIP_LPI* lpi /**< LP interface structure */
2025 )
2026{
2027 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
2028
2029 assert(lpi != NULL);
2030 assert(lpi->highs != NULL);
2031
2032 return lpi->highs->getModelStatus() == HighsModelStatus::kObjectiveBound;
2033}
2034
2035/** returns TRUE iff the iteration limit was reached */
2037 SCIP_LPI* lpi /**< LP interface structure */
2038 )
2039{
2040 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
2041
2042 assert(lpi != NULL);
2043 assert(lpi->highs != NULL);
2044
2045 return lpi->highs->getModelStatus() == HighsModelStatus::kIterationLimit;
2046}
2047
2048/** returns TRUE iff the time limit was reached */
2050 SCIP_LPI* lpi /**< LP interface structure */
2051 )
2052{
2053 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
2054
2055 assert(lpi != NULL);
2056 assert(lpi->highs != NULL);
2057
2058 return lpi->highs->getModelStatus() == HighsModelStatus::kTimeLimit;
2059}
2060
2061/** returns the internal solution status of the solver */
2063 SCIP_LPI* lpi /**< LP interface structure */
2064 )
2065{
2066 SCIPdebugMessage("calling SCIPlpiGetInternalStatus()\n");
2067
2068 assert(lpi != NULL);
2069 assert(lpi->highs != NULL);
2070
2071 return (int) lpi->highs->getModelStatus();
2072}
2073
2074/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
2076 SCIP_LPI* lpi, /**< LP interface structure */
2077 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
2078 )
2079{
2080 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
2081
2082 assert(lpi != NULL);
2083 assert(lpi->highs != NULL);
2084
2085 assert(success != NULL);
2086
2087 *success = TRUE;
2088 return SCIP_OKAY;
2089}
2090
2091/** gets objective value of solution */
2093 SCIP_LPI* lpi, /**< LP interface structure */
2094 SCIP_Real* objval /**< stores the objective value */
2095 )
2096{
2097 SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
2098
2099 assert(lpi != NULL);
2100 assert(lpi->highs != NULL);
2101 assert(objval != NULL);
2102
2103 HIGHS_CALL( lpi->highs->getInfoValue("objective_function_value", *objval) );
2104 assert(lpi->highs->getModelStatus() != HighsModelStatus::kModelEmpty || *objval == 0.0);
2105
2106 return SCIP_OKAY;
2107}
2108
2109/** gets primal and dual solution vectors for feasible LPs
2110 *
2111 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
2112 * SCIPlpiIsOptimal() returns true.
2113 */
2115 SCIP_LPI* lpi, /**< LP interface structure */
2116 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
2117 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
2118 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
2119 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
2120 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
2121 )
2122{
2123 SCIPdebugMessage("calling SCIPlpiGetSol()\n");
2124
2125 assert(lpi != NULL);
2126 assert(lpi->highs != NULL);
2127
2128 int ncols;
2129 int nrows;
2130 int i;
2131
2132 if( objval != NULL )
2133 {
2134 HIGHS_CALL( lpi->highs->getInfoValue("objective_function_value", *objval) );
2135 assert(lpi->highs->getModelStatus() != HighsModelStatus::kModelEmpty || *objval == 0.0);
2136 }
2137
2138 const std::vector<double> &colValue = lpi->highs->getSolution().col_value;
2139 const std::vector<double> &colDual = lpi->highs->getSolution().col_dual;
2140 const std::vector<double> &rowValue = lpi->highs->getSolution().row_value;
2141 const std::vector<double> &rowDual = lpi->highs->getSolution().row_dual;
2142
2143 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
2144 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
2145 if( colValue.size() != (size_t) ncols || colDual.size() != (size_t) ncols
2146 || rowValue.size() != (size_t) nrows || rowDual.size() != (size_t) nrows )
2147 {
2148 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);
2149 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);
2150 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);
2151 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);
2152 assert((int) rowValue.size() == nrows);
2153 SCIPmessagePrintWarning( lpi->messagehdlr, "HiGHS returned solution vector of inconsistent dimension\n" );
2154 return SCIP_LPERROR;
2155 }
2156
2157 if( primsol != NULL )
2158 for( i = 0; i < ncols; i++ )
2159 primsol[i] = colValue[i];
2160 if( dualsol != NULL )
2161 for( i = 0; i < nrows; i++ )
2162 dualsol[i] = rowDual[i];
2163 if( activity != NULL )
2164 for( i = 0; i < nrows; i++ )
2165 activity[i] = rowValue[i];
2166 if( redcost != NULL )
2167 for( i = 0; i < ncols; i++ )
2168 redcost[i] = colDual[i];
2169
2170 return SCIP_OKAY;
2171}
2172
2173
2174/** gets primal ray for unbounded LPs */
2176 SCIP_LPI* lpi, /**< LP interface structure */
2177 SCIP_Real* ray /**< primal ray */
2178 )
2179{
2180 SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
2181
2182 bool success = false;
2183
2184 assert(lpi != NULL);
2185 assert(lpi->highs != NULL);
2186 assert(SCIPlpiHasPrimalRay(lpi));
2187
2188 /* HiGHS does not implement this case, but we can easily construct an unbounded primal ray */
2189 if( lpi->highs->getNumRow() == 0 )
2190 {
2191 int numcol = lpi->highs->getNumCol();
2192
2193 for( int i = 0; i < numcol; i++ )
2194 {
2195 SCIP_Real minobj = lpi->highs->getLp().col_cost_[i];
2196 if( lpi->highs->getLp().sense_ == ObjSense::kMaximize )
2197 minobj = -minobj;
2198
2199 if( SCIPlpiIsInfinity(lpi, -lpi->highs->getLp().col_lower_[i]) && minobj > 0.0 )
2200 {
2201 ray[i] = -1.0;
2202 success = true;
2203 }
2204 else if( SCIPlpiIsInfinity(lpi, lpi->highs->getLp().col_upper_[i]) && minobj < 0.0 )
2205 {
2206 ray[i] = 1.0;
2207 success = true;
2208 }
2209 else
2210 ray[i] = 0.0;
2211 }
2212 }
2213 else
2214 {
2215 HIGHS_CALL( lpi->highs->getPrimalRay(success, ray) );
2216 }
2217
2218 return success ? SCIP_OKAY : SCIP_LPERROR;
2219}
2220
2221/** gets dual Farkas proof for infeasibility */
2223 SCIP_LPI* lpi, /**< LP interface structure */
2224 SCIP_Real* dualfarkas /**< dual farkas row multipliers */
2225 )
2226{
2227 SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
2228
2229 assert(lpi != NULL);
2230 assert(lpi->highs != NULL);
2231 assert(dualfarkas != NULL);
2232
2233 HighsModelStatus model_status = lpi->highs->getModelStatus();
2234
2235 /* HiGHS does not implement this case, but we can easily construct an unbounded dual ray */
2236 if( model_status == HighsModelStatus::kModelEmpty )
2237 {
2238 SCIP_Real dualdir = lpi->highs->getLp().sense_ == ObjSense::kMinimize ? 1.0 : -1.0;
2239 int numrow = lpi->highs->getNumRow();
2240
2241 assert(lpi->highs->getNumCol() == 0);
2242
2243 for( int i = 0; i < numrow; i++ )
2244 {
2245 if( lpi->highs->getLp().row_lower_[i] > 0.0 )
2246 dualfarkas[i] = dualdir;
2247 else if( lpi->highs->getLp().row_upper_[i] < 0.0 )
2248 dualfarkas[i] = -dualdir;
2249 else
2250 dualfarkas[i] = 0.0;
2251 }
2252
2253 return SCIP_OKAY;
2254 }
2255
2256 bool has_dual_ray = false;
2257 HIGHS_CALL( lpi->highs->getDualRay(has_dual_ray, dualfarkas) );
2258
2259 return has_dual_ray ? SCIP_OKAY : SCIP_LPERROR;
2260}
2261
2262/** gets the number of LP iterations of the last solve call */
2264 SCIP_LPI* lpi, /**< LP interface structure */
2265 int* iterations /**< pointer to store the number of iterations of the last solve call */
2266 )
2267{
2268 SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
2269
2270 assert(lpi != NULL);
2271 assert(lpi->highs != NULL);
2272 assert(iterations != NULL);
2273
2274 *iterations = 0;
2275 /* this may return with a warning if the last solve failed */
2276 HIGHS_CALL_WITH_WARNING( lpi->highs->getInfoValue("simplex_iteration_count", *iterations) );
2277 assert(*iterations >= 0);
2278 return SCIP_OKAY;
2279}
2280
2281/** gets information about the quality of an LP solution
2282 *
2283 * Such information is usually only available, if also a (maybe not optimal) solution is available.
2284 * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
2285 */
2287 SCIP_LPI* lpi, /**< LP interface structure */
2288 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
2289 SCIP_Real* quality /**< pointer to store quality number */
2290 )
2291{
2292 SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
2293
2294 assert(lpi != NULL);
2295 assert(lpi->highs != NULL);
2296 assert(quality != NULL);
2297
2298 *quality = SCIP_INVALID;
2299
2300 return SCIP_OKAY;
2301}
2302
2303/**@} */
2304
2305/*
2306 * LP Basis Methods
2307 */
2308
2309/**@name LP Basis Methods */
2310/**@{ */
2311
2312/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
2314 SCIP_LPI* lpi, /**< LP interface structure */
2315 int* cstat, /**< array to store column basis status, or NULL */
2316 int* rstat /**< array to store row basis status, or NULL */
2317 )
2318{
2319 SCIPdebugMessage("calling SCIPlpiGetBase()\n");
2320
2321 assert(lpi != NULL);
2322 assert(lpi->highs != NULL);
2323
2324 if( cstat != NULL )
2325 {
2326 for( int i = 0; i < lpi->highs->getLp().num_col_; ++i )
2327 cstat[i] = (int) lpi->highs->getBasis().col_status[i];
2328 }
2329 if( rstat != NULL )
2330 {
2331 for( int i = 0; i < lpi->highs->getLp().num_row_; ++i )
2332 rstat[i] = (int) lpi->highs->getBasis().row_status[i];
2333 }
2334
2335 return SCIP_OKAY;
2336}
2337
2338/** sets current basis status for columns and rows */
2340 SCIP_LPI* lpi, /**< LP interface structure */
2341 const int* cstat, /**< array with column basis status */
2342 const int* rstat /**< array with row basis status */
2343 )
2344{
2345 SCIPdebugMessage("calling SCIPlpiSetBase()\n");
2346
2347 assert(lpi != NULL);
2348 assert(lpi->highs != NULL);
2349
2350 HighsBasis local_highs_basis;
2351
2352 local_highs_basis.col_status.resize(lpi->highs->getLp().num_col_);
2353 local_highs_basis.row_status.resize(lpi->highs->getLp().num_row_);
2354
2355 if( cstat != NULL )
2356 {
2357 for( int i = 0; i < lpi->highs->getLp().num_col_; ++i )
2358 local_highs_basis.col_status[i] = basestatToHighsBasisStatus(cstat[i]);
2359 }
2360 if( rstat != NULL )
2361 {
2362 for( int i = 0; i < lpi->highs->getLp().num_row_; ++i )
2363 local_highs_basis.row_status[i] = basestatToHighsBasisStatus(rstat[i]);
2364 }
2365 HIGHS_CALL( lpi->highs->setBasis(local_highs_basis) );
2366
2367 return SCIP_OKAY;
2368}
2369
2370/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
2372 SCIP_LPI* lpi, /**< LP interface structure */
2373 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
2374 )
2375 {
2376 SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
2377
2378 assert(lpi != NULL);
2379 assert(lpi->highs != NULL);
2380 assert(bind != NULL);
2381
2382 if( !lpi->highs->getBasis().valid )
2383 {
2384 SCIPdebugMessage( "HiGHS Basis is not valid in function call SCIPlpiGetBasisInd()\n" );
2385 return SCIP_ERROR;
2386 }
2387 HIGHS_CALL( lpi->highs->getBasicVariables(bind) );
2388
2389 return SCIP_OKAY;
2390}
2391
2392/** get row of inverse basis matrix B^-1
2393 *
2394 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2395 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2396 * see also the explanation in lpi.h.
2397 */
2399 SCIP_LPI* lpi, /**< LP interface structure */
2400 int r, /**< row number */
2401 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
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 SCIPlpiGetBInvRow()\n");
2408
2409 assert(lpi != NULL);
2410 assert(lpi->highs != NULL);
2411
2412 if( lpi->highs->getBasisInverseRow(r, coef, ninds, inds) != HighsStatus::kOk )
2413 {
2415 }
2416
2417 HIGHS_CALL( lpi->highs->getBasisInverseRow(r, coef, ninds, inds) );
2418 return SCIP_OKAY;
2419}
2420
2421/** get column of inverse basis matrix B^-1
2422 *
2423 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2424 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2425 * see also the explanation in lpi.h.
2426 */
2428 SCIP_LPI* lpi, /**< LP interface structure */
2429 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
2430 * you have to call SCIPlpiGetBasisInd() to get the array which links the
2431 * B^-1 column numbers to the row and column numbers of the LP!
2432 * c must be between 0 and nrows-1, since the basis has the size
2433 * nrows * nrows */
2434 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
2435 int* inds, /**< array to store the non-zero indices, or NULL */
2436 int* ninds /**< pointer to store the number of non-zero indices, or NULL
2437 * (-1: if we do not store sparsity information) */
2438 )
2439{
2440 SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
2441
2442 assert(lpi != NULL);
2443 assert(lpi->highs != NULL);
2444
2445 if( lpi->highs->getBasisInverseCol(c, coef, ninds, inds) != HighsStatus::kOk )
2446 {
2448 }
2449
2450 HIGHS_CALL( lpi->highs->getBasisInverseCol(c, coef, ninds, inds) );
2451
2452 return SCIP_OKAY;
2453}
2454
2455/** get row of inverse basis matrix times constraint matrix B^-1 * A
2456 *
2457 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2458 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2459 * see also the explanation in lpi.h.
2460 */
2462 SCIP_LPI* lpi, /**< LP interface structure */
2463 int r, /**< row number */
2464 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
2465 SCIP_Real* coef, /**< vector to return coefficients of the row */
2466 int* inds, /**< array to store the non-zero indices, or NULL */
2467 int* ninds /**< pointer to store the number of non-zero indices, or NULL
2468 * (-1: if we do not store sparsity information) */
2469 )
2470{
2471 SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
2472
2473 assert(lpi != NULL);
2474 assert(lpi->highs != NULL);
2475
2476 if( lpi->highs->getReducedRow(r, coef, ninds, inds, binvrow) != HighsStatus::kOk )
2477 {
2479 }
2480
2481 HIGHS_CALL( lpi->highs->getReducedRow(r, coef, ninds, inds, binvrow) );
2482
2483 return SCIP_OKAY;
2484}
2485
2486/** get dense column of inverse basis matrix times constraint matrix B^-1 * A
2487 *
2488 * @note The LP interface defines slack variables to have coefficient +1. This
2489 * means that if, internally, the LP solver uses a -1 coefficient, then rows
2490 * associated with slacks variables whose coefficient is -1, should be negated;
2491 * see also the explanation in lpi.h.
2492 */
2494 SCIP_LPI* lpi, /**< LP interface structure */
2495 int c, /**< column number */
2496 SCIP_Real* coef, /**< vector to return coefficients of the column */
2497 int* inds, /**< array to store the non-zero indices, or NULL */
2498 int* ninds /**< pointer to store the number of non-zero indices, or NULL
2499 * (-1: if we do not store sparsity information) */
2500 )
2501{
2502 SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
2503
2504 assert(lpi != NULL);
2505 assert(lpi->highs != NULL);
2506
2507 if( lpi->highs->getReducedColumn(c, coef, ninds, inds) != HighsStatus::kOk )
2508 {
2510 }
2511
2512 HIGHS_CALL( lpi->highs->getReducedColumn(c, coef, ninds, inds) );
2513 return SCIP_OKAY;
2514}
2515
2516/**@} */
2517
2518/*
2519 * LP State Methods
2520 */
2521
2522/**@name LP State Methods */
2523/**@{ */
2524
2525/** stores LPi state (like basis information) into lpistate object */
2527 SCIP_LPI* lpi, /**< LP interface structure */
2528 BMS_BLKMEM* blkmem, /**< block memory */
2529 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
2530 )
2531{
2532 SCIPdebugMessage("calling SCIPlpiGetState()\n");
2533
2534 assert(blkmem != NULL);
2535
2536 assert(lpi != NULL);
2537 assert(lpi->highs != NULL);
2538 assert(lpistate != NULL);
2539
2540 int ncols;
2541 int nrows;
2542
2543 ncols = lpi->highs->getLp().num_col_;
2544 nrows = lpi->highs->getLp().num_row_;
2545 assert(ncols >= 0);
2546 assert(nrows >= 0);
2547
2548 /* allocate lpistate data */
2549 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
2550
2551 /* allocate enough memory for storing uncompressed basis information */
2552 SCIP_CALL( ensureCstatMem(lpi, ncols) );
2553 SCIP_CALL( ensureRstatMem(lpi, nrows) );
2554
2555 /* get unpacked basis information */
2556 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
2557
2558 /* pack LPi state data */
2559 (*lpistate)->ncols = ncols;
2560 (*lpistate)->nrows = nrows;
2561 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
2562
2563 return SCIP_OKAY;
2564}
2565
2566/** loads LPi state (like basis information) into solver; note that the LP might
2567 * have been extended with additional columns and rows since the state was
2568 * stored with SCIPlpiGetState()
2569 */
2571 SCIP_LPI* lpi, /**< LP interface structure */
2572 BMS_BLKMEM* blkmem, /**< block memory */
2573 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
2574 )
2575{
2576 SCIPdebugMessage("calling SCIPlpiSetState()\n");
2577
2578 assert(lpi != NULL);
2579 assert(lpi->highs != NULL);
2580 assert(lpistate != NULL);
2581
2582 int lpncols;
2583 int lpnrows;
2584 int i;
2585
2586 lpncols = lpi->highs->getLp().num_col_;
2587 lpnrows = lpi->highs->getLp().num_row_;
2588 assert(lpistate->ncols <= lpncols);
2589 assert(lpistate->nrows <= lpnrows);
2590
2591 /* allocate enough memory for storing uncompressed basis information */
2592 SCIP_CALL( ensureCstatMem(lpi, lpncols) );
2593 SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
2594
2595 /* unpack LPi state data */
2596 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
2597
2598 /* extend the basis to the current LP beyond the previously existing columns */
2599 for( i = lpistate->ncols; i < lpncols; ++i )
2600 {
2601 if( !SCIPlpiIsInfinity(lpi, -lpi->highs->getLp().col_lower_[i]) )
2602 /* use finite lower bound */
2603 lpi->cstat[i] = SCIP_BASESTAT_LOWER;
2604 else if( !SCIPlpiIsInfinity(lpi, lpi->highs->getLp().col_upper_[i]) )
2605 /* use finite upper bound */
2606 lpi->cstat[i] = SCIP_BASESTAT_UPPER;
2607 else
2608 /* variable is free */
2609 lpi->cstat[i] = SCIP_BASESTAT_ZERO;
2610 }
2611 for( i = lpistate->nrows; i < lpnrows; ++i )
2612 lpi->rstat[i] = SCIP_BASESTAT_BASIC;
2613
2614 /* load basis information */
2615 SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
2616
2617 return SCIP_OKAY;
2618}
2619
2620/** clears current LPi state (like basis information) of the solver */
2622 SCIP_LPI* lpi /**< LP interface structure */
2623)
2624{
2625 SCIPdebugMessage("calling SCIPlpiClearState()\n");
2626
2627 assert(lpi != NULL);
2628 assert(lpi->highs != NULL);
2629
2630 HIGHS_CALL( lpi->highs->clearSolver() );
2631 return SCIP_OKAY;
2632}
2633
2634/** frees LPi state information */
2636 SCIP_LPI* lpi, /**< LP interface structure */
2637 BMS_BLKMEM* blkmem, /**< block memory */
2638 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
2639)
2640{
2641 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
2642
2643 assert(lpi != NULL);
2644 assert(lpistate != NULL);
2645
2646 if( *lpistate != NULL )
2647 lpistateFree(lpistate, blkmem);
2648
2649 return SCIP_OKAY;
2650}
2651
2652/** checks, whether the given LP state contains simplex basis information */
2654 SCIP_LPI* lpi, /**< LP interface structure */
2655 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
2656 )
2657{
2658 SCIPdebugMessage("calling SCIPlpiHasStateBasis()\n");
2659 assert(lpi != NULL);
2660 return TRUE;
2661}
2662
2663/** reads LP state (like basis information from a file */
2665 SCIP_LPI* lpi, /**< LP interface structure */
2666 const char* fname /**< file name */
2667)
2668{
2669 SCIPdebugMessage("calling SCIPlpiReadState()\n");
2670
2671 assert(lpi != NULL);
2672 assert(lpi->highs != NULL);
2673
2674 HIGHS_CALL( lpi->highs->readBasis(fname) );
2675 return SCIP_OKAY;
2676}
2677
2678/** writes LPi state (i.e. basis information) to a file */
2680 SCIP_LPI* lpi, /**< LP interface structure */
2681 const char* fname /**< file name */
2682)
2683{
2684 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
2685
2686 assert(lpi != NULL);
2687 assert(lpi->highs != NULL);
2688
2689 HIGHS_CALL( lpi->highs->writeBasis(fname) );
2690 return SCIP_OKAY;
2691}
2692
2693/**@} */
2694
2695/*
2696 * LP Pricing Norms Methods
2697 */
2698
2699/**@name LP Pricing Norms Methods */
2700/**@{ */
2701
2702/** stores LPi pricing norms information
2703 * @todo Could storing norm information improve warm start performance in HiGHS?
2704 */
2706 SCIP_LPI* lpi, /**< LP interface structure */
2707 BMS_BLKMEM* blkmem, /**< block memory */
2708 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
2709)
2710{
2711 SCIPdebugMessage("calling SCIPlpiGetNorms()\n");
2712
2713 assert(lpi != NULL);
2714 assert(lpinorms != NULL);
2715
2716 (*lpinorms) = NULL;
2717
2718 return SCIP_OKAY;
2719}
2720
2721/** loads LPi pricing norms into solver; note that the LP might have been extended with additional
2722 * columns and rows since the state was stored with SCIPlpiGetNorms()
2723 */
2725 SCIP_LPI* lpi, /**< LP interface structure */
2726 BMS_BLKMEM* blkmem, /**< block memory */
2727 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
2728 )
2729{
2730 SCIPdebugMessage("calling SCIPlpiSetNorms()\n");
2731
2732 assert(lpi != NULL);
2733 assert(lpinorms == NULL);
2734
2735 /* no work necessary */
2736 return SCIP_OKAY;
2737}
2738
2739/** frees pricing norms information */
2741 SCIP_LPI* lpi, /**< LP interface structure */
2742 BMS_BLKMEM* blkmem, /**< block memory */
2743 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
2744 )
2745{
2746 SCIPdebugMessage("calling SCIPlpiFreeNorms()\n");
2747
2748 assert(lpi != NULL);
2749 assert(lpinorms == NULL);
2750
2751 /* no work necessary */
2752 return SCIP_OKAY;
2753}
2754
2755/**@} */
2756
2757/*
2758 * Parameter Methods
2759 */
2760
2761/**@name Parameter Methods */
2762/**@{ */
2763
2764/** gets integer parameter of LP */
2766 SCIP_LPI* lpi, /**< LP interface structure */
2767 SCIP_LPPARAM type, /**< parameter number */
2768 int* ival /**< buffer to store the parameter value */
2769 )
2770{
2771 SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
2772
2773 assert(lpi != NULL);
2774 assert(lpi->highs != NULL);
2775 assert(ival != NULL);
2776
2777 switch( type )
2778 {
2780 *ival = (int) lpi->fromscratch;
2781 break;
2782 case SCIP_LPPAR_LPINFO:
2783 {
2784 bool bool_ival;
2785 HIGHS_CALL( lpi->highs->getOptionValue("output_flag", bool_ival) );
2786 *ival = bool_ival;
2787 }
2788 break;
2789 case SCIP_LPPAR_SCALING:
2790 HIGHS_CALL( lpi->highs->getOptionValue("simplex_scale_strategy", *ival) );
2791 assert(*ival == 0 || *ival == 2 || *ival == 4); /* values used in SCIPlpiSetIntpar() */
2792 if( *ival <= 0 )
2793 *ival = 0;
2794 else if( *ival <= 2 )
2795 *ival = 1;
2796 else
2797 *ival = 2;
2798 break;
2800 *ival = lpi->presolve;
2801 break;
2802 case SCIP_LPPAR_PRICING:
2803 *ival = (int)lpi->pricing; /* store pricing method in LPI struct */
2804 break;
2805 case SCIP_LPPAR_THREADS:
2806 *ival = lpi->nthreads;
2807 break;
2808 case SCIP_LPPAR_LPITLIM:
2809 HIGHS_CALL( lpi->highs->getOptionValue("simplex_iteration_limit", *ival) );
2810 break;
2812 HIGHS_CALL( lpi->highs->getOptionValue("random_seed", *ival) );
2813 break;
2814 default:
2815 return SCIP_PARAMETERUNKNOWN;
2816 }
2817
2818 return SCIP_OKAY;
2819}
2820
2821/** sets integer parameter of LP */
2823 SCIP_LPI* lpi, /**< LP interface structure */
2824 SCIP_LPPARAM type, /**< parameter number */
2825 int ival /**< parameter value */
2826 )
2827{
2828 SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
2829
2830 assert(lpi != NULL);
2831 assert(lpi->highs != NULL);
2832
2833 switch( type )
2834 {
2836 assert(ival == TRUE || ival == FALSE);
2837 lpi->fromscratch = (SCIP_Bool) ival;
2838 break;
2839 case SCIP_LPPAR_LPINFO:
2840 assert(ival == TRUE || ival == FALSE);
2841 HIGHS_CALL( lpi->highs->setOptionValue("output_flag", (bool) ival) );
2842 break;
2843 case SCIP_LPPAR_SCALING:
2844 assert(ival >= 0 && ival <= 2);
2845 if( ival == 0 )
2846 /* off */
2847 HIGHS_CALL( lpi->highs->setOptionValue("simplex_scale_strategy", 0) );
2848 else if( ival == 1 )
2849 /* forced equilibration */
2850 HIGHS_CALL( lpi->highs->setOptionValue("simplex_scale_strategy", 2) );
2851 else
2852 /* max. value scaling */
2853 HIGHS_CALL( lpi->highs->setOptionValue("simplex_scale_strategy", 4) );
2854 break;
2856 assert(ival == TRUE || ival == FALSE);
2857 lpi->presolve = ival;
2858 HIGHS_CALL( lpi->highs->setOptionValue("presolve", ival ? "on" : "off") );
2859 break;
2860 case SCIP_LPPAR_PRICING:
2861 lpi->pricing = (SCIP_PRICING)ival;
2862 switch( lpi->pricing )
2863 {
2866 case SCIP_PRICING_AUTO:
2867 HIGHS_CALL( lpi->highs->setOptionValue("simplex_primal_edge_weight_strategy", -1) );
2868 HIGHS_CALL( lpi->highs->setOptionValue("simplex_dual_edge_weight_strategy", -1) );
2869 break;
2870 case SCIP_PRICING_DEVEX:
2871 HIGHS_CALL( lpi->highs->setOptionValue("simplex_primal_edge_weight_strategy", 1) );
2872 HIGHS_CALL( lpi->highs->setOptionValue("simplex_dual_edge_weight_strategy", 1) );
2873 break;
2874 case SCIP_PRICING_FULL:
2875 case SCIP_PRICING_STEEP:
2877 HIGHS_CALL( lpi->highs->setOptionValue("simplex_primal_edge_weight_strategy", 2) );
2878 HIGHS_CALL( lpi->highs->setOptionValue("simplex_dual_edge_weight_strategy", 2) );
2879 break;
2880 default:
2881 return SCIP_LPERROR;
2882 }
2883 break;
2884 case SCIP_LPPAR_THREADS:
2885 lpi->nthreads = ival;
2886 break;
2887 case SCIP_LPPAR_LPITLIM:
2888 HIGHS_CALL( lpi->highs->setOptionValue("simplex_iteration_limit", ival) );
2889 break;
2891 HIGHS_CALL( lpi->highs->setOptionValue("random_seed", ival) );
2892 break;
2893 default:
2894 return SCIP_PARAMETERUNKNOWN;
2895 }
2896
2897 return SCIP_OKAY;
2898}
2899
2900/** gets floating point parameter of LP */
2902 SCIP_LPI* lpi, /**< LP interface structure */
2903 SCIP_LPPARAM type, /**< parameter number */
2904 SCIP_Real* dval /**< buffer to store the parameter value */
2905)
2906{
2907 SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
2908
2909 assert(lpi != NULL);
2910 assert(lpi->highs != NULL);
2911 assert(dval != NULL);
2912
2913 switch( type )
2914 {
2915 case SCIP_LPPAR_FEASTOL:
2916 HIGHS_CALL( lpi->highs->getOptionValue("primal_feasibility_tolerance", *dval) );
2917 break;
2919 HIGHS_CALL( lpi->highs->getOptionValue("dual_feasibility_tolerance", *dval) );
2920 break;
2921 case SCIP_LPPAR_LPTILIM:
2922 HIGHS_CALL( lpi->highs->getOptionValue("time_limit", *dval) );
2923 break;
2924 case SCIP_LPPAR_OBJLIM:
2925 HIGHS_CALL( lpi->highs->getOptionValue("objective_bound", *dval) );
2926 break;
2927 default:
2928 return SCIP_PARAMETERUNKNOWN;
2929 }
2930
2931 return SCIP_OKAY;
2932}
2933
2934/** sets floating point parameter of LP */
2936 SCIP_LPI* lpi, /**< LP interface structure */
2937 SCIP_LPPARAM type, /**< parameter number */
2938 SCIP_Real dval /**< parameter value */
2939 )
2940{
2941 SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
2942
2943 assert(lpi != NULL);
2944 assert(lpi->highs != NULL);
2945
2946 switch( type )
2947 {
2948 case SCIP_LPPAR_FEASTOL:
2949 /* Primal feasibility tolerance cannot be smaller than 1e-10 */
2950 dval = MAX(dval, 1e-10);
2951 HIGHS_CALL( lpi->highs->setOptionValue("primal_feasibility_tolerance", dval) );
2952 break;
2954 /* Dual feasibility tolerance cannot be smaller than 1e-10 */
2955 dval = MAX(dval, 1e-10);
2956 HIGHS_CALL( lpi->highs->setOptionValue("dual_feasibility_tolerance", dval) );
2957 break;
2958 case SCIP_LPPAR_LPTILIM:
2959 HIGHS_CALL( lpi->highs->setOptionValue("time_limit", dval) );
2960 break;
2961 case SCIP_LPPAR_OBJLIM:
2962 HIGHS_CALL( lpi->highs->setOptionValue("objective_bound", dval) );
2963 break;
2964 default:
2965 return SCIP_PARAMETERUNKNOWN;
2966 }
2967
2968 return SCIP_OKAY;
2969}
2970
2971/** interrupts the currently ongoing lp solve or disables the interrupt */
2973 SCIP_LPI* lpi, /**< LP interface structure */
2974 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
2975 )
2976{
2977 SCIPdebugMessage("calling SCIPlpiInterrupt()\n");
2978
2979 assert(lpi != NULL);
2980 assert(lpi->highs != NULL);
2981
2982 /* not implemented */
2983 return SCIP_OKAY;
2984}
2985
2986
2987/**@} */
2988
2989/*
2990 * Numerical Methods
2991 */
2992
2993/**@name Numerical Methods */
2994/**@{ */
2995
2996/** returns value treated as infinity in the LP solver */
2998 SCIP_LPI* lpi /**< LP interface structure */
2999 )
3000{
3001 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
3002
3003 assert(lpi != NULL);
3004
3005 return kHighsInf;
3006}
3007
3008/** checks if given value is treated as infinity in the LP solver */
3010 SCIP_LPI* lpi, /**< LP interface structure */
3011 SCIP_Real val
3012 )
3013{
3014 SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
3015
3016 assert(lpi != NULL);
3017
3018 return val >= kHighsInf;
3019}
3020
3021/**@} */
3022
3023/*
3024 * File Interface Methods
3025 */
3026
3027/**@name File Interface Methods */
3028/**@{ */
3029
3030/** reads LP from a file */
3032 SCIP_LPI* lpi, /**< LP interface structure */
3033 const char* fname /**< file name */
3034 )
3035{
3036 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
3037
3038 assert(lpi != NULL);
3039 assert(lpi->highs != NULL);
3040 assert(fname != NULL);
3041
3042 HIGHS_CALL( lpi->highs->readModel(fname) );
3043
3044 return SCIP_OKAY;
3045}
3046
3047/** writes LP to a file */
3049 SCIP_LPI* lpi, /**< LP interface structure */
3050 const char* fname /**< file name */
3051 )
3052{
3053 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
3054 assert(fname != NULL);
3055
3056 assert(lpi != NULL);
3057 assert(lpi->highs != NULL);
3058
3059 HIGHS_CALL( lpi->highs->writeModel(fname) );
3060
3061 return SCIP_OKAY;
3062}
3063
3064/**@} */
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:262
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_ALLOC(x)
Definition: def.h:380
#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:234
#define SCIP_CALL(x)
Definition: def.h:369
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_highs.cpp:1039
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPISTATE *lpistate)
Definition: lpi_highs.cpp:2570
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_highs.cpp:2493
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_highs.cpp:2901
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:2997
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:2023
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_highs.cpp:1089
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
Definition: lpi_highs.cpp:3009
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:978
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:2621
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1880
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1758
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_highs.cpp:2313
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_highs.cpp:2664
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_highs.cpp:878
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_highs.cpp:2175
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_highs.cpp:2765
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_highs.cpp:3048
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:1929
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_highs.cpp:2935
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:1560
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_highs.cpp:2724
SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
Definition: lpi_highs.cpp:1212
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:1648
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_highs.cpp:1379
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_highs.cpp:615
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_highs.cpp:2222
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_highs.cpp:2092
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_highs.cpp:1150
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:2062
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1534
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_highs.cpp:1737
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_highs.cpp:2740
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:2036
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_highs.cpp:996
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1797
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_highs.cpp:2075
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_highs.cpp:2679
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:1602
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_highs.cpp:1435
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1844
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_highs.cpp:3031
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_highs.cpp:2286
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1946
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_highs.cpp:2705
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:2049
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_highs.cpp:2653
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_highs.cpp:2822
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:2339
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1775
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_highs.cpp:2398
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_highs.cpp:928
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:1233
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_highs.cpp:2427
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_highs.cpp:1292
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_highs.cpp:2461
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:1264
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1716
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_highs.cpp:556
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_highs.cpp:1519
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1969
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_highs.cpp:1315
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_highs.cpp:606
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1547
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_highs.cpp:1407
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:1676
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:2114
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1894
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_highs.cpp:856
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_highs.cpp:1356
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_highs.cpp:2635
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1810
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1486
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:1464
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:1916
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_highs.cpp:2263
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_highs.cpp:2371
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:1107
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_highs.cpp:1338
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_highs.cpp:1991
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_highs.cpp:1195
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_highs.cpp:2972
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:954
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_highs.cpp:1129
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_highs.cpp:1178
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_highs.cpp:2526
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_highs.cpp:1068
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