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