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-2021 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  (void)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  (void)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  (void)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  (void)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  assert( lpi != NULL );
1015  assert( ncols >= 0 );
1016  assert( ncols == 0 || intInfo != NULL );
1017 
1018 #if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
1019  assert(ncols == lpi->spx->numColsReal() || (ncols == 0 && intInfo == NULL));
1020  lpi->spx->setIntegralityInformation(ncols, intInfo);
1021  return SCIP_OKAY;
1022 #else
1023  SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
1024  return SCIP_LPERROR;
1025 #endif
1026 }
1027 
1028 /** informs about availability of a primal simplex solving method */
1030  void
1031  )
1033  return TRUE;
1034 }
1035 
1036 /** informs about availability of a dual simplex solving method */
1038  void
1039  )
1041  return TRUE;
1042 }
1043 
1044 /** informs about availability of a barrier solving method */
1046  void
1047  )
1049  return FALSE;
1050 }
1051 
1052 /**@} */
1053 
1054 
1055 
1056 
1057 /*
1058  * LPI Creation and Destruction Methods
1059  */
1060 
1061 /**@name LPI Creation and Destruction Methods */
1062 /**@{ */
1063 
1064 /** creates an LP problem object */
1066  SCIP_LPI** lpi, /**< pointer to an LP interface structure */
1067  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
1068  const char* name, /**< problem name */
1069  SCIP_OBJSEN objsen /**< objective sense */
1070  )
1071 {
1072  assert(lpi != NULL);
1073  assert(name != NULL);
1074 
1075  /* create SoPlex object */
1076  SCIP_ALLOC( BMSallocMemory(lpi) );
1077 
1078  /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
1079  (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
1080  SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
1081  (void) (*lpi)->spx->setIntParam(SoPlex::SYNCMODE, SoPlex::SYNCMODE_ONLYREAL);
1082  (void) (*lpi)->spx->setIntParam(SoPlex::SOLVEMODE, SoPlex::SOLVEMODE_REAL);
1083  (void) (*lpi)->spx->setIntParam(SoPlex::REPRESENTATION, SoPlex::REPRESENTATION_AUTO);
1084 
1085  /* disable time-measurement for statistics */
1086 #if SOPLEX_APIVERSION >= 10
1087  (void) (*lpi)->spx->setIntParam(SoPlex::STATTIMER, 0);
1088 #endif
1089 
1090  (*lpi)->cstat = NULL;
1091  (*lpi)->rstat = NULL;
1092  (*lpi)->cstatsize = 0;
1093  (*lpi)->rstatsize = 0;
1094  (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
1095  (*lpi)->conditionlimit = -1.0;
1096  (*lpi)->checkcondition = FALSE;
1097  (*lpi)->messagehdlr = messagehdlr;
1098 
1099  invalidateSolution(*lpi);
1100 
1101  /* set objective sense */
1102  SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
1103 
1104  /* set default pricing */
1105  SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
1106 
1107  {
1108  SPxOut::Verbosity verbosity = (*lpi)->spx->spxout.getVerbosity();
1109  (*lpi)->spx->spxout.setVerbosity((SPxOut::Verbosity)((*lpi)->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
1110  (*lpi)->spx->printVersion();
1111  (*lpi)->spx->spxout.setVerbosity(verbosity);
1112  }
1113 
1114  return SCIP_OKAY;
1115 }
1116 
1117 /** deletes an LP problem object */
1119  SCIP_LPI** lpi /**< pointer to an LP interface structure */
1120  )
1122  assert(lpi != NULL);
1123  assert(*lpi != NULL);
1124  assert((*lpi)->spx != NULL);
1125 
1126  /* free LP using destructor and free memory via blockmemshell */
1127  (*lpi)->spx->~SPxSCIP();
1128  BMSfreeMemory(&((*lpi)->spx));
1129 
1130  /* free memory */
1131  BMSfreeMemoryArrayNull(&(*lpi)->cstat);
1132  BMSfreeMemoryArrayNull(&(*lpi)->rstat);
1133  BMSfreeMemory(lpi);
1134 
1135  return SCIP_OKAY;
1136 }
1137 
1138 /**@} */
1139 
1140 
1141 
1142 
1143 /*
1144  * Modification Methods
1145  */
1146 
1147 /**@name Modification Methods */
1148 /**@{ */
1149 
1150 /** copies LP data with column matrix into LP solver */
1152  SCIP_LPI* lpi, /**< LP interface structure */
1153  SCIP_OBJSEN objsen, /**< objective sense */
1154  int ncols, /**< number of columns */
1155  const SCIP_Real* obj, /**< objective function values of columns */
1156  const SCIP_Real* lb, /**< lower bounds of columns */
1157  const SCIP_Real* ub, /**< upper bounds of columns */
1158  char** colnames, /**< column names, or NULL */
1159  int nrows, /**< number of rows */
1160  const SCIP_Real* lhs, /**< left hand sides of rows */
1161  const SCIP_Real* rhs, /**< right hand sides of rows */
1162  char** /*rownames*/, /**< row names, or NULL */
1163  int nnonz, /**< number of nonzero elements in the constraint matrix */
1164  const int* beg, /**< start index of each column in ind- and val-array */
1165  const int* ind, /**< row indices of constraint matrix entries */
1166  const SCIP_Real* val /**< values of constraint matrix entries */
1167  )
1168 {
1169 #ifndef NDEBUG
1170  {
1171  int j;
1172  for( j = 0; j < nnonz; j++ )
1173  assert( val[j] != 0 );
1174  }
1175 #endif
1176 
1177  SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
1178 
1179  assert(lpi != NULL);
1180  assert(lpi->spx != NULL);
1181  assert(lhs != NULL);
1182  assert(rhs != NULL);
1183  assert(obj != NULL);
1184  assert(lb != NULL);
1185  assert(ub != NULL);
1186  assert(beg != NULL);
1187  assert(ind != NULL);
1188  assert(val != NULL);
1189 
1190  invalidateSolution(lpi);
1191  assert(lpi->spx->preStrongbranchingBasisFreed());
1192 
1193  try
1194  {
1195  SPxSCIP* spx = lpi->spx;
1196  LPRowSet rows(nrows);
1197  DSVector emptyVector(0);
1198  int i;
1199 
1200  spx->clearLPReal();
1201 
1202  /* set objective sense */
1203  (void) spx->setIntParam(SoPlex::OBJSENSE, (objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE));
1204 
1205  /* create empty rows with given sides */
1206  for( i = 0; i < nrows; ++i )
1207  rows.add(lhs[i], emptyVector, rhs[i]);
1208  spx->addRowsReal(rows);
1209 
1210  /* create column vectors with coefficients and bounds */
1211  SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
1212  }
1213 #ifndef NDEBUG
1214  catch( const SPxException& x )
1215  {
1216  std::string s = x.what();
1217  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1218 #else
1219  catch( const SPxException& )
1220  {
1221 #endif
1222  return SCIP_LPERROR;
1223  }
1224 
1225  return SCIP_OKAY;
1226 }
1227 
1228 /** adds columns to the LP */
1230  SCIP_LPI* lpi, /**< LP interface structure */
1231  int ncols, /**< number of columns to be added */
1232  const SCIP_Real* obj, /**< objective function values of new columns */
1233  const SCIP_Real* lb, /**< lower bounds of new columns */
1234  const SCIP_Real* ub, /**< upper bounds of new columns */
1235  char** /*colnames*/, /**< column names, or NULL */
1236  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1237  const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1238  const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1239  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1240  )
1241 {
1242  SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1243 
1244  assert(lpi != NULL);
1245  assert(lpi->spx != NULL);
1246  assert(obj != NULL);
1247  assert(lb != NULL);
1248  assert(ub != NULL);
1249  assert(nnonz == 0 || beg != NULL);
1250  assert(nnonz == 0 || ind != NULL);
1251  assert(nnonz == 0 || val != NULL);
1252  assert(nnonz >= 0);
1253  assert(ncols >= 0);
1254 
1255  invalidateSolution(lpi);
1256 
1257  assert( lpi->spx->preStrongbranchingBasisFreed() );
1258 
1259 #ifndef NDEBUG
1260  if ( nnonz > 0 )
1261  {
1262  /* perform check that no new rows are added - this is likely to be a mistake */
1263  int nrows = lpi->spx->numRowsReal();
1264  for (int j = 0; j < nnonz; ++j)
1265  {
1266  assert( 0 <= ind[j] && ind[j] < nrows );
1267  assert( val[j] != 0.0 );
1268  }
1269  }
1270 #endif
1271 
1272  SPxSCIP* spx = lpi->spx;
1273  try
1274  {
1275  LPColSet cols(ncols);
1276  DSVector colVector(ncols);
1277  int start;
1278  int last;
1279  int i;
1280 
1281  /* create column vectors with coefficients and bounds */
1282  for( i = 0; i < ncols; ++i )
1283  {
1284  colVector.clear();
1285  if( nnonz > 0 )
1286  {
1287  start = beg[i];
1288  last = (i == ncols-1 ? nnonz : beg[i+1]);
1289  colVector.add( last-start, &ind[start], &val[start] );
1290  }
1291  cols.add(obj[i], lb[i], colVector, ub[i]);
1292  }
1293  spx->addColsReal(cols);
1294  }
1295 #ifndef NDEBUG
1296  catch( const SPxException& x )
1297  {
1298  std::string s = x.what();
1299  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1300 #else
1301  catch( const SPxException& )
1302  {
1303 #endif
1304  return SCIP_LPERROR;
1305  }
1306 
1307  return SCIP_OKAY;
1308 }
1309 
1310 /** deletes all columns in the given range from LP */
1312  SCIP_LPI* lpi, /**< LP interface structure */
1313  int firstcol, /**< first column to be deleted */
1314  int lastcol /**< last column to be deleted */
1315  )
1316 {
1317  SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1318 
1319  assert(lpi != NULL);
1320  assert(lpi->spx != NULL);
1321  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
1322 
1323  invalidateSolution(lpi);
1324 
1325  assert( lpi->spx->preStrongbranchingBasisFreed() );
1326 
1327  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRangeReal(firstcol, lastcol) );
1328 
1329  return SCIP_OKAY;
1330 }
1331 
1332 /** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1334  SCIP_LPI* lpi, /**< LP interface structure */
1335  int* dstat /**< deletion status of columns
1336  * input: 1 if column should be deleted, 0 if not
1337  * output: new position of column, -1 if column was deleted */
1338  )
1339 {
1340  int ncols;
1341  int i;
1342 
1343  SCIPdebugMessage("calling SCIPlpiDelColset()\n");
1344 
1345  assert(lpi != NULL);
1346  assert(lpi->spx != NULL);
1347  assert(dstat != NULL);
1348 
1349  invalidateSolution(lpi);
1350 
1351  assert( lpi->spx->preStrongbranchingBasisFreed() );
1352 
1353  ncols = lpi->spx->numColsReal();
1354 
1355  /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
1356  for( i = 0; i < ncols; ++i )
1357  dstat[i] *= -1;
1358 
1359  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColsReal(dstat) );
1360 
1361  return SCIP_OKAY;
1362 }
1363 
1364 /** adds rows to the LP */
1366  SCIP_LPI* lpi, /**< LP interface structure */
1367  int nrows, /**< number of rows to be added */
1368  const SCIP_Real* lhs, /**< left hand sides of new rows */
1369  const SCIP_Real* rhs, /**< right hand sides of new rows */
1370  char** /*rownames*/, /**< row names, or NULL */
1371  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1372  const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
1373  const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
1374  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1375  )
1376 {
1377  SCIPdebugMessage("calling SCIPlpiAddRows()\n");
1378 
1379  assert(lpi != NULL);
1380  assert(lpi->spx != NULL);
1381  assert(lhs != NULL);
1382  assert(rhs != NULL);
1383  assert(nnonz == 0 || beg != NULL);
1384  assert(nnonz == 0 || ind != NULL);
1385  assert(nnonz == 0 || val != NULL);
1386 
1387  invalidateSolution(lpi);
1388 
1389  assert( lpi->spx->preStrongbranchingBasisFreed() );
1390 
1391 #ifndef NDEBUG
1392  if ( nnonz > 0 )
1393  {
1394  /* perform check that no new columns are added - this is likely to be a mistake */
1395  int ncols = lpi->spx->numColsReal();
1396  for (int j = 0; j < nnonz; ++j)
1397  {
1398  assert( val[j] != 0.0 );
1399  assert( 0 <= ind[j] && ind[j] < ncols );
1400  }
1401  }
1402 #endif
1403 
1404  try
1405  {
1406  SPxSCIP* spx = lpi->spx;
1407  LPRowSet rows(nrows);
1408  DSVector rowVector;
1409  int start;
1410  int last;
1411  int i;
1412 
1413  /* create row vectors with given sides */
1414  for( i = 0; i < nrows; ++i )
1415  {
1416  rowVector.clear();
1417  if( nnonz > 0 )
1418  {
1419  start = beg[i];
1420  last = (i == nrows-1 ? nnonz : beg[i+1]);
1421  rowVector.add( last-start, &ind[start], &val[start] );
1422  }
1423  rows.add(lhs[i], rowVector, rhs[i]);
1424  }
1425  spx->addRowsReal(rows);
1426  }
1427 #ifndef NDEBUG
1428  catch( const SPxException& x )
1429  {
1430  std::string s = x.what();
1431  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1432 #else
1433  catch( const SPxException& )
1434  {
1435 #endif
1436  return SCIP_LPERROR;
1437  }
1438 
1439  return SCIP_OKAY;
1440 }
1441 
1442 /** deletes all rows in the given range from LP */
1444  SCIP_LPI* lpi, /**< LP interface structure */
1445  int firstrow, /**< first row to be deleted */
1446  int lastrow /**< last row to be deleted */
1447  )
1448 {
1449  SCIPdebugMessage("calling SCIPlpiDelRows()\n");
1450 
1451  assert(lpi != NULL);
1452  assert(lpi->spx != NULL);
1453  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
1454 
1455  invalidateSolution(lpi);
1456 
1457  assert( lpi->spx->preStrongbranchingBasisFreed() );
1458 
1459  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRangeReal(firstrow, lastrow) );
1460 
1461  return SCIP_OKAY;
1462 }
1463 
1464 /** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
1466  SCIP_LPI* lpi, /**< LP interface structure */
1467  int* dstat /**< deletion status of rows
1468  * input: 1 if row should be deleted, 0 if not
1469  * output: new position of row, -1 if row was deleted */
1470  )
1471 {
1472  int nrows;
1473  int i;
1474 
1475  SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
1476 
1477  assert(lpi != NULL);
1478  assert(lpi->spx != NULL);
1479 
1480  invalidateSolution(lpi);
1481 
1482  assert( lpi->spx->preStrongbranchingBasisFreed() );
1483 
1484  nrows = lpi->spx->numRowsReal();
1485 
1486  /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
1487  for( i = 0; i < nrows; ++i )
1488  dstat[i] *= -1;
1489 
1490  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowsReal(dstat) );
1491 
1492  return SCIP_OKAY;
1493 }
1494 
1495 /** clears the whole LP */
1497  SCIP_LPI* lpi /**< LP interface structure */
1498  )
1500  SCIPdebugMessage("calling SCIPlpiClear()\n");
1501 
1502  assert(lpi != NULL);
1503  assert(lpi->spx != NULL);
1504 
1505  invalidateSolution(lpi);
1506 
1507  assert( lpi->spx->preStrongbranchingBasisFreed() );
1508  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clearLPReal() );
1509 
1510  return SCIP_OKAY;
1511 }
1512 
1513 /** changes lower and upper bounds of columns */
1515  SCIP_LPI* lpi, /**< LP interface structure */
1516  int ncols, /**< number of columns to change bounds for */
1517  const int* ind, /**< column indices or NULL if ncols is zero */
1518  const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
1519  const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
1520  )
1521 {
1522  int i;
1523 
1524  SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
1525 
1526  assert(lpi != NULL);
1527  assert(lpi->spx != NULL);
1528  assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
1529  if( ncols <= 0 )
1530  return SCIP_OKAY;
1531 
1532  invalidateSolution(lpi);
1533 
1534  assert( lpi->spx->preStrongbranchingBasisFreed() );
1535 
1536  try
1537  {
1538  for( i = 0; i < ncols; ++i )
1539  {
1540  assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
1541 
1542  if ( SCIPlpiIsInfinity(lpi, lb[i]) )
1543  {
1544  SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
1545  return SCIP_LPERROR;
1546  }
1547  if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
1548  {
1549  SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
1550  return SCIP_LPERROR;
1551  }
1552 
1553  lpi->spx->changeBoundsReal(ind[i], lb[i], ub[i]);
1554  assert(lpi->spx->lowerReal(ind[i]) <= lpi->spx->upperReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
1555  }
1556  }
1557 #ifndef NDEBUG
1558  catch( const SPxException& x )
1559  {
1560  std::string s = x.what();
1561  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1562 #else
1563  catch( const SPxException& )
1564  {
1565 #endif
1566  return SCIP_LPERROR;
1567  }
1568 
1569  return SCIP_OKAY;
1570 }
1571 
1572 /** changes left and right hand sides of rows */
1574  SCIP_LPI* lpi, /**< LP interface structure */
1575  int nrows, /**< number of rows to change sides for */
1576  const int* ind, /**< row indices */
1577  const SCIP_Real* lhs, /**< new values for left hand sides */
1578  const SCIP_Real* rhs /**< new values for right hand sides */
1579  )
1580 {
1581  int i;
1582 
1583  SCIPdebugMessage("calling SCIPlpiChgSides()\n");
1584 
1585  assert(lpi != NULL);
1586  assert(lpi->spx != NULL);
1587  assert(ind != NULL);
1588  assert(lhs != NULL);
1589  assert(rhs != NULL);
1590  if( nrows <= 0 )
1591  return SCIP_OKAY;
1592 
1593  invalidateSolution(lpi);
1594 
1595  assert( lpi->spx->preStrongbranchingBasisFreed() );
1596 
1597  try
1598  {
1599  for( i = 0; i < nrows; ++i )
1600  {
1601  assert(0 <= ind[i] && ind[i] < lpi->spx->numRowsReal());
1602  lpi->spx->changeRangeReal(ind[i], lhs[i], rhs[i]);
1603  assert(lpi->spx->lhsReal(ind[i]) <= lpi->spx->rhsReal(ind[i]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
1604  }
1605  }
1606 #ifndef NDEBUG
1607  catch( const SPxException& x )
1608  {
1609  std::string s = x.what();
1610  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1611 #else
1612  catch( const SPxException& )
1613  {
1614 #endif
1615  return SCIP_LPERROR;
1616  }
1617 
1618  return SCIP_OKAY;
1619 }
1620 
1621 /** changes a single coefficient */
1623  SCIP_LPI* lpi, /**< LP interface structure */
1624  int row, /**< row number of coefficient to change */
1625  int col, /**< column number of coefficient to change */
1626  SCIP_Real newval /**< new value of coefficient */
1627  )
1628 {
1629  SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
1630 
1631  assert(lpi != NULL);
1632  assert(lpi->spx != NULL);
1633  assert(0 <= row && row < lpi->spx->numRowsReal());
1634  assert(0 <= col && col < lpi->spx->numColsReal());
1635 
1636  invalidateSolution(lpi);
1637 
1638  assert( lpi->spx->preStrongbranchingBasisFreed() );
1639 
1640  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElementReal(row, col, newval) );
1641 
1642  return SCIP_OKAY;
1643 }
1644 
1645 /** changes the objective sense */
1647  SCIP_LPI* lpi, /**< LP interface structure */
1648  SCIP_OBJSEN objsen /**< new objective sense */
1649  )
1650 {
1651  SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
1652 
1653  assert(lpi != NULL);
1654  assert(lpi->spx != NULL);
1655 
1656  invalidateSolution(lpi);
1657 
1658  assert( lpi->spx->preStrongbranchingBasisFreed() );
1659 
1660  SOPLEX_TRY( lpi->messagehdlr, (void) lpi->spx->setIntParam(SoPlex::OBJSENSE, objsen == SCIP_OBJSEN_MINIMIZE ? SoPlex::OBJSENSE_MINIMIZE : SoPlex::OBJSENSE_MAXIMIZE ) );
1661 
1662  return SCIP_OKAY;
1663 }
1664 
1665 /** changes objective values of columns in the LP */
1667  SCIP_LPI* lpi, /**< LP interface structure */
1668  int ncols, /**< number of columns to change objective value for */
1669  const int* ind, /**< column indices to change objective value for */
1670  const SCIP_Real* obj /**< new objective values for columns */
1671  )
1672 {
1673  int i;
1674 
1675  SCIPdebugMessage("calling SCIPlpiChgObj()\n");
1676 
1677  assert(lpi != NULL);
1678  assert(lpi->spx != NULL);
1679  assert(ind != NULL);
1680  assert(obj != NULL);
1681 
1682  invalidateSolution(lpi);
1683 
1684  assert( lpi->spx->preStrongbranchingBasisFreed() );
1685 
1686  try
1687  {
1688  for( i = 0; i < ncols; ++i )
1689  {
1690  assert(0 <= ind[i] && ind[i] < lpi->spx->numColsReal());
1691  lpi->spx->changeObjReal(ind[i], obj[i]);
1692  }
1693  }
1694 #ifndef NDEBUG
1695  catch( const SPxException& x )
1696  {
1697  std::string s = x.what();
1698  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1699 #else
1700  catch( const SPxException& )
1701  {
1702 #endif
1703  return SCIP_LPERROR;
1704  }
1705 
1706  return SCIP_OKAY;
1707 }
1708 
1709 /** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
1711  SCIP_LPI* lpi, /**< LP interface structure */
1712  int row, /**< row number to scale */
1713  SCIP_Real scaleval /**< scaling multiplier */
1714  )
1715 {
1716  SCIP_Real lhs;
1717  SCIP_Real rhs;
1718 
1719  SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
1720 
1721  assert(lpi != NULL);
1722  assert(lpi->spx != NULL);
1723  assert(scaleval != 0.0);
1724 
1725  try
1726  {
1727  invalidateSolution(lpi);
1728 
1729  assert( lpi->spx->preStrongbranchingBasisFreed() );
1730 
1731  /* get the row vector and the row's sides */
1732 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1733  SVector rowvec = lpi->spx->rowVectorRealInternal(row);
1734 #else
1735  SVector rowvec = lpi->spx->rowVectorReal(row);
1736 #endif
1737  lhs = lpi->spx->lhsReal(row);
1738  rhs = lpi->spx->rhsReal(row);
1739 
1740  /* scale the row vector */
1741  rowvec *= scaleval;
1742 
1743  /* adjust the sides */
1744  if( lhs > -lpi->spx->realParam(SoPlex::INFTY) )
1745  lhs *= scaleval;
1746  else if( scaleval < 0.0 )
1747  lhs = lpi->spx->realParam(SoPlex::INFTY);
1748  if( rhs < lpi->spx->realParam(SoPlex::INFTY) )
1749  rhs *= scaleval;
1750  else if( scaleval < 0.0 )
1751  rhs = -lpi->spx->realParam(SoPlex::INFTY);
1752  if( scaleval < 0.0 )
1753  {
1754  SCIP_Real oldlhs = lhs;
1755  lhs = rhs;
1756  rhs = oldlhs;
1757  }
1758 
1759  /* create the new row */
1760  LPRow lprow(lhs, rowvec, rhs);
1761 
1762  /* change the row in the LP */
1763  lpi->spx->changeRowReal(row, lprow);
1764  assert(lpi->spx->lhsReal(row) <= lpi->spx->rhsReal(row));
1765  }
1766 #ifndef NDEBUG
1767  catch( const SPxException& x )
1768  {
1769  std::string s = x.what();
1770  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1771 #else
1772  catch( const SPxException& )
1773  {
1774 #endif
1775  return SCIP_LPERROR;
1776  }
1777 
1778  return SCIP_OKAY;
1779 }
1780 
1781 /** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
1782  * are divided by the scalar; for negative scalars, the column's bounds are switched
1783  */
1785  SCIP_LPI* lpi, /**< LP interface structure */
1786  int col, /**< column number to scale */
1787  SCIP_Real scaleval /**< scaling multiplier */
1788  )
1789 {
1790  SCIP_Real obj;
1791  SCIP_Real lb;
1792  SCIP_Real ub;
1793 
1794  SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
1795 
1796  assert(lpi != NULL);
1797  assert(lpi->spx != NULL);
1798  assert(scaleval != 0.0);
1799 
1800  try
1801  {
1802  invalidateSolution(lpi);
1803 
1804  assert( lpi->spx->preStrongbranchingBasisFreed() );
1805 
1806  /* get the col vector and the col's bounds and objective value */
1807 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1808  SVector colvec = lpi->spx->colVectorRealInternal(col);
1809 #else
1810  SVector colvec = lpi->spx->colVectorReal(col);
1811 #endif
1812  obj = lpi->spx->objReal(col);
1813  lb = lpi->spx->lowerReal(col);
1814  ub = lpi->spx->upperReal(col);
1815 
1816  /* scale the col vector */
1817  colvec *= scaleval;
1818 
1819  /* scale the objective value */
1820  obj *= scaleval;
1821 
1822  /* adjust the bounds */
1823  if( lb > -lpi->spx->realParam(SoPlex::INFTY) )
1824  lb /= scaleval;
1825  else if( scaleval < 0.0 )
1826  lb = lpi->spx->realParam(SoPlex::INFTY);
1827  if( ub < lpi->spx->realParam(SoPlex::INFTY) )
1828  ub /= scaleval;
1829  else if( scaleval < 0.0 )
1830  ub = -lpi->spx->realParam(SoPlex::INFTY);
1831  if( scaleval < 0.0 )
1832  {
1833  SCIP_Real oldlb = lb;
1834  lb = ub;
1835  ub = oldlb;
1836  }
1837 
1838  /* create the new col (in LPCol's constructor, the upper bound is given first!) */
1839  LPCol lpcol(obj, colvec, ub, lb);
1840 
1841  /* change the col in the LP */
1842  lpi->spx->changeColReal(col, lpcol);
1843  assert(lpi->spx->lowerReal(col) <= lpi->spx->upperReal(col));
1844  }
1845 #ifndef NDEBUG
1846  catch( const SPxException& x )
1847  {
1848  std::string s = x.what();
1849  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1850 #else
1851  catch( const SPxException& )
1852  {
1853 #endif
1854  return SCIP_LPERROR;
1855  }
1856 
1857  return SCIP_OKAY;
1858 }
1859 
1860 /**@} */
1861 
1862 
1863 
1864 
1865 /*
1866  * Data Accessing Methods
1867  */
1868 
1869 /**@name Data Accessing Methods */
1870 /**@{ */
1871 
1872 /** gets the number of rows in the LP */
1874  SCIP_LPI* lpi, /**< LP interface structure */
1875  int* nrows /**< pointer to store the number of rows */
1876  )
1877 {
1878  SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
1879 
1880  assert(lpi != NULL);
1881  assert(lpi->spx != NULL);
1882  assert(nrows != NULL);
1883 
1884  *nrows = lpi->spx->numRowsReal();
1885 
1886  return SCIP_OKAY;
1887 }
1888 
1889 /** gets the number of columns in the LP */
1891  SCIP_LPI* lpi, /**< LP interface structure */
1892  int* ncols /**< pointer to store the number of cols */
1893  )
1894 {
1895  SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
1896 
1897  assert(lpi != NULL);
1898  assert(lpi->spx != NULL);
1899  assert(ncols != NULL);
1900 
1901  *ncols = lpi->spx->numColsReal();
1902 
1903  return SCIP_OKAY;
1904 }
1905 
1906 /** gets the number of nonzero elements in the LP constraint matrix */
1908  SCIP_LPI* lpi, /**< LP interface structure */
1909  int* nnonz /**< pointer to store the number of nonzeros */
1910  )
1911 {
1912  int i;
1913 
1914  SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
1915 
1916  assert(lpi != NULL);
1917  assert(lpi->spx != NULL);
1918  assert(nnonz != NULL);
1919 
1920  /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
1921  *nnonz = 0;
1922  if( lpi->spx->numRowsReal() < lpi->spx->numColsReal() )
1923  {
1924  for( i = 0; i < lpi->spx->numRowsReal(); ++i )
1925 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1926  (*nnonz) += lpi->spx->rowVectorRealInternal(i).size();
1927 #else
1928  (*nnonz) += lpi->spx->rowVectorReal(i).size();
1929 #endif
1930  }
1931  else
1932  {
1933  for( i = 0; i < lpi->spx->numColsReal(); ++i )
1934 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1935  (*nnonz) += lpi->spx->colVectorRealInternal(i).size();
1936 #else
1937  (*nnonz) += lpi->spx->colVectorReal(i).size();
1938 #endif
1939  }
1940 
1941  return SCIP_OKAY;
1942 }
1943 
1944 /** gets columns from LP problem object; the arrays have to be large enough to store all values
1945  * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
1946  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1947  */
1949  SCIP_LPI* lpi, /**< LP interface structure */
1950  int firstcol, /**< first column to get from LP */
1951  int lastcol, /**< last column to get from LP */
1952  SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
1953  SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
1954  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1955  int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1956  int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1957  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1958  )
1959 {
1960  int i;
1961  int j;
1962 
1963  SCIPdebugMessage("calling SCIPlpiGetCols()\n");
1964 
1965  assert(lpi != NULL);
1966  assert(lpi->spx != NULL);
1967  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
1968  assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
1969  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1970 
1971  if( lb != NULL )
1972  {
1973 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
1974  if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
1975  {
1976  DVector lbvec(lpi->spx->numColsReal());
1977  DVector ubvec(lpi->spx->numColsReal());
1978  lpi->spx->getLowerReal(lbvec);
1979  lpi->spx->getUpperReal(ubvec);
1980  for( i = firstcol; i <= lastcol; ++i )
1981  {
1982  lb[i-firstcol] = lbvec[i];
1983  ub[i-firstcol] = ubvec[i];
1984  }
1985  }
1986  else
1987  {
1988  const Vector& lbvec = lpi->spx->lowerRealInternal();
1989  const Vector& ubvec = lpi->spx->upperRealInternal();
1990  for( i = firstcol; i <= lastcol; ++i )
1991  {
1992  lb[i-firstcol] = lbvec[i];
1993  ub[i-firstcol] = ubvec[i];
1994  }
1995  }
1996 #else
1997  const Vector& lbvec = lpi->spx->lowerReal();
1998  const Vector& ubvec = lpi->spx->upperReal();
1999 
2000  for( i = firstcol; i <= lastcol; ++i )
2001  {
2002  lb[i-firstcol] = lbvec[i];
2003  ub[i-firstcol] = ubvec[i];
2004  }
2005 #endif
2006  }
2007 
2008  if( nnonz != NULL )
2009  {
2010  *nnonz = 0;
2011  for( i = firstcol; i <= lastcol; ++i )
2012  {
2013  beg[i-firstcol] = *nnonz;
2014 
2015 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2016  if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2017  {
2018  DSVector cvec;
2019  lpi->spx->getColVectorReal(i, cvec);
2020  for( j = 0; j < cvec.size(); ++j )
2021  {
2022  ind[*nnonz] = cvec.index(j);
2023  val[*nnonz] = cvec.value(j);
2024  (*nnonz)++;
2025  }
2026  }
2027  else
2028  {
2029  const SVector& cvec = lpi->spx->colVectorRealInternal(i);
2030  for( j = 0; j < cvec.size(); ++j )
2031  {
2032  ind[*nnonz] = cvec.index(j);
2033  val[*nnonz] = cvec.value(j);
2034  (*nnonz)++;
2035  }
2036  }
2037 #else
2038  const SVector& cvec = lpi->spx->colVectorReal(i);
2039  for( j = 0; j < cvec.size(); ++j )
2040  {
2041  ind[*nnonz] = cvec.index(j);
2042  val[*nnonz] = cvec.value(j);
2043  (*nnonz)++;
2044  }
2045 #endif
2046  }
2047  }
2048 
2049  return SCIP_OKAY;
2050 }
2051 
2052 /** gets rows from LP problem object; the arrays have to be large enough to store all values.
2053  * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
2054  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2055  */
2057  SCIP_LPI* lpi, /**< LP interface structure */
2058  int firstrow, /**< first row to get from LP */
2059  int lastrow, /**< last row to get from LP */
2060  SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
2061  SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
2062  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2063  int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
2064  int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
2065  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2066  )
2067 {
2068  int i;
2069  int j;
2070 
2071  SCIPdebugMessage("calling SCIPlpiGetRows()\n");
2072 
2073  assert(lpi != NULL);
2074  assert(lpi->spx != NULL);
2075  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
2076  assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
2077  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2078 
2079  if( lhs != NULL )
2080  {
2081 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2082  if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2083  {
2084  DVector lhsvec(lpi->spx->numRowsReal());
2085  DVector rhsvec(lpi->spx->numRowsReal());
2086  lpi->spx->getLhsReal(lhsvec);
2087  lpi->spx->getRhsReal(rhsvec);
2088  for( i = firstrow; i <= lastrow; ++i )
2089  {
2090  lhs[i-firstrow] = lhsvec[i];
2091  rhs[i-firstrow] = rhsvec[i];
2092  }
2093  }
2094  else
2095  {
2096  const Vector& lhsvec = lpi->spx->lhsRealInternal();
2097  const Vector& rhsvec = lpi->spx->rhsRealInternal();
2098  for( i = firstrow; i <= lastrow; ++i )
2099  {
2100  lhs[i-firstrow] = lhsvec[i];
2101  rhs[i-firstrow] = rhsvec[i];
2102  }
2103  }
2104 #else
2105  const Vector& lhsvec = lpi->spx->lhsReal();
2106  const Vector& rhsvec = lpi->spx->rhsReal();
2107  for( i = firstrow; i <= lastrow; ++i )
2108  {
2109  lhs[i-firstrow] = lhsvec[i];
2110  rhs[i-firstrow] = rhsvec[i];
2111  }
2112 #endif
2113  }
2114 
2115  if( nnonz != NULL )
2116  {
2117  *nnonz = 0;
2118  for( i = firstrow; i <= lastrow; ++i )
2119  {
2120  beg[i-firstrow] = *nnonz;
2121 
2122 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2123  if( lpi->spx->boolParam(SoPlex::PERSISTENTSCALING) )
2124  {
2125  DSVector rvec;
2126  lpi->spx->getRowVectorReal(i, rvec);
2127  for( j = 0; j < rvec.size(); ++j )
2128  {
2129  ind[*nnonz] = rvec.index(j);
2130  val[*nnonz] = rvec.value(j);
2131  (*nnonz)++;
2132  }
2133  }
2134  else
2135  {
2136  const SVector& rvec = lpi->spx->rowVectorRealInternal(i);
2137  for( j = 0; j < rvec.size(); ++j )
2138  {
2139  ind[*nnonz] = rvec.index(j);
2140  val[*nnonz] = rvec.value(j);
2141  (*nnonz)++;
2142  }
2143  }
2144 #else
2145  const SVector& rvec = lpi->spx->rowVectorReal(i);
2146  for( j = 0; j < rvec.size(); ++j )
2147  {
2148  ind[*nnonz] = rvec.index(j);
2149  val[*nnonz] = rvec.value(j);
2150  (*nnonz)++;
2151  }
2152 #endif
2153  }
2154  }
2155 
2156  return SCIP_OKAY;
2157 }
2158 
2159 /** gets column names */
2161  SCIP_LPI* lpi, /**< LP interface structure */
2162  int firstcol, /**< first column to get name from LP */
2163  int lastcol, /**< last column to get name from LP */
2164  char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
2165  char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
2166  int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
2167  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2168  )
2169 {
2170  assert( lpi != NULL );
2171  assert( lpi->spx != NULL );
2172  assert( colnames != NULL || namestoragesize == 0 );
2173  assert( namestorage != NULL || namestoragesize == 0 );
2174  assert( namestoragesize >= 0 );
2175  assert( storageleft != NULL );
2176  assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal() );
2177 
2178  SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
2179 
2180 // lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
2181 
2182  return SCIP_OKAY;
2183 }
2184 
2185 /** gets row names */
2187  SCIP_LPI* lpi, /**< LP interface structure */
2188  int firstrow, /**< first row to get name from LP */
2189  int lastrow, /**< last row to get name from LP */
2190  char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
2191  char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
2192  int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
2193  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2194  )
2195 {
2196  assert( lpi != NULL );
2197  assert( lpi->spx != NULL );
2198  assert( rownames != NULL || namestoragesize == 0 );
2199  assert( namestorage != NULL || namestoragesize == 0 );
2200  assert( namestoragesize >= 0 );
2201  assert( storageleft != NULL );
2202  assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal() );
2203 
2204  SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
2205 
2206 // lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
2207 
2208  return SCIP_OKAY;
2209 }
2210 
2211 /** gets objective sense of the LP */
2213  SCIP_LPI* lpi, /**< LP interface structure */
2214  SCIP_OBJSEN* objsen /**< pointer to store objective sense */
2215  )
2216 {
2217  SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
2218 
2219  assert(lpi != NULL);
2220  assert(lpi->spx != NULL);
2221  assert(objsen != NULL);
2222 
2223  *objsen = (lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
2224 
2225  return SCIP_OKAY;
2226 }
2227 
2228 /** gets objective coefficients from LP problem object */
2230  SCIP_LPI* lpi, /**< LP interface structure */
2231  int firstcol, /**< first column to get objective coefficient for */
2232  int lastcol, /**< last column to get objective coefficient for */
2233  SCIP_Real* vals /**< array to store objective coefficients */
2234  )
2235 {
2236  int i;
2237 
2238  SCIPdebugMessage("calling SCIPlpiGetObj()\n");
2239 
2240  assert(lpi != NULL);
2241  assert(lpi->spx != NULL);
2242  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
2243  assert(vals != NULL);
2244 
2245  for( i = firstcol; i <= lastcol; ++i )
2246  vals[i-firstcol] = lpi->spx->objReal(i);
2247 
2248  return SCIP_OKAY;
2249 }
2250 
2251 /** gets current bounds from LP problem object */
2253  SCIP_LPI* lpi, /**< LP interface structure */
2254  int firstcol, /**< first column to get objective value for */
2255  int lastcol, /**< last column to get objective value for */
2256  SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
2257  SCIP_Real* ubs /**< array to store upper bound values, or NULL */
2258  )
2259 {
2260  int i;
2261 
2262  SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
2263 
2264  assert(lpi != NULL);
2265  assert(lpi->spx != NULL);
2266  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->numColsReal());
2267 
2268  for( i = firstcol; i <= lastcol; ++i )
2269  {
2270  if( lbs != NULL )
2271  lbs[i-firstcol] = lpi->spx->lowerReal(i);
2272  if( ubs != NULL )
2273  ubs[i-firstcol] = lpi->spx->upperReal(i);
2274  }
2275 
2276  return SCIP_OKAY;
2277 }
2278 
2279 /** gets current row sides from LP problem object */
2281  SCIP_LPI* lpi, /**< LP interface structure */
2282  int firstrow, /**< first row to get sides for */
2283  int lastrow, /**< last row to get sides for */
2284  SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2285  SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2286  )
2287 {
2288  int i;
2289 
2290  SCIPdebugMessage("calling SCIPlpiGetSides()\n");
2291 
2292  assert(lpi != NULL);
2293  assert(lpi->spx != NULL);
2294  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->numRowsReal());
2295 
2296  for( i = firstrow; i <= lastrow; ++i )
2297  {
2298  if( lhss != NULL )
2299  lhss[i-firstrow] = lpi->spx->lhsReal(i);
2300  if( rhss != NULL )
2301  rhss[i-firstrow] = lpi->spx->rhsReal(i);
2302  }
2303 
2304  return SCIP_OKAY;
2305 }
2306 
2307 /** gets a single coefficient */
2309  SCIP_LPI* lpi, /**< LP interface structure */
2310  int row, /**< row number of coefficient */
2311  int col, /**< column number of coefficient */
2312  SCIP_Real* val /**< pointer to store the value of the coefficient */
2313  )
2314 {
2315  SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
2316 
2317  assert(lpi != NULL);
2318  assert(lpi->spx != NULL);
2319  assert(0 <= col && col < lpi->spx->numColsReal());
2320  assert(0 <= row && row < lpi->spx->numRowsReal());
2321  assert(val != NULL);
2322 
2323 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2324  *val = lpi->spx->coefReal(row, col);
2325 #else
2326  *val = lpi->spx->colVectorReal(col)[row];
2327 #endif
2328 
2329  return SCIP_OKAY;
2330 }
2331 
2332 /**@} */
2333 
2334 
2335 
2336 
2337 /*
2338  * Solving Methods
2339  */
2340 
2341 /**@name Solving Methods */
2342 /**@{ */
2343 
2344 /** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
2345 static
2347  SCIP_LPI* lpi /**< LP interface structure */
2348  )
2350  assert( lpi != NULL );
2351  assert( lpi->spx != NULL );
2352 
2353  SPxOut::Verbosity verbosity;
2354  /* store and set verbosity */
2355  verbosity = lpi->spx->spxout.getVerbosity();
2356  lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2357 
2358  SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows\n", lpi->spx->numColsReal(), lpi->spx->numRowsReal());
2359 
2360  invalidateSolution(lpi);
2361 
2362  assert( lpi->spx->preStrongbranchingBasisFreed() );
2363 
2364 #ifdef SCIP_WITH_LPSCHECK
2365  lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2366 #endif
2367 
2368  /* delete starting basis if solving from scratch */
2369  if( lpi->spx->getFromScratch() )
2370  {
2371  try
2372  {
2373  lpi->spx->clearBasis();
2374  }
2375 #ifndef NDEBUG
2376  catch(const SPxException& x)
2377  {
2378  std::string s = x.what();
2379  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2380 #else
2381  catch(const SPxException&)
2382  {
2383 #endif
2384  assert( lpi->spx->status() != SPxSolver::OPTIMAL );
2385  return SCIP_LPERROR;
2386  }
2387  }
2388  assert(!lpi->spx->getFromScratch() || lpi->spx->status() == SPxSolver::NO_PROBLEM);
2389 
2390  SPxSolver::Status status = lpi->spx->doSolve();
2391  SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->status(), lpi->spx->basisStatus());
2392  lpi->solved = TRUE;
2393 
2394  /* restore verbosity */
2395  lpi->spx->spxout.setVerbosity(verbosity);
2396 
2397  switch( status )
2398  {
2399  case SPxSolver::ABORT_TIME:
2400  case SPxSolver::ABORT_ITER:
2401  case SPxSolver::ABORT_VALUE:
2402  case SPxSolver::SINGULAR:
2403  case SPxSolver::REGULAR:
2404  case SPxSolver::UNKNOWN:
2405  case SPxSolver::OPTIMAL:
2406 #if SOPLEX_APIVERSION >= 3
2407  case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2408 #endif
2409  case SPxSolver::UNBOUNDED:
2410  case SPxSolver::INFEASIBLE:
2411  return SCIP_OKAY;
2412  default:
2413  return SCIP_LPERROR;
2414  } /*lint !e788*/
2415 }
2416 
2417 /** calls primal simplex to solve the LP */
2419  SCIP_LPI* lpi /**< LP interface structure */
2420  )
2422  SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2423 
2424  assert(lpi != NULL);
2425  assert(lpi->spx != NULL);
2426 
2427  (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_PRIMAL);
2428  return spxSolve(lpi);
2429 }
2430 
2431 /** calls dual simplex to solve the LP */
2433  SCIP_LPI* lpi /**< LP interface structure */
2434  )
2436  SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2437 
2438  assert(lpi != NULL);
2439  assert(lpi->spx != NULL);
2440 
2441  (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2442  return spxSolve(lpi);
2443 }
2444 
2445 /** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
2447  SCIP_LPI* lpi, /**< LP interface structure */
2448  SCIP_Bool crossover /**< perform crossover */
2449  )
2450 { /*lint --e{715}*/
2451  assert(lpi != NULL);
2452  assert(lpi->spx != NULL);
2453 
2454  SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
2455 
2456  /* Since SoPlex does not support barrier we switch to DUAL */
2457  return SCIPlpiSolveDual(lpi);
2458 }
2459 
2460 /** start strong branching - call before any strongbranching */
2462  SCIP_LPI* lpi /**< LP interface structure */
2463  )
2465  assert(lpi != NULL);
2466  assert(lpi->spx != NULL);
2467 
2468  assert( lpi->spx->preStrongbranchingBasisFreed() );
2469  lpi->spx->savePreStrongbranchingBasis();
2470 
2471  return SCIP_OKAY;
2472 }
2473 
2474 /** end strong branching - call after any strongbranching */
2476  SCIP_LPI* lpi /**< LP interface structure */
2477  )
2479  assert(lpi != NULL);
2480  assert(lpi->spx != NULL);
2481 
2482  assert( ! lpi->spx->preStrongbranchingBasisFreed() );
2483  lpi->spx->restorePreStrongbranchingBasis();
2484  lpi->spx->freePreStrongbranchingBasis();
2485 
2486  return SCIP_OKAY;
2487 }
2488 
2489 /** performs strong branching iterations on one arbitrary candidate */
2490 static
2492  SCIP_LPI* lpi, /**< LP interface structure */
2493  int col, /**< column to apply strong branching on */
2494  SCIP_Real psol, /**< current primal solution value of column */
2495  int itlim, /**< iteration limit for strong branchings */
2496  SCIP_Real* down, /**< stores dual bound after branching column down */
2497  SCIP_Real* up, /**< stores dual bound after branching column up */
2498  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2499  * otherwise, it can only be used as an estimate value */
2500  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2501  * otherwise, it can only be used as an estimate value */
2502  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2503  )
2504 {
2505  assert(lpi != NULL);
2506  assert(lpi->spx != NULL);
2507 
2508  SPxSCIP* spx;
2509  SPxSolver::Status status;
2510  SCIP_Real oldlb;
2511  SCIP_Real oldub;
2512  SCIP_Real newlb;
2513  SCIP_Real newub;
2514  bool fromparentbasis;
2515  bool error;
2516  int oldItlim;
2517  SPxOut::Verbosity verbosity;
2518 
2519  /* store and set verbosity */
2520  verbosity = lpi->spx->spxout.getVerbosity();
2521  lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2522 
2523  SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
2524 
2525  assert(lpi != NULL);
2526  assert(lpi->spx != NULL);
2527  /* assert(down != NULL);
2528  * assert(up != NULL); temporary hack for cloud branching */
2529  assert(downvalid != NULL);
2530  assert(upvalid != NULL);
2531 
2532  spx = lpi->spx;
2533 #ifndef STRONGBRANCH_RESTOREBASIS
2534  fromparentbasis = false;
2535 #endif
2536  error = false;
2537  oldItlim = spx->intParam(SoPlex::ITERLIMIT);
2538 
2539  /* get current bounds of column */
2540  oldlb = spx->lowerReal(col);
2541  oldub = spx->upperReal(col);
2542 
2543  *downvalid = FALSE;
2544  *upvalid = FALSE;
2545 
2546  if( iter != NULL )
2547  *iter = 0;
2548 
2549  /* set the algorithm type to use dual simplex */
2550  (void) spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2551 
2552  /* down branch */
2553  newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
2554  if( newub >= oldlb - 0.5 && down != NULL )
2555  {
2556  SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
2557 
2558  spx->changeUpperReal(col, newub);
2559  assert(spx->lowerReal(col) <= spx->upperReal(col));
2560 
2561  (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2562  do
2563  {
2564 #ifndef STRONGBRANCH_RESTOREBASIS
2565  SCIP_Bool repeatstrongbranching;
2566 #endif
2567 #ifdef SCIP_WITH_LPSCHECK
2568  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2569 #endif
2570 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2571  status = spx->optimize();
2572 #else
2573  status = spx->solve();
2574 #endif
2575  SCIPdebugMessage(" --> Terminate with status %d\n", status);
2576  switch( status )
2577  {
2578  case SPxSolver::OPTIMAL:
2579  *down = spx->objValueReal();
2580  *downvalid = TRUE;
2581  SCIPdebugMessage(" --> Terminate with value %f\n", *down);
2582  break;
2583  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2584  case SPxSolver::ABORT_ITER:
2585  case SPxSolver::ABORT_CYCLING:
2586 #if SOPLEX_APIVERSION >= 3
2587  case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2588 #endif
2589  *down = spx->objValueReal();
2590  break;
2591  case SPxSolver::ABORT_VALUE:
2592  case SPxSolver::INFEASIBLE:
2593  *down = spx->getObjLimit();
2594  *downvalid = TRUE;
2595  break;
2596  default:
2597  error = true;
2598  break;
2599  } /*lint !e788*/
2600  if( iter != NULL )
2601  (*iter) += spx->numIterations();
2602 
2603 #ifdef STRONGBRANCH_RESTOREBASIS
2604  /* we restore the pre-strong-branching basis by default (and don't solve again) */
2605  assert( ! spx->preStrongbranchingBasisFreed() );
2606  spx->restorePreStrongbranchingBasis();
2607  fromparentbasis = false;
2608 #else
2609  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2610  * pre-strong-branching basis and try again with reduced iteration limit */
2611 #if SOPLEX_APIVERSION >= 3
2612  repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
2613  || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
2614 #else
2615  repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
2616  && !fromparentbasis && spx->numIterations() < itlim);
2617 #endif
2618  if( repeatstrongbranching )
2619  {
2620  SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n",
2621  itlim - spx->numIterations());
2622  spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2623  spx->restorePreStrongbranchingBasis();
2624  fromparentbasis = true;
2625  error = false;
2626  }
2627  /* otherwise don't solve again */
2628  else
2629  fromparentbasis = false;
2630 #endif
2631  }
2632  while( fromparentbasis );
2633 
2634  spx->changeUpperReal(col, oldub);
2635  assert(spx->lowerReal(col) <= spx->upperReal(col));
2636  }
2637  else if( down != NULL )
2638  {
2639  *down = spx->getObjLimit();
2640  *downvalid = TRUE;
2641  }
2642  else
2643  *downvalid = TRUE;
2644 
2645  /* up branch */
2646  if( !error )
2647  {
2648  newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
2649  if( newlb <= oldub + 0.5 && up != NULL )
2650  {
2651  SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
2652 
2653  spx->changeLowerReal(col, newlb);
2654  assert(spx->lowerReal(col) <= spx->upperReal(col));
2655 
2656  (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2657  do
2658  {
2659 #ifndef STRONGBRANCH_RESTOREBASIS
2660  SCIP_Bool repeatstrongbranching;
2661 #endif
2662 #ifdef SCIP_WITH_LPSCHECK
2663  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2664 #endif
2665 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
2666  status = spx->optimize();
2667 #else
2668  status = spx->solve();
2669 #endif
2670  SCIPdebugMessage(" --> Terminate with status %d\n", status);
2671  switch( status )
2672  {
2673  case SPxSolver::OPTIMAL:
2674  *up = spx->objValueReal();
2675  *upvalid = TRUE;
2676  SCIPdebugMessage(" --> Terminate with value %f\n", spx->objValueReal());
2677  break;
2678  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2679  case SPxSolver::ABORT_ITER:
2680  case SPxSolver::ABORT_CYCLING:
2681 #if SOPLEX_APIVERSION >= 3
2682  case SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS:
2683 #endif
2684  *up = spx->objValueReal();
2685  break;
2686  case SPxSolver::ABORT_VALUE:
2687  case SPxSolver::INFEASIBLE:
2688  *up = spx->getObjLimit();
2689  *upvalid = TRUE;
2690  break;
2691  default:
2692  error = true;
2693  break;
2694  } /*lint !e788*/
2695  if( iter != NULL )
2696  (*iter) += spx->numIterations();
2697 
2698 #ifdef STRONGBRANCH_RESTOREBASIS
2699  /* we restore the pre-strong-branching basis by default (and don't solve again) */
2700  assert( ! spx->preStrongbranchingBasisFreed() );
2701  spx->restorePreStrongbranchingBasis();
2702  fromparentbasis = false;
2703 #else
2704  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2705  * pre-strong-branching basis and try again with reduced iteration limit */
2706 #if SOPLEX_APIVERSION >= 3
2707  repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS
2708  || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim);
2709 #else
2710  repeatstrongbranching = ((status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR)
2711  && !fromparentbasis && spx->numIterations() < itlim);
2712 #endif
2713  if( repeatstrongbranching )
2714  {
2715  SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->numIterations());
2716  spx->restorePreStrongbranchingBasis();
2717  spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2718  error = false;
2719  fromparentbasis = true;
2720  }
2721  /* otherwise don't solve again */
2722  else
2723  fromparentbasis = false;
2724 #endif
2725  }
2726  while( fromparentbasis );
2727 
2728  spx->changeLowerReal(col, oldlb);
2729  assert(spx->lowerReal(col) <= spx->upperReal(col));
2730  }
2731  else if( up != NULL )
2732  {
2733  *up = spx->getObjLimit();
2734  *upvalid = TRUE;
2735  }
2736  else
2737  *upvalid = TRUE;
2738  }
2739 
2740  /* reset old iteration limit */
2741  (void) spx->setIntParam(SoPlex::ITERLIMIT, oldItlim);
2742 
2743  /* restore verbosity */
2744  lpi->spx->spxout.setVerbosity(verbosity);
2745 
2746  if( error )
2747  {
2748  SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status)); /*lint !e644*/
2749  return SCIP_LPERROR;
2750  }
2751 
2752  return SCIP_OKAY;
2753 }
2754 
2755 /** performs strong branching iterations on one @b fractional candidate */
2757  SCIP_LPI* lpi, /**< LP interface structure */
2758  int col, /**< column to apply strong branching on */
2759  SCIP_Real psol, /**< fractional current primal solution value of column */
2760  int itlim, /**< iteration limit for strong branchings */
2761  SCIP_Real* down, /**< stores dual bound after branching column down */
2762  SCIP_Real* up, /**< stores dual bound after branching column up */
2763  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2764  * otherwise, it can only be used as an estimate value */
2765  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2766  * otherwise, it can only be used as an estimate value */
2767  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2768  )
2769 {
2770  SCIP_RETCODE retcode;
2771 
2772  /* pass call on to lpiStrongbranch() */
2773  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2774 
2775  /* pass SCIP_LPERROR to SCIP without a back trace */
2776  if( retcode == SCIP_LPERROR )
2777  return SCIP_LPERROR;
2778 
2779  /* evaluate retcode */
2780  SCIP_CALL( retcode );
2781 
2782  return SCIP_OKAY;
2783 }
2784 
2785 /** performs strong branching iterations on given @b fractional candidates */
2787  SCIP_LPI* lpi, /**< LP interface structure */
2788  int* cols, /**< columns to apply strong branching on */
2789  int ncols, /**< number of columns */
2790  SCIP_Real* psols, /**< fractional current primal solution values of columns */
2791  int itlim, /**< iteration limit for strong branchings */
2792  SCIP_Real* down, /**< stores dual bounds after branching columns down */
2793  SCIP_Real* up, /**< stores dual bounds after branching columns up */
2794  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2795  * otherwise, they can only be used as an estimate values */
2796  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2797  * otherwise, they can only be used as an estimate values */
2798  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2799  )
2800 {
2801  SCIP_RETCODE retcode;
2802 
2803  assert( cols != NULL );
2804  assert( psols != NULL );
2805  assert( down != NULL );
2806  assert( up != NULL );
2807  assert( downvalid != NULL );
2808  assert( upvalid != NULL );
2809  assert( down != NULL );
2810 
2811  if ( iter != NULL )
2812  *iter = 0;
2813 
2814  for (int j = 0; j < ncols; ++j)
2815  {
2816  /* pass call on to lpiStrongbranch() */
2817  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2818 
2819  /* pass SCIP_LPERROR to SCIP without a back trace */
2820  if( retcode == SCIP_LPERROR )
2821  return SCIP_LPERROR;
2822 
2823  /* evaluate retcode */
2824  SCIP_CALL( retcode );
2825  }
2826  return SCIP_OKAY;
2827 }
2828 
2829 /** performs strong branching iterations on one candidate with @b integral value */
2831  SCIP_LPI* lpi, /**< LP interface structure */
2832  int col, /**< column to apply strong branching on */
2833  SCIP_Real psol, /**< current integral primal solution value of column */
2834  int itlim, /**< iteration limit for strong branchings */
2835  SCIP_Real* down, /**< stores dual bound after branching column down */
2836  SCIP_Real* up, /**< stores dual bound after branching column up */
2837  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2838  * otherwise, it can only be used as an estimate value */
2839  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2840  * otherwise, it can only be used as an estimate value */
2841  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2842  )
2843 {
2844  SCIP_RETCODE retcode;
2845 
2846  /* pass call on to lpiStrongbranch() */
2847  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2848 
2849  /* pass SCIP_LPERROR to SCIP without a back trace */
2850  if( retcode == SCIP_LPERROR )
2851  return SCIP_LPERROR;
2852 
2853  /* evaluate retcode */
2854  SCIP_CALL( retcode );
2855 
2856  return SCIP_OKAY;
2857 }
2858 
2859 /** performs strong branching iterations on given candidates with @b integral values */
2861  SCIP_LPI* lpi, /**< LP interface structure */
2862  int* cols, /**< columns to apply strong branching on */
2863  int ncols, /**< number of columns */
2864  SCIP_Real* psols, /**< current integral primal solution values of columns */
2865  int itlim, /**< iteration limit for strong branchings */
2866  SCIP_Real* down, /**< stores dual bounds after branching columns down */
2867  SCIP_Real* up, /**< stores dual bounds after branching columns up */
2868  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2869  * otherwise, they can only be used as an estimate values */
2870  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2871  * otherwise, they can only be used as an estimate values */
2872  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2873  )
2874 {
2875  SCIP_RETCODE retcode;
2876 
2877  assert( cols != NULL );
2878  assert( psols != NULL );
2879  assert( down != NULL );
2880  assert( up != NULL );
2881  assert( downvalid != NULL );
2882  assert( upvalid != NULL );
2883  assert( down != NULL );
2884 
2885  if ( iter != NULL )
2886  *iter = 0;
2887 
2888  for (int j = 0; j < ncols; ++j)
2889  {
2890  /* pass call on to lpiStrongbranch() */
2891  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2892 
2893  /* pass SCIP_LPERROR to SCIP without a back trace */
2894  if( retcode == SCIP_LPERROR )
2895  return SCIP_LPERROR;
2896 
2897  /* evaluate retcode */
2898  SCIP_CALL( retcode );
2899  }
2900 
2901  return SCIP_OKAY;
2902 }
2903 /**@} */
2904 
2905 
2906 
2907 
2908 /*
2909  * Solution Information Methods
2910  */
2911 
2912 /**@name Solution Information Methods */
2913 /**@{ */
2914 
2915 /** returns whether a solve method was called after the last modification of the LP */
2917  SCIP_LPI* lpi /**< LP interface structure */
2918  )
2920  assert(lpi != NULL);
2921 
2922  return lpi->solved;
2923 }
2924 
2925 /** gets information about primal and dual feasibility of the current LP solution
2926  *
2927  * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
2928  * returns true. If the LP is changed, this information might be invalidated.
2929  *
2930  * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
2931  * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
2932  * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
2933  * the problem might actually be feasible).
2934  */
2936  SCIP_LPI* lpi, /**< LP interface structure */
2937  SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
2938  SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
2939  )
2940 {
2941  SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
2942 
2943  assert(lpi != NULL);
2944  assert(primalfeasible != NULL);
2945  assert(dualfeasible != NULL);
2946 
2947  *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
2948  *dualfeasible = SCIPlpiIsDualFeasible(lpi);
2949 
2950  return SCIP_OKAY;
2951 }
2952 
2953 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
2954  * this does not necessarily mean, that the solver knows and can return the primal ray
2955  */
2957  SCIP_LPI* lpi /**< LP interface structure */
2958  )
2960  SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
2961 
2962  assert(lpi != NULL);
2963  assert(lpi->spx != NULL);
2964 
2965  return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2966 }
2967 
2968 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
2969  * and the solver knows and can return the primal ray
2970  */
2972  SCIP_LPI* lpi /**< LP interface structure */
2973  )
2975  SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
2976 
2977  assert(lpi != NULL);
2978  assert(lpi->spx != NULL);
2979 
2980  return lpi->spx->hasPrimalRay();
2981 }
2982 
2983 /** returns TRUE iff LP is proven to be primal unbounded */
2985  SCIP_LPI* lpi /**< LP interface structure */
2986  )
2988  SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
2989 
2990  assert(lpi != NULL);
2991  assert(lpi->spx != NULL);
2992 
2993  assert(lpi->spx->status() != SPxSolver::UNBOUNDED || lpi->spx->basisStatus() == SPxBasis::UNBOUNDED);
2994 
2995  /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
2996  * feasible point; hence we have to check the perturbation
2997  */
2998  return lpi->spx->status() == SPxSolver::UNBOUNDED;
2999 }
3000 
3001 /** returns TRUE iff LP is proven to be primal infeasible */
3003  SCIP_LPI* lpi /**< LP interface structure */
3004  )
3006  SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
3007 
3008  assert(lpi != NULL);
3009  assert(lpi->spx != NULL);
3010 
3011  return (lpi->spx->status() == SPxSolver::INFEASIBLE);
3012 }
3013 
3014 /** returns TRUE iff LP is proven to be primal feasible */
3016  SCIP_LPI* lpi /**< LP interface structure */
3017  )
3019  SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
3020 
3021  assert(lpi != NULL);
3022  assert(lpi->spx != NULL);
3023 
3024  return lpi->spx->basisStatus() == SPxBasis::OPTIMAL || lpi->spx->basisStatus() == SPxBasis::PRIMAL;
3025 }
3026 
3027 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3028  * this does not necessarily mean, that the solver knows and can return the dual ray
3029  */
3031  SCIP_LPI* lpi /**< LP interface structure */
3032  )
3034  SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
3035 
3036  assert(lpi != NULL);
3037  assert(lpi->spx != NULL);
3038 
3039  return (lpi->spx->status() == SPxSolver::INFEASIBLE);
3040 }
3041 
3042 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3043  * and the solver knows and can return the dual ray
3044  */
3046  SCIP_LPI* lpi /**< LP interface structure */
3047  )
3049  SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
3050 
3051  assert(lpi != NULL);
3052  assert(lpi->spx != NULL);
3053 
3054  return lpi->spx->hasDualFarkas();
3055 }
3056 
3057 /** returns TRUE iff LP is dual unbounded */
3059  SCIP_LPI* lpi /**< LP interface structure */
3060  )
3062  SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
3063 
3064  assert(lpi != NULL);
3065  assert(lpi->spx != NULL);
3066 
3067  return lpi->spx->status() == SPxSolver::INFEASIBLE && lpi->spx->basisStatus() == SPxBasis::DUAL;
3068 }
3069 
3070 /** returns TRUE iff LP is dual infeasible */
3072  SCIP_LPI* lpi /**< LP interface structure */
3073  )
3075  SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
3076 
3077  assert(lpi != NULL);
3078  assert(lpi->spx != NULL);
3079 
3080  return (lpi->spx->status() == SPxSolver::UNBOUNDED);
3081 }
3082 
3083 /** returns TRUE iff LP is proven to be dual feasible */
3085  SCIP_LPI* lpi /**< LP interface structure */
3086  )
3088  SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
3089 
3090  assert(lpi != NULL);
3091  assert(lpi->spx != NULL);
3092 
3093  return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL) || lpi->spx->basisStatus() == SPxBasis::DUAL;
3094 }
3095 
3096 /** returns TRUE iff LP was solved to optimality */
3098  SCIP_LPI* lpi /**< LP interface structure */
3099  )
3101  SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
3102 
3103  assert(lpi != NULL);
3104  assert(lpi->spx != NULL);
3105  assert((lpi->spx->basisStatus() == SPxBasis::OPTIMAL)
3107 
3108  return (lpi->spx->status() == SPxSolver::OPTIMAL);
3109 }
3110 
3111 /** returns TRUE iff current LP solution is stable
3112  *
3113  * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3114  * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3115  * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3116  * SCIPlpiIsStable() should return false.
3117  */
3119  SCIP_LPI* lpi /**< LP interface structure */
3120  )
3122  SCIPdebugMessage("calling SCIPlpiIsStable()\n");
3123 
3124  assert(lpi != NULL);
3125  assert(lpi->spx != NULL);
3126 
3127  if( lpi->spx->status() == SPxSolver::ERROR || lpi->spx->status() == SPxSolver::SINGULAR )
3128  return FALSE;
3129 #if SOPLEX_APIVERSION >= 3
3130  if( lpi->spx->status() == SPxSolver::OPTIMAL_UNSCALED_VIOLATIONS )
3131  return FALSE;
3132 #endif
3133  /* only if we have a regular basis and the condition limit is set, we compute the condition number of the basis;
3134  * everything above the specified threshold is then counted as instable
3135  */
3136  if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
3137  {
3138  SCIP_RETCODE retcode;
3139  SCIP_Real kappa;
3140 
3142  if( retcode != SCIP_OKAY )
3143  {
3144  SCIPABORT();
3145  }
3146  assert(kappa != SCIP_INVALID); /*lint !e777*/
3147 
3148  if( kappa > lpi->conditionlimit )
3149  return FALSE;
3150  }
3151  return TRUE;
3152 }
3153 
3154 /** returns TRUE iff the objective limit was reached */
3156  SCIP_LPI* lpi /**< LP interface structure */
3157  )
3159  SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3160 
3161  assert(lpi != NULL);
3162  assert(lpi->spx != NULL);
3163 
3164  return (lpi->spx->status() == SPxSolver::ABORT_VALUE);
3165 }
3166 
3167 /** returns TRUE iff the iteration limit was reached */
3169  SCIP_LPI* lpi /**< LP interface structure */
3170  )
3172  SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3173 
3174  assert(lpi != NULL);
3175  assert(lpi->spx != NULL);
3176 
3177  return (lpi->spx->status() == SPxSolver::ABORT_ITER);
3178 }
3179 
3180 /** returns TRUE iff the time limit was reached */
3182  SCIP_LPI* lpi /**< LP interface structure */
3183  )
3185  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3186 
3187  assert(lpi != NULL);
3188  assert(lpi->spx != NULL);
3189 
3190  return (lpi->spx->status() == SPxSolver::ABORT_TIME);
3191 }
3192 
3193 /** returns the internal solution status of the solver */
3195  SCIP_LPI* lpi /**< LP interface structure */
3196  )
3198  SCIPdebugMessage("calling SCIPlpiGetInternalStatus()\n");
3199 
3200  assert(lpi != NULL);
3201  assert(lpi->spx != NULL);
3202 
3203  return static_cast<int>(lpi->spx->status());
3204 }
3205 
3206 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3208  SCIP_LPI* lpi, /**< LP interface structure */
3209  SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3210  )
3211 { /*lint --e{715}*/
3212  SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3213 
3214  assert(lpi != NULL);
3215  assert(lpi->spx != NULL);
3216  assert(success != NULL);
3217 
3218 #if SOPLEX_APIVERSION >= 4
3219  *success = lpi->spx->ignoreUnscaledViolations();
3220 #else
3221  *success = FALSE;
3222 #endif
3223 
3224  return SCIP_OKAY;
3225 }
3226 
3227 /** gets objective value of solution */
3229  SCIP_LPI* lpi, /**< LP interface structure */
3230  SCIP_Real* objval /**< stores the objective value */
3231  )
3232 {
3233  SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3234 
3235  assert(lpi != NULL);
3236  assert(lpi->spx != NULL);
3237  assert(objval != NULL);
3238 
3239  *objval = lpi->spx->objValueReal();
3240 
3241  return SCIP_OKAY;
3242 }
3243 
3244 /** gets primal and dual solution vectors for feasible LPs
3245  *
3246  * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3247  * SCIPlpiIsOptimal() returns true.
3248  */
3250  SCIP_LPI* lpi, /**< LP interface structure */
3251  SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3252  SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3253  SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3254  SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3255  SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3256  )
3257 {
3258  SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3259 
3260  assert(lpi != NULL);
3261  assert(lpi->spx != NULL);
3262 
3263  if( objval != NULL )
3264  *objval = lpi->spx->objValueReal();
3265 
3266  try
3267  {
3268  if( primsol != NULL )
3269  {
3270 #if SOPLEX_APIVERSION > 10
3271  (void)lpi->spx->getPrimalReal(primsol, lpi->spx->numColsReal());
3272 #else
3273  Vector tmp(lpi->spx->numColsReal(), primsol);
3274  (void)lpi->spx->getPrimalReal(tmp);
3275 #endif
3276  }
3277  if( dualsol != NULL )
3278  {
3279 #if SOPLEX_APIVERSION > 10
3280  (void)lpi->spx->getDualReal(dualsol, lpi->spx->numRowsReal());
3281 #else
3282  Vector tmp(lpi->spx->numRowsReal(), dualsol);
3283  (void)lpi->spx->getDualReal(tmp);
3284 #endif
3285  }
3286  if( activity != NULL )
3287  {
3288 #if SOPLEX_APIVERSION > 10
3289  (void)lpi->spx->getSlacksReal(activity, lpi->spx->numRowsReal()); /* in SoPlex, the activities are called "slacks" */
3290 #else
3291  Vector tmp(lpi->spx->numRowsReal(), activity);
3292  (void)lpi->spx->getSlacksReal(tmp); /* in SoPlex, the activities are called "slacks" */
3293 #endif
3294  }
3295  if( redcost != NULL )
3296  {
3297 #if SOPLEX_APIVERSION > 10
3298  (void)lpi->spx->getRedCostReal(redcost, lpi->spx->numColsReal());
3299 #else
3300  Vector tmp(lpi->spx->numColsReal(), redcost);
3301  (void)lpi->spx->getRedCostReal(tmp);
3302 #endif
3303  }
3304  }
3305 #ifndef NDEBUG
3306  catch( const SPxException& x )
3307  {
3308  std::string s = x.what();
3309  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3310 #else
3311  catch( const SPxException& )
3312  {
3313 #endif
3314  return SCIP_LPERROR;
3315  }
3316 
3317  return SCIP_OKAY;
3318 }
3319 
3320 /** gets primal ray for unbounded LPs */
3322  SCIP_LPI* lpi, /**< LP interface structure */
3323  SCIP_Real* ray /**< primal ray */
3324  )
3325 { /*lint --e{715}*/
3326  SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3327 
3328  assert(lpi != NULL);
3329  assert(lpi->spx != NULL);
3330  assert(lpi->spx->hasPrimalRay());
3331  assert(ray != NULL);
3332 
3333  try
3334  {
3335 #if SOPLEX_APIVERSION > 10
3336  (void)lpi->spx->getPrimalRayReal(ray, lpi->spx->numColsReal());
3337 #else
3338  Vector tmp(lpi->spx->numColsReal(), ray);
3339  (void)lpi->spx->getPrimalRayReal(tmp);
3340 #endif
3341  }
3342 #ifndef NDEBUG
3343  catch( const SPxException& x )
3344  {
3345  std::string s = x.what();
3346  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3347 #else
3348  catch( const SPxException& )
3349  {
3350 #endif
3351  return SCIP_LPERROR;
3352  }
3353 
3354  return SCIP_OKAY;
3355 }
3356 
3357 /** gets dual farkas proof for infeasibility */
3359  SCIP_LPI* lpi, /**< LP interface structure */
3360  SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3361  )
3362 {
3363  SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3364 
3365  assert(lpi != NULL);
3366  assert(lpi->spx != NULL);
3367  assert(lpi->spx->hasDualFarkas());
3368  assert(dualfarkas != NULL);
3369 
3370  try
3371  {
3372 #if SOPLEX_APIVERSION > 10
3373  (void)lpi->spx->getDualFarkasReal(dualfarkas, lpi->spx->numRowsReal());
3374 #else
3375  Vector tmp(lpi->spx->numRowsReal(), dualfarkas);
3376  (void)lpi->spx->getDualFarkasReal(tmp);
3377 #endif
3378  }
3379 #ifndef NDEBUG
3380  catch( const SPxException& x )
3381  {
3382  std::string s = x.what();
3383  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3384 #else
3385  catch( const SPxException& )
3386  {
3387 #endif
3388  return SCIP_LPERROR;
3389  }
3390 
3391  return SCIP_OKAY;
3392 }
3393 
3394 /** gets the number of LP iterations of the last solve call */
3396  SCIP_LPI* lpi, /**< LP interface structure */
3397  int* iterations /**< pointer to store the number of iterations of the last solve call */
3398  )
3399 {
3400  SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3401 
3402  assert(lpi != NULL);
3403  assert(lpi->spx != NULL);
3404  assert(iterations != NULL);
3405 
3406  *iterations = lpi->spx->numIterations();
3407 
3408  return SCIP_OKAY;
3409 }
3410 
3411 /** gets information about the quality of an LP solution
3412  *
3413  * Such information is usually only available, if also a (maybe not optimal) solution is available.
3414  * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
3415  */
3417  SCIP_LPI* lpi, /**< LP interface structure */
3418  SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3419  SCIP_Real* quality /**< pointer to store quality number */
3420  )
3421 {
3422  SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3423 
3424  assert(lpi != NULL);
3425  assert(quality != NULL);
3426 
3427  bool success;
3428 
3429  SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3430 
3431  switch( qualityindicator )
3432  {
3434  success = lpi->spx->getEstimatedCondition(*quality);
3435  break;
3436 
3438  success = lpi->spx->getExactCondition(*quality);
3439  break;
3440 
3441  default:
3442  SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3443  return SCIP_INVALIDDATA;
3444  }
3445 
3446  if( !success )
3447  {
3448  SCIPdebugMessage("problem computing condition number\n");
3449  *quality = SCIP_INVALID;
3450  }
3451 
3452  return SCIP_OKAY;
3453 }
3454 
3455 /**@} */
3456 
3457 
3458 
3459 
3460 /*
3461  * LP Basis Methods
3462  */
3463 
3464 /**@name LP Basis Methods */
3465 /**@{ */
3466 
3467 
3468 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
3470  SCIP_LPI* lpi, /**< LP interface structure */
3471  int* cstat, /**< array to store column basis status, or NULL */
3472  int* rstat /**< array to store row basis status, or NULL */
3473  )
3474 {
3475  int i;
3476 
3477  SCIPdebugMessage("calling SCIPlpiGetBase()\n");
3478 
3479  assert(lpi != NULL);
3480  assert(lpi->spx != NULL);
3481 
3482  assert( lpi->spx->preStrongbranchingBasisFreed() );
3483 
3484  if( rstat != NULL )
3485  {
3486  for( i = 0; i < lpi->spx->numRowsReal(); ++i )
3487  {
3488  switch( lpi->spx->basisRowStatus(i) )
3489  {
3490  case SPxSolver::BASIC:
3491  rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3492  break;
3493  case SPxSolver::FIXED:
3494  case SPxSolver::ON_LOWER:
3495  rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3496  break;
3497  case SPxSolver::ON_UPPER:
3498  rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3499  break;
3500  case SPxSolver::ZERO:
3501  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3502  return SCIP_LPERROR;
3503  case SPxSolver::UNDEFINED:
3504  default:
3505  SCIPerrorMessage("invalid basis status\n");
3506  SCIPABORT();
3507  return SCIP_INVALIDDATA; /*lint !e527*/
3508  }
3509  }
3510  }
3511 
3512  if( cstat != NULL )
3513  {
3514  for( i = 0; i < lpi->spx->numColsReal(); ++i )
3515  {
3516 // SCIP_Real val = 0.0;
3517  switch( lpi->spx->basisColStatus(i) )
3518  {
3519  case SPxSolver::BASIC:
3520  cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3521  break;
3522  case SPxSolver::FIXED:
3523  /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
3524  * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
3525  * this case there is no problem at all. If the basis is saved and/or used in some other
3526  * solver, it usually is very cheap to perform the pivots necessary to get an optimal
3527  * basis.
3528  * @todo implement getRedCostEst()
3529  * */
3530 // SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
3531 // if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
3532 // cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3533 // else
3534  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3535  break;
3536  case SPxSolver::ON_LOWER:
3537  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3538  break;
3539  case SPxSolver::ON_UPPER:
3540  cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3541  break;
3542  case SPxSolver::ZERO:
3543  cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3544  break;
3545  case SPxSolver::UNDEFINED:
3546  default:
3547  SCIPerrorMessage("invalid basis status\n");
3548  SCIPABORT();
3549  return SCIP_INVALIDDATA; /*lint !e527*/
3550  }
3551  }
3552  }
3553 
3554  return SCIP_OKAY;
3555 }
3556 
3557 /** sets current basis status for columns and rows */
3559  SCIP_LPI* lpi, /**< LP interface structure */
3560  const int* cstat, /**< array with column basis status */
3561  const int* rstat /**< array with row basis status */
3562  )
3563 {
3564  int i;
3565  int ncols;
3566  int nrows;
3567 
3568  SCIPdebugMessage("calling SCIPlpiSetBase()\n");
3569 
3570  assert(lpi != NULL);
3571  assert(lpi->spx != NULL);
3572 
3573  SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
3574  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
3575 
3576  assert(cstat != NULL || ncols == 0);
3577  assert(rstat != NULL || nrows == 0);
3578 
3579  assert( lpi->spx->preStrongbranchingBasisFreed() );
3580  invalidateSolution(lpi);
3581 
3582  DataArray<SPxSolver::VarStatus>& _colstat = lpi->spx->colStat();
3583  DataArray<SPxSolver::VarStatus>& _rowstat = lpi->spx->rowStat();
3584 
3585  _colstat.reSize(ncols);
3586  _rowstat.reSize(nrows);
3587 
3588  for( i = 0; i < nrows; ++i )
3589  {
3590  switch( rstat[i] ) /*lint !e613*/
3591  {
3592  case SCIP_BASESTAT_LOWER:
3593  _rowstat[i] = SPxSolver::ON_LOWER;
3594  break;
3595  case SCIP_BASESTAT_BASIC:
3596  _rowstat[i] = SPxSolver::BASIC;
3597  break;
3598  case SCIP_BASESTAT_UPPER:
3599  _rowstat[i] = SPxSolver::ON_UPPER;
3600  break;
3601  case SCIP_BASESTAT_ZERO:
3602  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3603  return SCIP_LPERROR; /*lint !e429*/
3604  default:
3605  SCIPerrorMessage("invalid basis status\n");
3606  SCIPABORT();
3607  return SCIP_INVALIDDATA; /*lint !e527*/
3608  }
3609  }
3610 
3611  for( i = 0; i < ncols; ++i )
3612  {
3613  switch( cstat[i] ) /*lint !e613*/
3614  {
3615  case SCIP_BASESTAT_LOWER:
3616  _colstat[i] = SPxSolver::ON_LOWER;
3617  break;
3618  case SCIP_BASESTAT_BASIC:
3619  _colstat[i] = SPxSolver::BASIC;
3620  break;
3621  case SCIP_BASESTAT_UPPER:
3622  _colstat[i] = SPxSolver::ON_UPPER;
3623  break;
3624  case SCIP_BASESTAT_ZERO:
3625  _colstat[i] = SPxSolver::ZERO;
3626  break;
3627  default:
3628  SCIPerrorMessage("invalid basis status\n");
3629  SCIPABORT();
3630  return SCIP_INVALIDDATA; /*lint !e527*/
3631  }
3632  }
3633 
3634  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(_rowstat.get_ptr(), _colstat.get_ptr()) );
3635  lpi->spx->freePreStrongbranchingBasis();
3636 
3637  return SCIP_OKAY;
3638 }
3639 
3640 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
3642  SCIP_LPI* lpi, /**< LP interface structure */
3643  int* bind /**< pointer to store basis indices ready to keep number of rows entries */
3644  )
3645 {
3646  SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
3647 
3648  assert(lpi != NULL);
3649  assert(lpi->spx != NULL);
3650  assert(bind != NULL);
3651 
3652  assert(lpi->spx->preStrongbranchingBasisFreed());
3653 
3654  lpi->spx->getBasisInd(bind);
3655 
3656  return SCIP_OKAY;
3657 }
3658 
3659 
3660 /** get row of inverse basis matrix B^-1
3661  *
3662  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3663  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3664  * see also the explanation in lpi.h.
3665  */
3667  SCIP_LPI* lpi, /**< LP interface structure */
3668  int r, /**< row number */
3669  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
3670  int* inds, /**< array to store the non-zero indices, or NULL */
3671  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3672  * (-1: if we do not store sparsity information) */
3673  )
3674 {
3675  SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
3676 
3677  assert(lpi != NULL);
3678  assert(lpi->spx != NULL);
3679  assert(lpi->spx->preStrongbranchingBasisFreed());
3680  assert(coef != NULL);
3681 
3682  assert(r >= 0);
3683  assert(r < lpi->spx->numRowsReal());
3684 
3685  if( ! lpi->spx->getBasisInverseRowReal(r, coef, inds, ninds) )
3686  return SCIP_LPERROR;
3687 
3688  return SCIP_OKAY;
3689 }
3690 
3691 /** get column of inverse basis matrix B^-1
3692  *
3693  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3694  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3695  * see also the explanation in lpi.h.
3696  */
3698  SCIP_LPI* lpi, /**< LP interface structure */
3699  int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
3700  * you have to call SCIPlpiGetBasisInd() to get the array which links the
3701  * B^-1 column numbers to the row and column numbers of the LP!
3702  * c must be between 0 and nrows-1, since the basis has the size
3703  * nrows * nrows */
3704  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
3705  int* inds, /**< array to store the non-zero indices, or NULL */
3706  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3707  * (-1: if we do not store sparsity information) */
3708  )
3709 {
3710  SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
3711 
3712  assert( lpi != NULL );
3713  assert( lpi->spx != NULL );
3714  assert( lpi->spx->preStrongbranchingBasisFreed() );
3715  assert(coef != NULL);
3716 
3717  if( ! lpi->spx->getBasisInverseColReal(c, coef, inds, ninds) )
3718  return SCIP_LPERROR;
3719 
3720  return SCIP_OKAY;
3721 }
3722 
3723 /** get row of inverse basis matrix times constraint matrix B^-1 * A
3724  *
3725  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3726  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3727  * see also the explanation in lpi.h.
3728  */
3730  SCIP_LPI* lpi, /**< LP interface structure */
3731  int r, /**< row number */
3732  const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
3733  SCIP_Real* coef, /**< vector to return coefficients of the row */
3734  int* inds, /**< array to store the non-zero indices, or NULL */
3735  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3736  * (-1: if we do not store sparsity information) */
3737  )
3738 {
3739  SCIP_Real* buf;
3740  SCIP_Real* binv;
3741  int nrows;
3742  int ncols;
3743  int c;
3744 
3745  SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
3746 
3747  assert(lpi != NULL);
3748  assert(lpi->spx != NULL);
3749  assert( lpi->spx->preStrongbranchingBasisFreed() );
3750  assert(coef != NULL);
3751 
3752  nrows = lpi->spx->numRowsReal();
3753  ncols = lpi->spx->numColsReal();
3754  buf = NULL;
3755 
3756  /* get (or calculate) the row in B^-1 */
3757  if( binvrow == NULL )
3758  {
3759  SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
3760  SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
3761  binv = buf;
3762  }
3763  else
3764  binv = const_cast<SCIP_Real*>(binvrow);
3765 
3766  assert(binv != NULL);
3767 
3768  /* mark sparsity pattern as invalid */
3769  if( ninds != NULL )
3770  *ninds = -1;
3771 
3772  // @todo exploit sparsity in binv by looping over nrows
3773  /* calculate the scalar product of the row in B^-1 and A */
3774  Vector binvvec(nrows, binv);
3775 
3776 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3777  /* temporary unscaled column of A */
3778  DSVector acol;
3779 #endif
3780 
3781  for( c = 0; c < ncols; ++c )
3782  {
3783 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3784  lpi->spx->getColVectorReal(c, acol);
3785  coef[c] = binvvec * acol; /* scalar product */ /*lint !e1702*/
3786 #else
3787  coef[c] = binvvec * lpi->spx->colVectorReal(c); /* scalar product */ /*lint !e1702*/
3788 #endif
3789  }
3790 
3791  /* free memory if it was temporarily allocated */
3792  BMSfreeMemoryArrayNull(&buf);
3793 
3794  return SCIP_OKAY;
3795 }
3796 
3797 /** get column of inverse basis matrix times constraint matrix B^-1 * A
3798  *
3799  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3800  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3801  * see also the explanation in lpi.h.
3802  */
3804  SCIP_LPI* lpi, /**< LP interface structure */
3805  int c, /**< column number */
3806  SCIP_Real* coef, /**< vector to return coefficients of the column */
3807  int* inds, /**< array to store the non-zero indices, or NULL */
3808  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3809  * (-1: if we do not store sparsity information) */
3810  )
3811 { /*lint --e{715}*/
3812  /* create a new uninitialized full vector */
3813  DVector col(lpi->spx->numRowsReal());
3814 
3815 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3816  /* temporary sparse vector used for unscaling (memory is automatically enlarged) */
3817  DSVector colsparse;
3818 #endif
3819 
3820  SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
3821 
3822  assert( lpi != NULL );
3823  assert( lpi->spx != NULL );
3824  assert( lpi->spx->preStrongbranchingBasisFreed() );
3825  assert(coef != NULL);
3826 
3827  /* extract column c of A */
3828  assert(c >= 0);
3829  assert(c < lpi->spx->numColsReal());
3830 
3831  /* @todo implement this with sparse vectors */
3832  /* mark sparsity pattern as invalid */
3833  if( ninds != NULL )
3834  *ninds = -1;
3835 
3836  /* col needs to be cleared because copying colVectorReal only regards nonzeros */
3837  col.clear();
3838 
3839 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3840  lpi->spx->getColVectorReal(c, colsparse);
3841  /* the copy is necessary to transform the sparse column into a dense vector */
3842  col = colsparse;
3843 #else
3844  col = lpi->spx->colVectorReal(c);
3845 #endif
3846 
3847  /* solve */
3848  if( ! lpi->spx->getBasisInverseTimesVecReal(col.get_ptr(), coef) )
3849  return SCIP_LPERROR;
3850 
3851  return SCIP_OKAY;
3852 }
3853 
3854 /**@} */
3855 
3856 
3857 
3858 
3859 /*
3860  * LP State Methods
3861  */
3862 
3863 /**@name LP State Methods */
3864 /**@{ */
3865 
3866 /** stores LPi state (like basis information) into lpistate object */
3868  SCIP_LPI* lpi, /**< LP interface structure */
3869  BMS_BLKMEM* blkmem, /**< block memory */
3870  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3871  )
3872 {
3873  int ncols;
3874  int nrows;
3875 
3876  SCIPdebugMessage("calling SCIPlpiGetState()\n");
3877 
3878  assert(blkmem != NULL);
3879  assert(lpi != NULL);
3880  assert(lpi->spx != NULL);
3881  assert(lpistate != NULL);
3882 
3883  assert( lpi->spx->preStrongbranchingBasisFreed() );
3884 
3885  ncols = lpi->spx->numColsReal();
3886  nrows = lpi->spx->numRowsReal();
3887  assert(ncols >= 0);
3888  assert(nrows >= 0);
3889 
3890  /* allocate lpistate data */
3891  SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
3892 
3893  /* allocate enough memory for storing uncompressed basis information */
3894  SCIP_CALL( ensureCstatMem(lpi, ncols) );
3895  SCIP_CALL( ensureRstatMem(lpi, nrows) );
3896 
3897  /* get unpacked basis information */
3898  SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
3899 
3900  /* pack LPi state data */
3901  (*lpistate)->ncols = ncols;
3902  (*lpistate)->nrows = nrows;
3903  lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
3904 
3905  return SCIP_OKAY;
3906 }
3907 
3908 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
3909  * columns and rows since the state was stored with SCIPlpiGetState()
3910  */
3912  SCIP_LPI* lpi, /**< LP interface structure */
3913  BMS_BLKMEM* /*blkmem*/, /**< block memory */
3914  const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
3915  )
3916 {
3917  int lpncols;
3918  int lpnrows;
3919  int i;
3920 
3921  SCIPdebugMessage("calling SCIPlpiSetState()\n");
3922 
3923  assert(lpi != NULL);
3924  assert(lpi->spx != NULL);
3925  assert(lpistate != NULL);
3926  /* assert(blkmem != NULL); */
3927 
3928  assert( lpi->spx->preStrongbranchingBasisFreed() );
3929 
3930  lpncols = lpi->spx->numColsReal();
3931  lpnrows = lpi->spx->numRowsReal();
3932  assert(lpistate->ncols <= lpncols);
3933  assert(lpistate->nrows <= lpnrows);
3934 
3935  /* allocate enough memory for storing uncompressed basis information */
3936  SCIP_CALL( ensureCstatMem(lpi, lpncols) );
3937  SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
3938 
3939  /* unpack LPi state data */
3940  lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
3941 
3942  /* extend the basis to the current LP beyond the previously existing columns */
3943  for( i = lpistate->ncols; i < lpncols; ++i )
3944  {
3945  SCIP_Real bnd = lpi->spx->lowerReal(i);
3946  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3947  {
3948  /* if lower bound is +/- infinity -> try upper bound */
3949  bnd = lpi->spx->lowerReal(i);
3950  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3951  /* variable is free */
3952  lpi->cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3953  else
3954  /* use finite upper bound */
3955  lpi->cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3956  }
3957  else
3958  /* use finite lower bound */
3959  lpi->cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3960  }
3961  for( i = lpistate->nrows; i < lpnrows; ++i )
3962  lpi->rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3963 
3964  /* load basis information */
3965  SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
3966 
3967  return SCIP_OKAY;
3968 }
3969 
3970 /** clears current LPi state (like basis information) of the solver */
3972  SCIP_LPI* lpi /**< LP interface structure */
3973  )
3974 { /*lint --e{715}*/
3975  SCIPdebugMessage("calling SCIPlpiClearState()\n");
3976 
3977  assert(lpi != NULL);
3978  assert(lpi->spx != NULL);
3979 
3980  try
3981  {
3982  lpi->spx->clearBasis();
3983  }
3984 #ifndef NDEBUG
3985  catch( const SPxException& x )
3986  {
3987  std::string s = x.what();
3988  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3989 #else
3990  catch( const SPxException& )
3991  {
3992 #endif
3993  assert( lpi->spx->status() != SPxSolver::OPTIMAL );
3994  return SCIP_LPERROR;
3995  }
3996 
3997  return SCIP_OKAY;
3998 }
3999 
4000 /** frees LPi state information */
4002  SCIP_LPI* lpi, /**< LP interface structure */
4003  BMS_BLKMEM* blkmem, /**< block memory */
4004  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4005  )
4006 { /*lint --e{715}*/
4007  SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4008 
4009  assert(lpi != NULL);
4010  assert(lpistate != NULL);
4011  assert(blkmem != NULL);
4012 
4013  if ( *lpistate != NULL )
4014  lpistateFree(lpistate, blkmem);
4015 
4016  return SCIP_OKAY;
4017 }
4018 
4019 /** checks, whether the given LP state contains simplex basis information */
4021  SCIP_LPI* lpi, /**< LP interface structure */
4022  SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4023  )
4024 { /*lint --e{715}*/
4025  assert(lpi != NULL);
4026  return TRUE;
4027 }
4028 
4029 /** reads LP state (like basis information from a file */
4031  SCIP_LPI* lpi, /**< LP interface structure */
4032  const char* fname /**< file name */
4033  )
4034 {
4035  SCIPdebugMessage("calling SCIPlpiReadState()\n");
4036  assert(lpi != NULL);
4037  assert(lpi->spx != NULL);
4038  assert(fname != NULL);
4039 
4040  assert( lpi->spx->preStrongbranchingBasisFreed() );
4041 
4042  bool success;
4043  SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
4044 
4045  return success ? SCIP_OKAY : SCIP_LPERROR;
4046 }
4047 
4048 /** writes LPi state (i.e. basis information) to a file */
4050  SCIP_LPI* lpi, /**< LP interface structure */
4051  const char* fname /**< file name */
4052  )
4053 {
4054  assert(lpi != NULL);
4055  assert(lpi->spx != NULL);
4056  assert(fname != NULL);
4057  SCIPdebugMessage("calling SCIPlpiWriteState()\n");
4058 
4059  assert( lpi->spx->preStrongbranchingBasisFreed() );
4060 
4061  bool res;
4062  SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
4063 
4064  if ( ! res )
4065  return SCIP_LPERROR;
4066 
4067  return SCIP_OKAY;
4068 }
4069 
4070 /**@} */
4071 
4072 
4073 
4074 
4075 /*
4076  * LP Pricing Norms Methods
4077  */
4078 
4079 /**@name LP Pricing Norms Methods */
4080 /**@{ */
4081 
4082 /** stores LPi pricing norms information
4083  * @todo should we store norm information?
4084  */
4086  SCIP_LPI* lpi, /**< LP interface structure */
4087  BMS_BLKMEM* blkmem, /**< block memory */
4088  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
4089  )
4090 { /*lint --e{715}*/
4091 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4092  int nrows;
4093  int ncols;
4094 
4095  assert(blkmem != NULL);
4096  assert(lpi != NULL);
4097  assert(lpi->spx != NULL);
4098  assert(lpinorms != NULL);
4099 
4100  lpi->spx->getNdualNorms(nrows, ncols);
4101 
4102  if( nrows == 0 && ncols == 0)
4103  {
4104  (*lpinorms = NULL);
4105  return SCIP_OKAY;
4106  }
4107 
4108  /* allocate lpinorms data */
4109  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
4110  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
4111  (*lpinorms)->nrows = 0;
4112  (*lpinorms)->ncols = 0;
4113 
4114  SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
4115 
4116  if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
4117  {
4118  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4119  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
4120  BMSfreeBlockMemory(blkmem, lpinorms);
4121  assert(*lpinorms == NULL);
4122  }
4123 #ifndef NDEBUG
4124  else
4125  {
4126  assert(nrows == (*lpinorms)->nrows);
4127  assert(ncols == (*lpinorms)->ncols);
4128  }
4129 #endif
4130 #else
4131  (*lpinorms) = NULL;
4132 #endif
4133 
4134  return SCIP_OKAY;
4135 }
4136 
4137 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
4138  * columns and rows since the state was stored with SCIPlpiGetNorms()
4139  */
4141  SCIP_LPI* lpi, /**< LP interface structure */
4142  BMS_BLKMEM* blkmem, /**< block memory */
4143  const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
4144  )
4145 { /*lint --e{715}*/
4146 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4147  assert(blkmem != NULL);
4148  assert(lpi != NULL);
4149  assert(lpi->spx != NULL);
4150 
4151  /* if there was no pricing norms information available, the LPi norms were not stored */
4152  if( lpinorms == NULL )
4153  return SCIP_OKAY;
4154 
4155  assert(lpinorms->nrows <= lpi->spx->numRowsReal());
4156  assert(lpinorms->ncols <= lpi->spx->numColsReal());
4157 
4158  if( lpinorms->nrows == 0 )
4159  return SCIP_OKAY;
4160 
4161  SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
4162  (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->numRowsReal(), lpi->spx->numColsReal());
4163 
4164  (void) lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms);
4165 #endif
4166 
4167  return SCIP_OKAY;
4168 }
4169 
4170 /** frees pricing norms information */
4172  SCIP_LPI* lpi, /**< LP interface structure */
4173  BMS_BLKMEM* blkmem, /**< block memory */
4174  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
4175  )
4176 { /*lint --e{715}*/
4177 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4178  assert(lpi != NULL);
4179  assert(lpinorms != NULL);
4180 
4181  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4182 
4183  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
4184  BMSfreeBlockMemory(blkmem, lpinorms);
4185  assert(*lpinorms == NULL);
4186 #endif
4187 
4188  return SCIP_OKAY;
4189 }
4190 
4191 /**@} */
4192 
4193 
4194 
4195 
4196 /*
4197  * Parameter Methods
4198  */
4199 
4200 /**@name Parameter Methods */
4201 /**@{ */
4202 
4203 /** gets integer parameter of LP */
4205  SCIP_LPI* lpi, /**< LP interface structure */
4206  SCIP_LPPARAM type, /**< parameter number */
4207  int* ival /**< buffer to store the parameter value */
4208  )
4209 {
4210  int scaleparam;
4211 
4212  SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
4213 
4214  assert(lpi != NULL);
4215  assert(lpi->spx != NULL);
4216  assert(ival != NULL);
4217 
4218  switch( type )
4219  {
4221  *ival = lpi->spx->getFromScratch();
4222  break;
4223  case SCIP_LPPAR_LPINFO:
4224  *ival = lpi->spx->getLpInfo();
4225  break;
4226  case SCIP_LPPAR_LPITLIM:
4227  *ival = lpi->spx->intParam(SoPlex::ITERLIMIT);
4228  if( *ival == -1 )
4229  *ival = INT_MAX;
4230  break;
4231  case SCIP_LPPAR_PRESOLVING:
4232  *ival = lpi->spx->intParam(SoPlex::SIMPLIFIER) == SoPlex::SIMPLIFIER_AUTO;
4233  break;
4234  case SCIP_LPPAR_PRICING:
4235  *ival = (int) lpi->pricing;
4236  break;
4237  case SCIP_LPPAR_SCALING:
4238  scaleparam = lpi->spx->intParam(SoPlex::SCALER);
4239 
4240  if( scaleparam == SoPlex::SCALER_OFF )
4241  *ival = 0;
4242  else if( scaleparam == SoPlex::SCALER_BIEQUI )
4243  *ival = 1;
4244 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4245  else
4246  {
4247  assert(scaleparam == SoPlex::SCALER_LEASTSQ);
4248  *ival = 2;
4249  }
4250 #else
4251  else
4252  {
4253  assert(scaleparam == SoPlex::SCALER_GEO8);
4254  *ival = 2;
4255  }
4256 #endif
4257  break;
4258 #if SOPLEX_VERSION >= 201
4259  case SCIP_LPPAR_TIMING:
4260  *ival = (int) (lpi->spx->intParam(SoPlex::TIMER));
4261  break;
4262 #endif
4263 #if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
4264  case SCIP_LPPAR_RANDOMSEED:
4265  *ival = (int) lpi->spx->randomSeed();
4266  break;
4267 #endif
4268 #if SOPLEX_APIVERSION >= 1
4269  case SCIP_LPPAR_REFACTOR:
4270  *ival = (int) lpi->spx->intParam(SoPlex::FACTOR_UPDATE_MAX);
4271  break;
4272 #endif
4273  default:
4274  return SCIP_PARAMETERUNKNOWN;
4275  } /*lint !e788*/
4276 
4277  return SCIP_OKAY;
4278 }
4279 
4280 /** sets integer parameter of LP */
4282  SCIP_LPI* lpi, /**< LP interface structure */
4283  SCIP_LPPARAM type, /**< parameter number */
4284  int ival /**< parameter value */
4285  )
4286 {
4287  SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
4288 
4289  assert(lpi != NULL);
4290  assert(lpi->spx != NULL);
4291 
4292  switch( type )
4293  {
4295  assert(ival == TRUE || ival == FALSE);
4296  lpi->spx->setFromScratch(bool(ival));
4297  break;
4298  case SCIP_LPPAR_LPINFO:
4299  assert(ival == TRUE || ival == FALSE);
4300  lpi->spx->setLpInfo(bool(ival));
4301  break;
4302  case SCIP_LPPAR_LPITLIM:
4303  assert( ival >= 0 );
4304  /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
4305  if( ival >= INT_MAX )
4306  ival = -1;
4307  (void) lpi->spx->setIntParam(SoPlex::ITERLIMIT, ival);
4308  break;
4309  case SCIP_LPPAR_PRESOLVING:
4310  assert(ival == TRUE || ival == FALSE);
4311  (void) lpi->spx->setIntParam(SoPlex::SIMPLIFIER, (ival ? SoPlex::SIMPLIFIER_AUTO : SoPlex::SIMPLIFIER_OFF));
4312  break;
4313  case SCIP_LPPAR_PRICING:
4314  lpi->pricing = (SCIP_PRICING)ival;
4315  switch( lpi->pricing )
4316  {
4318  case SCIP_PRICING_AUTO:
4319  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_AUTO);
4320  break;
4321  case SCIP_PRICING_FULL:
4322  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4323  break;
4324  case SCIP_PRICING_PARTIAL:
4325  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_PARMULT);
4326  break;
4327  case SCIP_PRICING_STEEP:
4328  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4329  break;
4331  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_QUICKSTEEP);
4332  break;
4333  case SCIP_PRICING_DEVEX:
4334  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_DEVEX);
4335  break;
4336  default:
4337  return SCIP_LPERROR;
4338  }
4339  break;
4340  case SCIP_LPPAR_SCALING:
4341  assert(ival >= 0 && ival <= 2);
4342  if( ival == 0 )
4343  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_OFF);
4344  else if( ival == 1 )
4345  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_BIEQUI);
4346  else
4347 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4348  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_LEASTSQ);
4349 #else
4350  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_GEO8);
4351 #endif
4352 
4353  break;
4354 #if SOPLEX_VERSION >= 201
4355  case SCIP_LPPAR_TIMING:
4356  assert(ival >= 0 && ival < 3);
4357  (void) lpi->spx->setIntParam(SoPlex::TIMER, ival);
4358  break;
4359 #endif
4360 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
4361  case SCIP_LPPAR_RANDOMSEED:
4362  lpi->spx->setRandomSeed((unsigned long)(long)ival);
4363  break;
4364 #endif
4365 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION >= 221 && SOPLEX_SUBVERSION >= 3)
4366  case SCIP_LPPAR_POLISHING:
4367  assert(ival >= 0 && ival < 3);
4368  (void) lpi->spx->setIntParam(SoPlex::SOLUTION_POLISHING, ival);
4369  break;
4370 #endif
4371 #if SOPLEX_APIVERSION >= 1
4372  case SCIP_LPPAR_REFACTOR:
4373  assert(ival >= 0);
4374  (void) lpi->spx->setIntParam(SoPlex::FACTOR_UPDATE_MAX, ival);
4375  break;
4376 #endif
4377 
4378  default:
4379  return SCIP_PARAMETERUNKNOWN;
4380  } /*lint !e788*/
4381 
4382  return SCIP_OKAY;
4383 }
4384 
4385 /** gets floating point parameter of LP */
4387  SCIP_LPI* lpi, /**< LP interface structure */
4388  SCIP_LPPARAM type, /**< parameter number */
4389  SCIP_Real* dval /**< buffer to store the parameter value */
4390  )
4391 {
4392  SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
4393 
4394  assert(lpi != NULL);
4395  assert(lpi->spx != NULL);
4396  assert(dval != NULL);
4397 
4398  switch( type )
4399  {
4400  case SCIP_LPPAR_FEASTOL:
4401  *dval = lpi->spx->feastol();
4402  break;
4404  *dval = lpi->spx->opttol();
4405  break;
4406  case SCIP_LPPAR_OBJLIM:
4407  if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4408  *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_UPPER);
4409  else
4410  *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_LOWER);
4411  break;
4412  case SCIP_LPPAR_LPTILIM:
4413  *dval = lpi->spx->realParam(SoPlex::TIMELIMIT);
4414  break;
4416  *dval = lpi->spx->realParam(SoPlex::REPRESENTATION_SWITCH);
4417  if( *dval >= SCIPlpiInfinity(lpi) )
4418  *dval = -1.0;
4419  break;
4421  *dval = lpi->conditionlimit;
4422  break;
4423  case SCIP_LPPAR_MARKOWITZ:
4424 #if (SOPLEX_APIVERSION >= 9)
4425  *dval = lpi->spx->realParam(SoPlex::MIN_MARKOWITZ);
4426  break;
4427 #endif
4428  default:
4429  return SCIP_PARAMETERUNKNOWN;
4430  } /*lint !e788*/
4431 
4432  return SCIP_OKAY;
4433 }
4434 
4435 /** sets floating point parameter of LP */
4437  SCIP_LPI* lpi, /**< LP interface structure */
4438  SCIP_LPPARAM type, /**< parameter number */
4439  SCIP_Real dval /**< parameter value */
4440  )
4441 {
4442  SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
4443 
4444  assert(lpi != NULL);
4445  assert(lpi->spx != NULL);
4446 
4447  switch( type )
4448  {
4449  case SCIP_LPPAR_FEASTOL:
4450  /* 0 < dval */
4451  assert( dval > 0.0 );
4452  lpi->spx->setFeastol(dval);
4453  break;
4455  /* 0 < dval */
4456  assert( dval > 0.0 );
4457  lpi->spx->setOpttol(dval);
4458  break;
4459  case SCIP_LPPAR_OBJLIM:
4460  /* no restrictions on dval */
4461  if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4462  (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_UPPER, dval);
4463  else
4464  (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_LOWER, dval);
4465  break;
4466  case SCIP_LPPAR_LPTILIM:
4467  assert( dval > 0.0 );
4468  /* soplex requires 0 < dval < DEFAULT_INFINITY (= 1e100), -1 means unlimited */
4469  (void) lpi->spx->setRealParam(SoPlex::TIMELIMIT, dval);
4470  break;
4472  /* 0 <= dval <= inf */
4473  assert( dval >= 0.0 || dval == -1.0 );
4474  if( dval == -1 )
4475  (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, SCIPlpiInfinity(lpi));
4476  else
4477  (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, dval);
4478  break;
4480  lpi->conditionlimit = dval;
4481  lpi->checkcondition = (dval >= 0.0);
4482  break;
4483  case SCIP_LPPAR_MARKOWITZ:
4484 #if (SOPLEX_APIVERSION >= 9)
4485  /* 1e-4 <= dval <= 0.999 */
4486  if( dval < 1e-4 )
4487  dval = 1e-4;
4488  else if( dval > 0.9999 )
4489  dval = 0.9999;
4490 
4491  (void) lpi->spx->setRealParam(SoPlex::MIN_MARKOWITZ, dval);
4492  break;
4493 #endif
4494  default:
4495  return SCIP_PARAMETERUNKNOWN;
4496  } /*lint !e788*/
4497 
4498  return SCIP_OKAY;
4499 }
4500 
4501 /**@} */
4502 
4503 
4504 
4505 
4506 /*
4507  * Numerical Methods
4508  */
4509 
4510 /**@name Numerical Methods */
4511 /**@{ */
4512 
4513 /** returns value treated as infinity in the LP solver */
4515  SCIP_LPI* lpi /**< LP interface structure */
4516  )
4518  assert(lpi != NULL);
4519  SCIPdebugMessage("calling SCIPlpiInfinity()\n");
4520 
4521  return lpi->spx->realParam(SoPlex::INFTY);
4522 }
4523 
4524 /** checks if given value is treated as infinity in the LP solver */
4526  SCIP_LPI* lpi, /**< LP interface structure */
4527  SCIP_Real val
4528  )
4529 {
4530  assert(lpi != NULL);
4531  SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
4532 
4533  return (val >= lpi->spx->realParam(SoPlex::INFTY));
4534 }
4535 
4536 /**@} */
4537 
4538 
4539 
4540 
4541 /*
4542  * File Interface Methods
4543  */
4544 
4545 /**@name File Interface Methods */
4546 /**@{ */
4547 
4548 /** returns, whether the given file exists */
4549 static
4551  const char* filename /**< file name */
4552  )
4554  FILE* f;
4555 
4556  f = fopen(filename, "r");
4557  if( f == NULL )
4558  return FALSE;
4559 
4560  fclose(f);
4561 
4562  return TRUE;
4563 }
4564 
4565 /** reads LP from a file */
4567  SCIP_LPI* lpi, /**< LP interface structure */
4568  const char* fname /**< file name */
4569  )
4570 {
4571  SCIPdebugMessage("calling SCIPlpiReadLP()\n");
4572 
4573  assert(lpi != NULL);
4574  assert(lpi->spx != NULL);
4575  assert(fname != NULL);
4576 
4577  assert( lpi->spx->preStrongbranchingBasisFreed() );
4578 
4579  if( !fileExists(fname) )
4580  return SCIP_NOFILE;
4581 
4582  try
4583  {
4584  assert(lpi->spx->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL);
4585  if( !lpi->spx->readFile(fname) )
4586  return SCIP_READERROR;
4587  }
4588 #ifndef NDEBUG
4589  catch( const SPxException& x )
4590  {
4591  std::string s = x.what();
4592  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4593 #else
4594  catch( const SPxException& )
4595  {
4596 #endif
4597  return SCIP_READERROR;
4598  }
4599 
4600  return SCIP_OKAY;
4601 }
4602 
4603 /** writes LP to a file */
4605  SCIP_LPI* lpi, /**< LP interface structure */
4606  const char* fname /**< file name */
4607  )
4608 {
4609  SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
4610 
4611  assert(lpi != NULL);
4612  assert(lpi->spx != NULL);
4613  assert(fname != NULL);
4614 
4615  try
4616  {
4617  (void) lpi->spx->writeFileReal(fname);
4618  }
4619 #ifndef NDEBUG
4620  catch( const SPxException& x )
4621  {
4622  std::string s = x.what();
4623  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4624 #else
4625  catch( const SPxException& )
4626  {
4627 #endif
4628  return SCIP_WRITEERROR;
4629  }
4630 
4631  return SCIP_OKAY;
4632 }
4633 
4634 /**@} */
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_spx2.cpp:1068
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx2.cpp:4284
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:2789
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition: type_lpi.h:95
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:4517
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:4207
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_spx2.cpp:4143
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx2.cpp:3361
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_spx2.cpp:1625
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:3472
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_spx2.cpp:2232
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:4023
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:2974
interface methods for specific LP solvers
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_spx2.cpp:2449
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:1368
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:4528
#define FALSE
Definition: def.h:73
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_spx2.cpp:1032
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:914
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3005
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:3806
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2464
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:4088
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:3158
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_spx2.cpp:1446
#define SCIPdebugMessage
Definition: pub_message.h:87
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_spx2.cpp:2311
#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:489
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:3700
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3171
#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:1154
#define SOPLEX_TRY(messagehdlr, x)
Definition: lpi_spx2.cpp:159
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3061
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_spx2.cpp:1787
polyscip::Polyscip::PolyscipStatus Status
abbreviation
Definition: main.cpp:29
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4033
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:2759
#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:1876
packing single and dual bit values
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_spx2.cpp:2938
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:2478
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3184
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_spx2.cpp:3561
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4607
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx2.cpp:1336
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx2.cpp:2189
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:3033
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:1649
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_spx2.cpp:3231
static char spxname[100]
Definition: lpi_spx2.cpp:967
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_spx2.cpp:1040
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_spx2.cpp:3210
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:1314
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3974
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:2283
int cstatsize
Definition: lpi_clp.cpp:100
#define SCIP_CALL(x)
Definition: def.h:370
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:1576
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:2494
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:2863
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:1232
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx2.cpp:4174
static SCIP_Bool fileExists(const char *filename)
Definition: lpi_spx2.cpp:4553
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3087
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:1517
#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:3732
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_spx2.cpp:1713
#define SCIP_Bool
Definition: def.h:70
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2421
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:445
static void setFeastol(SCIP_NLPIPROBLEM *nlpiproblem, SCIP_Real feastol)
Definition: nlpi_ipopt.cpp:458
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:4439
#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:1893
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_spx2.cpp:2255
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:1951
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:2059
static SCIP_RETCODE spxSolve(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2349
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_spx2.cpp:1669
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3121
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_spx2.cpp:3644
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx2.cpp:2163
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3197
SCIP_Real * r
Definition: circlepacking.c:50
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3048
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2987
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:3252
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx2.cpp:3870
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3018
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3100
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_spx2.cpp:1121
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
Definition: lpi_spx2.cpp:3914
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:1910
#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:2919
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:1499
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:2833
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2959
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:3669
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2435
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:4004
#define UNKNOWN
Definition: sepa_mcf.c:4095
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx2.cpp:3398
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3074
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:443
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx2.cpp:4389
#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:1468
#define SCIP_ALLOC(x)
Definition: def.h:381
#define SCIPABORT()
Definition: def.h:342
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_spx2.cpp:3324
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4569
int * cstat
Definition: lpi_clp.cpp:98
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_spx2.cpp:3419
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4052
#define FEASTOL
Definition: lpi_qso.c:90
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_spx2.cpp:1048
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_spx2.cpp:2215