SCIP Doxygen Documentation
 
Loading...
Searching...
No Matches
lpi_spx2.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-2023 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file lpi_spx2.cpp
26 * @ingroup LPIS
27 * @brief LP interface for SoPlex version 2.0 and higher
28 * @author Matthias Miltenberger
29 * @author Ambros Gleixner
30 *
31 * This is an implementation of SCIP's LP interface for SoPlex using the extended and improved interface of SoPlex 2.0
32 *
33 * For debugging purposes, the SoPlex results can be double checked with CPLEX if SCIP_WITH_LPSCHECK is defined. This may
34 * yield false positives, since the LP is dumped to a file for transfering it to CPLEX, hence, precision may be lost.
35 */
36
37/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
38
39#define STRONGBRANCH_RESTOREBASIS /**< if defined then in SCIPlpiStrongbranch() we restore the basis after the
40 * down branch and after the up branch; if false only after the end of a
41 * strong branching phase, which however seems to mostly increase strong
42 * branching time and iterations */
43
44/*
45 * include build configuration flags
46 */
47#ifndef NO_CONFIG_HEADER
48#include "scip/config.h"
49#endif
50
51/* in this case the SoPlex results are double checked using CPLEX */
52#ifdef SCIP_WITH_LPSCHECK
53#include <cplex.h>
54
55#define CHECK_SPXSOLVE true /**< shall the SoPlex results in spxSolve() be double checked using CPLEX? */
56#define CHECK_SPXSTRONGBRANCH true /**< shall the SoPlex results in SCIPlpStrongbranch() be double checked using CPLEX? */
57#define CHECK_START 0 /**< skip first CHECK_START number of checks */
58#define EXIT_AT_WRONG_RESULT false/**< shall program be exited if CPLEX returns different result than SoPlex? */
59#define EXIT_AT_CPXERROR false/**< shall program be exited if CPLEX returns an error? */
60
61#define CPX_CALL(x) do \
62 { \
63 int _cpxstat_; \
64 if( (_cpxstat_ = (x)) != 0 ) \
65 { \
66 SCIPmessagePrintWarning(_messagehdlr, "CPLEX error <%d>; SoPlex result unchecked\n", _cpxstat_); \
67 if( EXIT_AT_CPXERROR ) \
68 { \
69 exit(1); \
70 } \
71 else \
72 { \
73 goto ENDCHECK; \
74 } \
75 } \
76 } \
77 while( false )
78#endif
79
80/* check the return value of setParam methods */
81#define CHECK_SOPLEX_PARAM(x) \
82 if( !x ) \
83 { \
84 SCIPmessagePrintWarning(_messagehdlr, "SoPlex: unsupported parameter value\n"); \
85 }
86
87/* remember the original value of the SCIP_DEBUG define and undefine it */
88#ifdef SCIP_DEBUG
89#define ___DEBUG
90#undef SCIP_DEBUG
91#endif
92
93/* compile the SoPlex header with visibility=default because the SoPlex lib has been compiled that way */
94#ifdef __GNUC__
95#pragma GCC visibility push(default)
96#endif
97
98/* include SoPlex solver */
99#include "soplex.h"
100
101/* define subversion for versions <= 1.5.0.1 */
102#ifndef SOPLEX_SUBVERSION
103#define SOPLEX_SUBVERSION 0
104#endif
105/* define API version for versions <= 3.0.0 */
106#ifndef SOPLEX_APIVERSION
107#define SOPLEX_APIVERSION 0
108#endif
109
110/* check version */
111#if (SOPLEX_VERSION < 200 || (SOPLEX_VERSION == 200 && SOPLEX_SUBVERSION < 2) || (SOPLEX_VERSION > 200 && SOPLEX_VERSION < 201))
112#error "This interface is not compatible with SoPlex versions prior to 2.0.0.2"
113#endif
114
115#if (SOPLEX_APIVERSION <= 5)
116#include "spxgithash.h"
117#endif
118
119/* reset the SCIP_DEBUG define to its original SCIP value */
120#undef SCIP_DEBUG
121#ifdef ___DEBUG
122#define SCIP_DEBUG
123#undef ___DEBUG
124#endif
125
126/* define snprintf when using a too old MSVC version */
127#if defined(_MSC_VER) && _MSC_VER < 1900
128#ifndef snprintf
129#define snprintf _snprintf
130#endif
131#endif
132
133#define SOPLEX_VERBLEVEL 5 /**< verbosity level for LPINFO */
134
135#include "scip/pub_message.h"
136
137/********************************************************************/
138/*----------------------------- C++ --------------------------------*/
139/********************************************************************/
140
141/* in C++ we have to use "0" instead of "(void*)0" */
142#undef NULL
143#define NULL 0
144
145#include <cassert>
146using namespace soplex;
147
148
149/** Macro for a single SoPlex call for which exceptions have to be catched - return an LP error. We
150 * make no distinction between different exception types, e.g., between memory allocation and other
151 * exceptions.
152 */
153#ifndef NDEBUG
154#define SOPLEX_TRY(messagehdlr, x) do \
155 { \
156 try \
157 { \
158 (x); \
159 } \
160 catch( const SPxMemoryException& E ) \
161 { \
162 std::string s = E.what(); \
163 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
164 return SCIP_ERROR; \
165 } \
166 catch( const SPxException& E ) \
167 { \
168 std::string s = E.what(); \
169 SCIPmessagePrintWarning((messagehdlr), "SoPlex threw an exception: %s\n", s.c_str()); \
170 return SCIP_LPERROR; \
171 } \
172 } \
173 while( FALSE )
174
175#else
176#define SOPLEX_TRY(messagehdlr, x) do \
177 { \
178 try \
179 { \
180 (x); \
181 } \
182 catch( const SPxMemoryException& E ) \
183 { \
184 std::string s = E.what(); \
185 SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
186 return SCIP_ERROR; \
187 } \
188 catch( const SPxException& ) \
189 { \
190 return SCIP_LPERROR; \
191 } \
192 } \
193 while( FALSE )
194#endif
195
196/* Macro for a single SoPlex call for which exceptions have to be catched - abort if they
197 * arise. SCIP_ABORT() is not accessible here.
198 */
199#define SOPLEX_TRY_ABORT(x) do \
200 { \
201 try \
202 { \
203 (x); \
204 } \
205 catch( const SPxException& E ) \
206 { \
207 std::string s = E.what(); \
208 SCIPerrorMessage("SoPlex threw an exception: %s\n", s.c_str()); \
209 abort(); \
210 } \
211 } \
212 while( FALSE )
213
214
215
216/** SCIP's SoPlex class */
217class SPxSCIP : public SoPlex
218{/*lint !e1790*/
219 bool _lpinfo;
220 bool _fromscratch;
221 bool _interrupt;
222 char* _probname;
223 DataArray<SPxSolver::VarStatus> _colStat; /**< column basis status used for strong branching */
224 DataArray<SPxSolver::VarStatus> _rowStat; /**< row basis status used for strong branching */
225#ifdef SCIP_WITH_LPSCHECK
226 int _checknum;
227 bool _doublecheck;
228 CPXENVptr _cpxenv; /**< CPLEX memory environment */
229 CPXLPptr _cpxlp; /**< CPLEX lp structure */
230#endif
231 SCIP_MESSAGEHDLR* _messagehdlr; /**< messagehdlr handler for printing messages, or NULL */
232
233public:
234 SPxSCIP(
235 SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
236 const char* probname = NULL /**< name of problem */
237 )
238 : _lpinfo(false),
239 _fromscratch(false),
240 _probname(NULL),
241 _colStat(0),
242 _rowStat(0),
243 _messagehdlr(messagehdlr)
244 {
245 if ( probname != NULL )
246 SOPLEX_TRY_ABORT( setProbname(probname) );
247
248#if SOPLEX_APIVERSION >= 2
249 (void)setBoolParam(SoPlex::ENSURERAY, true);
250#endif
251
252#ifdef SCIP_WITH_LPSCHECK
253 int cpxstat;
254 _checknum = 0;
255 _doublecheck = false;
257 assert(_cpxenv != NULL);
258 _cpxlp = CPXcreateprob(_cpxenv, &cpxstat, probname != NULL ? probname : "spxcheck");
260#endif
261 }
262
263 virtual ~SPxSCIP()
264 {
265 if( _probname != NULL )
266 spx_free(_probname); /*lint !e1551*/
267
268 freePreStrongbranchingBasis(); /*lint !e1551*/
269
270#ifdef SCIP_WITH_LPSCHECK
273#endif
274 }/*lint -e1579*/
275
276 // we might need these methods to return the original values SCIP provided, even if they could not be set
277 /** return feastol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
278 Real feastol() const
279 {
280 return realParam(FEASTOL);
281 }
282
283 /** set feastol and store value in case SoPlex only accepts a larger tolerance */
284 void setFeastol(
285 const Real d
286 )
287 {
289 }
290
291 /** return opttol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
292 Real opttol() const
293 {
294 return realParam(OPTTOL);
295 }
296
297 /** set opttol and store value in case SoPlex only accepts a larger tolerance */
298 void setOpttol(
299 const Real d
300 )
301 {
303 }
304
305 /** get objective limit according to objective sense */
306 Real getObjLimit() const
307 {
308 return (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE)
309 ? realParam(SoPlex::OBJLIMIT_UPPER)
310 : realParam(SoPlex::OBJLIMIT_LOWER);
311 }
312
313 // @todo realize this with a member variable as before
314 bool getFromScratch() const
315 {
316 return _fromscratch;
317 }
318
319 void setFromScratch(bool fs)
320 {
321 _fromscratch = fs;
322 }
323
324 void setInterrupt(bool interrupt)
325 {
326 _interrupt = interrupt;
327 }
328
329 bool* getInterrupt()
330 {
331 return &_interrupt;
332 }
333
334 // @todo member variable?
335 bool getLpInfo() const
336 {
337 return _lpinfo;
338 }
339
340 void setLpInfo(bool lpinfo)
341 {
342 _lpinfo = lpinfo;
343 }
344
345 // @todo member variable?
346 void setProbname(const char* probname)
347 {
348 size_t len;
349
350 assert(probname != NULL);
351 if( _probname != NULL )
352 spx_free(_probname);
353
354 len = strlen(probname);
355 spx_alloc(_probname, len + 1);
356 memcpy(_probname, probname, len + 1);
357 }
358
359 void setRep(SPxSolver::Representation p_rep)
360 {
361 if( p_rep == SPxSolver::COLUMN && intParam(REPRESENTATION) == REPRESENTATION_ROW )
362 {
363 SCIPdebugMessage("switching to column representation of the basis\n");
365 }
366 else if( (p_rep == SPxSolver::ROW && intParam(REPRESENTATION) == REPRESENTATION_COLUMN) )
367 {
368 SCIPdebugMessage("switching to row representation of the basis\n");
370 }
371 }
372
373#ifdef SCIP_WITH_LPSCHECK
374 bool getDoubleCheck()
375 {
376 _checknum++;
377 return _doublecheck && _checknum + 1 >= CHECK_START;
378 }
379
380 void setDoubleCheck(bool dc)
381 {
383 }
384
385 const char* spxStatusString(const SPxSolver::Status stat) const
386 {
387 switch( stat )
388 {
389 case SPxSolver::ABORT_TIME:
390 return "ABORT_TIME";
391 case SPxSolver::ABORT_ITER:
392 return "ABORT_ITER";
393 case SPxSolver::ABORT_VALUE:
394 return "ABORT_VALUE";
395 case SPxSolver::SINGULAR:
396 return "SINGULAR";
397 case SPxSolver::REGULAR:
398 return "REGULAR";
399 case SPxSolver::UNKNOWN:
400 return "UNKNOWN";
401 case SPxSolver::OPTIMAL:
402 return "OPTIMAL";
403#if SOPLEX_APIVERSION >= 3
404 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
405 return "OPTIMAL_UNSCALED_VIOLATIONS";
406#endif
407 case SPxSolver::UNBOUNDED:
408 return "UNBOUNDED";
409 case SPxSolver::INFEASIBLE:
410 return "INFEASIBLE";
411 default:
412 return "UNKNOWN";
413 } /*lint !e788*/
414 }
415
416 const char* cpxStatusString(const int stat) const
417 {
418 switch( stat )
419 {
421 return "ABORT_TIME";
423 return "ABORT_ITER";
425 return "ABORT_VALUE";
426 case CPX_STAT_OPTIMAL:
427 return "OPTIMAL";
429 return "CPX_STAT_OPTIMAL_INFEAS: OPT SOL INFEASIBLE AFTER UNSCALING";
431 return "UNBOUNDED";
433 return "INFEASIBLE";
435 return "INFEASIBLE or UNBOUNDED";
437 return "CPX_STAT_NUM_BEST: SOL AVAILABLE BUT NOT PROVEN OPTIMAL DUE TO NUM TROUBLE";
438 default:
439 return "UNKNOWN";
440 } /*lint !e788*/
441 }
442#endif
443
444#ifndef NDEBUG
445 bool checkConsistentBounds() const
446 {
447 for( int i = 0; i < numColsReal(); ++i )
448 {
449 if( lowerReal(i) > upperReal(i) + realParam(SoPlex::EPSILON_ZERO) )
450 {
451 SCIPerrorMessage("inconsistent bounds on column %d: lower=%.17g, upper=%.17g\n",
452 i, lowerReal(i), upperReal(i));
453 return false;
454 }
455 }
456
457 return true;
458 }
459
460 bool checkConsistentSides() const
461 {
462 for( int i = 0; i < numRowsReal(); ++i )
463 {
464 if( lhsReal(i) > rhsReal(i) + realParam(SoPlex::EPSILON_ZERO) )
465 {
466 SCIPerrorMessage("inconsistent sides on row %d: lhs=%.17g, rhs=%.17g\n",
467 i, lhsReal(i), rhsReal(i));
468 return false;
469 }
470 }
471
472 return true;
473 }
474#endif
475
476 void trySolve(bool printwarning = true)
477 {
479 Real timelimit;
480
481 try
482 {
483#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
484#if SOPLEX_APIVERSION > 11
485 (void) optimize(&_interrupt);
486#else
487 (void) optimize();
488#endif
489#else
490 (void) solve();
491#endif
492 }
493 catch(const SPxException& x)
494 {
495 std::string s = x.what();
496 if( printwarning )
497 {
498 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
499 }
500
501 /* since it is not clear if the status in SoPlex are set correctly
502 * we want to make sure that if an error is thrown the status is
503 * not OPTIMAL anymore.
504 */
505 assert(status() != SPxSolver::OPTIMAL);
506 }
507
509
510 /* update time limit */
512 if( timespent > 0 )
513 {
514 /* get current time limit */
515 timelimit = realParam(TIMELIMIT);
516 if( timelimit > timespent )
517 timelimit -= timespent;
518 else
519 timelimit = 0;
520 /* set new time limit */
521 assert(timelimit >= 0);
523 }
524 }
525
526 SPxSolver::Status doSolve(bool printwarning = true)
527 {
528 SPxOut::Verbosity verbosity;
529
530 SPxSolver::Status spxStatus;
531
532 /* store and set verbosity */
533 verbosity = spxout.getVerbosity();
534 spxout.setVerbosity((SPxOut::Verbosity)(getLpInfo() ? SOPLEX_VERBLEVEL : 0));
535
536 assert(checkConsistentBounds());
537 assert(checkConsistentSides());
538
539#ifdef SCIP_WITH_LPSCHECK
540 /* dump LP with current basis and settings saved in SoPlex */
541 if( getDoubleCheck() )
542 writeStateReal("spxcheck", NULL, NULL);
543#endif
544
545 trySolve(printwarning);
546 spxStatus = status();
547
548 /* for safety reset iteration limit */
549// setTerminationIter(_itlim);
550
551#ifdef SCIP_WITH_LPSCHECK
555
556 /* if SoPlex gave a definite answer, we double check if it is consistent with CPLEX's answer */
557 if( getDoubleCheck() && (spxStatus == SPxSolver::OPTIMAL || spxStatus == SPxSolver::UNBOUNDED || spxStatus == SPxSolver::INFEASIBLE || spxStatus == SPxSolver::ABORT_VALUE) )
558 {
559 SCIP_Real cpxobj;
560 int cpxstat;
561
562 /* read LP with basis */
563 CPX_CALL( CPXreadcopyprob(_cpxenv, _cpxlp, "spxcheck.mps", NULL) );
564 CPX_CALL( CPXreadcopybase(_cpxenv, _cpxlp, "spxcheck.bas") );
565
566 /* set tolerances */
568 CPX_CALL( CPXsetdblparam(_cpxenv, CPX_PARAM_EPRHS, MAX(feastol(), 1e-9)) );
569
570 /* solve LP */
572
573 /* get solution status and objective value */
575 if( !minimize )
576 cpxobj *= -1.0;
577
578 /* check for inconsistent statuses */
580 {
581 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s)\n",
583 if( EXIT_AT_CPXERROR )
584 exit(1);
585 }
586 else if( (spxStatus == SPxSolver::OPTIMAL && cpxstat != CPX_STAT_OPTIMAL)
587 || (spxStatus == SPxSolver::UNBOUNDED && cpxstat != CPX_STAT_UNBOUNDED)
588 || (spxStatus == SPxSolver::INFEASIBLE && cpxstat != CPX_STAT_INFEASIBLE) )
589 {
590 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
593 exit(1);
594 }
595 else if( spxStatus == SPxSolver::ABORT_VALUE )
596 {
597 switch( cpxstat )
598 {
599 case CPX_STAT_OPTIMAL:
600 if( (minimize && LTrel(cpxobj, objLimitUpper, 2*opttol()))
601 || (!minimize && GTrel(cpxobj, objLimitLower, 2*opttol())) )
602 {
603 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
604 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize ? "<" : ">",
607 exit(1);
608 }
609 else if( (minimize && cpxobj < objLimitUpper) || (!minimize && cpxobj > objLimitLower) )
610 {
611 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
612 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize? "<" : ">",
614 }
615 break;
619 {
620 SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
621 _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize ? "<" : ">",
623 }
624 break;
626 break;
628 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
631 exit(1);
632 break;
634 default:
635 SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
637 break;
638 } /*lint !e788*/
639 }
640 /* check for same objective values */
641 else if( spxStatus == SPxSolver::OPTIMAL )
642 {
643 if( (minimize && LTrel(objValueReal(), cpxobj, 2*opttol()))
644 || (!minimize && GTrel(objValueReal(), cpxobj, 2*opttol())) )
645 {
646 /* SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f too good (checknum=%d)\n", value(),
647 _probname, getSense() == SPxSolver::MINIMIZE ? "<" : ">", cpxobj, _checknum); */
648 }
649 else if( (minimize && GTrel(objValueReal(), cpxobj, 2*opttol()))
650 || (!minimize && LTrel(objValueReal(), cpxobj, 2*opttol())) )
651 {
652 SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f suboptimal (checknum=%d)\n", _probname, objValueReal(),
653 minimize ? ">" : "<", cpxobj, _checknum);
655 exit(1);
656 }
657 }
658 }
659
660 ENDCHECK:
661#endif
662
663 /* restore verbosity */
664 spxout.setVerbosity(verbosity);
665
666 return spxStatus;
667 }
668
669 /** save the current basis */
670 void savePreStrongbranchingBasis()
671 {
672 _rowStat.reSize(numRowsReal());
673 _colStat.reSize(numColsReal());
674
675 try
676 {
677 getBasis(_rowStat.get_ptr(), _colStat.get_ptr());
678 }
679#ifndef NDEBUG
680 catch(const SPxException& x)
681 {
682 std::string s = x.what();
683 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
684
685 /* since it is not clear if the status in SoPlex are set correctly
686 * we want to make sure that if an error is thrown the status is
687 * not OPTIMAL anymore.
688 */
689 assert(status() != SPxSolver::OPTIMAL);
690 }
691#else
692 catch(const SPxException&)
693 { }
694#endif
695 }
696
697 /** restore basis */
698 void restorePreStrongbranchingBasis()
699 {
700 assert(_rowStat.size() == numRowsReal());
701 assert(_colStat.size() == numColsReal());
702
703 try
704 {
705 setBasis(_rowStat.get_ptr(), _colStat.get_ptr());
706 }
707#ifndef NDEBUG
708 catch(const SPxException& x)
709 {
710 std::string s = x.what();
711 SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
712#else
713 catch(const SPxException&)
714 {
715#endif
716 /* since it is not clear if the status in SoPlex are set correctly
717 * we want to make sure that if an error is thrown the status is
718 * not OPTIMAL anymore.
719 */
720 assert(status() != SPxSolver::OPTIMAL);
721 }
722 }
723
724 /** if basis is in store, delete it without restoring it */
725 void freePreStrongbranchingBasis()
726 {
727 _rowStat.clear();
728 _colStat.clear();
729 }
730
731 /** is pre-strong-branching basis freed? */
732 bool preStrongbranchingBasisFreed() const
733 {
734 return ((_rowStat.size() == 0 ) && (_colStat.size() == 0));
735 }
736
737 /** provides access for temporary storage of basis status of rows */
739 {
740 return _rowStat; /*lint !e1536*/
741 }
742
743 /** provides access for temporary storage of basis status or columns */
745 {
746 return _colStat; /*lint !e1536*/
747 }
748
749}; /*lint !e1748*/
750
751
752
753
754/********************************************************************/
755/*----------------------------- C --------------------------------*/
756/********************************************************************/
757
758#include "lpi/lpi.h"
759#include "scip/bitencode.h"
760
761typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
762#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
763typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
764#define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
765
766
767
768/** LP interface */
769struct SCIP_LPi
770{
771 SPxSCIP* spx; /**< our SoPlex implementation */
772 int* cstat; /**< array for storing column basis status */
773 int* rstat; /**< array for storing row basis status */
774 int cstatsize; /**< size of cstat array */
775 int rstatsize; /**< size of rstat array */
776 SCIP_PRICING pricing; /**< current pricing strategy */
777 SCIP_Bool solved; /**< was the current LP solved? */
778 SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
779 SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
780 SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
781};
782
783/** LPi state stores basis information */
784struct SCIP_LPiState
785{
786 int ncols; /**< number of LP columns */
787 int nrows; /**< number of LP rows */
788 COLPACKET* packcstat; /**< column basis status in compressed form */
789 ROWPACKET* packrstat; /**< row basis status in compressed form */
790};
791
792/** LPi norms to store dual steepest edge */
793struct SCIP_LPiNorms
794{
795 int nrows; /**< number of stored norms corresponding to rows */
796 int ncols; /**< number of stored norms corresponding to cols */
797 SCIP_Real* norms; /**< norms to be (re)stored */
798};
799
800
801
802/*
803 * dynamic memory arrays
804 */
805
806/** resizes cstat array to have at least num entries */
807static
809 SCIP_LPI* lpi, /**< LP interface structure */
810 int num /**< minimal number of entries in array */
811 )
812{
813 assert(lpi != NULL);
814
815 if( num > lpi->cstatsize )
816 {
817 int newsize;
818
819 newsize = MAX(2*lpi->cstatsize, num);
821 lpi->cstatsize = newsize;
822 }
823 assert(num <= lpi->cstatsize);
824
825 return SCIP_OKAY;
826}
827
828/** resizes rstat array to have at least num entries */
829static
831 SCIP_LPI* lpi, /**< LP interface structure */
832 int num /**< minimal number of entries in array */
833 )
834{
835 assert(lpi != NULL);
836
837 if( num > lpi->rstatsize )
838 {
839 int newsize;
840
841 newsize = MAX(2*lpi->rstatsize, num);
843 lpi->rstatsize = newsize;
844 }
845 assert(num <= lpi->rstatsize);
846
847 return SCIP_OKAY;
848}
849
850
851
852
853/*
854 * LPi state methods
855 */
856
857/** returns the number of packets needed to store column packet information */
858static
860 int ncols /**< number of columns to store */
861 )
862{
863 return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
864}
865
866/** returns the number of packets needed to store row packet information */
867static
869 int nrows /**< number of rows to store */
870 )
871{
872 return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
873}
874
875/** store row and column basis status in a packed LPi state object */
876static
878 SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
879 const int* cstat, /**< basis status of columns in unpacked format */
880 const int* rstat /**< basis status of rows in unpacked format */
881 )
882{
883 assert(lpistate != NULL);
884 assert(lpistate->packcstat != NULL);
885 assert(lpistate->packrstat != NULL);
886
887 SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
888 SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
889}
890
891/** unpacks row and column basis status from a packed LPi state object */
892static
894 const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
895 int* cstat, /**< buffer for storing basis status of columns in unpacked format */
896 int* rstat /**< buffer for storing basis status of rows in unpacked format */
897 )
898{
899 assert(lpistate != NULL);
900 assert(lpistate->packcstat != NULL);
901 assert(lpistate->packrstat != NULL);
902
903 SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
904 SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
905}
906
907/** creates LPi state information object */
908static
910 SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
911 BMS_BLKMEM* blkmem, /**< block memory */
912 int ncols, /**< number of columns to store */
913 int nrows /**< number of rows to store */
914 )
915{
916 assert(lpistate != NULL);
917 assert(blkmem != NULL);
918 assert(ncols >= 0);
919 assert(nrows >= 0);
920
921 int nColPackets = colpacketNum(ncols);
922 int nRowPackets = rowpacketNum(nrows);
923
924 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
925 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
926 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
927
928 return SCIP_OKAY;
929}
930
931/** frees LPi state information */
932static
934 SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
935 BMS_BLKMEM* blkmem /**< block memory */
936 )
937{
938 assert(blkmem != NULL);
939 assert(lpistate != NULL);
940 assert(*lpistate != NULL);
941
942 int nColPackets = colpacketNum((*lpistate)->ncols);
943 int nRowPackets = rowpacketNum((*lpistate)->nrows);
944
945 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
946 BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
947 BMSfreeBlockMemory(blkmem, lpistate);
948}
949
950
951
952
953/*
954 * local methods
955 */
956
957
958/** marks the current LP to be unsolved */
959static
961{
962 assert(lpi != NULL);
963 lpi->solved = FALSE;
964}
965
966
967
968/*
969 * LP Interface Methods
970 */
971
972
973/*
974 * Miscellaneous Methods
975 */
976
977#if (SOPLEX_SUBVERSION > 0)
978 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'};
979#else
980 const static char spxname[20] = {'S', 'o', 'p', 'l', 'e', 'x', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0'};
981#endif
982const static char spxdesc[200] = {'L', 'i', 'n', 'e', 'a', 'r', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g',
983 ' ', 'S', 'o', 'l', 'v', 'e', 'r', ' ' , 'd', 'e', 'v', 'e', 'l', 'o', 'p', 'e', 'd',
984 ' ', 'a', 't', ' ', 'Z', 'u', 's', 'e', ' ', 'I', 'n', 's', 't', 'i', 't', 'u', 't', 'e',
985 ' ', 'B', 'e', 'r', 'l', 'i', 'n', ' ', '(', 's', 'o', 'p', 'l', 'e', 'x', '.', 'z', 'i', 'b', '.', 'd', 'e', ')',
986#ifdef SCIP_WITH_LPSCHECK
987 ' ', '-', ' ', 'i', 'n', 'c', 'l', 'u', 'd', 'i', 'n', 'g', ' ', 'C','P','L', 'E', 'X',
988 ' ', 'd', 'o', 'u', 'b', 'l', 'e', ' ', 'c', 'h', 'e', 'c', 'k',
989#endif
990 ' ', '[', 'G', 'i', 't', 'H', 'a', 's', 'h', ':', ' ',
991 getGitHash()[0], getGitHash()[1], getGitHash()[2], getGitHash()[3],
992 getGitHash()[4], getGitHash()[5], getGitHash()[6], getGitHash()[7],
993 ']'};
994
995/**@name Miscellaneous Methods */
996/**@{ */
997
998/** gets name and version of LP solver */
1000 void
1001 )
1002{
1003 SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
1004 return spxname;
1005}
1006
1007/** gets description of LP solver (developer, webpage, ...) */
1009 void
1010 )
1011{
1012 return spxdesc;
1013}
1014
1015/** gets pointer for LP solver - use only with great care */
1017 SCIP_LPI* lpi /**< pointer to an LP interface structure */
1018 )
1019{
1020 return (void*) lpi->spx;
1021}
1022
1023/** pass integrality information about variables to the solver */
1025 SCIP_LPI* lpi, /**< pointer to an LP interface structure */
1026 int ncols, /**< length of integrality array */
1027 int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
1028 )
1029{
1030 assert( lpi != NULL );
1031 assert( ncols >= 0 );
1032 assert( ncols == 0 || intInfo != NULL );
1033
1034#if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
1035 assert(ncols == lpi->spx->numColsReal() || (ncols == 0 && intInfo == NULL));
1036 lpi->spx->setIntegralityInformation(ncols, intInfo);
1037 return SCIP_OKAY;
1038#else
1039 SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
1040 return SCIP_LPERROR;
1041#endif
1042}
1043
1044/** informs about availability of a primal simplex solving method */
1046 void
1047 )
1048{
1049 return TRUE;
1050}
1051
1052/** informs about availability of a dual simplex solving method */
1054 void
1055 )
1056{
1057 return TRUE;
1058}
1059
1060/** informs about availability of a barrier solving method */
1062 void
1063 )
1064{
1065 return FALSE;
1066}
1067
1068/**@} */
1069
1070
1071
1072
1073/*
1074 * LPI Creation and Destruction Methods
1075 */
1076
1077/**@name LPI Creation and Destruction Methods */
1078/**@{ */
1079
1080/** creates an LP problem object */
1082 SCIP_LPI** lpi, /**< pointer to an LP interface structure */
1083 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
1084 const char* name, /**< problem name */
1085 SCIP_OBJSEN objsen /**< objective sense */
1086 )
1087{
1088 assert(lpi != NULL);
1089 assert(name != NULL);
1090
1091 /* create SoPlex object */
1092 SCIP_ALLOC( BMSallocMemory(lpi) );
1093
1094 /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
1095 (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
1096 SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
1097 (void) (*lpi)->spx->setIntParam(SoPlex::SYNCMODE, SoPlex::SYNCMODE_ONLYREAL);
1098 (void) (*lpi)->spx->setIntParam(SoPlex::SOLVEMODE, SoPlex::SOLVEMODE_REAL);
1099 (void) (*lpi)->spx->setIntParam(SoPlex::REPRESENTATION, SoPlex::REPRESENTATION_AUTO);
1100
1101 /* disable time-measurement for statistics */
1102#if SOPLEX_APIVERSION >= 10
1103 (void) (*lpi)->spx->setIntParam(SoPlex::STATTIMER, 0);
1104#endif
1105
1106 (*lpi)->cstat = NULL;
1107 (*lpi)->rstat = NULL;
1108 (*lpi)->cstatsize = 0;
1109 (*lpi)->rstatsize = 0;
1110 (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
1111 (*lpi)->conditionlimit = -1.0;
1112 (*lpi)->checkcondition = FALSE;
1113 (*lpi)->messagehdlr = messagehdlr;
1114
1115 invalidateSolution(*lpi);
1116
1117 /* set objective sense */
1119
1120 /* set default pricing */
1121 SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
1122
1123 {
1124 (*lpi)->spx->setInterrupt(FALSE);
1125 SPxOut::Verbosity verbosity = (*lpi)->spx->spxout.getVerbosity();
1126 (*lpi)->spx->spxout.setVerbosity((SPxOut::Verbosity)((*lpi)->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
1127 (*lpi)->spx->printVersion();
1128 (*lpi)->spx->spxout.setVerbosity(verbosity);
1129 }
1130
1131 return SCIP_OKAY;
1132}
1133
1134/** deletes an LP problem object */
1136 SCIP_LPI** lpi /**< pointer to an LP interface structure */
1137 )
1138{
1139 assert(lpi != NULL);
1140 assert(*lpi != NULL);
1141 assert((*lpi)->spx != NULL);
1142
1143 /* free LP using destructor and free memory via blockmemshell */
1144 (*lpi)->spx->~SPxSCIP();
1145 BMSfreeMemory(&((*lpi)->spx));
1146
1147 /* free memory */
1148 BMSfreeMemoryArrayNull(&(*lpi)->cstat);
1149 BMSfreeMemoryArrayNull(&(*lpi)->rstat);
1150 BMSfreeMemory(lpi);
1151
1152 return SCIP_OKAY;
1153}
1154
1155/**@} */
1156
1157
1158
1159
1160/*
1161 * Modification Methods
1162 */
1163
1164/**@name Modification Methods */
1165/**@{ */
1166
1167/** copies LP data with column matrix into LP solver */
1169 SCIP_LPI* lpi, /**< LP interface structure */
1170 SCIP_OBJSEN objsen, /**< objective sense */
1171 int ncols, /**< number of columns */
1172 const SCIP_Real* obj, /**< objective function values of columns */
1173 const SCIP_Real* lb, /**< lower bounds of columns */
1174 const SCIP_Real* ub, /**< upper bounds of columns */
1175 char** colnames, /**< column names, or NULL */
1176 int nrows, /**< number of rows */
1177 const SCIP_Real* lhs, /**< left hand sides of rows */
1178 const SCIP_Real* rhs, /**< right hand sides of rows */
1179 char** /*rownames*/, /**< row names, or NULL */
1180 int nnonz, /**< number of nonzero elements in the constraint matrix */
1181 const int* beg, /**< start index of each column in ind- and val-array */
1182 const int* ind, /**< row indices of constraint matrix entries */
1183 const SCIP_Real* val /**< values of constraint matrix entries */
1184 )
1185{
1186#ifndef NDEBUG
1187 {
1188 int j;
1189 for( j = 0; j < nnonz; j++ )
1190 assert( val[j] != 0 );
1191 }
1192#endif
1193
1194 SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
1195
1196 assert(lpi != NULL);
1197 assert(lpi->spx != NULL);
1198 assert(lhs != NULL);
1199 assert(rhs != NULL);
1200 assert(obj != NULL);
1201 assert(lb != NULL);
1202 assert(ub != NULL);
1203 assert(beg != NULL);
1204 assert(ind != NULL);
1205 assert(val != NULL);
1206
1207 invalidateSolution(lpi);
1208 assert(lpi->spx->preStrongbranchingBasisFreed());
1209
1210 try
1211 {
1212 SPxSCIP* spx = lpi->spx;
1213 LPRowSet rows(nrows);
1215 int i;
1216
1217 spx->clearLPReal();
1218
1219 /* set objective sense */
1220 (void) spx->setIntParam(SoPlex::OBJSENSE, (objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE));
1221
1222 /* create empty rows with given sides */
1223 for( i = 0; i < nrows; ++i )
1224 rows.add(lhs[i], emptyVector, rhs[i]);
1225 spx->addRowsReal(rows);
1226
1227 /* create column vectors with coefficients and bounds */
1228 SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
1229 }
1230#ifndef NDEBUG
1231 catch( const SPxException& x )
1232 {
1233 std::string s = x.what();
1234 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1235#else
1236 catch( const SPxException& )
1237 {
1238#endif
1239 return SCIP_LPERROR;
1240 }
1241
1242 return SCIP_OKAY;
1243}
1244
1245/** adds columns to the LP */
1247 SCIP_LPI* lpi, /**< LP interface structure */
1248 int ncols, /**< number of columns to be added */
1249 const SCIP_Real* obj, /**< objective function values of new columns */
1250 const SCIP_Real* lb, /**< lower bounds of new columns */
1251 const SCIP_Real* ub, /**< upper bounds of new columns */
1252 char** /*colnames*/, /**< column names, or NULL */
1253 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1254 const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1255 const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1256 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1257 )
1258{
1259 SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1260
1261 assert(lpi != NULL);
1262 assert(lpi->spx != NULL);
1263 assert(obj != NULL);
1264 assert(lb != NULL);
1265 assert(ub != NULL);
1266 assert(nnonz == 0 || beg != NULL);
1267 assert(nnonz == 0 || ind != NULL);
1268 assert(nnonz == 0 || val != NULL);
1269 assert(nnonz >= 0);
1270 assert(ncols >= 0);
1271
1272 invalidateSolution(lpi);
1273
1274 assert( lpi->spx->preStrongbranchingBasisFreed() );
1275
1276#ifndef NDEBUG
1277 if ( nnonz > 0 )
1278 {
1279 /* perform check that no new rows are added - this is likely to be a mistake */
1280 int nrows = lpi->spx->numRowsReal();
1281 for (int j = 0; j < nnonz; ++j)
1282 {
1283 assert( 0 <= ind[j] && ind[j] < nrows );
1284 assert( val[j] != 0.0 );
1285 }
1286 }
1287#endif
1288
1289 SPxSCIP* spx = lpi->spx;
1290 try
1291 {
1292 LPColSet cols(ncols);
1293 DSVector colVector(ncols);
1294 int start;
1295 int last;
1296 int i;
1297
1298 /* create column vectors with coefficients and bounds */
1299 for( i = 0; i < ncols; ++i )
1300 {
1301 colVector.clear();
1302 if( nnonz > 0 )
1303 {
1304 start = beg[i];
1305 last = (i == ncols-1 ? nnonz : beg[i+1]);
1306 colVector.add( last-start, &ind[start], &val[start] );
1307 }
1308 cols.add(obj[i], lb[i], colVector, ub[i]);
1309 }
1310 spx->addColsReal(cols);
1311 }
1312#ifndef NDEBUG
1313 catch( const SPxException& x )
1314 {
1315 std::string s = x.what();
1316 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1317#else
1318 catch( const SPxException& )
1319 {
1320#endif
1321 return SCIP_LPERROR;
1322 }
1323
1324 return SCIP_OKAY;
1325}
1326
1327/** deletes all columns in the given range from LP */
1329 SCIP_LPI* lpi, /**< LP interface structure */
1330 int firstcol, /**< first column to be deleted */
1331 int lastcol /**< last column to be deleted */
1332 )
1333{
1334 SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1335
1336 assert(lpi != NULL);
1337 assert(lpi->spx != NULL);
1338 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
1339
1340 invalidateSolution(lpi);
1341
1342 assert( lpi->spx->preStrongbranchingBasisFreed() );
1343
1344 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRangeReal(firstcol, lastcol) );
1345
1346 return SCIP_OKAY;
1347}
1348
1349/** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1351 SCIP_LPI* lpi, /**< LP interface structure */
1352 int* dstat /**< deletion status of columns
1353 * input: 1 if column should be deleted, 0 if not
1354 * output: new position of column, -1 if column was deleted */
1355 )
1356{
1357 int ncols;
1358 int i;
1359
1360 SCIPdebugMessage("calling SCIPlpiDelColset()\n");
1361
1362 assert(lpi != NULL);
1363 assert(lpi->spx != NULL);
1364 assert(dstat != NULL);
1365
1366 invalidateSolution(lpi);
1367
1368 assert( lpi->spx->preStrongbranchingBasisFreed() );
1369
1370 ncols = lpi->spx->numColsReal();
1371
1372 /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
1373 for( i = 0; i < ncols; ++i )
1374 dstat[i] *= -1;
1375
1376 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColsReal(dstat) );
1377
1378 return SCIP_OKAY;
1379}
1380
1381/** adds rows to the LP */
1383 SCIP_LPI* lpi, /**< LP interface structure */
1384 int nrows, /**< number of rows to be added */
1385 const SCIP_Real* lhs, /**< left hand sides of new rows */
1386 const SCIP_Real* rhs, /**< right hand sides of new rows */
1387 char** /*rownames*/, /**< row names, or NULL */
1388 int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1389 const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
1390 const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
1391 const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1392 )
1393{
1394 SCIPdebugMessage("calling SCIPlpiAddRows()\n");
1395
1396 assert(lpi != NULL);
1397 assert(lpi->spx != NULL);
1398 assert(lhs != NULL);
1399 assert(rhs != NULL);
1400 assert(nnonz == 0 || beg != NULL);
1401 assert(nnonz == 0 || ind != NULL);
1402 assert(nnonz == 0 || val != NULL);
1403
1404 invalidateSolution(lpi);
1405
1406 assert( lpi->spx->preStrongbranchingBasisFreed() );
1407
1408#ifndef NDEBUG
1409 if ( nnonz > 0 )
1410 {
1411 /* perform check that no new columns are added - this is likely to be a mistake */
1412 int ncols = lpi->spx->numColsReal();
1413 for (int j = 0; j < nnonz; ++j)
1414 {
1415 assert( val[j] != 0.0 );
1416 assert( 0 <= ind[j] && ind[j] < ncols );
1417 }
1418 }
1419#endif
1420
1421 try
1422 {
1423 SPxSCIP* spx = lpi->spx;
1424 LPRowSet rows(nrows);
1426 int start;
1427 int last;
1428 int i;
1429
1430 /* create row vectors with given sides */
1431 for( i = 0; i < nrows; ++i )
1432 {
1433 rowVector.clear();
1434 if( nnonz > 0 )
1435 {
1436 start = beg[i];
1437 last = (i == nrows-1 ? nnonz : beg[i+1]);
1438 rowVector.add( last-start, &ind[start], &val[start] );
1439 }
1440 rows.add(lhs[i], rowVector, rhs[i]);
1441 }
1442 spx->addRowsReal(rows);
1443 }
1444#ifndef NDEBUG
1445 catch( const SPxException& x )
1446 {
1447 std::string s = x.what();
1448 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1449#else
1450 catch( const SPxException& )
1451 {
1452#endif
1453 return SCIP_LPERROR;
1454 }
1455
1456 return SCIP_OKAY;
1457}
1458
1459/** deletes all rows in the given range from LP */
1461 SCIP_LPI* lpi, /**< LP interface structure */
1462 int firstrow, /**< first row to be deleted */
1463 int lastrow /**< last row to be deleted */
1464 )
1465{
1466 SCIPdebugMessage("calling SCIPlpiDelRows()\n");
1467
1468 assert(lpi != NULL);
1469 assert(lpi->spx != NULL);
1470 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
1471
1472 invalidateSolution(lpi);
1473
1474 assert( lpi->spx->preStrongbranchingBasisFreed() );
1475
1476 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRangeReal(firstrow, lastrow) );
1477
1478 return SCIP_OKAY;
1479}
1480
1481/** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
1483 SCIP_LPI* lpi, /**< LP interface structure */
1484 int* dstat /**< deletion status of rows
1485 * input: 1 if row should be deleted, 0 if not
1486 * output: new position of row, -1 if row was deleted */
1487 )
1488{
1489 int nrows;
1490 int i;
1491
1492 SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
1493
1494 assert(lpi != NULL);
1495 assert(lpi->spx != NULL);
1496
1497 invalidateSolution(lpi);
1498
1499 assert( lpi->spx->preStrongbranchingBasisFreed() );
1500
1501 nrows = lpi->spx->numRowsReal();
1502
1503 /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
1504 for( i = 0; i < nrows; ++i )
1505 dstat[i] *= -1;
1506
1507 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowsReal(dstat) );
1508
1509 return SCIP_OKAY;
1510}
1511
1512/** clears the whole LP */
1514 SCIP_LPI* lpi /**< LP interface structure */
1515 )
1516{
1517 SCIPdebugMessage("calling SCIPlpiClear()\n");
1518
1519 assert(lpi != NULL);
1520 assert(lpi->spx != NULL);
1521
1522 invalidateSolution(lpi);
1523
1524 assert( lpi->spx->preStrongbranchingBasisFreed() );
1525 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clearLPReal() );
1526
1527 return SCIP_OKAY;
1528}
1529
1530/** changes lower and upper bounds of columns */
1532 SCIP_LPI* lpi, /**< LP interface structure */
1533 int ncols, /**< number of columns to change bounds for */
1534 const int* ind, /**< column indices or NULL if ncols is zero */
1535 const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
1536 const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
1537 )
1538{
1539 int i;
1540
1541 SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
1542
1543 assert(lpi != NULL);
1544 assert(lpi->spx != NULL);
1545 assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
1546 if( ncols <= 0 )
1547 return SCIP_OKAY;
1548
1549 invalidateSolution(lpi);
1550
1551 assert( lpi->spx->preStrongbranchingBasisFreed() );
1552
1553 try
1554 {
1555 for( i = 0; i < ncols; ++i )
1556 {
1557 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
1558
1559 if ( SCIPlpiIsInfinity(lpi, lb[i]) )
1560 {
1561 SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
1562 return SCIP_LPERROR;
1563 }
1564 if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
1565 {
1566 SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
1567 return SCIP_LPERROR;
1568 }
1569
1570 lpi->spx->changeBoundsReal(ind[i], lb[i], ub[i]);
1571 assert(lpi->spx->lowerReal(ind[i]) <= lpi->spx->upperReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
1572 }
1573 }
1574#ifndef NDEBUG
1575 catch( const SPxException& x )
1576 {
1577 std::string s = x.what();
1578 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1579#else
1580 catch( const SPxException& )
1581 {
1582#endif
1583 return SCIP_LPERROR;
1584 }
1585
1586 return SCIP_OKAY;
1587}
1588
1589/** changes left and right hand sides of rows */
1591 SCIP_LPI* lpi, /**< LP interface structure */
1592 int nrows, /**< number of rows to change sides for */
1593 const int* ind, /**< row indices */
1594 const SCIP_Real* lhs, /**< new values for left hand sides */
1595 const SCIP_Real* rhs /**< new values for right hand sides */
1596 )
1597{
1598 int i;
1599
1600 SCIPdebugMessage("calling SCIPlpiChgSides()\n");
1601
1602 assert(lpi != NULL);
1603 assert(lpi->spx != NULL);
1604 assert(ind != NULL);
1605 assert(lhs != NULL);
1606 assert(rhs != NULL);
1607 if( nrows <= 0 )
1608 return SCIP_OKAY;
1609
1610 invalidateSolution(lpi);
1611
1612 assert( lpi->spx->preStrongbranchingBasisFreed() );
1613
1614 try
1615 {
1616 for( i = 0; i < nrows; ++i )
1617 {
1618 assert(0 <= ind[i] && ind[i] < lpi->spx->numRowsReal());
1619 lpi->spx->changeRangeReal(ind[i], lhs[i], rhs[i]);
1620 assert(lpi->spx->lhsReal(ind[i]) <= lpi->spx->rhsReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
1621 }
1622 }
1623#ifndef NDEBUG
1624 catch( const SPxException& x )
1625 {
1626 std::string s = x.what();
1627 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1628#else
1629 catch( const SPxException& )
1630 {
1631#endif
1632 return SCIP_LPERROR;
1633 }
1634
1635 return SCIP_OKAY;
1636}
1637
1638/** changes a single coefficient */
1640 SCIP_LPI* lpi, /**< LP interface structure */
1641 int row, /**< row number of coefficient to change */
1642 int col, /**< column number of coefficient to change */
1643 SCIP_Real newval /**< new value of coefficient */
1644 )
1645{
1646 SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
1647
1648 assert(lpi != NULL);
1649 assert(lpi->spx != NULL);
1650 assert(0 <= row && row < lpi->spx->numRowsReal());
1651 assert(0 <= col && col < lpi->spx->numColsReal());
1652
1653 invalidateSolution(lpi);
1654
1655 assert( lpi->spx->preStrongbranchingBasisFreed() );
1656
1657 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElementReal(row, col, newval) );
1658
1659 return SCIP_OKAY;
1660}
1661
1662/** changes the objective sense */
1664 SCIP_LPI* lpi, /**< LP interface structure */
1665 SCIP_OBJSEN objsen /**< new objective sense */
1666 )
1667{
1668 SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
1669
1670 assert(lpi != NULL);
1671 assert(lpi->spx != NULL);
1672
1673 invalidateSolution(lpi);
1674
1675 assert( lpi->spx->preStrongbranchingBasisFreed() );
1676
1677 SOPLEX_TRY( lpi->messagehdlr, (void) lpi->spx->setIntParam(SoPlex::OBJSENSE, objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE ) );
1678
1679 return SCIP_OKAY;
1680}
1681
1682/** changes objective values of columns in the LP */
1684 SCIP_LPI* lpi, /**< LP interface structure */
1685 int ncols, /**< number of columns to change objective value for */
1686 const int* ind, /**< column indices to change objective value for */
1687 const SCIP_Real* obj /**< new objective values for columns */
1688 )
1689{
1690 int i;
1691
1692 SCIPdebugMessage("calling SCIPlpiChgObj()\n");
1693
1694 assert(lpi != NULL);
1695 assert(lpi->spx != NULL);
1696 assert(ind != NULL);
1697 assert(obj != NULL);
1698
1699 invalidateSolution(lpi);
1700
1701 assert( lpi->spx->preStrongbranchingBasisFreed() );
1702
1703 try
1704 {
1705 for( i = 0; i < ncols; ++i )
1706 {
1707 assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
1708 lpi->spx->changeObjReal(ind[i], obj[i]);
1709 }
1710 }
1711#ifndef NDEBUG
1712 catch( const SPxException& x )
1713 {
1714 std::string s = x.what();
1715 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1716#else
1717 catch( const SPxException& )
1718 {
1719#endif
1720 return SCIP_LPERROR;
1721 }
1722
1723 return SCIP_OKAY;
1724}
1725
1726/** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
1728 SCIP_LPI* lpi, /**< LP interface structure */
1729 int row, /**< row number to scale */
1730 SCIP_Real scaleval /**< scaling multiplier */
1731 )
1732{
1733 SCIP_Real lhs;
1734 SCIP_Real rhs;
1735
1736 SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
1737
1738 assert(lpi != NULL);
1739 assert(lpi->spx != NULL);
1740 assert(scaleval != 0.0);
1741
1742 try
1743 {
1744 invalidateSolution(lpi);
1745
1746 assert( lpi->spx->preStrongbranchingBasisFreed() );
1747
1748 /* get the row vector and the row's sides */
1749#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1750 SVector rowvec = lpi->spx->rowVectorRealInternal(row);
1751#else
1752 SVector rowvec = lpi->spx->rowVectorReal(row);
1753#endif
1754 lhs = lpi->spx->lhsReal(row);
1755 rhs = lpi->spx->rhsReal(row);
1756
1757 /* scale the row vector */
1758 rowvec *= scaleval;
1759
1760 /* adjust the sides */
1761 if( lhs > -lpi->spx->realParam(SoPlex::INFTY) )
1762 lhs *= scaleval;
1763 else if( scaleval < 0.0 )
1764 lhs = lpi->spx->realParam(SoPlex::INFTY);
1765 if( rhs < lpi->spx->realParam(SoPlex::INFTY) )
1766 rhs *= scaleval;
1767 else if( scaleval < 0.0 )
1768 rhs = -lpi->spx->realParam(SoPlex::INFTY);
1769 if( scaleval < 0.0 )
1770 {
1771 SCIP_Real oldlhs = lhs;
1772 lhs = rhs;
1773 rhs = oldlhs;
1774 }
1775
1776 /* create the new row */
1777 LPRow lprow(lhs, rowvec, rhs);
1778
1779 /* change the row in the LP */
1780 lpi->spx->changeRowReal(row, lprow);
1781 assert(lpi->spx->lhsReal(row) <= lpi->spx->rhsReal(row));
1782 }
1783#ifndef NDEBUG
1784 catch( const SPxException& x )
1785 {
1786 std::string s = x.what();
1787 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1788#else
1789 catch( const SPxException& )
1790 {
1791#endif
1792 return SCIP_LPERROR;
1793 }
1794
1795 return SCIP_OKAY;
1796}
1797
1798/** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
1799 * are divided by the scalar; for negative scalars, the column's bounds are switched
1800 */
1802 SCIP_LPI* lpi, /**< LP interface structure */
1803 int col, /**< column number to scale */
1804 SCIP_Real scaleval /**< scaling multiplier */
1805 )
1806{
1807 SCIP_Real obj;
1808 SCIP_Real lb;
1809 SCIP_Real ub;
1810
1811 SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
1812
1813 assert(lpi != NULL);
1814 assert(lpi->spx != NULL);
1815 assert(scaleval != 0.0);
1816
1817 try
1818 {
1819 invalidateSolution(lpi);
1820
1821 assert( lpi->spx->preStrongbranchingBasisFreed() );
1822
1823 /* get the col vector and the col's bounds and objective value */
1824#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1825 SVector colvec = lpi->spx->colVectorRealInternal(col);
1826#else
1827 SVector colvec = lpi->spx->colVectorReal(col);
1828#endif
1829 obj = lpi->spx->objReal(col);
1830 lb = lpi->spx->lowerReal(col);
1831 ub = lpi->spx->upperReal(col);
1832
1833 /* scale the col vector */
1834 colvec *= scaleval;
1835
1836 /* scale the objective value */
1837 obj *= scaleval;
1838
1839 /* adjust the bounds */
1840 if( lb > -lpi->spx->realParam(SoPlex::INFTY) )
1841 lb /= scaleval;
1842 else if( scaleval < 0.0 )
1843 lb = lpi->spx->realParam(SoPlex::INFTY);
1844 if( ub < lpi->spx->realParam(SoPlex::INFTY) )
1845 ub /= scaleval;
1846 else if( scaleval < 0.0 )
1847 ub = -lpi->spx->realParam(SoPlex::INFTY);
1848 if( scaleval < 0.0 )
1849 {
1850 SCIP_Real oldlb = lb;
1851 lb = ub;
1852 ub = oldlb;
1853 }
1854
1855 /* create the new col (in LPCol's constructor, the upper bound is given first!) */
1856 LPCol lpcol(obj, colvec, ub, lb);
1857
1858 /* change the col in the LP */
1859 lpi->spx->changeColReal(col, lpcol);
1860 assert(lpi->spx->lowerReal(col) <= lpi->spx->upperReal(col));
1861 }
1862#ifndef NDEBUG
1863 catch( const SPxException& x )
1864 {
1865 std::string s = x.what();
1866 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1867#else
1868 catch( const SPxException& )
1869 {
1870#endif
1871 return SCIP_LPERROR;
1872 }
1873
1874 return SCIP_OKAY;
1875}
1876
1877/**@} */
1878
1879
1880
1881
1882/*
1883 * Data Accessing Methods
1884 */
1885
1886/**@name Data Accessing Methods */
1887/**@{ */
1888
1889/** gets the number of rows in the LP */
1891 SCIP_LPI* lpi, /**< LP interface structure */
1892 int* nrows /**< pointer to store the number of rows */
1893 )
1894{
1895 SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
1896
1897 assert(lpi != NULL);
1898 assert(lpi->spx != NULL);
1899 assert(nrows != NULL);
1900
1901 *nrows = lpi->spx->numRowsReal();
1902
1903 return SCIP_OKAY;
1904}
1905
1906/** gets the number of columns in the LP */
1908 SCIP_LPI* lpi, /**< LP interface structure */
1909 int* ncols /**< pointer to store the number of cols */
1910 )
1911{
1912 SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
1913
1914 assert(lpi != NULL);
1915 assert(lpi->spx != NULL);
1916 assert(ncols != NULL);
1917
1918 *ncols = lpi->spx->numColsReal();
1919
1920 return SCIP_OKAY;
1921}
1922
1923/** gets the number of nonzero elements in the LP constraint matrix */
1925 SCIP_LPI* lpi, /**< LP interface structure */
1926 int* nnonz /**< pointer to store the number of nonzeros */
1927 )
1928{
1929 int i;
1930
1931 SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
1932
1933 assert(lpi != NULL);
1934 assert(lpi->spx != NULL);
1935 assert(nnonz != NULL);
1936
1937 /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
1938 *nnonz = 0;
1939 if( lpi->spx->numRowsReal() < lpi->spx->numColsReal() )
1940 {
1941 for( i = 0; i < lpi->spx->numRowsReal(); ++i )
1942#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1943 (*nnonz) += lpi->spx->rowVectorRealInternal(i).size();
1944#else
1945 (*nnonz) += lpi->spx->rowVectorReal(i).size();
1946#endif
1947 }
1948 else
1949 {
1950 for( i = 0; i < lpi->spx->numColsReal(); ++i )
1951#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1952 (*nnonz) += lpi->spx->colVectorRealInternal(i).size();
1953#else
1954 (*nnonz) += lpi->spx->colVectorReal(i).size();
1955#endif
1956 }
1957
1958 return SCIP_OKAY;
1959}
1960
1961/** gets columns from LP problem object; the arrays have to be large enough to store all values
1962 * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
1963 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1964 */
1966 SCIP_LPI* lpi, /**< LP interface structure */
1967 int firstcol, /**< first column to get from LP */
1968 int lastcol, /**< last column to get from LP */
1969 SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
1970 SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
1971 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1972 int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1973 int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1974 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1975 )
1976{
1977 int i;
1978 int j;
1979
1980 SCIPdebugMessage("calling SCIPlpiGetCols()\n");
1981
1982 assert(lpi != NULL);
1983 assert(lpi->spx != NULL);
1984 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
1985 assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
1986 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1987
1988 if( lb != NULL )
1989 {
1990#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1991 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
1992 {
1993 DVector lbvec(lpi->spx->numColsReal());
1994 DVector ubvec(lpi->spx->numColsReal());
1995 lpi->spx->getLowerReal(lbvec);
1996 lpi->spx->getUpperReal(ubvec);
1997 for( i = firstcol; i <= lastcol; ++i )
1998 {
1999 lb[i-firstcol] = lbvec[i];
2000 ub[i-firstcol] = ubvec[i];
2001 }
2002 }
2003 else
2004 {
2005 const Vector& lbvec = lpi->spx->lowerRealInternal();
2006 const Vector& ubvec = lpi->spx->upperRealInternal();
2007 for( i = firstcol; i <= lastcol; ++i )
2008 {
2009 lb[i-firstcol] = lbvec[i];
2010 ub[i-firstcol] = ubvec[i];
2011 }
2012 }
2013#else
2014 const Vector& lbvec = lpi->spx->lowerReal();
2015 const Vector& ubvec = lpi->spx->upperReal();
2016
2017 for( i = firstcol; i <= lastcol; ++i )
2018 {
2019 lb[i-firstcol] = lbvec[i];
2020 ub[i-firstcol] = ubvec[i];
2021 }
2022#endif
2023 }
2024
2025 if( nnonz != NULL )
2026 {
2027 *nnonz = 0;
2028 for( i = firstcol; i <= lastcol; ++i )
2029 {
2030 beg[i-firstcol] = *nnonz;
2031
2032#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2033 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2034 {
2035 DSVector cvec;
2036 lpi->spx->getColVectorReal(i, cvec);
2037 for( j = 0; j < cvec.size(); ++j )
2038 {
2039 ind[*nnonz] = cvec.index(j);
2040 val[*nnonz] = cvec.value(j);
2041 (*nnonz)++;
2042 }
2043 }
2044 else
2045 {
2046 const SVector& cvec = lpi->spx->colVectorRealInternal(i);
2047 for( j = 0; j < cvec.size(); ++j )
2048 {
2049 ind[*nnonz] = cvec.index(j);
2050 val[*nnonz] = cvec.value(j);
2051 (*nnonz)++;
2052 }
2053 }
2054#else
2055 const SVector& cvec = lpi->spx->colVectorReal(i);
2056 for( j = 0; j < cvec.size(); ++j )
2057 {
2058 ind[*nnonz] = cvec.index(j);
2059 val[*nnonz] = cvec.value(j);
2060 (*nnonz)++;
2061 }
2062#endif
2063 }
2064 }
2065
2066 return SCIP_OKAY;
2067}
2068
2069/** gets rows from LP problem object; the arrays have to be large enough to store all values.
2070 * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
2071 * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2072 */
2074 SCIP_LPI* lpi, /**< LP interface structure */
2075 int firstrow, /**< first row to get from LP */
2076 int lastrow, /**< last row to get from LP */
2077 SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
2078 SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
2079 int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2080 int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
2081 int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
2082 SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2083 )
2084{
2085 int i;
2086 int j;
2087
2088 SCIPdebugMessage("calling SCIPlpiGetRows()\n");
2089
2090 assert(lpi != NULL);
2091 assert(lpi->spx != NULL);
2092 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
2093 assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
2094 assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2095
2096 if( lhs != NULL )
2097 {
2098#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2099 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2100 {
2101 DVector lhsvec(lpi->spx->numRowsReal());
2102 DVector rhsvec(lpi->spx->numRowsReal());
2103 lpi->spx->getLhsReal(lhsvec);
2104 lpi->spx->getRhsReal(rhsvec);
2105 for( i = firstrow; i <= lastrow; ++i )
2106 {
2107 lhs[i-firstrow] = lhsvec[i];
2108 rhs[i-firstrow] = rhsvec[i];
2109 }
2110 }
2111 else
2112 {
2113 const Vector& lhsvec = lpi->spx->lhsRealInternal();
2114 const Vector& rhsvec = lpi->spx->rhsRealInternal();
2115 for( i = firstrow; i <= lastrow; ++i )
2116 {
2117 lhs[i-firstrow] = lhsvec[i];
2118 rhs[i-firstrow] = rhsvec[i];
2119 }
2120 }
2121#else
2122 const Vector& lhsvec = lpi->spx->lhsReal();
2123 const Vector& rhsvec = lpi->spx->rhsReal();
2124 for( i = firstrow; i <= lastrow; ++i )
2125 {
2126 lhs[i-firstrow] = lhsvec[i];
2127 rhs[i-firstrow] = rhsvec[i];
2128 }
2129#endif
2130 }
2131
2132 if( nnonz != NULL )
2133 {
2134 *nnonz = 0;
2135 for( i = firstrow; i <= lastrow; ++i )
2136 {
2137 beg[i-firstrow] = *nnonz;
2138
2139#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2140 if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2141 {
2142 DSVector rvec;
2143 lpi->spx->getRowVectorReal(i, rvec);
2144 for( j = 0; j < rvec.size(); ++j )
2145 {
2146 ind[*nnonz] = rvec.index(j);
2147 val[*nnonz] = rvec.value(j);
2148 (*nnonz)++;
2149 }
2150 }
2151 else
2152 {
2153 const SVector& rvec = lpi->spx->rowVectorRealInternal(i);
2154 for( j = 0; j < rvec.size(); ++j )
2155 {
2156 ind[*nnonz] = rvec.index(j);
2157 val[*nnonz] = rvec.value(j);
2158 (*nnonz)++;
2159 }
2160 }
2161#else
2162 const SVector& rvec = lpi->spx->rowVectorReal(i);
2163 for( j = 0; j < rvec.size(); ++j )
2164 {
2165 ind[*nnonz] = rvec.index(j);
2166 val[*nnonz] = rvec.value(j);
2167 (*nnonz)++;
2168 }
2169#endif
2170 }
2171 }
2172
2173 return SCIP_OKAY;
2174}
2175
2176/** gets column names */
2178 SCIP_LPI* lpi, /**< LP interface structure */
2179 int firstcol, /**< first column to get name from LP */
2180 int lastcol, /**< last column to get name from LP */
2181 char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
2182 char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
2183 int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
2184 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2185 )
2186{
2187 assert( lpi != NULL );
2188 assert( lpi->spx != NULL );
2189 assert( colnames != NULL || namestoragesize == 0 );
2190 assert( namestorage != NULL || namestoragesize == 0 );
2191 assert( namestoragesize >= 0 );
2192 assert( storageleft != NULL );
2193 assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal() );
2194
2195 SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
2196
2197// lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
2198
2199 return SCIP_OKAY;
2200}
2201
2202/** gets row names */
2204 SCIP_LPI* lpi, /**< LP interface structure */
2205 int firstrow, /**< first row to get name from LP */
2206 int lastrow, /**< last row to get name from LP */
2207 char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
2208 char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
2209 int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
2210 int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2211 )
2212{
2213 assert( lpi != NULL );
2214 assert( lpi->spx != NULL );
2215 assert( rownames != NULL || namestoragesize == 0 );
2216 assert( namestorage != NULL || namestoragesize == 0 );
2217 assert( namestoragesize >= 0 );
2218 assert( storageleft != NULL );
2219 assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal() );
2220
2221 SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
2222
2223// lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
2224
2225 return SCIP_OKAY;
2226}
2227
2228/** gets objective sense of the LP */
2230 SCIP_LPI* lpi, /**< LP interface structure */
2231 SCIP_OBJSEN* objsen /**< pointer to store objective sense */
2232 )
2233{
2234 SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
2235
2236 assert(lpi != NULL);
2237 assert(lpi->spx != NULL);
2238 assert(objsen != NULL);
2239
2240 *objsen = (lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
2241
2242 return SCIP_OKAY;
2243}
2244
2245/** gets objective coefficients from LP problem object */
2247 SCIP_LPI* lpi, /**< LP interface structure */
2248 int firstcol, /**< first column to get objective coefficient for */
2249 int lastcol, /**< last column to get objective coefficient for */
2250 SCIP_Real* vals /**< array to store objective coefficients */
2251 )
2252{
2253 int i;
2254
2255 SCIPdebugMessage("calling SCIPlpiGetObj()\n");
2256
2257 assert(lpi != NULL);
2258 assert(lpi->spx != NULL);
2259 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
2260 assert(vals != NULL);
2261
2262 for( i = firstcol; i <= lastcol; ++i )
2263 vals[i-firstcol] = lpi->spx->objReal(i);
2264
2265 return SCIP_OKAY;
2266}
2267
2268/** gets current bounds from LP problem object */
2270 SCIP_LPI* lpi, /**< LP interface structure */
2271 int firstcol, /**< first column to get objective value for */
2272 int lastcol, /**< last column to get objective value for */
2273 SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
2274 SCIP_Real* ubs /**< array to store upper bound values, or NULL */
2275 )
2276{
2277 int i;
2278
2279 SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
2280
2281 assert(lpi != NULL);
2282 assert(lpi->spx != NULL);
2283 assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
2284
2285 for( i = firstcol; i <= lastcol; ++i )
2286 {
2287 if( lbs != NULL )
2288 lbs[i-firstcol] = lpi->spx->lowerReal(i);
2289 if( ubs != NULL )
2290 ubs[i-firstcol] = lpi->spx->upperReal(i);
2291 }
2292
2293 return SCIP_OKAY;
2294}
2295
2296/** gets current row sides from LP problem object */
2298 SCIP_LPI* lpi, /**< LP interface structure */
2299 int firstrow, /**< first row to get sides for */
2300 int lastrow, /**< last row to get sides for */
2301 SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2302 SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2303 )
2304{
2305 int i;
2306
2307 SCIPdebugMessage("calling SCIPlpiGetSides()\n");
2308
2309 assert(lpi != NULL);
2310 assert(lpi->spx != NULL);
2311 assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
2312
2313 for( i = firstrow; i <= lastrow; ++i )
2314 {
2315 if( lhss != NULL )
2316 lhss[i-firstrow] = lpi->spx->lhsReal(i);
2317 if( rhss != NULL )
2318 rhss[i-firstrow] = lpi->spx->rhsReal(i);
2319 }
2320
2321 return SCIP_OKAY;
2322}
2323
2324/** gets a single coefficient */
2326 SCIP_LPI* lpi, /**< LP interface structure */
2327 int row, /**< row number of coefficient */
2328 int col, /**< column number of coefficient */
2329 SCIP_Real* val /**< pointer to store the value of the coefficient */
2330 )
2331{
2332 SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
2333
2334 assert(lpi != NULL);
2335 assert(lpi->spx != NULL);
2336 assert(0 <= col && col < lpi->spx->numColsReal());
2337 assert(0 <= row && row < lpi->spx->numRowsReal());
2338 assert(val != NULL);
2339
2340#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2341 *val = lpi->spx->coefReal(row, col);
2342#else
2343 *val = lpi->spx->colVectorReal(col)[row];
2344#endif
2345
2346 return SCIP_OKAY;
2347}
2348
2349/**@} */
2350
2351
2352
2353
2354/*
2355 * Solving Methods
2356 */
2357
2358/**@name Solving Methods */
2359/**@{ */
2360
2361/** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
2362static
2364 SCIP_LPI* lpi /**< LP interface structure */
2365 )
2366{
2367 assert( lpi != NULL );
2368 assert( lpi->spx != NULL );
2369
2370 SPxOut::Verbosity verbosity;
2371 /* store and set verbosity */
2372 verbosity = lpi->spx->spxout.getVerbosity();
2373 lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2374
2375 SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows\n", lpi->spx->numColsReal(), lpi->spx->numRowsReal());
2376
2377 invalidateSolution(lpi);
2378
2379 assert( lpi->spx->preStrongbranchingBasisFreed() );
2380
2381#ifdef SCIP_WITH_LPSCHECK
2382 lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2383#endif
2384
2385 /* delete starting basis if solving from scratch */
2386 if( lpi->spx->getFromScratch() )
2387 {
2388 try
2389 {
2390 lpi->spx->clearBasis();
2391 }
2392#ifndef NDEBUG
2393 catch(const SPxException& x)
2394 {
2395 std::string s = x.what();
2396 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2397#else
2398 catch(const SPxException&)
2399 {
2400#endif
2401 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
2402 return SCIP_LPERROR;
2403 }
2404 }
2405 assert(!lpi->spx->getFromScratch() || lpi->spx->status() == SPxSolver::NO_PROBLEM);
2406
2407 SPxSolver::Status status = lpi->spx->doSolve();
2408 SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->status(), lpi->spx->basisStatus());
2409 lpi->solved = TRUE;
2410
2411 /* restore verbosity */
2412 lpi->spx->spxout.setVerbosity(verbosity);
2413
2414 switch( status )
2415 {
2416 case SPxSolver::ABORT_TIME:
2417 case SPxSolver::ABORT_ITER:
2418 case SPxSolver::ABORT_VALUE:
2419 case SPxSolver::SINGULAR:
2420 case SPxSolver::REGULAR:
2421 case SPxSolver::UNKNOWN:
2422 case SPxSolver::OPTIMAL:
2423#if SOPLEX_APIVERSION >= 3
2424 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2425#endif
2426 case SPxSolver::UNBOUNDED:
2427 case SPxSolver::INFEASIBLE:
2428 return SCIP_OKAY;
2429 default:
2430 return SCIP_LPERROR;
2431 } /*lint !e788*/
2432}
2433
2434/** calls primal simplex to solve the LP */
2436 SCIP_LPI* lpi /**< LP interface structure */
2437 )
2438{
2439 SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2440
2441 assert(lpi != NULL);
2442 assert(lpi->spx != NULL);
2443
2444 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_PRIMAL);
2445 return spxSolve(lpi);
2446}
2447
2448/** calls dual simplex to solve the LP */
2450 SCIP_LPI* lpi /**< LP interface structure */
2451 )
2452{
2453 SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2454
2455 assert(lpi != NULL);
2456 assert(lpi->spx != NULL);
2457
2458 (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2459 return spxSolve(lpi);
2460}
2461
2462/** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
2464 SCIP_LPI* lpi, /**< LP interface structure */
2465 SCIP_Bool crossover /**< perform crossover */
2466 )
2467{ /*lint --e{715}*/
2468 assert(lpi != NULL);
2469 assert(lpi->spx != NULL);
2470
2471 SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
2472
2473 /* Since SoPlex does not support barrier we switch to DUAL */
2474 return SCIPlpiSolveDual(lpi);
2475}
2476
2477/** start strong branching - call before any strongbranching */
2479 SCIP_LPI* lpi /**< LP interface structure */
2480 )
2481{
2482 assert(lpi != NULL);
2483 assert(lpi->spx != NULL);
2484
2485 assert( lpi->spx->preStrongbranchingBasisFreed() );
2486 lpi->spx->savePreStrongbranchingBasis();
2487
2488 return SCIP_OKAY;
2489}
2490
2491/** end strong branching - call after any strongbranching */
2493 SCIP_LPI* lpi /**< LP interface structure */
2494 )
2495{
2496 assert(lpi != NULL);
2497 assert(lpi->spx != NULL);
2498
2499 assert( ! lpi->spx->preStrongbranchingBasisFreed() );
2500 lpi->spx->restorePreStrongbranchingBasis();
2501 lpi->spx->freePreStrongbranchingBasis();
2502
2503 return SCIP_OKAY;
2504}
2505
2506/** performs strong branching iterations on one arbitrary candidate */
2507static
2509 SCIP_LPI* lpi, /**< LP interface structure */
2510 int col, /**< column to apply strong branching on */
2511 SCIP_Real psol, /**< current primal solution value of column */
2512 int itlim, /**< iteration limit for strong branchings */
2513 SCIP_Real* down, /**< stores dual bound after branching column down */
2514 SCIP_Real* up, /**< stores dual bound after branching column up */
2515 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2516 * otherwise, it can only be used as an estimate value */
2517 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2518 * otherwise, it can only be used as an estimate value */
2519 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2520 )
2521{
2522 assert(lpi != NULL);
2523 assert(lpi->spx != NULL);
2524
2525 SPxSCIP* spx;
2526 SPxSolver::Status status;
2527 SCIP_Real oldlb;
2528 SCIP_Real oldub;
2529 SCIP_Real newlb;
2530 SCIP_Real newub;
2531 bool fromparentbasis;
2532 bool error;
2533 int oldItlim;
2534 SPxOut::Verbosity verbosity;
2535
2536 /* store and set verbosity */
2537 verbosity = lpi->spx->spxout.getVerbosity();
2538 lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2539
2540 SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
2541
2542 assert(lpi != NULL);
2543 assert(lpi->spx != NULL);
2544 /* assert(down != NULL);
2545 * assert(up != NULL); temporary hack for cloud branching */
2546 assert(downvalid != NULL);
2547 assert(upvalid != NULL);
2548
2549 spx = lpi->spx;
2550#ifndef STRONGBRANCH_RESTOREBASIS
2551 fromparentbasis = false;
2552#endif
2553 error = false;
2554 oldItlim = spx->intParam(SoPlex::ITERLIMIT);
2555
2556 /* get current bounds of column */
2557 oldlb = spx->lowerReal(col);
2558 oldub = spx->upperReal(col);
2559
2560 *downvalid = FALSE;
2561 *upvalid = FALSE;
2562
2563 if( iter != NULL )
2564 *iter = 0;
2565
2566 /* set the algorithm type to use dual simplex */
2567 (void) spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2568
2569 /* down branch */
2570 newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
2571 if( newub >= oldlb - 0.5 && down != NULL )
2572 {
2573 SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
2574
2575 spx->changeUpperReal(col, newub);
2576 assert(spx->lowerReal(col) <= spx->upperReal(col));
2577
2578 (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2579 do
2580 {
2581#ifndef STRONGBRANCH_RESTOREBASIS
2582 SCIP_Bool repeatstrongbranching;
2583#endif
2584#ifdef SCIP_WITH_LPSCHECK
2585 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2586#endif
2587#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2588#if SOPLEX_APIVERSION > 11
2589 status = spx->optimize(spx->getInterrupt());
2590#else
2591 status = spx->optimize();
2592#endif
2593#else
2594 status = spx->solve();
2595#endif
2596 SCIPdebugMessage(" --> Terminate with status %d\n", status);
2597 switch( status )
2598 {
2599 case SPxSolver::OPTIMAL:
2600 *down = spx->objValueReal();
2601 *downvalid = TRUE;
2602 SCIPdebugMessage(" --> Terminate with value %f\n", *down);
2603 break;
2604 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2605 case SPxSolver::ABORT_ITER:
2606 case SPxSolver::ABORT_CYCLING:
2607#if SOPLEX_APIVERSION >= 3
2608 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2609#endif
2610 *down = spx->objValueReal();
2611 break;
2612 case SPxSolver::ABORT_VALUE:
2613 case SPxSolver::INFEASIBLE:
2614 *down = spx->getObjLimit();
2615 *downvalid = TRUE;
2616 break;
2617 default:
2618 error = true;
2619 break;
2620 } /*lint !e788*/
2621 if( iter != NULL )
2622 (*iter) += spx->numIterations();
2623
2624#ifdef STRONGBRANCH_RESTOREBASIS
2625 /* we restore the pre-strong-branching basis by default (and don't solve again) */
2626 assert( ! spx->preStrongbranchingBasisFreed() );
2627 spx->restorePreStrongbranchingBasis();
2628 fromparentbasis = false;
2629#else
2630 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2631 * pre-strong-branching basis and try again with reduced iteration limit */
2632#if SOPLEX_APIVERSION >= 3
2633 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
2634 || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
2635#else
2636 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
2637 && !fromparentbasis && spx->numIterations() < itlim);
2638#endif
2640 {
2641 SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n",
2642 itlim - spx->numIterations());
2643 spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2644 spx->restorePreStrongbranchingBasis();
2645 fromparentbasis = true;
2646 error = false;
2647 }
2648 /* otherwise don't solve again */
2649 else
2650 fromparentbasis = false;
2651#endif
2652 }
2653 while( fromparentbasis );
2654
2655 spx->changeUpperReal(col, oldub);
2656 assert(spx->lowerReal(col) <= spx->upperReal(col));
2657 }
2658 else if( down != NULL )
2659 {
2660 *down = spx->getObjLimit();
2661 *downvalid = TRUE;
2662 }
2663 else
2664 *downvalid = TRUE;
2665
2666 /* up branch */
2667 if( !error )
2668 {
2669 newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
2670 if( newlb <= oldub + 0.5 && up != NULL )
2671 {
2672 SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
2673
2674 spx->changeLowerReal(col, newlb);
2675 assert(spx->lowerReal(col) <= spx->upperReal(col));
2676
2677 (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2678 do
2679 {
2680#ifndef STRONGBRANCH_RESTOREBASIS
2681 SCIP_Bool repeatstrongbranching;
2682#endif
2683#ifdef SCIP_WITH_LPSCHECK
2684 spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2685#endif
2686#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2687#if SOPLEX_APIVERSION > 11
2688 status = spx->optimize(spx->getInterrupt());
2689#else
2690 status = spx->optimize();
2691#endif
2692#else
2693 status = spx->solve();
2694#endif
2695 SCIPdebugMessage(" --> Terminate with status %d\n", status);
2696 switch( status )
2697 {
2698 case SPxSolver::OPTIMAL:
2699 *up = spx->objValueReal();
2700 *upvalid = TRUE;
2701 SCIPdebugMessage(" --> Terminate with value %f\n", spx->objValueReal());
2702 break;
2703 case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2704 case SPxSolver::ABORT_ITER:
2705 case SPxSolver::ABORT_CYCLING:
2706#if SOPLEX_APIVERSION >= 3
2707 case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2708#endif
2709 *up = spx->objValueReal();
2710 break;
2711 case SPxSolver::ABORT_VALUE:
2712 case SPxSolver::INFEASIBLE:
2713 *up = spx->getObjLimit();
2714 *upvalid = TRUE;
2715 break;
2716 default:
2717 error = true;
2718 break;
2719 } /*lint !e788*/
2720 if( iter != NULL )
2721 (*iter) += spx->numIterations();
2722
2723#ifdef STRONGBRANCH_RESTOREBASIS
2724 /* we restore the pre-strong-branching basis by default (and don't solve again) */
2725 assert( ! spx->preStrongbranchingBasisFreed() );
2726 spx->restorePreStrongbranchingBasis();
2727 fromparentbasis = false;
2728#else
2729 /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2730 * pre-strong-branching basis and try again with reduced iteration limit */
2731#if SOPLEX_APIVERSION >= 3
2732 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
2733 || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
2734#else
2735 repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
2736 && !fromparentbasis && spx->numIterations() < itlim);
2737#endif
2739 {
2740 SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->numIterations());
2741 spx->restorePreStrongbranchingBasis();
2742 spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2743 error = false;
2744 fromparentbasis = true;
2745 }
2746 /* otherwise don't solve again */
2747 else
2748 fromparentbasis = false;
2749#endif
2750 }
2751 while( fromparentbasis );
2752
2753 spx->changeLowerReal(col, oldlb);
2754 assert(spx->lowerReal(col) <= spx->upperReal(col));
2755 }
2756 else if( up != NULL )
2757 {
2758 *up = spx->getObjLimit();
2759 *upvalid = TRUE;
2760 }
2761 else
2762 *upvalid = TRUE;
2763 }
2764
2765 /* reset old iteration limit */
2766 (void) spx->setIntParam(SoPlex::ITERLIMIT, oldItlim);
2767
2768 /* restore verbosity */
2769 lpi->spx->spxout.setVerbosity(verbosity);
2770
2771 if( error )
2772 {
2773 SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status)); /*lint !e644*/
2774 return SCIP_LPERROR;
2775 }
2776
2777 return SCIP_OKAY;
2778}
2779
2780/** performs strong branching iterations on one @b fractional candidate */
2782 SCIP_LPI* lpi, /**< LP interface structure */
2783 int col, /**< column to apply strong branching on */
2784 SCIP_Real psol, /**< fractional current primal solution value of column */
2785 int itlim, /**< iteration limit for strong branchings */
2786 SCIP_Real* down, /**< stores dual bound after branching column down */
2787 SCIP_Real* up, /**< stores dual bound after branching column up */
2788 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2789 * otherwise, it can only be used as an estimate value */
2790 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2791 * otherwise, it can only be used as an estimate value */
2792 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2793 )
2794{
2795 SCIP_RETCODE retcode;
2796
2797 /* pass call on to lpiStrongbranch() */
2798 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2799
2800 /* pass SCIP_LPERROR to SCIP without a back trace */
2801 if( retcode == SCIP_LPERROR )
2802 return SCIP_LPERROR;
2803
2804 /* evaluate retcode */
2805 SCIP_CALL( retcode );
2806
2807 return SCIP_OKAY;
2808}
2809
2810/** performs strong branching iterations on given @b fractional candidates */
2812 SCIP_LPI* lpi, /**< LP interface structure */
2813 int* cols, /**< columns to apply strong branching on */
2814 int ncols, /**< number of columns */
2815 SCIP_Real* psols, /**< fractional current primal solution values of columns */
2816 int itlim, /**< iteration limit for strong branchings */
2817 SCIP_Real* down, /**< stores dual bounds after branching columns down */
2818 SCIP_Real* up, /**< stores dual bounds after branching columns up */
2819 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2820 * otherwise, they can only be used as an estimate values */
2821 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2822 * otherwise, they can only be used as an estimate values */
2823 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2824 )
2825{
2826 SCIP_RETCODE retcode;
2827
2828 assert( cols != NULL );
2829 assert( psols != NULL );
2830 assert( down != NULL );
2831 assert( up != NULL );
2832 assert( downvalid != NULL );
2833 assert( upvalid != NULL );
2834 assert( down != NULL );
2835
2836 if ( iter != NULL )
2837 *iter = 0;
2838
2839 for (int j = 0; j < ncols; ++j)
2840 {
2841 /* pass call on to lpiStrongbranch() */
2842 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2843
2844 /* pass SCIP_LPERROR to SCIP without a back trace */
2845 if( retcode == SCIP_LPERROR )
2846 return SCIP_LPERROR;
2847
2848 /* evaluate retcode */
2849 SCIP_CALL( retcode );
2850 }
2851 return SCIP_OKAY;
2852}
2853
2854/** performs strong branching iterations on one candidate with @b integral value */
2856 SCIP_LPI* lpi, /**< LP interface structure */
2857 int col, /**< column to apply strong branching on */
2858 SCIP_Real psol, /**< current integral primal solution value of column */
2859 int itlim, /**< iteration limit for strong branchings */
2860 SCIP_Real* down, /**< stores dual bound after branching column down */
2861 SCIP_Real* up, /**< stores dual bound after branching column up */
2862 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2863 * otherwise, it can only be used as an estimate value */
2864 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2865 * otherwise, it can only be used as an estimate value */
2866 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2867 )
2868{
2869 SCIP_RETCODE retcode;
2870
2871 /* pass call on to lpiStrongbranch() */
2872 retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2873
2874 /* pass SCIP_LPERROR to SCIP without a back trace */
2875 if( retcode == SCIP_LPERROR )
2876 return SCIP_LPERROR;
2877
2878 /* evaluate retcode */
2879 SCIP_CALL( retcode );
2880
2881 return SCIP_OKAY;
2882}
2883
2884/** performs strong branching iterations on given candidates with @b integral values */
2886 SCIP_LPI* lpi, /**< LP interface structure */
2887 int* cols, /**< columns to apply strong branching on */
2888 int ncols, /**< number of columns */
2889 SCIP_Real* psols, /**< current integral primal solution values of columns */
2890 int itlim, /**< iteration limit for strong branchings */
2891 SCIP_Real* down, /**< stores dual bounds after branching columns down */
2892 SCIP_Real* up, /**< stores dual bounds after branching columns up */
2893 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2894 * otherwise, they can only be used as an estimate values */
2895 SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2896 * otherwise, they can only be used as an estimate values */
2897 int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2898 )
2899{
2900 SCIP_RETCODE retcode;
2901
2902 assert( cols != NULL );
2903 assert( psols != NULL );
2904 assert( down != NULL );
2905 assert( up != NULL );
2906 assert( downvalid != NULL );
2907 assert( upvalid != NULL );
2908 assert( down != NULL );
2909
2910 if ( iter != NULL )
2911 *iter = 0;
2912
2913 for (int j = 0; j < ncols; ++j)
2914 {
2915 /* pass call on to lpiStrongbranch() */
2916 retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2917
2918 /* pass SCIP_LPERROR to SCIP without a back trace */
2919 if( retcode == SCIP_LPERROR )
2920 return SCIP_LPERROR;
2921
2922 /* evaluate retcode */
2923 SCIP_CALL( retcode );
2924 }
2925
2926 return SCIP_OKAY;
2927}
2928/**@} */
2929
2930
2931
2932
2933/*
2934 * Solution Information Methods
2935 */
2936
2937/**@name Solution Information Methods */
2938/**@{ */
2939
2940/** returns whether a solve method was called after the last modification of the LP */
2942 SCIP_LPI* lpi /**< LP interface structure */
2943 )
2944{
2945 assert(lpi != NULL);
2946
2947 return lpi->solved;
2948}
2949
2950/** gets information about primal and dual feasibility of the current LP solution
2951 *
2952 * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
2953 * returns true. If the LP is changed, this information might be invalidated.
2954 *
2955 * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
2956 * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
2957 * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
2958 * the problem might actually be feasible).
2959 */
2961 SCIP_LPI* lpi, /**< LP interface structure */
2962 SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
2963 SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
2964 )
2965{
2966 SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
2967
2968 assert(lpi != NULL);
2969 assert(primalfeasible != NULL);
2970 assert(dualfeasible != NULL);
2971
2972 *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
2973 *dualfeasible = SCIPlpiIsDualFeasible(lpi);
2974
2975 return SCIP_OKAY;
2976}
2977
2978/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
2979 * this does not necessarily mean, that the solver knows and can return the primal ray
2980 */
2982 SCIP_LPI* lpi /**< LP interface structure */
2983 )
2984{
2985 SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
2986
2987 assert(lpi != NULL);
2988 assert(lpi->spx != NULL);
2989
2990 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2991}
2992
2993/** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
2994 * and the solver knows and can return the primal ray
2995 */
2997 SCIP_LPI* lpi /**< LP interface structure */
2998 )
2999{
3000 SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
3001
3002 assert(lpi != NULL);
3003 assert(lpi->spx != NULL);
3004
3005 return lpi->spx->hasPrimalRay();
3006}
3007
3008/** returns TRUE iff LP is proven to be primal unbounded */
3010 SCIP_LPI* lpi /**< LP interface structure */
3011 )
3012{
3013 SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
3014
3015 assert(lpi != NULL);
3016 assert(lpi->spx != NULL);
3017
3018 assert(lpi->spx->status() != SPxSolver::UNBOUNDED || lpi->spx->basisStatus() == SPxBasis::UNBOUNDED);
3019
3020 /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
3021 * feasible point; hence we have to check the perturbation
3022 */
3023 return lpi->spx->status() == SPxSolver::UNBOUNDED;
3024}
3025
3026/** returns TRUE iff LP is proven to be primal infeasible */
3028 SCIP_LPI* lpi /**< LP interface structure */
3029 )
3030{
3031 SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
3032
3033 assert(lpi != NULL);
3034 assert(lpi->spx != NULL);
3035
3036 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
3037}
3038
3039/** returns TRUE iff LP is proven to be primal feasible */
3041 SCIP_LPI* lpi /**< LP interface structure */
3042 )
3043{
3044 SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
3045
3046 assert(lpi != NULL);
3047 assert(lpi->spx != NULL);
3048
3049 return lpi->spx->basisStatus() == SPxBasis::OPTIMAL || lpi->spx->basisStatus() == SPxBasis::PRIMAL;
3050}
3051
3052/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3053 * this does not necessarily mean, that the solver knows and can return the dual ray
3054 */
3056 SCIP_LPI* lpi /**< LP interface structure */
3057 )
3058{
3059 SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
3060
3061 assert(lpi != NULL);
3062 assert(lpi->spx != NULL);
3063
3064 return (lpi->spx->status() == SPxSolver::INFEASIBLE);
3065}
3066
3067/** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3068 * and the solver knows and can return the dual ray
3069 */
3071 SCIP_LPI* lpi /**< LP interface structure */
3072 )
3073{
3074 SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
3075
3076 assert(lpi != NULL);
3077 assert(lpi->spx != NULL);
3078
3079 return lpi->spx->hasDualFarkas();
3080}
3081
3082/** returns TRUE iff LP is dual unbounded */
3084 SCIP_LPI* lpi /**< LP interface structure */
3085 )
3086{
3087 SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
3088
3089 assert(lpi != NULL);
3090 assert(lpi->spx != NULL);
3091
3092 return lpi->spx->status() == SPxSolver::INFEASIBLE && lpi->spx->basisStatus() == SPxBasis::DUAL;
3093}
3094
3095/** returns TRUE iff LP is dual infeasible */
3097 SCIP_LPI* lpi /**< LP interface structure */
3098 )
3099{
3100 SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
3101
3102 assert(lpi != NULL);
3103 assert(lpi->spx != NULL);
3104
3105 return (lpi->spx->status() == SPxSolver::UNBOUNDED);
3106}
3107
3108/** returns TRUE iff LP is proven to be dual feasible */
3110 SCIP_LPI* lpi /**< LP interface structure */
3111 )
3112{
3113 SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
3114
3115 assert(lpi != NULL);
3116 assert(lpi->spx != NULL);
3117
3118 return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL) || lpi->spx->basisStatus() == SPxBasis::DUAL;
3119}
3120
3121/** returns TRUE iff LP was solved to optimality */
3123 SCIP_LPI* lpi /**< LP interface structure */
3124 )
3125{
3126 SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
3127
3128 assert(lpi != NULL);
3129 assert(lpi->spx != NULL);
3130 assert((lpi->spx->basisStatus() == SPxBasis::OPTIMAL)
3132
3133 return (lpi->spx->status() == SPxSolver::OPTIMAL);
3134}
3135
3136/** returns TRUE iff current LP solution is stable
3137 *
3138 * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3139 * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3140 * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3141 * SCIPlpiIsStable() should return false.
3142 */
3144 SCIP_LPI* lpi /**< LP interface structure */
3145 )
3146{
3147 SCIPdebugMessage("calling SCIPlpiIsStable()\n");
3148
3149 assert(lpi != NULL);
3150 assert(lpi->spx != NULL);
3151
3152 if( lpi->spx->status() == SPxSolver::ERROR || lpi->spx->status() == SPxSolver::SINGULAR )
3153 return FALSE;
3154#if SOPLEX_APIVERSION >= 3
3155 if( lpi->spx->status() == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS )
3156 return FALSE;
3157#endif
3158 /* only if we have a regular basis and the condition limit is set, we compute the condition number of the basis;
3159 * everything above the specified threshold is then counted as instable
3160 */
3161 if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
3162 {
3163 SCIP_RETCODE retcode;
3164 SCIP_Real kappa;
3165
3167 if( retcode != SCIP_OKAY )
3168 {
3169 SCIPABORT();
3170 }
3171 assert(kappa != SCIP_INVALID); /*lint !e777*/
3172
3173 if( kappa > lpi->conditionlimit )
3174 return FALSE;
3175 }
3176 /* if an objective limit is set and SoPlex claims that it is exceeded, we should check that this is indeed the case;
3177 * if not this points at numerical instability; note that this aligns with an assert in lp.c */
3178 if( SCIPlpiIsObjlimExc(lpi) )
3179 {
3180 SCIP_Real objlimit = lpi->spx->getObjLimit();
3181 SCIP_Real objvalue = lpi->spx->objValueReal();
3182
3183 if( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE )
3184 {
3185 objlimit *= -1.0;
3186 objvalue *= -1.0;
3187 }
3188 if( !SCIPlpiIsInfinity(lpi, objlimit) && LTrel(objvalue, objlimit, 2*lpi->spx->opttol()) )
3189 return FALSE;
3190 }
3191 return TRUE;
3192}
3193
3194/** returns TRUE iff the objective limit was reached */
3196 SCIP_LPI* lpi /**< LP interface structure */
3197 )
3198{
3199 SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3200
3201 assert(lpi != NULL);
3202 assert(lpi->spx != NULL);
3203
3204 return (lpi->spx->status() == SPxSolver::ABORT_VALUE);
3205}
3206
3207/** returns TRUE iff the iteration limit was reached */
3209 SCIP_LPI* lpi /**< LP interface structure */
3210 )
3211{
3212 SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3213
3214 assert(lpi != NULL);
3215 assert(lpi->spx != NULL);
3216
3217 return (lpi->spx->status() == SPxSolver::ABORT_ITER);
3218}
3219
3220/** returns TRUE iff the time limit was reached */
3222 SCIP_LPI* lpi /**< LP interface structure */
3223 )
3224{
3225 SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3226
3227 assert(lpi != NULL);
3228 assert(lpi->spx != NULL);
3229
3230 return (lpi->spx->status() == SPxSolver::ABORT_TIME);
3231}
3232
3233/** returns the internal solution status of the solver */
3235 SCIP_LPI* lpi /**< LP interface structure */
3236 )
3237{
3238 SCIPdebugMessage("calling SCIPlpiGetInternalStatus()\n");
3239
3240 assert(lpi != NULL);
3241 assert(lpi->spx != NULL);
3242
3243 return static_cast<int>(lpi->spx->status());
3244}
3245
3246/** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3248 SCIP_LPI* lpi, /**< LP interface structure */
3249 SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3250 )
3251{ /*lint --e{715}*/
3252 SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3253
3254 assert(lpi != NULL);
3255 assert(lpi->spx != NULL);
3256 assert(success != NULL);
3257
3258#if SOPLEX_APIVERSION >= 4
3259 *success = lpi->spx->ignoreUnscaledViolations();
3260#else
3261 *success = FALSE;
3262#endif
3263
3264 return SCIP_OKAY;
3265}
3266
3267/** gets objective value of solution */
3269 SCIP_LPI* lpi, /**< LP interface structure */
3270 SCIP_Real* objval /**< stores the objective value */
3271 )
3272{
3273 SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3274
3275 assert(lpi != NULL);
3276 assert(lpi->spx != NULL);
3277 assert(objval != NULL);
3278
3279 *objval = lpi->spx->objValueReal();
3280
3281 return SCIP_OKAY;
3282}
3283
3284/** gets primal and dual solution vectors for feasible LPs
3285 *
3286 * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3287 * SCIPlpiIsOptimal() returns true.
3288 */
3290 SCIP_LPI* lpi, /**< LP interface structure */
3291 SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3292 SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3293 SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3294 SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3295 SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3296 )
3297{
3298 SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3299
3300 assert(lpi != NULL);
3301 assert(lpi->spx != NULL);
3302
3303 if( objval != NULL )
3304 *objval = lpi->spx->objValueReal();
3305
3306 try
3307 {
3308 if( primsol != NULL )
3309 {
3310#if SOPLEX_APIVERSION > 10
3311 (void)lpi->spx->getPrimalReal(primsol, lpi->spx->numColsReal());
3312#else
3313 Vector tmp(lpi->spx->numColsReal(), primsol);
3314 (void)lpi->spx->getPrimalReal(tmp);
3315#endif
3316 }
3317 if( dualsol != NULL )
3318 {
3319#if SOPLEX_APIVERSION > 10
3320 (void)lpi->spx->getDualReal(dualsol, lpi->spx->numRowsReal());
3321#else
3322 Vector tmp(lpi->spx->numRowsReal(), dualsol);
3323 (void)lpi->spx->getDualReal(tmp);
3324#endif
3325 }
3326 if( activity != NULL )
3327 {
3328#if SOPLEX_APIVERSION > 10
3329 (void)lpi->spx->getSlacksReal(activity, lpi->spx->numRowsReal()); /* in SoPlex, the activities are called "slacks" */
3330#else
3331 Vector tmp(lpi->spx->numRowsReal(), activity);
3332 (void)lpi->spx->getSlacksReal(tmp); /* in SoPlex, the activities are called "slacks" */
3333#endif
3334 }
3335 if( redcost != NULL )
3336 {
3337#if SOPLEX_APIVERSION > 10
3338 (void)lpi->spx->getRedCostReal(redcost, lpi->spx->numColsReal());
3339#else
3340 Vector tmp(lpi->spx->numColsReal(), redcost);
3341 (void)lpi->spx->getRedCostReal(tmp);
3342#endif
3343 }
3344 }
3345#ifndef NDEBUG
3346 catch( const SPxException& x )
3347 {
3348 std::string s = x.what();
3349 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3350#else
3351 catch( const SPxException& )
3352 {
3353#endif
3354 return SCIP_LPERROR;
3355 }
3356
3357 return SCIP_OKAY;
3358}
3359
3360/** gets primal ray for unbounded LPs */
3362 SCIP_LPI* lpi, /**< LP interface structure */
3363 SCIP_Real* ray /**< primal ray */
3364 )
3365{ /*lint --e{715}*/
3366 SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3367
3368 assert(lpi != NULL);
3369 assert(lpi->spx != NULL);
3370 assert(lpi->spx->hasPrimalRay());
3371 assert(ray != NULL);
3372
3373 try
3374 {
3375#if SOPLEX_APIVERSION > 10
3376 (void)lpi->spx->getPrimalRayReal(ray, lpi->spx->numColsReal());
3377#else
3378 Vector tmp(lpi->spx->numColsReal(), ray);
3379 (void)lpi->spx->getPrimalRayReal(tmp);
3380#endif
3381 }
3382#ifndef NDEBUG
3383 catch( const SPxException& x )
3384 {
3385 std::string s = x.what();
3386 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3387#else
3388 catch( const SPxException& )
3389 {
3390#endif
3391 return SCIP_LPERROR;
3392 }
3393
3394 return SCIP_OKAY;
3395}
3396
3397/** gets dual farkas proof for infeasibility */
3399 SCIP_LPI* lpi, /**< LP interface structure */
3400 SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3401 )
3402{
3403 SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3404
3405 assert(lpi != NULL);
3406 assert(lpi->spx != NULL);
3407 assert(lpi->spx->hasDualFarkas());
3408 assert(dualfarkas != NULL);
3409
3410 try
3411 {
3412#if SOPLEX_APIVERSION > 10
3413 (void)lpi->spx->getDualFarkasReal(dualfarkas, lpi->spx->numRowsReal());
3414#else
3415 Vector tmp(lpi->spx->numRowsReal(), dualfarkas);
3416 (void)lpi->spx->getDualFarkasReal(tmp);
3417#endif
3418 }
3419#ifndef NDEBUG
3420 catch( const SPxException& x )
3421 {
3422 std::string s = x.what();
3423 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3424#else
3425 catch( const SPxException& )
3426 {
3427#endif
3428 return SCIP_LPERROR;
3429 }
3430
3431 return SCIP_OKAY;
3432}
3433
3434/** gets the number of LP iterations of the last solve call */
3436 SCIP_LPI* lpi, /**< LP interface structure */
3437 int* iterations /**< pointer to store the number of iterations of the last solve call */
3438 )
3439{
3440 SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3441
3442 assert(lpi != NULL);
3443 assert(lpi->spx != NULL);
3444 assert(iterations != NULL);
3445
3446 *iterations = lpi->spx->numIterations();
3447
3448 return SCIP_OKAY;
3449}
3450
3451/** gets information about the quality of an LP solution
3452 *
3453 * Such information is usually only available, if also a (maybe not optimal) solution is available.
3454 * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
3455 */
3457 SCIP_LPI* lpi, /**< LP interface structure */
3458 SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3459 SCIP_Real* quality /**< pointer to store quality number */
3460 )
3461{
3462 SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3463
3464 assert(lpi != NULL);
3465 assert(quality != NULL);
3466
3467 bool success;
3468
3469 SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3470
3471 switch( qualityindicator )
3472 {
3474 success = lpi->spx->getEstimatedCondition(*quality);
3475 break;
3476
3478 success = lpi->spx->getExactCondition(*quality);
3479 break;
3480
3481 default:
3482 SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3483 return SCIP_INVALIDDATA;
3484 }
3485
3486 if( !success )
3487 {
3488 SCIPdebugMessage("problem computing condition number\n");
3490 }
3491
3492 return SCIP_OKAY;
3493}
3494
3495/**@} */
3496
3497
3498
3499
3500/*
3501 * LP Basis Methods
3502 */
3503
3504/**@name LP Basis Methods */
3505/**@{ */
3506
3507
3508/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
3510 SCIP_LPI* lpi, /**< LP interface structure */
3511 int* cstat, /**< array to store column basis status, or NULL */
3512 int* rstat /**< array to store row basis status, or NULL */
3513 )
3514{
3515 int i;
3516
3517 SCIPdebugMessage("calling SCIPlpiGetBase()\n");
3518
3519 assert(lpi != NULL);
3520 assert(lpi->spx != NULL);
3521
3522 assert( lpi->spx->preStrongbranchingBasisFreed() );
3523
3524 if( rstat != NULL )
3525 {
3526 for( i = 0; i < lpi->spx->numRowsReal(); ++i )
3527 {
3528 switch( lpi->spx->basisRowStatus(i) )
3529 {
3530 case SPxSolver::BASIC:
3531 rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3532 break;
3533 case SPxSolver::FIXED:
3534 case SPxSolver::ON_LOWER:
3535 rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3536 break;
3537 case SPxSolver::ON_UPPER:
3538 rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3539 break;
3540 case SPxSolver::ZERO:
3541 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3542 return SCIP_LPERROR;
3543 case SPxSolver::UNDEFINED:
3544 default:
3545 SCIPerrorMessage("invalid basis status\n");
3546 SCIPABORT();
3547 return SCIP_INVALIDDATA; /*lint !e527*/
3548 }
3549 }
3550 }
3551
3552 if( cstat != NULL )
3553 {
3554 for( i = 0; i < lpi->spx->numColsReal(); ++i )
3555 {
3556// SCIP_Real val = 0.0;
3557 switch( lpi->spx->basisColStatus(i) )
3558 {
3559 case SPxSolver::BASIC:
3560 cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3561 break;
3562 case SPxSolver::FIXED:
3563 /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
3564 * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
3565 * this case there is no problem at all. If the basis is saved and/or used in some other
3566 * solver, it usually is very cheap to perform the pivots necessary to get an optimal
3567 * basis.
3568 * @todo implement getRedCostEst()
3569 * */
3570// SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
3571// if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
3572// cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3573// else
3574 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3575 break;
3576 case SPxSolver::ON_LOWER:
3577 cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3578 break;
3579 case SPxSolver::ON_UPPER:
3580 cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3581 break;
3582 case SPxSolver::ZERO:
3583 cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3584 break;
3585 case SPxSolver::UNDEFINED:
3586 default:
3587 SCIPerrorMessage("invalid basis status\n");
3588 SCIPABORT();
3589 return SCIP_INVALIDDATA; /*lint !e527*/
3590 }
3591 }
3592 }
3593
3594 return SCIP_OKAY;
3595}
3596
3597/** sets current basis status for columns and rows */
3599 SCIP_LPI* lpi, /**< LP interface structure */
3600 const int* cstat, /**< array with column basis status */
3601 const int* rstat /**< array with row basis status */
3602 )
3603{
3604 int i;
3605 int ncols;
3606 int nrows;
3607
3608 SCIPdebugMessage("calling SCIPlpiSetBase()\n");
3609
3610 assert(lpi != NULL);
3611 assert(lpi->spx != NULL);
3612
3613 SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
3614 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
3615
3616 assert(cstat != NULL || ncols == 0);
3617 assert(rstat != NULL || nrows == 0);
3618
3619 assert( lpi->spx->preStrongbranchingBasisFreed() );
3620 invalidateSolution(lpi);
3621
3622 DataArray<SPxSolver::VarStatus>& _colstat = lpi->spx->colStat();
3623 DataArray<SPxSolver::VarStatus>& _rowstat = lpi->spx->rowStat();
3624
3625 _colstat.reSize(ncols);
3626 _rowstat.reSize(nrows);
3627
3628 for( i = 0; i < nrows; ++i )
3629 {
3630 switch( rstat[i] ) /*lint !e613*/
3631 {
3633 _rowstat[i] = SPxSolver::ON_LOWER;
3634 break;
3636 _rowstat[i] = SPxSolver::BASIC;
3637 break;
3639 _rowstat[i] = SPxSolver::ON_UPPER;
3640 break;
3641 case SCIP_BASESTAT_ZERO:
3642 SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3643 return SCIP_LPERROR; /*lint !e429*/
3644 default:
3645 SCIPerrorMessage("invalid basis status\n");
3646 SCIPABORT();
3647 return SCIP_INVALIDDATA; /*lint !e527*/
3648 }
3649 }
3650
3651 for( i = 0; i < ncols; ++i )
3652 {
3653 switch( cstat[i] ) /*lint !e613*/
3654 {
3656 _colstat[i] = SPxSolver::ON_LOWER;
3657 break;
3659 _colstat[i] = SPxSolver::BASIC;
3660 break;
3662 _colstat[i] = SPxSolver::ON_UPPER;
3663 break;
3664 case SCIP_BASESTAT_ZERO:
3665 _colstat[i] = SPxSolver::ZERO;
3666 break;
3667 default:
3668 SCIPerrorMessage("invalid basis status\n");
3669 SCIPABORT();
3670 return SCIP_INVALIDDATA; /*lint !e527*/
3671 }
3672 }
3673
3674 SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(_rowstat.get_ptr(), _colstat.get_ptr()) );
3675 lpi->spx->freePreStrongbranchingBasis();
3676
3677 return SCIP_OKAY;
3678}
3679
3680/** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
3682 SCIP_LPI* lpi, /**< LP interface structure */
3683 int* bind /**< pointer to store basis indices ready to keep number of rows entries */
3684 )
3685{
3686 SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
3687
3688 assert(lpi != NULL);
3689 assert(lpi->spx != NULL);
3690 assert(bind != NULL);
3691
3692 assert(lpi->spx->preStrongbranchingBasisFreed());
3693
3694 lpi->spx->getBasisInd(bind);
3695
3696 return SCIP_OKAY;
3697}
3698
3699
3700/** get row of inverse basis matrix B^-1
3701 *
3702 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3703 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3704 * see also the explanation in lpi.h.
3705 */
3707 SCIP_LPI* lpi, /**< LP interface structure */
3708 int r, /**< row number */
3709 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
3710 int* inds, /**< array to store the non-zero indices, or NULL */
3711 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3712 * (-1: if we do not store sparsity information) */
3713 )
3714{
3715 SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
3716
3717 assert(lpi != NULL);
3718 assert(lpi->spx != NULL);
3719 assert(lpi->spx->preStrongbranchingBasisFreed());
3720 assert(coef != NULL);
3721
3722 assert(r >= 0);
3723 assert(r < lpi->spx->numRowsReal());
3724
3725 if( ! lpi->spx->getBasisInverseRowReal(r, coef, inds, ninds) )
3726 return SCIP_LPERROR;
3727
3728 return SCIP_OKAY;
3729}
3730
3731/** get column of inverse basis matrix B^-1
3732 *
3733 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3734 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3735 * see also the explanation in lpi.h.
3736 */
3738 SCIP_LPI* lpi, /**< LP interface structure */
3739 int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
3740 * you have to call SCIPlpiGetBasisInd() to get the array which links the
3741 * B^-1 column numbers to the row and column numbers of the LP!
3742 * c must be between 0 and nrows-1, since the basis has the size
3743 * nrows * nrows */
3744 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
3745 int* inds, /**< array to store the non-zero indices, or NULL */
3746 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3747 * (-1: if we do not store sparsity information) */
3748 )
3749{
3750 SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
3751
3752 assert( lpi != NULL );
3753 assert( lpi->spx != NULL );
3754 assert( lpi->spx->preStrongbranchingBasisFreed() );
3755 assert(coef != NULL);
3756
3757 if( ! lpi->spx->getBasisInverseColReal(c, coef, inds, ninds) )
3758 return SCIP_LPERROR;
3759
3760 return SCIP_OKAY;
3761}
3762
3763/** get row of inverse basis matrix times constraint matrix B^-1 * A
3764 *
3765 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3766 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3767 * see also the explanation in lpi.h.
3768 */
3770 SCIP_LPI* lpi, /**< LP interface structure */
3771 int r, /**< row number */
3772 const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
3773 SCIP_Real* coef, /**< vector to return coefficients of the row */
3774 int* inds, /**< array to store the non-zero indices, or NULL */
3775 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3776 * (-1: if we do not store sparsity information) */
3777 )
3778{
3779 SCIP_Real* buf;
3780 SCIP_Real* binv;
3781 int nrows;
3782 int ncols;
3783 int c;
3784
3785 SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
3786
3787 assert(lpi != NULL);
3788 assert(lpi->spx != NULL);
3789 assert( lpi->spx->preStrongbranchingBasisFreed() );
3790 assert(coef != NULL);
3791
3792 nrows = lpi->spx->numRowsReal();
3793 ncols = lpi->spx->numColsReal();
3794 buf = NULL;
3795
3796 /* get (or calculate) the row in B^-1 */
3797 if( binvrow == NULL )
3798 {
3799 SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
3800 SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
3801 binv = buf;
3802 }
3803 else
3804 binv = const_cast<SCIP_Real*>(binvrow);
3805
3806 assert(binv != NULL);
3807
3808 /* mark sparsity pattern as invalid */
3809 if( ninds != NULL )
3810 *ninds = -1;
3811
3812 // @todo exploit sparsity in binv by looping over nrows
3813 /* calculate the scalar product of the row in B^-1 and A */
3814 Vector binvvec(nrows, binv);
3815
3816#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3817 /* temporary unscaled column of A */
3818 DSVector acol;
3819#endif
3820
3821 for( c = 0; c < ncols; ++c )
3822 {
3823#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3824 lpi->spx->getColVectorReal(c, acol);
3825 coef[c] = binvvec * acol; /* scalar product */ /*lint !e1702*/
3826#else
3827 coef[c] = binvvec * lpi->spx->colVectorReal(c); /* scalar product */ /*lint !e1702*/
3828#endif
3829 }
3830
3831 /* free memory if it was temporarily allocated */
3833
3834 return SCIP_OKAY;
3835}
3836
3837/** get column of inverse basis matrix times constraint matrix B^-1 * A
3838 *
3839 * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3840 * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3841 * see also the explanation in lpi.h.
3842 */
3844 SCIP_LPI* lpi, /**< LP interface structure */
3845 int c, /**< column number */
3846 SCIP_Real* coef, /**< vector to return coefficients of the column */
3847 int* inds, /**< array to store the non-zero indices, or NULL */
3848 int* ninds /**< pointer to store the number of non-zero indices, or NULL
3849 * (-1: if we do not store sparsity information) */
3850 )
3851{ /*lint --e{715}*/
3852 /* create a new uninitialized full vector */
3853 DVector col(lpi->spx->numRowsReal());
3854
3855#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3856 /* temporary sparse vector used for unscaling (memory is automatically enlarged) */
3858#endif
3859
3860 SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
3861
3862 assert( lpi != NULL );
3863 assert( lpi->spx != NULL );
3864 assert( lpi->spx->preStrongbranchingBasisFreed() );
3865 assert(coef != NULL);
3866
3867 /* extract column c of A */
3868 assert(c >= 0);
3869 assert(c < lpi->spx->numColsReal());
3870
3871 /* @todo implement this with sparse vectors */
3872 /* mark sparsity pattern as invalid */
3873 if( ninds != NULL )
3874 *ninds = -1;
3875
3876 /* col needs to be cleared because copying colVectorReal only regards nonzeros */
3877 col.clear();
3878
3879#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3880 lpi->spx->getColVectorReal(c, colsparse);
3881 /* the copy is necessary to transform the sparse column into a dense vector */
3882 col = colsparse;
3883#else
3884 col = lpi->spx->colVectorReal(c);
3885#endif
3886
3887 /* solve */
3888 if( ! lpi->spx->getBasisInverseTimesVecReal(col.get_ptr(), coef) )
3889 return SCIP_LPERROR;
3890
3891 return SCIP_OKAY;
3892}
3893
3894/**@} */
3895
3896
3897
3898
3899/*
3900 * LP State Methods
3901 */
3902
3903/**@name LP State Methods */
3904/**@{ */
3905
3906/** stores LPi state (like basis information) into lpistate object */
3908 SCIP_LPI* lpi, /**< LP interface structure */
3909 BMS_BLKMEM* blkmem, /**< block memory */
3910 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3911 )
3912{
3913 int ncols;
3914 int nrows;
3915
3916 SCIPdebugMessage("calling SCIPlpiGetState()\n");
3917
3918 assert(blkmem != NULL);
3919 assert(lpi != NULL);
3920 assert(lpi->spx != NULL);
3921 assert(lpistate != NULL);
3922
3923 assert( lpi->spx->preStrongbranchingBasisFreed() );
3924
3925 ncols = lpi->spx->numColsReal();
3926 nrows = lpi->spx->numRowsReal();
3927 assert(ncols >= 0);
3928 assert(nrows >= 0);
3929
3930 /* allocate lpistate data */
3931 SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
3932
3933 /* allocate enough memory for storing uncompressed basis information */
3934 SCIP_CALL( ensureCstatMem(lpi, ncols) );
3935 SCIP_CALL( ensureRstatMem(lpi, nrows) );
3936
3937 /* get unpacked basis information */
3938 SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
3939
3940 /* pack LPi state data */
3941 (*lpistate)->ncols = ncols;
3942 (*lpistate)->nrows = nrows;
3943 lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
3944
3945 return SCIP_OKAY;
3946}
3947
3948/** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
3949 * columns and rows since the state was stored with SCIPlpiGetState()
3950 */
3952 SCIP_LPI* lpi, /**< LP interface structure */
3953 BMS_BLKMEM* /*blkmem*/, /**< block memory */
3954 const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
3955 )
3956{
3957 int lpncols;
3958 int lpnrows;
3959 int i;
3960
3961 SCIPdebugMessage("calling SCIPlpiSetState()\n");
3962
3963 assert(lpi != NULL);
3964 assert(lpi->spx != NULL);
3965 assert(lpistate != NULL);
3966 /* assert(blkmem != NULL); */
3967
3968 assert( lpi->spx->preStrongbranchingBasisFreed() );
3969
3970 lpncols = lpi->spx->numColsReal();
3971 lpnrows = lpi->spx->numRowsReal();
3972 assert(lpistate->ncols <= lpncols);
3973 assert(lpistate->nrows <= lpnrows);
3974
3975 /* allocate enough memory for storing uncompressed basis information */
3978
3979 /* unpack LPi state data */
3980 lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
3981
3982 /* extend the basis to the current LP beyond the previously existing columns */
3983 for( i = lpistate->ncols; i < lpncols; ++i )
3984 {
3985 SCIP_Real bnd = lpi->spx->lowerReal(i);
3986 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3987 {
3988 /* if lower bound is +/- infinity -> try upper bound */
3989 bnd = lpi->spx->lowerReal(i);
3990 if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3991 /* variable is free */
3992 lpi->cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3993 else
3994 /* use finite upper bound */
3995 lpi->cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3996 }
3997 else
3998 /* use finite lower bound */
3999 lpi->cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4000 }
4001 for( i = lpistate->nrows; i < lpnrows; ++i )
4002 lpi->rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4003
4004 /* load basis information */
4005 SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
4006
4007 return SCIP_OKAY;
4008}
4009
4010/** clears current LPi state (like basis information) of the solver */
4012 SCIP_LPI* lpi /**< LP interface structure */
4013 )
4014{ /*lint --e{715}*/
4015 SCIPdebugMessage("calling SCIPlpiClearState()\n");
4016
4017 assert(lpi != NULL);
4018 assert(lpi->spx != NULL);
4019
4020 try
4021 {
4022 lpi->spx->clearBasis();
4023 }
4024#ifndef NDEBUG
4025 catch( const SPxException& x )
4026 {
4027 std::string s = x.what();
4028 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4029#else
4030 catch( const SPxException& )
4031 {
4032#endif
4033 assert( lpi->spx->status() != SPxSolver::OPTIMAL );
4034 return SCIP_LPERROR;
4035 }
4036
4037 return SCIP_OKAY;
4038}
4039
4040/** frees LPi state information */
4042 SCIP_LPI* lpi, /**< LP interface structure */
4043 BMS_BLKMEM* blkmem, /**< block memory */
4044 SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4045 )
4046{ /*lint --e{715}*/
4047 SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4048
4049 assert(lpi != NULL);
4050 assert(lpistate != NULL);
4051 assert(blkmem != NULL);
4052
4053 if ( *lpistate != NULL )
4054 lpistateFree(lpistate, blkmem);
4055
4056 return SCIP_OKAY;
4057}
4058
4059/** checks, whether the given LP state contains simplex basis information */
4061 SCIP_LPI* lpi, /**< LP interface structure */
4062 SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4063 )
4064{ /*lint --e{715}*/
4065 assert(lpi != NULL);
4066 return TRUE;
4067}
4068
4069/** reads LP state (like basis information from a file */
4071 SCIP_LPI* lpi, /**< LP interface structure */
4072 const char* fname /**< file name */
4073 )
4074{
4075 SCIPdebugMessage("calling SCIPlpiReadState()\n");
4076 assert(lpi != NULL);
4077 assert(lpi->spx != NULL);
4078 assert(fname != NULL);
4079
4080 assert( lpi->spx->preStrongbranchingBasisFreed() );
4081
4082 bool success;
4083 SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
4084
4085 return success ? SCIP_OKAY : SCIP_LPERROR;
4086}
4087
4088/** writes LPi state (i.e. basis information) to a file */
4090 SCIP_LPI* lpi, /**< LP interface structure */
4091 const char* fname /**< file name */
4092 )
4093{
4094 assert(lpi != NULL);
4095 assert(lpi->spx != NULL);
4096 assert(fname != NULL);
4097 SCIPdebugMessage("calling SCIPlpiWriteState()\n");
4098
4099 assert( lpi->spx->preStrongbranchingBasisFreed() );
4100
4101 bool res;
4102 SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
4103
4104 if ( ! res )
4105 return SCIP_LPERROR;
4106
4107 return SCIP_OKAY;
4108}
4109
4110/**@} */
4111
4112
4113
4114
4115/*
4116 * LP Pricing Norms Methods
4117 */
4118
4119/**@name LP Pricing Norms Methods */
4120/**@{ */
4121
4122/** stores LPi pricing norms information
4123 * @todo should we store norm information?
4124 */
4126 SCIP_LPI* lpi, /**< LP interface structure */
4127 BMS_BLKMEM* blkmem, /**< block memory */
4128 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
4129 )
4130{ /*lint --e{715}*/
4131#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4132 int nrows;
4133 int ncols;
4134
4135 assert(blkmem != NULL);
4136 assert(lpi != NULL);
4137 assert(lpi->spx != NULL);
4138 assert(lpinorms != NULL);
4139
4140 lpi->spx->getNdualNorms(nrows, ncols);
4141
4142 if( nrows == 0 && ncols == 0)
4143 {
4144 (*lpinorms = NULL);
4145 return SCIP_OKAY;
4146 }
4147
4148 /* allocate lpinorms data */
4149 SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
4150 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
4151 (*lpinorms)->nrows = 0;
4152 (*lpinorms)->ncols = 0;
4153
4154 SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
4155
4156 if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
4157 {
4158 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4159 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
4160 BMSfreeBlockMemory(blkmem, lpinorms);
4161 assert(*lpinorms == NULL);
4162 }
4163#ifndef NDEBUG
4164 else
4165 {
4166 assert(nrows == (*lpinorms)->nrows);
4167 assert(ncols == (*lpinorms)->ncols);
4168 }
4169#endif
4170#else
4171 (*lpinorms) = NULL;
4172#endif
4173
4174 return SCIP_OKAY;
4175}
4176
4177/** loads LPi pricing norms into solver; note that the LP might have been extended with additional
4178 * columns and rows since the state was stored with SCIPlpiGetNorms()
4179 */
4181 SCIP_LPI* lpi, /**< LP interface structure */
4182 BMS_BLKMEM* blkmem, /**< block memory */
4183 const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
4184 )
4185{ /*lint --e{715}*/
4186#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4187 assert(blkmem != NULL);
4188 assert(lpi != NULL);
4189 assert(lpi->spx != NULL);
4190
4191 /* if there was no pricing norms information available, the LPi norms were not stored */
4192 if( lpinorms == NULL )
4193 return SCIP_OKAY;
4194
4195 assert(lpinorms->nrows <= lpi->spx->numRowsReal());
4196 assert(lpinorms->ncols <= lpi->spx->numColsReal());
4197
4198 if( lpinorms->nrows == 0 )
4199 return SCIP_OKAY;
4200
4201 SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
4202 (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->numRowsReal(), lpi->spx->numColsReal());
4203
4204 (void) lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms);
4205#endif
4206
4207 return SCIP_OKAY;
4208}
4209
4210/** frees pricing norms information */
4212 SCIP_LPI* lpi, /**< LP interface structure */
4213 BMS_BLKMEM* blkmem, /**< block memory */
4214 SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
4215 )
4216{ /*lint --e{715}*/
4217#if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4218 assert(lpi != NULL);
4219 assert(lpinorms != NULL);
4220
4221 SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4222
4223 BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
4224 BMSfreeBlockMemory(blkmem, lpinorms);
4225 assert(*lpinorms == NULL);
4226#endif
4227
4228 return SCIP_OKAY;
4229}
4230
4231/**@} */
4232
4233
4234
4235
4236/*
4237 * Parameter Methods
4238 */
4239
4240/**@name Parameter Methods */
4241/**@{ */
4242
4243/** gets integer parameter of LP */
4245 SCIP_LPI* lpi, /**< LP interface structure */
4246 SCIP_LPPARAM type, /**< parameter number */
4247 int* ival /**< buffer to store the parameter value */
4248 )
4249{
4250 int scaleparam;
4251
4252 SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
4253
4254 assert(lpi != NULL);
4255 assert(lpi->spx != NULL);
4256 assert(ival != NULL);
4257
4258 switch( type )
4259 {
4261 *ival = lpi->spx->getFromScratch();
4262 break;
4263 case SCIP_LPPAR_LPINFO:
4264 *ival = lpi->spx->getLpInfo();
4265 break;
4266 case SCIP_LPPAR_LPITLIM:
4267 *ival = lpi->spx->intParam(SoPlex::ITERLIMIT);
4268 if( *ival == -1 )
4269 *ival = INT_MAX;
4270 break;
4272 *ival = lpi->spx->intParam(SoPlex::SIMPLIFIER);
4273 break;
4274 case SCIP_LPPAR_PRICING:
4275 *ival = (int) lpi->pricing;
4276 break;
4277 case SCIP_LPPAR_SCALING:
4278 scaleparam = lpi->spx->intParam(SoPlex::SCALER);
4279
4280 if( scaleparam == SoPlex::SCALER_OFF )
4281 *ival = 0;
4282 else if( scaleparam == SoPlex::SCALER_BIEQUI )
4283 *ival = 1;
4284#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4285 else
4286 {
4287 assert(scaleparam == SoPlex::SCALER_LEASTSQ);
4288 *ival = 2;
4289 }
4290#else
4291 else
4292 {
4293 assert(scaleparam == SoPlex::SCALER_GEO8);
4294 *ival = 2;
4295 }
4296#endif
4297 break;
4298#if SOPLEX_VERSION >= 201
4299 case SCIP_LPPAR_TIMING:
4300 *ival = (int) (lpi->spx->intParam(SoPlex::TIMER));
4301 break;
4302#endif
4303#if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
4305 *ival = (int) lpi->spx->randomSeed();
4306 break;
4307#endif
4308#if SOPLEX_APIVERSION >= 1
4310 *ival = (int) lpi->spx->intParam(SoPlex::FACTOR_UPDATE_MAX);
4311 break;
4312#endif
4313 default:
4314 return SCIP_PARAMETERUNKNOWN;
4315 } /*lint !e788*/
4316
4317 return SCIP_OKAY;
4318}
4319
4320/** sets integer parameter of LP */
4322 SCIP_LPI* lpi, /**< LP interface structure */
4323 SCIP_LPPARAM type, /**< parameter number */
4324 int ival /**< parameter value */
4325 )
4326{
4327 SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
4328
4329 assert(lpi != NULL);
4330 assert(lpi->spx != NULL);
4331
4332 switch( type )
4333 {
4335 assert(ival == TRUE || ival == FALSE);
4336 lpi->spx->setFromScratch(bool(ival));
4337 break;
4338 case SCIP_LPPAR_LPINFO:
4339 assert(ival == TRUE || ival == FALSE);
4340 lpi->spx->setLpInfo(bool(ival));
4341 break;
4342 case SCIP_LPPAR_LPITLIM:
4343 assert( ival >= 0 );
4344 /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
4345 if( ival >= INT_MAX )
4346 ival = -1;
4347 (void) lpi->spx->setIntParam(SoPlex::ITERLIMIT, ival);
4348 break;
4350 assert(ival == TRUE || ival == FALSE);
4351#if SOPLEX_APIVERSION < 13
4352 assert(ival == TRUE || ival == FALSE);
4353#else
4354 assert(ival == 1 || ival == 0 || ival == 2);
4355#endif
4356 (void) lpi->spx->setIntParam(SoPlex::SIMPLIFIER, ival);
4357 break;
4358 case SCIP_LPPAR_PRICING:
4359 lpi->pricing = (SCIP_PRICING)ival;
4360 switch( lpi->pricing )
4361 {
4363 case SCIP_PRICING_AUTO:
4364 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_AUTO);
4365 break;
4366 case SCIP_PRICING_FULL:
4367 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4368 break;
4370 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_PARMULT);
4371 break;
4372 case SCIP_PRICING_STEEP:
4373 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4374 break;
4376 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_QUICKSTEEP);
4377 break;
4378 case SCIP_PRICING_DEVEX:
4379 (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_DEVEX);
4380 break;
4381 default:
4382 return SCIP_LPERROR;
4383 }
4384 break;
4385 case SCIP_LPPAR_SCALING:
4386 assert(ival >= 0 && ival <= 2);
4387 if( ival == 0 )
4388 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_OFF);
4389 else if( ival == 1 )
4390 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_BIEQUI);
4391 else
4392#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4393 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_LEASTSQ);
4394#else
4395 (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_GEO8);
4396#endif
4397
4398 break;
4399#if SOPLEX_VERSION >= 201
4400 case SCIP_LPPAR_TIMING:
4401 assert(ival >= 0 && ival < 3);
4402 (void) lpi->spx->setIntParam(SoPlex::TIMER, ival);
4403 break;
4404#endif
4405#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
4407 lpi->spx->setRandomSeed((unsigned long)(long)ival);
4408 break;
4409#endif
4410#if SOPLEX_VERSION > 221 || (SOPLEX_VERSION >= 221 && SOPLEX_SUBVERSION >= 3)
4412 assert(ival >= 0 && ival < 3);
4413 (void) lpi->spx->setIntParam(SoPlex::SOLUTION_POLISHING, ival);
4414 break;
4415#endif
4416#if SOPLEX_APIVERSION >= 1
4418 assert(ival >= 0);
4419 (void) lpi->spx->setIntParam(SoPlex::FACTOR_UPDATE_MAX, ival);
4420 break;
4421#endif
4422
4423 default:
4424 return SCIP_PARAMETERUNKNOWN;
4425 } /*lint !e788*/
4426
4427 return SCIP_OKAY;
4428}
4429
4430/** gets floating point parameter of LP */
4432 SCIP_LPI* lpi, /**< LP interface structure */
4433 SCIP_LPPARAM type, /**< parameter number */
4434 SCIP_Real* dval /**< buffer to store the parameter value */
4435 )
4436{
4437 SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
4438
4439 assert(lpi != NULL);
4440 assert(lpi->spx != NULL);
4441 assert(dval != NULL);
4442
4443 switch( type )
4444 {
4445 case SCIP_LPPAR_FEASTOL:
4446 *dval = lpi->spx->feastol();
4447 break;
4449 *dval = lpi->spx->opttol();
4450 break;
4451 case SCIP_LPPAR_OBJLIM:
4452 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4453 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_UPPER);
4454 else
4455 *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_LOWER);
4456 break;
4457 case SCIP_LPPAR_LPTILIM:
4458 *dval = lpi->spx->realParam(SoPlex::TIMELIMIT);
4459 break;
4461 *dval = lpi->spx->realParam(SoPlex::REPRESENTATION_SWITCH);
4462 if( *dval >= SCIPlpiInfinity(lpi) )
4463 *dval = -1.0;
4464 break;
4466 *dval = lpi->conditionlimit;
4467 break;
4469#if (SOPLEX_APIVERSION >= 9)
4470 *dval = lpi->spx->realParam(SoPlex::MIN_MARKOWITZ);
4471 break;
4472#endif
4473 default:
4474 return SCIP_PARAMETERUNKNOWN;
4475 } /*lint !e788*/
4476
4477 return SCIP_OKAY;
4478}
4479
4480/** sets floating point parameter of LP */
4482 SCIP_LPI* lpi, /**< LP interface structure */
4483 SCIP_LPPARAM type, /**< parameter number */
4484 SCIP_Real dval /**< parameter value */
4485 )
4486{
4487 SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
4488
4489 assert(lpi != NULL);
4490 assert(lpi->spx != NULL);
4491
4492 switch( type )
4493 {
4494 case SCIP_LPPAR_FEASTOL:
4495 /* 0 < dval */
4496 assert( dval > 0.0 );
4497 lpi->spx->setFeastol(dval);
4498 break;
4500 /* 0 < dval */
4501 assert( dval > 0.0 );
4502 lpi->spx->setOpttol(dval);
4503 break;
4504 case SCIP_LPPAR_OBJLIM:
4505 /* no restrictions on dval */
4506 if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4507 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_UPPER, dval);
4508 else
4509 (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_LOWER, dval);
4510 break;
4511 case SCIP_LPPAR_LPTILIM:
4512 assert( dval > 0.0 );
4513 /* soplex requires 0 < dval < DEFAULT_INFINITY (= 1e100), -1 means unlimited */
4514 (void) lpi->spx->setRealParam(SoPlex::TIMELIMIT, dval);
4515 break;
4517 /* 0 <= dval <= inf */
4518 assert( dval >= 0.0 || dval == -1.0 );
4519 if( dval == -1 )
4520 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, SCIPlpiInfinity(lpi));
4521 else
4522 (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, dval);
4523 break;
4525 lpi->conditionlimit = dval;
4526 lpi->checkcondition = (dval >= 0.0);
4527 break;
4529#if (SOPLEX_APIVERSION >= 9)
4530 /* 1e-4 <= dval <= 0.999 */
4531 if( dval < 1e-4 )
4532 dval = 1e-4;
4533 else if( dval > 0.9999 )
4534 dval = 0.9999;
4535
4536 (void) lpi->spx->setRealParam(SoPlex::MIN_MARKOWITZ, dval);
4537 break;
4538#endif
4539 default:
4540 return SCIP_PARAMETERUNKNOWN;
4541 } /*lint !e788*/
4542
4543 return SCIP_OKAY;
4544}
4545
4546/** interrupts the currently ongoing lp solve or disables the interrupt */
4548 SCIP_LPI* lpi, /**< LP interface structure */
4549 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
4550 )
4551{
4552 assert(lpi != NULL);
4553 assert(lpi->spx != NULL);
4554
4555 lpi->spx->setInterrupt(interrupt);
4556
4557 return SCIP_OKAY;
4558}
4559
4560/**@} */
4561
4562
4563
4564
4565/*
4566 * Numerical Methods
4567 */
4568
4569/**@name Numerical Methods */
4570/**@{ */
4571
4572/** returns value treated as infinity in the LP solver */
4574 SCIP_LPI* lpi /**< LP interface structure */
4575 )
4576{
4577 assert(lpi != NULL);
4578 SCIPdebugMessage("calling SCIPlpiInfinity()\n");
4579
4580 return lpi->spx->realParam(SoPlex::INFTY);
4581}
4582
4583/** checks if given value is treated as infinity in the LP solver */
4585 SCIP_LPI* lpi, /**< LP interface structure */
4586 SCIP_Real val
4587 )
4588{
4589 assert(lpi != NULL);
4590 SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
4591
4592 return (val >= lpi->spx->realParam(SoPlex::INFTY));
4593}
4594
4595/**@} */
4596
4597
4598
4599
4600/*
4601 * File Interface Methods
4602 */
4603
4604/**@name File Interface Methods */
4605/**@{ */
4606
4607/** returns, whether the given file exists */
4608static
4609SCIP_Bool fileExists(
4610 const char* filename /**< file name */
4611 )
4612{
4613 FILE* f;
4614
4615 f = fopen(filename, "r");
4616 if( f == NULL )
4617 return FALSE;
4618
4619 fclose(f);
4620
4621 return TRUE;
4622}
4623
4624/** reads LP from a file */
4626 SCIP_LPI* lpi, /**< LP interface structure */
4627 const char* fname /**< file name */
4628 )
4629{
4630 SCIPdebugMessage("calling SCIPlpiReadLP()\n");
4631
4632 assert(lpi != NULL);
4633 assert(lpi->spx != NULL);
4634 assert(fname != NULL);
4635
4636 assert( lpi->spx->preStrongbranchingBasisFreed() );
4637
4638 if( !fileExists(fname) )
4639 return SCIP_NOFILE;
4640
4641 try
4642 {
4643 assert(lpi->spx->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL);
4644 if( !lpi->spx->readFile(fname) )
4645 return SCIP_READERROR;
4646 }
4647#ifndef NDEBUG
4648 catch( const SPxException& x )
4649 {
4650 std::string s = x.what();
4651 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4652#else
4653 catch( const SPxException& )
4654 {
4655#endif
4656 return SCIP_READERROR;
4657 }
4658
4659 return SCIP_OKAY;
4660}
4661
4662/** writes LP to a file */
4664 SCIP_LPI* lpi, /**< LP interface structure */
4665 const char* fname /**< file name */
4666 )
4667{
4668 SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
4669
4670 assert(lpi != NULL);
4671 assert(lpi->spx != NULL);
4672 assert(fname != NULL);
4673
4674 try
4675 {
4676 (void) lpi->spx->writeFileReal(fname);
4677 }
4678#ifndef NDEBUG
4679 catch( const SPxException& x )
4680 {
4681 std::string s = x.what();
4682 SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4683#else
4684 catch( const SPxException& )
4685 {
4686#endif
4687 return SCIP_WRITEERROR;
4688 }
4689
4690 return SCIP_OKAY;
4691}
4692
4693/**@} */
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
#define SCIP_INVALID
Definition def.h:206
#define SCIP_ALLOC(x)
Definition def.h:399
#define TRUE
Definition def.h:95
#define FALSE
Definition def.h:96
#define EPSCEIL(x, eps)
Definition def.h:220
#define SCIPABORT()
Definition def.h:360
#define EPSFLOOR(x, eps)
Definition def.h:219
#define REALABS(x)
Definition def.h:210
#define SCIP_CALL(x)
Definition def.h:388
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
SCIP_Bool SCIPlpiHasPrimalSolve(void)
SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
SCIP_Bool SCIPlpiHasBarrierSolve(void)
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
const char * SCIPlpiGetSolverName(void)
Definition lpi_spx2.cpp:999
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
SCIP_RETCODE SCIPlpiGetCols(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lb, SCIP_Real *ub, int *nnonz, int *beg, int *ind, SCIP_Real *val)
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
SCIP_RETCODE SCIPlpiGetRows(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhs, SCIP_Real *rhs, int *nnonz, int *beg, int *ind, SCIP_Real *val)
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
const char * SCIPlpiGetSolverDesc(void)
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
SCIP_Bool SCIPlpiHasDualSolve(void)
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiLoadColLP(SCIP_LPI *lpi, SCIP_OBJSEN objsen, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
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)
interface methods for specific LP solvers
SCIP_DUALPACKET ROWPACKET
Definition lpi_clp.cpp:128
SCIP_DUALPACKET COLPACKET
Definition lpi_clp.cpp:126
static void setIntParam(SCIP_LPI *lpi, int const param, int const parval)
Definition lpi_cpx.c:653
#define FEASTOL
Definition lpi_qso.c:99
static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
Definition lpi_spx2.cpp:877
#define NULL
Definition lpi_spx2.cpp:143
static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
Definition lpi_spx2.cpp:893
static SCIP_Bool fileExists(const char *filename)
#define SOPLEX_TRY(messagehdlr, x)
Definition lpi_spx2.cpp:154
static int rowpacketNum(int nrows)
Definition lpi_spx2.cpp:868
static SCIP_RETCODE spxSolve(SCIP_LPI *lpi)
SCIP_DUALPACKET ROWPACKET
Definition lpi_spx2.cpp:763
#define SOPLEX_VERBLEVEL
Definition lpi_spx2.cpp:133
static SCIP_RETCODE ensureCstatMem(SCIP_LPI *lpi, int num)
Definition lpi_spx2.cpp:808
static const char spxdesc[200]
Definition lpi_spx2.cpp:982
#define COLS_PER_PACKET
Definition lpi_spx2.cpp:762
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
Definition lpi_spx2.cpp:933
SCIP_DUALPACKET COLPACKET
Definition lpi_spx2.cpp:761
static SCIP_RETCODE lpiStrongbranch(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
static SCIP_RETCODE ensureRstatMem(SCIP_LPI *lpi, int num)
Definition lpi_spx2.cpp:830
static int colpacketNum(int ncols)
Definition lpi_spx2.cpp:859
#define CHECK_SOPLEX_PARAM(x)
Definition lpi_spx2.cpp:81
#define SOPLEX_SUBVERSION
Definition lpi_spx2.cpp:103
static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
Definition lpi_spx2.cpp:909
#define SOPLEX_TRY_ABORT(x)
Definition lpi_spx2.cpp:199
#define ROWS_PER_PACKET
Definition lpi_spx2.cpp:764
static const char spxname[20]
Definition lpi_spx2.cpp:980
static void invalidateSolution(SCIP_LPI *lpi)
Definition lpi_spx2.cpp:960
#define BMSfreeMemory(ptr)
Definition memory.h:147
#define BMSfreeBlockMemory(mem, ptr)
Definition memory.h:467
#define BMSallocBlockMemory(mem, ptr)
Definition memory.h:453
#define BMSreallocMemoryArray(ptr, num)
Definition memory.h:129
#define BMSallocMemoryArray(ptr, num)
Definition memory.h:125
#define BMSallocMemoryCPP(size)
Definition memory.h:123
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition memory.h:456
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition memory.h:469
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:439
#define BMSfreeMemoryArrayNull(ptr)
Definition memory.h:150
#define BMSallocMemory(ptr)
Definition memory.h:120
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
SCIP_Real * norms
Definition lpi_qso.c:85
COLPACKET * packcstat
Definition lpi_clp.cpp:136
ROWPACKET * packrstat
Definition lpi_clp.cpp:137
SCIP_Bool solved
Definition lpi_clp.cpp:114
SCIP_Real conditionlimit
Definition lpi_cpx.c:173
int * cstat
Definition lpi_clp.cpp:107
int rstatsize
Definition lpi_clp.cpp:110
int * rstat
Definition lpi_clp.cpp:108
SCIP_PRICING pricing
Definition lpi_clp.cpp:112
int cstatsize
Definition lpi_clp.cpp:109
SCIP_MESSAGEHDLR * messagehdlr
Definition lpi_cpx.c:184
SPxSCIP * spx
SCIP_Bool checkcondition
Definition lpi_cpx.c:174
#define MAX(x, y)
Definition tclique_def.h:92
@ SCIP_PRICING_STEEPQSTART
Definition type_lpi.h:83
@ SCIP_PRICING_AUTO
Definition type_lpi.h:79
@ SCIP_PRICING_DEVEX
Definition type_lpi.h:84
@ SCIP_PRICING_STEEP
Definition type_lpi.h:82
@ SCIP_PRICING_FULL
Definition type_lpi.h:80
@ SCIP_PRICING_LPIDEFAULT
Definition type_lpi.h:78
@ SCIP_PRICING_PARTIAL
Definition type_lpi.h:81
enum SCIP_Pricing SCIP_PRICING
Definition type_lpi.h:86
enum SCIP_LPParam SCIP_LPPARAM
Definition type_lpi.h:73
@ SCIP_LPSOLQUALITY_EXACTCONDITION
Definition type_lpi.h:102
@ SCIP_LPSOLQUALITY_ESTIMCONDITION
Definition type_lpi.h:101
@ 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_MARKOWITZ
Definition type_lpi.h:62
@ 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
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition type_lpi.h:104
@ SCIP_OBJSEN_MAXIMIZE
Definition type_lpi.h:42
@ SCIP_OBJSEN_MINIMIZE
Definition type_lpi.h:43
enum SCIP_ObjSen SCIP_OBJSEN
Definition type_lpi.h:45
@ SCIP_LPERROR
@ SCIP_NOFILE
@ SCIP_READERROR
@ SCIP_INVALIDDATA
@ SCIP_PARAMETERUNKNOWN
@ SCIP_WRITEERROR
enum SCIP_Retcode SCIP_RETCODE