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