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