SCIP Doxygen Documentation
Loading...
Searching...
No Matches
lpiexact_spx.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-2026 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 lpiexact_spx.cpp
26 * @ingroup LPIEXACTS
27 * @brief exact LP interface for SoPlex
28 * @author Leon Eifler
29 *
30 * This is an implementation of SCIP's LP interface for SoPlex.
31 *
32 * For debugging purposes, the SoPlex results can be double checked with CPLEX if WITH_LPSCHECK is defined. This may
33 * yield false positives, since the LP is dumped to a file for transferring it to CPLEX, hence, precision may be lost.
34 */
35
36/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37#include "scip/def.h"
39#include "scip/type_retcode.h"
41#include "lpiexact/lpiexact.h"
42#include "scip/rational.h"
43#include "scip/rationalgmp.h"
44
45/* check the return value of setParam methods */
46#define CHECK_SOPLEX_PARAM(x) \
47 if( !x ) \
48 { \
49 SCIPmessagePrintWarning(_messagehdlr, "SoPlex: unsupported parameter value\n"); \
50 }
51
52/* remember the original value of the SCIP_DEBUG define and undefine it */
53#ifdef SCIP_DEBUG
54#define ___DEBUG
55#undef SCIP_DEBUG
56#endif
57
58/* disable -Wclass-memaccess warnings due to dubious memcpy/realloc calls in SoPlex headers, e.g.,
59 * dataarray.h:314:16: warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘struct soplex::SPxParMultPR::SPxParMultPr_Tmp’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess]
60 */
61#ifdef __GNUC__
62#if __GNUC__ >= 8
63#pragma GCC diagnostic ignored "-Wclass-memaccess"
64#endif
65#endif
66
67/* include SoPlex solver */
68#include "soplex.h"
69
70/* define subversion for versions <= 1.5.0.1 */
71#ifndef SOPLEX_SUBVERSION
72#define SOPLEX_SUBVERSION 0
73#endif
74/* define API version for versions <= 3.0.0 */
75#ifndef SOPLEX_APIVERSION
76#define SOPLEX_APIVERSION 0
77#endif
78
79/* check version */
80#if (SOPLEX_APIVERSION < 11)
81#error "This interface requires SoPlex with API version 11 or higher, which is available from SoPlex 5.0.0."
82#endif
83
84#if (SOPLEX_APIVERSION <= 5)
85#include "spxgithash.h"
86#endif
87
88#ifndef SOPLEX_WITH_GMP
89#error "SOPLEX_WITH_GMP not defined: SoPlex must be build with GMP to be used with LPSEXACT=spx"
90#endif
91
92#ifndef SOPLEX_WITH_MPFR
93#error "SOPLEX_WITH_MPFR not defined: SoPlex must be build with MPFR to be used with LPSEXACT=spx"
94#endif
95
96#ifndef SOPLEX_WITH_BOOST
97#error "SOPLEX_WITH_BOOST not defined: SoPlex must be build with BOOST to be used with LPSEXACT=spx"
98#endif
99
100/* reset the SCIP_DEBUG define to its original SCIP value */
101#undef SCIP_DEBUG
102#ifdef ___DEBUG
103#define SCIP_DEBUG
104#undef ___DEBUG
105#endif
106
107/* define snprintf when using a too old MSVC version */
108#if defined(_MSC_VER) && _MSC_VER < 1900
109#ifndef snprintf
110#define snprintf _snprintf
111#endif
112#endif
113
114#define SOPLEX_VERBLEVEL 5 /**< verbosity level for LPINFO */
115
116#include "scip/pub_message.h"
117#include "scip/struct_rational.h"
118
119/********************************************************************/
120/*----------------------------- C++ --------------------------------*/
121/********************************************************************/
122
123/* in C++ we have to use "0" instead of "(void*)0" */
124#undef NULL
125#define NULL 0
126
127#include <cassert>
128using namespace soplex;
129
130
131/** Macro for a single SoPlex call for which exceptions have to be catched - return an LP error. We
132 * make no distinction between different exception types, e.g., between memory allocation and other
133 * exceptions.
134 */
135#ifndef NDEBUG
136#define SOPLEX_TRY(messagehdlr, x) do \
137 { \
138 try \
139 { \
140 (x); \
141 } \
142 catch( const SPxMemoryException& E ) \
143 { \
144 std::string s = E.what(); \
145 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
146 return SCIP_ERROR; \
147 } \
148 catch( const SPxException& E ) \
149 { \
150 std::string s = E.what(); \
151 SCIPmessagePrintWarning((messagehdlr), "SoPlex threw an exception: %s\n", s.c_str()); \
152 return SCIP_LPERROR; \
153 } \
154 } \
155 while( FALSE )
156
157#else
158#define SOPLEX_TRY(messagehdlr, x) do \
159 { \
160 try \
161 { \
162 (x); \
163 } \
164 catch( const SPxMemoryException& E ) \
165 { \
166 std::string s = E.what(); \
167 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
168 return SCIP_ERROR; \
169 } \
170 catch( const SPxException& ) \
171 { \
172 return SCIP_LPERROR; \
173 } \
174 } \
175 while( FALSE )
176#endif
177
178/* Macro for a single SoPlex call for which exceptions have to be catched - abort if they
179 * arise. SCIP_ABORT() is not accessible here.
180 */
181#define SOPLEX_TRY_ABORT(x) do \
182 { \
183 try \
184 { \
185 (x); \
186 } \
187 catch( const SPxException& E ) \
188 { \
189 std::string s = E.what(); \
190 SCIPerrorMessage("SoPlex threw an exception: %s\n", s.c_str()); \
191 abort(); \
192 } \
193 } \
194 while( FALSE )
195
196/* Set the value of a SCIP_RATIONAL* from a SoPlex Rational */
197static void RsetSpxR(
198 SCIP_LPIEXACT* lpi, /**< exact lpi*/
199 SCIP_RATIONAL* r, /**< scip rational */
200 const soplex::Rational& spxr /**< soplex rational */
201 )
202{
203 if( SCIPlpiExactIsInfinity(lpi, double(spxr)) )
205 else if( SCIPlpiExactIsInfinity(lpi, -double(spxr)) )
207 else
208 {
209#if defined(SCIP_WITH_BOOST) && defined(SCIP_WITH_GMP)
210 r->val = spxr;
211#else
212 r->val = (double) spxr;
213#endif
214 r->isinf = FALSE;
215 r->isfprepresentable = SCIP_ISFPREPRESENTABLE_UNKNOWN;
216 }
217}
218
219/* Set the value of a SoPlex Rational vector from a SCIP_RATIONAL** */
220static void RsetSpxVector(
221 SCIP_LPIEXACT* lpi, /**< exact LPI */
222 SCIP_RATIONAL** r, /**< SCIP_RATIONAL array */
223 VectorRational src /**< SoPlex rational vector */
224 )
225{
226 for( int i = 0; i < src.dim(); ++i )
227 {
228 assert(r[i] != NULL);
229
230 RsetSpxR(lpi, r[i], src[i]);
231 }
232}
233
234/** set the value of a SoPlex rational from a SCIP_RATIONAL */
235static void SpxRSetRat(
236 SCIP_LPIEXACT* lpi, /**< exact LPI */
237 soplex::Rational& spxr, /**< SoPlex Rational*/
238 SCIP_RATIONAL* src /**< SCIP_RATIONAL */
239 )
240{
242 {
243 if( SCIPrationalIsPositive(src) )
244 spxr = soplex::Rational(SCIPlpiExactInfinity(lpi));
245 else
246 spxr = soplex::Rational(-SCIPlpiExactInfinity(lpi));
247 }
248 else
249 {
250#if defined(SOPLEX_WITH_GMP) && defined(SCIP_WITH_BOOST) && defined(SCIP_WITH_GMP)
251 spxr = soplex::Rational(*SCIPrationalGetGMP(src));
252#else
253 spxr = soplex::Rational(SCIPrationalGetReal(src));
254#endif
255 }
256}
257
258
259
260/** SCIP's SoPlex class */
261class SPxexSCIP : public SoPlex
262{/*lint !e1790*/
263 bool _lpinfo;
264 bool _fromscratch;
265 char* _probname;
266 DataArray<SPxSolver::VarStatus> _colStat; /**< column basis status used for strong branching */
267 DataArray<SPxSolver::VarStatus> _rowStat; /**< row basis status used for strong branching */
268 SCIP_MESSAGEHDLR* _messagehdlr; /**< messagehdlr handler for printing messages, or NULL */
269
270public:
271 explicit SPxexSCIP(
272 SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
273 const char* probname = NULL /**< name of problem */
274 )
275 : _lpinfo(false),
276 _fromscratch(false),
277 _probname(NULL),
278 _colStat(0),
279 _rowStat(0),
280 _messagehdlr(messagehdlr)
281 {
282 if ( probname != NULL )
283 SOPLEX_TRY_ABORT( setProbname(probname) );
284
285#if SOPLEX_APIVERSION >= 2
286 (void) setBoolParam(SoPlex::ENSURERAY, true);
287#endif
288 }
289
290 virtual ~SPxexSCIP()
291 {
292 if( _probname != NULL )
293 spx_free(_probname); /*lint !e1551*/
294
295 freePreStrongbranchingBasis(); /*lint !e1551*/
296 }/*lint -e1579*/
297
298 /** get objective limit according to objective sense */
299 Real getObjLimit() const
300 {
301 return (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE)
302 ? realParam(SoPlex::OBJLIMIT_UPPER)
303 : realParam(SoPlex::OBJLIMIT_LOWER);
304 }
305
306 // @todo realize this with a member variable as before
307 bool getFromScratch() const
308 {
309 return _fromscratch;
310 }
311
312 void setFromScratch(bool fs)
313 {
314 _fromscratch = fs;
315 }
316
317 // @todo member variable?
318 bool getLpInfo() const
319 {
320 return _lpinfo;
321 }
322
323 void setLpInfo(bool lpinfo)
324 {
325 _lpinfo = lpinfo;
326 }
327
328 // @todo member variable?
329 void setProbname(const char* probname)
330 {
331 size_t len;
332
333 assert(probname != NULL);
334 if( _probname != NULL )
335 spx_free(_probname);
336
337 len = strlen(probname);
338 spx_alloc(_probname, (int) len + 1);
339 memcpy(_probname, probname, len + 1);
340 }
341
342 void setRep(SPxSolver::Representation p_rep)
343 {
344 if( p_rep == SPxSolver::COLUMN && intParam(SoPlex::REPRESENTATION) == SoPlex::REPRESENTATION_ROW )
345 {
346 SCIPdebugMessage("switching to column representation of the basis\n");
347 CHECK_SOPLEX_PARAM(setIntParam(SoPlex::REPRESENTATION, (int) SoPlex::REPRESENTATION_COLUMN));
348 }
349 else if( (p_rep == SPxSolver::ROW && intParam(SoPlex::REPRESENTATION) == SoPlex::REPRESENTATION_COLUMN) )
350 {
351 SCIPdebugMessage("switching to row representation of the basis\n");
352 CHECK_SOPLEX_PARAM(setIntParam(SoPlex::REPRESENTATION, (int) SoPlex::REPRESENTATION_ROW));
353 }
354 }
355
356#ifndef NDEBUG
358 {
359 for( int i = 0; i < numColsRational(); ++i )
360 {
361 if( lowerRational(i) > upperRational(i) )
362 {
363 SCIPerrorMessage("inconsistent bounds on column %d: lower=%s, upper=%s\n",
364 i, lowerRational(i).str().c_str(), upperRational(i).str().c_str());
365 return false;
366 }
367 }
368
369 return true;
370 }
371
373 {
374 for( int i = 0; i < numRowsRational(); ++i )
375 {
376 if( lhsRational(i) > rhsRational(i) )
377 {
378 SCIPerrorMessage("inconsistent sides on row %d: lhs=%s, rhs=%s\n",
379 i, lhsRational(i).str().c_str(), rhsRational(i).str().c_str());
380 return false;
381 }
382 }
383
384 return true;
385 }
386#endif
387
388 void trySolve(bool printwarning = true)
389 {
390 Real timespent;
391 Real timelimit;
392
393 try
394 {
395 (void) optimize();
396 }
397 catch(const SPxException& x)
398 {
399 std::string s = x.what();
400 if( printwarning )
401 {
402 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
403 }
404
405 /* since it is not clear if the status in SoPlex are set correctly
406 * we want to make sure that if an error is thrown the status is
407 * not OPTIMAL anymore.
408 */
409 assert(status() != SPxSolver::OPTIMAL);
410 }
411
412 assert(intParam(ITERLIMIT) < 0 || numIterations() <= intParam(ITERLIMIT));
413
414 /* update time limit */
415 timespent = solveTime();
416 if( timespent > 0 )
417 {
418 /* get current time limit */
419 timelimit = realParam(TIMELIMIT);
420 if( timelimit > timespent )
421 timelimit -= timespent;
422 else
423 timelimit = 0;
424 /* set new time limit */
425 assert(timelimit >= 0);
426 CHECK_SOPLEX_PARAM(setRealParam(TIMELIMIT, timelimit));
427 }
428 }
429
430 SPxSolver::Status doSolve(bool printwarning = true)
431 {
432 SPxOut::Verbosity verbosity;
433
434 SPxSolver::Status spxStatus;
435
436 /* store and set verbosity */
437 verbosity = spxout.getVerbosity();
438 spxout.setVerbosity((SPxOut::Verbosity)(getLpInfo() ? SOPLEX_VERBLEVEL : 0));
439
442
443 trySolve(printwarning);
444 spxStatus = status();
445
446 /* restore verbosity */
447 spxout.setVerbosity(verbosity);
448
449 return spxStatus;
450 }
451
452 /** save the current basis */
454 {
455 _rowStat.reSize(numRowsRational());
456 _colStat.reSize(numColsRational());
457
458 try
459 {
460 getBasis(_rowStat.get_ptr(), _colStat.get_ptr());
461 }
462#ifndef NDEBUG
463 catch(const SPxException& x)
464 {
465 std::string s = x.what();
466 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
467
468 /* since it is not clear if the status in SoPlex are set correctly
469 * we want to make sure that if an error is thrown the status is
470 * not OPTIMAL anymore.
471 */
472 assert(status() != SPxSolver::OPTIMAL);
473 }
474#else
475 catch(const SPxException&)
476 { }
477#endif
478 }
479
480 /** restore basis */
482 {
483 assert(_rowStat.size() == numRowsRational());
484 assert(_colStat.size() == numColsRational());
485
486 try
487 {
488 setBasis(_rowStat.get_ptr(), _colStat.get_ptr());
489 }
490#ifndef NDEBUG
491 catch(const SPxException& x)
492 {
493 std::string s = x.what();
494 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
495#else
496 catch(const SPxException&)
497 {
498#endif
499 /* since it is not clear if the status in SoPlex are set correctly
500 * we want to make sure that if an error is thrown the status is
501 * not OPTIMAL anymore.
502 */
503 assert(status() != SPxSolver::OPTIMAL);
504 }
505 }
506
507 /** if basis is in store, delete it without restoring it */
509 {
510 _rowStat.clear();
511 _colStat.clear();
512 }
513
514 /** is pre-strong-branching basis freed? */
516 {
517 return ((_rowStat.size() == 0 ) && (_colStat.size() == 0));
518 }
519
520 /** provides access for temporary storage of basis status of rows */
521 DataArray<SPxSolver::VarStatus>& rowStat()
522 {
523 return _rowStat; /*lint !e1536*/
524 }
525
526 /** provides access for temporary storage of basis status or columns */
527 DataArray<SPxSolver::VarStatus>& colStat()
528 {
529 return _colStat; /*lint !e1536*/
530 }
531
532}; /*lint !e1748*/
533
534
535
536
537/********************************************************************/
538/*----------------------------- C --------------------------------*/
539/********************************************************************/
540
541#include "lpiexact/lpiexact.h"
542#include "scip/bitencode.h"
543
544typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
545#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
546typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
547#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
548
549
550
551/** LP interface */
552struct SCIP_LPiExact
553{
554 SPxexSCIP* spx; /**< our SoPlex implementation */
555 int* cstat; /**< array for storing column basis status */
556 int* rstat; /**< array for storing row basis status */
557 int cstatsize; /**< size of cstat array */
558 int rstatsize; /**< size of rstat array */
559 SCIP_PRICING pricing; /**< current pricing strategy */
560 SCIP_Bool solved; /**< was the current LP solved? */
561 SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
562 SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
563 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
564};
565
566/** LPi state stores basis information */
567struct SCIP_LPiState
568{
569 int ncols; /**< number of LP columns */
570 int nrows; /**< number of LP rows */
571 COLPACKET* packcstat; /**< column basis status in compressed form */
572 ROWPACKET* packrstat; /**< row basis status in compressed form */
573};
574
575
576/*
577 * dynamic memory arrays
578 */
579
580/** resizes cstat array to have at least num entries */
581static
583 SCIP_LPIEXACT* lpi, /**< LP interface structure */
584 int num /**< minimal number of entries in array */
585 )
586{
587 assert(lpi != NULL);
588
589 if( num > lpi->cstatsize )
590 {
591 int newsize;
592
593 newsize = MAX(2*lpi->cstatsize, num);
594 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->cstat, newsize) );
595 lpi->cstatsize = newsize;
596 }
597 assert(num <= lpi->cstatsize);
598
599 return SCIP_OKAY;
600}
601
602/** resizes rstat array to have at least num entries */
603static
605 SCIP_LPIEXACT* lpi, /**< LP interface structure */
606 int num /**< minimal number of entries in array */
607 )
608{
609 assert(lpi != NULL);
610
611 if( num > lpi->rstatsize )
612 {
613 int newsize;
614
615 newsize = MAX(2*lpi->rstatsize, num);
616 SCIP_ALLOC( BMSreallocMemoryArray(&lpi->rstat, newsize) );
617 lpi->rstatsize = newsize;
618 }
619 assert(num <= lpi->rstatsize);
620
621 return SCIP_OKAY;
622}
623
624
625
626
627/*
628 * LPi state methods
629 */
630
631/** returns the number of packets needed to store column packet information */
632static
634 int ncols /**< number of columns to store */
635 )
636{
637 return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
638}
639
640/** returns the number of packets needed to store row packet information */
641static
643 int nrows /**< number of rows to store */
644 )
645{
646 return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
647}
648
649/** store row and column basis status in a packed LPi state object */
650static
652 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
653 const int* cstat, /**< basis status of columns in unpacked format */
654 const int* rstat /**< basis status of rows in unpacked format */
655 )
656{
657 assert(lpistate != NULL);
658 assert(lpistate->packcstat != NULL);
659 assert(lpistate->packrstat != NULL);
660
661 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
662 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
663}
664
665/** unpacks row and column basis status from a packed LPi state object */
666static
668 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
669 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
670 int* rstat /**< buffer for storing basis status of rows in unpacked format */
671 )
672{
673 assert(lpistate != NULL);
674 assert(lpistate->packcstat != NULL);
675 assert(lpistate->packrstat != NULL);
676
677 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
678 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
679}
680
681/** creates LPi state information object */
682static
684 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
685 BMS_BLKMEM* blkmem, /**< block memory */
686 int ncols, /**< number of columns to store */
687 int nrows /**< number of rows to store */
688 )
689{
690 assert(lpistate != NULL);
691 assert(blkmem != NULL);
692 assert(ncols >= 0);
693 assert(nrows >= 0);
694
695 int nColPackets = colpacketNum(ncols);
696 int nRowPackets = rowpacketNum(nrows);
697
698 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
699 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
700 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
701
702 return SCIP_OKAY;
703}
704
705/** frees LPi state information */
706static
708 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
709 BMS_BLKMEM* blkmem /**< block memory */
710 )
711{
712 assert(blkmem != NULL);
713 assert(lpistate != NULL);
714 assert(*lpistate != NULL);
715
716 int nColPackets = colpacketNum((*lpistate)->ncols);
717 int nRowPackets = rowpacketNum((*lpistate)->nrows);
718
719 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
720 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
721 BMSfreeBlockMemory(blkmem, lpistate);
722}
723
724
725
726
727/*
728 * local methods
729 */
730
731
732/** marks the current LP to be unsolved */
733static
735{
736 assert(lpi != NULL);
737 lpi->solved = FALSE;
738}
739
740
741
742/*
743 * LP Interface Methods
744 */
745
746
747/*
748 * Miscellaneous Methods
749 */
750
751#if (SOPLEX_SUBVERSION > 0)
752 const static char spxname[20] = {'S', 'o', 'P', 'l', 'e', 'x', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '.', SOPLEX_SUBVERSION + '0', '\0'};
753#else
754 const static char spxname[20] = {'S', 'o', 'P', 'l', 'e', 'x', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '\0'};
755#endif
756const static char spxdesc[200] = {'L', 'i', 'n', 'e', 'a', 'r', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g',
757 ' ', 's', 'o', 'l', 'v', 'e', 'r', ' ' , 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'e', 'd',
758 ' ', 'a', 't', ' ', 'Z', 'u', 's', 'e', ' ', 'I', 'n', 's', 't', 'i', 't', 'u', 't', 'e',
759 ' ', 'B', 'e', 'r', 'l', 'i', 'n', ' ', '(', 's', 'o', 'p', 'l', 'e', 'x', '.', 'z', 'i', 'b', '.', 'd', 'e', ')',
760 ' ', '[', 'G', 'i', 't', 'H', 'a', 's', 'h', ':', ' ',
761 getGitHash()[0], getGitHash()[1], getGitHash()[2], getGitHash()[3],
762 getGitHash()[4], getGitHash()[5], getGitHash()[6], getGitHash()[7],
763 ']', '\0'};
764
765/**@name Miscellaneous Methods */
766/**@{ */
767
768/** gets name and version of LP solver */
770 void
771 )
772{
773 SCIPdebugMessage("calling SCIPlpiExactGetSolverName()\n");
774 return spxname;
775}
776
777/** gets description of LP solver (developer, webpage, ...) */
779 void
780 )
781{
782 return spxdesc;
783}
784
785/** gets pointer for LP solver - use only with great care */
787 SCIP_LPIEXACT* lpi /**< pointer to an LP interface structure */
788 )
789{
790 return (void*) lpi->spx;
791}
792
793/** pass integrality information about variables to the solver */
795 SCIP_LPIEXACT* lpi, /**< pointer to an LP interface structure */
796 int ncols, /**< length of integrality array */
797 int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
798 )
799{
800 assert(ncols == lpi->spx->numColsRational() || (ncols == 0 && intInfo == NULL));
801 lpi->spx->setIntegralityInformation(ncols, intInfo);
802 return SCIP_OKAY;
803}
804
805/** informs about availability of a primal simplex solving method */
807 void
808 )
809{
810 return TRUE;
811}
812
813/** informs about availability of a dual simplex solving method */
815 void
816 )
817{
818 return TRUE;
819}
820
821/** informs about availability of a barrier solving method */
823 void
824 )
825{
826 return FALSE;
827}
828
829/**@} */
830
831
832/*
833 * LPI Creation and Destruction Methods
834 */
835
836/**@name LPI Creation and Destruction Methods */
837/**@{ */
838
839/** creates an LP problem object */
841 SCIP_LPIEXACT** lpi, /**< pointer to an LP interface structure */
842 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
843 const char* name, /**< problem name */
844 SCIP_OBJSEN objsen /**< objective sense */
845 )
846{
847 assert(lpi != NULL);
848 assert(name != NULL);
849
850 /* create SoPlex object */
852
853 /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
854 (*lpi)->spx = static_cast<SPxexSCIP*>(BMSallocMemoryCPP(sizeof(SPxexSCIP)));
855 SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxexSCIP(messagehdlr, name) );
856 (void) (*lpi)->spx->setIntParam(SoPlex::SYNCMODE, (int) SoPlex::SYNCMODE_AUTO);
857 (void) (*lpi)->spx->setIntParam(SoPlex::SOLVEMODE, (int) SoPlex::SOLVEMODE_RATIONAL);
858 (void) (*lpi)->spx->setRealParam(SoPlex::FEASTOL, 0.0, true);
859 (void) (*lpi)->spx->setRealParam(SoPlex::OPTTOL, 0.0, true);
860 (void) (*lpi)->spx->setBoolParam(SoPlex::FORCEBASIC, true);
861
862 (*lpi)->cstat = NULL;
863 (*lpi)->rstat = NULL;
864 (*lpi)->cstatsize = 0;
865 (*lpi)->rstatsize = 0;
866 (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
867 (*lpi)->conditionlimit = -1.0;
868 (*lpi)->checkcondition = FALSE;
869 (*lpi)->messagehdlr = messagehdlr;
870
871 invalidateSolution(*lpi);
872
873 /* set objective sense */
874 SCIP_CALL( SCIPlpiExactChgObjsen(*lpi, objsen) );
875
876 /* set default pricing */
877 SCIP_CALL( SCIPlpiExactSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
878
879 {
880 SPxOut::Verbosity verbosity = (*lpi)->spx->spxout.getVerbosity();
881 (*lpi)->spx->spxout.setVerbosity((SPxOut::Verbosity)((*lpi)->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
882 (*lpi)->spx->printVersion();
883 (*lpi)->spx->spxout.setVerbosity(verbosity);
884 }
885
886 return SCIP_OKAY;
887}
888
889/** deletes an LP problem object */
891 SCIP_LPIEXACT** lpi /**< pointer to an LP interface structure */
892 )
893{
894 assert(lpi != NULL);
895 assert(*lpi != NULL);
896 assert((*lpi)->spx != NULL);
897
898 /* free LP using destructor and free memory via blockmemshell */
899 (*lpi)->spx->~SPxexSCIP();
900 BMSfreeMemory(&((*lpi)->spx));
901
902 /* free memory */
903 BMSfreeMemoryArrayNull(&(*lpi)->cstat);
904 BMSfreeMemoryArrayNull(&(*lpi)->rstat);
905 BMSfreeMemory(lpi);
906
907 return SCIP_OKAY;
908}
909
910/**@} */
911
912
913/*
914 * Modification Methods
915 */
916
917/**@name Modification Methods */
918/**@{ */
919
920/** copies LP data with column matrix into LP solver */
922 SCIP_LPIEXACT* lpi, /**< LP interface structure */
923 SCIP_OBJSEN objsen, /**< objective sense */
924 int ncols, /**< number of columns */
925 SCIP_RATIONAL** obj, /**< objective function values of columns */
926 SCIP_RATIONAL** lb, /**< lower bounds of columns */
927 SCIP_RATIONAL** ub, /**< upper bounds of columns */
928 char** colnames, /**< column names, or NULL */
929 int nrows, /**< number of rows */
930 SCIP_RATIONAL** lhs, /**< left hand sides of rows */
931 SCIP_RATIONAL** rhs, /**< right hand sides of rows */
932 char** /*rownames*/, /**< row names, or NULL */
933 int nnonz, /**< number of nonzero elements in the constraint matrix */
934 int* beg, /**< start index of each column in ind- and val-array */
935 int* ind, /**< row indices of constraint matrix entries */
936 SCIP_RATIONAL** val /**< values of constraint matrix entries */
937 )
938{
939#ifndef NDEBUG
940 {
941 int j;
942 for( j = 0; j < nnonz; j++ )
943 {
944 assert(val[j] != NULL);
945 assert(!SCIPrationalIsZero(val[j]));
946 }
947 }
948#endif
949
950 SCIPdebugMessage("calling SCIPlpiExactLoadColLP()\n");
951
952 assert(lpi != NULL);
953 assert(lpi->spx != NULL);
954 assert(lhs != NULL);
955 assert(rhs != NULL);
956 assert(obj != NULL);
957 assert(lb != NULL);
958 assert(ub != NULL);
959 assert(beg != NULL);
960 assert(ind != NULL);
961 assert(val != NULL);
962
965
966 try
967 {
968 SPxexSCIP* spx = lpi->spx;
969 LPRowSetRational rows(nrows);
970 DSVectorRational emptyVector(0);
971 int i;
972
973 spx->clearLPRational();
974
975 /* set objective sense */
976 (void) spx->setIntParam(SoPlex::OBJSENSE, (int) (objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE));
977
978 /* create empty rows with given sides */
979 for( i = 0; i < nrows; ++i )
980 {
981 soplex::Rational spxlhs;
982 soplex::Rational spxrhs;
983 SpxRSetRat(lpi, spxlhs, lhs[i]);
984 SpxRSetRat(lpi, spxlhs, rhs[i]);
985 rows.add(spxlhs, emptyVector, spxrhs);
986 }
987 spx->addRowsRational(rows);
988
989 /* create column vectors with coefficients and bounds */
990 SCIP_CALL( SCIPlpiExactAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
991 //spx->syncLPReal();
992 }
993#ifndef NDEBUG
994 catch( const SPxException& x )
995 {
996 std::string s = x.what();
997 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
998#else
999 catch( const SPxException& )
1000 {
1001#endif
1002 return SCIP_LPERROR;
1003 }
1004
1005 return SCIP_OKAY;
1006}
1007
1008/** adds columns to the LP */
1010 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1011 int ncols, /**< number of columns to be added */
1012 SCIP_RATIONAL** obj, /**< objective function values of new columns */
1013 SCIP_RATIONAL** lb, /**< lower bounds of new columns */
1014 SCIP_RATIONAL** ub, /**< upper bounds of new columns */
1015 char** colnames, /**< column names, or NULL */
1016 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1017 int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1018 int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1019 SCIP_RATIONAL** val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1020 )
1021{ /*lint --e{715}*/
1022 SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1023
1024 assert(lpi != NULL);
1025 assert(lpi->spx != NULL);
1026 assert(obj != NULL);
1027 assert(lb != NULL);
1028 assert(ub != NULL);
1029 assert(nnonz == 0 || beg != NULL);
1030 assert(nnonz == 0 || ind != NULL);
1031 assert(nnonz == 0 || val != NULL);
1032 assert(nnonz >= 0);
1033 assert(ncols >= 0);
1034
1035 invalidateSolution(lpi);
1036
1038
1039#ifndef NDEBUG
1040 if ( nnonz > 0 )
1041 {
1042 /* perform check that no new rows are added - this is likely to be a mistake */
1043 int nrows = lpi->spx->numRowsRational();
1044 for (int j = 0; j < nnonz; ++j)
1045 {
1046 assert( 0 <= ind[j] && ind[j] < nrows );
1047 assert( val[j] != NULL );
1048 assert( !SCIPrationalIsZero(val[j]) );
1049 }
1050 }
1051#endif
1052
1053 SPxexSCIP* spx = lpi->spx;
1054 try
1055 {
1056 LPColSetRational cols(ncols);
1057 DSVectorRational colVector(ncols);
1058 int start;
1059 int last;
1060 int i;
1061
1062 /* create column vectors with coefficients and bounds */
1063 for( i = 0; i < ncols; ++i )
1064 {
1065 int j;
1066 soplex::Rational spxlb;
1067 soplex::Rational spxub;
1068 soplex::Rational spxobj;
1069 std::vector<soplex::Rational> spxval;
1070
1071 SpxRSetRat(lpi, spxlb, lb[i]);
1072 SpxRSetRat(lpi, spxub, ub[i]);
1073 SpxRSetRat(lpi, spxobj, obj[i]);
1074
1075 colVector.clear();
1076 if( nnonz > 0 )
1077 {
1078 soplex::Rational tmp;
1079
1080 start = beg[i];
1081 last = (i == ncols-1 ? nnonz : beg[i+1]);
1082 spxval.reserve((size_t) (last - start));
1083 for( j = start; j < last; ++j )
1084 {
1085 spxval.push_back(tmp);
1086 SpxRSetRat(lpi, spxval[(size_t) (j - start)], val[j]);
1087 }
1088 colVector.add(last - start, ind + start, spxval.data());
1089 }
1090 cols.add(spxobj, spxlb, colVector, spxub);
1091 }
1092 spx->addColsRational(cols);
1093 }
1094#ifndef NDEBUG
1095 catch( const SPxException& x )
1096 {
1097 std::string s = x.what();
1098 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1099#else
1100 catch( const SPxException& )
1101 {
1102#endif
1103 return SCIP_LPERROR;
1104 }
1105
1106 return SCIP_OKAY;
1107}
1108
1109/** deletes all columns in the given range from LP */
1111 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1112 int firstcol, /**< first column to be deleted */
1113 int lastcol /**< last column to be deleted */
1114 )
1115{
1116 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1117
1118 assert(lpi != NULL);
1119 assert(lpi->spx != NULL);
1120 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsRational());
1121
1122 invalidateSolution(lpi);
1123
1125
1126 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRangeRational(firstcol, lastcol) );
1127
1128 return SCIP_OKAY;
1129}
1130
1131/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1133 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1134 int* dstat /**< deletion status of columns
1135 * input: 1 if column should be deleted, 0 if not
1136 * output: new position of column, -1 if column was deleted */
1137 )
1138{
1139 int ncols;
1140 int i;
1141
1142 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
1143
1144 assert(lpi != NULL);
1145 assert(lpi->spx != NULL);
1146 assert(dstat != NULL);
1147
1148 invalidateSolution(lpi);
1149
1151
1152 ncols = lpi->spx->numColsRational();
1153
1154 /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
1155 for( i = 0; i < ncols; ++i )
1156 dstat[i] *= -1;
1157
1158 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColsRational(dstat) );
1159
1160 return SCIP_OKAY;
1161}
1162
1163/** adds rows to the LP */
1165 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1166 int nrows, /**< number of rows to be added */
1167 SCIP_RATIONAL** lhs, /**< left hand sides of new rows */
1168 SCIP_RATIONAL** rhs, /**< right hand sides of new rows */
1169 char** rownames, /**< row names, or NULL */
1170 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1171 int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
1172 int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
1173 SCIP_RATIONAL** val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1174 )
1175{ /*lint --e{715}*/
1176 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
1177
1178 assert(lpi != NULL);
1179 assert(lpi->spx != NULL);
1180 assert(lhs != NULL);
1181 assert(rhs != NULL);
1182 assert(nnonz == 0 || beg != NULL);
1183 assert(nnonz == 0 || ind != NULL);
1184 assert(nnonz == 0 || val != NULL);
1185
1186 invalidateSolution(lpi);
1187
1189
1190#ifndef NDEBUG
1191 if ( nnonz > 0 )
1192 {
1193 /* perform check that no new columns are added - this is likely to be a mistake */
1194 int ncols = lpi->spx->numColsRational();
1195 for (int j = 0; j < nnonz; ++j)
1196 {
1197 assert( !SCIPrationalIsZero(val[j]) );
1198 assert( 0 <= ind[j] && ind[j] < ncols );
1199 }
1200 }
1201#endif
1202
1203 try
1204 {
1205 SPxexSCIP* spx = lpi->spx;
1206 LPRowSetRational rows(nrows);
1207 DSVectorRational rowVector;
1208 int start;
1209 int last;
1210 int i;
1211
1212 /* create row vectors with given sides */
1213 for( i = 0; i < nrows; ++i )
1214 {
1215 soplex::Rational spxlhs;
1216 soplex::Rational spxrhs;
1217 std::vector<soplex::Rational> spxval;
1218
1219 SpxRSetRat(lpi, spxlhs, lhs[i]);
1220 SpxRSetRat(lpi, spxrhs, rhs[i]);
1221
1222 rowVector.clear();
1223 if( nnonz > 0 )
1224 {
1225 start = beg[i];
1226 last = (i == nrows-1 ? nnonz : beg[i+1]);
1227 spxval.reserve((size_t) (last - start));
1228
1229 for( int j = start; j < last; ++j )
1230 {
1231 soplex::Rational tmp;
1232 spxval.push_back(tmp);
1233 SpxRSetRat(lpi, spxval[(size_t) (j - start)], val[j]);
1234 }
1235 rowVector.add(last - start, ind + start, spxval.data());
1236 }
1237 rows.add(spxlhs, rowVector, spxrhs);
1238 }
1239 spx->addRowsRational(rows);
1240 }
1241#ifndef NDEBUG
1242 catch( const SPxException& x )
1243 {
1244 std::string s = x.what();
1245 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1246#else
1247 catch( const SPxException& )
1248 {
1249#endif
1250 return SCIP_LPERROR;
1251 }
1252
1253 return SCIP_OKAY;
1254}
1255
1256/** deletes all rows in the given range from LP */
1258 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1259 int firstrow, /**< first row to be deleted */
1260 int lastrow /**< last row to be deleted */
1261 )
1262{
1263 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
1264
1265 assert(lpi != NULL);
1266 assert(lpi->spx != NULL);
1267 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsRational());
1268
1269 invalidateSolution(lpi);
1270
1272
1273 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRangeRational(firstrow, lastrow) );
1274
1275 return SCIP_OKAY;
1276}
1277
1278/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
1280 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1281 int* dstat /**< deletion status of rows
1282 * input: 1 if row should be deleted, 0 if not
1283 * output: new position of row, -1 if row was deleted */
1284 )
1285{
1286 int nrows;
1287 int i;
1288
1289 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
1290
1291 assert(lpi != NULL);
1292 assert(lpi->spx != NULL);
1293
1294 invalidateSolution(lpi);
1295
1297
1298 nrows = lpi->spx->numRowsRational();
1299
1300 /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
1301 for( i = 0; i < nrows; ++i )
1302 dstat[i] *= -1;
1303
1304 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowsRational(dstat) );
1305
1306 return SCIP_OKAY;
1307}
1308
1309/** clears the whole LP */
1311 SCIP_LPIEXACT* lpi /**< LP interface structure */
1312 )
1313{
1314 SCIPdebugMessage("calling SCIPlpiExactClear()\n");
1315
1316 assert(lpi != NULL);
1317 assert(lpi->spx != NULL);
1318
1319 invalidateSolution(lpi);
1320
1322 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clearLPRational() );
1323
1324 return SCIP_OKAY;
1325}
1326
1327/** changes lower and upper bounds of columns */
1329 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1330 int ncols, /**< number of columns to change bounds for */
1331 int* ind, /**< column indices or NULL if ncols is zero */
1332 SCIP_RATIONAL** lb, /**< values for the new lower bounds or NULL if ncols is zero */
1333 SCIP_RATIONAL** ub /**< values for the new upper bounds or NULL if ncols is zero */
1334 )
1335{
1336 int i;
1337
1338 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
1339
1340 assert(lpi != NULL);
1341 assert(lpi->spx != NULL);
1342 assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
1343 if( ncols <= 0 )
1344 return SCIP_OKAY;
1345
1346 invalidateSolution(lpi);
1347
1349
1350 try
1351 {
1352 soplex::Rational spxlb;
1353 soplex::Rational spxub;
1354
1355 for( i = 0; i < ncols; ++i )
1356 {
1357 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsRational());
1358 assert(lb[i] != NULL && ub[i] != NULL);
1359
1360 if( SCIPrationalIsInfinity(lb[i]) )
1361 {
1362 SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
1363 return SCIP_LPERROR;
1364 }
1365 if( SCIPrationalIsNegInfinity(ub[i]) )
1366 {
1367 SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
1368 return SCIP_LPERROR;
1369 }
1370
1371 SpxRSetRat(lpi, spxlb, lb[i]);
1372 SpxRSetRat(lpi, spxub, ub[i]);
1373
1374 lpi->spx->changeBoundsRational(ind[i], spxlb, spxub);
1375 assert(lpi->spx->lowerRational(ind[i]) <= lpi->spx->upperRational(ind[i]));
1376 }
1377 }
1378#ifndef NDEBUG
1379 catch( const SPxException& x )
1380 {
1381 std::string s = x.what();
1382 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1383#else
1384 catch( const SPxException& )
1385 {
1386#endif
1387 return SCIP_LPERROR;
1388 }
1389
1390 return SCIP_OKAY;
1391}
1392
1393/** changes left and right hand sides of rows */
1395 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1396 int nrows, /**< number of rows to change sides for */
1397 int* ind, /**< row indices */
1398 SCIP_RATIONAL** lhs, /**< new values for left hand sides */
1399 SCIP_RATIONAL** rhs /**< new values for right hand sides */
1400 )
1401{
1402 int i;
1403
1404 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
1405
1406 assert(lpi != NULL);
1407 assert(lpi->spx != NULL);
1408 assert(ind != NULL);
1409 assert(lhs != NULL);
1410 assert(rhs != NULL);
1411 if( nrows <= 0 )
1412 return SCIP_OKAY;
1413
1414 invalidateSolution(lpi);
1415
1417
1418 try
1419 {
1420 soplex::Rational spxlhs;
1421 soplex::Rational spxrhs;
1422
1423 for( i = 0; i < nrows; ++i )
1424 {
1425 assert(0 <= ind[i] && ind[i] < lpi->spx->numRowsRational());
1426
1427 SpxRSetRat(lpi, spxlhs, lhs[i]);
1428 SpxRSetRat(lpi, spxrhs, rhs[i]);
1429
1430 lpi->spx->changeRangeRational(ind[i], spxlhs, spxrhs);
1431 assert(lpi->spx->lhsRational(ind[i]) <= lpi->spx->rhsRational(ind[i]));
1432 }
1433 }
1434#ifndef NDEBUG
1435 catch( const SPxException& x )
1436 {
1437 std::string s = x.what();
1438 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1439#else
1440 catch( const SPxException& )
1441 {
1442#endif
1443 return SCIP_LPERROR;
1444 }
1445
1446 return SCIP_OKAY;
1447}
1448
1449/** changes a single coefficient */
1451 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1452 int row, /**< row number of coefficient to change */
1453 int col, /**< column number of coefficient to change */
1454 SCIP_RATIONAL* newval /**< new value of coefficient */
1455 )
1456{
1457 soplex::Rational spxval;
1458
1459 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
1460
1461 assert(lpi != NULL);
1462 assert(lpi->spx != NULL);
1463 assert(0 <= row && row < lpi->spx->numRowsRational());
1464 assert(0 <= col && col < lpi->spx->numColsRational());
1465
1466 invalidateSolution(lpi);
1467
1469
1470 SpxRSetRat(lpi, spxval, newval);
1471 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElementRational(row, col, spxval) );
1472
1473 return SCIP_OKAY;
1474}
1475
1476/** changes the objective sense */
1478 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1479 SCIP_OBJSEN objsen /**< new objective sense */
1480 )
1481{
1482 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
1483
1484 assert(lpi != NULL);
1485 assert(lpi->spx != NULL);
1486
1487 invalidateSolution(lpi);
1488
1490
1491 SOPLEX_TRY( lpi->messagehdlr, (void) lpi->spx->setIntParam(SoPlex::OBJSENSE, (int) (objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE) ) );
1492
1493 return SCIP_OKAY;
1494}
1495
1496/** changes objective values of columns in the LP */
1498 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1499 int ncols, /**< number of columns to change objective value for */
1500 int* ind, /**< column indices to change objective value for */
1501 SCIP_RATIONAL** obj /**< new objective values for columns */
1502 )
1503{
1504 int i;
1505
1506 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
1507
1508 assert(lpi != NULL);
1509 assert(lpi->spx != NULL);
1510 assert(ind != NULL);
1511 assert(obj != NULL);
1512
1513 invalidateSolution(lpi);
1514
1516
1517 try
1518 {
1519 soplex::Rational spxobj;
1520
1521 for( i = 0; i < ncols; ++i )
1522 {
1523 assert(obj[i] != NULL);
1524 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsRational());
1525
1526 SpxRSetRat(lpi, spxobj, obj[i]);
1527 lpi->spx->changeObjRational(ind[i], spxobj);
1528 }
1529 }
1530#ifndef NDEBUG
1531 catch( const SPxException& x )
1532 {
1533 std::string s = x.what();
1534 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1535#else
1536 catch( const SPxException& )
1537 {
1538#endif
1539 return SCIP_LPERROR;
1540 }
1541
1542 return SCIP_OKAY;
1543}
1544
1545/**@} */
1546
1547
1548/*
1549 * Data Accessing Methods
1550 */
1551
1552/**@name Data Accessing Methods */
1553/**@{ */
1554
1555/** gets the number of rows in the LP */
1557 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1558 int* nrows /**< pointer to store the number of rows */
1559 )
1560{
1561 SCIPdebugMessage("calling SCIPlpiExactGetNRows()\n");
1562
1563 assert(lpi != NULL);
1564 assert(lpi->spx != NULL);
1565 assert(nrows != NULL);
1566
1567 *nrows = lpi->spx->numRowsRational();
1568
1569 return SCIP_OKAY;
1570}
1571
1572/** gets the number of columns in the LP */
1574 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1575 int* ncols /**< pointer to store the number of cols */
1576 )
1577{
1578 SCIPdebugMessage("calling SCIPlpiExactGetNCols()\n");
1579
1580 assert(lpi != NULL);
1581 assert(lpi->spx != NULL);
1582 assert(ncols != NULL);
1583
1584 *ncols = lpi->spx->numColsRational();
1585
1586 return SCIP_OKAY;
1587}
1588
1589/** gets the number of nonzero elements in the LP constraint matrix */
1591 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1592 int* nnonz /**< pointer to store the number of nonzeros */
1593 )
1594{
1595 int i;
1596
1597 SCIPdebugMessage("calling SCIPlpiExactGetNNonz()\n");
1598
1599 assert(lpi != NULL);
1600 assert(lpi->spx != NULL);
1601 assert(nnonz != NULL);
1602
1603 /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
1604 *nnonz = 0;
1605 if( lpi->spx->numRowsRational() < lpi->spx->numColsRational() )
1606 {
1607 for( i = 0; i < lpi->spx->numRowsRational(); ++i )
1608 (*nnonz) += lpi->spx->rowVectorRational(i).size();
1609 }
1610 else
1611 {
1612 for( i = 0; i < lpi->spx->numColsRational(); ++i )
1613 (*nnonz) += lpi->spx->colVectorRational(i).size();
1614 }
1615
1616 return SCIP_OKAY;
1617}
1618
1619/** gets columns from LP problem object; the arrays have to be large enough to store all values
1620 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
1621 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1622 */
1624 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1625 int firstcol, /**< first column to get from LP */
1626 int lastcol, /**< last column to get from LP */
1627 SCIP_RATIONAL** lb, /**< buffer to store the lower bound vector, or NULL */
1628 SCIP_RATIONAL** ub, /**< buffer to store the upper bound vector, or NULL */
1629 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1630 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1631 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1632 SCIP_RATIONAL** val /**< buffer to store values of constraint matrix entries, or NULL */
1633 )
1634{
1635 int i;
1636 int j;
1637
1638 SCIPdebugMessage("calling SCIPlpiExactGetCols()\n");
1639
1640 assert(lpi != NULL);
1641 assert(lpi->spx != NULL);
1642 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsRational());
1643 assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
1644 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1645
1646 if( lb != NULL )
1647 {
1648 const VectorRational& lbvec = lpi->spx->lowerRational();
1649 const VectorRational& ubvec = lpi->spx->upperRational();
1650
1651 for( i = firstcol; i <= lastcol; ++i )
1652 {
1653 RsetSpxR(lpi, lb[i-firstcol], lbvec[i]);
1654 RsetSpxR(lpi, ub[i-firstcol], ubvec[i]);
1655 }
1656 }
1657
1658 if( nnonz != NULL )
1659 {
1660 *nnonz = 0;
1661 for( i = firstcol; i <= lastcol; ++i )
1662 {
1663 const SVectorRational& cvec = lpi->spx->colVectorRational(i);
1664 beg[i-firstcol] = *nnonz;
1665
1666 for( j = 0; j < cvec.size(); ++j )
1667 {
1668 ind[*nnonz] = cvec.index(j);
1669 RsetSpxR(lpi, val[*nnonz], cvec.value(j));
1670 (*nnonz)++;
1671 }
1672 }
1673 }
1674
1675 return SCIP_OKAY;
1676}
1677
1678/** gets rows from LP problem object; the arrays have to be large enough to store all values.
1679 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
1680 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1681 */
1683 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1684 int firstrow, /**< first row to get from LP */
1685 int lastrow, /**< last row to get from LP */
1686 SCIP_RATIONAL** lhs, /**< buffer to store left hand side vector, or NULL */
1687 SCIP_RATIONAL** rhs, /**< buffer to store right hand side vector, or NULL */
1688 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1689 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
1690 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
1691 SCIP_RATIONAL** val /**< buffer to store values of constraint matrix entries, or NULL */
1692 )
1693{
1694 int i;
1695 int j;
1696
1697 SCIPdebugMessage("calling SCIPlpiExactGetRows()\n");
1698
1699 assert(lpi != NULL);
1700 assert(lpi->spx != NULL);
1701 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsRational());
1702 assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
1703 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1704
1705 if( lhs != NULL )
1706 {
1707 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) && FALSE )
1708 {
1709 }
1710 else
1711 {
1712 const VectorRational& lhsvec = lpi->spx->lhsRational();
1713 const VectorRational& rhsvec = lpi->spx->rhsRational();
1714 for( i = firstrow; i <= lastrow; ++i )
1715 {
1716 RsetSpxR(lpi, lhs[i-firstrow], lhsvec[i]);
1717 RsetSpxR(lpi, rhs[i-firstrow], rhsvec[i]);
1718 }
1719 }
1720 }
1721
1722 if( nnonz != NULL )
1723 {
1724 *nnonz = 0;
1725 for( i = firstrow; i <= lastrow; ++i )
1726 {
1727 beg[i-firstrow] = *nnonz;
1728
1729 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
1730 {
1731 }
1732 else
1733 {
1734 const SVectorRational& rvec = lpi->spx->rowVectorRational(i);
1735 for( j = 0; j < rvec.size(); ++j )
1736 {
1737 ind[*nnonz] = rvec.index(j);
1738 RsetSpxR(lpi, val[*nnonz], rvec.value(j));
1739 (*nnonz)++;
1740 }
1741 }
1742 }
1743 }
1744
1745 return SCIP_OKAY;
1746}
1747
1748/** gets column names */
1750 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1751 int firstcol, /**< first column to get name from LP */
1752 int lastcol, /**< last column to get name from LP */
1753 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
1754 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
1755 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
1756 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1757 )
1758{
1759 assert( lpi != NULL );
1760 assert( lpi->spx != NULL );
1761 assert( colnames != NULL || namestoragesize == 0 );
1762 assert( namestorage != NULL || namestoragesize == 0 );
1763 assert( namestoragesize >= 0 );
1764 assert( storageleft != NULL );
1765 assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsRational() );
1766
1767 SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
1768
1769 SCIPerrorMessage("SCIPlpiExactGetColNames() not implemented\n");
1770
1771 return SCIP_NOTIMPLEMENTED;
1772}
1773
1774/** gets row names */
1776 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1777 int firstrow, /**< first row to get name from LP */
1778 int lastrow, /**< last row to get name from LP */
1779 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
1780 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
1781 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
1782 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1783 )
1784{
1785 assert( lpi != NULL );
1786 assert( lpi->spx != NULL );
1787 assert( rownames != NULL || namestoragesize == 0 );
1788 assert( namestorage != NULL || namestoragesize == 0 );
1789 assert( namestoragesize >= 0 );
1790 assert( storageleft != NULL );
1791 assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsRational() );
1792
1793 SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
1794
1795 SCIPerrorMessage("SCIPlpiExactGetRowNames() not implemented\n");
1796
1797 return SCIP_NOTIMPLEMENTED;
1798}
1799
1800/** gets objective sense of the LP */
1802 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1803 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
1804 )
1805{
1806 SCIPdebugMessage("calling SCIPlpiExactGetObjsen()\n");
1807
1808 assert(lpi != NULL);
1809 assert(lpi->spx != NULL);
1810 assert(objsen != NULL);
1811
1812 *objsen = (lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
1813
1814 return SCIP_OKAY;
1815}
1816
1817/** gets objective coefficients from LP problem object */
1819 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1820 int firstcol, /**< first column to get objective coefficient for */
1821 int lastcol, /**< last column to get objective coefficient for */
1822 SCIP_RATIONAL** vals /**< array to store objective coefficients */
1823 )
1824{
1825 int i;
1826
1827 SCIPdebugMessage("calling SCIPlpiExactGetObj()\n");
1828
1829 assert(lpi != NULL);
1830 assert(lpi->spx != NULL);
1831 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsRational());
1832 assert(vals != NULL);
1833
1834 for( i = firstcol; i <= lastcol; ++i )
1835 {
1836 assert(vals[i-firstcol] != NULL);
1837 RsetSpxR(lpi, vals[i-firstcol], lpi->spx->objRational(i));
1838 }
1839
1840 return SCIP_OKAY;
1841}
1842
1843/** gets current bounds from LP problem object */
1845 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1846 int firstcol, /**< first column to get objective value for */
1847 int lastcol, /**< last column to get objective value for */
1848 SCIP_RATIONAL** lbs, /**< array to store lower bound values, or NULL */
1849 SCIP_RATIONAL** ubs /**< array to store upper bound values, or NULL */
1850 )
1851{
1852 int i;
1853
1854 SCIPdebugMessage("calling SCIPlpiExactGetBounds()\n");
1855
1856 assert(lpi != NULL);
1857 assert(lpi->spx != NULL);
1858 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsRational());
1859
1860 for( i = firstcol; i <= lastcol; ++i )
1861 {
1862 if( lbs != NULL )
1863 {
1864 assert(lbs[i-firstcol] != NULL);
1865 RsetSpxR(lpi, lbs[i-firstcol], lpi->spx->lowerRational(i));
1866 }
1867 if( ubs != NULL )
1868 {
1869 assert(ubs[i-firstcol] != NULL);
1870 RsetSpxR(lpi, ubs[i-firstcol], lpi->spx->upperRational(i));
1871 }
1872 }
1873
1874 return SCIP_OKAY;
1875}
1876
1877/** gets current row sides from LP problem object */
1879 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1880 int firstrow, /**< first row to get sides for */
1881 int lastrow, /**< last row to get sides for */
1882 SCIP_RATIONAL** lhss, /**< array to store left hand side values, or NULL */
1883 SCIP_RATIONAL** rhss /**< array to store right hand side values, or NULL */
1884 )
1885{
1886 int i;
1887
1888 SCIPdebugMessage("calling SCIPlpiExactGetSides()\n");
1889
1890 assert(lpi != NULL);
1891 assert(lpi->spx != NULL);
1892 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsRational());
1893
1894 for( i = firstrow; i <= lastrow; ++i )
1895 {
1896 if( lhss != NULL )
1897 {
1898 assert(lhss[i-firstrow] != NULL);
1899 RsetSpxR(lpi, lhss[i-firstrow], lpi->spx->lhsRational(i));
1900 }
1901 if( rhss != NULL )
1902 {
1903 assert(rhss[i-firstrow] != NULL);
1904 RsetSpxR(lpi, rhss[i-firstrow], lpi->spx->rhsReal(i));
1905 }
1906 }
1907
1908 return SCIP_OKAY;
1909}
1910
1911/** gets a single coefficient */
1913 SCIP_LPIEXACT* lpi, /**< LP interface structure */
1914 int row, /**< row number of coefficient */
1915 int col, /**< column number of coefficient */
1916 SCIP_RATIONAL* val /**< pointer to store the value of the coefficient */
1917 )
1918{
1919 SCIPdebugMessage("calling SCIPlpiExactGetCoef()\n");
1920
1921 assert(lpi != NULL);
1922 assert(lpi->spx != NULL);
1923 assert(0 <= col && col < lpi->spx->numColsRational());
1924 assert(0 <= row && row < lpi->spx->numRowsRational());
1925 assert(val != NULL);
1926
1927 RsetSpxR(lpi, val, lpi->spx->colVectorRational(col)[row]);
1928
1929 return SCIP_OKAY;
1930}
1931
1932/**@} */
1933
1934
1935/*
1936 * Solving Methods
1937 */
1938
1939/**@name Solving Methods */
1940/**@{ */
1941
1942/** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
1943static
1945 SCIP_LPIEXACT* lpi /**< LP interface structure */
1946 )
1947{
1948 assert( lpi != NULL );
1949 assert( lpi->spx != NULL );
1950
1951 SPxOut::Verbosity verbosity;
1952 /* store and set verbosity */
1953 verbosity = lpi->spx->spxout.getVerbosity();
1954 lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
1955
1956 SCIPdebugMessage("calling exact SoPlex solve(): %d cols, %d rows\n", lpi->spx->numColsRational(), lpi->spx->numRowsRational());
1957
1958 invalidateSolution(lpi);
1959
1961
1962#ifdef WITH_LPSCHECK
1963 lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
1964#endif
1965
1966 /* delete starting basis if solving from scratch */
1967 if( lpi->spx->getFromScratch() )
1968 {
1969 try
1970 {
1971 lpi->spx->clearBasis();
1972 }
1973#ifndef NDEBUG
1974 catch(const SPxException& x)
1975 {
1976 std::string s = x.what();
1977 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1978#else
1979 catch(const SPxException&)
1980 {
1981#endif
1982 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
1983 return SCIP_LPERROR;
1984 }
1985 }
1986 assert(!lpi->spx->getFromScratch() || lpi->spx->status() == SPxSolver::NO_PROBLEM);
1987
1988 SPxSolver::Status status = lpi->spx->doSolve();
1989 SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->status(), lpi->spx->basisStatus());
1990 lpi->solved = TRUE;
1991
1992 /* restore verbosity */
1993 lpi->spx->spxout.setVerbosity(verbosity);
1994
1995 switch( status )
1996 {
1997 case SPxSolver::ABORT_TIME:
1998 case SPxSolver::ABORT_ITER:
1999 case SPxSolver::ABORT_VALUE:
2000 case SPxSolver::SINGULAR:
2001 case SPxSolver::REGULAR:
2002 case SPxSolver::OPTIMAL:
2003#if SOPLEX_APIVERSION >= 3
2004 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2005#endif
2006 case SPxSolver::UNBOUNDED:
2007 case SPxSolver::INFEASIBLE:
2008 return SCIP_OKAY;
2009 case SPxSolver::UNKNOWN:
2010 default:
2011 return SCIP_LPERROR;
2012 } /*lint !e788*/
2013}
2014
2015/** calls primal simplex to solve the LP */
2017 SCIP_LPIEXACT* lpi /**< LP interface structure */
2018 )
2019{
2020 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2021
2022 assert(lpi != NULL);
2023 assert(lpi->spx != NULL);
2024
2025 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, (int) SoPlex::ALGORITHM_PRIMAL);
2026 return spxSolve(lpi);
2027}
2028
2029/** calls dual simplex to solve the LP */
2031 SCIP_LPIEXACT* lpi /**< LP interface structure */
2032 )
2033{
2034 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2035
2036 assert(lpi != NULL);
2037 assert(lpi->spx != NULL);
2038
2039 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, (int) SoPlex::ALGORITHM_DUAL);
2040 return spxSolve(lpi);
2041}
2042
2043/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
2045 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2046 SCIP_Bool crossover /**< perform crossover */
2047 )
2048{ /*lint --e{715}*/
2049 assert(lpi != NULL);
2050 assert(lpi->spx != NULL);
2051
2052 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
2053
2054 /* Since SoPlex does not support barrier we switch to DUAL */
2055 return SCIPlpiExactSolveDual(lpi);
2056}
2057
2058/** start strong branching - call before any strongbranching */
2060 SCIP_LPIEXACT* lpi /**< LP interface structure */
2061 )
2062{
2063 assert(lpi != NULL);
2064 assert(lpi->spx != NULL);
2065
2068
2069 return SCIP_OKAY;
2070}
2071
2072/** end strong branching - call after any strongbranching */
2074 SCIP_LPIEXACT* lpi /**< LP interface structure */
2075 )
2076{
2077 assert(lpi != NULL);
2078 assert(lpi->spx != NULL);
2079
2083
2084 return SCIP_OKAY;
2085}
2086
2087/**@} */
2088
2089
2090/*
2091 * Solution Information Methods
2092 */
2093
2094/**@name Solution Information Methods */
2095/**@{ */
2096
2097/** returns whether a solve method was called after the last modification of the LP */
2099 SCIP_LPIEXACT* lpi /**< LP interface structure */
2100 )
2101{
2102 assert(lpi != NULL);
2103
2104 return lpi->solved;
2105}
2106
2107/** gets information about primal and dual feasibility of the current LP solution
2108 *
2109 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
2110 * returns true. If the LP is changed, this information might be invalidated.
2111 *
2112 * Note that @param primalfeasible and @param dualfeasible should only return true if the solver has proved the respective LP to
2113 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
2114 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
2115 * the problem might actually be feasible).
2116 */
2118 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2119 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
2120 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
2121 )
2122{
2123 SCIPdebugMessage("calling SCIPlpiExactGetSolFeasibility()\n");
2124
2125 assert(lpi != NULL);
2126 assert(primalfeasible != NULL);
2127 assert(dualfeasible != NULL);
2128
2129 *primalfeasible = SCIPlpiExactIsPrimalFeasible(lpi);
2130 *dualfeasible = SCIPlpiExactIsDualFeasible(lpi);
2131
2132 return SCIP_OKAY;
2133}
2134
2135/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
2136 * this does not necessarily mean, that the solver knows and can return the primal ray
2137 */
2139 SCIP_LPIEXACT* lpi /**< LP interface structure */
2140 )
2141{
2142 SCIPdebugMessage("calling SCIPlpiExactExistsPrimalRay()\n");
2143
2144 assert(lpi != NULL);
2145 assert(lpi->spx != NULL);
2146
2147 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2148}
2149
2150/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
2151 * and the solver knows and can return the primal ray
2152 */
2154 SCIP_LPIEXACT* lpi /**< LP interface structure */
2155 )
2156{
2157 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
2158
2159 assert(lpi != NULL);
2160 assert(lpi->spx != NULL);
2161
2162 return lpi->spx->hasPrimalRay();
2163}
2164
2165/** returns TRUE iff LP is proven to be primal unbounded */
2167 SCIP_LPIEXACT* lpi /**< LP interface structure */
2168 )
2169{
2170 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
2171
2172 assert(lpi != NULL);
2173 assert(lpi->spx != NULL);
2174
2175 assert(lpi->spx->status() != SPxSolver::UNBOUNDED || lpi->spx->basisStatus() == SPxBasis::UNBOUNDED);
2176
2177 /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
2178 * feasible point; hence we have to check the perturbation
2179 */
2180 return lpi->spx->status() == SPxSolver::UNBOUNDED;
2181}
2182
2183/** returns TRUE iff LP is proven to be primal infeasible */
2185 SCIP_LPIEXACT* lpi /**< LP interface structure */
2186 )
2187{
2188 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
2189
2190 assert(lpi != NULL);
2191 assert(lpi->spx != NULL);
2192
2193 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
2194}
2195
2196/** returns TRUE iff LP is proven to be primal feasible */
2198 SCIP_LPIEXACT* lpi /**< LP interface structure */
2199 )
2200{
2201 SPxBasis::SPxStatus basestatus;
2202
2203 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
2204
2205 assert(lpi != NULL);
2206 assert(lpi->spx != NULL);
2207
2208 basestatus = lpi->spx->basisStatus();
2209
2210 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
2211 * still return true as long as perturbation plus violation is within tolerances
2212 */
2213 assert(basestatus == SPxBasis::OPTIMAL || lpi->spx->status() != SPxSolver::OPTIMAL);
2214
2215 return basestatus == SPxBasis::OPTIMAL || basestatus == SPxBasis::PRIMAL;
2216}
2217
2218/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
2219 * this does not necessarily mean, that the solver knows and can return the dual ray
2220 */
2222 SCIP_LPIEXACT* lpi /**< LP interface structure */
2223 )
2224{
2225 SCIPdebugMessage("calling SCIPlpiExactExistsDualRay()\n");
2226
2227 assert(lpi != NULL);
2228 assert(lpi->spx != NULL);
2229
2230 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
2231}
2232
2233/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
2234 * and the solver knows and can return the dual ray
2235 */
2237 SCIP_LPIEXACT* lpi /**< LP interface structure */
2238 )
2239{
2240 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
2241
2242 assert(lpi != NULL);
2243 assert(lpi->spx != NULL);
2244
2245 return lpi->spx->hasDualFarkas();
2246}
2247
2248/** returns TRUE iff LP is dual unbounded */
2250 SCIP_LPIEXACT* lpi /**< LP interface structure */
2251 )
2252{
2253 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
2254
2255 assert(lpi != NULL);
2256 assert(lpi->spx != NULL);
2257
2258 return lpi->spx->status() == SPxSolver::INFEASIBLE && lpi->spx->basisStatus() == SPxBasis::DUAL;
2259}
2260
2261/** returns TRUE iff LP is dual infeasible */
2263 SCIP_LPIEXACT* lpi /**< LP interface structure */
2264 )
2265{
2266 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
2267
2268 assert(lpi != NULL);
2269 assert(lpi->spx != NULL);
2270
2271 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2272}
2273
2274/** returns TRUE iff LP is proven to be dual feasible */
2276 SCIP_LPIEXACT* lpi /**< LP interface structure */
2277 )
2278{
2279 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
2280
2281 assert(lpi != NULL);
2282 assert(lpi->spx != NULL);
2283
2284 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
2285 * still return true as long as perturbation plus violation is within tolerances
2286 */
2287 assert(lpi->spx->basisStatus() == SPxBasis::OPTIMAL || lpi->spx->status() != SPxSolver::OPTIMAL);
2288
2289 return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL) || lpi->spx->basisStatus() == SPxBasis::DUAL;
2290}
2291
2292/** returns TRUE iff LP was solved to optimality */
2294 SCIP_LPIEXACT* lpi /**< LP interface structure */
2295 )
2296{
2297 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
2298
2299 assert(lpi != NULL);
2300 assert(lpi->spx != NULL);
2301 assert((lpi->spx->basisStatus() == SPxBasis::OPTIMAL)
2303
2304 /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
2305 * still return true as long as perturbation plus violation is within tolerances
2306 */
2307 return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL);
2308}
2309
2310/** returns TRUE iff the objective limit was reached */
2312 SCIP_LPIEXACT* lpi /**< LP interface structure */
2313 )
2314{
2315 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
2316
2317 assert(lpi != NULL);
2318 assert(lpi->spx != NULL);
2319
2320 return (lpi->spx->status() == SPxSolver::ABORT_VALUE);
2321}
2322
2323/** returns TRUE iff the iteration limit was reached */
2325 SCIP_LPIEXACT* lpi /**< LP interface structure */
2326 )
2327{
2328 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
2329
2330 assert(lpi != NULL);
2331 assert(lpi->spx != NULL);
2332
2333 return (lpi->spx->status() == SPxSolver::ABORT_ITER);
2334}
2335
2336/** returns TRUE iff the time limit was reached */
2338 SCIP_LPIEXACT* lpi /**< LP interface structure */
2339 )
2340{
2341 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
2342
2343 assert(lpi != NULL);
2344 assert(lpi->spx != NULL);
2345
2346 return (lpi->spx->status() == SPxSolver::ABORT_TIME);
2347}
2348
2349/** returns the internal solution status of the solver */
2351 SCIP_LPIEXACT* lpi /**< LP interface structure */
2352 )
2353{
2354 SCIPdebugMessage("calling SCIPlpiExactGetInternalStatus()\n");
2355
2356 assert(lpi != NULL);
2357 assert(lpi->spx != NULL);
2358
2359 return static_cast<int>(lpi->spx->status());
2360}
2361
2362/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
2364 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2365 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
2366 )
2367{ /*lint --e{715}*/
2368 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
2369
2370 assert(lpi != NULL);
2371 assert(lpi->spx != NULL);
2372 assert(success != NULL);
2373
2374#if SOPLEX_APIVERSION >= 4
2375 *success = lpi->spx->ignoreUnscaledViolations();
2376#else
2377 *success = FALSE;
2378#endif
2379
2380 return SCIP_OKAY;
2381}
2382
2383/** gets objective value of solution */
2385 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2386 SCIP_RATIONAL* objval /**< stores the objective value */
2387 )
2388{
2389 SCIPdebugMessage("calling SCIPlpiExactGetObjval()\n");
2390
2391 assert(lpi != NULL);
2392 assert(lpi->spx != NULL);
2393 assert(objval != NULL);
2394
2395 RsetSpxR(lpi, objval, lpi->spx->objValueRational());
2396
2397 return SCIP_OKAY;
2398}
2399
2400
2401/** gets primal and dual solution vectors for feasible LPs
2402 *
2403 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
2404 * SCIPlpiIsOptimal() returns true.
2405 */
2407 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2408 SCIP_RATIONAL* objval, /**< stores the objective value, may be NULL if not needed */
2409 SCIP_RATIONAL** primsol, /**< primal solution vector, may be NULL if not needed */
2410 SCIP_RATIONAL** dualsol, /**< dual solution vector, may be NULL if not needed */
2411 SCIP_RATIONAL** activity, /**< row activity vector, may be NULL if not needed */
2412 SCIP_RATIONAL** redcost /**< reduced cost vector, may be NULL if not needed */
2413 )
2414{
2415 DVectorRational* tmpvec;
2416 SCIPdebugMessage("calling SCIPlpiExactGetSol()\n");
2417
2418 assert(lpi != NULL);
2419 assert(lpi->spx != NULL);
2420
2421 tmpvec = new DVectorRational(MAX(lpi->spx->numColsRational(), lpi->spx->numRowsRational()));
2422 tmpvec->clear();
2423
2424 if( objval != NULL )
2425 RsetSpxR(lpi, objval, lpi->spx->objValueRational());
2426
2427 try
2428 {
2429 if( primsol != NULL )
2430 {
2431 VectorRational tmp(lpi->spx->numColsRational(), tmpvec->get_ptr());
2432 (void)lpi->spx->getPrimalRational(tmp);
2433 RsetSpxVector(lpi, primsol, tmp);
2434 }
2435 if( dualsol != NULL )
2436 {
2437 VectorRational tmp(lpi->spx->numRowsRational(), tmpvec->get_ptr());
2438 (void)lpi->spx->getDualRational(tmp);
2439 RsetSpxVector(lpi, dualsol, tmp);
2440 }
2441 if( activity != NULL )
2442 {
2443 VectorRational tmp(lpi->spx->numRowsRational(), tmpvec->get_ptr());
2444 (void)lpi->spx->getSlacksRational(tmp); /* in SoPlex, the activities are called "slacks" */
2445 RsetSpxVector(lpi, activity, tmp);
2446 }
2447 if( redcost != NULL )
2448 {
2449 VectorRational tmp(lpi->spx->numColsRational(), tmpvec->get_ptr());
2450 (void)lpi->spx->getRedCostRational(tmp);
2451 RsetSpxVector(lpi, redcost, tmp);
2452 }
2453
2454 delete tmpvec;
2455 }
2456#ifndef NDEBUG
2457 catch( const SPxException& x )
2458 {
2459 std::string s = x.what();
2460 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2461#else
2462 catch( const SPxException& )
2463 {
2464#endif
2465 return SCIP_LPERROR;
2466 }
2467
2468 return SCIP_OKAY;
2469}
2470
2471
2472/** gets primal ray for unbounded LPs */
2474 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2475 SCIP_RATIONAL** ray /**< primal ray */
2476 )
2477{ /*lint --e{715}*/
2478 DVectorRational* tmpvec;
2479 SCIPdebugMessage("calling SCIPlpiExactGetPrimalRay()\n");
2480
2481 assert(lpi != NULL);
2482 assert(lpi->spx != NULL);
2483 assert(lpi->spx->hasPrimalRay());
2484 assert(ray != NULL);
2485
2486 tmpvec = new DVectorRational(MAX(lpi->spx->numColsRational(), lpi->spx->numRowsRational()));
2487
2488 try
2489 {
2490 VectorRational tmp(lpi->spx->numColsRational(), tmpvec->get_ptr());
2491 (void)lpi->spx->getPrimalRayRational(tmp);
2492 RsetSpxVector(lpi, ray, tmp);
2493 }
2494#ifndef NDEBUG
2495 catch( const SPxException& x )
2496 {
2497 std::string s = x.what();
2498 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2499#else
2500 catch( const SPxException& )
2501 {
2502#endif
2503 delete tmpvec;
2504 return SCIP_LPERROR;
2505 }
2506
2507 delete tmpvec;
2508
2509 return SCIP_OKAY;
2510}
2511
2512/** gets dual farkas proof for infeasibility */
2514 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2515 SCIP_RATIONAL** dualfarkas /**< dual farkas row multipliers */
2516 )
2517{
2518 DVectorRational* tmpvec;
2519 SCIPdebugMessage("calling SCIPlpiExactGetDualfarkas()\n");
2520
2521 assert(lpi != NULL);
2522 assert(lpi->spx != NULL);
2523 assert(lpi->spx->hasDualFarkas());
2524 assert(dualfarkas != NULL);
2525
2526 tmpvec = new DVectorRational(MAX(lpi->spx->numColsRational(), lpi->spx->numRowsRational()));
2527
2528 try
2529 {
2530 VectorRational tmp(lpi->spx->numRowsRational(), tmpvec->get_ptr());
2531 (void)lpi->spx->getDualFarkasRational(tmp);
2532 RsetSpxVector(lpi, dualfarkas, tmp);
2533 }
2534#ifndef NDEBUG
2535 catch( const SPxException& x )
2536 {
2537 std::string s = x.what();
2538 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2539#else
2540 catch( const SPxException& )
2541 {
2542#endif
2543 return SCIP_LPERROR;
2544 }
2545 delete tmpvec;
2546
2547 return SCIP_OKAY;
2548}
2549
2550/** gets the number of LP iterations of the last solve call */
2552 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2553 int* iterations /**< pointer to store the number of iterations of the last solve call */
2554 )
2555{
2556 SCIPdebugMessage("calling SCIPlpiExactGetIterations()\n");
2557
2558 assert(lpi != NULL);
2559 assert(lpi->spx != NULL);
2560 assert(iterations != NULL);
2561
2562 *iterations = lpi->spx->numIterations();
2563
2564 return SCIP_OKAY;
2565}
2566
2567/**@} */
2568
2569
2570/*
2571 * LP Basis Methods
2572 */
2573
2574/**@name LP Basis Methods */
2575/**@{ */
2576
2577
2578/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
2580 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2581 int* cstat, /**< array to store column basis status, or NULL */
2582 int* rstat /**< array to store row basis status, or NULL */
2583 )
2584{
2585 int i;
2586
2587 SCIPdebugMessage("calling SCIPlpiExactGetBase()\n");
2588
2589 assert(lpi != NULL);
2590 assert(lpi->spx != NULL);
2591
2593
2594 if( rstat != NULL )
2595 {
2596 for( i = 0; i < lpi->spx->numRowsRational(); ++i )
2597 {
2598 switch( lpi->spx->basisRowStatus(i) )
2599 {
2600 case SPxSolver::BASIC:
2601 rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
2602 break;
2603 case SPxSolver::FIXED:
2604 case SPxSolver::ON_LOWER:
2605 rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
2606 break;
2607 case SPxSolver::ON_UPPER:
2608 rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
2609 break;
2610 case SPxSolver::ZERO:
2611 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
2612 return SCIP_LPERROR;
2613 case SPxSolver::UNDEFINED:
2614 default:
2615 SCIPerrorMessage("invalid basis status\n");
2616 SCIPABORT();
2617 return SCIP_INVALIDDATA; /*lint !e527*/
2618 }
2619 }
2620 }
2621
2622 if( cstat != NULL )
2623 {
2624 for( i = 0; i < lpi->spx->numColsRational(); ++i )
2625 {
2626 switch( lpi->spx->basisColStatus(i) )
2627 {
2628 case SPxSolver::BASIC:
2629 cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
2630 break;
2631 case SPxSolver::FIXED:
2632 /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
2633 * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
2634 * this case there is no problem at all. If the basis is saved and/or used in some other
2635 * solver, it usually is very cheap to perform the pivots necessary to get an optimal
2636 * basis.
2637 * @todo implement getRedCostEst()
2638 * */
2639// SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
2640// if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
2641// cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
2642// else
2643 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
2644 break;
2645 case SPxSolver::ON_LOWER:
2646 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
2647 break;
2648 case SPxSolver::ON_UPPER:
2649 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
2650 break;
2651 case SPxSolver::ZERO:
2652 cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
2653 break;
2654 case SPxSolver::UNDEFINED:
2655 default:
2656 SCIPerrorMessage("invalid basis status\n");
2657 SCIPABORT();
2658 return SCIP_INVALIDDATA; /*lint !e527*/
2659 }
2660 }
2661 }
2662
2663 return SCIP_OKAY;
2664}
2665
2666/** sets current basis status for columns and rows */
2668 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2669 int* cstat, /**< array with column basis status */
2670 int* rstat /**< array with row basis status */
2671 )
2672{
2673 int i;
2674 int ncols;
2675 int nrows;
2676
2677 SCIPdebugMessage("calling SCIPlpiExactSetBase()\n");
2678
2679 assert(lpi != NULL);
2680 assert(lpi->spx != NULL);
2681
2682 SCIP_CALL( SCIPlpiExactGetNRows(lpi, &nrows) );
2683 SCIP_CALL( SCIPlpiExactGetNCols(lpi, &ncols) );
2684
2685 assert(cstat != NULL || ncols == 0);
2686 assert(rstat != NULL || nrows == 0);
2687
2689 invalidateSolution(lpi);
2690
2691 DataArray<SPxSolver::VarStatus>& _colstat = lpi->spx->colStat();
2692 DataArray<SPxSolver::VarStatus>& _rowstat = lpi->spx->rowStat();
2693
2694 _colstat.reSize(ncols);
2695 _rowstat.reSize(nrows);
2696
2697 for( i = 0; i < nrows; ++i )
2698 {
2699 switch( rstat[i] ) /*lint !e613*/
2700 {
2702 _rowstat[i] = SPxSolver::ON_LOWER;
2703 break;
2705 _rowstat[i] = SPxSolver::BASIC;
2706 break;
2708 _rowstat[i] = SPxSolver::ON_UPPER;
2709 break;
2710 case SCIP_BASESTAT_ZERO:
2711 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
2712 return SCIP_LPERROR; /*lint !e429*/
2713 default:
2714 SCIPerrorMessage("invalid basis status\n");
2715 SCIPABORT();
2716 return SCIP_INVALIDDATA; /*lint !e527*/
2717 }
2718 }
2719
2720 for( i = 0; i < ncols; ++i )
2721 {
2722 switch( cstat[i] ) /*lint !e613*/
2723 {
2725 _colstat[i] = SPxSolver::ON_LOWER;
2726 break;
2728 _colstat[i] = SPxSolver::BASIC;
2729 break;
2731 _colstat[i] = SPxSolver::ON_UPPER;
2732 break;
2733 case SCIP_BASESTAT_ZERO:
2734 _colstat[i] = SPxSolver::ZERO;
2735 break;
2736 default:
2737 SCIPerrorMessage("invalid basis status\n");
2738 SCIPABORT();
2739 return SCIP_INVALIDDATA; /*lint !e527*/
2740 }
2741 }
2742
2743 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(_rowstat.get_ptr(), _colstat.get_ptr()) );
2745
2746 return SCIP_OKAY;
2747}
2748
2749/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
2751 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2752 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
2753 )
2754{
2755 SCIPdebugMessage("calling SCIPlpiExactGetBasisInd()\n");
2756
2757 assert(lpi != NULL);
2758 assert(lpi->spx != NULL);
2759 assert(bind != NULL);
2760
2762
2763 lpi->spx->getBasisInd(bind);
2764
2765 return SCIP_OKAY;
2766}
2767
2768/** get row of inverse basis matrix B^-1
2769 *
2770 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2771 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2772 * see also the explanation in lpi.h.
2773 */
2775 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2776 int r, /**< row number */
2777 SCIP_RATIONAL** coef, /**< pointer to store the coefficients of the row */
2778 int* inds, /**< array to store the non-zero indices, or NULL */
2779 int* ninds /**< pointer to store the number of non-zero indices, or NULL
2780 * (-1: if we do not store sparsity information) */
2781 )
2782{
2783 int i;
2784 SSVectorBase<soplex::Rational> tmpvec(0);
2785 SCIPdebugMessage("calling SCIPlpiExactGetBInvRow()\n");
2786
2787 assert(lpi != NULL);
2788 assert(lpi->spx != NULL);
2790 assert(coef != NULL);
2791
2792 assert(r >= 0);
2793 assert(r < lpi->spx->numRowsRational());
2794
2795 if( !lpi->spx->getBasisInverseRowRational(r, tmpvec) )
2796 return SCIP_LPERROR;
2797
2798 for( i = 0; i < tmpvec.size(); ++i )
2799 {
2800 inds[i] = tmpvec.index(i);
2801 RsetSpxR(lpi, coef[i], tmpvec.value(i));
2802 }
2803
2804 *ninds = tmpvec.size();
2805
2806 return SCIP_OKAY;
2807}
2808
2809/** get column of inverse basis matrix B^-1
2810 *
2811 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
2812 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
2813 * see also the explanation in lpi.h.
2814 */
2816 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2817 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
2818 * you have to call SCIPlpiExactGetBasisInd() to get the array which links the
2819 * B^-1 column numbers to the row and column numbers of the LP!
2820 * c must be between 0 and nrows-1, since the basis has the size
2821 * nrows * nrows */
2822 SCIP_RATIONAL** coef, /**< pointer to store the coefficients of the column */
2823 int* inds, /**< array to store the non-zero indices, or NULL */
2824 int* ninds /**< pointer to store the number of non-zero indices, or NULL
2825 * (-1: if we do not store sparsity information) */
2826 )
2827{
2828 int i;
2829 SSVectorRational tmpvec(0);
2830
2831 SCIPdebugMessage("calling SCIPlpiExactGetBInvCol()\n");
2832
2833 assert( lpi != NULL );
2834 assert( lpi->spx != NULL );
2836 assert(coef != NULL);
2837
2838 if( ! lpi->spx->getBasisInverseColRational(c, tmpvec) )
2839 return SCIP_LPERROR;
2840
2841 for( i = 0; i < tmpvec.size(); ++i )
2842 {
2843 inds[i] = tmpvec.index(i);
2844 RsetSpxR(lpi, coef[i], tmpvec.value(i));
2845 }
2846
2847 *ninds = tmpvec.size();
2848
2849
2850 return SCIP_OKAY;
2851}
2852
2853/**@} */
2854
2855
2856/*
2857 * LP State Methods
2858 */
2859
2860/**@name LP State Methods */
2861/**@{ */
2862
2863/** stores LPi state (like basis information) into lpistate object */
2865 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2866 BMS_BLKMEM* blkmem, /**< block memory */
2867 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
2868 )
2869{
2870 int ncols;
2871 int nrows;
2872
2873 SCIPdebugMessage("calling SCIPlpiExactGetState()\n");
2874
2875 assert(blkmem != NULL);
2876 assert(lpi != NULL);
2877 assert(lpi->spx != NULL);
2878 assert(lpistate != NULL);
2879
2881
2882 ncols = lpi->spx->numColsRational();
2883 nrows = lpi->spx->numRowsRational();
2884 assert(ncols >= 0);
2885 assert(nrows >= 0);
2886
2887 /* allocate lpistate data */
2888 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
2889
2890 /* allocate enough memory for storing uncompressed basis information */
2891 SCIP_CALL( ensureCstatMem(lpi, ncols) );
2892 SCIP_CALL( ensureRstatMem(lpi, nrows) );
2893
2894 /* get unpacked basis information */
2895 SCIP_CALL( SCIPlpiExactGetBase(lpi, lpi->cstat, lpi->rstat) );
2896
2897 /* pack LPi state data */
2898 (*lpistate)->ncols = ncols;
2899 (*lpistate)->nrows = nrows;
2900 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
2901
2902 return SCIP_OKAY;
2903}
2904
2905/** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
2906 * columns and rows since the state was stored with SCIPlpiExactGetState()
2907 */
2909 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2910 BMS_BLKMEM* blkmem, /**< block memory */
2911 SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
2912 )
2913{ /*lint --e{715}*/
2914 int lpncols;
2915 int lpnrows;
2916 int i;
2917
2918 SCIPdebugMessage("calling SCIPlpiExactSetState()\n");
2919
2920 assert(lpi != NULL);
2921 assert(lpi->spx != NULL);
2922 assert(lpistate != NULL);
2923
2925
2926 lpncols = lpi->spx->numColsRational();
2927 lpnrows = lpi->spx->numRowsRational();
2928 assert(lpistate->ncols <= lpncols);
2929 assert(lpistate->nrows <= lpnrows);
2930
2931 /* allocate enough memory for storing uncompressed basis information */
2932 SCIP_CALL( ensureCstatMem(lpi, lpncols) );
2933 SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
2934
2935 /* unpack LPi state data */
2936 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
2937
2938 /* extend the basis to the current LP beyond the previously existing columns */
2939 for( i = lpistate->ncols; i < lpncols; ++i )
2940 {
2941 SCIP_Real bnd = lpi->spx->lowerReal(i);
2942 if ( SCIPlpiExactIsInfinity(lpi, REALABS(bnd)) )
2943 {
2944 /* if lower bound is +/- infinity -> try upper bound */
2945 bnd = lpi->spx->lowerReal(i);
2946 if ( SCIPlpiExactIsInfinity(lpi, REALABS(bnd)) )
2947 /* variable is free */
2948 lpi->cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
2949 else
2950 /* use finite upper bound */
2951 lpi->cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
2952 }
2953 else
2954 /* use finite lower bound */
2955 lpi->cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
2956 }
2957 for( i = lpistate->nrows; i < lpnrows; ++i )
2958 lpi->rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
2959
2960 /* load basis information */
2961 SCIP_CALL( SCIPlpiExactSetBase(lpi, lpi->cstat, lpi->rstat) );
2962
2963 return SCIP_OKAY;
2964}
2965
2966/** clears current LPi state (like basis information) of the solver */
2968 SCIP_LPIEXACT* lpi /**< LP interface structure */
2969 )
2970{ /*lint --e{715}*/
2971 SCIPdebugMessage("calling SCIPlpiClearState()\n");
2972
2973 assert(lpi != NULL);
2974 assert(lpi->spx != NULL);
2975
2976 try
2977 {
2978 lpi->spx->clearBasis();
2979 }
2980#ifndef NDEBUG
2981 catch( const SPxException& x )
2982 {
2983 std::string s = x.what();
2984 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2985#else
2986 catch( const SPxException& )
2987 {
2988#endif
2989 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
2990 return SCIP_LPERROR;
2991 }
2992
2993 return SCIP_OKAY;
2994}
2995
2996/** frees LPi state information */
2998 SCIP_LPIEXACT* lpi, /**< LP interface structure */
2999 BMS_BLKMEM* blkmem, /**< block memory */
3000 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3001 )
3002{ /*lint --e{715}*/
3003 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
3004
3005 assert(lpi != NULL);
3006 assert(lpistate != NULL);
3007 assert(blkmem != NULL);
3008
3009 if ( *lpistate != NULL )
3010 lpistateFree(lpistate, blkmem);
3011
3012 return SCIP_OKAY;
3013}
3014
3015/** checks, whether the given LP state contains simplex basis information */
3017 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3018 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
3019 )
3020{ /*lint --e{715}*/
3021 assert(lpi != NULL);
3022 return TRUE;
3023}
3024
3025/** reads LP state (like basis information from a file */
3027 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3028 const char* fname /**< file name */
3029 )
3030{
3031 SCIPdebugMessage("calling SCIPlpiReadState()\n");
3032 assert(lpi != NULL);
3033 assert(lpi->spx != NULL);
3034 assert(fname != NULL);
3035
3037
3038 bool success;
3039 SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
3040
3041 return success ? SCIP_OKAY : SCIP_LPERROR;
3042}
3043
3044/** writes LPi state (i.e. basis information) to a file */
3046 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3047 const char* fname /**< file name */
3048 )
3049{
3050 assert(lpi != NULL);
3051 assert(lpi->spx != NULL);
3052 assert(fname != NULL);
3053 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
3054
3056
3057 bool res;
3058 SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
3059
3060 if ( ! res )
3061 return SCIP_LPERROR;
3062
3063 return SCIP_OKAY;
3064}
3065
3066/**@} */
3067
3068/*
3069 * Parameter Methods
3070 */
3071
3072/**@name Parameter Methods */
3073/**@{ */
3074
3075/** gets integer parameter of LP */
3077 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3078 SCIP_LPPARAM type, /**< parameter number */
3079 int* ival /**< buffer to store the parameter value */
3080 )
3081{
3082 int scaleparam;
3083
3084 SCIPdebugMessage("calling SCIPlpiExactGetIntpar()\n");
3085
3086 assert(lpi != NULL);
3087 assert(lpi->spx != NULL);
3088 assert(ival != NULL);
3089
3090 switch( type )
3091 {
3093 *ival = (int) lpi->spx->getFromScratch();
3094 break;
3095 case SCIP_LPPAR_LPINFO:
3096 *ival = (int) lpi->spx->getLpInfo();
3097 break;
3098 case SCIP_LPPAR_LPITLIM:
3099 *ival = lpi->spx->intParam(SoPlex::ITERLIMIT);
3100 if( *ival == -1 )
3101 *ival = INT_MAX;
3102 break;
3104 *ival = lpi->spx->intParam(SoPlex::SIMPLIFIER) == (int) SoPlex::SIMPLIFIER_AUTO;
3105 break;
3106 case SCIP_LPPAR_PRICING:
3107 *ival = (int) lpi->pricing;
3108 break;
3109 case SCIP_LPPAR_SCALING:
3110 scaleparam = lpi->spx->intParam(SoPlex::SCALER);
3111
3112 if( scaleparam == SoPlex::SCALER_OFF )
3113 *ival = 0;
3114 else if( scaleparam == SoPlex::SCALER_BIEQUI )
3115 *ival = 1;
3116#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
3117 else
3118 {
3119 assert(scaleparam == SoPlex::SCALER_LEASTSQ);
3120 *ival = 2;
3121 }
3122#else
3123 else
3124 {
3125 assert(scaleparam == SoPlex::SCALER_GEO8);
3126 *ival = 2;
3127 }
3128#endif
3129 break;
3130#if SOPLEX_VERSION >= 201
3131 case SCIP_LPPAR_TIMING:
3132 *ival = (int) (lpi->spx->intParam(SoPlex::TIMER));
3133 break;
3134#endif
3135#if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
3137 *ival = (int) lpi->spx->randomSeed();
3138 break;
3139#endif
3140#if SOPLEX_APIVERSION >= 1
3142 *ival = (int) lpi->spx->intParam(SoPlex::FACTOR_UPDATE_MAX);
3143 break;
3144#endif
3145 default:
3146 return SCIP_PARAMETERUNKNOWN;
3147 } /*lint !e788*/
3148
3149 return SCIP_OKAY;
3150}
3151
3152/** sets integer parameter of LP */
3154 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3155 SCIP_LPPARAM type, /**< parameter number */
3156 int ival /**< parameter value */
3157 )
3158{
3159 SCIPdebugMessage("calling SCIPlpiExactSetIntpar()\n");
3160
3161 assert(lpi != NULL);
3162 assert(lpi->spx != NULL);
3163
3164 switch( type )
3165 {
3167 assert(ival == TRUE || ival == FALSE);
3168 lpi->spx->setFromScratch(bool(ival));
3169 break;
3170 case SCIP_LPPAR_LPINFO:
3171 assert(ival == TRUE || ival == FALSE);
3172 lpi->spx->setLpInfo(bool(ival));
3173 break;
3174 case SCIP_LPPAR_LPITLIM:
3175 assert( ival >= 0 );
3176 /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
3177 if( ival >= INT_MAX )
3178 ival = -1;
3179 (void) lpi->spx->setIntParam(SoPlex::ITERLIMIT, ival);
3180 break;
3182 assert(ival == TRUE || ival == FALSE);
3183 (void) lpi->spx->setIntParam(SoPlex::SIMPLIFIER, (int) (ival ? SoPlex::SIMPLIFIER_AUTO : SoPlex::SIMPLIFIER_OFF));
3184 break;
3185 case SCIP_LPPAR_PRICING:
3186 lpi->pricing = (SCIP_PRICING)ival;
3187 switch( lpi->pricing )
3188 {
3190 case SCIP_PRICING_AUTO:
3191 (void) lpi->spx->setIntParam(SoPlex::PRICER, (int) SoPlex::PRICER_AUTO);
3192 break;
3193 case SCIP_PRICING_FULL:
3194 (void) lpi->spx->setIntParam(SoPlex::PRICER, (int) SoPlex::PRICER_STEEP);
3195 break;
3197 (void) lpi->spx->setIntParam(SoPlex::PRICER, (int) SoPlex::PRICER_PARMULT);
3198 break;
3199 case SCIP_PRICING_STEEP:
3200 (void) lpi->spx->setIntParam(SoPlex::PRICER, (int) SoPlex::PRICER_STEEP);
3201 break;
3203 (void) lpi->spx->setIntParam(SoPlex::PRICER, (int) SoPlex::PRICER_QUICKSTEEP);
3204 break;
3205 case SCIP_PRICING_DEVEX:
3206 (void) lpi->spx->setIntParam(SoPlex::PRICER, (int) SoPlex::PRICER_DEVEX);
3207 break;
3208 default:
3209 return SCIP_LPERROR;
3210 }
3211 break;
3212 case SCIP_LPPAR_SCALING:
3213 assert(ival >= 0 && ival <= 2);
3214 if( ival == 0 )
3215 (void) lpi->spx->setIntParam(SoPlex::SCALER, (int) SoPlex::SCALER_OFF);
3216 else if( ival == 1 )
3217 (void) lpi->spx->setIntParam(SoPlex::SCALER, (int) SoPlex::SCALER_BIEQUI);
3218 else
3219#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
3220 (void) lpi->spx->setIntParam(SoPlex::SCALER, (int) SoPlex::SCALER_LEASTSQ);
3221#else
3222 (void) lpi->spx->setIntParam(SoPlex::SCALER, (int) SoPlex::SCALER_GEO8);
3223#endif
3224
3225 break;
3226#if SOPLEX_VERSION >= 201
3227 case SCIP_LPPAR_TIMING:
3228 assert(ival >= 0 && ival < 3);
3229 (void) lpi->spx->setIntParam(SoPlex::TIMER, ival);
3230 break;
3231#endif
3232#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
3234 lpi->spx->setRandomSeed((unsigned long)(long)ival);
3235 break;
3236#endif
3237#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION >= 221 && SOPLEX_SUBVERSION >= 3)
3239 assert(ival >= 0 && ival < 3);
3240 (void) lpi->spx->setIntParam(SoPlex::SOLUTION_POLISHING, ival);
3241 break;
3242#endif
3243#if SOPLEX_APIVERSION >= 1
3245 assert(ival >= 0);
3246 (void) lpi->spx->setIntParam(SoPlex::FACTOR_UPDATE_MAX, ival);
3247 break;
3248#endif
3249
3250 default:
3251 return SCIP_PARAMETERUNKNOWN;
3252 } /*lint !e788*/
3253
3254 return SCIP_OKAY;
3255}
3256
3257/** gets floating point parameter of LP */
3259 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3260 SCIP_LPPARAM type, /**< parameter number */
3261 SCIP_Real* dval /**< buffer to store the parameter value */
3262 )
3263{
3264 SCIPdebugMessage("calling SCIPlpiExactGetRealpar()\n");
3265
3266 assert(lpi != NULL);
3267 assert(lpi->spx != NULL);
3268 assert(dval != NULL);
3269
3270 switch( type )
3271 {
3272 case SCIP_LPPAR_FEASTOL:
3273 *dval = 0.0; //lpi->spx->feastol();
3274 break;
3276 *dval = 0.0; //lpi->spx->opttol();
3277 break;
3278 case SCIP_LPPAR_OBJLIM:
3279 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
3280 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_UPPER);
3281 else
3282 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_LOWER);
3283 break;
3284 case SCIP_LPPAR_LPTILIM:
3285 *dval = lpi->spx->realParam(SoPlex::TIMELIMIT);
3286 break;
3288 *dval = lpi->spx->realParam(SoPlex::REPRESENTATION_SWITCH);
3289 if( *dval >= SCIPlpiExactInfinity(lpi) )
3290 *dval = -1.0;
3291 break;
3293 *dval = lpi->conditionlimit;
3294 break;
3295 default:
3296 return SCIP_PARAMETERUNKNOWN;
3297 } /*lint !e788*/
3298
3299 return SCIP_OKAY;
3300}
3301
3302/** sets floating point parameter of LP */
3304 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3305 SCIP_LPPARAM type, /**< parameter number */
3306 SCIP_Real dval /**< parameter value */
3307 )
3308{
3309 SCIPdebugMessage("calling SCIPlpiExactSetRealpar()\n");
3310
3311 assert(lpi != NULL);
3312 assert(lpi->spx != NULL);
3313
3314 switch( type )
3315 {
3316 case SCIP_LPPAR_OBJLIM:
3317 /* no restrictions on dval */
3318 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
3319 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_UPPER, dval);
3320 else
3321 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_LOWER, dval);
3322 break;
3323 case SCIP_LPPAR_LPTILIM:
3324 assert( dval > 0.0 );
3325 /* soplex requires 0 < dval < DEFAULT_INFINITY (= 1e100), -1 means unlimited */
3326 (void) lpi->spx->setRealParam(SoPlex::TIMELIMIT, dval);
3327 break;
3329 /* 0 <= dval <= inf */
3330 assert( dval >= 0.0 || dval == -1.0 );
3331 if( dval == -1 )
3332 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, SCIPlpiExactInfinity(lpi));
3333 else
3334 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, dval);
3335 break;
3337 lpi->conditionlimit = dval;
3338 lpi->checkcondition = (dval >= 0.0);
3339 break;
3340 default:
3341 return SCIP_PARAMETERUNKNOWN;
3342 } /*lint !e788*/
3343
3344 return SCIP_OKAY;
3345}
3346
3347/**@} */
3348
3349
3350/*
3351 * Numerical Methods
3352 */
3353
3354/**@name Numerical Methods */
3355/**@{ */
3356
3357/** returns value treated as infinity in the LP solver */
3359 SCIP_LPIEXACT* lpi /**< LP interface structure */
3360 )
3361{
3362 assert(lpi != NULL);
3363 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
3364
3365 return lpi->spx->realParam(SoPlex::INFTY);
3366}
3367
3368/** checks if given value is treated as infinity in the LP solver */
3370 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3371 SCIP_Real val /**< the value */
3372 )
3373{
3374 assert(lpi != NULL);
3375 SCIPdebugMessage("calling SCIPlpiExactIsInfinity()\n");
3376
3377 return (val >= lpi->spx->realParam(SoPlex::INFTY));
3378}
3379
3380/**@} */
3381
3382
3383/*
3384 * File Interface Methods
3385 */
3386
3387/**@name File Interface Methods */
3388/**@{ */
3389
3390/** returns, whether the given file exists */
3391static
3393 const char* filename /**< file name */
3394 )
3395{
3396 FILE* f;
3397
3398 f = fopen(filename, "r");
3399 if( f == NULL )
3400 return FALSE;
3401
3402 fclose(f);
3403
3404 return TRUE;
3405}
3406
3407/** reads LP from a file */
3409 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3410 const char* fname /**< file name */
3411 )
3412{
3413 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
3414
3415 assert(lpi != NULL);
3416 assert(lpi->spx != NULL);
3417 assert(fname != NULL);
3418
3420
3421 if( !fileExists(fname) )
3422 return SCIP_NOFILE;
3423
3424 try
3425 {
3426 assert(lpi->spx->intParam(SoPlex::READMODE) == SoPlex::READMODE_RATIONAL);
3427 if( !lpi->spx->readFile(fname) )
3428 return SCIP_READERROR;
3429 }
3430#ifndef NDEBUG
3431 catch( const SPxException& x )
3432 {
3433 std::string s = x.what();
3434 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3435#else
3436 catch( const SPxException& )
3437 {
3438#endif
3439 return SCIP_READERROR;
3440 }
3441
3442 return SCIP_OKAY;
3443}
3444
3445/** writes LP to a file */
3447 SCIP_LPIEXACT* lpi, /**< LP interface structure */
3448 const char* fname /**< file name */
3449 )
3450{
3451 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
3452
3453 assert(lpi != NULL);
3454 assert(lpi->spx != NULL);
3455 assert(fname != NULL);
3456
3457 try
3458 {
3459 (void) lpi->spx->writeFileRational(fname);
3460 }
3461#ifndef NDEBUG
3462 catch( const SPxException& x )
3463 {
3464 std::string s = x.what();
3465 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3466#else
3467 catch( const SPxException& )
3468 {
3469#endif
3470 return SCIP_WRITEERROR;
3471 }
3472
3473 return SCIP_OKAY;
3474}
3475
3476/**@} */
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_VAR ** x
void setProbname(const char *probname)
DataArray< SPxSolver::VarStatus > & colStat()
bool checkConsistentSides() const
bool getFromScratch() const
SPxSolver::Status doSolve(bool printwarning=true)
void savePreStrongbranchingBasis()
bool preStrongbranchingBasisFreed() const
SPxexSCIP(SCIP_MESSAGEHDLR *messagehdlr=NULL, const char *probname=NULL)
void freePreStrongbranchingBasis()
Real getObjLimit() const
void setRep(SPxSolver::Representation p_rep)
void trySolve(bool printwarning=true)
bool getLpInfo() const
bool checkConsistentBounds() const
void setFromScratch(bool fs)
void setLpInfo(bool lpinfo)
DataArray< SPxSolver::VarStatus > & rowStat()
virtual ~SPxexSCIP()
void restorePreStrongbranchingBasis()
common defines and data types used in all packages of SCIP
#define NULL
Definition def.h:255
#define SCIP_Bool
Definition def.h:98
#define SCIP_ALLOC(x)
Definition def.h:373
#define SCIP_Real
Definition def.h:163
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define MAX(x, y)
Definition def.h:227
#define SCIPABORT()
Definition def.h:334
#define REALABS(x)
Definition def.h:189
#define SCIP_CALL(x)
Definition def.h:362
void * SCIPlpiExactGetSolverPointer(SCIP_LPIEXACT *lpi)
SCIP_Bool SCIPlpiExactHasDualRay(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactSetRealpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, SCIP_Real dval)
SCIP_RETCODE SCIPlpiExactSetBase(SCIP_LPIEXACT *lpi, int *cstat, int *rstat)
SCIP_RETCODE SCIPlpiExactReadState(SCIP_LPIEXACT *lpi, const char *fname)
SCIP_Bool SCIPlpiExactHasStateBasis(SCIP_LPIEXACT *lpi, SCIP_LPISTATE *lpistate)
SCIP_RETCODE SCIPlpiExactGetObj(SCIP_LPIEXACT *lpi, int firstcol, int lastcol, SCIP_RATIONAL **vals)
SCIP_RETCODE SCIPlpiExactStartStrongbranch(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactIgnoreInstability(SCIP_LPIEXACT *lpi, SCIP_Bool *success)
SCIP_RETCODE SCIPlpiExactGetObjval(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *objval)
SCIP_Bool SCIPlpiExactIsDualUnbounded(SCIP_LPIEXACT *lpi)
SCIP_Bool SCIPlpiExactHasBarrierSolve(void)
SCIP_RETCODE SCIPlpiExactWriteLP(SCIP_LPIEXACT *lpi, const char *fname)
SCIP_Bool SCIPlpiExactHasPrimalRay(SCIP_LPIEXACT *lpi)
SCIP_Bool SCIPlpiExactExistsDualRay(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetDualfarkas(SCIP_LPIEXACT *lpi, SCIP_RATIONAL **dualfarkas)
SCIP_RETCODE SCIPlpiExactEndStrongbranch(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactSolveDual(SCIP_LPIEXACT *lpi)
const char * SCIPlpiExactGetSolverDesc(void)
SCIP_RETCODE SCIPlpiExactChgObjsen(SCIP_LPIEXACT *lpi, SCIP_OBJSEN objsen)
SCIP_RETCODE SCIPlpiExactSetIntpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, int ival)
SCIP_RETCODE SCIPlpiExactWriteState(SCIP_LPIEXACT *lpi, const char *fname)
SCIP_RETCODE SCIPlpiExactChgCoef(SCIP_LPIEXACT *lpi, int row, int col, SCIP_RATIONAL *newval)
SCIP_Bool SCIPlpiExactWasSolved(SCIP_LPIEXACT *lpi)
SCIP_Bool SCIPlpiExactIsPrimalUnbounded(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetSides(SCIP_LPIEXACT *lpi, int firstrow, int lastrow, SCIP_RATIONAL **lhss, SCIP_RATIONAL **rhss)
SCIP_Bool SCIPlpiExactHasDualSolve(void)
const char * SCIPlpiExactGetSolverName(void)
SCIP_RETCODE SCIPlpiExactGetCols(SCIP_LPIEXACT *lpi, int firstcol, int lastcol, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub, int *nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
SCIP_Bool SCIPlpiExactIsPrimalInfeasible(SCIP_LPIEXACT *lpi)
SCIP_Real SCIPlpiExactInfinity(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetRows(SCIP_LPIEXACT *lpi, int firstrow, int lastrow, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs, int *nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
SCIP_RETCODE SCIPlpiExactGetSolFeasibility(SCIP_LPIEXACT *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
SCIP_RETCODE SCIPlpiExactGetBInvCol(SCIP_LPIEXACT *lpi, int c, SCIP_RATIONAL **coef, int *inds, int *ninds)
SCIP_Bool SCIPlpiExactExistsPrimalRay(SCIP_LPIEXACT *lpi)
SCIP_Bool SCIPlpiExactIsInfinity(SCIP_LPIEXACT *lpi, SCIP_Real val)
SCIP_Bool SCIPlpiExactHasPrimalSolve(void)
SCIP_RETCODE SCIPlpiExactAddRows(SCIP_LPIEXACT *lpi, int nrows, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs, char **rownames, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
SCIP_RETCODE SCIPlpiExactCreate(SCIP_LPIEXACT **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
SCIP_Bool SCIPlpiExactIsIterlimExc(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactLoadColLP(SCIP_LPIEXACT *lpi, SCIP_OBJSEN objsen, int ncols, SCIP_RATIONAL **obj, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub, char **colnames, int nrows, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs, char **, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
SCIP_Bool SCIPlpiExactIsPrimalFeasible(SCIP_LPIEXACT *lpi)
SCIP_Bool SCIPlpiExactIsDualFeasible(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactReadLP(SCIP_LPIEXACT *lpi, const char *fname)
SCIP_RETCODE SCIPlpiExactGetBasisInd(SCIP_LPIEXACT *lpi, int *bind)
SCIP_RETCODE SCIPlpiExactGetObjsen(SCIP_LPIEXACT *lpi, SCIP_OBJSEN *objsen)
SCIP_Bool SCIPlpiExactIsOptimal(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetRowNames(SCIP_LPIEXACT *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
SCIP_RETCODE SCIPlpiExactAddCols(SCIP_LPIEXACT *lpi, int ncols, SCIP_RATIONAL **obj, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub, char **colnames, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
SCIP_RETCODE SCIPlpiExactGetBase(SCIP_LPIEXACT *lpi, int *cstat, int *rstat)
SCIP_RETCODE SCIPlpiExactDelCols(SCIP_LPIEXACT *lpi, int firstcol, int lastcol)
SCIP_RETCODE SCIPlpiExactChgObj(SCIP_LPIEXACT *lpi, int ncols, int *ind, SCIP_RATIONAL **obj)
SCIP_RETCODE SCIPlpiExactGetPrimalRay(SCIP_LPIEXACT *lpi, SCIP_RATIONAL **ray)
SCIP_RETCODE SCIPlpiExactGetBounds(SCIP_LPIEXACT *lpi, int firstcol, int lastcol, SCIP_RATIONAL **lbs, SCIP_RATIONAL **ubs)
int SCIPlpiExactGetInternalStatus(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPIEXACT *lpi, int *dstat)
SCIP_RETCODE SCIPlpiExactGetCoef(SCIP_LPIEXACT *lpi, int row, int col, SCIP_RATIONAL *val)
SCIP_RETCODE SCIPlpiExactGetColNames(SCIP_LPIEXACT *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
SCIP_RETCODE SCIPlpiExactClear(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetNNonz(SCIP_LPIEXACT *lpi, int *nnonz)
SCIP_RETCODE SCIPlpiExactFree(SCIP_LPIEXACT **lpi)
SCIP_Bool SCIPlpiExactIsDualInfeasible(SCIP_LPIEXACT *lpi)
SCIP_Bool SCIPlpiExactIsObjlimExc(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactClearState(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetNCols(SCIP_LPIEXACT *lpi, int *ncols)
SCIP_RETCODE SCIPlpiExactSolveBarrier(SCIP_LPIEXACT *lpi, SCIP_Bool crossover)
SCIP_RETCODE SCIPlpiExactGetBInvRow(SCIP_LPIEXACT *lpi, int r, SCIP_RATIONAL **coef, int *inds, int *ninds)
SCIP_RETCODE SCIPlpiExactChgSides(SCIP_LPIEXACT *lpi, int nrows, int *ind, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs)
SCIP_RETCODE SCIPlpiExactGetState(SCIP_LPIEXACT *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
SCIP_RETCODE SCIPlpiExactDelRows(SCIP_LPIEXACT *lpi, int firstrow, int lastrow)
SCIP_RETCODE SCIPlpiExactGetNRows(SCIP_LPIEXACT *lpi, int *nrows)
SCIP_Bool SCIPlpiExactIsTimelimExc(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetRealpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
SCIP_RETCODE SCIPlpiExactChgBounds(SCIP_LPIEXACT *lpi, int ncols, int *ind, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub)
SCIP_RETCODE SCIPlpiExactFreeState(SCIP_LPIEXACT *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
SCIP_RETCODE SCIPlpiExactDelRowset(SCIP_LPIEXACT *lpi, int *dstat)
SCIP_RETCODE SCIPlpiExactGetSol(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *objval, SCIP_RATIONAL **primsol, SCIP_RATIONAL **dualsol, SCIP_RATIONAL **activity, SCIP_RATIONAL **redcost)
SCIP_RETCODE SCIPlpiExactSolvePrimal(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactGetIntpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, int *ival)
SCIP_RETCODE SCIPlpiExactSetState(SCIP_LPIEXACT *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE *lpistate)
SCIP_RETCODE SCIPlpiExactGetIterations(SCIP_LPIEXACT *lpi, int *iterations)
SCIP_RETCODE SCIPlpiExactSetIntegralityInformation(SCIP_LPIEXACT *lpi, int ncols, int *intInfo)
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:619
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsPositive(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:631
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
return SCIP_OKAY
int c
SCIP_Real objval
int r
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_Real primsol
static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
SCIP_DUALPACKET ROWPACKET
Definition lpi_clp.cpp:128
#define COLS_PER_PACKET
Definition lpi_clp.cpp:127
SCIP_DUALPACKET COLPACKET
Definition lpi_clp.cpp:126
#define ROWS_PER_PACKET
Definition lpi_clp.cpp:129
static void setIntParam(SCIP_LPI *lpi, int const param, int const parval)
Definition lpi_cpx.c:654
#define SOPLEX_VERBLEVEL
Definition lpi_spx.cpp:132
static const char spxdesc[200]
Definition lpi_spx.cpp:981
static const char spxname[20]
Definition lpi_spx.cpp:979
interface methods for specific exact LP solvers
static void RsetSpxR(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *r, const soplex::Rational &spxr)
static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
#define NULL
static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
static SCIP_Bool fileExists(const char *filename)
#define SOPLEX_TRY(messagehdlr, x)
static int rowpacketNum(int nrows)
#define SOPLEX_VERBLEVEL
static void invalidateSolution(SCIP_LPIEXACT *lpi)
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
static SCIP_RETCODE ensureCstatMem(SCIP_LPIEXACT *lpi, int num)
static SCIP_RETCODE spxSolve(SCIP_LPIEXACT *lpi)
static int colpacketNum(int ncols)
static SCIP_RETCODE ensureRstatMem(SCIP_LPIEXACT *lpi, int num)
#define CHECK_SOPLEX_PARAM(x)
#define SOPLEX_SUBVERSION
static void SpxRSetRat(SCIP_LPIEXACT *lpi, soplex::Rational &spxr, SCIP_RATIONAL *src)
static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
#define SOPLEX_TRY_ABORT(x)
static const char spxname[20]
static void RsetSpxVector(SCIP_LPIEXACT *lpi, SCIP_RATIONAL **r, VectorRational src)
memory allocation routines
#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 BMSallocMemoryCPP(size)
Definition memory.h:121
#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
wrapper for rational number arithmetic
wrapper for rational number arithmetic that interacts with GMP
SCIP_PRICING pricing
SCIP_MESSAGEHDLR * messagehdlr
SPxexSCIP * spx
SCIP_Bool checkcondition
SCIP_Real conditionlimit
COLPACKET * packcstat
Definition lpi_clp.cpp:136
ROWPACKET * packrstat
Definition lpi_clp.cpp:137
definition of wrapper class for rational numbers
@ 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
struct SCIP_LPiState SCIP_LPISTATE
Definition type_lpi.h:107
@ SCIP_LPPAR_PRICING
Definition type_lpi.h:54
@ SCIP_LPPAR_REFACTOR
Definition type_lpi.h:71
@ SCIP_LPPAR_LPINFO
Definition type_lpi.h:55
@ SCIP_LPPAR_POLISHING
Definition type_lpi.h:70
@ SCIP_LPPAR_SCALING
Definition type_lpi.h:52
@ SCIP_LPPAR_TIMING
Definition type_lpi.h:68
@ SCIP_LPPAR_LPTILIM
Definition type_lpi.h:61
@ SCIP_LPPAR_PRESOLVING
Definition type_lpi.h:53
@ SCIP_LPPAR_CONDITIONLIMIT
Definition type_lpi.h:67
@ 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_ROWREPSWITCH
Definition type_lpi.h:63
@ 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
@ 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
type definitions for specific exact LP solvers interface
struct SCIP_LPiExact SCIP_LPIEXACT
struct SCIP_Messagehdlr SCIP_MESSAGEHDLR
struct SCIP_Rational SCIP_RATIONAL
@ SCIP_ISFPREPRESENTABLE_UNKNOWN
type definitions for return codes for SCIP methods
@ SCIP_LPERROR
@ SCIP_NOFILE
@ SCIP_READERROR
@ SCIP_INVALIDDATA
@ SCIP_PARAMETERUNKNOWN
@ SCIP_WRITEERROR
@ SCIP_NOTIMPLEMENTED
enum SCIP_Retcode SCIP_RETCODE