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