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