Scippy

SCIP

Solving Constraint Integer Programs

lpi_spx1.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-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file lpi_spx1.cpp
17  * @ingroup LPIS
18  * @brief LP interface for SoPlex version 1.4 and higher
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  * @author Ambros Gleixner
22  * @author Marc Pfetsch
23  *
24  * This is an implementation of SCIP's LP interface for SoPlex. While the ratio test is fixed to SoPlex's standard,
25  * different pricing methods can be chosen and an autopricing strategy (start with devex and switch to steepest edge
26  * after too many iterations) is implemented directly. Scaler and simplifier may be applied if solving from scratch.
27  *
28  * For debugging purposes, the SoPlex results can be double checked with CPLEX if SCIP_WITH_LPSCHECK is defined. This may
29  * yield false positives, since the LP is dumped to a file for transfering it to CPLEX, hence, precision may be lost.
30  */
31 
32 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33 
34 #define AUTOPRICING_ITERSWITCH 10000/**< start with devex and switch to steepest edge after this many iterations */
35 #define STRONGBRANCH_RESTOREBASIS /**< if defined then in SCIPlpiStrongbranch() we restore the basis after the
36  * down branch and after the up branch; if false only after the end of a
37  * strong branching phase, which however seems to mostly increase strong
38  * branching time and iterations */
39 
40 /* in this case the SoPlex results are double checked using CPLEX */
41 #ifdef SCIP_WITH_LPSCHECK
42 #include <cplex.h>
43 
44 #define CHECK_SPXSOLVE true /**< shall the SoPlex results in spxSolve() be double checked using CPLEX? */
45 #define CHECK_SPXSTRONGBRANCH true /**< shall the SoPlex results in SCIPlpStrongbranch() be double checked using CPLEX? */
46 #define CHECK_START 0 /**< skip first CHECK_START number of checks */
47 #define EXIT_AT_WRONG_RESULT false/**< shall program be exited if CPLEX returns different result than SoPlex? */
48 #define EXIT_AT_CPXERROR false/**< shall program be exited if CPLEX returns an error? */
49 
50 #define CPX_CALL(x) do \
51  { \
52  int _cpxstat_; \
53  if( (_cpxstat_ = (x)) != 0 ) \
54  { \
55  SCIPmessagePrintWarning(m_messagehdlr, "CPLEX error <%d>; SoPlex result unchecked\n", _cpxstat_); \
56  if( EXIT_AT_CPXERROR ) \
57  { \
58  exit(1); \
59  } \
60  else \
61  { \
62  goto ENDCHECK; \
63  } \
64  } \
65  } \
66  while( false )
67 #endif
68 
69 /* remember the original value of the SCIP_DEBUG define and undefine it */
70 #ifdef SCIP_DEBUG
71 #define ___DEBUG
72 #undef SCIP_DEBUG
73 #endif
74 
75 /* disable -Wclass-memaccess warnings due to dubious memcpy/realloc calls in SoPlex headers, e.g.,
76  * dataarray.h:314:16: warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘struct soplex::SPxParMultPR::SPxParMultPr_Tmp’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess]
77  */
78 #ifdef __GNUC__
79 #if __GNUC__ >= 8
80 #pragma GCC diagnostic ignored "-Wclass-memaccess"
81 #endif
82 #endif
83 
84 /* include SoPlex solver */
85 #include "soplex.h"
86 
87 /* define subversion for versions <= 1.5.0.1 */
88 #ifndef SOPLEX_SUBVERSION
89 #define SOPLEX_SUBVERSION 0
90 #endif
91 /* define API version for versions <= 3.0.0 */
92 #ifndef SOPLEX_APIVERSION
93 #define SOPLEX_APIVERSION 0
94 #endif
95 
96 /* check version */
97 #if (SOPLEX_VERSION < 133)
98 #error "This interface is not compatible with SoPlex versions prior to 1.4"
99 #endif
100 
101 /* get githash of SoPlex */
102 #if (SOPLEX_VERSION >= 160)
103 #if (SOPLEX_APIVERSION <= 5)
104 #include "spxgithash.h"
105 #endif
106 #endif
107 
108 #define WITH_BOUNDFLIPPING
109 #if (SOPLEX_APIVERSION <= 5)
110 /* include SoPlex components */
111 #include "spxsolver.h"
112 #include "slufactor.h"
113 #include "spxsteeppr.h"
114 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 6) || SOPLEX_VERSION > 160)
115 #include "spxsteepexpr.h"
116 #endif
117 #include "spxparmultpr.h"
118 #include "spxdevexpr.h"
119 #include "spxfastrt.h"
120 #include "spxmainsm.h"
121 #include "spxequilisc.h"
122 
123 #ifdef WITH_BOUNDFLIPPING
124 #include "spxboundflippingrt.h"
125 #endif
126 #endif
127 
128 /* reset the SCIP_DEBUG define to its original SCIP value */
129 #undef SCIP_DEBUG
130 #ifdef ___DEBUG
131 #define SCIP_DEBUG
132 #undef ___DEBUG
133 #endif
134 
135 /* define snprintf when using a too old MSVC version */
136 #if defined(_MSC_VER) && _MSC_VER < 1900
137 #ifndef snprintf
138 #define snprintf _snprintf
139 #endif
140 #endif
141 
142 #define SOPLEX_VERBLEVEL 5 /**< verbosity level for LPINFO */
143 
144 #include "scip/pub_message.h"
146 /********************************************************************/
147 /*----------------------------- C++ --------------------------------*/
148 /********************************************************************/
149 
150 /* in C++ we have to use "0" instead of "(void*)0" */
151 #undef NULL
152 #define NULL 0
153 
154 #include <cassert>
155 using namespace soplex;
156 
157 
158 /** Macro for a single SoPlex call for which exceptions have to be catched - return an LP error. We
159  * make no distinction between different exception types, e.g., between memory allocation and other
160  * exceptions.
161  */
162 #ifndef NDEBUG
163 #define SOPLEX_TRY(messagehdlr, x) do \
164  { \
165  try \
166  { \
167  (x); \
168  } \
169  catch( const SPxMemoryException& E ) \
170  { \
171  std::string s = E.what(); \
172  SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
173  return SCIP_ERROR; \
174  } \
175  catch( const SPxException& E ) \
176  { \
177  std::string s = E.what(); \
178  SCIPmessagePrintWarning((messagehdlr), "SoPlex threw an exception: %s\n", s.c_str()); \
179  return SCIP_LPERROR; \
180  } \
181  } \
182  while( FALSE )
183 
184 #else
185 #define SOPLEX_TRY(messagehdlr, x) do \
186  { \
187  try \
188  { \
189  (x); \
190  } \
191  catch( const SPxMemoryException& E ) \
192  { \
193  std::string s = E.what(); \
194  SCIPerrorMessage("SoPlex threw a memory exception: %s\n", s.c_str()); \
195  return SCIP_ERROR; \
196  } \
197  catch( const SPxException& ) \
198  { \
199  return SCIP_LPERROR; \
200  } \
201  } \
202  while( FALSE )
203 #endif
204 
205 /* Macro for a single SoPlex call for which exceptions have to be catched - abort if they
206  * arise. SCIP_ABORT() is not accessible here.
207  */
208 #define SOPLEX_TRY_ABORT(x) do \
209  { \
210  try \
211  { \
212  (x); \
213  } \
214  catch( const SPxException& E ) \
215  { \
216  std::string s = E.what(); \
217  SCIPerrorMessage("SoPlex threw an exception: %s\n", s.c_str()); \
218  abort(); \
219  } \
220  } \
221  while( FALSE )
222 
223 
224 
225 /** SCIP's SoPlex class */
226 class SPxSCIP : public SPxSolver
227 {
228  SPxLP::SPxSense m_sense; /**< optimization sense */
229  SLUFactor m_slu; /**< sparse LU factorization */
230  SPxSteepPR m_price_steep; /**< steepest edge pricer */
231 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 6) || SOPLEX_VERSION > 160)
232  SPxSteepExPR m_price_steep_ex; /**< steepest edge with exact weight initialization */
233 #else
234  SPxSteepPR m_price_steep_ex; /**< fallback to quick start pricer */
235 #endif
236  SPxParMultPR m_price_parmult; /**< partial multiple pricer */
237  SPxDevexPR m_price_devex; /**< devex pricer */
238 #ifdef WITH_BOUNDFLIPPING
239  SPxBoundFlippingRT m_ratio; /**< Long step dual ratio tester */
240 #else
241  SPxFastRT m_ratio; /**< Harris fast ratio tester */
242 #endif
243  char* m_probname; /**< problem name */
244  bool m_fromscratch; /**< use old basis indicator */
245  bool m_presolving; /**< use lp presolving */
246  Real m_lpifeastol; /**< feastol set by SCIPlpiSetRealpar() */
247  Real m_lpiopttol; /**< opttol set by SCIPlpiSetRealpar() */
248  Real m_objLoLimit; /**< lower objective limit */
249  Real m_objUpLimit; /**< upper objective limit */
250  Status m_stat; /**< solving status */
251  bool m_lpinfo; /**< storing whether output is turned on */
252  bool m_autopricing; /**< is automatic pricing selected? */
253  int m_itlim; /**< iteration limit (-1 for unbounded) */
254  int m_itused; /**< number of iterations spent in phase one of auto pricing */
255  int m_scaling; /**< LP scaling (0: none, 1: normal, 2: aggressive) */
256  DataArray<SPxSolver::VarStatus> m_rowstat; /**< basis status of rows before starting strong branching (if available, 0 otherwise) */
257  DataArray<SPxSolver::VarStatus> m_colstat; /**< basis status of columns before starting strong branching (if available, 0 otherwise) */
258  NameSet* m_rownames; /**< row names */
259  NameSet* m_colnames; /**< column names */
260 
261 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
262  SPxOut m_spxout;
263 #endif
264 
265 #ifdef SCIP_WITH_LPSCHECK
266  int m_checknum;
267  bool m_doublecheck;
268  CPXENVptr m_cpxenv; /**< CPLEX memory environment */
269  CPXLPptr m_cpxlp; /**< CPLEX lp structure */
270 #endif
271  SCIP_MESSAGEHDLR* m_messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
272 
273 public:
274  SPxSCIP(
275  SCIP_MESSAGEHDLR* messagehdlr = NULL, /**< message handler */
276  const char* probname = NULL /**< name of problem */
277  )
278  : SPxSolver(LEAVE, COLUMN),
279  m_probname(0),
280  m_fromscratch(false),
281  m_presolving(true),
282  m_objLoLimit(-soplex::infinity),
283  m_objUpLimit(soplex::infinity),
284  m_stat(NO_PROBLEM),
285  m_lpinfo(false),
286  m_autopricing(true),
287  m_itlim(-1),
288  m_itused(0),
289  m_scaling(1),
290  m_rowstat(0),
291  m_colstat(0),
292  m_rownames(0),
293  m_colnames(0),
294  m_messagehdlr(messagehdlr)
295  {
296 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
297  setOutstream(m_spxout);
298 #endif
299  m_sense = sense();
300  setSense(SPxLP::MINIMIZE);
301 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION == 4)
302  setBasisSolver(&m_slu); /*lint !e1506*/
303 #else
304  setSolver(&m_slu); /*lint !e1506*/
305 #endif
306  setTester(&m_ratio); /*lint !e1506*/
307  setPricer(&m_price_steep); /*lint !e1506*/
308  /* no starter */
309 
310  if ( probname != NULL )
311  SOPLEX_TRY_ABORT( setProbname(probname) );
312 
313 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
314  m_lpifeastol = SPxSolver::feastol();
315  m_lpiopttol = SPxSolver::opttol();
316 #else
317  m_lpifeastol = SPxSolver::delta();
318  m_lpiopttol = SPxSolver::delta();
319 #endif
320 
321 #ifdef SCIP_WITH_LPSCHECK
322  int cpxstat;
323  m_cpxenv = CPXopenCPLEX(&cpxstat);
324  assert(m_cpxenv != NULL);
325  m_cpxlp = CPXcreateprob(m_cpxenv, &cpxstat, probname != NULL ? probname : "spxcheck");
326  (void) CPXsetintparam(m_cpxenv, CPX_PARAM_SCRIND, 0);
327  m_checknum = 0;
328  m_doublecheck = false;
329 #endif
330  }
331 
332  virtual ~SPxSCIP()
333  {
334  if( m_probname != NULL )
335  spx_free(m_probname); /*lint !e1551*/
336 
337  freePreStrongbranchingBasis(); /*lint !e1551*/
338 
339  if( m_rownames != NULL )
340  {
341  m_rownames->~NameSet(); /*lint !e1551*/
342  spx_free(m_rownames); /*lint !e1551*/
343  }
344  if( m_colnames != NULL )
345  {
346  m_colnames->~NameSet(); /*lint !e1551*/
347  spx_free(m_colnames); /*lint !e1551*/
348  }
349 
350 #ifdef SCIP_WITH_LPSCHECK
351  (void) CPXfreeprob(m_cpxenv, &m_cpxlp);
352  (void) CPXcloseCPLEX(&m_cpxenv);
353 #endif
354  } /*lint !e1579*/
355 
356  /**< return feastol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
357  Real feastol() const
358  {/*lint !e1511*/
359  return m_lpifeastol;
360  }
361 
362  /**< set feastol and store value in case SoPlex only accepts a larger tolerance */
363  void setFeastol(
364  const Real d
365  )
366  {/*lint !e1511*/
367  m_lpifeastol = d;
368 
369 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
371 #else
372  SPxSolver::setDelta(d);
373 #endif
374  }
375 
376  /**< return opttol set by SCIPlpiSetRealpar(), which might be tighter than what SoPlex accepted */
377  Real opttol() const
378  {/*lint !e1511*/
379  return m_lpiopttol;
380  }
381 
382  /**< set opttol and store value in case SoPlex only accepts a larger tolerance */
383  void setOpttol(
384  const Real d
385  )
386  {/*lint !e1511*/
387  m_lpiopttol = d;
388 
389 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
391 #else
392  SPxSolver::setDelta(d);
393 #endif
394  }
395 
396  bool isPerturbed() const
397  {
398  /* the epsilon is 1e-16; we add a factor of ten to account for numerics */
399  return (shift() >= 10.0 * epsilon());
400  }
401 
402  /** set iteration limit (-1 = unbounded) */
403  void setIterationLimit(
404  const int itlim
405  )
406  {
407  m_itlim = itlim;
408  }
409 
410  void setAutoPricer()
411  {
412  setPricer(&m_price_devex);
413  m_autopricing = true;
414  }
415 
416  void setFullPricer()
417  {
418  setPricer(&m_price_steep);
419  m_autopricing = false;
420  }
421 
422  void setSteepPricer()
423  {
424  setPricer(&m_price_steep_ex);
425  m_autopricing = false;
426  }
427 
428  void setSteepQStartPricer()
429  {
430  setPricer(&m_price_steep);
431  m_autopricing = false;
432  }
433 
434  void setParmultPricer()
435  {
436  setPricer(&m_price_parmult);
437  m_autopricing = false;
438  }
439 
440  void setDevexPricer()
441  {
442  setPricer(&m_price_devex);
443  m_autopricing = false;
444  }
445 
446  /** get iteration limit (-1 = unbounded) */
447  int getIterationLimit() const
448  {
449  return m_itlim;
450  }
451 
452  bool getFromScratch() const
453  {
454  return m_fromscratch;
455  }
456 
457  void setFromScratch(bool fs)
458  {
459  m_fromscratch = fs;
460  }
461 
462  int getScaling() const
463  {
464  return m_scaling;
465  }
466 
467  void setScaling(int s)
468  {
469  m_scaling = s;
470  }
471 
472  bool getPresolving() const
473  {
474  return m_presolving;
475  }
476 
477  void setPresolving(bool p)
478  {
479  m_presolving = p;
480  }
481 
482  bool getLpInfo() const
483  {
484  return m_lpinfo;
485  }
486 
487  void setLpInfo(bool li)
488  {
489  m_lpinfo = li;
490  }
491 
492  SPxLP::SPxSense getSense() const
493  {
494  assert(m_sense == sense());
495 
496  return m_sense;
497  }
498 
499  void setSense(const SPxLP::SPxSense sen)
500  {
501  assert(m_sense == sense());
502 
503  if( m_sense != sen )
504  {
505  m_sense = sen;
506  changeSense(sen);
507 
508  /* if objective limit was set for the new sense previously, we have to apply it now */
509  if( m_sense == SPxLP::MINIMIZE && getObjUpLimit() < soplex::infinity )
510  {
511  SCIPdebugMessage("setting termination value to <%g>\n", getObjUpLimit());
512  SPxSolver::setTerminationValue(getObjUpLimit());
513  }
514  else if( m_sense == SPxLP::MAXIMIZE && getObjLoLimit() > -soplex::infinity )
515  {
516  SCIPdebugMessage("setting termination value to <%g>\n", getObjLoLimit());
517  SPxSolver::setTerminationValue(getObjLoLimit());
518  }
519  }
520  }
521 
522  void setProbname(const char* probname)
523  {
524  size_t len;
525 
526  assert(probname != NULL);
527  if( m_probname != NULL )
528  spx_free(m_probname);
529 
530  len = strlen(probname);
531  spx_alloc(m_probname, len + 1);
532  memcpy(m_probname, probname, len + 1);
533  }
534 
535  Real getObjLoLimit() const
536  {
537  return m_objLoLimit;
538  }
539 
540  void setObjLoLimit(Real limit)
541  {
542  if( getSense() == SPxLP::MAXIMIZE )
543  {
544  SCIPdebugMessage("setting termination value from <%g> to <%g>\n", m_objLoLimit, limit);
545  SPxSolver::setTerminationValue(limit);
546  }
547  m_objLoLimit = limit;
548  }
549 
550  Real getObjUpLimit() const
551  {
552  return m_objUpLimit;
553  }
554 
555  void setObjUpLimit(Real limit)
556  {
557  if( getSense() == SPxLP::MINIMIZE )
558  {
559  SCIPdebugMessage("setting termination value from <%g> to <%g>\n", m_objUpLimit, limit);
560  SPxSolver::setTerminationValue(limit);
561  }
562  m_objUpLimit = limit;
563  }
564 
565  void setRep(SPxSolver::Representation p_rep)
566  {/*lint !e1511*/
567  if( p_rep != rep() )
568  {
569  SCIPdebugMessage("switching to %s representation of the basis\n", p_rep == SPxSolver::ROW ? "row" : "column");
570  SPxSolver::setRep(p_rep);
571  }
572  }
573 
574 #ifdef SCIP_WITH_LPSCHECK
575  bool getDoubleCheck()
576  {
577  m_checknum++;
578  return m_doublecheck && m_checknum + 1 >= CHECK_START;
579  }
580 
581  void setDoubleCheck(bool dc)
582  {
583  m_doublecheck = dc;
584  }
585 
586  const char* spxStatusString(const SPxSolver::Status stat)
587  {
588  switch( stat )
589  {
590  case SPxSolver::ABORT_TIME:
591  return "ABORT_TIME";
592  case SPxSolver::ABORT_ITER:
593  return "ABORT_ITER";
594  case SPxSolver::ABORT_VALUE:
595  return "ABORT_VALUE";
596  case SPxSolver::SINGULAR:
597  return "SINGULAR";
598  case SPxSolver::REGULAR:
599  return "REGULAR";
600  case SPxSolver::UNKNOWN:
601  return "UNKNOWN";
602  case SPxSolver::OPTIMAL:
603  return "OPTIMAL";
604  case SPxSolver::UNBOUNDED:
605  return "UNBOUNDED";
606  case SPxSolver::INFEASIBLE:
607  return "INFEASIBLE";
608  default:
609  return "UNKNOWN";
610  } /*lint !e788*/
611 
612  return "UNKNOWN";
613  }
614 
615  const char* cpxStatusString(const int stat)
616  {
617  switch( stat )
618  {
619  case CPX_STAT_ABORT_TIME_LIM:
620  return "ABORT_TIME";
621  case CPX_STAT_ABORT_IT_LIM:
622  return "ABORT_ITER";
623  case CPX_STAT_ABORT_OBJ_LIM:
624  return "ABORT_VALUE";
625  case CPX_STAT_OPTIMAL:
626  return "OPTIMAL";
627  case CPX_STAT_OPTIMAL_INFEAS:
628  return "CPX_STAT_OPTIMAL_INFEAS: OPT SOL INFEASIBLE AFTER UNSCALING";
629  case CPX_STAT_UNBOUNDED:
630  return "UNBOUNDED";
631  case CPX_STAT_INFEASIBLE:
632  return "INFEASIBLE";
633  case CPX_STAT_INForUNBD:
634  return "INFEASIBLE or UNBOUNDED";
635  case CPX_STAT_NUM_BEST:
636  return "CPX_STAT_NUM_BEST: SOL AVAILABLE BUT NOT PROVEN OPTIMAL DUE TO NUM TROUBLE";
637  default:
638  return "UNKNOWN";
639  } /*lint !e788*/
640 
641  return "UNKNOWN";
642  }
643 #endif
644 
645 #ifndef NDEBUG
646  bool checkConsistentBounds() const
647  {
648  for( int i = 0; i < nCols(); ++i )
649  {
650  if( lower(i) > upper(i) + Param::epsilon() )
651  {
652  SCIPerrorMessage("inconsistent bounds on column %d: lower=%.17g, upper=%.17g\n",
653  i, lower(i), upper(i));
654  return false;
655  }
656  }
657 
658  return true;
659  }
660 
661  bool checkConsistentSides() const
662  {
663  for( int i = 0; i < nRows(); ++i )
664  {
665  if( lhs(i) > rhs(i) + Param::epsilon() )
666  {
667  SCIPerrorMessage("inconsistent sides on row %d: lhs=%.17g, rhs=%.17g\n",
668  i, lhs(i), rhs(i));
669  return false;
670  }
671  }
672 
673  return true;
674  }
675 #endif
676 
677  void trySolve(bool printwarning = true)
678  {
679  Real timespent;
680  Real timelimit;
681  try
682  {
683  m_stat = SPxSolver::solve();
684  }
685  catch( const SPxException& x )
686  {
687  std::string s = x.what();
688  if( printwarning )
689  {
690  SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
691  }
692  m_stat = SPxSolver::status();
693 
694  /* since it is not clear if the status in SoPlex are set correctly
695  * we want to make sure that if an error is thrown the status is
696  * not OPTIMAL anymore.
697  */
698  assert( m_stat != SPxSolver::OPTIMAL );
699  }
700 
701  /* save iteration count */
702  m_itused += SPxSolver::iterations();
703  assert(m_itlim < 0 || m_itused <= m_itlim);
704 
705  /* update time limit */
706  timespent = SPxSolver::time();
707  if( timespent > 0 )
708  {
709  /* get current time limit */
710  timelimit = SPxSolver::terminationTime();
711  if( timelimit > timespent )
712  timelimit -= timespent;
713  else
714  timelimit = 0;
715  /* set new time limit */
716  assert(timelimit >= 0);
717  SPxSolver::setTerminationTime(timelimit);
718  }
719  }
720 
721  void doSolve(bool printwarning = true)
722  {
723  /* store and set verbosity */
724 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
725  SPxOut::Verbosity verbosity;
726  verbosity = m_spxout.getVerbosity();
727  m_spxout.setVerbosity(getLpInfo() ? (SPxOut::Verbosity) SOPLEX_VERBLEVEL : (SPxOut::Verbosity) 0);
728 #else
729  int verbosity;
730  verbosity = Param::verbose();
731  Param::setVerbose(getLpInfo() ? SOPLEX_VERBLEVEL : 0);
732 #endif
733 
734  assert(checkConsistentBounds());
735  assert(checkConsistentSides());
736 
737 #ifdef SCIP_WITH_LPSCHECK
738  /* dump LP with current basis and settings saved in SoPlex */
739  if( getDoubleCheck() )
740  writeState("spxcheck", NULL, NULL);
741 #endif
742 
743  /* in auto pricing, do the first iterations with devex, then switch to steepest edge */
744  setTerminationIter(m_autopricing && (m_itlim < 0 || m_itlim - m_itused > AUTOPRICING_ITERSWITCH) ? AUTOPRICING_ITERSWITCH : m_itlim - m_itused);
745 
746  trySolve(printwarning);
747 
748  if( m_autopricing && m_stat == SPxSolver::ABORT_ITER && (m_itlim < 0 || m_itlim - m_itused > 0) )
749  {
750  setTerminationIter(m_itlim - m_itused);
751  setPricer(&m_price_steep_ex);
752 
753  trySolve(printwarning);
754 
755  setPricer(&m_price_devex);
756  }
757 
758  /* for safety reset iteration limit */
759  setTerminationIter(m_itlim);
760 
761  if( m_stat == OPTIMAL )
762  {
763  Real objval = value();
764 
765  if( (objval > m_objUpLimit) || (objval < m_objLoLimit) )
766  m_stat = ABORT_VALUE;
767  }
768 
769 #ifdef SCIP_WITH_LPSCHECK
770  /* if SoPlex gave a definite answer, we double check if it is consistent with CPLEX's answer */
771  if( getDoubleCheck() && (m_stat == SPxSolver::OPTIMAL || m_stat == SPxSolver::UNBOUNDED || m_stat == SPxSolver::INFEASIBLE || m_stat == SPxSolver::ABORT_VALUE) )
772  {
773  SCIP_Real cpxobj;
774  int cpxstat;
775 
776  /* read LP with basis */
777  CPX_CALL( CPXreadcopyprob(m_cpxenv, m_cpxlp, "spxcheck.mps", NULL) );
778  CPX_CALL( CPXreadcopybase(m_cpxenv, m_cpxlp, "spxcheck.bas") );
779 
780  /* set tolerances */
781  CPX_CALL( CPXsetdblparam(m_cpxenv, CPX_PARAM_EPOPT, MAX(opttol(), 1e-9)) );
782  CPX_CALL( CPXsetdblparam(m_cpxenv, CPX_PARAM_EPRHS, MAX(feastol(), 1e-9)) );
783 
784  /* solve LP */
785  CPX_CALL( CPXlpopt(m_cpxenv, m_cpxlp) );
786 
787  /* get solution status and objective value */
788  CPX_CALL( CPXsolution(m_cpxenv, m_cpxlp, &cpxstat, &cpxobj, NULL, NULL, NULL, NULL) );
789  if( getSense() == SPxLP::MAXIMIZE )
790  cpxobj *= -1.0;
791 
792  /* check for inconsistent statuses */
793  if( cpxstat == CPX_STAT_OPTIMAL_INFEAS )
794  {
795  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s)\n",
796  m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat));
797  if( EXIT_AT_CPXERROR )
798  exit(1);
799  }
800  else if( (m_stat == SPxSolver::OPTIMAL && cpxstat != CPX_STAT_OPTIMAL)
801  || (m_stat == SPxSolver::UNBOUNDED && cpxstat != CPX_STAT_UNBOUNDED)
802  || (m_stat == SPxSolver::INFEASIBLE && cpxstat != CPX_STAT_INFEASIBLE) )
803  {
804  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
805  m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat), m_checknum);
806  if( EXIT_AT_WRONG_RESULT )
807  exit(1);
808  }
809  else if( m_stat == SPxSolver::ABORT_VALUE )
810  {
811  switch( cpxstat )
812  {
813  case CPX_STAT_OPTIMAL:
814  if( (getSense() == SPxSolver::MINIMIZE && LTrel(cpxobj, getObjUpLimit(), 2*opttol()))
815  || (getSense() == SPxSolver::MAXIMIZE && GTrel(cpxobj, getObjLoLimit(), 2*opttol())) )
816  {
817  SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
818  m_probname, m_stat, spxStatusString(m_stat), cpxobj, getSense() == SPxSolver::MINIMIZE ? "<" : ">",
819  getSense() == SPxSolver::MINIMIZE ? getObjUpLimit() : getObjLoLimit(), cpxStatusString(cpxstat), m_checknum);
820  if( EXIT_AT_WRONG_RESULT )
821  exit(1);
822  }
823  else if( (getSense() == SPxSolver::MINIMIZE && cpxobj < getObjUpLimit())
824  || (getSense() == SPxSolver::MAXIMIZE && cpxobj > getObjLoLimit()) )
825  {
826  SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
827  m_probname, m_stat, spxStatusString(m_stat), cpxobj, getSense() == SPxSolver::MINIMIZE ? "<" : ">",
828  getSense() == SPxSolver::MINIMIZE ? getObjUpLimit() : getObjLoLimit(), cpxStatusString(cpxstat), m_checknum);
829  }
830  break;
831  case CPX_STAT_OPTIMAL_INFEAS:
832  case CPX_STAT_NUM_BEST:
833  if( (getSense() == SPxSolver::MINIMIZE && cpxobj < getObjUpLimit())
834  || (getSense() == SPxSolver::MAXIMIZE && cpxobj > getObjLoLimit()) )
835  {
836  SCIPerrorMessage("In %s: SoPlex returned status=%d (%s) while CPLEX claims obj=%.10f %s %.10f=obj.limit (%s) (checknum=%d)\n",
837  m_probname, m_stat, spxStatusString(m_stat), cpxobj, getSense() == SPxSolver::MINIMIZE ? "<" : ">",
838  getSense() == SPxSolver::MINIMIZE ? getObjUpLimit() : getObjLoLimit(), cpxStatusString(cpxstat), m_checknum);
839  }
840  break;
841  case CPX_STAT_INFEASIBLE:
842  break;
843  case CPX_STAT_UNBOUNDED:
844  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
845  m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat), m_checknum);
846  if( EXIT_AT_WRONG_RESULT )
847  exit(1);
848  break;
849  case CPX_STAT_INForUNBD:
850  default:
851  SCIPerrorMessage("In %s: SoPlex status=%d (%s) while CPLEX status=%d (%s) (checknum=%d)\n",
852  m_probname, m_stat, spxStatusString(m_stat), cpxstat, cpxStatusString(cpxstat), m_checknum);
853  break;
854  } /*lint !e788*/
855  }
856  /* check for same objective values */
857  else if( m_stat == SPxSolver::OPTIMAL )
858  {
859  if( (getSense() == SPxSolver::MINIMIZE && LTrel(value(), cpxobj, 2*opttol()))
860  || (getSense() == SPxSolver::MAXIMIZE && GTrel(value(), cpxobj, 2*opttol())) )
861  {
862  /* SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f too good (checknum=%d)\n", value(),
863  m_probname, getSense() == SPxSolver::MINIMIZE ? "<" : ">", cpxobj, m_checknum); */
864  }
865  else if( (getSense() == SPxSolver::MINIMIZE && GTrel(value(), cpxobj, 2*opttol()))
866  || (getSense() == SPxSolver::MAXIMIZE && LTrel(value(), cpxobj, 2*opttol())) )
867  {
868  SCIPerrorMessage("In %s: LP optimal; SoPlex value=%.10f %s CPLEX value=%.10f suboptimal (checknum=%d)\n", value(),
869  m_probname, getSense() == SPxSolver::MINIMIZE ? ">" : "<", cpxobj, m_checknum);
870  if( EXIT_AT_WRONG_RESULT )
871  exit(1);
872  }
873  }
874  }
875 
876  ENDCHECK:
877 #endif
878 
879  /* restore verbosity */
880 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
881  m_spxout.setVerbosity(verbosity);
882 #else
883  Param::setVerbose(verbosity);
884 #endif
885 
886  }
887 
888  virtual Status solve()
889  {
890  assert(m_sense == sense());
891  SPxEquiliSC* scaler = NULL;
892  SPxMainSM* simplifier = NULL;
893  SPxLP origlp;
894  SPxSimplifier::Result result = SPxSimplifier::OKAY;
895 
896  /* delete starting basis if solving from scratch */
897  if ( getFromScratch() )
898  {
899  try
900  {
901  SPxSolver::reLoad();
902  }
903  catch( const SPxException& x )
904  {
905  std::string s = x.what();
906  SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
907  m_stat = SPxSolver::status();
908  assert( m_stat != SPxSolver::OPTIMAL );
909  return m_stat;
910  }
911  }
912  assert(!getFromScratch() || getBasisStatus() == SPxBasis::NO_PROBLEM);
913 
914  /* use scaler and simplifier if no basis is loaded, i.e., if solving for the first time or from scratch */
915  if( SPxSolver::getBasisStatus() == SPxBasis::NO_PROBLEM && (getScaling() > 0) && nCols() > 0 && nRows() > 0 )
916  {
917  spx_alloc(scaler, 1);
918  scaler = new (scaler) SPxEquiliSC();
919  assert(scaler != NULL);
920 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
921  scaler->setOutstream(m_spxout);
922 #endif
923  }
924 
925  if( SPxSolver::getBasisStatus() == SPxBasis::NO_PROBLEM && getPresolving() && nCols() > 0 && nRows() > 0 )
926  {
927  spx_alloc(simplifier, 1);
928  simplifier = new (simplifier) SPxMainSM();
929  assert(simplifier != NULL);
930  }
931 
932  /* store original lp */
933  if( scaler != NULL || simplifier != NULL )
934  origlp = SPxLP(*this);
935 
936  m_itused = 0;
937 
938  SOLVEAGAIN:
939  /* perform scaling and presolving */
940  if( scaler != NULL )
941  {
942  SCIPdebugMessage("scaling LP\n");
943  scaler->scale(*this);
944  }
945 
946  if( simplifier != NULL )
947  {
948  /* store and set verbosity */
949 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
950  SPxOut::Verbosity verbosity;
951  verbosity = m_spxout.getVerbosity();
952  m_spxout.setVerbosity(getLpInfo() ? (SPxOut::Verbosity) SOPLEX_VERBLEVEL : (SPxOut::Verbosity) 0);
953 #else
954  int verbosity;
955  verbosity = Param::verbose();
956  Param::setVerbose(getLpInfo() ? SOPLEX_VERBLEVEL : 0);
957 #endif
958  SCIPdebugMessage("simplifying LP\n");
959 #ifdef WITH_BOUNDFLIPPING
960  result = simplifier->simplify(*this, epsilon(), feastol(), opttol(), true);
961 #else
962 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
963  result = simplifier->simplify(*this, epsilon(), feastol(), opttol());
964 #else
965  result = simplifier->simplify(*this, epsilon(), delta());
966 #endif
967 #endif
968  SCIPdebugMessage("simplifier ended with status %u (0: OKAY, 1: INFEASIBLE, 2: DUAL_INFEASIBLE, 3: UNBOUNDED, 4: VANISHED)\n", result);
969 
970  /* unsimplification is not designed for these cases, thus reload original/scaled lp */
971  if( result == SPxSimplifier::INFEASIBLE || result == SPxSimplifier::DUAL_INFEASIBLE )
972  {
973  SCIPdebugMessage("simplifier detected primal or dual infeasibility - reloading and solving unsimplified LP\n");
974 
975  simplifier->~SPxMainSM();
976  spx_free(simplifier);
977 
978  SPxSolver::loadLP(origlp);
979  m_sense = sense();
980 
981  goto SOLVEAGAIN;
982  }
983  /* reset verbosity */
984 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 201)
985  m_spxout.setVerbosity(verbosity);
986 #else
987  Param::setVerbose(verbosity);
988 #endif
989  }
990 
991  /* solve */
992  if( result != SPxSimplifier::VANISHED )
993  {
994  /* we have to deactivate the objective limit, since we do not know the transformed value */
995  Real objlolimit = getObjLoLimit();
996  Real objuplimit = getObjUpLimit();
997 
998  if( simplifier != NULL || scaler != NULL )
999  {
1000  setObjLoLimit(-soplex::infinity);
1001  setObjUpLimit(soplex::infinity);
1002  }
1003 
1004 #ifndef NDEBUG
1005  doSolve();
1006 #else
1007  doSolve(false);
1008 #endif
1009 
1010  if( simplifier != NULL || scaler != NULL )
1011  {
1012  setObjLoLimit(objlolimit);
1013  setObjUpLimit(objuplimit);
1014  }
1015  }
1016 
1017  /* unsimplification only stable for optimal basis */
1018  if( m_stat != SPxSolver::OPTIMAL && simplifier != NULL )
1019  {
1020  SCIPdebugMessage("presolved LP not optimal - reloading and solving original LP\n");
1021 
1022  simplifier->~SPxMainSM();
1023  spx_free(simplifier);
1024 
1025  SPxSolver::loadLP(origlp);
1026  m_sense = sense();
1027 
1028  goto SOLVEAGAIN;
1029  }
1030 
1031  /* if scaling or presolving was applied, restore original lp */
1032  if( scaler != NULL || simplifier != NULL )
1033  {
1034  SPxSolver::VarStatus* cstat = NULL;
1035  SPxSolver::VarStatus* rstat = NULL;
1036 
1037  /* get basis if at least regular */
1038  if( (simplifier == NULL || result != SPxSimplifier::VANISHED) && SPxSolver::getBasisStatus() >= SPxBasis::REGULAR )
1039  {
1040  SCIPdebugMessage("get basis of presolved LP\n");
1041  spx_alloc(rstat, nRows());
1042  spx_alloc(cstat, nCols());
1043  (void) SPxSolver::getBasis(rstat, cstat);
1044  }
1045 
1046  /* unsimplify */
1047  if( simplifier != NULL && SPxSolver::getBasisStatus() >= SPxBasis::REGULAR )
1048  {
1049  assert((result == SPxSimplifier::VANISHED) == (cstat == NULL));
1050  assert((result == SPxSimplifier::VANISHED) == (rstat == NULL));
1051 
1052  /* dimension of presolved lp */
1053  int ncols = result == SPxSimplifier::VANISHED ? 0 : nCols();
1054  int nrows = result == SPxSimplifier::VANISHED ? 0 : nRows();
1055 
1056  /* get solution of presolved lp */
1057  DVector primals(ncols);
1058  DVector duals(nrows);
1059  DVector slacks(nrows);
1060  DVector redcosts(ncols);
1061  if( result != SPxSimplifier::VANISHED )
1062  {
1063  (void) SPxSolver::getPrimal(primals);
1064  (void) SPxSolver::getDual(duals);
1065  (void) SPxSolver::getSlacks(slacks);
1066  (void) SPxSolver::getRedCost(redcosts);
1067  }
1068 
1069  /* perform unsimplification */
1070  SCIPdebugMessage("unsimplify\n");
1071  try
1072  {
1073  simplifier->unsimplify(primals, duals, slacks, redcosts, rstat, cstat);
1074  }
1075  catch( const SPxException& x )
1076  {
1077  std::string s = x.what();
1078  SCIPmessagePrintWarning(m_messagehdlr, "SoPlex unsimplification unsuccessful; solving again without LP presolving (SoPlex says %s)\n",
1079  s.c_str());
1080  }
1081 
1082  if( cstat != NULL )
1083  spx_free(cstat);
1084  if( rstat != NULL )
1085  spx_free(rstat);
1086 
1087  if( simplifier->isUnsimplified() )
1088  {
1089  /* get basis for original lp */
1090  rstat = NULL;
1091  cstat = NULL;
1092  spx_alloc(rstat, origlp.nRows());
1093  spx_alloc(cstat, origlp.nCols());
1094  simplifier->getBasis(rstat, cstat);
1095  }
1096  }
1097 
1098  /* reload original lp */
1099  SCIPdebugMessage("reload original LP\n");
1100  SPxSolver::loadLP(origlp);
1101  m_sense = sense();
1102 
1103  /* set basis from preprocessed lp and reoptimize */
1104  if( rstat != NULL && cstat != NULL )
1105  {
1106  SCIPdebugMessage("load unsimplified basis into original LP\n");
1107  SPxSolver::setBasis(rstat, cstat);
1108  }
1109 
1110  SCIPdebugMessage("solve original LP\n");
1111 #ifndef NDEBUG
1112  doSolve();
1113 #else
1114  doSolve(false);
1115 #endif
1116 
1117  /* free allocated memory */
1118  if( cstat != NULL )
1119  spx_free(cstat);
1120  if( rstat != NULL )
1121  spx_free(rstat);
1122  if( scaler != NULL )
1123  {
1124  scaler->~SPxEquiliSC();
1125  spx_free(scaler);
1126  }
1127  if( simplifier != NULL )
1128  {
1129  simplifier->~SPxMainSM();
1130  spx_free(simplifier);
1131  }
1132  }
1133 
1134  if( m_stat == OPTIMAL )
1135  {
1136  Real objval = value();
1137 
1138  if( (objval > m_objUpLimit) || (objval < m_objLoLimit) )
1139  m_stat = ABORT_VALUE;
1140  }
1141 
1142  return m_stat;
1143  }
1144 
1145  /** save the current basis */
1146  void savePreStrongbranchingBasis()
1147  {
1148  m_rowstat.reSize(nRows());
1149  m_colstat.reSize(nCols());
1150 
1151  try
1152  {
1153  m_stat = getBasis(m_rowstat.get_ptr(), m_colstat.get_ptr());
1154  }
1155 #ifndef NDEBUG
1156  catch( const SPxException& x )
1157  {
1158  std::string s = x.what();
1159  SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1160 
1161  /* since it is not clear if the status in SoPlex are set correctly
1162  * we want to make sure that if an error is thrown the status is
1163  * not OPTIMAL anymore.
1164  */
1165  assert(m_stat != SPxSolver::OPTIMAL);
1166  }
1167 #else
1168  catch( const SPxException& )
1169  { }
1170 #endif
1171 
1172  }
1173 
1174  /** restore basis */
1175  void restorePreStrongbranchingBasis()
1176  {
1177  assert(m_rowstat.size() == nRows());
1178  assert(m_colstat.size() == nCols());
1179 
1180  try
1181  {
1182  setBasis(m_rowstat.get_const_ptr(), m_colstat.get_const_ptr());
1183  }
1184 #ifndef NDEBUG
1185  catch( const SPxException& x )
1186  {
1187  std::string s = x.what();
1188  SCIPmessagePrintWarning(m_messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1189 #else
1190  catch( const SPxException& )
1191  {
1192 #endif
1193  m_stat = SPxSolver::status();
1194 
1195  /* since it is not clear if the status in SoPlex are set correctly
1196  * we want to make sure that if an error is thrown the status is
1197  * not OPTIMAL anymore.
1198  */
1199  assert(m_stat != SPxSolver::OPTIMAL);
1200  }
1201  }
1202 
1203  /** if basis is in store, delete it without restoring it */
1204  void freePreStrongbranchingBasis()
1205  {
1206  m_rowstat.clear();
1207  m_colstat.clear();
1208  }
1209 
1210  /** is pre-strong-branching basis freed? */
1211  bool preStrongbranchingBasisFreed() const
1212  {
1213  return ((m_rowstat.size() == 0 ) && (m_colstat.size() == 0));
1214  }
1215 
1216  /** provides access for temporary storage of basis status of rows */
1217  DataArray<SPxSolver::VarStatus>& rowStat()
1218  {
1219  return m_rowstat;
1220  }
1221 
1222  /** provides access for temporary storage of basis status or columns */
1223  DataArray<SPxSolver::VarStatus>& colStat()
1224  {
1225  return m_colstat;
1226  }
1227 
1228  Status getStatus() const
1229  {
1230  return m_stat;
1231  }
1232 
1233  Status updateStatus()
1234  {
1235  m_stat = SPxSolver::status();
1236  return m_stat;
1237  }
1238 
1239  bool isInitialized() const
1240  {/*lint !e1511*/
1241  return SPxSolver::isInitialized();
1242  }
1243 
1244  int iterations() const
1245  {/*lint !e1511*/
1246  return m_itused;
1247  }
1248 
1249  virtual void clear()
1250  {
1251  SPxSolver::clear();
1252  freePreStrongbranchingBasis();
1253  m_stat = NO_PROBLEM;
1254  m_sense = sense();
1255  }
1256 
1257  bool readLP(const char* fname)
1258  {
1259  clear();
1260 
1261  if ( m_rownames != 0 )
1262  m_rownames->~NameSet();
1263  else
1264  spx_alloc(m_colnames, 1);
1265 
1266  if ( m_colnames != 0 )
1267  m_colnames->~NameSet();
1268  else
1269  spx_alloc(m_rownames, 1);
1270 
1271  m_rownames = new (m_rownames) NameSet();
1272  m_colnames = new (m_colnames) NameSet();
1273 
1274  if( SPxSolver::readFile(fname, m_rownames, m_colnames) )
1275  {
1276  m_stat = NO_PROBLEM;
1277  m_sense = sense();
1278  return true;
1279  }
1280 
1281  return false;
1282  }
1283 
1284  /** copy column names into namestorage with access via colnames */
1285  void getColNames(
1286  int firstcol, /**< first column to get name from LP */
1287  int lastcol, /**< last column to get name from LP */
1288  char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) */
1289  char* namestorage, /**< storage for col names */
1290  int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
1291  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) */
1292  )
1293  {
1294  assert( m_colnames != NULL );
1295 
1296  // compute size
1297  if ( namestoragesize == 0 )
1298  {
1299  // the following may overestimate the space requirements
1300  *storageleft = -m_colnames->memSize();
1301  }
1302  else
1303  {
1304  NameSet* names = m_colnames;
1305  assert( names != 0 );
1306  int sizeleft = namestoragesize;
1307  char* s = namestorage;
1308  for (int j = firstcol; j <= lastcol; ++j)
1309  {
1310  const char* t = (*names)[j];
1311  colnames[j-firstcol] = s;
1312  while( *t != '\0' && sizeleft >= 0 )
1313  {
1314  *(s++) = *(t++);
1315  --sizeleft;
1316  }
1317  *(s++) = '\0';
1318  }
1319  if ( sizeleft == 0 )
1320  {
1321  *storageleft = namestoragesize - m_colnames->memSize();
1322  assert( *storageleft <= 0 );
1323  }
1324  else
1325  *storageleft = sizeleft;
1326  }
1327  }
1328 
1329  /** copy row names into namestorage with access via row */
1330  void getRowNames(
1331  int firstrow, /**< first row to get name from LP */
1332  int lastrow, /**< last row to get name from LP */
1333  char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) */
1334  char* namestorage, /**< storage for row names */
1335  int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
1336  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) */
1337  )
1338  {
1339  assert( m_rownames != NULL );
1340 
1341  // compute size
1342  if ( namestoragesize == 0 )
1343  {
1344  // the following may overestimate the space requirements
1345  *storageleft = -m_rownames->memSize();
1346  }
1347  else
1348  {
1349  NameSet* names = m_rownames;
1350  assert( names != 0 );
1351  int sizeleft = namestoragesize;
1352  char* s = namestorage;
1353  for (int i = firstrow; i <= lastrow; ++i)
1354  {
1355  const char* t = (*names)[i];
1356  rownames[i-firstrow] = s;
1357  while( *t != '\0' && sizeleft >= 0 )
1358  {
1359  *(s++) = *(t++);
1360  --sizeleft;
1361  }
1362  *(s++) = '\0';
1363  }
1364  if ( sizeleft == 0 )
1365  {
1366  *storageleft = m_rownames->memSize() - namestoragesize;
1367  assert( *storageleft <= 0 );
1368  }
1369  else
1370  *storageleft = sizeleft;
1371  }
1372  }
1373 }; /*lint !e1748*/
1374 
1375 
1376 
1377 
1378 /********************************************************************/
1379 /*----------------------------- C --------------------------------*/
1380 /********************************************************************/
1381 
1382 #include "lpi/lpi.h"
1383 #include "scip/bitencode.h"
1384 
1385 typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
1386 #define COLS_PER_PACKET SCIP_DUALPACKETSIZE
1387 typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
1388 #define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
1392 /** LP interface */
1393 struct SCIP_LPi
1394 {
1395  SPxSCIP* spx; /**< our SPxSolver implementation */
1396  int* cstat; /**< array for storing column basis status */
1397  int* rstat; /**< array for storing row basis status */
1398  int cstatsize; /**< size of cstat array */
1399  int rstatsize; /**< size of rstat array */
1400  SCIP_PRICING pricing; /**< current pricing strategy */
1401  SCIP_Bool solved; /**< was the current LP solved? */
1402  SLUFactor* factorization; /**< factorization possibly needed for basis inverse */
1403  SCIP_Real rowrepswitch; /**< use row representation if number of rows divided by number of columns exceeds this value */
1404  SCIP_Real conditionlimit; /**< maximum condition number of LP basis counted as stable (-1.0: no limit) */
1405  SCIP_Bool checkcondition; /**< should condition number of LP basis be checked for stability? */
1406  SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
1407 };
1408 
1409 /** LPi state stores basis information */
1410 struct SCIP_LPiState
1411 {
1412  int ncols; /**< number of LP columns */
1413  int nrows; /**< number of LP rows */
1414  COLPACKET* packcstat; /**< column basis status in compressed form */
1415  ROWPACKET* packrstat; /**< row basis status in compressed form */
1416 };
1417 
1418 /** LPi norms to store dual steepest edge */
1419 struct SCIP_LPiNorms
1420 {
1421  int nrows; /**< number of stored norms corresponding to rows */
1422  int ncols; /**< number of stored norms corresponding to cols */
1423  SCIP_Real* norms; /**< norms to be (re)stored */
1424 };
1425 
1426 
1427 /*
1428  * dynamic memory arrays
1429  */
1430 
1431 /** resizes cstat array to have at least num entries */
1432 static
1434  SCIP_LPI* lpi, /**< LP interface structure */
1435  int num /**< minimal number of entries in array */
1436  )
1437 {
1438  assert(lpi != NULL);
1439 
1440  if( num > lpi->cstatsize )
1441  {
1442  int newsize;
1443 
1444  newsize = MAX(2*lpi->cstatsize, num);
1445  SCIP_ALLOC( BMSreallocMemoryArray(&lpi->cstat, newsize) );
1446  lpi->cstatsize = newsize;
1447  }
1448  assert(num <= lpi->cstatsize);
1449 
1450  return SCIP_OKAY;
1451 }
1452 
1453 /** resizes rstat array to have at least num entries */
1454 static
1456  SCIP_LPI* lpi, /**< LP interface structure */
1457  int num /**< minimal number of entries in array */
1458  )
1459 {
1460  assert(lpi != NULL);
1461 
1462  if( num > lpi->rstatsize )
1463  {
1464  int newsize;
1465 
1466  newsize = MAX(2*lpi->rstatsize, num);
1467  SCIP_ALLOC( BMSreallocMemoryArray(&lpi->rstat, newsize) );
1468  lpi->rstatsize = newsize;
1469  }
1470  assert(num <= lpi->rstatsize);
1471 
1472  return SCIP_OKAY;
1473 }
1474 
1475 
1476 
1477 
1478 /*
1479  * LPi state methods
1480  */
1481 
1482 /** returns the number of packets needed to store column packet information */
1483 static
1484 int colpacketNum(
1485  int ncols /**< number of columns to store */
1486  )
1488  return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
1489 }
1490 
1491 /** returns the number of packets needed to store row packet information */
1492 static
1493 int rowpacketNum(
1494  int nrows /**< number of rows to store */
1495  )
1497  return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
1498 }
1499 
1500 /** store row and column basis status in a packed LPi state object */
1501 static
1502 void lpistatePack(
1503  SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
1504  const int* cstat, /**< basis status of columns in unpacked format */
1505  const int* rstat /**< basis status of rows in unpacked format */
1506  )
1507 {
1508  assert(lpistate != NULL);
1509  assert(lpistate->packcstat != NULL);
1510  assert(lpistate->packrstat != NULL);
1511 
1512  SCIPencodeDualBit(cstat, lpistate->packcstat, lpistate->ncols);
1513  SCIPencodeDualBit(rstat, lpistate->packrstat, lpistate->nrows);
1514 }
1515 
1516 /** unpacks row and column basis status from a packed LPi state object */
1517 static
1518 void lpistateUnpack(
1519  const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
1520  int* cstat, /**< buffer for storing basis status of columns in unpacked format */
1521  int* rstat /**< buffer for storing basis status of rows in unpacked format */
1522  )
1523 {
1524  assert(lpistate != NULL);
1525  assert(lpistate->packcstat != NULL);
1526  assert(lpistate->packrstat != NULL);
1527 
1528  SCIPdecodeDualBit(lpistate->packcstat, cstat, lpistate->ncols);
1529  SCIPdecodeDualBit(lpistate->packrstat, rstat, lpistate->nrows);
1530 }
1531 
1532 /** creates LPi state information object */
1533 static
1535  SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
1536  BMS_BLKMEM* blkmem, /**< block memory */
1537  int ncols, /**< number of columns to store */
1538  int nrows /**< number of rows to store */
1539  )
1540 {
1541  assert(lpistate != NULL);
1542  assert(blkmem != NULL);
1543  assert(ncols >= 0);
1544  assert(nrows >= 0);
1545 
1546  int nColPackets = colpacketNum(ncols);
1547  int nRowPackets = rowpacketNum(nrows);
1548 
1549  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
1550  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets) );
1551  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets) );
1552 
1553  return SCIP_OKAY;
1554 }
1555 
1556 /** frees LPi state information */
1557 static
1558 void lpistateFree(
1559  SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
1560  BMS_BLKMEM* blkmem /**< block memory */
1561  )
1562 {
1563  assert(blkmem != NULL);
1564  assert(lpistate != NULL);
1565  assert(*lpistate != NULL);
1566 
1567  int nColPackets = colpacketNum((*lpistate)->ncols);
1568  int nRowPackets = rowpacketNum((*lpistate)->nrows);
1569 
1570  BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packcstat, nColPackets);
1571  BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->packrstat, nRowPackets);
1572  BMSfreeBlockMemory(blkmem, lpistate);
1573 }
1574 
1575 
1576 
1577 
1578 /*
1579  * local methods
1580  */
1581 
1582 /** converts SCIP's objective sense into SoPlex's objective sense */
1583 static
1584 SPxLP::SPxSense spxObjsen(
1585  SCIP_OBJSEN objsen /**< SCIP's objective sense value */
1586  )
1588  switch( objsen )
1589  {
1590  case SCIP_OBJSEN_MAXIMIZE:
1591  return SPxLP::MAXIMIZE;
1592  case SCIP_OBJSEN_MINIMIZE:
1593  return SPxLP::MINIMIZE;
1594  default:
1595  SCIPerrorMessage("invalid objective sense\n");
1596  SCIPABORT();
1597  return SPxLP::MINIMIZE; /*lint !e527 */
1598  }
1599 }
1600 
1601 /** marks the current LP to be unsolved */
1602 static
1603 void invalidateSolution(SCIP_LPI* lpi)
1604 {
1605  assert(lpi != NULL);
1606  lpi->solved = FALSE;
1607  if ( lpi->factorization != 0 )
1608  {
1609  delete lpi->factorization;
1610  lpi->factorization = 0;
1611  }
1612 }
1613 
1614 
1615 
1616 /*
1617  * LP Interface Methods
1618  */
1619 
1620 
1621 /*
1622  * Miscellaneous Methods
1623  */
1624 
1625 static char spxname[100];
1626 static char spxdesc[200];
1627 
1628 /**@name Miscellaneous Methods */
1629 /**@{ */
1630 
1631 /** gets name and version of LP solver */
1632 const char* SCIPlpiGetSolverName(
1633  void
1634  )
1636  SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
1637 
1638 #if (SOPLEX_SUBVERSION > 0)
1639  snprintf(spxname, 100, "SoPlex1 %d.%d.%d.%d", SOPLEX_VERSION/100, (SOPLEX_VERSION % 100)/10, SOPLEX_VERSION % 10, SOPLEX_SUBVERSION); /*lint !e778*/
1640 #else
1641  snprintf(spxname, 100, "SoPlex1 %d.%d.%d", SOPLEX_VERSION/100, (SOPLEX_VERSION % 100)/10, SOPLEX_VERSION % 10); /*lint !e778*/
1642 #endif
1643  return spxname;
1644 }
1645 
1646 /** gets description of LP solver (developer, webpage, ...) */
1647 const char* SCIPlpiGetSolverDesc(
1648  void
1649  )
1651 #if (SOPLEX_VERSION >= 160)
1652  snprintf(spxdesc, 200, "Linear Programming Solver developed at Zuse Institute Berlin (soplex.zib.de) [GitHash: %s]"
1653 #ifdef SCIP_WITH_LPSCHECK
1654  " - including CPLEX double check"
1655 #endif
1656  , getGitHash());
1657 #else
1658  snprintf(spxdesc, 200, "Linear Programming Solver developed at Zuse Institute Berlin (soplex.zib.de)"
1659 #ifdef SCIP_WITH_LPSCHECK
1660  " - including CPLEX double check"
1661 #endif
1662  );
1663 #endif
1664  return spxdesc;
1665 }
1666 
1667 /** gets pointer for LP solver - use only with great care */
1669  SCIP_LPI* lpi /**< pointer to an LP interface structure */
1670  )
1672  return (void*) lpi->spx;
1673 }
1674 
1675 /** pass integrality information about variables to the solver */
1677  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
1678  int ncols, /**< length of integrality array */
1679  int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
1680  )
1681 {
1682 #if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
1683  assert(ncols == lpi->spx->nCols() || (ncols == 0 && intInfo == NULL));
1684  lpi->spx->setIntegralityInformation(ncols, intInfo);
1685  return SCIP_OKAY;
1686 #else
1687  SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
1688  return SCIP_LPERROR;
1689 #endif
1690 }
1691 
1692 /** informs about availability of a primal simplex solving method */
1694  void
1695  )
1697  return TRUE;
1698 }
1699 
1700 /** informs about availability of a dual simplex solving method */
1702  void
1703  )
1705  return TRUE;
1706 }
1707 
1708 /** informs about availability of a barrier solving method */
1710  void
1711  )
1713  return FALSE;
1714 }
1715 
1716 /**@} */
1717 
1718 
1719 
1720 
1721 /*
1722  * LPI Creation and Destruction Methods
1723  */
1724 
1725 /**@name LPI Creation and Destruction Methods */
1726 /**@{ */
1727 
1728 /** creates an LP problem object */
1730  SCIP_LPI** lpi, /**< pointer to an LP interface structure */
1731  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
1732  const char* name, /**< problem name */
1733  SCIP_OBJSEN objsen /**< objective sense */
1734  )
1735 {
1736  assert(lpi != NULL);
1737  assert(name != NULL);
1738 
1739  /* create SoPlex object */
1740  SCIP_ALLOC( BMSallocMemory(lpi) );
1741 
1742  /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
1743  (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
1744  SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
1745  (*lpi)->cstat = NULL;
1746  (*lpi)->rstat = NULL;
1747  (*lpi)->cstatsize = 0;
1748  (*lpi)->rstatsize = 0;
1749  (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
1750  (*lpi)->factorization = 0;
1751  (*lpi)->rowrepswitch = SCIPlpiInfinity(*lpi);
1752  (*lpi)->conditionlimit = -1.0;
1753  (*lpi)->checkcondition = FALSE;
1754  (*lpi)->messagehdlr = messagehdlr;
1755 
1756  invalidateSolution(*lpi);
1757 
1758  /* set objective sense */
1759  SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
1760 
1761  /* set default pricing */
1762  SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
1763 
1764  return SCIP_OKAY;
1765 }
1766 
1767 /** deletes an LP problem object */
1769  SCIP_LPI** lpi /**< pointer to an LP interface structure */
1770  )
1772  assert(lpi != NULL);
1773  assert(*lpi != NULL);
1774  assert((*lpi)->spx != NULL);
1775 
1776  /* free LP using destructor and free memory via blockmemshell */
1777  (*lpi)->spx->~SPxSCIP();
1778  BMSfreeMemory(&((*lpi)->spx));
1779 
1780  /* free memory */
1781  BMSfreeMemoryArrayNull(&(*lpi)->cstat);
1782  BMSfreeMemoryArrayNull(&(*lpi)->rstat);
1783  BMSfreeMemory(lpi);
1784 
1785  return SCIP_OKAY;
1786 }
1787 
1788 /**@} */
1789 
1790 
1791 
1792 
1793 /*
1794  * Modification Methods
1795  */
1796 
1797 /**@name Modification Methods */
1798 /**@{ */
1799 
1800 /** copies LP data with column matrix into LP solver */
1802  SCIP_LPI* lpi, /**< LP interface structure */
1803  SCIP_OBJSEN objsen, /**< objective sense */
1804  int ncols, /**< number of columns */
1805  const SCIP_Real* obj, /**< objective function values of columns */
1806  const SCIP_Real* lb, /**< lower bounds of columns */
1807  const SCIP_Real* ub, /**< upper bounds of columns */
1808  char** colnames, /**< column names, or NULL */
1809  int nrows, /**< number of rows */
1810  const SCIP_Real* lhs, /**< left hand sides of rows */
1811  const SCIP_Real* rhs, /**< right hand sides of rows */
1812  char** /*rownames*/, /**< row names, or NULL */
1813  int nnonz, /**< number of nonzero elements in the constraint matrix */
1814  const int* beg, /**< start index of each column in ind- and val-array */
1815  const int* ind, /**< row indices of constraint matrix entries */
1816  const SCIP_Real* val /**< values of constraint matrix entries */
1817  )
1818 {
1819 #ifndef NDEBUG
1820  {
1821  int j;
1822  for( j = 0; j < nnonz; j++ )
1823  assert( val[j] != 0 );
1824  }
1825 #endif
1826 
1827  SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
1828 
1829  assert(lpi != NULL);
1830  assert(lpi->spx != NULL);
1831  assert(lhs != NULL);
1832  assert(rhs != NULL);
1833  assert(obj != NULL);
1834  assert(lb != NULL);
1835  assert(ub != NULL);
1836  assert(beg != NULL);
1837  assert(ind != NULL);
1838  assert(val != NULL);
1839 
1840  invalidateSolution(lpi);
1841  assert( lpi->spx->preStrongbranchingBasisFreed() );
1842 
1843  try
1844  {
1845  SPxSCIP* spx = lpi->spx;
1846  LPRowSet rows(nrows);
1847  DSVector emptyVector(0);
1848  int i;
1849 
1850  spx->clear();
1851 
1852  /* set objective sense */
1853  spx->setSense(spxObjsen(objsen));
1854 
1855  /* create empty rows with given sides */
1856  for( i = 0; i < nrows; ++i )
1857  rows.add(lhs[i], emptyVector, rhs[i]);
1858  spx->addRows(rows);
1859 
1860  /* create column vectors with coefficients and bounds */
1861  SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
1862  }
1863 #ifndef NDEBUG
1864  catch( const SPxException& x )
1865  {
1866  std::string s = x.what();
1867  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1868 #else
1869  catch( const SPxException& )
1870  {
1871 #endif
1872  return SCIP_LPERROR;
1873  }
1874 
1875  return SCIP_OKAY;
1876 }
1877 
1878 /** adds columns to the LP */
1880  SCIP_LPI* lpi, /**< LP interface structure */
1881  int ncols, /**< number of columns to be added */
1882  const SCIP_Real* obj, /**< objective function values of new columns */
1883  const SCIP_Real* lb, /**< lower bounds of new columns */
1884  const SCIP_Real* ub, /**< upper bounds of new columns */
1885  char** /*colnames*/, /**< column names, or NULL */
1886  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1887  const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1888  const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1889  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1890  )
1891 {
1892  SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1893 
1894  assert(lpi != NULL);
1895  assert(lpi->spx != NULL);
1896  assert(obj != NULL);
1897  assert(lb != NULL);
1898  assert(ub != NULL);
1899  assert(nnonz == 0 || beg != NULL);
1900  assert(nnonz == 0 || ind != NULL);
1901  assert(nnonz == 0 || val != NULL);
1902  assert(nnonz >= 0);
1903  assert(ncols >= 0);
1904 
1905  invalidateSolution(lpi);
1906 
1907  assert( lpi->spx->preStrongbranchingBasisFreed() );
1908 
1909 #ifndef NDEBUG
1910  if ( nnonz > 0 )
1911  {
1912  /* perform check that no new rows are added - this is likely to be a mistake */
1913  int nrows = lpi->spx->nRows();
1914  for (int j = 0; j < nnonz; ++j)
1915  {
1916  assert( 0 <= ind[j] && ind[j] < nrows );
1917  assert( val[j] != 0.0 );
1918  }
1919  }
1920 #endif
1921 
1922  SPxSCIP* spx = lpi->spx;
1923  try
1924  {
1925  LPColSet cols(ncols);
1926  DSVector colVector(ncols);
1927  int start;
1928  int last;
1929  int i;
1930 
1931  /* create column vectors with coefficients and bounds */
1932  for( i = 0; i < ncols; ++i )
1933  {
1934  colVector.clear();
1935  if( nnonz > 0 )
1936  {
1937  start = beg[i];
1938  last = (i == ncols-1 ? nnonz : beg[i+1]);
1939  colVector.add( last-start, &ind[start], &val[start] );
1940  }
1941  cols.add(obj[i], lb[i], colVector, ub[i]);
1942  }
1943  spx->addCols(cols);
1944  }
1945 #ifndef NDEBUG
1946  catch( const SPxException& x )
1947  {
1948  std::string s = x.what();
1949  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1950 #else
1951  catch( const SPxException& )
1952  {
1953 #endif
1954  return SCIP_LPERROR;
1955  }
1956 
1957  return SCIP_OKAY;
1958 }
1959 
1960 /** deletes all columns in the given range from LP */
1962  SCIP_LPI* lpi, /**< LP interface structure */
1963  int firstcol, /**< first column to be deleted */
1964  int lastcol /**< last column to be deleted */
1965  )
1966 {
1967  SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1968 
1969  assert(lpi != NULL);
1970  assert(lpi->spx != NULL);
1971  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
1972 
1973  invalidateSolution(lpi);
1974 
1975  assert( lpi->spx->preStrongbranchingBasisFreed() );
1976 
1977  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRange(firstcol, lastcol) );
1978 
1979  return SCIP_OKAY;
1980 }
1981 
1982 /** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1984  SCIP_LPI* lpi, /**< LP interface structure */
1985  int* dstat /**< deletion status of columns
1986  * input: 1 if column should be deleted, 0 if not
1987  * output: new position of column, -1 if column was deleted */
1988  )
1989 {
1990  int ncols;
1991  int i;
1992 
1993  SCIPdebugMessage("calling SCIPlpiDelColset()\n");
1994 
1995  assert(lpi != NULL);
1996  assert(lpi->spx != NULL);
1997  assert(dstat != NULL);
1998 
1999  invalidateSolution(lpi);
2000 
2001  assert( lpi->spx->preStrongbranchingBasisFreed() );
2002 
2003  ncols = lpi->spx->nCols();
2004 
2005  /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
2006  for( i = 0; i < ncols; ++i )
2007  dstat[i] *= -1;
2008 
2009  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeCols(dstat) );
2010 
2011  return SCIP_OKAY;
2012 }
2013 
2014 /** adds rows to the LP */
2016  SCIP_LPI* lpi, /**< LP interface structure */
2017  int nrows, /**< number of rows to be added */
2018  const SCIP_Real* lhs, /**< left hand sides of new rows */
2019  const SCIP_Real* rhs, /**< right hand sides of new rows */
2020  char** /*rownames*/, /**< row names, or NULL */
2021  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
2022  const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
2023  const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
2024  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
2025  )
2026 {
2027  SCIPdebugMessage("calling SCIPlpiAddRows()\n");
2028 
2029  assert(lpi != NULL);
2030  assert(lpi->spx != NULL);
2031  assert(lhs != NULL);
2032  assert(rhs != NULL);
2033  assert(nnonz == 0 || beg != NULL);
2034  assert(nnonz == 0 || ind != NULL);
2035  assert(nnonz == 0 || val != NULL);
2036 
2037  invalidateSolution(lpi);
2038 
2039  assert( lpi->spx->preStrongbranchingBasisFreed() );
2040 
2041 #ifndef NDEBUG
2042  if ( nnonz > 0 )
2043  {
2044  /* perform check that no new columns are added - this is likely to be a mistake */
2045  int ncols = lpi->spx->nCols();
2046  for (int j = 0; j < nnonz; ++j)
2047  {
2048  assert( 0 <= ind[j] && ind[j] < ncols );
2049  assert( val[j] != 0.0 );
2050  }
2051  }
2052 #endif
2053 
2054  try
2055  {
2056  SPxSCIP* spx = lpi->spx;
2057  LPRowSet rows(nrows);
2058  DSVector rowVector;
2059  int start;
2060  int last;
2061  int i;
2062 
2063  /* create row vectors with given sides */
2064  for( i = 0; i < nrows; ++i )
2065  {
2066  rowVector.clear();
2067  if( nnonz > 0 )
2068  {
2069  start = beg[i];
2070  last = (i == nrows-1 ? nnonz : beg[i+1]);
2071  rowVector.add( last-start, &ind[start], &val[start] );
2072  }
2073  rows.add(lhs[i], rowVector, rhs[i]);
2074  }
2075  spx->addRows(rows);
2076  }
2077 #ifndef NDEBUG
2078  catch( const SPxException& x )
2079  {
2080  std::string s = x.what();
2081  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2082 #else
2083  catch( const SPxException& )
2084  {
2085 #endif
2086  return SCIP_LPERROR;
2087  }
2088 
2089  return SCIP_OKAY;
2090 }
2091 
2092 /** deletes all rows in the given range from LP */
2094  SCIP_LPI* lpi, /**< LP interface structure */
2095  int firstrow, /**< first row to be deleted */
2096  int lastrow /**< last row to be deleted */
2097  )
2098 {
2099  SCIPdebugMessage("calling SCIPlpiDelRows()\n");
2100 
2101  assert(lpi != NULL);
2102  assert(lpi->spx != NULL);
2103  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2104 
2105  invalidateSolution(lpi);
2106 
2107  assert( lpi->spx->preStrongbranchingBasisFreed() );
2108 
2109  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRange(firstrow, lastrow) );
2110 
2111  return SCIP_OKAY;
2112 }
2113 
2114 /** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
2116  SCIP_LPI* lpi, /**< LP interface structure */
2117  int* dstat /**< deletion status of rows
2118  * input: 1 if row should be deleted, 0 if not
2119  * output: new position of row, -1 if row was deleted */
2120  )
2121 {
2122  int nrows;
2123  int i;
2124 
2125  SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
2126 
2127  assert(lpi != NULL);
2128  assert(lpi->spx != NULL);
2129 
2130  invalidateSolution(lpi);
2131 
2132  assert( lpi->spx->preStrongbranchingBasisFreed() );
2133 
2134  nrows = lpi->spx->nRows();
2135 
2136  /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
2137  for( i = 0; i < nrows; ++i )
2138  dstat[i] *= -1;
2139 
2140  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRows(dstat) );
2141 
2142  return SCIP_OKAY;
2143 }
2144 
2145 /** clears the whole LP */
2147  SCIP_LPI* lpi /**< LP interface structure */
2148  )
2150  SCIPdebugMessage("calling SCIPlpiClear()\n");
2151 
2152  assert(lpi != NULL);
2153  assert(lpi->spx != NULL);
2154 
2155  invalidateSolution(lpi);
2156 
2157  assert( lpi->spx->preStrongbranchingBasisFreed() );
2158  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clear() );
2159 
2160  return SCIP_OKAY;
2161 }
2162 
2163 /** changes lower and upper bounds of columns */
2165  SCIP_LPI* lpi, /**< LP interface structure */
2166  int ncols, /**< number of columns to change bounds for */
2167  const int* ind, /**< column indices or NULL if ncols is zero */
2168  const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
2169  const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
2170  )
2171 {
2172  int i;
2173 
2174  SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
2175 
2176  assert(lpi != NULL);
2177  assert(lpi->spx != NULL);
2178  assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
2179  if( ncols <= 0 )
2180  return SCIP_OKAY;
2181 
2182  invalidateSolution(lpi);
2183 
2184  assert( lpi->spx->preStrongbranchingBasisFreed() );
2185 
2186  try
2187  {
2188  for( i = 0; i < ncols; ++i )
2189  {
2190  assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2191 
2192  if ( SCIPlpiIsInfinity(lpi, lb[i]) )
2193  {
2194  SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
2195  return SCIP_LPERROR;
2196  }
2197  if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
2198  {
2199  SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
2200  return SCIP_LPERROR;
2201  }
2202 
2203  lpi->spx->changeBounds(ind[i], lb[i], ub[i]);
2204  assert(lpi->spx->lower(ind[i]) <= lpi->spx->upper(ind[i]) + Param::epsilon());
2205  }
2206  }
2207 #ifndef NDEBUG
2208  catch( const SPxException& x )
2209  {
2210  std::string s = x.what();
2211  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2212 #else
2213  catch( const SPxException& )
2214  {
2215 #endif
2216  return SCIP_LPERROR;
2217  }
2218 
2219  return SCIP_OKAY;
2220 }
2221 
2222 /** changes left and right hand sides of rows */
2224  SCIP_LPI* lpi, /**< LP interface structure */
2225  int nrows, /**< number of rows to change sides for */
2226  const int* ind, /**< row indices */
2227  const SCIP_Real* lhs, /**< new values for left hand sides */
2228  const SCIP_Real* rhs /**< new values for right hand sides */
2229  )
2230 {
2231  int i;
2232 
2233  SCIPdebugMessage("calling SCIPlpiChgSides()\n");
2234 
2235  assert(lpi != NULL);
2236  assert(lpi->spx != NULL);
2237  assert(ind != NULL);
2238  assert(lhs != NULL);
2239  assert(rhs != NULL);
2240  if( nrows <= 0 )
2241  return SCIP_OKAY;
2242 
2243  invalidateSolution(lpi);
2244 
2245  assert( lpi->spx->preStrongbranchingBasisFreed() );
2246 
2247  try
2248  {
2249  for( i = 0; i < nrows; ++i )
2250  {
2251  assert(0 <= ind[i] && ind[i] < lpi->spx->nRows());
2252  lpi->spx->changeRange(ind[i], lhs[i], rhs[i]);
2253  assert(lpi->spx->lhs(ind[i]) <= lpi->spx->rhs(ind[i]) + Param::epsilon());
2254  }
2255  }
2256 #ifndef NDEBUG
2257  catch( const SPxException& x )
2258  {
2259  std::string s = x.what();
2260  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2261 #else
2262  catch( const SPxException& )
2263  {
2264 #endif
2265  return SCIP_LPERROR;
2266  }
2267 
2268  return SCIP_OKAY;
2269 }
2270 
2271 /** changes a single coefficient */
2273  SCIP_LPI* lpi, /**< LP interface structure */
2274  int row, /**< row number of coefficient to change */
2275  int col, /**< column number of coefficient to change */
2276  SCIP_Real newval /**< new value of coefficient */
2277  )
2278 {
2279  SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
2280 
2281  assert(lpi != NULL);
2282  assert(lpi->spx != NULL);
2283  assert(0 <= row && row < lpi->spx->nRows());
2284  assert(0 <= col && col < lpi->spx->nCols());
2285 
2286  invalidateSolution(lpi);
2287 
2288  assert( lpi->spx->preStrongbranchingBasisFreed() );
2289 
2290  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElement(row, col, newval) );
2291 
2292  return SCIP_OKAY;
2293 }
2294 
2295 /** changes the objective sense */
2297  SCIP_LPI* lpi, /**< LP interface structure */
2298  SCIP_OBJSEN objsen /**< new objective sense */
2299  )
2300 {
2301  SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
2302 
2303  assert(lpi != NULL);
2304  assert(lpi->spx != NULL);
2305 
2306  invalidateSolution(lpi);
2307 
2308  assert( lpi->spx->preStrongbranchingBasisFreed() );
2309 
2310  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setSense(spxObjsen(objsen)) );
2311 
2312  return SCIP_OKAY;
2313 }
2314 
2315 /** changes objective values of columns in the LP */
2317  SCIP_LPI* lpi, /**< LP interface structure */
2318  int ncols, /**< number of columns to change objective value for */
2319  const int* ind, /**< column indices to change objective value for */
2320  const SCIP_Real* obj /**< new objective values for columns */
2321  )
2322 {
2323  int i;
2324 
2325  SCIPdebugMessage("calling SCIPlpiChgObj()\n");
2326 
2327  assert(lpi != NULL);
2328  assert(lpi->spx != NULL);
2329  assert(ind != NULL);
2330  assert(obj != NULL);
2331 
2332  invalidateSolution(lpi);
2333 
2334  assert( lpi->spx->preStrongbranchingBasisFreed() );
2335 
2336  try
2337  {
2338  for( i = 0; i < ncols; ++i )
2339  {
2340  assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2341  lpi->spx->changeObj(ind[i], obj[i]);
2342  }
2343  }
2344 #ifndef NDEBUG
2345  catch( const SPxException& x )
2346  {
2347  std::string s = x.what();
2348  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2349 #else
2350  catch( const SPxException& )
2351  {
2352 #endif
2353  return SCIP_LPERROR;
2354  }
2355 
2356  return SCIP_OKAY;
2357 }
2358 
2359 /** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
2361  SCIP_LPI* lpi, /**< LP interface structure */
2362  int row, /**< row number to scale */
2363  SCIP_Real scaleval /**< scaling multiplier */
2364  )
2365 {
2366  SCIP_Real lhs;
2367  SCIP_Real rhs;
2368 
2369  SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
2370 
2371  assert(lpi != NULL);
2372  assert(lpi->spx != NULL);
2373  assert(scaleval != 0.0);
2374 
2375  try
2376  {
2377  invalidateSolution(lpi);
2378 
2379  assert( lpi->spx->preStrongbranchingBasisFreed() );
2380 
2381  /* get the row vector and the row's sides */
2382  SVector rowvec = lpi->spx->rowVector(row);
2383  lhs = lpi->spx->lhs(row);
2384  rhs = lpi->spx->rhs(row);
2385 
2386  /* scale the row vector */
2387  rowvec *= scaleval;
2388 
2389  /* adjust the sides */
2390  if( lhs > -soplex::infinity )
2391  lhs *= scaleval;
2392  else if( scaleval < 0.0 )
2393  lhs = soplex::infinity;
2394  if( rhs < soplex::infinity )
2395  rhs *= scaleval;
2396  else if( scaleval < 0.0 )
2397  rhs = -soplex::infinity;
2398  if( scaleval < 0.0 )
2399  {
2400  SCIP_Real oldlhs = lhs;
2401  lhs = rhs;
2402  rhs = oldlhs;
2403  }
2404 
2405  /* create the new row */
2406  LPRow lprow(lhs, rowvec, rhs);
2407 
2408  /* change the row in the LP */
2409  lpi->spx->changeRow(row, lprow);
2410  assert(lpi->spx->lhs(row) <= lpi->spx->rhs(row));
2411  }
2412 #ifndef NDEBUG
2413  catch( const SPxException& x )
2414  {
2415  std::string s = x.what();
2416  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2417 #else
2418  catch( const SPxException& )
2419  {
2420 #endif
2421  return SCIP_LPERROR;
2422  }
2423 
2424  return SCIP_OKAY;
2425 }
2426 
2427 /** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
2428  * are divided by the scalar; for negative scalars, the column's bounds are switched
2429  */
2431  SCIP_LPI* lpi, /**< LP interface structure */
2432  int col, /**< column number to scale */
2433  SCIP_Real scaleval /**< scaling multiplier */
2434  )
2435 {
2436  SCIP_Real obj;
2437  SCIP_Real lb;
2438  SCIP_Real ub;
2439 
2440  SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
2441 
2442  assert(lpi != NULL);
2443  assert(lpi->spx != NULL);
2444  assert(scaleval != 0.0);
2445 
2446  try
2447  {
2448  invalidateSolution(lpi);
2449 
2450  assert( lpi->spx->preStrongbranchingBasisFreed() );
2451 
2452  /* get the col vector and the col's bounds and objective value */
2453  SVector colvec = lpi->spx->colVector(col);
2454  obj = lpi->spx->obj(col);
2455  lb = lpi->spx->lower(col);
2456  ub = lpi->spx->upper(col);
2457 
2458  /* scale the col vector */
2459  colvec *= scaleval;
2460 
2461  /* scale the objective value */
2462  obj *= scaleval;
2463 
2464  /* adjust the bounds */
2465  if( lb > -soplex::infinity )
2466  lb /= scaleval;
2467  else if( scaleval < 0.0 )
2468  lb = soplex::infinity;
2469  if( ub < soplex::infinity )
2470  ub /= scaleval;
2471  else if( scaleval < 0.0 )
2472  ub = -soplex::infinity;
2473  if( scaleval < 0.0 )
2474  {
2475  SCIP_Real oldlb = lb;
2476  lb = ub;
2477  ub = oldlb;
2478  }
2479 
2480  /* create the new col (in LPCol's constructor, the upper bound is given first!) */
2481  LPCol lpcol(obj, colvec, ub, lb);
2482 
2483  /* change the col in the LP */
2484  lpi->spx->changeCol(col, lpcol);
2485  assert(lpi->spx->lower(col) <= lpi->spx->upper(col));
2486  }
2487 #ifndef NDEBUG
2488  catch( const SPxException& x )
2489  {
2490  std::string s = x.what();
2491  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2492 #else
2493  catch( const SPxException& )
2494  {
2495 #endif
2496  return SCIP_LPERROR;
2497  }
2498 
2499  return SCIP_OKAY;
2500 }
2501 
2502 /**@} */
2503 
2504 
2505 
2506 
2507 /*
2508  * Data Accessing Methods
2509  */
2510 
2511 /**@name Data Accessing Methods */
2512 /**@{ */
2513 
2514 /** gets the number of rows in the LP */
2516  SCIP_LPI* lpi, /**< LP interface structure */
2517  int* nrows /**< pointer to store the number of rows */
2518  )
2519 {
2520  SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
2521 
2522  assert(lpi != NULL);
2523  assert(lpi->spx != NULL);
2524  assert(nrows != NULL);
2525 
2526  *nrows = lpi->spx->nRows();
2527 
2528  return SCIP_OKAY;
2529 }
2530 
2531 /** gets the number of columns in the LP */
2533  SCIP_LPI* lpi, /**< LP interface structure */
2534  int* ncols /**< pointer to store the number of cols */
2535  )
2536 {
2537  SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
2538 
2539  assert(lpi != NULL);
2540  assert(lpi->spx != NULL);
2541  assert(ncols != NULL);
2542 
2543  *ncols = lpi->spx->nCols();
2544 
2545  return SCIP_OKAY;
2546 }
2547 
2548 /** gets the number of nonzero elements in the LP constraint matrix */
2550  SCIP_LPI* lpi, /**< LP interface structure */
2551  int* nnonz /**< pointer to store the number of nonzeros */
2552  )
2553 {
2554  int i;
2555 
2556  SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
2557 
2558  assert(lpi != NULL);
2559  assert(lpi->spx != NULL);
2560  assert(nnonz != NULL);
2561 
2562  /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
2563  *nnonz = 0;
2564  if( lpi->spx->nRows() < lpi->spx->nCols() )
2565  {
2566  for( i = 0; i < lpi->spx->nRows(); ++i )
2567  (*nnonz) += lpi->spx->rowVector(i).size();
2568  }
2569  else
2570  {
2571  for( i = 0; i < lpi->spx->nCols(); ++i )
2572  (*nnonz) += lpi->spx->colVector(i).size();
2573  }
2574 
2575  return SCIP_OKAY;
2576 }
2577 
2578 /** gets columns from LP problem object; the arrays have to be large enough to store all values
2579  * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
2580  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2581  */
2583  SCIP_LPI* lpi, /**< LP interface structure */
2584  int firstcol, /**< first column to get from LP */
2585  int lastcol, /**< last column to get from LP */
2586  SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
2587  SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
2588  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2589  int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
2590  int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
2591  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2592  )
2593 {
2594  int i;
2595  int j;
2596 
2597  SCIPdebugMessage("calling SCIPlpiGetCols()\n");
2598 
2599  assert(lpi != NULL);
2600  assert(lpi->spx != NULL);
2601  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2602  assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
2603  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2604 
2605  if( lb != NULL )
2606  {
2607  const Vector& lbvec = lpi->spx->lower();
2608  const Vector& ubvec = lpi->spx->upper();
2609  for( i = firstcol; i <= lastcol; ++i )
2610  {
2611  lb[i-firstcol] = lbvec[i];
2612  ub[i-firstcol] = ubvec[i];
2613  }
2614  }
2615 
2616  if( nnonz != NULL )
2617  {
2618  *nnonz = 0;
2619  for( i = firstcol; i <= lastcol; ++i )
2620  {
2621  beg[i-firstcol] = *nnonz;
2622  const SVector& cvec = lpi->spx->colVector(i);
2623  for( j = 0; j < cvec.size(); ++j )
2624  {
2625  ind[*nnonz] = cvec.index(j);
2626  val[*nnonz] = cvec.value(j);
2627  (*nnonz)++;
2628  }
2629  }
2630  }
2631 
2632  return SCIP_OKAY;
2633 }
2634 
2635 /** gets rows from LP problem object; the arrays have to be large enough to store all values.
2636  * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
2637  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2638  */
2640  SCIP_LPI* lpi, /**< LP interface structure */
2641  int firstrow, /**< first row to get from LP */
2642  int lastrow, /**< last row to get from LP */
2643  SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
2644  SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
2645  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2646  int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
2647  int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
2648  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2649  )
2650 {
2651  int i;
2652  int j;
2653 
2654  SCIPdebugMessage("calling SCIPlpiGetRows()\n");
2655 
2656  assert(lpi != NULL);
2657  assert(lpi->spx != NULL);
2658  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2659  assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
2660  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2661 
2662  if( lhs != NULL )
2663  {
2664  const Vector& lhsvec = lpi->spx->lhs();
2665  const Vector& rhsvec = lpi->spx->rhs();
2666  for( i = firstrow; i <= lastrow; ++i )
2667  {
2668  lhs[i-firstrow] = lhsvec[i];
2669  rhs[i-firstrow] = rhsvec[i];
2670  }
2671  }
2672 
2673  if( nnonz != NULL )
2674  {
2675  *nnonz = 0;
2676  for( i = firstrow; i <= lastrow; ++i )
2677  {
2678  beg[i-firstrow] = *nnonz;
2679  const SVector& rvec = lpi->spx->rowVector(i);
2680  for( j = 0; j < rvec.size(); ++j )
2681  {
2682  ind[*nnonz] = rvec.index(j);
2683  val[*nnonz] = rvec.value(j);
2684  (*nnonz)++;
2685  }
2686  }
2687  }
2688 
2689  return SCIP_OKAY;
2690 }
2691 
2692 /** gets column names */
2694  SCIP_LPI* lpi, /**< LP interface structure */
2695  int firstcol, /**< first column to get name from LP */
2696  int lastcol, /**< last column to get name from LP */
2697  char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
2698  char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
2699  int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
2700  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2701  )
2702 {
2703  assert( lpi != NULL );
2704  assert( lpi->spx != NULL );
2705  assert( colnames != NULL || namestoragesize == 0 );
2706  assert( namestorage != NULL || namestoragesize == 0 );
2707  assert( namestoragesize >= 0 );
2708  assert( storageleft != NULL );
2709  assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols() );
2710 
2711  SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
2712 
2713  lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
2714 
2715  return SCIP_OKAY;
2716 }
2717 
2718 /** gets row names */
2720  SCIP_LPI* lpi, /**< LP interface structure */
2721  int firstrow, /**< first row to get name from LP */
2722  int lastrow, /**< last row to get name from LP */
2723  char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
2724  char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
2725  int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
2726  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2727  )
2728 {
2729  assert( lpi != NULL );
2730  assert( lpi->spx != NULL );
2731  assert( rownames != NULL || namestoragesize == 0 );
2732  assert( namestorage != NULL || namestoragesize == 0 );
2733  assert( namestoragesize >= 0 );
2734  assert( storageleft != NULL );
2735  assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows() );
2736 
2737  SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
2738 
2739  lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
2740 
2741  return SCIP_OKAY;
2742 }
2743 
2744 /** gets objective sense of the LP */
2746  SCIP_LPI* lpi, /**< LP interface structure */
2747  SCIP_OBJSEN* objsen /**< pointer to store objective sense */
2748  )
2749 {
2750  SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
2751 
2752  assert(lpi != NULL);
2753  assert(lpi->spx != NULL);
2754  assert(objsen != NULL);
2755 
2756  *objsen = (lpi->spx->getSense() == SPxLP::MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
2757 
2758  return SCIP_OKAY;
2759 }
2760 
2761 /** gets objective coefficients from LP problem object */
2763  SCIP_LPI* lpi, /**< LP interface structure */
2764  int firstcol, /**< first column to get objective coefficient for */
2765  int lastcol, /**< last column to get objective coefficient for */
2766  SCIP_Real* vals /**< array to store objective coefficients */
2767  )
2768 {
2769  int i;
2770 
2771  SCIPdebugMessage("calling SCIPlpiGetObj()\n");
2772 
2773  assert(lpi != NULL);
2774  assert(lpi->spx != NULL);
2775  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2776  assert(vals != NULL);
2777 
2778  for( i = firstcol; i <= lastcol; ++i )
2779  vals[i-firstcol] = lpi->spx->obj(i);
2780 
2781  return SCIP_OKAY;
2782 }
2783 
2784 /** gets current bounds from LP problem object */
2786  SCIP_LPI* lpi, /**< LP interface structure */
2787  int firstcol, /**< first column to get objective value for */
2788  int lastcol, /**< last column to get objective value for */
2789  SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
2790  SCIP_Real* ubs /**< array to store upper bound values, or NULL */
2791  )
2792 {
2793  int i;
2794 
2795  SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
2796 
2797  assert(lpi != NULL);
2798  assert(lpi->spx != NULL);
2799  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2800 
2801  for( i = firstcol; i <= lastcol; ++i )
2802  {
2803  if( lbs != NULL )
2804  lbs[i-firstcol] = lpi->spx->lower(i);
2805  if( ubs != NULL )
2806  ubs[i-firstcol] = lpi->spx->upper(i);
2807  }
2808 
2809  return SCIP_OKAY;
2810 }
2811 
2812 /** gets current row sides from LP problem object */
2814  SCIP_LPI* lpi, /**< LP interface structure */
2815  int firstrow, /**< first row to get sides for */
2816  int lastrow, /**< last row to get sides for */
2817  SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2818  SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2819  )
2820 {
2821  int i;
2822 
2823  SCIPdebugMessage("calling SCIPlpiGetSides()\n");
2824 
2825  assert(lpi != NULL);
2826  assert(lpi->spx != NULL);
2827  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2828 
2829  for( i = firstrow; i <= lastrow; ++i )
2830  {
2831  if( lhss != NULL )
2832  lhss[i-firstrow] = lpi->spx->lhs(i);
2833  if( rhss != NULL )
2834  rhss[i-firstrow] = lpi->spx->rhs(i);
2835  }
2836 
2837  return SCIP_OKAY;
2838 }
2839 
2840 /** gets a single coefficient */
2842  SCIP_LPI* lpi, /**< LP interface structure */
2843  int row, /**< row number of coefficient */
2844  int col, /**< column number of coefficient */
2845  SCIP_Real* val /**< pointer to store the value of the coefficient */
2846  )
2847 {
2848  SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
2849 
2850  assert(lpi != NULL);
2851  assert(lpi->spx != NULL);
2852  assert(0 <= col && col < lpi->spx->nCols());
2853  assert(0 <= row && row < lpi->spx->nRows());
2854  assert(val != NULL);
2855 
2856  *val = lpi->spx->colVector(col)[row];
2857 
2858  return SCIP_OKAY;
2859 }
2860 
2861 /**@} */
2862 
2863 
2864 
2865 
2866 /*
2867  * Solving Methods
2868  */
2869 
2870 /**@name Solving Methods */
2871 /**@{ */
2872 
2873 /** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
2874 static
2876  SCIP_LPI* lpi, /**< LP interface structure */
2877  SPxSolver::Representation rep, /**< basis representation */
2878  SPxSolver::Type type /**< algorithm type */
2879  )
2880 {
2881  assert( lpi != NULL );
2882  assert( lpi->spx != NULL );
2883  assert( rep == SPxSolver::ROW || rep == SPxSolver::COLUMN );
2884  assert( type == SPxSolver::ENTER || type == SPxSolver::LEAVE );
2885 
2886  SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows, rep=%s\n", lpi->spx->nCols(), lpi->spx->nRows(),
2887  rep == SPxSolver::COLUMN ? "column" : "row");
2888 
2889  invalidateSolution(lpi);
2890 
2891  assert( lpi->spx->preStrongbranchingBasisFreed() );
2892 
2893  /* set basis representation and algorithm type */
2894  lpi->spx->setRep(rep);
2895  lpi->spx->setType(type);
2896 
2897 #ifdef SCIP_WITH_LPSCHECK
2898  lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2899 #endif
2900 
2901  SPxSolver::Status status = lpi->spx->solve();
2902  SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->getStatus(), lpi->spx->basis().status());
2903  lpi->solved = TRUE;
2904 
2905  switch( status )
2906  {
2907  case SPxSolver::ABORT_TIME:
2908  case SPxSolver::ABORT_ITER:
2909  case SPxSolver::ABORT_VALUE:
2910  case SPxSolver::SINGULAR:
2911  case SPxSolver::REGULAR:
2912  case SPxSolver::UNKNOWN:
2913  case SPxSolver::OPTIMAL:
2914  case SPxSolver::UNBOUNDED:
2915  case SPxSolver::INFEASIBLE:
2916  return SCIP_OKAY;
2917  default:
2918  return SCIP_LPERROR;
2919  } /*lint !e788*/
2920 }
2921 
2922 /** calls primal simplex to solve the LP */
2924  SCIP_LPI* lpi /**< LP interface structure */
2925  )
2927  SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2928 
2929  SCIP_RETCODE retcode;
2930  SCIP_Bool rowrep;
2931 
2932  assert(lpi != NULL);
2933  assert(lpi->spx != NULL);
2934 
2935  /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
2936  factor 1.1 for switching back to column representation */
2937  if( lpi->rowrepswitch >= 0 )
2938  {
2939  rowrep = lpi->spx->rep() == SPxSolver::ROW;
2940 
2941  if( !rowrep )
2942  rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
2943  else
2944  rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
2945  }
2946  else
2947  rowrep = FALSE;
2948 
2949  /* SoPlex doesn't distinct between the primal and dual simplex; however
2950  * we can force SoPlex to start with the desired method:
2951  * If the representation is COLUMN:
2952  * - ENTER = PRIMAL
2953  * - LEAVE = DUAL
2954  *
2955  * If the representation is ROW:
2956  * - ENTER = DUAL
2957  * - LEAVE = PRIMAL
2958  */
2959  retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::LEAVE) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::ENTER);
2960  assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
2961  assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
2962 
2963  return retcode;
2964 }
2965 
2966 /** calls dual simplex to solve the LP */
2968  SCIP_LPI* lpi /**< LP interface structure */
2969  )
2971  SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2972 
2973  SCIP_RETCODE retcode;
2974  SCIP_Bool rowrep;
2975 
2976  assert(lpi != NULL);
2977  assert(lpi->spx != NULL);
2978 
2979  /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
2980  factor 1.1 for switching back to column representation */
2981  if( lpi->rowrepswitch >= 0 )
2982  {
2983  rowrep = lpi->spx->rep() == SPxSolver::ROW;
2984 
2985  if( !rowrep )
2986  rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
2987  else
2988  rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
2989  }
2990  else
2991  rowrep = FALSE;
2992 
2993  /* SoPlex doesn't distinct between the primal and dual simplex; however
2994  * we can force SoPlex to start with the desired method:
2995  * If the representation is COLUMN:
2996  * - ENTER = PRIMAL
2997  * - LEAVE = DUAL
2998  *
2999  * If the representation is ROW:
3000  * - ENTER = DUAL
3001  * - LEAVE = PRIMAL
3002  */
3003  retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::ENTER) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::LEAVE);
3004  assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
3005  assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
3006 
3007  return retcode;
3008 }
3009 
3010 /** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
3012  SCIP_LPI* lpi, /**< LP interface structure */
3013  SCIP_Bool crossover /**< perform crossover */
3014  )
3015 { /*lint --e{715}*/
3016  assert(lpi != NULL);
3017  assert(lpi->spx != NULL);
3018 
3019  SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
3020 
3021  /* SoPlex does not support barrier (yet) */
3022  SCIPerrorMessage("SCIPlpiSolveBarrier() not supported by SoPlex\n");
3023  return SCIP_INVALIDCALL;
3024 }
3025 
3026 /** start strong branching - call before any strongbranching */
3028  SCIP_LPI* lpi /**< LP interface structure */
3029  )
3031  assert(lpi != NULL);
3032  assert(lpi->spx != NULL);
3033 
3034  assert( lpi->spx->preStrongbranchingBasisFreed() );
3035  lpi->spx->savePreStrongbranchingBasis();
3036 
3037  return SCIP_OKAY;
3038 }
3039 
3040 /** end strong branching - call after any strongbranching */
3042  SCIP_LPI* lpi /**< LP interface structure */
3043  )
3045  assert(lpi != NULL);
3046  assert(lpi->spx != NULL);
3047 
3048  assert( ! lpi->spx->preStrongbranchingBasisFreed() );
3049  lpi->spx->restorePreStrongbranchingBasis();
3050  lpi->spx->freePreStrongbranchingBasis();
3051 
3052  return SCIP_OKAY;
3053 }
3054 
3055 /** performs strong branching iterations on one arbitrary candidate */
3056 static
3058  SCIP_LPI* lpi, /**< LP interface structure */
3059  int col, /**< column to apply strong branching on */
3060  SCIP_Real psol, /**< current primal solution value of column */
3061  int itlim, /**< iteration limit for strong branchings */
3062  SCIP_Real* down, /**< stores dual bound after branching column down */
3063  SCIP_Real* up, /**< stores dual bound after branching column up */
3064  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3065  * otherwise, it can only be used as an estimate value */
3066  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3067  * otherwise, it can only be used as an estimate value */
3068  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3069  )
3070 {
3071  SPxSCIP* spx;
3072  SPxSolver::Status status;
3073  SCIP_Real oldlb;
3074  SCIP_Real oldub;
3075  SCIP_Real newlb;
3076  SCIP_Real newub;
3077  bool fromparentbasis;
3078  bool error;
3079  int oldItlim;
3080 
3081  SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
3082 
3083  assert(lpi != NULL);
3084  assert(lpi->spx != NULL);
3085  /* assert(down != NULL);
3086  * assert(up != NULL); temporary hack for cloud branching */
3087  assert(downvalid != NULL);
3088  assert(upvalid != NULL);
3089 
3090  spx = lpi->spx;
3091  status = SPxSolver::UNKNOWN;
3092  fromparentbasis = false;
3093  error = false;
3094  oldItlim = spx->getIterationLimit();
3095 
3096  /* get current bounds of column */
3097  oldlb = spx->lower(col);
3098  oldub = spx->upper(col);
3099 
3100  *downvalid = FALSE;
3101  *upvalid = FALSE;
3102 
3103  if( iter != NULL )
3104  *iter = 0;
3105 
3106  /* set the algorithm type to use dual simplex */
3107  lpi->spx->setType( lpi->spx->rep() == SPxSolver::ROW ? SPxSolver::ENTER : SPxSolver::LEAVE);
3108 
3109  /* down branch */
3110  newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
3111  if( newub >= oldlb - 0.5 && down != NULL )
3112  {
3113  SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
3114 
3115  spx->changeUpper(col, newub);
3116  assert(spx->lower(col) <= spx->upper(col));
3117 
3118  spx->setIterationLimit(itlim);
3119  do
3120  {
3121 #ifdef SCIP_WITH_LPSCHECK
3122  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3123 #endif
3124  status = spx->solve();
3125  SCIPdebugMessage(" --> Terminate with status %d\n", status);
3126  switch( status )
3127  {
3128  case SPxSolver::OPTIMAL:
3129  *down = spx->value();
3130  *downvalid = TRUE;
3131  SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3132  break;
3133  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3134  case SPxSolver::ABORT_ITER:
3135  case SPxSolver::ABORT_CYCLING:
3136  *down = spx->value();
3137  break;
3138  case SPxSolver::ABORT_VALUE:
3139  case SPxSolver::INFEASIBLE:
3140  *down = spx->terminationValue();
3141  *downvalid = TRUE;
3142  break;
3143  default:
3144  error = true;
3145  break;
3146  } /*lint !e788*/
3147  if( iter != NULL )
3148  (*iter) += spx->iterations();
3149 
3150 #ifdef STRONGBRANCH_RESTOREBASIS
3151  /* we restore the pre-strong-branching basis by default (and don't solve again) */
3152  assert( ! spx->preStrongbranchingBasisFreed() );
3153  spx->restorePreStrongbranchingBasis();
3154  fromparentbasis = false;
3155 #else
3156  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3157  * pre-strong-branching basis and try again with reduced iteration limit */
3158  if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3159  {
3160  SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n", itlim - spx->iterations());
3161  spx->setIterationLimit(itlim - spx->iterations());
3162  spx->restorePreStrongbranchingBasis();
3163  fromparentbasis = true;
3164  error = false;
3165  }
3166  /* otherwise don't solve again */
3167  else
3168  fromparentbasis = false;
3169 #endif
3170  }
3171  while( fromparentbasis );
3172 
3173  spx->changeUpper(col, oldub);
3174  assert(spx->lower(col) <= spx->upper(col));
3175  }
3176  else if( down != NULL )
3177  {
3178  *down = spx->terminationValue();
3179  *downvalid = TRUE;
3180  }
3181  else
3182  *downvalid = TRUE;
3183 
3184  /* up branch */
3185  if( !error )
3186  {
3187  newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
3188  if( newlb <= oldub + 0.5 && up != NULL )
3189  {
3190  SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
3191 
3192  spx->changeLower(col, newlb);
3193  assert(spx->lower(col) <= spx->upper(col));
3194 
3195  spx->setIterationLimit(itlim);
3196  do
3197  {
3198 #ifdef SCIP_WITH_LPSCHECK
3199  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3200 #endif
3201  status = spx->solve();
3202  SCIPdebugMessage(" --> Terminate with status %d\n", status);
3203  switch( status )
3204  {
3205  case SPxSolver::OPTIMAL:
3206  *up = spx->value();
3207  *upvalid = TRUE;
3208  SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3209  break;
3210  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3211  case SPxSolver::ABORT_ITER:
3212  case SPxSolver::ABORT_CYCLING:
3213  *up = spx->value();
3214  break;
3215  case SPxSolver::ABORT_VALUE:
3216  case SPxSolver::INFEASIBLE:
3217  *up = spx->terminationValue();
3218  *upvalid = TRUE;
3219  break;
3220  default:
3221  error = true;
3222  break;
3223  } /*lint !e788*/
3224  if( iter != NULL )
3225  (*iter) += spx->iterations();
3226 
3227 #ifdef STRONGBRANCH_RESTOREBASIS
3228  /* we restore the pre-strong-branching basis by default (and don't solve again) */
3229  assert( ! spx->preStrongbranchingBasisFreed() );
3230  spx->restorePreStrongbranchingBasis();
3231  fromparentbasis = false;
3232 #else
3233  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3234  * pre-strong-branching basis and try again with reduced iteration limit */
3235  if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3236  {
3237  SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->iterations());
3238  spx->restorePreStrongbranchingBasis();
3239  spx->setIterationLimit(itlim - spx->iterations());
3240  error = false;
3241  fromparentbasis = true;
3242  }
3243  /* otherwise don't solve again */
3244  else
3245  fromparentbasis = false;
3246 #endif
3247  }
3248  while( fromparentbasis );
3249 
3250  spx->changeLower(col, oldlb);
3251  assert(spx->lower(col) <= spx->upper(col));
3252  }
3253  else if( up != NULL )
3254  {
3255  *up = spx->terminationValue();
3256  *upvalid = TRUE;
3257  }
3258  else
3259  *upvalid = TRUE;
3260  }
3261 
3262  /* reset old iteration limit */
3263  spx->setIterationLimit(oldItlim);
3264 
3265  if( error )
3266  {
3267  SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status));
3268  return SCIP_LPERROR;
3269  }
3270 
3271  return SCIP_OKAY;
3272 }
3273 
3274 /** performs strong branching iterations on one @b fractional candidate */
3276  SCIP_LPI* lpi, /**< LP interface structure */
3277  int col, /**< column to apply strong branching on */
3278  SCIP_Real psol, /**< fractional current primal solution value of column */
3279  int itlim, /**< iteration limit for strong branchings */
3280  SCIP_Real* down, /**< stores dual bound after branching column down */
3281  SCIP_Real* up, /**< stores dual bound after branching column up */
3282  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3283  * otherwise, it can only be used as an estimate value */
3284  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3285  * otherwise, it can only be used as an estimate value */
3286  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3287  )
3288 {
3289  SCIP_RETCODE retcode;
3290 
3291  /* pass call on to lpiStrongbranch() */
3292  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
3293 
3294  /* pass SCIP_LPERROR to SCIP without a back trace */
3295  if( retcode == SCIP_LPERROR )
3296  return SCIP_LPERROR;
3297 
3298  /* evaluate retcode */
3299  SCIP_CALL( retcode );
3300 
3301  return SCIP_OKAY;
3302 }
3303 
3304 /** performs strong branching iterations on given @b fractional candidates */
3306  SCIP_LPI* lpi, /**< LP interface structure */
3307  int* cols, /**< columns to apply strong branching on */
3308  int ncols, /**< number of columns */
3309  SCIP_Real* psols, /**< fractional current primal solution values of columns */
3310  int itlim, /**< iteration limit for strong branchings */
3311  SCIP_Real* down, /**< stores dual bounds after branching columns down */
3312  SCIP_Real* up, /**< stores dual bounds after branching columns up */
3313  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3314  * otherwise, they can only be used as an estimate values */
3315  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3316  * otherwise, they can only be used as an estimate values */
3317  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3318  )
3319 {
3320  SCIP_RETCODE retcode;
3321 
3322  assert( cols != NULL );
3323  assert( psols != NULL );
3324  assert( down != NULL );
3325  assert( up != NULL );
3326  assert( downvalid != NULL );
3327  assert( upvalid != NULL );
3328  assert( down != NULL );
3329 
3330  if ( iter != NULL )
3331  *iter = 0;
3332 
3333  for (int j = 0; j < ncols; ++j)
3334  {
3335  /* pass call on to lpiStrongbranch() */
3336  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3337 
3338  /* pass SCIP_LPERROR to SCIP without a back trace */
3339  if( retcode == SCIP_LPERROR )
3340  return SCIP_LPERROR;
3341 
3342  /* evaluate retcode */
3343  SCIP_CALL( retcode );
3344  }
3345  return SCIP_OKAY;
3346 }
3347 
3348 /** performs strong branching iterations on one candidate with @b integral value */
3350  SCIP_LPI* lpi, /**< LP interface structure */
3351  int col, /**< column to apply strong branching on */
3352  SCIP_Real psol, /**< current integral primal solution value of column */
3353  int itlim, /**< iteration limit for strong branchings */
3354  SCIP_Real* down, /**< stores dual bound after branching column down */
3355  SCIP_Real* up, /**< stores dual bound after branching column up */
3356  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3357  * otherwise, it can only be used as an estimate value */
3358  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3359  * otherwise, it can only be used as an estimate value */
3360  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3361  )
3362 {
3363  SCIP_RETCODE retcode;
3364 
3365  /* pass call on to lpiStrongbranch() */
3366  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
3367 
3368  /* pass SCIP_LPERROR to SCIP without a back trace */
3369  if( retcode == SCIP_LPERROR )
3370  return SCIP_LPERROR;
3371 
3372  /* evaluate retcode */
3373  SCIP_CALL( retcode );
3374 
3375  return SCIP_OKAY;
3376 }
3377 
3378 /** performs strong branching iterations on given candidates with @b integral values */
3380  SCIP_LPI* lpi, /**< LP interface structure */
3381  int* cols, /**< columns to apply strong branching on */
3382  int ncols, /**< number of columns */
3383  SCIP_Real* psols, /**< current integral primal solution values of columns */
3384  int itlim, /**< iteration limit for strong branchings */
3385  SCIP_Real* down, /**< stores dual bounds after branching columns down */
3386  SCIP_Real* up, /**< stores dual bounds after branching columns up */
3387  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3388  * otherwise, they can only be used as an estimate values */
3389  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3390  * otherwise, they can only be used as an estimate values */
3391  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3392  )
3393 {
3394  SCIP_RETCODE retcode;
3395 
3396  assert( cols != NULL );
3397  assert( psols != NULL );
3398  assert( down != NULL );
3399  assert( up != NULL );
3400  assert( downvalid != NULL );
3401  assert( upvalid != NULL );
3402  assert( down != NULL );
3403 
3404  if ( iter != NULL )
3405  *iter = 0;
3406 
3407  for (int j = 0; j < ncols; ++j)
3408  {
3409  /* pass call on to lpiStrongbranch() */
3410  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3411 
3412  /* pass SCIP_LPERROR to SCIP without a back trace */
3413  if( retcode == SCIP_LPERROR )
3414  return SCIP_LPERROR;
3415 
3416  /* evaluate retcode */
3417  SCIP_CALL( retcode );
3418  }
3419 
3420  return SCIP_OKAY;
3421 }
3422 /**@} */
3423 
3424 
3425 
3426 
3427 /*
3428  * Solution Information Methods
3429  */
3430 
3431 /**@name Solution Information Methods */
3432 /**@{ */
3433 
3434 /** returns whether a solve method was called after the last modification of the LP */
3436  SCIP_LPI* lpi /**< LP interface structure */
3437  )
3439  assert(lpi != NULL);
3440 
3441  return lpi->solved;
3442 }
3443 
3444 /** gets information about primal and dual feasibility of the current LP solution
3445  *
3446  * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
3447  * returns true. If the LP is changed, this information might be invalidated.
3448  *
3449  * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
3450  * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
3451  * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
3452  * the problem might actually be feasible).
3453  */
3455  SCIP_LPI* lpi, /**< LP interface structure */
3456  SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
3457  SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
3458  )
3459 {
3460  SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
3461 
3462  assert(lpi != NULL);
3463  assert(primalfeasible != NULL);
3464  assert(dualfeasible != NULL);
3465 
3466  *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
3467  *dualfeasible = SCIPlpiIsDualFeasible(lpi);
3468 
3469  return SCIP_OKAY;
3470 }
3471 
3472 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
3473  * this does not necessarily mean, that the solver knows and can return the primal ray
3474  */
3476  SCIP_LPI* lpi /**< LP interface structure */
3477  )
3479  SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
3480 
3481  assert(lpi != NULL);
3482  assert(lpi->spx != NULL);
3483 
3484  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3485 }
3486 
3487 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
3488  * and the solver knows and can return the primal ray
3489  */
3491  SCIP_LPI* lpi /**< LP interface structure */
3492  )
3494  SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
3495 
3496  assert(lpi != NULL);
3497  assert(lpi->spx != NULL);
3498 
3499 #if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3500  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3501 #else
3502  return FALSE;
3503 #endif
3504 }
3505 
3506 /** returns TRUE iff LP is proven to be primal unbounded */
3508  SCIP_LPI* lpi /**< LP interface structure */
3509  )
3511  SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
3512 
3513  assert(lpi != NULL);
3514  assert(lpi->spx != NULL);
3515 
3516  assert(lpi->spx->getStatus() != SPxSolver::UNBOUNDED || lpi->spx->basis().status() == SPxBasis::UNBOUNDED);
3517 
3518  /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
3519  * feasible point; hence we have to check the perturbation
3520  */
3521  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED && !lpi->spx->isPerturbed());
3522 }
3523 
3524 /** returns TRUE iff LP is proven to be primal infeasible */
3526  SCIP_LPI* lpi /**< LP interface structure */
3527  )
3529  SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
3530 
3531  assert(lpi != NULL);
3532  assert(lpi->spx != NULL);
3533 
3534  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3535 }
3536 
3537 /** returns TRUE iff LP is proven to be primal feasible */
3539  SCIP_LPI* lpi /**< LP interface structure */
3540  )
3542  SPxBasis::SPxStatus basestatus;
3543 
3544  SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
3545 
3546  assert(lpi != NULL);
3547  assert(lpi->spx != NULL);
3548 
3549  basestatus = lpi->spx->basis().status();
3550 
3551  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3552  * still return true as long as perturbation plus violation is within tolerances
3553  */
3554  assert(basestatus == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3555 
3556  return basestatus == SPxBasis::OPTIMAL ||
3557  ((basestatus == SPxBasis::PRIMAL || basestatus == SPxBasis::UNBOUNDED) && !lpi->spx->isPerturbed());
3558 }
3559 
3560 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3561  * this does not necessarily mean, that the solver knows and can return the dual ray
3562  */
3564  SCIP_LPI* lpi /**< LP interface structure */
3565  )
3567  SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
3568 
3569  assert(lpi != NULL);
3570  assert(lpi->spx != NULL);
3571 
3572  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3573 }
3574 
3575 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3576  * and the solver knows and can return the dual ray
3577  */
3579  SCIP_LPI* lpi /**< LP interface structure */
3580  )
3582  SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
3583 
3584  assert(lpi != NULL);
3585  assert(lpi->spx != NULL);
3586 
3587  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3588 }
3589 
3590 /** returns TRUE iff LP is dual unbounded */
3592  SCIP_LPI* lpi /**< LP interface structure */
3593  )
3595  SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
3596 
3597  assert(lpi != NULL);
3598  assert(lpi->spx != NULL);
3599 
3600  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE && lpi->spx->basis().status() == SPxBasis::DUAL
3601  && !lpi->spx->isPerturbed());
3602 }
3603 
3604 /** returns TRUE iff LP is dual infeasible */
3606  SCIP_LPI* lpi /**< LP interface structure */
3607  )
3609  SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
3610 
3611  assert(lpi != NULL);
3612  assert(lpi->spx != NULL);
3613 
3614  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3615 }
3616 
3617 /** returns TRUE iff LP is proven to be dual feasible */
3619  SCIP_LPI* lpi /**< LP interface structure */
3620  )
3622  SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
3623 
3624  assert(lpi != NULL);
3625  assert(lpi->spx != NULL);
3626 
3627  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3628  * still return true as long as perturbation plus violation is within tolerances
3629  */
3630  assert(lpi->spx->basis().status() == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3631 
3632  return (lpi->spx->basis().status() == SPxBasis::OPTIMAL) ||
3633  (lpi->spx->basis().status() == SPxBasis::DUAL && !lpi->spx->isPerturbed());
3634 }
3635 
3636 /** returns TRUE iff LP was solved to optimality */
3638  SCIP_LPI* lpi /**< LP interface structure */
3639  )
3641  SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
3642 
3643  assert(lpi != NULL);
3644  assert(lpi->spx != NULL);
3645  assert((lpi->spx->basis().status() == SPxBasis::OPTIMAL)
3647 
3648  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3649  * still return true as long as perturbation plus violation is within tolerances
3650  */
3651  return (lpi->spx->basis().status() == SPxBasis::OPTIMAL);
3652 }
3653 
3654 /** returns TRUE iff current LP solution is stable
3655  *
3656  * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3657  * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3658  * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3659  * SCIPlpiIsStable() should return false.
3660  */
3662  SCIP_LPI* lpi /**< LP interface structure */
3663  )
3665  SCIPdebugMessage("calling SCIPlpiIsStable()\n");
3666 
3667  assert(lpi != NULL);
3668  assert(lpi->spx != NULL);
3669 
3670 #if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3671  /* If the condition number of the basis should be checked, everything above the specified threshold is counted
3672  * as instable.
3673  */
3674  if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
3675  {
3676 #ifndef NDEBUG
3677  SCIP_RETCODE retcode;
3678 #endif
3679  SCIP_Real kappa;
3680 
3681 #ifndef NDEBUG
3682  retcode =
3683 #endif
3685  assert(kappa != SCIP_INVALID); /*lint !e777*/
3686  assert(retcode == SCIP_OKAY);
3687 
3688  if( kappa > lpi->conditionlimit )
3689  return FALSE;
3690  }
3691 #endif
3692 
3693  return (lpi->spx->getStatus() != SPxSolver::ERROR && lpi->spx->getStatus() != SPxSolver::SINGULAR);
3694 }
3695 
3696 /** returns TRUE iff the objective limit was reached */
3698  SCIP_LPI* lpi /**< LP interface structure */
3699  )
3701  SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3702 
3703  assert(lpi != NULL);
3704  assert(lpi->spx != NULL);
3705 
3706  return (lpi->spx->getStatus() == SPxSolver::ABORT_VALUE);
3707 }
3708 
3709 /** returns TRUE iff the iteration limit was reached */
3711  SCIP_LPI* lpi /**< LP interface structure */
3712  )
3714  SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3715 
3716  assert(lpi != NULL);
3717  assert(lpi->spx != NULL);
3718 
3719  return (lpi->spx->getStatus() == SPxSolver::ABORT_ITER);
3720 }
3721 
3722 /** returns TRUE iff the time limit was reached */
3724  SCIP_LPI* lpi /**< LP interface structure */
3725  )
3727  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3728 
3729  assert(lpi != NULL);
3730  assert(lpi->spx != NULL);
3731 
3732  return (lpi->spx->getStatus() == SPxSolver::ABORT_TIME);
3733 }
3734 
3735 /** returns the internal solution status of the solver */
3737  SCIP_LPI* lpi /**< LP interface structure */
3738  )
3740  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3741 
3742  assert(lpi != NULL);
3743  assert(lpi->spx != NULL);
3744 
3745  return static_cast<int>(lpi->spx->getStatus());
3746 }
3747 
3748 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3750  SCIP_LPI* lpi, /**< LP interface structure */
3751  SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3752  )
3753 { /*lint --e{715}*/
3754  SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3755 
3756  assert(lpi != NULL);
3757  assert(lpi->spx != NULL);
3758  assert(success != NULL);
3759 
3760  /* instable situations cannot be ignored */
3761  *success = FALSE;
3762 
3763  return SCIP_OKAY;
3764 }
3765 
3766 /** gets objective value of solution */
3768  SCIP_LPI* lpi, /**< LP interface structure */
3769  SCIP_Real* objval /**< stores the objective value */
3770  )
3771 {
3772  SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3773 
3774  assert(lpi != NULL);
3775  assert(lpi->spx != NULL);
3776  assert(objval != NULL);
3777 
3778  *objval = lpi->spx->value();
3779 
3780  return SCIP_OKAY;
3781 }
3782 
3783 /** gets primal and dual solution vectors for feasible LPs
3784  *
3785  * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3786  * SCIPlpiIsOptimal() returns true.
3787  */
3789  SCIP_LPI* lpi, /**< LP interface structure */
3790  SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3791  SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3792  SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3793  SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3794  SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3795  )
3796 {
3797  SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3798 
3799  assert(lpi != NULL);
3800  assert(lpi->spx != NULL);
3801 
3802  if( objval != NULL )
3803  *objval = lpi->spx->value();
3804 
3805  try
3806  {
3807  if( primsol != NULL )
3808  {
3809  Vector tmp(lpi->spx->nCols(), primsol);
3810  (void)lpi->spx->getPrimal(tmp);
3811  }
3812  if( dualsol != NULL )
3813  {
3814  Vector tmp(lpi->spx->nRows(), dualsol);
3815  (void)lpi->spx->getDual(tmp);
3816  }
3817  if( activity != NULL )
3818  {
3819  Vector tmp(lpi->spx->nRows(), activity);
3820  (void)lpi->spx->getSlacks(tmp); /* in SoPlex, the activities are called "slacks" */
3821  }
3822  if( redcost != NULL )
3823  {
3824  Vector tmp(lpi->spx->nCols(), redcost);
3825  (void)lpi->spx->getRedCost(tmp);
3826  }
3827  }
3828 #ifndef NDEBUG
3829  catch( const SPxException& x )
3830  {
3831  std::string s = x.what();
3832  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3833 #else
3834  catch( const SPxException& )
3835  {
3836 #endif
3837  return SCIP_LPERROR;
3838  }
3839 
3840  return SCIP_OKAY;
3841 }
3842 
3843 /** gets primal ray for unbounded LPs */
3845  SCIP_LPI* lpi, /**< LP interface structure */
3846  SCIP_Real* ray /**< primal ray */
3847  )
3848 { /*lint --e{715}*/
3849  SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3850 
3851  assert(lpi != NULL);
3852  assert(lpi->spx != NULL);
3853  assert(ray != NULL);
3854 
3855 #if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3856  try
3857  {
3858  Vector tmp(lpi->spx->nCols(), ray);
3859  (void)lpi->spx->getPrimalray(tmp);
3860  }
3861 #ifndef NDEBUG
3862  catch( const SPxException& x )
3863  {
3864  std::string s = x.what();
3865  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3866 #else
3867  catch( const SPxException& )
3868  {
3869 #endif
3870  return SCIP_LPERROR;
3871  }
3872 
3873  return SCIP_OKAY;
3874 #else
3875  SCIPerrorMessage("SCIPlpiGetPrimalRay() not supported by SoPlex versions <= 1.5.0\n");
3876  return SCIP_LPERROR;
3877 #endif
3878 }
3879 
3880 /** gets dual farkas proof for infeasibility */
3882  SCIP_LPI* lpi, /**< LP interface structure */
3883  SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3884  )
3885 {
3886  SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3887 
3888  assert(lpi != NULL);
3889  assert(lpi->spx != NULL);
3890  assert(dualfarkas != NULL);
3891 
3892  try
3893  {
3894  Vector tmp(lpi->spx->nRows(), dualfarkas);
3895  (void)lpi->spx->getDualfarkas(tmp);
3896  }
3897 #ifndef NDEBUG
3898  catch( const SPxException& x )
3899  {
3900  std::string s = x.what();
3901  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3902 #else
3903  catch( const SPxException& )
3904  {
3905 #endif
3906  return SCIP_LPERROR;
3907  }
3908 
3909  return SCIP_OKAY;
3910 }
3911 
3912 /** gets the number of LP iterations of the last solve call */
3914  SCIP_LPI* lpi, /**< LP interface structure */
3915  int* iterations /**< pointer to store the number of iterations of the last solve call */
3916  )
3917 {
3918  SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3919 
3920  assert(lpi != NULL);
3921  assert(lpi->spx != NULL);
3922  assert(iterations != NULL);
3923 
3924  *iterations = lpi->spx->iterations();
3925 
3926  return SCIP_OKAY;
3927 }
3928 
3929 /** gets information about the quality of an LP solution
3930  *
3931  * Such information is usually only available, if also a (maybe not optimal) solution is available.
3932  * The LPI should return SCIP_INVALID for @p quality, if the requested quality is not available.
3933  */
3935  SCIP_LPI* lpi, /**< LP interface structure */
3936  SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3937  SCIP_Real* quality /**< pointer to store quality number */
3938  )
3939 {
3940  SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3941 
3942  assert(lpi != NULL);
3943  assert(quality != NULL);
3944 
3945 #if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3946  int maxiter;
3947  Real tolerance;
3948 
3949  SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3950 
3951  switch( qualityindicator )
3952  {
3954  maxiter = 20;
3955  tolerance = 1e-6;
3956  break;
3957 
3959  maxiter = 10000;
3960  tolerance = 1e-9;
3961  break;
3962 
3963  default:
3964  SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3965  return SCIP_INVALIDDATA;
3966  }
3967 
3968  *quality = lpi->spx->basis().condition(maxiter, tolerance);
3969 #else
3970  *quality = SCIP_INVALID;
3971 #endif
3972  return SCIP_OKAY;
3973 }
3974 
3975 /**@} */
3976 
3977 
3978 
3979 
3980 /*
3981  * LP Basis Methods
3982  */
3983 
3984 /**@name LP Basis Methods */
3985 /**@{ */
3986 
3987 /** Return reduced cost of column @c col if this is readily available, otherwise return 0.0 */
3988 static
3989 SCIP_RETCODE getRedCostEst(SPxSCIP* spx, int col, SCIP_Real* val)
3990 {
3991  assert( spx != NULL );
3992  assert( val != NULL );
3993 
3994  *val = 0.0;
3995 
3996  /* Return if the vectors are not set up. The vectors are not set up if for instance we preformed
3997  * strong branching before. */
3998  if (! spx->isInitialized() )
3999  return SCIP_OKAY;
4000 
4001  assert( 0 <= col && col < spx->nCols() );
4002 
4003  if( spx->rep() == SPxSolver::COLUMN )
4004  {
4005  /* in column case the reduced costs are available: */
4006  if (spx->getSense() == SPxLP::MINIMIZE)
4007  *val = spx->pVec()[col] - spx->maxObj()[col];
4008  else
4009  *val = spx->maxObj()[col] - spx->pVec()[col];
4010  }
4011  else
4012  {
4013  assert( spx->rep() == SPxSolver::ROW );
4014 
4015  /* In row case for computing the reduced costs one needs to pass through the basis. We skip this expensive part. */
4016 #ifdef SCIP_DISABLED_CODE
4017  /* Here is the code necessary to compute the reduced costs for row representation: */
4018  SCIP_Real sign = 1.0;
4019  if ( spx->getSense() == SPxLP::MINIMIZE )
4020  sign = -1.0;
4021 
4022  if ( spx->isColBasic(col) )
4023  {
4024  /* It seems necessary to search through the basis in order to find the correct position */
4025  for (int i = spx->dim() - 1; i >= 0; --i)
4026  {
4027  SPxId id = spx->basis().baseId(i);
4028  if ( id.isSPxColId() && col == spx->number(SPxColId(id)) )
4029  {
4030  *val = sign * spx->fVec()[i];
4031  break;
4032  }
4033  }
4034  }
4035 #endif
4036  }
4037 
4038  return SCIP_OKAY;
4039 }
4040 
4041 
4042 
4043 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
4045  SCIP_LPI* lpi, /**< LP interface structure */
4046  int* cstat, /**< array to store column basis status, or NULL */
4047  int* rstat /**< array to store row basis status, or NULL */
4048  )
4049 {
4050  int i;
4051 
4052  SCIPdebugMessage("calling SCIPlpiGetBase()\n");
4053 
4054  assert(lpi != NULL);
4055  assert(lpi->spx != NULL);
4056 
4057  assert( lpi->spx->preStrongbranchingBasisFreed() );
4058 
4059  if( rstat != NULL )
4060  {
4061  for( i = 0; i < lpi->spx->nRows(); ++i )
4062  {
4063  switch( lpi->spx->getBasisRowStatus(i) )
4064  {
4065  case SPxSolver::BASIC:
4066  rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4067  break;
4068  case SPxSolver::FIXED:
4069  case SPxSolver::ON_LOWER:
4070  rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4071  break;
4072  case SPxSolver::ON_UPPER:
4073  rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4074  break;
4075  case SPxSolver::ZERO:
4076  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4077  return SCIP_LPERROR;
4078  case SPxSolver::UNDEFINED:
4079  default:
4080  SCIPerrorMessage("invalid basis status\n");
4081  SCIPABORT();
4082  return SCIP_INVALIDDATA; /*lint !e527*/
4083  }
4084  }
4085  }
4086 
4087  if( cstat != NULL )
4088  {
4089  for( i = 0; i < lpi->spx->nCols(); ++i )
4090  {
4091  SCIP_Real val = 0.0;
4092  switch( lpi->spx->getBasisColStatus(i) )
4093  {
4094  case SPxSolver::BASIC:
4095  cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4096  break;
4097  case SPxSolver::FIXED:
4098  /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
4099  * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
4100  * this case there is no problem at all. If the basis is saved and/or used in some other
4101  * solver, it usually is very cheap to perform the pivots necessary to get an optimal
4102  * basis. */
4103  SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
4104  if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
4105  cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4106  else
4107  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4108  break;
4109  case SPxSolver::ON_LOWER:
4110  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4111  break;
4112  case SPxSolver::ON_UPPER:
4113  cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4114  break;
4115  case SPxSolver::ZERO:
4116  cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
4117  break;
4118  case SPxSolver::UNDEFINED:
4119  default:
4120  SCIPerrorMessage("invalid basis status\n");
4121  SCIPABORT();
4122  return SCIP_INVALIDDATA; /*lint !e527*/
4123  }
4124  }
4125  }
4126 
4127  return SCIP_OKAY;
4128 }
4129 
4130 /** sets current basis status for columns and rows */
4132  SCIP_LPI* lpi, /**< LP interface structure */
4133  const int* cstat, /**< array with column basis status */
4134  const int* rstat /**< array with row basis status */
4135  )
4136 {
4137  int i;
4138  int ncols;
4139  int nrows;
4140 
4141  SCIPdebugMessage("calling SCIPlpiSetBase()\n");
4142 
4143  assert(lpi != NULL);
4144  assert(lpi->spx != NULL);
4145 
4146  SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
4147  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
4148 
4149  assert(cstat != NULL || ncols == 0);
4150  assert(rstat != NULL || nrows == 0);
4151 
4152  assert( lpi->spx->preStrongbranchingBasisFreed() );
4153  invalidateSolution(lpi);
4154 
4155  DataArray<SPxSolver::VarStatus>& m_colstat = lpi->spx->colStat();
4156  DataArray<SPxSolver::VarStatus>& m_rowstat = lpi->spx->rowStat();
4157 
4158  m_colstat.reSize(ncols);
4159  m_rowstat.reSize(nrows);
4160 
4161  for( i = 0; i < nrows; ++i )
4162  {
4163  assert( rstat != 0 ); /* for lint */
4164  switch( rstat[i] )
4165  {
4166  case SCIP_BASESTAT_LOWER:
4167  m_rowstat[i] = SPxSolver::ON_LOWER;
4168  break;
4169  case SCIP_BASESTAT_BASIC:
4170  m_rowstat[i] = SPxSolver::BASIC;
4171  break;
4172  case SCIP_BASESTAT_UPPER:
4173  m_rowstat[i] = SPxSolver::ON_UPPER;
4174  break;
4175  case SCIP_BASESTAT_ZERO:
4176  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4177  return SCIP_LPERROR; /*lint !e429*/
4178  default:
4179  SCIPerrorMessage("invalid basis status\n");
4180  SCIPABORT();
4181  return SCIP_INVALIDDATA; /*lint !e527*/
4182  }
4183  }
4184 
4185  for( i = 0; i < ncols; ++i )
4186  {
4187  assert( cstat != 0 ); /* for lint */
4188  switch( cstat[i] )
4189  {
4190  case SCIP_BASESTAT_LOWER:
4191  m_colstat[i] = SPxSolver::ON_LOWER;
4192  break;
4193  case SCIP_BASESTAT_BASIC:
4194  m_colstat[i] = SPxSolver::BASIC;
4195  break;
4196  case SCIP_BASESTAT_UPPER:
4197  m_colstat[i] = SPxSolver::ON_UPPER;
4198  break;
4199  case SCIP_BASESTAT_ZERO:
4200  m_colstat[i] = SPxSolver::ZERO;
4201  break;
4202  default:
4203  SCIPerrorMessage("invalid basis status\n");
4204  SCIPABORT();
4205  return SCIP_INVALIDDATA; /*lint !e527*/
4206  }
4207  }
4208 
4209  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(m_rowstat.get_const_ptr(), m_colstat.get_const_ptr()) );
4210  (void) lpi->spx->updateStatus();
4211 
4212  lpi->spx->freePreStrongbranchingBasis();
4213 
4214  return SCIP_OKAY;
4215 }
4216 
4217 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
4219  SCIP_LPI* lpi, /**< LP interface structure */
4220  int* bind /**< pointer to store basis indices ready to keep number of rows entries */
4221  )
4222 {
4223  SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
4224 
4225  SPxSolver* spx;
4226 
4227  assert(lpi != NULL);
4228  assert(lpi->spx != NULL);
4229  assert(bind != NULL);
4230 
4231  assert( lpi->spx->preStrongbranchingBasisFreed() );
4232 
4233  /* the LPi defines the basis as column basis, i.e., as the set of (indices of) non-fixed columns and rows; if SoPlex
4234  * uses row representation, this is just the complement of the basis
4235  */
4236  spx = lpi->spx;
4237 
4238  /* for column representation, return the basis */
4239  if( spx->rep() == SPxSolver::COLUMN )
4240  {
4241  for( int i = 0; i < spx->nRows(); ++i )
4242  {
4243  SPxId id = spx->basis().baseId(i);
4244 
4245  bind[i] = (id.isSPxColId() ? spx->number(id) : - 1 - spx->number(id));
4246  }
4247  }
4248  /* for row representation, return the complement of the basis; for this, we need to loop through all rows and columns */
4249  else
4250  {
4251  int k = 0;
4252  int nrows = spx->nRows();
4253  int ncols = spx->nCols();
4254 
4255  assert( spx->rep() == SPxSolver::ROW );
4256 
4257  for( int i = 0; i < nrows; ++i )
4258  {
4259  if( !spx->isRowBasic(i) )
4260  {
4261  bind[k++] = -1 - i;
4262  if( k >= nrows )
4263  break;
4264  }
4265  }
4266 
4267  for( int j = 0; j < ncols && k < nrows; ++j )
4268  {
4269  if( !spx->isColBasic(j) )
4270  bind[k++] = j;
4271  }
4272 
4273  assert(k == nrows);
4274  }
4275 
4276  return SCIP_OKAY;
4277 }
4278 
4279 #ifdef OLD_BINV
4280 /* prepare a factorization of the basis matrix in column representation */
4281 static
4282 SCIP_RETCODE prepareFactorization(
4283  SCIP_LPI* lpi
4284  )
4285 {
4286  SCIPdebugMessage("Preparing factorization for computation of basis inverse.\n");
4287 
4288  try
4289  {
4290  /* if the factorization has not been set up, we compute a new factorization */
4291  if ( lpi->factorization == 0 )
4292  {
4293  SPxSolver* spx = lpi->spx;
4294 
4295  /* matrix to store columns */
4296  DataArray <const SVector*> matrix(spx->nRows());
4297 
4298  int k = 0;
4299  for (int i = 0; i < spx->nRows(); ++i)
4300  {
4301  if ( ! spx->isRowBasic(i) )
4302  matrix[k++] = new UnitVector(i);
4303  }
4304  for (int j = 0; j < spx->nCols(); ++j)
4305  {
4306  if ( ! spx->isColBasic(j) )
4307  matrix[k++] = &spx->colVector(j);
4308  }
4309  assert( k == spx->nRows() );
4310  assert( k == matrix.size() );
4311 
4312  /* compute factorization */
4313  lpi->factorization = new SLUFactor;
4314 #ifndef NDEBUG
4315  SLinSolver::Status status = lpi->factorization->load(matrix.get_ptr(), k);
4316 #else
4317  (void) lpi->factorization->load(matrix.get_ptr(), k);
4318 #endif
4319  assert( status == SLinSolver::OK );
4320  assert( k == lpi->factorization->dim() );
4321 
4322  /* delete matrix columns corresponding to unit vectors */
4323  k = 0;
4324  for (int i = 0; i < spx->nRows(); ++i)
4325  {
4326  if ( ! spx->isRowBasic(i) )
4327  delete matrix[k++];
4328  }
4329  }
4330  }
4331 #ifndef NDEBUG
4332  catch( const SPxException& x )
4333  {
4334  std::string s = x.what();
4335  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4336 #else
4337  catch( const SPxException& )
4338  {
4339 #endif
4340  return SCIP_LPERROR;
4341  }
4342 
4343  return SCIP_OKAY;
4344 }
4345 #endif
4346 
4347 /** get row of inverse basis matrix B^-1
4348  *
4349  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4350  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4351  * see also the explanation in lpi.h.
4352  */
4354  SCIP_LPI* lpi, /**< LP interface structure */
4355  int r, /**< row number */
4356  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
4357  int* inds, /**< array to store the non-zero indices, or NULL */
4358  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4359  * (-1: if we do not store sparsity information) */
4360  )
4361 {
4362  SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
4363 
4364  assert( lpi != NULL );
4365  assert( lpi->spx != NULL );
4366  assert( lpi->spx->preStrongbranchingBasisFreed() );
4367  assert(coef != NULL);
4368 
4369  int nCols = lpi->spx->nCols();
4370  int nRows = lpi->spx->nRows();
4371 
4372  assert(r >= 0);
4373  assert(r < nRows);
4374 
4375  try
4376  {
4377  SPxSolver* spx = lpi->spx;
4378 
4379  /* in the column case use the existing factorization */
4380  if ( spx->rep() == SPxSolver::COLUMN )
4381  {
4382  SSVector x(nRows);
4383  spx->basis().coSolve(x, spx->unitVector(r));
4384 
4385  /* copy sparse data to dense result vector based on coef array */
4386  if( ninds != NULL && inds != NULL )
4387  {
4388  int idx;
4389  /* during solving SoPlex may have destroyed the sparsity structure so we need to restore it */
4390  x.setup();
4391  *ninds = x.size();
4392  for( int i = 0; i < *ninds; ++i )
4393  {
4394  idx = x.index(i);
4395  coef[idx] = x[idx];
4396  /* set sparsity pattern of coef array */
4397  inds[i] = idx;
4398  }
4399  }
4400  else
4401  {
4402  /* @todo check whether we only need to copy nonzeros to coef - is coef cleared? */
4403  Vector y(nRows, coef);
4404  y = x;
4405  if( ninds != NULL )
4406  *ninds = -1;
4407  }
4408  }
4409  else
4410  {
4411  assert(spx->rep() == SPxSolver::ROW);
4412 
4413 #ifdef OLD_BINV
4414  DVector e(nRows);
4415 
4416  /* prepare unit vector */
4417  e.clear();
4418  e[r] = 1.0;
4419 
4420  /* factorization is deleted in invalidateSolution() */
4421  SCIP_CALL( prepareFactorization(lpi) );
4422  assert( lpi->factorization != 0 );
4423  assert( lpi->factorization->dim() == nRows );
4424 
4425  /* solve system "x = e_r^T * B^-1" to get r'th row of B^-1 */
4426  lpi->factorization->solveLeft(x, e);
4427 #else
4428  Vector x(nRows, coef); /* row of B^-1 has nrows entries - note that x is based on coef */
4429  /**@todo should rhs be a reference? */
4430  DSVector rhs(nCols);
4431  SSVector y(nCols);
4432  int* bind;
4433  int idx;
4434 
4435  bind = NULL;
4436 
4437  /**@todo should bind be stored globally in lpi? */
4438  /* get ordering of column basis matrix */
4439  SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4440  SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4441 
4442  /* get vector corresponding to requested index r */
4443  idx = bind[r];
4444 
4445  /* r corresponds to a row vector */
4446  if( idx < 0 )
4447  {
4448  idx = -idx-1;
4449 
4450  /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4451  assert(idx >= 0);
4452  assert(idx < nRows);
4453  assert(!spx->isRowBasic(idx));
4454 
4455  /* get row vector */
4456  rhs = spx->rowVector(idx);
4457  rhs *= -1.0;
4458  }
4459  /* r corresponds to a column vector */
4460  else
4461  {
4462  /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4463  assert(idx < nCols);
4464  assert(!spx->isColBasic(idx));
4465 
4466  /* get unit vector */
4467  rhs = spx->unitVector(idx);
4468  }
4469 
4470  /* solve system "y B = rhs", where B is the row basis matrix */
4471  spx->basis().solve(y, rhs);
4472 
4473  /* initialize result vector x as zero */
4474  BMSclearMemoryArray(coef, nRows);
4475 
4476  /* add nonzero entries */
4477  for( int i = 0; i < nCols; ++i )
4478  {
4479  SPxId id = spx->basis().baseId(i);
4480 
4481  if( id.isSPxRowId() )
4482  {
4483  assert(spx->number(id) >= 0);
4484  assert(spx->number(id) < nRows);
4485  assert(bind[r] >= 0 || spx->number(id) != idx);
4486 
4487  x[spx->number(id)] = y[i];
4488  }
4489  }
4490 
4491  /* if r corresponds to a row vector, we have to add a 1 at position r */
4492  if( bind[r] < 0 )
4493  {
4494  assert(x[idx] == 0.0);
4495  x[idx] = 1.0;
4496  }
4497 
4498  /* @todo implement returning of sparsity information like in column wise case */
4499  if( ninds != NULL )
4500  *ninds = -1;
4501 
4502  /* free memory */
4503  BMSfreeMemoryArray(&bind);
4504 #endif
4505  }
4506  }
4507 #ifndef NDEBUG
4508  catch( const SPxException& x )
4509  {
4510  std::string s = x.what();
4511  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4512 #else
4513  catch( const SPxException& )
4514  {
4515 #endif
4516  return SCIP_LPERROR;
4517  }
4518 
4519  return SCIP_OKAY;
4520 }
4521 
4522 /** get solution of basis matrix B * coef = rhs */
4523 static
4525  SCIP_LPI* lpi, /**< LP interface structure */
4526  SCIP_Real* rhs, /**< right-hand side vector */
4527  SCIP_Real* coef /**< vector to return coefficients */
4528  )
4529 {
4530  SCIPdebugMessage("calling SCIPlpiGetBInvVec()\n");
4531 
4532  assert(lpi != NULL);
4533  assert(lpi->spx != NULL);
4534  assert(lpi->spx->preStrongbranchingBasisFreed());
4535  assert(rhs != NULL);
4536  assert(coef != NULL);
4537 
4538  int nCols = lpi->spx->nCols();
4539  int nRows = lpi->spx->nRows();
4540 
4541  try
4542  {
4543  SPxSolver* spx = lpi->spx;
4544  Vector v(nRows, rhs);
4545  Vector x(nRows, coef);
4546 
4547  /* in the column case use the existing factorization */
4548  if( spx->rep() == SPxSolver::COLUMN )
4549  {
4550  /* solve system "x = B^-1 * A_c" to get c'th column of B^-1 * A */
4551  spx->basis().solve(x, v);
4552  }
4553  else
4554  {
4555  assert(spx->rep() == SPxSolver::ROW);
4556 
4557 #ifdef OLD_BINV
4558  /* factorization is deleted in invalidateSolution() */
4559  SCIP_CALL( prepareFactorization(lpi) );
4560  assert(lpi->factorization != 0);
4561  assert(lpi->factorization->dim() == spx->nRows());
4562 
4563  /* solve system B * x = v */
4564  lpi->factorization->solveRight(x, v);
4565 #else
4566  DSVector rowrhs(nCols);
4567  SSVector y(nCols);
4568  int* bind;
4569 
4570  bind = NULL;
4571 
4572  /**@todo should bind be stored globally in lpi? */
4573  /* get ordering of column basis matrix */
4574  SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4575  SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4576 
4577  /* fill right-hand side for row-based system */
4578  for( int i = 0; i < nCols; ++i )
4579  {
4580  SPxId id = spx->basis().baseId(i);
4581 
4582  if( id.isSPxRowId() )
4583  {
4584  assert(spx->number(id) >= 0);
4585  assert(spx->number(id) < nRows);
4586 
4587  rowrhs.add(i, v[spx->number(id)]);
4588  }
4589  else
4590  {
4591  assert(rowrhs[i] == 0.0);
4592  }
4593  }
4594 
4595  /* solve system "B y = rowrhs", where B is the row basis matrix */
4596  spx->basis().coSolve(y, rowrhs);
4597 
4598  /* fill result w.r.t. order given by bind */
4599  for( int i = 0; i < nRows; ++i )
4600  {
4601  int idx;
4602 
4603  idx = bind[i];
4604 
4605  if( idx < 0 )
4606  {
4607  idx = -idx-1;
4608 
4609  /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4610  assert(idx >= 0);
4611  assert(idx < nRows);
4612  assert(!spx->isRowBasic(idx));
4613 
4614  x[i] = v[idx] - (spx->rowVector(idx) * Vector(nCols, y.get_ptr())); /*lint !e1702*/
4615  }
4616  else
4617  {
4618  /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4619  assert(idx >= 0);
4620  assert(idx < nCols);
4621  assert(!spx->isColBasic(idx));
4622 
4623  x[i] = y[idx];
4624  }
4625  }
4626 
4627  /* free memory */
4628  BMSfreeMemoryArray(&bind);
4629 #endif
4630  }
4631  }
4632 #ifndef NDEBUG
4633  catch( const SPxException& x )
4634  {
4635  std::string s = x.what();
4636  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4637 #else
4638  catch( const SPxException& )
4639  {
4640 #endif
4641  return SCIP_LPERROR;
4642  }
4643 
4644  return SCIP_OKAY;
4645 }
4646 
4647 /** get column of inverse basis matrix B^-1
4648  *
4649  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4650  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4651  * see also the explanation in lpi.h.
4652  */
4654  SCIP_LPI* lpi, /**< LP interface structure */
4655  int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
4656  * you have to call SCIPlpiGetBasisInd() to get the array which links the
4657  * B^-1 column numbers to the row and column numbers of the LP!
4658  * c must be between 0 and nrows-1, since the basis has the size
4659  * nrows * nrows */
4660  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
4661  int* inds, /**< array to store the non-zero indices, or NULL */
4662  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4663  * (-1: if we do not store sparsity information) */
4664  )
4665 { /*lint --e{715}*/
4666  SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
4667 
4668  assert( lpi != NULL );
4669  assert( lpi->spx != NULL );
4670  assert( lpi->spx->preStrongbranchingBasisFreed() );
4671  assert(coef != NULL);
4672 
4673  /* mark sparsity pattern as invalid */
4674  if( ninds != NULL )
4675  *ninds = -1;
4676 
4677  /* prepare unit vector */
4678  DVector e(lpi->spx->nRows());
4679 
4680  e.clear();
4681 
4682  assert(c >= 0);
4683  assert(c < lpi->spx->nRows());
4684  e[c] = 1.0;
4685 
4686  /* solve */
4687  SCIP_CALL( lpiGetBInvVec(lpi, e.get_ptr(), coef) );
4688 
4689  return SCIP_OKAY;
4690 }
4691 
4692 /** get row of inverse basis matrix times constraint matrix B^-1 * A
4693  *
4694  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4695  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4696  * see also the explanation in lpi.h.
4697  */
4699  SCIP_LPI* lpi, /**< LP interface structure */
4700  int r, /**< row number */
4701  const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
4702  SCIP_Real* coef, /**< vector to return coefficients of the row */
4703  int* inds, /**< array to store the non-zero indices, or NULL */
4704  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4705  * (-1: if we do not store sparsity information) */
4706  )
4707 {
4708  SCIP_Real* buf;
4709  SCIP_Real* binv;
4710  int nrows;
4711  int ncols;
4712  int c;
4713 
4714  SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
4715 
4716  assert(lpi != NULL);
4717  assert(lpi->spx != NULL);
4718  assert( lpi->spx->preStrongbranchingBasisFreed() );
4719  assert(coef != NULL);
4720 
4721  nrows = lpi->spx->nRows();
4722  ncols = lpi->spx->nCols();
4723  buf = NULL;
4724 
4725  /* get (or calculate) the row in B^-1 */
4726  if( binvrow == NULL )
4727  {
4728  SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
4729  SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
4730  binv = buf;
4731  }
4732  else
4733  binv = const_cast<SCIP_Real*>(binvrow);
4734 
4735  assert(binv != NULL);
4736 
4737  /* mark sparsity pattern as invalid */
4738  if( ninds != NULL )
4739  *ninds = -1;
4740 
4741  /* calculate the scalar product of the row in B^-1 and A */
4742  soplex::Vector binvvec(nrows, binv);
4743  for( c = 0; c < ncols; ++c )
4744  coef[c] = binvvec * lpi->spx->colVector(c); /* scalar product */ /*lint !e1702*/
4745 
4746  /* free memory if it was temporarily allocated */
4747  BMSfreeMemoryArrayNull(&buf);
4748 
4749  return SCIP_OKAY;
4750 }
4751 
4752 /** get column of inverse basis matrix times constraint matrix B^-1 * A
4753  *
4754  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4755  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4756  * see also the explanation in lpi.h.
4757  */
4759  SCIP_LPI* lpi, /**< LP interface structure */
4760  int c, /**< column number */
4761  SCIP_Real* coef, /**< vector to return coefficients of the column */
4762  int* inds, /**< array to store the non-zero indices, or NULL */
4763  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4764  * (-1: if we do not store sparsity information) */
4765  )
4766 { /*lint --e{715}*/
4767  DVector col(lpi->spx->nRows());
4768 
4769  SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
4770 
4771  assert( lpi != NULL );
4772  assert( lpi->spx != NULL );
4773  assert( lpi->spx->preStrongbranchingBasisFreed() );
4774  assert(coef != NULL);
4775 
4776  /* extract column c of A */
4777  assert(c >= 0);
4778  assert(c < lpi->spx->nCols());
4779 
4780  /* mark sparsity pattern as invalid */
4781  if( ninds != NULL )
4782  *ninds = -1;
4783 
4784  col.clear();
4785  col = lpi->spx->colVector(c);
4786  col.reDim(lpi->spx->nRows());
4787 
4788  /* solve */
4789  SCIP_CALL( lpiGetBInvVec(lpi, col.get_ptr(), coef) );
4790 
4791  return SCIP_OKAY;
4792 }
4793 
4794 /**@} */
4795 
4796 
4797 
4798 
4799 /*
4800  * LP State Methods
4801  */
4802 
4803 /**@name LP State Methods */
4804 /**@{ */
4805 
4806 /** stores LPi state (like basis information) into lpistate object */
4808  SCIP_LPI* lpi, /**< LP interface structure */
4809  BMS_BLKMEM* blkmem, /**< block memory */
4810  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4811  )
4812 {
4813  int ncols;
4814  int nrows;
4815 
4816  SCIPdebugMessage("calling SCIPlpiGetState()\n");
4817 
4818  assert(blkmem != NULL);
4819  assert(lpi != NULL);
4820  assert(lpi->spx != NULL);
4821  assert(lpistate != NULL);
4822 
4823  assert( lpi->spx->preStrongbranchingBasisFreed() );
4824 
4825  ncols = lpi->spx->nCols();
4826  nrows = lpi->spx->nRows();
4827  assert(ncols >= 0);
4828  assert(nrows >= 0);
4829 
4830  /* allocate lpistate data */
4831  SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
4832 
4833  /* allocate enough memory for storing uncompressed basis information */
4834  SCIP_CALL( ensureCstatMem(lpi, ncols) );
4835  SCIP_CALL( ensureRstatMem(lpi, nrows) );
4836 
4837  /* get unpacked basis information */
4838  SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
4839 
4840  /* pack LPi state data */
4841  (*lpistate)->ncols = ncols;
4842  (*lpistate)->nrows = nrows;
4843  lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
4844 
4845  return SCIP_OKAY;
4846 }
4847 
4848 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
4849  * columns and rows since the state was stored with SCIPlpiGetState()
4850  */
4852  SCIP_LPI* lpi, /**< LP interface structure */
4853  BMS_BLKMEM* /*blkmem*/, /**< block memory */
4854  const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
4855  )
4856 {
4857  int lpncols;
4858  int lpnrows;
4859  int i;
4860 
4861  SCIPdebugMessage("calling SCIPlpiSetState()\n");
4862 
4863  assert(lpi != NULL);
4864  assert(lpi->spx != NULL);
4865  assert(lpistate != NULL);
4866  /* assert(blkmem != NULL); */
4867 
4868  assert( lpi->spx->preStrongbranchingBasisFreed() );
4869 
4870  lpncols = lpi->spx->nCols();
4871  lpnrows = lpi->spx->nRows();
4872  assert(lpistate->ncols <= lpncols);
4873  assert(lpistate->nrows <= lpnrows);
4874 
4875  /* allocate enough memory for storing uncompressed basis information */
4876  SCIP_CALL( ensureCstatMem(lpi, lpncols) );
4877  SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
4878 
4879  /* unpack LPi state data */
4880  lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
4881 
4882  /* extend the basis to the current LP beyond the previously existing columns */
4883  for( i = lpistate->ncols; i < lpncols; ++i )
4884  {
4885  SCIP_Real bnd = lpi->spx->lower(i);
4886  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4887  {
4888  /* if lower bound is +/- infinity -> try upper bound */
4889  bnd = lpi->spx->lower(i);
4890  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4891  lpi->cstat[i] = (int) SCIP_BASESTAT_ZERO; /* variable is free */
4892  else
4893  lpi->cstat[i] = (int) SCIP_BASESTAT_UPPER; /* use finite upper bound */
4894  }
4895  else
4896  lpi->cstat[i] = (int) SCIP_BASESTAT_LOWER; /* use finite lower bound */
4897  }
4898  for( i = lpistate->nrows; i < lpnrows; ++i )
4899  lpi->rstat[i] = (int) SCIP_BASESTAT_BASIC; /*lint !e641*/
4900 
4901  /* load basis information */
4902  SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
4903 
4904  return SCIP_OKAY;
4905 }
4906 
4907 /** clears current LPi state (like basis information) of the solver */
4909  SCIP_LPI* lpi /**< LP interface structure */
4910  )
4911 { /*lint --e{715}*/
4912  SCIPdebugMessage("calling SCIPlpiClearState()\n");
4913 
4914  assert(lpi != NULL);
4915  assert(lpi->spx != NULL);
4916 
4917  try
4918  {
4919  lpi->spx->reLoad();
4920  }
4921 #ifndef NDEBUG
4922  catch( const SPxException& x )
4923  {
4924  std::string s = x.what();
4925  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4926 #else
4927  catch( const SPxException& )
4928  {
4929 #endif
4930  assert( lpi->spx->getStatus() != SPxSolver::OPTIMAL );
4931  return SCIP_LPERROR;
4932  }
4933 
4934  return SCIP_OKAY;
4935 }
4936 
4937 /** frees LPi state information */
4939  SCIP_LPI* lpi, /**< LP interface structure */
4940  BMS_BLKMEM* blkmem, /**< block memory */
4941  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4942  )
4943 { /*lint --e{715}*/
4944  SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4945 
4946  assert(lpi != NULL);
4947  assert(lpistate != NULL);
4948  assert(blkmem != NULL);
4949 
4950  if ( *lpistate != NULL )
4951  lpistateFree(lpistate, blkmem);
4952 
4953  return SCIP_OKAY;
4954 }
4955 
4956 /** checks, whether the given LP state contains simplex basis information */
4958  SCIP_LPI* lpi, /**< LP interface structure */
4959  SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4960  )
4961 { /*lint --e{715}*/
4962  assert(lpi != NULL);
4963  return TRUE;
4964 }
4965 
4966 /** reads LP state (like basis information from a file */
4968  SCIP_LPI* lpi, /**< LP interface structure */
4969  const char* fname /**< file name */
4970  )
4971 {
4972  SCIPdebugMessage("calling SCIPlpiReadState()\n");
4973  assert(lpi != NULL);
4974  assert(lpi->spx != NULL);
4975  assert(fname != NULL);
4976 
4977  assert( lpi->spx->preStrongbranchingBasisFreed() );
4978 
4979  bool success;
4980  SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
4981 
4982  return success ? SCIP_OKAY : SCIP_LPERROR;
4983 }
4984 
4985 /** writes LPi state (i.e. basis information) to a file */
4987  SCIP_LPI* lpi, /**< LP interface structure */
4988  const char* fname /**< file name */
4989  )
4990 {
4991  assert(lpi != NULL);
4992  assert(lpi->spx != NULL);
4993  assert(fname != NULL);
4994  SCIPdebugMessage("calling SCIPlpiWriteState()\n");
4995 
4996  assert( lpi->spx->preStrongbranchingBasisFreed() );
4997 
4998  bool res;
4999  SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
5000 
5001  if ( ! res )
5002  return SCIP_LPERROR;
5003 
5004  return SCIP_OKAY;
5005 }
5006 
5007 /**@} */
5008 
5009 
5010 
5011 
5012 /*
5013  * LP Pricing Norms Methods
5014  */
5015 
5016 /**@name LP Pricing Norms Methods */
5017 /**@{ */
5018 
5019 /** stores LPi pricing norms information
5020  * @todo should we store norm information?
5021  */
5023  SCIP_LPI* lpi, /**< LP interface structure */
5024  BMS_BLKMEM* blkmem, /**< block memory */
5025  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
5026  )
5027 {
5028 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5029  int nrows;
5030  int ncols;
5031 
5032  assert(blkmem != NULL);
5033  assert(lpi != NULL);
5034  assert(lpi->spx != NULL);
5035  assert(lpinorms != NULL);
5036 
5037  lpi->spx->getNdualNorms(nrows, ncols);
5038 
5039  if( nrows == 0 && ncols == 0)
5040  {
5041  (*lpinorms = NULL);
5042  return SCIP_OKAY;
5043  }
5044 
5045  /* allocate lpinorms data */
5046  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
5047  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
5048  (*lpinorms)->nrows = 0;
5049  (*lpinorms)->ncols = 0;
5050 
5051  SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
5052 
5053  if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
5054  {
5055  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5056  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
5057  BMSfreeBlockMemory(blkmem, lpinorms);
5058  assert(*lpinorms == NULL);
5059  }
5060 #ifndef NDEBUG
5061  else
5062  {
5063  assert(nrows == (*lpinorms)->nrows);
5064  assert(ncols == (*lpinorms)->ncols);
5065  }
5066 #endif
5067 #else
5068  (*lpinorms) = NULL;
5069 #endif
5070 
5071  return SCIP_OKAY;
5072 }
5073 
5074 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
5075  * columns and rows since the state was stored with SCIPlpiGetNorms()
5076  */
5078  SCIP_LPI* lpi, /**< LP interface structure */
5079  BMS_BLKMEM* blkmem, /**< block memory */
5080  const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
5081  )
5082 {
5083 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5084  assert(blkmem != NULL);
5085  assert(lpi != NULL);
5086  assert(lpi->spx != NULL);
5087 
5088  /* if there was no pricing norms information available, the LPi norms were not stored */
5089  if( lpinorms == NULL )
5090  return SCIP_OKAY;
5091 
5092  assert(lpinorms->nrows <= lpi->spx->nRows());
5093  assert(lpinorms->ncols <= lpi->spx->nCols());
5094 
5095  if( lpinorms->nrows == 0 )
5096  return SCIP_OKAY;
5097 
5098  SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
5099  (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->nRows(), lpi->spx->nCols());
5100 
5101  if( !lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms) )
5102  SCIPdebugMessage("loading of LPi norms failed\n");
5103 #endif
5104 
5105  return SCIP_OKAY;
5106 }
5107 
5108 /** frees pricing norms information */
5110  SCIP_LPI* lpi, /**< LP interface structure */
5111  BMS_BLKMEM* blkmem, /**< block memory */
5112  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
5113  )
5114 {
5115 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5116  assert(lpi != NULL);
5117  assert(lpinorms != NULL);
5118 
5119  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5120 
5121  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
5122  BMSfreeBlockMemory(blkmem, lpinorms);
5123  assert(*lpinorms == NULL);
5124 #endif
5125 
5126  return SCIP_OKAY;
5127 }
5128 
5129 /**@} */
5130 
5131 
5132 
5133 
5134 /*
5135  * Parameter Methods
5136  */
5137 
5138 /**@name Parameter Methods */
5139 /**@{ */
5140 
5141 /** gets integer parameter of LP */
5143  SCIP_LPI* lpi, /**< LP interface structure */
5144  SCIP_LPPARAM type, /**< parameter number */
5145  int* ival /**< buffer to store the parameter value */
5146  )
5147 {
5148  SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
5149 
5150  assert(lpi != NULL);
5151  assert(lpi->spx != NULL);
5152  assert(ival != NULL);
5153 
5154  switch( type )
5155  {
5157  *ival = lpi->spx->getFromScratch();
5158  break;
5159  case SCIP_LPPAR_LPINFO:
5160  *ival = lpi->spx->getLpInfo();
5161  break;
5162  case SCIP_LPPAR_LPITLIM:
5163  *ival = lpi->spx->getIterationLimit();
5164  if( *ival == -1 )
5165  *ival = INT_MAX;
5166  break;
5167  case SCIP_LPPAR_PRESOLVING:
5168  *ival = lpi->spx->getPresolving();
5169  break;
5170  case SCIP_LPPAR_PRICING:
5171  *ival = (int)lpi->pricing;
5172  break;
5173  case SCIP_LPPAR_SCALING:
5174  *ival = lpi->spx->getScaling();
5175  break;
5176 #if SOPLEX_VERSION >= 201
5177  case SCIP_LPPAR_TIMING:
5178  *ival = (int) lpi->spx->getTiming();
5179  break;
5180 #endif
5181 #if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
5182  case SCIP_LPPAR_RANDOMSEED:
5183  *ival = (int) lpi->spx->random.getSeed();
5184  break;
5185 #endif
5186  default:
5187  return SCIP_PARAMETERUNKNOWN;
5188  } /*lint !e788*/
5189 
5190  return SCIP_OKAY;
5191 }
5192 
5193 /** sets integer parameter of LP */
5195  SCIP_LPI* lpi, /**< LP interface structure */
5196  SCIP_LPPARAM type, /**< parameter number */
5197  int ival /**< parameter value */
5198  )
5199 {
5200  SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
5201 
5202  assert(lpi != NULL);
5203  assert(lpi->spx != NULL);
5204 
5205  switch( type )
5206  {
5208  assert(ival == TRUE || ival == FALSE);
5209  lpi->spx->setFromScratch(bool(ival));
5210  break;
5211  case SCIP_LPPAR_LPINFO:
5212  assert(ival == TRUE || ival == FALSE);
5213  lpi->spx->setLpInfo(bool(ival));
5214  break;
5215  case SCIP_LPPAR_LPITLIM:
5216  assert( ival >= 0 );
5217  /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
5218  if( ival >= INT_MAX )
5219  ival = -1;
5220  lpi->spx->setIterationLimit(ival);
5221  break;
5222  case SCIP_LPPAR_PRESOLVING:
5223  assert(ival == TRUE || ival == FALSE);
5224  lpi->spx->setPresolving(bool(ival));
5225  break;
5226  case SCIP_LPPAR_PRICING:
5227  lpi->pricing = (SCIP_PRICING)ival;
5228  switch( lpi->pricing )
5229  {
5231  case SCIP_PRICING_AUTO:
5232  lpi->spx->setAutoPricer();
5233  break;
5234  case SCIP_PRICING_FULL:
5235  lpi->spx->setFullPricer();
5236  break;
5237  case SCIP_PRICING_PARTIAL:
5238  lpi->spx->setParmultPricer();
5239  break;
5240  case SCIP_PRICING_STEEP:
5241  lpi->spx->setSteepPricer();
5242  break;
5244  lpi->spx->setSteepQStartPricer();
5245  break;
5246  case SCIP_PRICING_DEVEX:
5247  lpi->spx->setDevexPricer();
5248  break;
5249  default:
5250  return SCIP_LPERROR;
5251  }
5252  break;
5253  case SCIP_LPPAR_SCALING:
5254  assert(ival == TRUE || ival == FALSE);
5255  lpi->spx->setScaling(ival);
5256  break;
5257 #if SOPLEX_VERSION >= 201
5258  case SCIP_LPPAR_TIMING:
5259  assert(ival >= 0 && ival < 3);
5260  lpi->spx->setTiming((Timer::TYPE) ival);
5261  break;
5262 #endif
5263 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 2)
5264  case SCIP_LPPAR_RANDOMSEED:
5265  lpi->spx->random.setSeed((unsigned int) ival);
5266  break;
5267 #endif
5268 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
5269  case SCIP_LPPAR_POLISHING:
5270  assert(ival >= 0 && ival < 3);
5271  lpi->spx->setSolutionPolishing((SPxSolver::SolutionPolish) ival);
5272  break;
5273 #endif
5274 
5275  default:
5276  return SCIP_PARAMETERUNKNOWN;
5277  } /*lint !e788*/
5278 
5279  return SCIP_OKAY;
5280 }
5281 
5282 /** gets floating point parameter of LP */
5284  SCIP_LPI* lpi, /**< LP interface structure */
5285  SCIP_LPPARAM type, /**< parameter number */
5286  SCIP_Real* dval /**< buffer to store the parameter value */
5287  )
5288 {
5289  SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
5290 
5291  assert(lpi != NULL);
5292  assert(lpi->spx != NULL);
5293  assert(dval != NULL);
5294 
5295  switch( type )
5296  {
5297  case SCIP_LPPAR_FEASTOL:
5298  *dval = lpi->spx->feastol();
5299  break;
5300 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5302  *dval = lpi->spx->opttol();
5303  break;
5304 #endif
5305  case SCIP_LPPAR_OBJLIM:
5306  if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5307  *dval = lpi->spx->getObjUpLimit();
5308  else
5309  *dval = lpi->spx->getObjLoLimit();
5310  break;
5311  case SCIP_LPPAR_LPTILIM:
5312  *dval = lpi->spx->terminationTime();
5313  break;
5315  *dval = lpi->rowrepswitch;
5316  break;
5318  *dval = lpi->conditionlimit;
5319  break;
5320  default:
5321  return SCIP_PARAMETERUNKNOWN;
5322  } /*lint !e788*/
5323 
5324  return SCIP_OKAY;
5325 }
5326 
5327 /** sets floating point parameter of LP */
5329  SCIP_LPI* lpi, /**< LP interface structure */
5330  SCIP_LPPARAM type, /**< parameter number */
5331  SCIP_Real dval /**< parameter value */
5332  )
5333 {
5334  SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
5335 
5336  assert(lpi != NULL);
5337  assert(lpi->spx != NULL);
5338 
5339  switch( type )
5340  {
5341  case SCIP_LPPAR_FEASTOL:
5342  /* 0 < dval */
5343  assert( dval > 0.0 );
5344  lpi->spx->setFeastol(dval);
5345  break;
5346 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5348  /* 0 < dval */
5349  assert( dval > 0.0 );
5350  lpi->spx->setOpttol(dval);
5351  break;
5352 #endif
5353  case SCIP_LPPAR_OBJLIM:
5354  if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5355  lpi->spx->setObjUpLimit(dval);
5356  else
5357  lpi->spx->setObjLoLimit(dval);
5358  break;
5359  case SCIP_LPPAR_LPTILIM:
5360  assert( dval > 0.0 );
5361  /* soplex requires 0 <= dval
5362  *
5363  * However for consistency we assert the timelimit to be strictly positive.
5364  */
5365  lpi->spx->setTerminationTime(dval);
5366  break;
5368  assert( dval >= 0.0 || dval == -1.0 );
5369  lpi->rowrepswitch = dval;
5370  break;
5372  lpi->conditionlimit = dval;
5373  lpi->checkcondition = (dval >= 0.0);
5374  break;
5375  default:
5376  return SCIP_PARAMETERUNKNOWN;
5377  } /*lint !e788*/
5378 
5379  return SCIP_OKAY;
5380 }
5381 
5382 /**@} */
5383 
5384 
5385 
5386 
5387 /*
5388  * Numerical Methods
5389  */
5390 
5391 /**@name Numerical Methods */
5392 /**@{ */
5393 
5394 /** returns value treated as infinity in the LP solver */
5396  SCIP_LPI* /*lpi*/ /**< LP interface structure */
5397  )
5399  SCIPdebugMessage("calling SCIPlpiInfinity()\n");
5400 
5401  return soplex::infinity;
5402 }
5403 
5404 /** checks if given value is treated as infinity in the LP solver */
5406  SCIP_LPI* /*lpi*/, /**< LP interface structure */
5407  SCIP_Real val
5408  )
5409 {
5410  SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
5411 
5412  return (val >= soplex::infinity);
5413 }
5414 
5415 /**@} */
5416 
5417 
5418 
5419 
5420 /*
5421  * File Interface Methods
5422  */
5423 
5424 /**@name File Interface Methods */
5425 /**@{ */
5426 
5427 /** returns, whether the given file exists */
5428 static
5430  const char* filename /**< file name */
5431  )
5433  FILE* f;
5434 
5435  f = fopen(filename, "r");
5436  if( f == NULL )
5437  return FALSE;
5438 
5439  fclose(f);
5440 
5441  return TRUE;
5442 }
5443 
5444 /** reads LP from a file */
5446  SCIP_LPI* lpi, /**< LP interface structure */
5447  const char* fname /**< file name */
5448  )
5449 {
5450  SCIPdebugMessage("calling SCIPlpiReadLP()\n");
5451 
5452  assert(lpi != NULL);
5453  assert(lpi->spx != NULL);
5454  assert(fname != NULL);
5455 
5456  assert( lpi->spx->preStrongbranchingBasisFreed() );
5457 
5458  if( !fileExists(fname) )
5459  return SCIP_NOFILE;
5460 
5461  try
5462  {
5463  if( !lpi->spx->readLP(fname) )
5464  return SCIP_READERROR;
5465  }
5466 #ifndef NDEBUG
5467  catch( const SPxException& x )
5468  {
5469  std::string s = x.what();
5470  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5471 #else
5472  catch( const SPxException& )
5473  {
5474 #endif
5475  return SCIP_READERROR;
5476  }
5477 
5478  return SCIP_OKAY;
5479 }
5480 
5481 /** writes LP to a file */
5483  SCIP_LPI* lpi, /**< LP interface structure */
5484  const char* fname /**< file name */
5485  )
5486 {
5487  SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
5488 
5489  assert(lpi != NULL);
5490  assert(lpi->spx != NULL);
5491  assert(fname != NULL);
5492 
5493  try
5494  {
5495  lpi->spx->writeFile(fname);
5496  }
5497 #ifndef NDEBUG
5498  catch( const SPxException& x )
5499  {
5500  std::string s = x.what();
5501  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5502 #else
5503  catch( const SPxException& )
5504  {
5505 #endif
5506  return SCIP_WRITEERROR;
5507  }
5508 
5509  return SCIP_OKAY;
5510 }
5511 
5512 /**@} */
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1732
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx1.cpp:5197
static SCIP_RETCODE lpiGetBInvVec(SCIP_LPI *lpi, SCIP_Real *rhs, SCIP_Real *coef)
Definition: lpi_spx1.cpp:4527
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_spx1.cpp:3308
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition: type_lpi.h:95
SCIP_Real SCIPlpiInfinity(SCIP_LPI *)
Definition: lpi_spx1.cpp:5398
const char * SCIPlpiGetSolverName(void)
Definition: lpi_spx1.cpp:1635
SCIP_Real conditionlimit
Definition: lpi_cpx.c:164
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:140
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_spx1.cpp:5145
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_spx1.cpp:5080
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx1.cpp:3884
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_spx1.cpp:2275
ROWPACKET * packrstat
Definition: lpi_clp.cpp:128
SCIP_PRICING pricing
Definition: lpi_clp.cpp:103
#define infinity
Definition: gastrans.c:71
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:4047
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_spx1.cpp:2765
enum SCIP_ObjSen SCIP_OBJSEN
Definition: type_lpi.h:36
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:1671
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4960
SCIP_Bool solved
Definition: lpi_clp.cpp:105
void SCIPdecodeDualBit(const SCIP_DUALPACKET *inp, int *out, int count)
Definition: bitencode.c:299
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3493
interface methods for specific LP solvers
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_spx1.cpp:3014
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_spx1.cpp:2018
static SCIP_RETCODE readFile(SCIP *scip, CMININPUT *cmininput, const char *filename)
Definition: reader_cmin.c:1139
static SCIP_RETCODE lpistateCreate(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem, int ncols, int nrows)
Definition: lpi_spx1.cpp:1537
SCIP_Real rowrepswitch
Definition: lpi_spx1.cpp:1406
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *, SCIP_Real val)
Definition: lpi_spx1.cpp:5408
#define FALSE
Definition: def.h:73
#define AUTOPRICING_ITERSWITCH
Definition: lpi_spx1.cpp:34
static int rowpacketNum(int nrows)
Definition: lpi_spx1.cpp:1496
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_spx1.cpp:1696
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3528
static void invalidateSolution(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:1606
static SCIP_RETCODE getRedCostEst(SPxSCIP *spx, int col, SCIP_Real *val)
Definition: lpi_spx1.cpp:3992
#define TRUE
Definition: def.h:72
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4761
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3030
int rstatsize
Definition: lpi_clp.cpp:101
SCIP_Bool checkcondition
Definition: lpi_cpx.c:165
static SCIP_RETCODE spxSolve(SCIP_LPI *lpi, SPxSolver::Representation rep, SPxSolver::Type type)
Definition: lpi_spx1.cpp:2878
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5025
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:64
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:115
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3700
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_spx1.cpp:2096
#define SCIPdebugMessage
Definition: pub_message.h:87
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_spx1.cpp:2844
#define SOPLEX_VERBLEVEL
Definition: lpi_spx1.cpp:145
#define BMSfreeMemory(ptr)
Definition: memory.h:137
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:77
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
Definition: lpi_spx1.cpp:1561
static void setOpttol(SCIP_NLPIPROBLEM *nlpiproblem, SCIP_Real opttol)
Definition: nlpi_ipopt.cpp:489
SCIP_VAR ** x
Definition: circlepacking.c:54
std::pair< SolType, OutcomeType > Result
A result comprises of a solution/ray in feasible space and a corresponding outcome in objective space...
static SCIP_RETCODE ensureRstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx1.cpp:1458
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4656
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3713
#define ROWS_PER_PACKET
Definition: lpi_spx1.cpp:1391
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_spx1.cpp:1804
#define SOPLEX_TRY(messagehdlr, x)
Definition: lpi_spx1.cpp:166
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3594
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2433
polyscip::Polyscip::PolyscipStatus Status
abbreviation
Definition: main.cpp:29
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:4970
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_spx1.cpp:3278
#define COLS_PER_PACKET
Definition: lpi_spx1.cpp:1389
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_spx1.cpp:2518
static SCIP_RETCODE ensureCstatMem(SCIP_LPI *lpi, int num)
Definition: lpi_spx1.cpp:1436
packing single and dual bit values
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:139
static int colpacketNum(int ncols)
Definition: lpi_spx1.cpp:1487
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_spx1.cpp:3457
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3044
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3726
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_spx1.cpp:4134
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5485
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:1986
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2722
static SPxLP::SPxSense spxObjsen(SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1587
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_spx1.cpp:1679
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3566
static SCIP_RETCODE pricing(SCIP *scip, SCIP_PRICER *pricer, SCIP_Real *lowerbound, SCIP_Bool farkas)
Definition: pricer_stp.c:176
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:2299
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_spx1.cpp:3770
SCIPInterval sign(const SCIPInterval &x)
static char spxname[100]
Definition: lpi_spx1.cpp:1628
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_spx1.cpp:1704
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_spx1.cpp:3752
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:418
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_spx1.cpp:1964
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:4911
#define NULL
Definition: lpi_spx1.cpp:155
int * rstat
Definition: lpi_clp.cpp:99
#define REALABS(x)
Definition: def.h:187
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_spx1.cpp:2816
int cstatsize
Definition: lpi_clp.cpp:100
#define SCIP_CALL(x)
Definition: def.h:370
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_spx1.cpp:2226
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_spx1.cpp:3382
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_spx1.cpp:3060
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_spx1.cpp:1882
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5112
static SCIP_Bool fileExists(const char *filename)
Definition: lpi_spx1.cpp:5432
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3621
void SCIPencodeDualBit(const int *inp, SCIP_DUALPACKET *out, int count)
Definition: bitencode.c:229
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_spx1.cpp:2167
#define EPSCEIL(x, eps)
Definition: def.h:197
#define SOPLEX_SUBVERSION
Definition: lpi_spx1.cpp:92
COLPACKET * packcstat
Definition: lpi_clp.cpp:127
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:456
unsigned int SCIP_DUALPACKET
Definition: bitencode.h:33
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4701
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2363
#define SCIP_Bool
Definition: def.h:70
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2926
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:445
static void setFeastol(SCIP_NLPIPROBLEM *nlpiproblem, SCIP_Real feastol)
Definition: nlpi_ipopt.cpp:458
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_spx1.cpp:1650
#define BMSallocMemoryCPP(size)
Definition: memory.h:113
unsigned short Type
Definition: cons_xor.c:121
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:458
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_spx1.cpp:5331
#define MAX(x, y)
Definition: tclique_def.h:83
static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
Definition: lpi_spx1.cpp:1505
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_spx1.cpp:2535
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_spx1.cpp:2788
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_spx1.cpp:2585
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_spx1.cpp:2642
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_spx1.cpp:2319
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3664
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_spx1.cpp:4221
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2696
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3739
SCIP_Real * r
Definition: circlepacking.c:50
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3581
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3510
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition: lpi_spx1.cpp:3791
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4810
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3541
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3640
SLUFactor * factorization
Definition: lpi_spx1.cpp:1405
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_spx1.cpp:1771
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4854
static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:1521
public methods for message output
SCIP_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
Definition: lpi_spx1.cpp:2552
SCIP_DUALPACKET COLPACKET
Definition: lpi_spx1.cpp:1388
#define SCIP_Real
Definition: def.h:163
SCIP_VAR ** y
Definition: circlepacking.c:55
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3438
SPxSCIP * spx
Definition: lpi_spx1.cpp:1398
#define BMSallocMemory(ptr)
Definition: memory.h:111
#define SCIP_INVALID
Definition: def.h:183
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:119
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2149
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_spx1.cpp:3352
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3478
SCIP_DUALPACKET ROWPACKET
Definition: lpi_spx1.cpp:1390
#define SOPLEX_TRY_ABORT(x)
Definition: lpi_spx1.cpp:211
SCIP_MESSAGEHDLR * messagehdlr
Definition: lpi_cpx.c:175
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4356
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2970
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4941
#define UNKNOWN
Definition: sepa_mcf.c:4095
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx1.cpp:3916
static char spxdesc[200]
Definition: lpi_spx1.cpp:1629
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3608
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:443
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx1.cpp:5286
#define EPSFLOOR(x, eps)
Definition: def.h:196
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:122
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:429
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:2118
#define SCIP_ALLOC(x)
Definition: def.h:381
#define SCIPABORT()
Definition: def.h:342
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_spx1.cpp:3847
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5448
int * cstat
Definition: lpi_clp.cpp:98
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_spx1.cpp:3937
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:4989
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_spx1.cpp:1712
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_spx1.cpp:2748