Scippy

SCIP

Solving Constraint Integer Programs

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