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  /* if an objective limit is set and SoPlex claims that it is exceeded, we should check that this is indeed the case;
3177  * if not this points at numerical instability; note that this aligns with an assert in lp.c */
3178  if( SCIPlpiIsObjlimExc(lpi) )
3179  {
3180  SCIP_Real objlimit = lpi->spx->getObjLimit();
3181  SCIP_Real objvalue = lpi->spx->objValueReal();
3182 
3183  if( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MAXIMIZE )
3184  {
3185  objlimit *= -1.0;
3186  objvalue *= -1.0;
3187  }
3188  if( !SCIPlpiIsInfinity(lpi, objlimit) && LTrel(objvalue, objlimit, 2*lpi->spx->opttol()) )
3189  return FALSE;
3190  }
3191  return TRUE;
3192 }
3193 
3194 /** returns TRUE iff the objective limit was reached */
3196  SCIP_LPI* lpi /**< LP interface structure */
3197  )
3199  SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3200 
3201  assert(lpi != NULL);
3202  assert(lpi->spx != NULL);
3203 
3204  return (lpi->spx->status() == SPxSolver::ABORT_VALUE);
3205 }
3206 
3207 /** returns TRUE iff the iteration limit was reached */
3209  SCIP_LPI* lpi /**< LP interface structure */
3210  )
3212  SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3213 
3214  assert(lpi != NULL);
3215  assert(lpi->spx != NULL);
3216 
3217  return (lpi->spx->status() == SPxSolver::ABORT_ITER);
3218 }
3219 
3220 /** returns TRUE iff the time limit was reached */
3222  SCIP_LPI* lpi /**< LP interface structure */
3223  )
3225  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3226 
3227  assert(lpi != NULL);
3228  assert(lpi->spx != NULL);
3229 
3230  return (lpi->spx->status() == SPxSolver::ABORT_TIME);
3231 }
3232 
3233 /** returns the internal solution status of the solver */
3235  SCIP_LPI* lpi /**< LP interface structure */
3236  )
3238  SCIPdebugMessage("calling SCIPlpiGetInternalStatus()\n");
3239 
3240  assert(lpi != NULL);
3241  assert(lpi->spx != NULL);
3242 
3243  return static_cast<int>(lpi->spx->status());
3244 }
3245 
3246 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3248  SCIP_LPI* lpi, /**< LP interface structure */
3249  SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3250  )
3251 { /*lint --e{715}*/
3252  SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3253 
3254  assert(lpi != NULL);
3255  assert(lpi->spx != NULL);
3256  assert(success != NULL);
3257 
3258 #if SOPLEX_APIVERSION >= 4
3259  *success = lpi->spx->ignoreUnscaledViolations();
3260 #else
3261  *success = FALSE;
3262 #endif
3263 
3264  return SCIP_OKAY;
3265 }
3266 
3267 /** gets objective value of solution */
3269  SCIP_LPI* lpi, /**< LP interface structure */
3270  SCIP_Real* objval /**< stores the objective value */
3271  )
3272 {
3273  SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3274 
3275  assert(lpi != NULL);
3276  assert(lpi->spx != NULL);
3277  assert(objval != NULL);
3278 
3279  *objval = lpi->spx->objValueReal();
3280 
3281  return SCIP_OKAY;
3282 }
3283 
3284 /** gets primal and dual solution vectors for feasible LPs
3285  *
3286  * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3287  * SCIPlpiIsOptimal() returns true.
3288  */
3290  SCIP_LPI* lpi, /**< LP interface structure */
3291  SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3292  SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3293  SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3294  SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3295  SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3296  )
3297 {
3298  SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3299 
3300  assert(lpi != NULL);
3301  assert(lpi->spx != NULL);
3302 
3303  if( objval != NULL )
3304  *objval = lpi->spx->objValueReal();
3305 
3306  try
3307  {
3308  if( primsol != NULL )
3309  {
3310 #if SOPLEX_APIVERSION > 10
3311  (void)lpi->spx->getPrimalReal(primsol, lpi->spx->numColsReal());
3312 #else
3313  Vector tmp(lpi->spx->numColsReal(), primsol);
3314  (void)lpi->spx->getPrimalReal(tmp);
3315 #endif
3316  }
3317  if( dualsol != NULL )
3318  {
3319 #if SOPLEX_APIVERSION > 10
3320  (void)lpi->spx->getDualReal(dualsol, lpi->spx->numRowsReal());
3321 #else
3322  Vector tmp(lpi->spx->numRowsReal(), dualsol);
3323  (void)lpi->spx->getDualReal(tmp);
3324 #endif
3325  }
3326  if( activity != NULL )
3327  {
3328 #if SOPLEX_APIVERSION > 10
3329  (void)lpi->spx->getSlacksReal(activity, lpi->spx->numRowsReal()); /* in SoPlex, the activities are called "slacks" */
3330 #else
3331  Vector tmp(lpi->spx->numRowsReal(), activity);
3332  (void)lpi->spx->getSlacksReal(tmp); /* in SoPlex, the activities are called "slacks" */
3333 #endif
3334  }
3335  if( redcost != NULL )
3336  {
3337 #if SOPLEX_APIVERSION > 10
3338  (void)lpi->spx->getRedCostReal(redcost, lpi->spx->numColsReal());
3339 #else
3340  Vector tmp(lpi->spx->numColsReal(), redcost);
3341  (void)lpi->spx->getRedCostReal(tmp);
3342 #endif
3343  }
3344  }
3345 #ifndef NDEBUG
3346  catch( const SPxException& x )
3347  {
3348  std::string s = x.what();
3349  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3350 #else
3351  catch( const SPxException& )
3352  {
3353 #endif
3354  return SCIP_LPERROR;
3355  }
3356 
3357  return SCIP_OKAY;
3358 }
3359 
3360 /** gets primal ray for unbounded LPs */
3362  SCIP_LPI* lpi, /**< LP interface structure */
3363  SCIP_Real* ray /**< primal ray */
3364  )
3365 { /*lint --e{715}*/
3366  SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3367 
3368  assert(lpi != NULL);
3369  assert(lpi->spx != NULL);
3370  assert(lpi->spx->hasPrimalRay());
3371  assert(ray != NULL);
3372 
3373  try
3374  {
3375 #if SOPLEX_APIVERSION > 10
3376  (void)lpi->spx->getPrimalRayReal(ray, lpi->spx->numColsReal());
3377 #else
3378  Vector tmp(lpi->spx->numColsReal(), ray);
3379  (void)lpi->spx->getPrimalRayReal(tmp);
3380 #endif
3381  }
3382 #ifndef NDEBUG
3383  catch( const SPxException& x )
3384  {
3385  std::string s = x.what();
3386  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3387 #else
3388  catch( const SPxException& )
3389  {
3390 #endif
3391  return SCIP_LPERROR;
3392  }
3393 
3394  return SCIP_OKAY;
3395 }
3396 
3397 /** gets dual farkas proof for infeasibility */
3399  SCIP_LPI* lpi, /**< LP interface structure */
3400  SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3401  )
3402 {
3403  SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3404 
3405  assert(lpi != NULL);
3406  assert(lpi->spx != NULL);
3407  assert(lpi->spx->hasDualFarkas());
3408  assert(dualfarkas != NULL);
3409 
3410  try
3411  {
3412 #if SOPLEX_APIVERSION > 10
3413  (void)lpi->spx->getDualFarkasReal(dualfarkas, lpi->spx->numRowsReal());
3414 #else
3415  Vector tmp(lpi->spx->numRowsReal(), dualfarkas);
3416  (void)lpi->spx->getDualFarkasReal(tmp);
3417 #endif
3418  }
3419 #ifndef NDEBUG
3420  catch( const SPxException& x )
3421  {
3422  std::string s = x.what();
3423  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3424 #else
3425  catch( const SPxException& )
3426  {
3427 #endif
3428  return SCIP_LPERROR;
3429  }
3430 
3431  return SCIP_OKAY;
3432 }
3433 
3434 /** gets the number of LP iterations of the last solve call */
3436  SCIP_LPI* lpi, /**< LP interface structure */
3437  int* iterations /**< pointer to store the number of iterations of the last solve call */
3438  )
3439 {
3440  SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3441 
3442  assert(lpi != NULL);
3443  assert(lpi->spx != NULL);
3444  assert(iterations != NULL);
3445 
3446  *iterations = lpi->spx->numIterations();
3447 
3448  return SCIP_OKAY;
3449 }
3450 
3451 /** gets information about the quality of an LP solution
3452  *
3453  * Such information is usually only available, if also a (maybe not optimal) solution is available.
3454  * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
3455  */
3457  SCIP_LPI* lpi, /**< LP interface structure */
3458  SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3459  SCIP_Real* quality /**< pointer to store quality number */
3460  )
3461 {
3462  SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3463 
3464  assert(lpi != NULL);
3465  assert(quality != NULL);
3466 
3467  bool success;
3468 
3469  SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3470 
3471  switch( qualityindicator )
3472  {
3474  success = lpi->spx->getEstimatedCondition(*quality);
3475  break;
3476 
3478  success = lpi->spx->getExactCondition(*quality);
3479  break;
3480 
3481  default:
3482  SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3483  return SCIP_INVALIDDATA;
3484  }
3485 
3486  if( !success )
3487  {
3488  SCIPdebugMessage("problem computing condition number\n");
3489  *quality = SCIP_INVALID;
3490  }
3491 
3492  return SCIP_OKAY;
3493 }
3494 
3495 /**@} */
3496 
3497 
3498 
3499 
3500 /*
3501  * LP Basis Methods
3502  */
3503 
3504 /**@name LP Basis Methods */
3505 /**@{ */
3506 
3507 
3508 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
3510  SCIP_LPI* lpi, /**< LP interface structure */
3511  int* cstat, /**< array to store column basis status, or NULL */
3512  int* rstat /**< array to store row basis status, or NULL */
3513  )
3514 {
3515  int i;
3516 
3517  SCIPdebugMessage("calling SCIPlpiGetBase()\n");
3518 
3519  assert(lpi != NULL);
3520  assert(lpi->spx != NULL);
3521 
3522  assert( lpi->spx->preStrongbranchingBasisFreed() );
3523 
3524  if( rstat != NULL )
3525  {
3526  for( i = 0; i < lpi->spx->numRowsReal(); ++i )
3527  {
3528  switch( lpi->spx->basisRowStatus(i) )
3529  {
3530  case SPxSolver::BASIC:
3531  rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3532  break;
3533  case SPxSolver::FIXED:
3534  case SPxSolver::ON_LOWER:
3535  rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3536  break;
3537  case SPxSolver::ON_UPPER:
3538  rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3539  break;
3540  case SPxSolver::ZERO:
3541  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3542  return SCIP_LPERROR;
3543  case SPxSolver::UNDEFINED:
3544  default:
3545  SCIPerrorMessage("invalid basis status\n");
3546  SCIPABORT();
3547  return SCIP_INVALIDDATA; /*lint !e527*/
3548  }
3549  }
3550  }
3551 
3552  if( cstat != NULL )
3553  {
3554  for( i = 0; i < lpi->spx->numColsReal(); ++i )
3555  {
3556 // SCIP_Real val = 0.0;
3557  switch( lpi->spx->basisColStatus(i) )
3558  {
3559  case SPxSolver::BASIC:
3560  cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
3561  break;
3562  case SPxSolver::FIXED:
3563  /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
3564  * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
3565  * this case there is no problem at all. If the basis is saved and/or used in some other
3566  * solver, it usually is very cheap to perform the pivots necessary to get an optimal
3567  * basis.
3568  * @todo implement getRedCostEst()
3569  * */
3570 // SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
3571 // if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
3572 // cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3573 // else
3574  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3575  break;
3576  case SPxSolver::ON_LOWER:
3577  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
3578  break;
3579  case SPxSolver::ON_UPPER:
3580  cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3581  break;
3582  case SPxSolver::ZERO:
3583  cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3584  break;
3585  case SPxSolver::UNDEFINED:
3586  default:
3587  SCIPerrorMessage("invalid basis status\n");
3588  SCIPABORT();
3589  return SCIP_INVALIDDATA; /*lint !e527*/
3590  }
3591  }
3592  }
3593 
3594  return SCIP_OKAY;
3595 }
3596 
3597 /** sets current basis status for columns and rows */
3599  SCIP_LPI* lpi, /**< LP interface structure */
3600  const int* cstat, /**< array with column basis status */
3601  const int* rstat /**< array with row basis status */
3602  )
3603 {
3604  int i;
3605  int ncols;
3606  int nrows;
3607 
3608  SCIPdebugMessage("calling SCIPlpiSetBase()\n");
3609 
3610  assert(lpi != NULL);
3611  assert(lpi->spx != NULL);
3612 
3613  SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
3614  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
3615 
3616  assert(cstat != NULL || ncols == 0);
3617  assert(rstat != NULL || nrows == 0);
3618 
3619  assert( lpi->spx->preStrongbranchingBasisFreed() );
3620  invalidateSolution(lpi);
3621 
3622  DataArray<SPxSolver::VarStatus>& _colstat = lpi->spx->colStat();
3623  DataArray<SPxSolver::VarStatus>& _rowstat = lpi->spx->rowStat();
3624 
3625  _colstat.reSize(ncols);
3626  _rowstat.reSize(nrows);
3627 
3628  for( i = 0; i < nrows; ++i )
3629  {
3630  switch( rstat[i] ) /*lint !e613*/
3631  {
3632  case SCIP_BASESTAT_LOWER:
3633  _rowstat[i] = SPxSolver::ON_LOWER;
3634  break;
3635  case SCIP_BASESTAT_BASIC:
3636  _rowstat[i] = SPxSolver::BASIC;
3637  break;
3638  case SCIP_BASESTAT_UPPER:
3639  _rowstat[i] = SPxSolver::ON_UPPER;
3640  break;
3641  case SCIP_BASESTAT_ZERO:
3642  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
3643  return SCIP_LPERROR; /*lint !e429*/
3644  default:
3645  SCIPerrorMessage("invalid basis status\n");
3646  SCIPABORT();
3647  return SCIP_INVALIDDATA; /*lint !e527*/
3648  }
3649  }
3650 
3651  for( i = 0; i < ncols; ++i )
3652  {
3653  switch( cstat[i] ) /*lint !e613*/
3654  {
3655  case SCIP_BASESTAT_LOWER:
3656  _colstat[i] = SPxSolver::ON_LOWER;
3657  break;
3658  case SCIP_BASESTAT_BASIC:
3659  _colstat[i] = SPxSolver::BASIC;
3660  break;
3661  case SCIP_BASESTAT_UPPER:
3662  _colstat[i] = SPxSolver::ON_UPPER;
3663  break;
3664  case SCIP_BASESTAT_ZERO:
3665  _colstat[i] = SPxSolver::ZERO;
3666  break;
3667  default:
3668  SCIPerrorMessage("invalid basis status\n");
3669  SCIPABORT();
3670  return SCIP_INVALIDDATA; /*lint !e527*/
3671  }
3672  }
3673 
3674  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(_rowstat.get_ptr(), _colstat.get_ptr()) );
3675  lpi->spx->freePreStrongbranchingBasis();
3676 
3677  return SCIP_OKAY;
3678 }
3679 
3680 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
3682  SCIP_LPI* lpi, /**< LP interface structure */
3683  int* bind /**< pointer to store basis indices ready to keep number of rows entries */
3684  )
3685 {
3686  SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
3687 
3688  assert(lpi != NULL);
3689  assert(lpi->spx != NULL);
3690  assert(bind != NULL);
3691 
3692  assert(lpi->spx->preStrongbranchingBasisFreed());
3693 
3694  lpi->spx->getBasisInd(bind);
3695 
3696  return SCIP_OKAY;
3697 }
3698 
3699 
3700 /** get row of inverse basis matrix B^-1
3701  *
3702  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3703  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3704  * see also the explanation in lpi.h.
3705  */
3707  SCIP_LPI* lpi, /**< LP interface structure */
3708  int r, /**< row number */
3709  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
3710  int* inds, /**< array to store the non-zero indices, or NULL */
3711  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3712  * (-1: if we do not store sparsity information) */
3713  )
3714 {
3715  SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
3716 
3717  assert(lpi != NULL);
3718  assert(lpi->spx != NULL);
3719  assert(lpi->spx->preStrongbranchingBasisFreed());
3720  assert(coef != NULL);
3721 
3722  assert(r >= 0);
3723  assert(r < lpi->spx->numRowsReal());
3724 
3725  if( ! lpi->spx->getBasisInverseRowReal(r, coef, inds, ninds) )
3726  return SCIP_LPERROR;
3727 
3728  return SCIP_OKAY;
3729 }
3730 
3731 /** get column of inverse basis matrix B^-1
3732  *
3733  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3734  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3735  * see also the explanation in lpi.h.
3736  */
3738  SCIP_LPI* lpi, /**< LP interface structure */
3739  int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
3740  * you have to call SCIPlpiGetBasisInd() to get the array which links the
3741  * B^-1 column numbers to the row and column numbers of the LP!
3742  * c must be between 0 and nrows-1, since the basis has the size
3743  * nrows * nrows */
3744  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
3745  int* inds, /**< array to store the non-zero indices, or NULL */
3746  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3747  * (-1: if we do not store sparsity information) */
3748  )
3749 {
3750  SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
3751 
3752  assert( lpi != NULL );
3753  assert( lpi->spx != NULL );
3754  assert( lpi->spx->preStrongbranchingBasisFreed() );
3755  assert(coef != NULL);
3756 
3757  if( ! lpi->spx->getBasisInverseColReal(c, coef, inds, ninds) )
3758  return SCIP_LPERROR;
3759 
3760  return SCIP_OKAY;
3761 }
3762 
3763 /** get row of inverse basis matrix times constraint matrix B^-1 * A
3764  *
3765  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3766  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3767  * see also the explanation in lpi.h.
3768  */
3770  SCIP_LPI* lpi, /**< LP interface structure */
3771  int r, /**< row number */
3772  const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
3773  SCIP_Real* coef, /**< vector to return coefficients of the row */
3774  int* inds, /**< array to store the non-zero indices, or NULL */
3775  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3776  * (-1: if we do not store sparsity information) */
3777  )
3778 {
3779  SCIP_Real* buf;
3780  SCIP_Real* binv;
3781  int nrows;
3782  int ncols;
3783  int c;
3784 
3785  SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
3786 
3787  assert(lpi != NULL);
3788  assert(lpi->spx != NULL);
3789  assert( lpi->spx->preStrongbranchingBasisFreed() );
3790  assert(coef != NULL);
3791 
3792  nrows = lpi->spx->numRowsReal();
3793  ncols = lpi->spx->numColsReal();
3794  buf = NULL;
3795 
3796  /* get (or calculate) the row in B^-1 */
3797  if( binvrow == NULL )
3798  {
3799  SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
3800  SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
3801  binv = buf;
3802  }
3803  else
3804  binv = const_cast<SCIP_Real*>(binvrow);
3805 
3806  assert(binv != NULL);
3807 
3808  /* mark sparsity pattern as invalid */
3809  if( ninds != NULL )
3810  *ninds = -1;
3811 
3812  // @todo exploit sparsity in binv by looping over nrows
3813  /* calculate the scalar product of the row in B^-1 and A */
3814  Vector binvvec(nrows, binv);
3815 
3816 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3817  /* temporary unscaled column of A */
3818  DSVector acol;
3819 #endif
3820 
3821  for( c = 0; c < ncols; ++c )
3822  {
3823 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3824  lpi->spx->getColVectorReal(c, acol);
3825  coef[c] = binvvec * acol; /* scalar product */ /*lint !e1702*/
3826 #else
3827  coef[c] = binvvec * lpi->spx->colVectorReal(c); /* scalar product */ /*lint !e1702*/
3828 #endif
3829  }
3830 
3831  /* free memory if it was temporarily allocated */
3832  BMSfreeMemoryArrayNull(&buf);
3833 
3834  return SCIP_OKAY;
3835 }
3836 
3837 /** get column of inverse basis matrix times constraint matrix B^-1 * A
3838  *
3839  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
3840  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
3841  * see also the explanation in lpi.h.
3842  */
3844  SCIP_LPI* lpi, /**< LP interface structure */
3845  int c, /**< column number */
3846  SCIP_Real* coef, /**< vector to return coefficients of the column */
3847  int* inds, /**< array to store the non-zero indices, or NULL */
3848  int* ninds /**< pointer to store the number of non-zero indices, or NULL
3849  * (-1: if we do not store sparsity information) */
3850  )
3851 { /*lint --e{715}*/
3852  /* create a new uninitialized full vector */
3853  DVector col(lpi->spx->numRowsReal());
3854 
3855 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3856  /* temporary sparse vector used for unscaling (memory is automatically enlarged) */
3857  DSVector colsparse;
3858 #endif
3859 
3860  SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
3861 
3862  assert( lpi != NULL );
3863  assert( lpi->spx != NULL );
3864  assert( lpi->spx->preStrongbranchingBasisFreed() );
3865  assert(coef != NULL);
3866 
3867  /* extract column c of A */
3868  assert(c >= 0);
3869  assert(c < lpi->spx->numColsReal());
3870 
3871  /* @todo implement this with sparse vectors */
3872  /* mark sparsity pattern as invalid */
3873  if( ninds != NULL )
3874  *ninds = -1;
3875 
3876  /* col needs to be cleared because copying colVectorReal only regards nonzeros */
3877  col.clear();
3878 
3879 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 4)
3880  lpi->spx->getColVectorReal(c, colsparse);
3881  /* the copy is necessary to transform the sparse column into a dense vector */
3882  col = colsparse;
3883 #else
3884  col = lpi->spx->colVectorReal(c);
3885 #endif
3886 
3887  /* solve */
3888  if( ! lpi->spx->getBasisInverseTimesVecReal(col.get_ptr(), coef) )
3889  return SCIP_LPERROR;
3890 
3891  return SCIP_OKAY;
3892 }
3893 
3894 /**@} */
3895 
3896 
3897 
3898 
3899 /*
3900  * LP State Methods
3901  */
3902 
3903 /**@name LP State Methods */
3904 /**@{ */
3905 
3906 /** stores LPi state (like basis information) into lpistate object */
3908  SCIP_LPI* lpi, /**< LP interface structure */
3909  BMS_BLKMEM* blkmem, /**< block memory */
3910  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
3911  )
3912 {
3913  int ncols;
3914  int nrows;
3915 
3916  SCIPdebugMessage("calling SCIPlpiGetState()\n");
3917 
3918  assert(blkmem != NULL);
3919  assert(lpi != NULL);
3920  assert(lpi->spx != NULL);
3921  assert(lpistate != NULL);
3922 
3923  assert( lpi->spx->preStrongbranchingBasisFreed() );
3924 
3925  ncols = lpi->spx->numColsReal();
3926  nrows = lpi->spx->numRowsReal();
3927  assert(ncols >= 0);
3928  assert(nrows >= 0);
3929 
3930  /* allocate lpistate data */
3931  SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
3932 
3933  /* allocate enough memory for storing uncompressed basis information */
3934  SCIP_CALL( ensureCstatMem(lpi, ncols) );
3935  SCIP_CALL( ensureRstatMem(lpi, nrows) );
3936 
3937  /* get unpacked basis information */
3938  SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
3939 
3940  /* pack LPi state data */
3941  (*lpistate)->ncols = ncols;
3942  (*lpistate)->nrows = nrows;
3943  lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
3944 
3945  return SCIP_OKAY;
3946 }
3947 
3948 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
3949  * columns and rows since the state was stored with SCIPlpiGetState()
3950  */
3952  SCIP_LPI* lpi, /**< LP interface structure */
3953  BMS_BLKMEM* /*blkmem*/, /**< block memory */
3954  const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
3955  )
3956 {
3957  int lpncols;
3958  int lpnrows;
3959  int i;
3960 
3961  SCIPdebugMessage("calling SCIPlpiSetState()\n");
3962 
3963  assert(lpi != NULL);
3964  assert(lpi->spx != NULL);
3965  assert(lpistate != NULL);
3966  /* assert(blkmem != NULL); */
3967 
3968  assert( lpi->spx->preStrongbranchingBasisFreed() );
3969 
3970  lpncols = lpi->spx->numColsReal();
3971  lpnrows = lpi->spx->numRowsReal();
3972  assert(lpistate->ncols <= lpncols);
3973  assert(lpistate->nrows <= lpnrows);
3974 
3975  /* allocate enough memory for storing uncompressed basis information */
3976  SCIP_CALL( ensureCstatMem(lpi, lpncols) );
3977  SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
3978 
3979  /* unpack LPi state data */
3980  lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
3981 
3982  /* extend the basis to the current LP beyond the previously existing columns */
3983  for( i = lpistate->ncols; i < lpncols; ++i )
3984  {
3985  SCIP_Real bnd = lpi->spx->lowerReal(i);
3986  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3987  {
3988  /* if lower bound is +/- infinity -> try upper bound */
3989  bnd = lpi->spx->lowerReal(i);
3990  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
3991  /* variable is free */
3992  lpi->cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
3993  else
3994  /* use finite upper bound */
3995  lpi->cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
3996  }
3997  else
3998  /* use finite lower bound */
3999  lpi->cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4000  }
4001  for( i = lpistate->nrows; i < lpnrows; ++i )
4002  lpi->rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4003 
4004  /* load basis information */
4005  SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
4006 
4007  return SCIP_OKAY;
4008 }
4009 
4010 /** clears current LPi state (like basis information) of the solver */
4012  SCIP_LPI* lpi /**< LP interface structure */
4013  )
4014 { /*lint --e{715}*/
4015  SCIPdebugMessage("calling SCIPlpiClearState()\n");
4016 
4017  assert(lpi != NULL);
4018  assert(lpi->spx != NULL);
4019 
4020  try
4021  {
4022  lpi->spx->clearBasis();
4023  }
4024 #ifndef NDEBUG
4025  catch( const SPxException& x )
4026  {
4027  std::string s = x.what();
4028  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4029 #else
4030  catch( const SPxException& )
4031  {
4032 #endif
4033  assert( lpi->spx->status() != SPxSolver::OPTIMAL );
4034  return SCIP_LPERROR;
4035  }
4036 
4037  return SCIP_OKAY;
4038 }
4039 
4040 /** frees LPi state information */
4042  SCIP_LPI* lpi, /**< LP interface structure */
4043  BMS_BLKMEM* blkmem, /**< block memory */
4044  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4045  )
4046 { /*lint --e{715}*/
4047  SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4048 
4049  assert(lpi != NULL);
4050  assert(lpistate != NULL);
4051  assert(blkmem != NULL);
4052 
4053  if ( *lpistate != NULL )
4054  lpistateFree(lpistate, blkmem);
4055 
4056  return SCIP_OKAY;
4057 }
4058 
4059 /** checks, whether the given LP state contains simplex basis information */
4061  SCIP_LPI* lpi, /**< LP interface structure */
4062  SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4063  )
4064 { /*lint --e{715}*/
4065  assert(lpi != NULL);
4066  return TRUE;
4067 }
4068 
4069 /** reads LP state (like basis information from a file */
4071  SCIP_LPI* lpi, /**< LP interface structure */
4072  const char* fname /**< file name */
4073  )
4074 {
4075  SCIPdebugMessage("calling SCIPlpiReadState()\n");
4076  assert(lpi != NULL);
4077  assert(lpi->spx != NULL);
4078  assert(fname != NULL);
4079 
4080  assert( lpi->spx->preStrongbranchingBasisFreed() );
4081 
4082  bool success;
4083  SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
4084 
4085  return success ? SCIP_OKAY : SCIP_LPERROR;
4086 }
4087 
4088 /** writes LPi state (i.e. basis information) to a file */
4090  SCIP_LPI* lpi, /**< LP interface structure */
4091  const char* fname /**< file name */
4092  )
4093 {
4094  assert(lpi != NULL);
4095  assert(lpi->spx != NULL);
4096  assert(fname != NULL);
4097  SCIPdebugMessage("calling SCIPlpiWriteState()\n");
4098 
4099  assert( lpi->spx->preStrongbranchingBasisFreed() );
4100 
4101  bool res;
4102  SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
4103 
4104  if ( ! res )
4105  return SCIP_LPERROR;
4106 
4107  return SCIP_OKAY;
4108 }
4109 
4110 /**@} */
4111 
4112 
4113 
4114 
4115 /*
4116  * LP Pricing Norms Methods
4117  */
4118 
4119 /**@name LP Pricing Norms Methods */
4120 /**@{ */
4121 
4122 /** stores LPi pricing norms information
4123  * @todo should we store norm information?
4124  */
4126  SCIP_LPI* lpi, /**< LP interface structure */
4127  BMS_BLKMEM* blkmem, /**< block memory */
4128  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
4129  )
4130 { /*lint --e{715}*/
4131 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4132  int nrows;
4133  int ncols;
4134 
4135  assert(blkmem != NULL);
4136  assert(lpi != NULL);
4137  assert(lpi->spx != NULL);
4138  assert(lpinorms != NULL);
4139 
4140  lpi->spx->getNdualNorms(nrows, ncols);
4141 
4142  if( nrows == 0 && ncols == 0)
4143  {
4144  (*lpinorms = NULL);
4145  return SCIP_OKAY;
4146  }
4147 
4148  /* allocate lpinorms data */
4149  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
4150  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
4151  (*lpinorms)->nrows = 0;
4152  (*lpinorms)->ncols = 0;
4153 
4154  SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
4155 
4156  if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
4157  {
4158  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4159  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
4160  BMSfreeBlockMemory(blkmem, lpinorms);
4161  assert(*lpinorms == NULL);
4162  }
4163 #ifndef NDEBUG
4164  else
4165  {
4166  assert(nrows == (*lpinorms)->nrows);
4167  assert(ncols == (*lpinorms)->ncols);
4168  }
4169 #endif
4170 #else
4171  (*lpinorms) = NULL;
4172 #endif
4173 
4174  return SCIP_OKAY;
4175 }
4176 
4177 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
4178  * columns and rows since the state was stored with SCIPlpiGetNorms()
4179  */
4181  SCIP_LPI* lpi, /**< LP interface structure */
4182  BMS_BLKMEM* blkmem, /**< block memory */
4183  const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
4184  )
4185 { /*lint --e{715}*/
4186 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4187  assert(blkmem != NULL);
4188  assert(lpi != NULL);
4189  assert(lpi->spx != NULL);
4190 
4191  /* if there was no pricing norms information available, the LPi norms were not stored */
4192  if( lpinorms == NULL )
4193  return SCIP_OKAY;
4194 
4195  assert(lpinorms->nrows <= lpi->spx->numRowsReal());
4196  assert(lpinorms->ncols <= lpi->spx->numColsReal());
4197 
4198  if( lpinorms->nrows == 0 )
4199  return SCIP_OKAY;
4200 
4201  SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
4202  (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->numRowsReal(), lpi->spx->numColsReal());
4203 
4204  (void) lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms);
4205 #endif
4206 
4207  return SCIP_OKAY;
4208 }
4209 
4210 /** frees pricing norms information */
4212  SCIP_LPI* lpi, /**< LP interface structure */
4213  BMS_BLKMEM* blkmem, /**< block memory */
4214  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
4215  )
4216 { /*lint --e{715}*/
4217 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
4218  assert(lpi != NULL);
4219  assert(lpinorms != NULL);
4220 
4221  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
4222 
4223  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
4224  BMSfreeBlockMemory(blkmem, lpinorms);
4225  assert(*lpinorms == NULL);
4226 #endif
4227 
4228  return SCIP_OKAY;
4229 }
4230 
4231 /**@} */
4232 
4233 
4234 
4235 
4236 /*
4237  * Parameter Methods
4238  */
4239 
4240 /**@name Parameter Methods */
4241 /**@{ */
4242 
4243 /** gets integer parameter of LP */
4245  SCIP_LPI* lpi, /**< LP interface structure */
4246  SCIP_LPPARAM type, /**< parameter number */
4247  int* ival /**< buffer to store the parameter value */
4248  )
4249 {
4250  int scaleparam;
4251 
4252  SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
4253 
4254  assert(lpi != NULL);
4255  assert(lpi->spx != NULL);
4256  assert(ival != NULL);
4257 
4258  switch( type )
4259  {
4261  *ival = lpi->spx->getFromScratch();
4262  break;
4263  case SCIP_LPPAR_LPINFO:
4264  *ival = lpi->spx->getLpInfo();
4265  break;
4266  case SCIP_LPPAR_LPITLIM:
4267  *ival = lpi->spx->intParam(SoPlex::ITERLIMIT);
4268  if( *ival == -1 )
4269  *ival = INT_MAX;
4270  break;
4271  case SCIP_LPPAR_PRESOLVING:
4272  *ival = lpi->spx->intParam(SoPlex::SIMPLIFIER);
4273  break;
4274  case SCIP_LPPAR_PRICING:
4275  *ival = (int) lpi->pricing;
4276  break;
4277  case SCIP_LPPAR_SCALING:
4278  scaleparam = lpi->spx->intParam(SoPlex::SCALER);
4279 
4280  if( scaleparam == SoPlex::SCALER_OFF )
4281  *ival = 0;
4282  else if( scaleparam == SoPlex::SCALER_BIEQUI )
4283  *ival = 1;
4284 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4285  else
4286  {
4287  assert(scaleparam == SoPlex::SCALER_LEASTSQ);
4288  *ival = 2;
4289  }
4290 #else
4291  else
4292  {
4293  assert(scaleparam == SoPlex::SCALER_GEO8);
4294  *ival = 2;
4295  }
4296 #endif
4297  break;
4298 #if SOPLEX_VERSION >= 201
4299  case SCIP_LPPAR_TIMING:
4300  *ival = (int) (lpi->spx->intParam(SoPlex::TIMER));
4301  break;
4302 #endif
4303 #if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
4304  case SCIP_LPPAR_RANDOMSEED:
4305  *ival = (int) lpi->spx->randomSeed();
4306  break;
4307 #endif
4308 #if SOPLEX_APIVERSION >= 1
4309  case SCIP_LPPAR_REFACTOR:
4310  *ival = (int) lpi->spx->intParam(SoPlex::FACTOR_UPDATE_MAX);
4311  break;
4312 #endif
4313  default:
4314  return SCIP_PARAMETERUNKNOWN;
4315  } /*lint !e788*/
4316 
4317  return SCIP_OKAY;
4318 }
4319 
4320 /** sets integer parameter of LP */
4322  SCIP_LPI* lpi, /**< LP interface structure */
4323  SCIP_LPPARAM type, /**< parameter number */
4324  int ival /**< parameter value */
4325  )
4326 {
4327  SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
4328 
4329  assert(lpi != NULL);
4330  assert(lpi->spx != NULL);
4331 
4332  switch( type )
4333  {
4335  assert(ival == TRUE || ival == FALSE);
4336  lpi->spx->setFromScratch(bool(ival));
4337  break;
4338  case SCIP_LPPAR_LPINFO:
4339  assert(ival == TRUE || ival == FALSE);
4340  lpi->spx->setLpInfo(bool(ival));
4341  break;
4342  case SCIP_LPPAR_LPITLIM:
4343  assert( ival >= 0 );
4344  /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
4345  if( ival >= INT_MAX )
4346  ival = -1;
4347  (void) lpi->spx->setIntParam(SoPlex::ITERLIMIT, ival);
4348  break;
4349  case SCIP_LPPAR_PRESOLVING:
4350  assert(ival == TRUE || ival == FALSE);
4351 #if SOPLEX_APIVERSION < 13
4352  assert(ival == TRUE || ival == FALSE);
4353 #else
4354  assert(ival == 1 || ival == 0 || ival == 2);
4355 #endif
4356  (void) lpi->spx->setIntParam(SoPlex::SIMPLIFIER, ival);
4357  break;
4358  case SCIP_LPPAR_PRICING:
4359  lpi->pricing = (SCIP_PRICING)ival;
4360  switch( lpi->pricing )
4361  {
4363  case SCIP_PRICING_AUTO:
4364  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_AUTO);
4365  break;
4366  case SCIP_PRICING_FULL:
4367  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4368  break;
4369  case SCIP_PRICING_PARTIAL:
4370  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_PARMULT);
4371  break;
4372  case SCIP_PRICING_STEEP:
4373  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_STEEP);
4374  break;
4376  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_QUICKSTEEP);
4377  break;
4378  case SCIP_PRICING_DEVEX:
4379  (void) lpi->spx->setIntParam(SoPlex::PRICER, SoPlex::PRICER_DEVEX);
4380  break;
4381  default:
4382  return SCIP_LPERROR;
4383  }
4384  break;
4385  case SCIP_LPPAR_SCALING:
4386  assert(ival >= 0 && ival <= 2);
4387  if( ival == 0 )
4388  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_OFF);
4389  else if( ival == 1 )
4390  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_BIEQUI);
4391  else
4392 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 2)
4393  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_LEASTSQ);
4394 #else
4395  (void) lpi->spx->setIntParam(SoPlex::SCALER, SoPlex::SCALER_GEO8);
4396 #endif
4397 
4398  break;
4399 #if SOPLEX_VERSION >= 201
4400  case SCIP_LPPAR_TIMING:
4401  assert(ival >= 0 && ival < 3);
4402  (void) lpi->spx->setIntParam(SoPlex::TIMER, ival);
4403  break;
4404 #endif
4405 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
4406  case SCIP_LPPAR_RANDOMSEED:
4407  lpi->spx->setRandomSeed((unsigned long)(long)ival);
4408  break;
4409 #endif
4410 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION >= 221 && SOPLEX_SUBVERSION >= 3)
4411  case SCIP_LPPAR_POLISHING:
4412  assert(ival >= 0 && ival < 3);
4413  (void) lpi->spx->setIntParam(SoPlex::SOLUTION_POLISHING, ival);
4414  break;
4415 #endif
4416 #if SOPLEX_APIVERSION >= 1
4417  case SCIP_LPPAR_REFACTOR:
4418  assert(ival >= 0);
4419  (void) lpi->spx->setIntParam(SoPlex::FACTOR_UPDATE_MAX, ival);
4420  break;
4421 #endif
4422 
4423  default:
4424  return SCIP_PARAMETERUNKNOWN;
4425  } /*lint !e788*/
4426 
4427  return SCIP_OKAY;
4428 }
4429 
4430 /** gets floating point parameter of LP */
4432  SCIP_LPI* lpi, /**< LP interface structure */
4433  SCIP_LPPARAM type, /**< parameter number */
4434  SCIP_Real* dval /**< buffer to store the parameter value */
4435  )
4436 {
4437  SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
4438 
4439  assert(lpi != NULL);
4440  assert(lpi->spx != NULL);
4441  assert(dval != NULL);
4442 
4443  switch( type )
4444  {
4445  case SCIP_LPPAR_FEASTOL:
4446  *dval = lpi->spx->feastol();
4447  break;
4449  *dval = lpi->spx->opttol();
4450  break;
4451  case SCIP_LPPAR_OBJLIM:
4452  if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4453  *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_UPPER);
4454  else
4455  *dval = lpi->spx->realParam(SoPlex::OBJLIMIT_LOWER);
4456  break;
4457  case SCIP_LPPAR_LPTILIM:
4458  *dval = lpi->spx->realParam(SoPlex::TIMELIMIT);
4459  break;
4461  *dval = lpi->spx->realParam(SoPlex::REPRESENTATION_SWITCH);
4462  if( *dval >= SCIPlpiInfinity(lpi) )
4463  *dval = -1.0;
4464  break;
4466  *dval = lpi->conditionlimit;
4467  break;
4468  case SCIP_LPPAR_MARKOWITZ:
4469 #if (SOPLEX_APIVERSION >= 9)
4470  *dval = lpi->spx->realParam(SoPlex::MIN_MARKOWITZ);
4471  break;
4472 #endif
4473  default:
4474  return SCIP_PARAMETERUNKNOWN;
4475  } /*lint !e788*/
4476 
4477  return SCIP_OKAY;
4478 }
4479 
4480 /** sets floating point parameter of LP */
4482  SCIP_LPI* lpi, /**< LP interface structure */
4483  SCIP_LPPARAM type, /**< parameter number */
4484  SCIP_Real dval /**< parameter value */
4485  )
4486 {
4487  SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
4488 
4489  assert(lpi != NULL);
4490  assert(lpi->spx != NULL);
4491 
4492  switch( type )
4493  {
4494  case SCIP_LPPAR_FEASTOL:
4495  /* 0 < dval */
4496  assert( dval > 0.0 );
4497  lpi->spx->setFeastol(dval);
4498  break;
4500  /* 0 < dval */
4501  assert( dval > 0.0 );
4502  lpi->spx->setOpttol(dval);
4503  break;
4504  case SCIP_LPPAR_OBJLIM:
4505  /* no restrictions on dval */
4506  if ( lpi->spx->intParam(SoPlex::OBJSENSE) == SoPlex::OBJSENSE_MINIMIZE )
4507  (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_UPPER, dval);
4508  else
4509  (void) lpi->spx->setRealParam(SoPlex::OBJLIMIT_LOWER, dval);
4510  break;
4511  case SCIP_LPPAR_LPTILIM:
4512  assert( dval > 0.0 );
4513  /* soplex requires 0 < dval < DEFAULT_INFINITY (= 1e100), -1 means unlimited */
4514  (void) lpi->spx->setRealParam(SoPlex::TIMELIMIT, dval);
4515  break;
4517  /* 0 <= dval <= inf */
4518  assert( dval >= 0.0 || dval == -1.0 );
4519  if( dval == -1 )
4520  (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, SCIPlpiInfinity(lpi));
4521  else
4522  (void) lpi->spx->setRealParam(SoPlex::REPRESENTATION_SWITCH, dval);
4523  break;
4525  lpi->conditionlimit = dval;
4526  lpi->checkcondition = (dval >= 0.0);
4527  break;
4528  case SCIP_LPPAR_MARKOWITZ:
4529 #if (SOPLEX_APIVERSION >= 9)
4530  /* 1e-4 <= dval <= 0.999 */
4531  if( dval < 1e-4 )
4532  dval = 1e-4;
4533  else if( dval > 0.9999 )
4534  dval = 0.9999;
4535 
4536  (void) lpi->spx->setRealParam(SoPlex::MIN_MARKOWITZ, dval);
4537  break;
4538 #endif
4539  default:
4540  return SCIP_PARAMETERUNKNOWN;
4541  } /*lint !e788*/
4542 
4543  return SCIP_OKAY;
4544 }
4545 
4546 /** interrupts the currently ongoing lp solve or disables the interrupt */
4548  SCIP_LPI* lpi, /**< LP interface structure */
4549  SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
4550  )
4551 {
4552  assert(lpi != NULL);
4553  assert(lpi->spx != NULL);
4554 
4555  lpi->spx->setInterrupt(interrupt);
4556 
4557  return SCIP_OKAY;
4558 }
4559 
4560 /**@} */
4561 
4562 
4563 
4564 
4565 /*
4566  * Numerical Methods
4567  */
4568 
4569 /**@name Numerical Methods */
4570 /**@{ */
4571 
4572 /** returns value treated as infinity in the LP solver */
4574  SCIP_LPI* lpi /**< LP interface structure */
4575  )
4577  assert(lpi != NULL);
4578  SCIPdebugMessage("calling SCIPlpiInfinity()\n");
4579 
4580  return lpi->spx->realParam(SoPlex::INFTY);
4581 }
4582 
4583 /** checks if given value is treated as infinity in the LP solver */
4585  SCIP_LPI* lpi, /**< LP interface structure */
4586  SCIP_Real val
4587  )
4588 {
4589  assert(lpi != NULL);
4590  SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
4591 
4592  return (val >= lpi->spx->realParam(SoPlex::INFTY));
4593 }
4594 
4595 /**@} */
4596 
4597 
4598 
4599 
4600 /*
4601  * File Interface Methods
4602  */
4603 
4604 /**@name File Interface Methods */
4605 /**@{ */
4606 
4607 /** returns, whether the given file exists */
4608 static
4610  const char* filename /**< file name */
4611  )
4613  FILE* f;
4614 
4615  f = fopen(filename, "r");
4616  if( f == NULL )
4617  return FALSE;
4618 
4619  fclose(f);
4620 
4621  return TRUE;
4622 }
4623 
4624 /** reads LP from a file */
4626  SCIP_LPI* lpi, /**< LP interface structure */
4627  const char* fname /**< file name */
4628  )
4629 {
4630  SCIPdebugMessage("calling SCIPlpiReadLP()\n");
4631 
4632  assert(lpi != NULL);
4633  assert(lpi->spx != NULL);
4634  assert(fname != NULL);
4635 
4636  assert( lpi->spx->preStrongbranchingBasisFreed() );
4637 
4638  if( !fileExists(fname) )
4639  return SCIP_NOFILE;
4640 
4641  try
4642  {
4643  assert(lpi->spx->intParam(SoPlex::READMODE) == SoPlex::READMODE_REAL);
4644  if( !lpi->spx->readFile(fname) )
4645  return SCIP_READERROR;
4646  }
4647 #ifndef NDEBUG
4648  catch( const SPxException& x )
4649  {
4650  std::string s = x.what();
4651  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4652 #else
4653  catch( const SPxException& )
4654  {
4655 #endif
4656  return SCIP_READERROR;
4657  }
4658 
4659  return SCIP_OKAY;
4660 }
4661 
4662 /** writes LP to a file */
4664  SCIP_LPI* lpi, /**< LP interface structure */
4665  const char* fname /**< file name */
4666  )
4667 {
4668  SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
4669 
4670  assert(lpi != NULL);
4671  assert(lpi->spx != NULL);
4672  assert(fname != NULL);
4673 
4674  try
4675  {
4676  (void) lpi->spx->writeFileReal(fname);
4677  }
4678 #ifndef NDEBUG
4679  catch( const SPxException& x )
4680  {
4681  std::string s = x.what();
4682  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4683 #else
4684  catch( const SPxException& )
4685  {
4686 #endif
4687  return SCIP_WRITEERROR;
4688  }
4689 
4690  return SCIP_OKAY;
4691 }
4692 
4693 /**@} */
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx2.cpp:3740
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:3954
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
Definition: lpi_spx2.cpp:4587
#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:4183
ROWPACKET * packrstat
Definition: lpi_clp.cpp:137
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx2.cpp:3401
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:3292
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx2.cpp:4324
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:3512
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:4247
interface methods for specific LP solvers
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx2.cpp:3438
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:4484
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:4128
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:4073
#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:3459
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:4014
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:3772
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:3237
#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:4666
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:3684
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:4044
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:4214
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:4612
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:4628
#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:3271
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:4063
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:4092
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:4576
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:3910
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:3601
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:3224
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:3364
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:3846
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:3198
#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:4550
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx2.cpp:3211
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:3709
#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:3250
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx2.cpp:4434
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx2.cpp:1353
#define FEASTOL
Definition: lpi_qso.c:99