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-2016 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_spx2.cpp
17  * @ingroup LPIS
18  * @brief LP interface for SoPlex version 2.0 and higher
19  * @author Matthias Miltenberger
20  * @author Ambros Gleixner
21  *
22  * This is an implementation of SCIP's LP interface for SoPlex using the extended and improved interface of SoPlex 2.0
23  *
24  * For debugging purposes, the SoPlex results can be double checked with CPLEX if WITH_LPSCHECK is defined. This may
25  * yield false positives, since the LP is dumped to a file for transfering it to CPLEX, hence, precision may be lost.
26  */
27 
28 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
29 
30 #define STRONGBRANCH_RESTOREBASIS /**< if defined then in SCIPlpiStrongbranch() we restore the basis after the
31  * down branch and after the up branch; if false only after the end of a
32  * strong branching phase, which however seems to mostly increase strong
33  * branching time and iterations */
34 
35 /* in this case the SoPlex results are double checked using CPLEX */
36 #ifdef WITH_LPSCHECK
37 #include <cplex.h>
38 
39 #define CHECK_SPXSOLVE true /**< shall the SoPlex results in spxSolve() be double checked using CPLEX? */
40 #define CHECK_SPXSTRONGBRANCH true /**< shall the SoPlex results in SCIPlpStrongbranch() be double checked using CPLEX? */
41 #define CHECK_START 0 /**< skip first CHECK_START number of checks */
42 #define EXIT_AT_WRONG_RESULT false/**< shall program be exited if CPLEX returns different result than SoPlex? */
43 #define EXIT_AT_CPXERROR false/**< shall program be exited if CPLEX returns an error? */
44 
45 #define CPX_CALL(x) do \
46  { \
47  int _cpxstat_; \
48  if( (_cpxstat_ = (x)) != 0 ) \
49  { \
50  SCIPmessagePrintWarning(_messagehdlr, "CPLEX error <%d>; SoPlex result unchecked\n", _cpxstat_); \
51  if( EXIT_AT_CPXERROR ) \
52  { \
53  exit(1); \
54  } \
55  else \
56  { \
57  goto ENDCHECK; \
58  } \
59  } \
60  } \
61  while( false )
62 #endif
63 
64 /* check the return value of setParam methods */
65 #define CHECK_SOPLEX_PARAM(x) \
66  if( !x ) \
67  { \
68  SCIPmessagePrintWarning(_messagehdlr, "SoPlex: unsupported parameter value\n"); \
69  }
70 
71 /* remember the original value of the SCIP_DEBUG define and undefine it */
72 #ifdef SCIP_DEBUG
73 #define ___DEBUG
74 #undef SCIP_DEBUG
75 #endif
76 
77 /* include SoPlex solver */
78 #include "soplex.h"
79 
80 /* define subversion for versions <= 1.5.0.1 */
81 #ifndef SOPLEX_SUBVERSION
82 #define SOPLEX_SUBVERSION 0
83 #endif
84 
85 /* check version */
86 #if (SOPLEX_VERSION < 200 || (SOPLEX_VERSION == 200 && SOPLEX_SUBVERSION < 2) || (SOPLEX_VERSION > 200 && SOPLEX_VERSION < 201))
87 #error "This interface is not compatible with SoPlex versions prior to 2.0.0.2"
88 #endif
89 
90 #include "spxgithash.h"
91 
92 /* reset the SCIP_DEBUG define to its original SCIP value */
93 #undef SCIP_DEBUG
94 #ifdef ___DEBUG
95 #define SCIP_DEBUG
96 #undef ___DEBUG
97 #endif
98 
99 #define SOPLEX_VERBLEVEL 5 /**< verbosity level for LPINFO */
100 
101 #include "scip/pub_message.h"
103 /********************************************************************/
104 /*----------------------------- C++ --------------------------------*/
105 /********************************************************************/
106 
107 /* in C++ we have to use "0" instead of "(void*)0" */
108 #undef NULL
109 #define NULL 0
110 
111 #include <cassert>
112 using namespace soplex;
113 
114 
115 /** Macro for a single SoPlex call for which exceptions have to be catched - return an LP error. We
116  * make no distinction between different exception types, e.g., between memory allocation and other
117  * exceptions.
118  */
119 #ifndef NDEBUG
120 #define SOPLEX_TRY(messagehdlr, x) do \
121  { \
122  try \
123  { \
124  (x); \
125  } \
126  catch(const SPxException& E) \
127  { \
128  std::string s = E.what(); \
129  SCIPmessagePrintWarning((messagehdlr), "SoPlex threw an exception: %s\n", s.c_str()); \
130  return SCIP_LPERROR; \
131  } \
132  } \
133  while( FALSE )
134 
135 #else
136 #define SOPLEX_TRY(messagehdlr, x) do \
137  { \
138  try \
139  { \
140  (x); \
141  } \
142  catch(const SPxException& E) \
143  { \
144  return SCIP_LPERROR; \
145  } \
146  } \
147  while( FALSE )
148 #endif
149 
150 /* Macro for a single SoPlex call for which exceptions have to be catched - abort if they
151  * arise. SCIP_ABORT() is not accessible here.
152  */
153 #define SOPLEX_TRY_ABORT(x) do \
154  { \
155  try \
156  { \
157  (x); \
158  } \
159  catch(const SPxException& E) \
160  { \
161  std::string s = E.what(); \
162  SCIPerrorMessage("SoPlex threw an exception: %s\n", s.c_str()); \
163  abort(); \
164  } \
165  } \
166  while( FALSE )
167 
168 
169 
170 /** SCIP's SoPlex class */
171 class SPxSCIP : public SoPlex
172 {
173  bool _lpinfo;
174  bool _fromscratch;
175  char* _probname;
176  SPxSolver::VarStatus* _colStat; /**< column basis status used for strong branching */
177  SPxSolver::VarStatus* _rowStat; /**< row basis status used for strong branching */
178 #ifdef WITH_LPSCHECK
179  int _checknum;
180  bool _doublecheck;
181  CPXENVptr _cpxenv; /**< CPLEX memory environment */
182  CPXLPptr _cpxlp; /**< CPLEX lp structure */
183 #endif
184  SCIP_MESSAGEHDLR* _messagehdlr; /**< messagehdlr handler for printing messages, or NULL */
185 
186 public:
187  SPxSCIP(
188  SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
189  const char* probname = NULL /**< name of problem */
190  )
191  : _lpinfo(false),
192  _fromscratch(false),
193  _probname(NULL),
194  _colStat(NULL),
195  _rowStat(NULL),
196  _messagehdlr(messagehdlr)
197  {
198  if ( probname != NULL )
199  SOPLEX_TRY_ABORT( setProbname(probname) );
200 
201 #ifdef WITH_LPSCHECK
202  int cpxstat;
203  _checknum = 0;
204  _doublecheck = false;
205  _cpxenv = CPXopenCPLEX(&cpxstat);
206  assert(_cpxenv != NULL);
207  _cpxlp = CPXcreateprob(_cpxenv, &cpxstat, probname != NULL ? probname : "spxcheck");
208  (void) CPXsetintparam(_cpxenv, CPX_PARAM_SCRIND, 0);
209 #endif
210  }
211 
212  virtual ~SPxSCIP()
213  {
214  if( _probname != NULL )
215  spx_free(_probname); /*lint !e1551*/
216 
217  if( _colStat != NULL )
218  spx_free(_colStat); /*lint !e1551*/
219 
220  if( _rowStat != NULL )
221  spx_free(_rowStat); /*lint !e1551*/
222 
223  freePreStrongbranchingBasis(); /*lint !e1551*/
224 
225 #ifdef WITH_LPSCHECK
226  (void) CPXfreeprob(_cpxenv, &_cpxlp);
227  (void) CPXcloseCPLEX(&_cpxenv);
228 #endif
229  }
230 
231  // we might need these methods to return the original values SCIP provided, even if they could not be set
232  /** return feastol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
233  Real feastol() const
234  {
235  return realParam(FEASTOL);
236  }
237 
238  /** set feastol and store value in case SoPlex only accepts a larger tolerance */
239  void setFeastol(
240  const Real d
241  )
242  {
243  CHECK_SOPLEX_PARAM(setRealParam(FEASTOL, d));
244  }
245 
246  /** return opttol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
247  Real opttol() const
248  {
249  return realParam(OPTTOL);
250  }
251 
252  /** set opttol and store value in case SoPlex only accepts a larger tolerance */
253  void setOpttol(
254  const Real d
255  )
256  {
257  CHECK_SOPLEX_PARAM(setRealParam(OPTTOL, d));
258  }
259 
260  /** get objective limit according to objective sense */
261  Real getObjLimit() const
262  {
263  return (intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE)
264  ? realParam(SoPlex::OBJLIMIT_UPPER)
265  : realParam(SoPlex::OBJLIMIT_LOWER);
266  }
267 
268  // @todo realize this with a member variable as before
269  bool getFromScratch() const
270  {
271  return _fromscratch;
272  }
273 
274  void setFromScratch(bool fs)
275  {
276  _fromscratch = fs;
277  }
278 
279  // @todo member variable?
280  bool getLpInfo() const
281  {
282  return _lpinfo;
283  }
284 
285  void setLpInfo(bool lpinfo)
286  {
287  _lpinfo = lpinfo;
288  }
289 
290  // @todo member variable?
291  void setProbname(const char* probname)
292  {
293  int len;
294 
295  assert(probname != NULL);
296  if( _probname != NULL )
297  spx_free(_probname);
298  len = (int)strlen(probname);
299  spx_alloc(_probname, len + 1);
300  strncpy(_probname, probname, len); /*lint !e732*/
301  _probname[len] = '\0';
302  }
303 
304  void setRep(SPxSolver::Representation p_rep)
305  {
306  if( p_rep == SPxSolver::COLUMN && intParam(REPRESENTATION) == REPRESENTATION_ROW )
307  {
308  SCIPdebugMessage("switching to column representation of the basis\n");
309  CHECK_SOPLEX_PARAM(setIntParam(REPRESENTATION, REPRESENTATION_COLUMN));
310  }
311  else if( (p_rep == SPxSolver::ROW && intParam(REPRESENTATION) == REPRESENTATION_COLUMN) )
312  {
313  SCIPdebugMessage("switching to row representation of the basis\n");
314  CHECK_SOPLEX_PARAM(setIntParam(REPRESENTATION, REPRESENTATION_ROW));
315  }
316  }
317 
318 #ifdef WITH_LPSCHECK
319  bool getDoubleCheck()
320  {
321  _checknum++;
322  return _doublecheck && _checknum + 1 >= CHECK_START;
323  }
324 
325  void setDoubleCheck(bool dc)
326  {
327  _doublecheck = dc;
328  }
329 
330  const char* spxStatusString(const SPxSolver::Status stat) const
331  {
332  switch( stat )
333  {
334  case SPxSolver::ABORT_TIME:
335  return "ABORT_TIME";
336  case SPxSolver::ABORT_ITER:
337  return "ABORT_ITER";
338  case SPxSolver::ABORT_VALUE:
339  return "ABORT_VALUE";
340  case SPxSolver::SINGULAR:
341  return "SINGULAR";
342  case SPxSolver::REGULAR:
343  return "REGULAR";
344  case SPxSolver::UNKNOWN:
345  return "UNKNOWN";
346  case SPxSolver::OPTIMAL:
347  return "OPTIMAL";
348  case SPxSolver::UNBOUNDED:
349  return "UNBOUNDED";
350  case SPxSolver::INFEASIBLE:
351  return "INFEASIBLE";
352  default:
353  return "UNKNOWN";
354  } /*lint !e788*/
355  }
356 
357  const char* cpxStatusString(const int stat) const
358  {
359  switch( stat )
360  {
361  case CPX_STAT_ABORT_TIME_LIM:
362  return "ABORT_TIME";
363  case CPX_STAT_ABORT_IT_LIM:
364  return "ABORT_ITER";
365  case CPX_STAT_ABORT_OBJ_LIM:
366  return "ABORT_VALUE";
367  case CPX_STAT_OPTIMAL:
368  return "OPTIMAL";
369  case CPX_STAT_OPTIMAL_INFEAS:
370  return "CPX_STAT_OPTIMAL_INFEAS: OPT SOL INFEASIBLE AFTER UNSCALING";
371  case CPX_STAT_UNBOUNDED:
372  return "UNBOUNDED";
373  case CPX_STAT_INFEASIBLE:
374  return "INFEASIBLE";
375  case CPX_STAT_INForUNBD:
376  return "INFEASIBLE or UNBOUNDED";
377  case CPX_STAT_NUM_BEST:
378  return "CPX_STAT_NUM_BEST: SOL AVAILABLE BUT NOT PROVEN OPTIMAL DUE TO NUM TROUBLE";
379  default:
380  return "UNKNOWN";
381  } /*lint !e788*/
382  }
383 #endif
384 
385 #ifndef NDEBUG
386  bool checkConsistentBounds() const
387  {
388  for( int i = 0; i < numColsReal(); ++i )
389  {
390  if( lowerReal(i) > upperReal(i) + realParam(SoPlex::EPSILON_ZERO) )
391  {
392  SCIPerrorMessage("inconsistent bounds on column %d: lower=%.17g, upper=%.17g\n",
393  i, lowerReal(i), upperReal(i));
394  return false;
395  }
396  }
397 
398  return true;
399  }
400 
401  bool checkConsistentSides() const
402  {
403  for( int i = 0; i < numRowsReal(); ++i )
404  {
405  if( lhsReal(i) > rhsReal(i) + realParam(SoPlex::EPSILON_ZERO) )
406  {
407  SCIPerrorMessage("inconsistent sides on row %d: lhs=%.17g, rhs=%.17g\n",
408  i, lhsReal(i), rhsReal(i));
409  return false;
410  }
411  }
412 
413  return true;
414  }
415 #endif
416 
417  void trySolve(bool printwarning = true)
418  {
419  Real timespent;
420  Real timelimit;
421 
422  try
423  {
424  (void) solve();
425  }
426  catch(const SPxException& x)
427  {
428  std::string s = x.what();
429  if( printwarning )
430  {
431  SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
432  }
433 
434  /* since it is not clear if the status in SoPlex are set correctly
435  * we want to make sure that if an error is thrown the status is
436  * not OPTIMAL anymore.
437  */
438  assert(status() != SPxSolver::OPTIMAL);
439  }
440 
441  assert(intParam(ITERLIMIT) < 0 || numIterations() <= intParam(ITERLIMIT));
442 
443  /* update time limit */
444  timespent = solveTime();
445  if( timespent > 0 )
446  {
447  /* get current time limit */
448  timelimit = realParam(TIMELIMIT);
449  if( timelimit > timespent )
450  timelimit -= timespent;
451  else
452  timelimit = 0;
453  /* set new time limit */
454  assert(timelimit >= 0);
455  CHECK_SOPLEX_PARAM(setRealParam(TIMELIMIT, timelimit));
456  }
457  }
458 
459  SPxSolver::Status doSolve(bool printwarning = true)
460  {
461  SPxOut::Verbosity verbosity;
462 
463  SPxSolver::Status spxStatus;
464 
465  /* store and set verbosity */
466  verbosity = spxout.getVerbosity();
467  spxout.setVerbosity((SPxOut::Verbosity)(getLpInfo() ? SOPLEX_VERBLEVEL : 0));
468 
469  assert(checkConsistentBounds());
470  assert(checkConsistentSides());
471 
472 #ifdef WITH_LPSCHECK
473  /* dump LP with current basis and settings saved in SoPlex */
474  if( getDoubleCheck() )
475  writeStateReal("spxcheck", NULL, NULL);
476 #endif
477 
478  trySolve(printwarning);
479  spxStatus = status();
480 
481  /* for safety reset iteration limit */
482 // setTerminationIter(_itlim);
483 
484 #ifdef WITH_LPSCHECK
485  bool minimize = intParam(OBJSENSE) == OBJSENSE_MINIMIZE;
486  Real objLimitUpper = realParam(OBJLIMIT_UPPER);
487  Real objLimitLower = realParam(OBJLIMIT_LOWER);
488 
489  /* if SoPlex gave a definite answer, we double check if it is consistent with CPLEX's answer */
490  if( getDoubleCheck() && (spxStatus == SPxSolver::OPTIMAL || spxStatus == SPxSolver::UNBOUNDED || spxStatus == SPxSolver::INFEASIBLE || spxStatus == SPxSolver::ABORT_VALUE) )
491  {
492  SCIP_Real cpxobj;
493  int cpxstat;
494 
495  /* read LP with basis */
496  CPX_CALL( CPXreadcopyprob(_cpxenv, _cpxlp, "spxcheck.mps", NULL) );
497  CPX_CALL( CPXreadcopybase(_cpxenv, _cpxlp, "spxcheck.bas") );
498 
499  /* set tolerances */
500  CPX_CALL( CPXsetdblparam(_cpxenv, CPX_PARAM_EPOPT, MAX(opttol(), 1e-9)) );
501  CPX_CALL( CPXsetdblparam(_cpxenv, CPX_PARAM_EPRHS, MAX(feastol(), 1e-9)) );
502 
503  /* solve LP */
504  CPX_CALL( CPXlpopt(_cpxenv, _cpxlp) );
505 
506  /* get solution status and objective value */
507  CPX_CALL( CPXsolution(_cpxenv, _cpxlp, &cpxstat, &cpxobj, NULL, NULL, NULL, NULL) );
508  if( !minimize )
509  cpxobj *= -1.0;
510 
511  /* check for inconsistent statuses */
512  if( cpxstat == CPX_STAT_OPTIMAL_INFEAS )
513  {
514  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s)\n",
515  _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat));
516  if( EXIT_AT_CPXERROR )
517  exit(1);
518  }
519  else if( (spxStatus == SPxSolver::OPTIMAL && cpxstat != CPX_STAT_OPTIMAL)
520  || (spxStatus == SPxSolver::UNBOUNDED && cpxstat != CPX_STAT_UNBOUNDED)
521  || (spxStatus == SPxSolver::INFEASIBLE && cpxstat != CPX_STAT_INFEASIBLE) )
522  {
523  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
524  _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
525  if( EXIT_AT_WRONG_RESULT )
526  exit(1);
527  }
528  else if( spxStatus == SPxSolver::ABORT_VALUE )
529  {
530  switch( cpxstat )
531  {
532  case CPX_STAT_OPTIMAL:
533  if( (minimize && LTrel(cpxobj, objLimitUpper, 2*opttol()))
534  || (!minimize && GTrel(cpxobj, objLimitLower, 2*opttol())) )
535  {
536  SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
537  _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize ? "<" : ">",
538  minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
539  if( EXIT_AT_WRONG_RESULT )
540  exit(1);
541  }
542  else if( (minimize && cpxobj < objLimitUpper) || (!minimize && cpxobj > objLimitLower) )
543  {
544  SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
545  _probname, spxStatus, spxStatusString(spxStatus), cpxobj, minimize? "<" : ">",
546  minimize ? objLimitUpper : objLimitLower, cpxStatusString(cpxstat), _checknum);
547  }
548  break;
549  case CPX_STAT_OPTIMAL_INFEAS:
550  case CPX_STAT_NUM_BEST:
551  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_INFEASIBLE:
559  break;
560  case CPX_STAT_UNBOUNDED:
561  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
562  _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
563  if( EXIT_AT_WRONG_RESULT )
564  exit(1);
565  break;
566  case CPX_STAT_INForUNBD:
567  default:
568  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
569  _probname, spxStatus, spxStatusString(spxStatus), cpxstat, cpxStatusString(cpxstat), _checknum);
570  break;
571  } /*lint !e788*/
572  }
573  /* check for same objective values */
574  else if( spxStatus == SPxSolver::OPTIMAL )
575  {
576  if( (minimize && LTrel(objValueReal(), cpxobj, 2*opttol()))
577  || (!minimize && GTrel(objValueReal(), cpxobj, 2*opttol())) )
578  {
579  /* SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f too good (checknum=%d)\n", value(),
580  _probname, getSense() == SPxSolver::MINIMIZE ? "<" : ">", cpxobj, _checknum); */
581  }
582  else if( (minimize && GTrel(objValueReal(), cpxobj, 2*opttol()))
583  || (!minimize && LTrel(objValueReal(), cpxobj, 2*opttol())) )
584  {
585  SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f suboptimal (checknum=%d)\n", objValueReal(),
586  _probname, minimize ? ">" : "<", cpxobj, _checknum);
587  if( EXIT_AT_WRONG_RESULT )
588  exit(1);
589  }
590  }
591  }
592 
593  ENDCHECK:
594 #endif
595 
596  /* restore verbosity */
597  spxout.setVerbosity(verbosity);
598 
599  return spxStatus;
600  }
601 
602  /** save the current basis */
603  void savePreStrongbranchingBasis()
604  {
605  assert(_rowStat == NULL);
606  assert(_colStat == NULL);
607 
608  spx_alloc(_rowStat, numRowsReal());
609  spx_alloc(_colStat, numColsReal());
610 
611  try
612  {
613  getBasis(_rowStat, _colStat);
614  }
615  catch(const SPxException& x)
616  {
617 #ifndef NDEBUG
618  std::string s = x.what();
619  SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
620 
621  /* since it is not clear if the status in SoPlex are set correctly
622  * we want to make sure that if an error is thrown the status is
623  * not OPTIMAL anymore.
624  */
625  assert(status() != SPxSolver::OPTIMAL);
626 #endif
627  }
628  }
629 
630  /** restore basis */
631  void restorePreStrongbranchingBasis()
632  {
633  assert(_rowStat != NULL);
634  assert(_colStat != NULL);
635 
636  try
637  {
638  setBasis(_rowStat, _colStat);
639  }
640  catch(const SPxException& x)
641  {
642 #ifndef NDEBUG
643  std::string s = x.what();
644  SCIPmessagePrintWarning(_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
645 #endif
646  /* since it is not clear if the status in SoPlex are set correctly
647  * we want to make sure that if an error is thrown the status is
648  * not OPTIMAL anymore.
649  */
650  assert(status() != SPxSolver::OPTIMAL);
651  }
652  }
653 
654  /** if basis is in store, delete it without restoring it */
655  void freePreStrongbranchingBasis()
656  {
657  if( _rowStat != NULL )
658  spx_free(_rowStat);
659  if( _colStat != NULL )
660  spx_free(_colStat);
661  }
662 
663  /** is pre-strong-branching basis freed? */
664  bool preStrongbranchingBasisFreed() const
665  {
666  return ((_rowStat == NULL ) && (_colStat == NULL));
667  }
668 
669 }; /*lint !e1748*/
670 
671 
672 
673 
674 /********************************************************************/
675 /*----------------------------- C --------------------------------*/
676 /********************************************************************/
677 
678 #include "lpi/lpi.h"
679 #include "scip/bitencode.h"
680 
681 typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
682 #define COLS_PER_PACKET SCIP_DUALPACKETSIZE
683 typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
684 #define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
688 /** LP interface */
689 struct SCIP_LPi
690 {
691  SPxSCIP* spx; /**< our SoPlex implementation */
692  int* cstat; /**< array for storing column basis status */
693  int* rstat; /**< array for storing row basis status */
694  int cstatsize; /**< size of cstat array */
695  int rstatsize; /**< size of rstat array */
696  SCIP_PRICING pricing; /**< current pricing strategy */
697  SCIP_Bool solved; /**< was the current LP solved? */
698  SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
699  SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
700  SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
701 };
702 
703 /** LPi state stores basis information */
704 struct SCIP_LPiState
705 {
706  int ncols; /**< number of LP columns */
707  int nrows; /**< number of LP rows */
708  COLPACKET* packcstat; /**< column basis status in compressed form */
709  ROWPACKET* packrstat; /**< row basis status in compressed form */
710 };
711 
712 /** LPi norms to store dual steepest edge */
713 struct SCIP_LPiNorms
714 {
715  int nrows; /**< number of stored norms corresponding to rows */
716  int ncols; /**< number of stored norms corresponding to cols */
717  SCIP_Real* norms; /**< norms to be (re)stored */
718 };
719 
720 
721 
722 /*
723  * dynamic memory arrays
724  */
725 
726 /** resizes cstat array to have at least num entries */
727 static
728 SCIP_RETCODE ensureCstatMem(
729  SCIP_LPI* lpi, /**< LP interface structure */
730  int num /**< minimal number of entries in array */
731  )
732 {
733  assert(lpi != NULL);
734 
735  if( num > lpi->cstatsize )
736  {
737  int newsize;
738 
739  newsize = MAX(2*lpi->cstatsize, num);
740  SCIP_ALLOC( BMSreallocMemoryArray(&lpi->cstat, newsize) );
741  lpi->cstatsize = newsize;
742  }
743  assert(num <= lpi->cstatsize);
744 
745  return SCIP_OKAY;
746 }
747 
748 /** resizes rstat array to have at least num entries */
749 static
750 SCIP_RETCODE ensureRstatMem(
751  SCIP_LPI* lpi, /**< LP interface structure */
752  int num /**< minimal number of entries in array */
753  )
754 {
755  assert(lpi != NULL);
756 
757  if( num > lpi->rstatsize )
758  {
759  int newsize;
760 
761  newsize = MAX(2*lpi->rstatsize, num);
762  SCIP_ALLOC( BMSreallocMemoryArray(&lpi->rstat, newsize) );
763  lpi->rstatsize = newsize;
764  }
765  assert(num <= lpi->rstatsize);
766 
767  return SCIP_OKAY;
768 }
769 
770 
771 
772 
773 /*
774  * LPi state methods
775  */
776 
777 /** returns the number of packets needed to store column packet information */
778 static
779 int colpacketNum(
780  int ncols /**< number of columns to store */
781  )
782 {
783  return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
784 }
785 
786 /** returns the number of packets needed to store row packet information */
787 static
788 int rowpacketNum(
789  int nrows /**< number of rows to store */
790  )
791 {
792  return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
793 }
794 
795 /** store row and column basis status in a packed LPi state object */
796 static
797 void lpistatePack(
798  SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
799  const int* cstat, /**< basis status of columns in unpacked format */
800  const int* rstat /**< basis status of rows in unpacked format */
801  )
802 {
803  assert(lpistate != NULL);
804  assert(lpistate->packcstat != NULL);
805  assert(lpistate->packrstat != NULL);
806 
807  SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
808  SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
809 }
810 
811 /** unpacks row and column basis status from a packed LPi state object */
812 static
813 void lpistateUnpack(
814  const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
815  int* cstat, /**< buffer for storing basis status of columns in unpacked format */
816  int* rstat /**< buffer for storing basis status of rows in unpacked format */
817  )
818 {
819  assert(lpistate != NULL);
820  assert(lpistate->packcstat != NULL);
821  assert(lpistate->packrstat != NULL);
822 
823  SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
824  SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
825 }
826 
827 /** creates LPi state information object */
828 static
829 SCIP_RETCODE lpistateCreate(
830  SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
831  BMS_BLKMEM* blkmem, /**< block memory */
832  int ncols, /**< number of columns to store */
833  int nrows /**< number of rows to store */
834  )
835 {
836  assert(lpistate != NULL);
837  assert(blkmem != NULL);
838  assert(ncols >= 0);
839  assert(nrows >= 0);
840 
841  int nColPackets = colpacketNum(ncols);
842  int nRowPackets = rowpacketNum(nrows);
843 
844  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
845  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
846  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
847 
848  return SCIP_OKAY;
849 }
850 
851 /** frees LPi state information */
852 static
853 void lpistateFree(
854  SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
855  BMS_BLKMEM* blkmem /**< block memory */
856  )
857 {
858  assert(blkmem != NULL);
859  assert(lpistate != NULL);
860  assert(*lpistate != NULL);
861 
862  int nColPackets = colpacketNum((*lpistate)->ncols);
863  int nRowPackets = rowpacketNum((*lpistate)->nrows);
864 
865  BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
866  BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
867  BMSfreeBlockMemory(blkmem, lpistate);
868 }
869 
870 
871 
872 
873 /*
874  * local methods
875  */
876 
877 
878 /** marks the current LP to be unsolved */
879 static
880 void invalidateSolution(SCIP_LPI* lpi)
881 {
882  assert(lpi != NULL);
883  lpi->solved = FALSE;
884 }
885 
886 
887 
888 /*
889  * LP Interface Methods
890  */
891 
892 
893 /*
894  * Miscellaneous Methods
895  */
896 
897 static char spxname[100];
898 static char spxdesc[200];
899 
900 /**@name Miscellaneous Methods */
901 /**@{ */
902 
903 /** gets name and version of LP solver */
904 const char* SCIPlpiGetSolverName(
905  void
906  )
907 {
908  SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
909 
910 #if (SOPLEX_SUBVERSION > 0)
911  sprintf(spxname, "SoPlex2 %d.%d.%d.%d", SOPLEX_VERSION/100, (SOPLEX_VERSION % 100)/10, SOPLEX_VERSION % 10, SOPLEX_SUBVERSION); /*lint !e778*/
912 #else
913  sprintf(spxname, "SoPlex2 %d.%d.%d", SOPLEX_VERSION/100, (SOPLEX_VERSION % 100)/10, SOPLEX_VERSION % 10); /*lint !e778*/
914 #endif
915  return spxname;
916 }
917 
918 /** gets description of LP solver (developer, webpage, ...) */
919 const char* SCIPlpiGetSolverDesc(
920  void
921  )
922 {
923  sprintf(spxdesc, "%s", "Linear Programming Solver developed at Zuse Institute Berlin (soplex.zib.de)");
924  sprintf(spxdesc, "%s [GitHash: %s]", spxdesc, getGitHash());
925 #ifdef WITH_LPSCHECK
926  sprintf(spxdesc, "%s %s", spxdesc, "- including CPLEX double check");
927 #endif
928  return spxdesc;
929 }
930 
931 /** gets pointer for LP solver - use only with great care */
933  SCIP_LPI* lpi /**< pointer to an LP interface structure */
934  )
935 {
936  return (void*) lpi->spx;
937 }
938 /**@} */
939 
940 
941 
942 
943 /*
944  * LPI Creation and Destruction Methods
945  */
946 
947 /**@name LPI Creation and Destruction Methods */
948 /**@{ */
949 
950 /** creates an LP problem object */
952  SCIP_LPI** lpi, /**< pointer to an LP interface structure */
953  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
954  const char* name, /**< problem name */
955  SCIP_OBJSEN objsen /**< objective sense */
956  )
957 {
958  assert(lpi != NULL);
959 
960  /* create SoPlex object */
961  SCIP_ALLOC( BMSallocMemory(lpi) );
962 
963  /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
964  (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
965  SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
966  (void) (*lpi)->spx->setIntParam(SoPlex::SYNCMODE, SoPlex::SYNCMODE_ONLYREAL);
967  (void) (*lpi)->spx->setIntParam(SoPlex::SOLVEMODE, SoPlex::SOLVEMODE_REAL);
968  (void) (*lpi)->spx->setIntParam(SoPlex::REPRESENTATION, SoPlex::REPRESENTATION_AUTO);
969 
970  (*lpi)->cstat = NULL;
971  (*lpi)->rstat = NULL;
972  (*lpi)->cstatsize = 0;
973  (*lpi)->rstatsize = 0;
974  (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
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  SPxOut::Verbosity verbosity = (*lpi)->spx->spxout.getVerbosity();
989  (*lpi)->spx->spxout.setVerbosity((SPxOut::Verbosity)((*lpi)->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
990  (*lpi)->spx->printVersion();
991  (*lpi)->spx->spxout.setVerbosity(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]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
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]) + lpi->spx->realParam(SoPlex::EPSILON_ZERO));
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  )
2043 {
2044  assert( lpi != NULL );
2045  assert( lpi->spx != NULL );
2046 
2047  SPxOut::Verbosity verbosity;
2048  /* store and set verbosity */
2049  verbosity = lpi->spx->spxout.getVerbosity();
2050  lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2051 
2052  SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows\n", lpi->spx->numColsReal(), lpi->spx->numRowsReal());
2053 
2054  invalidateSolution(lpi);
2055 
2056  assert( lpi->spx->preStrongbranchingBasisFreed() );
2057 
2058 #ifdef WITH_LPSCHECK
2059  lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2060 #endif
2061 
2062  /* delete starting basis if solving from scratch */
2063  if( lpi->spx->getFromScratch() )
2064  {
2065  try
2066  {
2067  lpi->spx->clearBasis();
2068  }
2069  catch(const SPxException& x)
2070  {
2071 #ifndef NDEBUG
2072  std::string s = x.what();
2073  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2074 #endif
2075  assert( lpi->spx->status() != SPxSolver::OPTIMAL );
2076  return SCIP_LPERROR;
2077  }
2078  }
2079  assert(!lpi->spx->getFromScratch() || lpi->spx->status() == SPxSolver::NO_PROBLEM);
2080 
2081  SPxSolver::Status status = lpi->spx->doSolve();
2082  SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->status(), lpi->spx->basisStatus());
2083  lpi->solved = TRUE;
2084 
2085  /* restore verbosity */
2086  lpi->spx->spxout.setVerbosity(verbosity);
2087 
2088  switch( status )
2089  {
2090  case SPxSolver::ABORT_TIME:
2091  case SPxSolver::ABORT_ITER:
2092  case SPxSolver::ABORT_VALUE:
2093  case SPxSolver::SINGULAR:
2094  case SPxSolver::REGULAR:
2095  case SPxSolver::UNKNOWN:
2096  case SPxSolver::OPTIMAL:
2097  case SPxSolver::UNBOUNDED:
2098  case SPxSolver::INFEASIBLE:
2099  return SCIP_OKAY;
2100  default:
2101  return SCIP_LPERROR;
2102  } /*lint !e788*/
2103 }
2104 
2105 /** calls primal simplex to solve the LP */
2107  SCIP_LPI* lpi /**< LP interface structure */
2108  )
2110  SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2111 
2112  assert(lpi != NULL);
2113  assert(lpi->spx != NULL);
2114 
2115  (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_PRIMAL);
2116  return spxSolve(lpi);
2117 }
2118 
2119 /** calls dual simplex to solve the LP */
2121  SCIP_LPI* lpi /**< LP interface structure */
2122  )
2124  SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2125 
2126  assert(lpi != NULL);
2127  assert(lpi->spx != NULL);
2128 
2129  (void) lpi->spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2130  return spxSolve(lpi);
2131 }
2132 
2133 /** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
2135  SCIP_LPI* lpi, /**< LP interface structure */
2136  SCIP_Bool crossover /**< perform crossover */
2137  )
2138 { /*lint --e{715}*/
2139  SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
2140 
2141  /* Since SoPlex does not support barrier we switch to DUAL */
2142  return SCIPlpiSolveDual(lpi);
2143 }
2144 
2145 /** start strong branching - call before any strongbranching */
2147  SCIP_LPI* lpi /**< LP interface structure */
2148  )
2150  assert( lpi->spx->preStrongbranchingBasisFreed() );
2151  lpi->spx->savePreStrongbranchingBasis();
2152 
2153  return SCIP_OKAY;
2154 }
2155 
2156 /** end strong branching - call after any strongbranching */
2158  SCIP_LPI* lpi /**< LP interface structure */
2159  )
2161  assert( ! lpi->spx->preStrongbranchingBasisFreed() );
2162  lpi->spx->restorePreStrongbranchingBasis();
2163  lpi->spx->freePreStrongbranchingBasis();
2164 
2165  return SCIP_OKAY;
2166 }
2167 
2168 /** performs strong branching iterations on one arbitrary candidate */
2169 static
2170 SCIP_RETCODE lpiStrongbranch(
2171  SCIP_LPI* lpi, /**< LP interface structure */
2172  int col, /**< column to apply strong branching on */
2173  SCIP_Real psol, /**< current primal solution value of column */
2174  int itlim, /**< iteration limit for strong branchings */
2175  SCIP_Real* down, /**< stores dual bound after branching column down */
2176  SCIP_Real* up, /**< stores dual bound after branching column up */
2177  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2178  * otherwise, it can only be used as an estimate value */
2179  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2180  * otherwise, it can only be used as an estimate value */
2181  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2182  )
2183 {
2184  SPxSCIP* spx;
2185  SPxSolver::Status status;
2186  SCIP_Real oldlb;
2187  SCIP_Real oldub;
2188  SCIP_Real newlb;
2189  SCIP_Real newub;
2190  bool fromparentbasis;
2191  bool error;
2192  int oldItlim;
2193  SPxOut::Verbosity verbosity;
2194 
2195  /* store and set verbosity */
2196  verbosity = lpi->spx->spxout.getVerbosity();
2197  lpi->spx->spxout.setVerbosity((SPxOut::Verbosity)(lpi->spx->getLpInfo() ? SOPLEX_VERBLEVEL : 0));
2198 
2199  SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
2200 
2201  assert(lpi != NULL);
2202  assert(lpi->spx != NULL);
2203  /* assert(down != NULL);
2204  * assert(up != NULL); temporary hack for cloud branching */
2205  assert(downvalid != NULL);
2206  assert(upvalid != NULL);
2207 
2208  spx = lpi->spx;
2209  status = SPxSolver::UNKNOWN;
2210  fromparentbasis = false;
2211  error = false;
2212  oldItlim = spx->intParam(SoPlex::ITERLIMIT);
2213 
2214  /* get current bounds of column */
2215  oldlb = spx->lowerReal(col);
2216  oldub = spx->upperReal(col);
2217 
2218  *downvalid = FALSE;
2219  *upvalid = FALSE;
2220 
2221  if( iter != NULL )
2222  *iter = 0;
2223 
2224  /* set the algorithm type to use dual simplex */
2225 
2226  (void) spx->setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_DUAL);
2227 
2228 
2229  /* down branch */
2230  newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
2231  if( newub >= oldlb - 0.5 && down != NULL )
2232  {
2233  SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
2234 
2235  spx->changeUpperReal(col, newub);
2236  assert(spx->lowerReal(col) <= spx->upperReal(col));
2237 
2238  (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2239  do
2240  {
2241 #ifdef WITH_LPSCHECK
2242  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2243 #endif
2244  status = spx->solve();
2245  SCIPdebugMessage(" --> Terminate with status %d\n", status);
2246  switch( status )
2247  {
2248  case SPxSolver::OPTIMAL:
2249  *down = spx->objValueReal();
2250  *downvalid = TRUE;
2251  SCIPdebugMessage(" --> Terminate with value %f\n", *down);
2252  break;
2253  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2254  case SPxSolver::ABORT_ITER:
2255  case SPxSolver::ABORT_CYCLING:
2256  *down = spx->objValueReal();
2257  break;
2258  case SPxSolver::ABORT_VALUE:
2259  case SPxSolver::INFEASIBLE:
2260  *down = spx->getObjLimit();
2261  *downvalid = TRUE;
2262  break;
2263  default:
2264  error = true;
2265  break;
2266  } /*lint !e788*/
2267  if( iter != NULL )
2268  (*iter) += spx->numIterations();
2269 
2270 #ifdef STRONGBRANCH_RESTOREBASIS
2271  /* we restore the pre-strong-branching basis by default (and don't solve again) */
2272  assert( ! spx->preStrongbranchingBasisFreed() );
2273  spx->restorePreStrongbranchingBasis();
2274  fromparentbasis = false;
2275 #else
2276  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2277  * pre-strong-branching basis and try again with reduced iteration limit */
2278  if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim )
2279  {
2280  SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n",
2281  itlim - spx->numIterations());
2282  spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2283  assert( ! spx->hasPreStrongbranchingBasis() );
2284  spx->restorePreStrongbranchingBasis();
2285  fromparentbasis = true;
2286  error = false;
2287  }
2288  /* otherwise don't solve again */
2289  else
2290  fromparentbasis = false;
2291 #endif
2292  }
2293  while( fromparentbasis );
2294 
2295  spx->changeUpperReal(col, oldub);
2296  assert(spx->lowerReal(col) <= spx->upperReal(col));
2297  }
2298  else if( down != NULL )
2299  {
2300  *down = spx->getObjLimit();
2301  *downvalid = TRUE;
2302  }
2303  else
2304  *downvalid = TRUE;
2305 
2306  /* up branch */
2307  if( !error )
2308  {
2309  newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
2310  if( newlb <= oldub + 0.5 && up != NULL )
2311  {
2312  SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
2313 
2314  spx->changeLowerReal(col, newlb);
2315  assert(spx->lowerReal(col) <= spx->upperReal(col));
2316 
2317  (void) spx->setIntParam(SoPlex::ITERLIMIT, itlim);
2318  do
2319  {
2320 #ifdef WITH_LPSCHECK
2321  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
2322 #endif
2323  status = spx->solve();
2324  SCIPdebugMessage(" --> Terminate with status %d\n", status);
2325  switch( status )
2326  {
2327  case SPxSolver::OPTIMAL:
2328  *up = spx->objValueReal();
2329  *upvalid = TRUE;
2330  SCIPdebugMessage(" --> Terminate with value %f\n", spx->objValueReal());
2331  break;
2332  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
2333  case SPxSolver::ABORT_ITER:
2334  case SPxSolver::ABORT_CYCLING:
2335  *up = spx->objValueReal();
2336  break;
2337  case SPxSolver::ABORT_VALUE:
2338  case SPxSolver::INFEASIBLE:
2339  *up = spx->getObjLimit();
2340  *upvalid = TRUE;
2341  break;
2342  default:
2343  error = true;
2344  break;
2345  } /*lint !e788*/
2346  if( iter != NULL )
2347  (*iter) += spx->numIterations();
2348 
2349 #ifdef STRONGBRANCH_RESTOREBASIS
2350  /* we restore the pre-strong-branching basis by default (and don't solve again) */
2351  assert( ! spx->preStrongbranchingBasisFreed() );
2352  spx->restorePreStrongbranchingBasis();
2353  fromparentbasis = false;
2354 #else
2355  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
2356  * pre-strong-branching basis and try again with reduced iteration limit */
2357  else if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->numIterations() < itlim )
2358  {
2359  SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->numIterations());
2360  assert( ! spx->hasPreStrongbranchingBasis() );
2361  spx->restorePreStrongbranchingBasis();
2362  spx->setIntParam(SoPlex::ITERLIMIT, itlim - spx->numIterations());
2363  error = false;
2364  fromparentbasis = true;
2365  }
2366  /* otherwise don't solve again */
2367  else
2368  fromparentbasis = false;
2369 #endif
2370  }
2371  while( fromparentbasis );
2372 
2373  spx->changeLowerReal(col, oldlb);
2374  assert(spx->lowerReal(col) <= spx->upperReal(col));
2375  }
2376  else if( up != NULL )
2377  {
2378  *up = spx->getObjLimit();
2379  *upvalid = TRUE;
2380  }
2381  else
2382  *upvalid = TRUE;
2383  }
2384 
2385  /* reset old iteration limit */
2386  (void) spx->setIntParam(SoPlex::ITERLIMIT, oldItlim);
2387 
2388  /* restore verbosity */
2389  lpi->spx->spxout.setVerbosity(verbosity);
2390 
2391  if( error )
2392  {
2393  SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status));
2394  return SCIP_LPERROR;
2395  }
2396 
2397  return SCIP_OKAY;
2398 }
2399 
2400 /** performs strong branching iterations on one @b fractional candidate */
2402  SCIP_LPI* lpi, /**< LP interface structure */
2403  int col, /**< column to apply strong branching on */
2404  SCIP_Real psol, /**< fractional current primal solution value of column */
2405  int itlim, /**< iteration limit for strong branchings */
2406  SCIP_Real* down, /**< stores dual bound after branching column down */
2407  SCIP_Real* up, /**< stores dual bound after branching column up */
2408  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2409  * otherwise, it can only be used as an estimate value */
2410  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2411  * otherwise, it can only be used as an estimate value */
2412  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2413  )
2414 {
2415  SCIP_RETCODE retcode;
2416 
2417  /* pass call on to lpiStrongbranch() */
2418  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2419 
2420  /* pass SCIP_LPERROR to SCIP without a back trace */
2421  if( retcode == SCIP_LPERROR )
2422  return SCIP_LPERROR;
2423 
2424  /* evaluate retcode */
2425  SCIP_CALL( retcode );
2426 
2427  return SCIP_OKAY;
2428 }
2429 
2430 /** performs strong branching iterations on given @b fractional candidates */
2432  SCIP_LPI* lpi, /**< LP interface structure */
2433  int* cols, /**< columns to apply strong branching on */
2434  int ncols, /**< number of columns */
2435  SCIP_Real* psols, /**< fractional current primal solution values of columns */
2436  int itlim, /**< iteration limit for strong branchings */
2437  SCIP_Real* down, /**< stores dual bounds after branching columns down */
2438  SCIP_Real* up, /**< stores dual bounds after branching columns up */
2439  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2440  * otherwise, they can only be used as an estimate values */
2441  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2442  * otherwise, they can only be used as an estimate values */
2443  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2444  )
2445 {
2446  SCIP_RETCODE retcode;
2447 
2448  assert( cols != NULL );
2449  assert( psols != NULL );
2450  assert( down != NULL );
2451  assert( up != NULL );
2452  assert( downvalid != NULL );
2453  assert( upvalid != NULL );
2454  assert( down != NULL );
2455 
2456  if ( iter != NULL )
2457  *iter = 0;
2458 
2459  for (int j = 0; j < ncols; ++j)
2460  {
2461  /* pass call on to lpiStrongbranch() */
2462  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2463 
2464  /* pass SCIP_LPERROR to SCIP without a back trace */
2465  if( retcode == SCIP_LPERROR )
2466  return SCIP_LPERROR;
2467 
2468  /* evaluate retcode */
2469  SCIP_CALL( retcode );
2470  }
2471  return SCIP_OKAY;
2472 }
2473 
2474 /** performs strong branching iterations on one candidate with @b integral value */
2476  SCIP_LPI* lpi, /**< LP interface structure */
2477  int col, /**< column to apply strong branching on */
2478  SCIP_Real psol, /**< current integral primal solution value of column */
2479  int itlim, /**< iteration limit for strong branchings */
2480  SCIP_Real* down, /**< stores dual bound after branching column down */
2481  SCIP_Real* up, /**< stores dual bound after branching column up */
2482  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2483  * otherwise, it can only be used as an estimate value */
2484  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2485  * otherwise, it can only be used as an estimate value */
2486  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2487  )
2488 {
2489  SCIP_RETCODE retcode;
2490 
2491  /* pass call on to lpiStrongbranch() */
2492  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
2493 
2494  /* pass SCIP_LPERROR to SCIP without a back trace */
2495  if( retcode == SCIP_LPERROR )
2496  return SCIP_LPERROR;
2497 
2498  /* evaluate retcode */
2499  SCIP_CALL( retcode );
2500 
2501  return SCIP_OKAY;
2502 }
2503 
2504 /** performs strong branching iterations on given candidates with @b integral values */
2506  SCIP_LPI* lpi, /**< LP interface structure */
2507  int* cols, /**< columns to apply strong branching on */
2508  int ncols, /**< number of columns */
2509  SCIP_Real* psols, /**< current integral primal solution values of columns */
2510  int itlim, /**< iteration limit for strong branchings */
2511  SCIP_Real* down, /**< stores dual bounds after branching columns down */
2512  SCIP_Real* up, /**< stores dual bounds after branching columns up */
2513  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
2514  * otherwise, they can only be used as an estimate values */
2515  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
2516  * otherwise, they can only be used as an estimate values */
2517  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2518  )
2519 {
2520  SCIP_RETCODE retcode;
2521 
2522  assert( cols != NULL );
2523  assert( psols != NULL );
2524  assert( down != NULL );
2525  assert( up != NULL );
2526  assert( downvalid != NULL );
2527  assert( upvalid != NULL );
2528  assert( down != NULL );
2529 
2530  if ( iter != NULL )
2531  *iter = 0;
2532 
2533  for (int j = 0; j < ncols; ++j)
2534  {
2535  /* pass call on to lpiStrongbranch() */
2536  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
2537 
2538  /* pass SCIP_LPERROR to SCIP without a back trace */
2539  if( retcode == SCIP_LPERROR )
2540  return SCIP_LPERROR;
2541 
2542  /* evaluate retcode */
2543  SCIP_CALL( retcode );
2544  }
2545 
2546  return SCIP_OKAY;
2547 }
2548 /**@} */
2549 
2550 
2551 
2552 
2553 /*
2554  * Solution Information Methods
2555  */
2556 
2557 /**@name Solution Information Methods */
2558 /**@{ */
2559 
2560 /** returns whether a solve method was called after the last modification of the LP */
2562  SCIP_LPI* lpi /**< LP interface structure */
2563  )
2565  assert(lpi != NULL);
2566 
2567  return lpi->solved;
2568 }
2569 
2570 /** gets information about primal and dual feasibility of the current LP solution */
2572  SCIP_LPI* lpi, /**< LP interface structure */
2573  SCIP_Bool* primalfeasible, /**< stores primal feasibility status */
2574  SCIP_Bool* dualfeasible /**< stores dual feasibility status */
2575  )
2576 {
2577  SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
2578 
2579  assert(lpi != NULL);
2580  assert(primalfeasible != NULL);
2581  assert(dualfeasible != NULL);
2582 
2583  *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
2584  *dualfeasible = SCIPlpiIsDualFeasible(lpi);
2585 
2586  return SCIP_OKAY;
2587 }
2588 
2589 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
2590  * this does not necessarily mean, that the solver knows and can return the primal ray
2591  */
2593  SCIP_LPI* lpi /**< LP interface structure */
2594  )
2596  SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
2597 
2598  assert(lpi != NULL);
2599  assert(lpi->spx != NULL);
2600 
2601  return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2602 }
2603 
2604 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
2605  * and the solver knows and can return the primal ray
2606  */
2608  SCIP_LPI* lpi /**< LP interface structure */
2609  )
2611  SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
2612 
2613  assert(lpi != NULL);
2614  assert(lpi->spx != NULL);
2615 
2616  return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2617 }
2618 
2619 /** returns TRUE iff LP is proven to be primal unbounded */
2621  SCIP_LPI* lpi /**< LP interface structure */
2622  )
2624  SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
2625 
2626  assert(lpi != NULL);
2627  assert(lpi->spx != NULL);
2628 
2629  assert(lpi->spx->status() != SPxSolver::UNBOUNDED || lpi->spx->basisStatus() == SPxBasis::UNBOUNDED);
2630 
2631  /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
2632  * feasible point; hence we have to check the perturbation
2633  */
2634  return lpi->spx->status() == SPxSolver::UNBOUNDED;
2635 }
2636 
2637 /** returns TRUE iff LP is proven to be primal infeasible */
2639  SCIP_LPI* lpi /**< LP interface structure */
2640  )
2642  SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
2643 
2644  assert(lpi != NULL);
2645  assert(lpi->spx != NULL);
2646 
2647  return (lpi->spx->status() == SPxSolver::INFEASIBLE);
2648 }
2649 
2650 /** returns TRUE iff LP is proven to be primal feasible */
2652  SCIP_LPI* lpi /**< LP interface structure */
2653  )
2655  SPxBasis::SPxStatus basestatus;
2656 
2657  SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
2658 
2659  assert(lpi != NULL);
2660  assert(lpi->spx != NULL);
2661 
2662  basestatus = lpi->spx->basisStatus();
2663 
2664  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
2665  * still return true as long as perturbation plus violation is within tolerances
2666  */
2667  assert(basestatus == SPxBasis::OPTIMAL || lpi->spx->status() != SPxSolver::OPTIMAL);
2668 
2669  return basestatus == SPxBasis::OPTIMAL || basestatus == SPxBasis::PRIMAL;
2670 }
2671 
2672 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
2673  * this does not necessarily mean, that the solver knows and can return the dual ray
2674  */
2676  SCIP_LPI* lpi /**< LP interface structure */
2677  )
2679  SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
2680 
2681  assert(lpi != NULL);
2682  assert(lpi->spx != NULL);
2683 
2684  return (lpi->spx->status() == SPxSolver::INFEASIBLE);
2685 }
2686 
2687 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
2688  * and the solver knows and can return the dual ray
2689  */
2691  SCIP_LPI* lpi /**< LP interface structure */
2692  )
2694  SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
2695 
2696  assert(lpi != NULL);
2697  assert(lpi->spx != NULL);
2698 
2699  return (lpi->spx->status() == SPxSolver::INFEASIBLE);
2700 }
2701 
2702 /** returns TRUE iff LP is dual unbounded */
2704  SCIP_LPI* lpi /**< LP interface structure */
2705  )
2707  SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
2708 
2709  assert(lpi != NULL);
2710  assert(lpi->spx != NULL);
2711 
2712  return lpi->spx->status() == SPxSolver::INFEASIBLE && lpi->spx->basisStatus() == SPxBasis::DUAL;
2713 }
2714 
2715 /** returns TRUE iff LP is dual infeasible */
2717  SCIP_LPI* lpi /**< LP interface structure */
2718  )
2720  SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
2721 
2722  assert(lpi != NULL);
2723  assert(lpi->spx != NULL);
2724 
2725  return (lpi->spx->status() == SPxSolver::UNBOUNDED);
2726 }
2727 
2728 /** returns TRUE iff LP is proven to be dual feasible */
2730  SCIP_LPI* lpi /**< LP interface structure */
2731  )
2733  SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
2734 
2735  assert(lpi != NULL);
2736  assert(lpi->spx != NULL);
2737 
2738  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
2739  * still return true as long as perturbation plus violation is within tolerances
2740  */
2741  assert(lpi->spx->basisStatus() == SPxBasis::OPTIMAL || lpi->spx->status() != SPxSolver::OPTIMAL);
2742 
2743  return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL) || lpi->spx->basisStatus() == SPxBasis::DUAL;
2744 }
2745 
2746 /** returns TRUE iff LP was solved to optimality */
2748  SCIP_LPI* lpi /**< LP interface structure */
2749  )
2751  SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
2752 
2753  assert(lpi != NULL);
2754  assert((lpi->spx->basisStatus() == SPxBasis::OPTIMAL)
2756 
2757  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
2758  * still return true as long as perturbation plus violation is within tolerances
2759  */
2760  return (lpi->spx->basisStatus() == SPxBasis::OPTIMAL);
2761 }
2762 
2763 /** returns TRUE iff current LP basis is stable */
2765  SCIP_LPI* lpi /**< LP interface structure */
2766  )
2768  SCIPdebugMessage("calling SCIPlpiIsStable()\n");
2769 
2770  assert(lpi != NULL);
2771  assert(lpi->spx != NULL);
2772 
2773  if( lpi->spx->status() == SPxSolver::ERROR || lpi->spx->status() == SPxSolver::SINGULAR )
2774  return FALSE;
2775 
2776  /* only if we have a regular basis and the condition limit is set, we compute the condition number of the basis;
2777  * everything above the specified threshold is then counted as instable
2778  */
2779  if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
2780  {
2781  SCIP_RETCODE retcode;
2782  SCIP_Real kappa;
2783 
2785  if( retcode != SCIP_OKAY )
2786  {
2787  SCIPABORT();
2788  }
2789  assert(kappa != SCIP_INVALID); /*lint !e777*/
2790 
2791  if( kappa > lpi->conditionlimit )
2792  return FALSE;
2793  }
2794 
2795  return TRUE;
2796 }
2797 
2798 /** returns TRUE iff the objective limit was reached */
2800  SCIP_LPI* lpi /**< LP interface structure */
2801  )
2803  SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
2804 
2805  assert(lpi != NULL);
2806  assert(lpi->spx != NULL);
2807 
2808  return (lpi->spx->status() == SPxSolver::ABORT_VALUE);
2809 }
2810 
2811 /** returns TRUE iff the iteration limit was reached */
2813  SCIP_LPI* lpi /**< LP interface structure */
2814  )
2816  SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
2817 
2818  assert(lpi != NULL);
2819  assert(lpi->spx != NULL);
2820 
2821  return (lpi->spx->status() == SPxSolver::ABORT_ITER);
2822 }
2823 
2824 /** returns TRUE iff the time limit was reached */
2826  SCIP_LPI* lpi /**< LP interface structure */
2827  )
2829  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
2830 
2831  assert(lpi != NULL);
2832  assert(lpi->spx != NULL);
2833 
2834  return (lpi->spx->status() == SPxSolver::ABORT_TIME);
2835 }
2836 
2837 /** returns the internal solution status of the solver */
2839  SCIP_LPI* lpi /**< LP interface structure */
2840  )
2842  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
2843 
2844  assert(lpi != NULL);
2845  assert(lpi->spx != NULL);
2846 
2847  return static_cast<int>(lpi->spx->status());
2848 }
2849 
2850 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
2852  SCIP_LPI* lpi, /**< LP interface structure */
2853  SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
2854  )
2855 { /*lint --e{715}*/
2856  SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
2857 
2858  assert(lpi != NULL);
2859  assert(lpi->spx != NULL);
2860 
2861  /* instable situations cannot be ignored */
2862  *success = FALSE;
2863 
2864  return SCIP_OKAY;
2865 }
2866 
2867 /** gets objective value of solution */
2869  SCIP_LPI* lpi, /**< LP interface structure */
2870  SCIP_Real* objval /**< stores the objective value */
2871  )
2872 {
2873  SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
2874 
2875  assert(lpi != NULL);
2876  assert(lpi->spx != NULL);
2877  assert(objval != NULL);
2878 
2879  *objval = lpi->spx->objValueReal();
2880 
2881  return SCIP_OKAY;
2882 }
2883 
2884 /** gets primal and dual solution vectors */
2886  SCIP_LPI* lpi, /**< LP interface structure */
2887  SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
2888  SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
2889  SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
2890  SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
2891  SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
2892  )
2893 {
2894  SCIPdebugMessage("calling SCIPlpiGetSol()\n");
2895 
2896  assert(lpi != NULL);
2897  assert(lpi->spx != NULL);
2898 
2899  if( objval != NULL )
2900  *objval = lpi->spx->objValueReal();
2901 
2902  try
2903  {
2904  if( primsol != NULL )
2905  {
2906  Vector tmp(lpi->spx->numColsReal(), primsol);
2907  (void)lpi->spx->getPrimalReal(tmp);
2908  }
2909  if( dualsol != NULL )
2910  {
2911  Vector tmp(lpi->spx->numRowsReal(), dualsol);
2912  (void)lpi->spx->getDualReal(tmp);
2913  }
2914  if( activity != NULL )
2915  {
2916  Vector tmp(lpi->spx->numRowsReal(), activity);
2917  (void)lpi->spx->getSlacksReal(tmp); /* in SoPlex, the activities are called "slacks" */
2918  }
2919  if( redcost != NULL )
2920  {
2921  Vector tmp(lpi->spx->numColsReal(), redcost);
2922  (void)lpi->spx->getRedCostReal(tmp);
2923  }
2924  }
2925  catch(const SPxException& x)
2926  {
2927 #ifndef NDEBUG
2928  std::string s = x.what();
2929  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2930 #endif
2931  return SCIP_LPERROR;
2932  }
2933 
2934  return SCIP_OKAY;
2935 }
2936 
2937 /** gets primal ray for unbounded LPs */
2939  SCIP_LPI* lpi, /**< LP interface structure */
2940  SCIP_Real* ray /**< primal ray */
2941  )
2942 { /*lint --e{715}*/
2943  SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
2944 
2945  assert(lpi != NULL);
2946  assert(lpi->spx != NULL);
2947 
2948  try
2949  {
2950  Vector tmp(lpi->spx->numColsReal(), ray);
2951  (void)lpi->spx->getPrimalRayReal(tmp);
2952  }
2953  catch(const SPxException& x)
2954  {
2955 #ifndef NDEBUG
2956  std::string s = x.what();
2957  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2958 #endif
2959  return SCIP_LPERROR;
2960  }
2961 
2962  return SCIP_OKAY;
2963 }
2964 
2965 /** gets dual farkas proof for infeasibility */
2967  SCIP_LPI* lpi, /**< LP interface structure */
2968  SCIP_Real* dualfarkas /**< dual farkas row multipliers */
2969  )
2970 {
2971  SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
2972 
2973  assert(lpi != NULL);
2974  assert(lpi->spx != NULL);
2975 
2976  try
2977  {
2978  Vector tmp(lpi->spx->numRowsReal(), dualfarkas);
2979  (void)lpi->spx->getDualFarkasReal(tmp);
2980  }
2981  catch(const SPxException& x)
2982  {
2983 #ifndef NDEBUG
2984  std::string s = x.what();
2985  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2986 #endif
2987  return SCIP_LPERROR;
2988  }
2989 
2990  return SCIP_OKAY;
2991 }
2992 
2993 /** gets the number of LP iterations of the last solve call */
2995  SCIP_LPI* lpi, /**< LP interface structure */
2996  int* iterations /**< pointer to store the number of iterations of the last solve call */
2997  )
2998 {
2999  SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3000 
3001  assert(lpi != NULL);
3002  assert(lpi->spx != NULL);
3003 
3004  *iterations = lpi->spx->numIterations();
3005 
3006  return SCIP_OKAY;
3007 }
3008 
3009 /** gets information about the quality of an LP solution
3010  *
3011  * Such information is usually only available, if also a (maybe not optimal) solution is available.
3012  * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
3013  */
3015  SCIP_LPI* lpi, /**< LP interface structure */
3016  SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3017  SCIP_Real* quality /**< pointer to store quality number */
3018  )
3019 {
3020  SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3021 
3022  assert(lpi != NULL);
3023  assert(quality != NULL);
3024 
3025  bool success;
3026 
3027  assert(lpi != NULL);
3028  assert(quality != NULL);
3029 
3030  SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3031 
3032  switch( qualityindicator )
3033  {
3035  success = lpi->spx->getEstimatedCondition(*quality);
3036  break;
3037 
3039  success = lpi->spx->getExactCondition(*quality);
3040  break;
3041 
3042  default:
3043  SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3044  return SCIP_INVALIDDATA;
3045  }
3046 
3047  if( !success )
3048  {
3049  SCIPdebugMessage("problem computing condition number\n");
3050  *quality = SCIP_INVALID;
3051  }
3052 
3053  return SCIP_OKAY;
3054 }
3055 
3056 /**@} */
3057 
3058 
3059 
3060 
3061 /*
3062  * LP Basis Methods
3063  */
3064 
3065 /**@name LP Basis Methods */
3066 /**@{ */
3067 
3068 
3069 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
3071  SCIP_LPI* lpi, /**< LP interface structure */
3072  int* cstat, /**< array to store column basis status, or NULL */
3073  int* rstat /**< array to store row basis status, or NULL */
3074  )
3075 {
3076  int i;
3077 
3078  SCIPdebugMessage("calling SCIPlpiGetBase()\n");
3079 
3080  assert(lpi != NULL);
3081  assert(lpi->spx != NULL);
3082 
3083  assert( lpi->spx->preStrongbranchingBasisFreed() );
3084 
3085  if( rstat != NULL && cstat != NULL )
3086  {
3087  for( i = 0; i < lpi->spx->numRowsReal(); ++i )
3088  {
3089  switch( lpi->spx->basisRowStatus(i) )
3090  {
3091  case SPxSolver::BASIC:
3092  rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3093  break;
3094  case SPxSolver::FIXED:
3095  case SPxSolver::ON_LOWER:
3096  rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3097  break;
3098  case SPxSolver::ON_UPPER:
3099  rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3100  break;
3101  case SPxSolver::ZERO:
3102  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3103  return SCIP_LPERROR;
3104  case SPxSolver::UNDEFINED:
3105  default:
3106  SCIPerrorMessage("invalid basis status\n");
3107  SCIPABORT();
3108  return SCIP_INVALIDDATA; /*lint !e527*/
3109  }
3110  }
3111  }
3112 
3113  if( cstat != NULL )
3114  {
3115  for( i = 0; i < lpi->spx->numColsReal(); ++i )
3116  {
3117 // SCIP_Real val = 0.0;
3118  switch( lpi->spx->basisColStatus(i) )
3119  {
3120  case SPxSolver::BASIC:
3121  cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3122  break;
3123  case SPxSolver::FIXED:
3124  /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
3125  * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
3126  * this case there is no problem at all. If the basis is saved and/or used in some other
3127  * solver, it usually is very cheap to perform the pivots necessary to get an optimal
3128  * basis.
3129  * @todo implement getRedCostEst()
3130  * */
3131 // SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
3132 // if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
3133 // cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3134 // else
3135  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3136  break;
3137  case SPxSolver::ON_LOWER:
3138  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3139  break;
3140  case SPxSolver::ON_UPPER:
3141  cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3142  break;
3143  case SPxSolver::ZERO:
3144  cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3145  break;
3146  case SPxSolver::UNDEFINED:
3147  default:
3148  SCIPerrorMessage("invalid basis status\n");
3149  SCIPABORT();
3150  return SCIP_INVALIDDATA; /*lint !e527*/
3151  }
3152  }
3153  }
3154 
3155  return SCIP_OKAY;
3156 }
3157 
3158 /** sets current basis status for columns and rows */
3160  SCIP_LPI* lpi, /**< LP interface structure */
3161  int* cstat, /**< array with column basis status */
3162  int* rstat /**< array with row basis status */
3163  )
3164 {
3165  int i;
3166  int nCols = lpi->spx->numColsReal();
3167  int nRows = lpi->spx->numRowsReal();
3168 
3169  SCIPdebugMessage("calling SCIPlpiSetBase()\n");
3170 
3171  assert(lpi != NULL);
3172  assert(lpi->spx != NULL);
3173  assert(cstat != NULL || nCols == 0);
3174  assert(rstat != NULL || nRows == 0);
3175 
3176  assert( lpi->spx->preStrongbranchingBasisFreed() );
3177  invalidateSolution(lpi);
3178 
3179  SPxSolver::VarStatus* spxcstat = NULL;
3180  SPxSolver::VarStatus* spxrstat = NULL;
3181  SCIP_ALLOC( BMSallocMemoryArray(&spxcstat, nCols) );
3182  SCIP_ALLOC( BMSallocMemoryArray(&spxrstat, nRows) );
3183 
3184  for( i = 0; i < nRows; ++i )
3185  {
3186  switch( rstat[i] ) /*lint !e613*/
3187  {
3188  case SCIP_BASESTAT_LOWER:
3189  spxrstat[i] = SPxSolver::ON_LOWER;
3190  break;
3191  case SCIP_BASESTAT_BASIC:
3192  spxrstat[i] = SPxSolver::BASIC;
3193  break;
3194  case SCIP_BASESTAT_UPPER:
3195  spxrstat[i] = SPxSolver::ON_UPPER;
3196  break;
3197  case SCIP_BASESTAT_ZERO:
3198  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3199  BMSfreeMemoryArrayNull(&spxcstat);
3200  BMSfreeMemoryArrayNull(&spxrstat);
3201  return SCIP_LPERROR; /*lint !e429*/
3202  default:
3203  SCIPerrorMessage("invalid basis status\n");
3204  BMSfreeMemoryArrayNull(&spxcstat);
3205  BMSfreeMemoryArrayNull(&spxrstat);
3206  SCIPABORT();
3207  return SCIP_INVALIDDATA; /*lint !e527*/
3208  }
3209  }
3210 
3211  for( i = 0; i < nCols; ++i )
3212  {
3213  switch( cstat[i] ) /*lint !e613*/
3214  {
3215  case SCIP_BASESTAT_LOWER:
3216  spxcstat[i] = SPxSolver::ON_LOWER;
3217  break;
3218  case SCIP_BASESTAT_BASIC:
3219  spxcstat[i] = SPxSolver::BASIC;
3220  break;
3221  case SCIP_BASESTAT_UPPER:
3222  spxcstat[i] = SPxSolver::ON_UPPER;
3223  break;
3224  case SCIP_BASESTAT_ZERO:
3225  spxcstat[i] = SPxSolver::ZERO;
3226  break;
3227  default:
3228  SCIPerrorMessage("invalid basis status\n");
3229  BMSfreeMemoryArrayNull(&spxcstat);
3230  BMSfreeMemoryArrayNull(&spxrstat);
3231  SCIPABORT();
3232  return SCIP_INVALIDDATA; /*lint !e527*/
3233  }
3234  }
3235 
3236  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(spxrstat, spxcstat) );
3237 
3238  BMSfreeMemoryArrayNull(&spxcstat);
3239  BMSfreeMemoryArrayNull(&spxrstat);
3240 
3241  return SCIP_OKAY;
3242 }
3243 
3244 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
3246  SCIP_LPI* lpi, /**< LP interface structure */
3247  int* bind /**< pointer to store basis indices ready to keep number of rows entries */
3248  )
3249 {
3250  SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
3251 
3252  assert(lpi != NULL);
3253  assert(lpi->spx != NULL);
3254 
3255  assert(lpi->spx->preStrongbranchingBasisFreed());
3256 
3257  lpi->spx->getBasisInd(bind);
3258 
3259  return SCIP_OKAY;
3260 }
3261 
3262 
3263 /** get dense row of inverse basis matrix B^-1
3264  *
3265  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3266  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3267  * see also the explanation in lpi.h.
3268  */
3270  SCIP_LPI* lpi, /**< LP interface structure */
3271  int r, /**< row number */
3272  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
3273  int* inds, /**< array to store the non-zero indices */
3274  int* ninds /**< pointer to store the number of non-zero indices
3275  * (-1: if we do not store sparsity informations) */
3276  )
3277 {
3278  SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
3279 
3280  assert( lpi != NULL);
3281  assert(lpi->spx != NULL);
3282  assert(lpi->spx->preStrongbranchingBasisFreed());
3283 
3284  assert(r >= 0);
3285  assert(r < lpi->spx->numRowsReal());
3286 
3287  if( ! lpi->spx->getBasisInverseRowReal(r, coef, inds, ninds) )
3288  return SCIP_LPERROR;
3289 
3290  return SCIP_OKAY;
3291 }
3292 
3293 /** get dense column of inverse basis matrix B^-1
3294  *
3295  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3296  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3297  * see also the explanation in lpi.h.
3298  */
3300  SCIP_LPI* lpi, /**< LP interface structure */
3301  int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
3302  * you have to call SCIPlpiGetBasisInd() to get the array which links the
3303  * B^-1 column numbers to the row and column numbers of the LP!
3304  * c must be between 0 and nrows-1, since the basis has the size
3305  * nrows * nrows */
3306  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
3307  int* inds, /**< array to store the non-zero indices */
3308  int* ninds /**< pointer to store the number of non-zero indices
3309  * (-1: if we do not store sparsity informations) */
3310  )
3311 {
3312  SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
3313 
3314  assert( lpi != NULL );
3315  assert( lpi->spx != NULL );
3316  assert( lpi->spx->preStrongbranchingBasisFreed() );
3317 
3318  if( ! lpi->spx->getBasisInverseColReal(c, coef, inds, ninds) )
3319  return SCIP_LPERROR;
3320 
3321  return SCIP_OKAY;
3322 }
3323 
3324 /** get dense row of inverse basis matrix times constraint matrix B^-1 * A
3325  *
3326  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3327  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3328  * see also the explanation in lpi.h.
3329  */
3331  SCIP_LPI* lpi, /**< LP interface structure */
3332  int r, /**< row number */
3333  const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
3334  SCIP_Real* coef, /**< vector to return coefficients */
3335  int* inds, /**< array to store the non-zero indices */
3336  int* ninds /**< pointer to store the number of non-zero indices
3337  * (-1: if we do not store sparsity informations) */
3338  )
3339 {
3340  SCIP_Real* buf;
3341  SCIP_Real* binv;
3342  int nrows;
3343  int ncols;
3344  int c;
3345 
3346  SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
3347 
3348  assert(lpi != NULL);
3349  assert(lpi->spx != NULL);
3350  assert( lpi->spx->preStrongbranchingBasisFreed() );
3351 
3352  nrows = lpi->spx->numRowsReal();
3353  ncols = lpi->spx->numColsReal();
3354  buf = NULL;
3355 
3356  /* get (or calculate) the row in B^-1 */
3357  if( binvrow == NULL )
3358  {
3359  SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
3360  SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
3361  binv = buf;
3362  }
3363  else
3364  binv = const_cast<SCIP_Real*>(binvrow);
3365 
3366  assert(binv != NULL);
3367 
3368  /* mark sparsity pattern as invalid */
3369  if( ninds != NULL )
3370  *ninds = -1;
3371 
3372  // @todo exploit sparsity in binv by looping over nrows
3373  /* calculate the scalar product of the row in B^-1 and A */
3374  Vector binvvec(nrows, binv);
3375  for( c = 0; c < ncols; ++c )
3376  coef[c] = binvvec * lpi->spx->colVectorReal(c); /* scalar product */ /*lint !e1702*/
3377 
3378  /* free memory if it was temporarily allocated */
3379  BMSfreeMemoryArrayNull(&buf);
3380 
3381  return SCIP_OKAY;
3382 }
3383 
3384 /** get dense column of inverse basis matrix times constraint matrix B^-1 * A
3385  *
3386  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3387  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3388  * see also the explanation in lpi.h.
3389  */
3391  SCIP_LPI* lpi, /**< LP interface structure */
3392  int c, /**< column number */
3393  SCIP_Real* coef, /**< vector to return coefficients */
3394  int* inds, /**< array to store the non-zero indices */
3395  int* ninds /**< pointer to store the number of non-zero indices
3396  * (-1: if we do not store sparsity informations) */
3397  )
3398 { /*lint --e{715}*/
3399  /* create a new uninitialized full vector */
3400  DVector col(lpi->spx->numRowsReal());
3401 
3402  SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
3403 
3404  assert( lpi != NULL );
3405  assert( lpi->spx != NULL );
3406  assert( lpi->spx->preStrongbranchingBasisFreed() );
3407 
3408  /* extract column c of A */
3409  assert(c >= 0);
3410  assert(c < lpi->spx->numColsReal());
3411 
3412  /* @todo implement this with sparse vectors */
3413  /* mark sparsity pattern as invalid */
3414  if( ninds != NULL )
3415  *ninds = -1;
3416 
3417  /* col needs to be cleared because copying colVectorReal only regards nonzeros */
3418  col.clear();
3419  col = lpi->spx->colVectorReal(c);
3420 
3421  /* solve */
3422  if( ! lpi->spx->getBasisInverseTimesVecReal(col.get_ptr(), coef) )
3423  return SCIP_LPERROR;
3424 
3425  return SCIP_OKAY;
3426 }
3427 
3428 /**@} */
3429 
3430 
3431 
3432 
3433 /*
3434  * LP State Methods
3435  */
3436 
3437 /**@name LP State Methods */
3438 /**@{ */
3439 
3440 /** stores LPi state (like basis information) into lpistate object */
3442  SCIP_LPI* lpi, /**< LP interface structure */
3443  BMS_BLKMEM* blkmem, /**< block memory */
3444  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3445  )
3446 {
3447  int ncols;
3448  int nrows;
3449 
3450  SCIPdebugMessage("calling SCIPlpiGetState()\n");
3451 
3452  assert(blkmem != NULL);
3453  assert(lpi != NULL);
3454  assert(lpi->spx != NULL);
3455  assert(lpistate != NULL);
3456 
3457  assert( lpi->spx->preStrongbranchingBasisFreed() );
3458 
3459  ncols = lpi->spx->numColsReal();
3460  nrows = lpi->spx->numRowsReal();
3461  assert(ncols >= 0);
3462  assert(nrows >= 0);
3463 
3464  /* allocate lpistate data */
3465  SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
3466 
3467  /* allocate enough memory for storing uncompressed basis information */
3468  SCIP_CALL( ensureCstatMem(lpi, ncols) );
3469  SCIP_CALL( ensureRstatMem(lpi, nrows) );
3470 
3471  /* get unpacked basis information */
3472  SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
3473 
3474  /* pack LPi state data */
3475  (*lpistate)->ncols = ncols;
3476  (*lpistate)->nrows = nrows;
3477  lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
3478 
3479  return SCIP_OKAY;
3480 }
3481 
3482 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
3483  * columns and rows since the state was stored with SCIPlpiGetState()
3484  */
3486  SCIP_LPI* lpi, /**< LP interface structure */
3487  BMS_BLKMEM* /*blkmem*/, /**< block memory */
3488  SCIP_LPISTATE* lpistate /**< LPi state information (like basis information) */
3489  )
3490 {
3491  int lpncols;
3492  int lpnrows;
3493  int i;
3494 
3495  SCIPdebugMessage("calling SCIPlpiSetState()\n");
3496 
3497  assert(lpi != NULL);
3498  assert(lpi->spx != NULL);
3499  assert(lpistate != NULL);
3500 
3501  assert( lpi->spx->preStrongbranchingBasisFreed() );
3502 
3503  lpncols = lpi->spx->numColsReal();
3504  lpnrows = lpi->spx->numRowsReal();
3505  assert(lpistate->ncols <= lpncols);
3506  assert(lpistate->nrows <= lpnrows);
3507 
3508  /* allocate enough memory for storing uncompressed basis information */
3509  SCIP_CALL( ensureCstatMem(lpi, lpncols) );
3510  SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
3511 
3512  /* unpack LPi state data */
3513  lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
3514 
3515  /* extend the basis to the current LP beyond the previously existing columns */
3516  for( i = lpistate->ncols; i < lpncols; ++i )
3517  {
3518  SCIP_Real bnd = lpi->spx->lowerReal(i);
3519  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3520  {
3521  /* if lower bound is +/- infinity -> try upper bound */
3522  bnd = lpi->spx->lowerReal(i);
3523  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3524  /* variable is free */
3525  lpi->cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3526  else
3527  /* use finite upper bound */
3528  lpi->cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3529  }
3530  else
3531  /* use finite lower bound */
3532  lpi->cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3533  }
3534  for( i = lpistate->nrows; i < lpnrows; ++i )
3535  lpi->rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3536 
3537  /* load basis information */
3538  SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
3539 
3540  return SCIP_OKAY;
3541 }
3542 
3543 /** clears current LPi state (like basis information) of the solver */
3545  SCIP_LPI* lpi /**< LP interface structure */
3546  )
3547 { /*lint --e{715}*/
3548  SCIPdebugMessage("calling SCIPlpiClearState()\n");
3549 
3550  assert(lpi != NULL);
3551  assert(lpi->spx != NULL);
3552 
3553  try
3554  {
3555  lpi->spx->clearBasis();
3556  }
3557  catch(const SPxException& x)
3558  {
3559 #ifndef NDEBUG
3560  std::string s = x.what();
3561  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3562 #endif
3563  assert( lpi->spx->status() != SPxSolver::OPTIMAL );
3564  return SCIP_LPERROR;
3565  }
3566 
3567  return SCIP_OKAY;
3568 }
3569 
3570 /** frees LPi state information */
3572  SCIP_LPI* lpi, /**< LP interface structure */
3573  BMS_BLKMEM* blkmem, /**< block memory */
3574  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3575  )
3576 { /*lint --e{715}*/
3577  SCIPdebugMessage("calling SCIPlpiFreeState()\n");
3578 
3579  assert(lpi != NULL);
3580  assert(lpistate != NULL);
3581 
3582  if ( *lpistate != NULL )
3583  lpistateFree(lpistate, blkmem);
3584 
3585  return SCIP_OKAY;
3586 }
3587 
3588 /** checks, whether the given LP state contains simplex basis information */
3590  SCIP_LPI* lpi, /**< LP interface structure */
3591  SCIP_LPISTATE* lpistate /**< LP state information (like basis information) */
3592  )
3593 { /*lint --e{715}*/
3594  return TRUE;
3595 }
3596 
3597 /** reads LP state (like basis information from a file */
3599  SCIP_LPI* lpi, /**< LP interface structure */
3600  const char* fname /**< file name */
3601  )
3602 {
3603  SCIPdebugMessage("calling SCIPlpiReadState()\n");
3604 
3605  assert( lpi->spx->preStrongbranchingBasisFreed() );
3606 
3607  bool success;
3608  SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
3609 
3610  return success ? SCIP_OKAY : SCIP_LPERROR;
3611 }
3612 
3613 /** writes LP state (like basis information) to a file */
3615  SCIP_LPI* lpi, /**< LP interface structure */
3616  const char* fname /**< file name */
3617  )
3618 {
3619  SCIPdebugMessage("calling SCIPlpiWriteState()\n");
3620 
3621  assert( lpi->spx->preStrongbranchingBasisFreed() );
3622 
3623  bool res;
3624  SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
3625 
3626  if ( ! res )
3627  return SCIP_LPERROR;
3628 
3629  return SCIP_OKAY;
3630 }
3631 
3632 /**@} */
3633 
3634 
3635 
3636 
3637 /*
3638  * LP Pricing Norms Methods
3639  */
3640 
3641 /**@name LP Pricing Norms Methods */
3642 /**@{ */
3643 
3644 /** stores LPi pricing norms information
3645  * @todo should we store norm information?
3646  */
3648  SCIP_LPI* lpi, /**< LP interface structure */
3649  BMS_BLKMEM* blkmem, /**< block memory */
3650  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
3651  )
3652 { /*lint --e{715}*/
3653 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
3654  int nrows;
3655  int ncols;
3656 
3657  assert(blkmem != NULL);
3658  assert(lpi != NULL);
3659  assert(lpi->spx != NULL);
3660  assert(lpinorms != NULL);
3661 
3662  lpi->spx->getNdualNorms(nrows, ncols);
3663 
3664  if( nrows == 0 && ncols == 0)
3665  {
3666  (*lpinorms = NULL);
3667  return SCIP_OKAY;
3668  }
3669 
3670  /* allocate lpinorms data */
3671  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
3672  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
3673  (*lpinorms)->nrows = 0;
3674  (*lpinorms)->ncols = 0;
3675 
3676  SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
3677 
3678  if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
3679  {
3680  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
3681  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
3682  BMSfreeBlockMemory(blkmem, lpinorms);
3683  assert(*lpinorms == NULL);
3684  }
3685 #ifndef NDEBUG
3686  else
3687  {
3688  assert(nrows == (*lpinorms)->nrows);
3689  assert(ncols == (*lpinorms)->ncols);
3690  }
3691 #endif
3692 #else
3693  (*lpinorms) = NULL;
3694 #endif
3695 
3696  return SCIP_OKAY;
3697 }
3698 
3699 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
3700  * columns and rows since the state was stored with SCIPlpiGetNorms()
3701  */
3703  SCIP_LPI* lpi, /**< LP interface structure */
3704  BMS_BLKMEM* blkmem, /**< block memory */
3705  SCIP_LPINORMS* lpinorms /**< LPi pricing norms information */
3706  )
3707 { /*lint --e{715}*/
3708 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
3709  assert(blkmem != NULL);
3710  assert(lpi != NULL);
3711  assert(lpi->spx != NULL);
3712 
3713  /* if there was no pricing norms information available, the LPi norms were not stored */
3714  if( lpinorms == NULL )
3715  return SCIP_OKAY;
3716 
3717  assert(lpinorms->nrows <= lpi->spx->numRowsReal());
3718  assert(lpinorms->ncols <= lpi->spx->numColsReal());
3719 
3720  if( lpinorms->nrows == 0 )
3721  return SCIP_OKAY;
3722 
3723  SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
3724  (void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->numRowsReal(), lpi->spx->numColsReal());
3725 
3726  (void) lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms);
3727 #endif
3728 
3729  return SCIP_OKAY;
3730 }
3731 
3732 /** frees pricing norms information */
3734  SCIP_LPI* lpi, /**< LP interface structure */
3735  BMS_BLKMEM* blkmem, /**< block memory */
3736  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
3737  )
3738 { /*lint --e{715}*/
3739 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
3740  assert(lpi != NULL);
3741  assert(lpinorms != NULL);
3742 
3743  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
3744 
3745  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
3746  BMSfreeBlockMemory(blkmem, lpinorms);
3747  assert(*lpinorms == NULL);
3748 #endif
3749 
3750  return SCIP_OKAY;
3751 }
3752 
3753 /**@} */
3754 
3755 
3756 
3757 
3758 /*
3759  * Parameter Methods
3760  */
3761 
3762 /**@name Parameter Methods */
3763 /**@{ */
3764 
3765 /** gets integer parameter of LP */
3767  SCIP_LPI* lpi, /**< LP interface structure */
3768  SCIP_LPPARAM type, /**< parameter number */
3769  int* ival /**< buffer to store the parameter value */
3770  )
3771 {
3772  SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
3773 
3774  assert(lpi != NULL);
3775  assert(lpi->spx != NULL);
3776  assert(ival != NULL);
3777 
3778  switch( type )
3779  {
3781  *ival = lpi->spx->getFromScratch();
3782  break;
3783  case SCIP_LPPAR_LPINFO:
3784  *ival = lpi->spx->getLpInfo();
3785  break;
3786  case SCIP_LPPAR_LPITLIM:
3787  *ival = lpi->spx->intParam(SoPlex::ITERLIMIT);
3788  break;
3789  case SCIP_LPPAR_PRESOLVING:
3790  *ival = lpi->spx->intParam(SoPlex::SIMPLIFIER) == SoPlex::SIMPLIFIER_AUTO;
3791  break;
3792  case SCIP_LPPAR_PRICING:
3793  *ival = (int) lpi->pricing;
3794  break;
3795  case SCIP_LPPAR_SCALING:
3796  *ival = (int) (lpi->spx->intParam(SoPlex::SCALER) != SoPlex::SCALER_OFF);
3797  break;
3798 #if SOPLEX_VERSION >= 201
3799  case SCIP_LPPAR_TIMING:
3800  *ival = (int) (lpi->spx->intParam(SoPlex::TIMER));
3801  break;
3802 #endif
3803  default:
3804  return SCIP_PARAMETERUNKNOWN;
3805  } /*lint !e788*/
3806 
3807  return SCIP_OKAY;
3808 }
3809 
3810 /** sets integer parameter of LP */
3812  SCIP_LPI* lpi, /**< LP interface structure */
3813  SCIP_LPPARAM type, /**< parameter number */
3814  int ival /**< parameter value */
3815  )
3816 {
3817  SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
3818 
3819  assert(lpi != NULL);
3820  assert(lpi->spx != NULL);
3821 
3822  switch( type )
3823  {
3825  assert(ival == TRUE || ival == FALSE);
3826  lpi->spx->setFromScratch(bool(ival));
3827  break;
3828  case SCIP_LPPAR_LPINFO:
3829  assert(ival == TRUE || ival == FALSE);
3830  lpi->spx->setLpInfo(bool(ival));
3831  break;
3832  case SCIP_LPPAR_LPITLIM:
3833  assert(ival >= -1);
3834  (void) lpi->spx->setIntParam(SoPlex::ITERLIMIT, ival);
3835  break;
3836  case SCIP_LPPAR_PRESOLVING:
3837  assert(ival == TRUE || ival == FALSE);
3838  (void) lpi->spx->setIntParam(SoPlex::SIMPLIFIER, (ival ? SoPlex::SIMPLIFIER_AUTO : SoPlex::SIMPLIFIER_OFF));
3839  break;
3840  case SCIP_LPPAR_PRICING:
3841  lpi->pricing = (SCIP_PRICING)ival;
3842  switch( lpi->pricing )
3843  {
3845  case SCIP_PRICING_AUTO:
3846  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_AUTO);
3847  break;
3848  case SCIP_PRICING_FULL:
3849  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
3850  break;
3851  case SCIP_PRICING_PARTIAL:
3852  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_PARMULT);
3853  break;
3854  case SCIP_PRICING_STEEP:
3855  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
3856  break;
3858  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_QUICKSTEEP);
3859  break;
3860  case SCIP_PRICING_DEVEX:
3861  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_DEVEX);
3862  break;
3863  default:
3864  return SCIP_LPERROR;
3865  }
3866  break;
3867  case SCIP_LPPAR_SCALING:
3868  assert(ival == TRUE || ival == FALSE);
3869  (void) lpi->spx->setIntParam(SoPlex::SCALER, ( ival ? SoPlex::SCALER_BIEQUI : SoPlex::SCALER_OFF));
3870  break;
3871 #if SOPLEX_VERSION >= 201
3872  case SCIP_LPPAR_TIMING:
3873  assert(ival >= 0 && ival < 3);
3874  (void) lpi->spx->setIntParam(SoPlex::TIMER, ival);
3875  break;
3876 #endif
3877  default:
3878  return SCIP_PARAMETERUNKNOWN;
3879  } /*lint !e788*/
3880 
3881  return SCIP_OKAY;
3882 }
3883 
3884 /** gets floating point parameter of LP */
3886  SCIP_LPI* lpi, /**< LP interface structure */
3887  SCIP_LPPARAM type, /**< parameter number */
3888  SCIP_Real* dval /**< buffer to store the parameter value */
3889  )
3890 {
3891  SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
3892 
3893  assert(lpi != NULL);
3894  assert(lpi->spx != NULL);
3895  assert(dval != NULL);
3896 
3897  switch( type )
3898  {
3899  case SCIP_LPPAR_FEASTOL:
3900  *dval = lpi->spx->feastol();
3901  break;
3903  *dval = lpi->spx->opttol();
3904  break;
3905  case SCIP_LPPAR_LOBJLIM:
3906  *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_LOWER);
3907  break;
3908  case SCIP_LPPAR_UOBJLIM:
3909  *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_UPPER);
3910  break;
3911  case SCIP_LPPAR_LPTILIM:
3912  *dval = lpi->spx->realParam(SoPlex::TIMELIMIT);
3913  break;
3915  *dval = lpi->spx->realParam(SoPlex::REPRESENTATION_SWITCH);
3916  if( *dval >= SCIPlpiInfinity(lpi) )
3917  *dval = -1.0;
3918  break;
3920  *dval = lpi->conditionlimit;
3921  break;
3922  default:
3923  return SCIP_PARAMETERUNKNOWN;
3924  } /*lint !e788*/
3925 
3926  return SCIP_OKAY;
3927 }
3928 
3929 /** sets floating point parameter of LP */
3931  SCIP_LPI* lpi, /**< LP interface structure */
3932  SCIP_LPPARAM type, /**< parameter number */
3933  SCIP_Real dval /**< parameter value */
3934  )
3935 {
3936  SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
3937 
3938  assert(lpi != NULL);
3939  assert(lpi->spx != NULL);
3940 
3941  switch( type )
3942  {
3943  case SCIP_LPPAR_FEASTOL:
3944  lpi->spx->setFeastol(dval);
3945  break;
3947  lpi->spx->setOpttol(dval);
3948  break;
3949  case SCIP_LPPAR_LOBJLIM:
3950  (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_LOWER, dval);
3951  break;
3952  case SCIP_LPPAR_UOBJLIM:
3953  (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_UPPER, dval);
3954  break;
3955  case SCIP_LPPAR_LPTILIM:
3956  (void) lpi->spx->setRealParam(SoPlex::TIMELIMIT, dval);
3957  break;
3959  assert(dval >= -1.5);
3960  if( dval < 0.0 )
3961  (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, SCIPlpiInfinity(lpi));
3962  else
3963  (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, dval);
3964  break;
3966  lpi->conditionlimit = dval;
3967  lpi->checkcondition = (dval >= 0);
3968  break;
3969  default:
3970  return SCIP_PARAMETERUNKNOWN;
3971  } /*lint !e788*/
3972 
3973  return SCIP_OKAY;
3974 }
3975 
3976 /**@} */
3977 
3978 
3979 
3980 
3981 /*
3982  * Numerical Methods
3983  */
3984 
3985 /**@name Numerical Methods */
3986 /**@{ */
3987 
3988 /** returns value treated as infinity in the LP solver */
3990  SCIP_LPI* lpi /**< LP interface structure */
3991  )
3993  SCIPdebugMessage("calling SCIPlpiInfinity()\n");
3994 
3995  return lpi->spx->realParam(SoPlex::INFTY);
3996 }
3997 
3998 /** checks if given value is treated as infinity in the LP solver */
4000  SCIP_LPI* lpi, /**< LP interface structure */
4001  SCIP_Real val
4002  )
4003 {
4004  SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
4005 
4006  return (val >= lpi->spx->realParam(SoPlex::INFTY));
4007 }
4008 
4009 /**@} */
4010 
4011 
4012 
4013 
4014 /*
4015  * File Interface Methods
4016  */
4017 
4018 /**@name File Interface Methods */
4019 /**@{ */
4020 
4021 /** returns, whether the given file exists */
4022 static
4023 SCIP_Bool fileExists(
4024  const char* filename /**< file name */
4025  )
4026 {
4027  FILE* f;
4028 
4029  f = fopen(filename, "r");
4030  if( f == NULL )
4031  return FALSE;
4032 
4033  fclose(f);
4034 
4035  return TRUE;
4036 }
4037 
4038 /** reads LP from a file */
4040  SCIP_LPI* lpi, /**< LP interface structure */
4041  const char* fname /**< file name */
4042  )
4043 {
4044  SCIPdebugMessage("calling SCIPlpiReadLP()\n");
4045 
4046  assert(lpi != NULL);
4047  assert(lpi->spx != NULL);
4048 
4049  assert( lpi->spx->preStrongbranchingBasisFreed() );
4050 
4051  if( !fileExists(fname) )
4052  return SCIP_NOFILE;
4053 
4054  try
4055  {
4056  assert(lpi->spx->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL);
4057  if( !lpi->spx->readFile(fname) )
4058  return SCIP_READERROR;
4059  }
4060  catch(const SPxException& x)
4061  {
4062 #ifndef NDEBUG
4063  std::string s = x.what();
4064  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4065 #endif
4066  return SCIP_READERROR;
4067  }
4068 
4069  return SCIP_OKAY;
4070 }
4071 
4072 /** writes LP to a file */
4074  SCIP_LPI* lpi, /**< LP interface structure */
4075  const char* fname /**< file name */
4076  )
4077 {
4078  SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
4079 
4080  assert(lpi != NULL);
4081  assert(lpi->spx != NULL);
4082 
4083  try
4084  {
4085  (void) lpi->spx->writeFileReal(fname);
4086  }
4087  catch(const SPxException& x)
4088  {
4089 #ifndef NDEBUG
4090  std::string s = x.what();
4091  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4092 #endif
4093  return SCIP_WRITEERROR;
4094  }
4095 
4096  return SCIP_OKAY;
4097 }
4098 
4099 /**@} */
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2732
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3272
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx2.cpp:1181
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2595
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition: type_lpi.h:92
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4042
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:2404
unsigned int SCIP_DUALPACKET
Definition: lpi_grb.c:83
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx2.cpp:3814
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:2109
interface methods for specific LP solvers
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2841
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2641
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:56
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2123
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2654
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2160
#define SCIP_CALL(x)
Definition: def.h:266
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:3769
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:61
const char * SCIPlpiGetSolverName(void)
Definition: lpi_spx2.cpp:907
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, SCIP_LPISTATE *lpistate)
Definition: lpi_spx2.cpp:3488
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx2.cpp:3736
#define SOPLEX_VERBLEVEL
Definition: lpi_spx2.cpp:102
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_spx2.cpp:1667
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:74
#define CHECK_SOPLEX_PARAM(x)
Definition: lpi_spx2.cpp:68
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:3162
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_spx2.cpp:2941
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
#define ROWS_PER_PACKET
Definition: lpi_spx2.cpp:687
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_spx2.cpp:2854
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:123
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:3601
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3333
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:935
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_spx2.cpp:2871
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:2610
#define COLS_PER_PACKET
Definition: lpi_spx2.cpp:685
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:4002
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:3705
SCIP_DUALPACKET ROWPACKET
Definition: lpi_clp.cpp:117
struct SCIP_LPiState SCIP_LPISTATE
Definition: type_lpi.h:95
SCIP_Real * norms
Definition: lpi_spx.cpp:1374
#define NULL
Definition: lpi_spx2.cpp:112
#define EPSFLOOR(x, eps)
Definition: def.h:160
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2828
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
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2678
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2623
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:2478
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_spx2.cpp:922
#define SOPLEX_SUBVERSION
Definition: lpi_spx2.cpp:85
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_spx2.cpp:954
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx2.cpp:2969
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:4076
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2564
#define SCIP_Bool
Definition: def.h:53
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:2802
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:3992
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_spx2.cpp:2574
#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:2434
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx2.cpp:2997
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:2888
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:2508
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_spx2.cpp:3017
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx2.cpp:3650
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:3444
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2719
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_spx2.cpp:3592
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:2750
#define REALABS(x)
Definition: def.h:151
#define EPSCEIL(x, eps)
Definition: def.h:161
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:3073
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:2693
#define SCIP_Real
Definition: def.h:127
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:684
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:3574
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2706
#define SCIP_INVALID
Definition: def.h:147
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_spx2.cpp:3248
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2767
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:2137
SCIP_DUALPACKET ROWPACKET
Definition: lpi_spx2.cpp:686
#define SOPLEX_TRY_ABORT(x)
Definition: lpi_spx2.cpp:156
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
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_spx2.cpp:3933
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2149
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx2.cpp:3617
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:2815
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3547
#define SCIP_ALLOC(x)
Definition: def.h:277
#define SCIPABORT()
Definition: def.h:238
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 SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3302
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3393
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx2.cpp:3888