Scippy

SCIP

Solving Constraint Integer Programs

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