Scippy

SCIP

Solving Constraint Integer Programs

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