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-2022 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)
370  SPxSolver::setFeastol(d);
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)
390  SPxSolver::setOpttol(d);
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 char* initSpxDesc( );
1626 
1627 #if (SOPLEX_SUBVERSION > 0)
1628  const static char spxname[20]= {'S', 'o', 'p', 'l', 'e', 'x', '1', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0', '.', SOPLEX_SUBVERSION + '0'};
1629 #else
1630  const static char spxname[20] = {'S', 'o', 'p', 'l', 'e', 'x', '1', ' ', SOPLEX_VERSION/100 + '0', '.', (SOPLEX_VERSION % 100)/10 + '0', '.', SOPLEX_VERSION % 10 + '0'};
1631 #endif
1632 
1633 static char* spxdesc = initSpxDesc();
1634 
1635 char* initSpxDesc( )
1637  spxdesc = new char[200];
1638  (void)snprintf(spxdesc, 200, "%s [GitHash: %s]", "Linear Programming Solver developed at Zuse Institute Berlin (soplex.zib.de)"
1639 #ifdef SCIP_WITH_LPSCHECK
1640  " - including CPLEX double check"
1641 #endif
1642  , getGitHash());
1643  return spxdesc;
1644 }
1645 
1646 /**@name Miscellaneous Methods */
1647 /**@{ */
1648 
1649 /** gets name and version of LP solver */
1650 const char* SCIPlpiGetSolverName(
1651  void
1652  )
1654  SCIPdebugMessage("calling SCIPlpiGetSolverName()\n");
1655  return spxname;
1656 }
1657 
1658 /** gets description of LP solver (developer, webpage, ...) */
1659 const char* SCIPlpiGetSolverDesc(
1660  void
1661  )
1663  return spxdesc;
1664 }
1665 
1666 /** gets pointer for LP solver - use only with great care */
1668  SCIP_LPI* lpi /**< pointer to an LP interface structure */
1669  )
1671  return (void*) lpi->spx;
1672 }
1673 
1674 /** pass integrality information about variables to the solver */
1676  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
1677  int ncols, /**< length of integrality array */
1678  int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
1679  )
1680 {
1681 #if (SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3))
1682  assert(ncols == lpi->spx->nCols() || (ncols == 0 && intInfo == NULL));
1683  lpi->spx->setIntegralityInformation(ncols, intInfo);
1684  return SCIP_OKAY;
1685 #else
1686  SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
1687  return SCIP_LPERROR;
1688 #endif
1689 }
1690 
1691 /** informs about availability of a primal simplex solving method */
1693  void
1694  )
1696  return TRUE;
1697 }
1698 
1699 /** informs about availability of a dual simplex solving method */
1701  void
1702  )
1704  return TRUE;
1705 }
1706 
1707 /** informs about availability of a barrier solving method */
1709  void
1710  )
1712  return FALSE;
1713 }
1714 
1715 /**@} */
1716 
1717 
1718 
1719 
1720 /*
1721  * LPI Creation and Destruction Methods
1722  */
1723 
1724 /**@name LPI Creation and Destruction Methods */
1725 /**@{ */
1726 
1727 /** creates an LP problem object */
1729  SCIP_LPI** lpi, /**< pointer to an LP interface structure */
1730  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
1731  const char* name, /**< problem name */
1732  SCIP_OBJSEN objsen /**< objective sense */
1733  )
1734 {
1735  assert(lpi != NULL);
1736  assert(name != NULL);
1737 
1738  /* create SoPlex object */
1739  SCIP_ALLOC( BMSallocMemory(lpi) );
1740 
1741  /* we use this construction to allocate the memory for the SoPlex class also via the blockmemshell */
1742  (*lpi)->spx = static_cast<SPxSCIP*>(BMSallocMemoryCPP(sizeof(SPxSCIP)));
1743  SOPLEX_TRY( messagehdlr, (*lpi)->spx = new ((*lpi)->spx) SPxSCIP(messagehdlr, name) );
1744  (*lpi)->cstat = NULL;
1745  (*lpi)->rstat = NULL;
1746  (*lpi)->cstatsize = 0;
1747  (*lpi)->rstatsize = 0;
1748  (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
1749  (*lpi)->factorization = 0;
1750  (*lpi)->rowrepswitch = SCIPlpiInfinity(*lpi);
1751  (*lpi)->conditionlimit = -1.0;
1752  (*lpi)->checkcondition = FALSE;
1753  (*lpi)->messagehdlr = messagehdlr;
1754 
1755  invalidateSolution(*lpi);
1756 
1757  /* set objective sense */
1758  SCIP_CALL( SCIPlpiChgObjsen(*lpi, objsen) );
1759 
1760  /* set default pricing */
1761  SCIP_CALL( SCIPlpiSetIntpar(*lpi, SCIP_LPPAR_PRICING, (int)(*lpi)->pricing) );
1762 
1763  return SCIP_OKAY;
1764 }
1765 
1766 /** deletes an LP problem object */
1768  SCIP_LPI** lpi /**< pointer to an LP interface structure */
1769  )
1771  assert(lpi != NULL);
1772  assert(*lpi != NULL);
1773  assert((*lpi)->spx != NULL);
1774 
1775  /* free LP using destructor and free memory via blockmemshell */
1776  (*lpi)->spx->~SPxSCIP();
1777  BMSfreeMemory(&((*lpi)->spx));
1778 
1779  /* free memory */
1780  BMSfreeMemoryArrayNull(&(*lpi)->cstat);
1781  BMSfreeMemoryArrayNull(&(*lpi)->rstat);
1782  BMSfreeMemory(lpi);
1783 
1784  return SCIP_OKAY;
1785 }
1786 
1787 /**@} */
1788 
1789 
1790 
1791 
1792 /*
1793  * Modification Methods
1794  */
1795 
1796 /**@name Modification Methods */
1797 /**@{ */
1798 
1799 /** copies LP data with column matrix into LP solver */
1801  SCIP_LPI* lpi, /**< LP interface structure */
1802  SCIP_OBJSEN objsen, /**< objective sense */
1803  int ncols, /**< number of columns */
1804  const SCIP_Real* obj, /**< objective function values of columns */
1805  const SCIP_Real* lb, /**< lower bounds of columns */
1806  const SCIP_Real* ub, /**< upper bounds of columns */
1807  char** colnames, /**< column names, or NULL */
1808  int nrows, /**< number of rows */
1809  const SCIP_Real* lhs, /**< left hand sides of rows */
1810  const SCIP_Real* rhs, /**< right hand sides of rows */
1811  char** /*rownames*/, /**< row names, or NULL */
1812  int nnonz, /**< number of nonzero elements in the constraint matrix */
1813  const int* beg, /**< start index of each column in ind- and val-array */
1814  const int* ind, /**< row indices of constraint matrix entries */
1815  const SCIP_Real* val /**< values of constraint matrix entries */
1816  )
1817 {
1818 #ifndef NDEBUG
1819  {
1820  int j;
1821  for( j = 0; j < nnonz; j++ )
1822  assert( val[j] != 0 );
1823  }
1824 #endif
1825 
1826  SCIPdebugMessage("calling SCIPlpiLoadColLP()\n");
1827 
1828  assert(lpi != NULL);
1829  assert(lpi->spx != NULL);
1830  assert(lhs != NULL);
1831  assert(rhs != NULL);
1832  assert(obj != NULL);
1833  assert(lb != NULL);
1834  assert(ub != NULL);
1835  assert(beg != NULL);
1836  assert(ind != NULL);
1837  assert(val != NULL);
1838 
1839  invalidateSolution(lpi);
1840  assert( lpi->spx->preStrongbranchingBasisFreed() );
1841 
1842  try
1843  {
1844  SPxSCIP* spx = lpi->spx;
1845  LPRowSet rows(nrows);
1846  DSVector emptyVector(0);
1847  int i;
1848 
1849  spx->clear();
1850 
1851  /* set objective sense */
1852  spx->setSense(spxObjsen(objsen));
1853 
1854  /* create empty rows with given sides */
1855  for( i = 0; i < nrows; ++i )
1856  rows.add(lhs[i], emptyVector, rhs[i]);
1857  spx->addRows(rows);
1858 
1859  /* create column vectors with coefficients and bounds */
1860  SCIP_CALL( SCIPlpiAddCols(lpi, ncols, obj, lb, ub, colnames, nnonz, beg, ind, val) );
1861  }
1862 #ifndef NDEBUG
1863  catch( const SPxException& x )
1864  {
1865  std::string s = x.what();
1866  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1867 #else
1868  catch( const SPxException& )
1869  {
1870 #endif
1871  return SCIP_LPERROR;
1872  }
1873 
1874  return SCIP_OKAY;
1875 }
1876 
1877 /** adds columns to the LP */
1879  SCIP_LPI* lpi, /**< LP interface structure */
1880  int ncols, /**< number of columns to be added */
1881  const SCIP_Real* obj, /**< objective function values of new columns */
1882  const SCIP_Real* lb, /**< lower bounds of new columns */
1883  const SCIP_Real* ub, /**< upper bounds of new columns */
1884  char** /*colnames*/, /**< column names, or NULL */
1885  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1886  const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1887  const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1888  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1889  )
1890 {
1891  SCIPdebugMessage("calling SCIPlpiAddCols()\n");
1892 
1893  assert(lpi != NULL);
1894  assert(lpi->spx != NULL);
1895  assert(obj != NULL);
1896  assert(lb != NULL);
1897  assert(ub != NULL);
1898  assert(nnonz == 0 || beg != NULL);
1899  assert(nnonz == 0 || ind != NULL);
1900  assert(nnonz == 0 || val != NULL);
1901  assert(nnonz >= 0);
1902  assert(ncols >= 0);
1903 
1904  invalidateSolution(lpi);
1905 
1906  assert( lpi->spx->preStrongbranchingBasisFreed() );
1907 
1908 #ifndef NDEBUG
1909  if ( nnonz > 0 )
1910  {
1911  /* perform check that no new rows are added - this is likely to be a mistake */
1912  int nrows = lpi->spx->nRows();
1913  for (int j = 0; j < nnonz; ++j)
1914  {
1915  assert( 0 <= ind[j] && ind[j] < nrows );
1916  assert( val[j] != 0.0 );
1917  }
1918  }
1919 #endif
1920 
1921  SPxSCIP* spx = lpi->spx;
1922  try
1923  {
1924  LPColSet cols(ncols);
1925  DSVector colVector(ncols);
1926  int start;
1927  int last;
1928  int i;
1929 
1930  /* create column vectors with coefficients and bounds */
1931  for( i = 0; i < ncols; ++i )
1932  {
1933  colVector.clear();
1934  if( nnonz > 0 )
1935  {
1936  start = beg[i];
1937  last = (i == ncols-1 ? nnonz : beg[i+1]);
1938  colVector.add( last-start, &ind[start], &val[start] );
1939  }
1940  cols.add(obj[i], lb[i], colVector, ub[i]);
1941  }
1942  spx->addCols(cols);
1943  }
1944 #ifndef NDEBUG
1945  catch( const SPxException& x )
1946  {
1947  std::string s = x.what();
1948  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
1949 #else
1950  catch( const SPxException& )
1951  {
1952 #endif
1953  return SCIP_LPERROR;
1954  }
1955 
1956  return SCIP_OKAY;
1957 }
1958 
1959 /** deletes all columns in the given range from LP */
1961  SCIP_LPI* lpi, /**< LP interface structure */
1962  int firstcol, /**< first column to be deleted */
1963  int lastcol /**< last column to be deleted */
1964  )
1965 {
1966  SCIPdebugMessage("calling SCIPlpiDelCols()\n");
1967 
1968  assert(lpi != NULL);
1969  assert(lpi->spx != NULL);
1970  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
1971 
1972  invalidateSolution(lpi);
1973 
1974  assert( lpi->spx->preStrongbranchingBasisFreed() );
1975 
1976  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeColRange(firstcol, lastcol) );
1977 
1978  return SCIP_OKAY;
1979 }
1980 
1981 /** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1983  SCIP_LPI* lpi, /**< LP interface structure */
1984  int* dstat /**< deletion status of columns
1985  * input: 1 if column should be deleted, 0 if not
1986  * output: new position of column, -1 if column was deleted */
1987  )
1988 {
1989  int ncols;
1990  int i;
1991 
1992  SCIPdebugMessage("calling SCIPlpiDelColset()\n");
1993 
1994  assert(lpi != NULL);
1995  assert(lpi->spx != NULL);
1996  assert(dstat != NULL);
1997 
1998  invalidateSolution(lpi);
1999 
2000  assert( lpi->spx->preStrongbranchingBasisFreed() );
2001 
2002  ncols = lpi->spx->nCols();
2003 
2004  /* SoPlex removeCols() method deletes the columns with dstat[i] < 0, so we have to negate the values */
2005  for( i = 0; i < ncols; ++i )
2006  dstat[i] *= -1;
2007 
2008  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeCols(dstat) );
2009 
2010  return SCIP_OKAY;
2011 }
2012 
2013 /** adds rows to the LP */
2015  SCIP_LPI* lpi, /**< LP interface structure */
2016  int nrows, /**< number of rows to be added */
2017  const SCIP_Real* lhs, /**< left hand sides of new rows */
2018  const SCIP_Real* rhs, /**< right hand sides of new rows */
2019  char** /*rownames*/, /**< row names, or NULL */
2020  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
2021  const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
2022  const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
2023  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
2024  )
2025 {
2026  SCIPdebugMessage("calling SCIPlpiAddRows()\n");
2027 
2028  assert(lpi != NULL);
2029  assert(lpi->spx != NULL);
2030  assert(lhs != NULL);
2031  assert(rhs != NULL);
2032  assert(nnonz == 0 || beg != NULL);
2033  assert(nnonz == 0 || ind != NULL);
2034  assert(nnonz == 0 || val != NULL);
2035 
2036  invalidateSolution(lpi);
2037 
2038  assert( lpi->spx->preStrongbranchingBasisFreed() );
2039 
2040 #ifndef NDEBUG
2041  if ( nnonz > 0 )
2042  {
2043  /* perform check that no new columns are added - this is likely to be a mistake */
2044  int ncols = lpi->spx->nCols();
2045  for (int j = 0; j < nnonz; ++j)
2046  {
2047  assert( 0 <= ind[j] && ind[j] < ncols );
2048  assert( val[j] != 0.0 );
2049  }
2050  }
2051 #endif
2052 
2053  try
2054  {
2055  SPxSCIP* spx = lpi->spx;
2056  LPRowSet rows(nrows);
2057  DSVector rowVector;
2058  int start;
2059  int last;
2060  int i;
2061 
2062  /* create row vectors with given sides */
2063  for( i = 0; i < nrows; ++i )
2064  {
2065  rowVector.clear();
2066  if( nnonz > 0 )
2067  {
2068  start = beg[i];
2069  last = (i == nrows-1 ? nnonz : beg[i+1]);
2070  rowVector.add( last-start, &ind[start], &val[start] );
2071  }
2072  rows.add(lhs[i], rowVector, rhs[i]);
2073  }
2074  spx->addRows(rows);
2075  }
2076 #ifndef NDEBUG
2077  catch( const SPxException& x )
2078  {
2079  std::string s = x.what();
2080  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2081 #else
2082  catch( const SPxException& )
2083  {
2084 #endif
2085  return SCIP_LPERROR;
2086  }
2087 
2088  return SCIP_OKAY;
2089 }
2090 
2091 /** deletes all rows in the given range from LP */
2093  SCIP_LPI* lpi, /**< LP interface structure */
2094  int firstrow, /**< first row to be deleted */
2095  int lastrow /**< last row to be deleted */
2096  )
2097 {
2098  SCIPdebugMessage("calling SCIPlpiDelRows()\n");
2099 
2100  assert(lpi != NULL);
2101  assert(lpi->spx != NULL);
2102  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2103 
2104  invalidateSolution(lpi);
2105 
2106  assert( lpi->spx->preStrongbranchingBasisFreed() );
2107 
2108  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRowRange(firstrow, lastrow) );
2109 
2110  return SCIP_OKAY;
2111 }
2112 
2113 /** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
2115  SCIP_LPI* lpi, /**< LP interface structure */
2116  int* dstat /**< deletion status of rows
2117  * input: 1 if row should be deleted, 0 if not
2118  * output: new position of row, -1 if row was deleted */
2119  )
2120 {
2121  int nrows;
2122  int i;
2123 
2124  SCIPdebugMessage("calling SCIPlpiDelRowset()\n");
2125 
2126  assert(lpi != NULL);
2127  assert(lpi->spx != NULL);
2128 
2129  invalidateSolution(lpi);
2130 
2131  assert( lpi->spx->preStrongbranchingBasisFreed() );
2132 
2133  nrows = lpi->spx->nRows();
2134 
2135  /* SoPlex removeRows() method deletes the rows with dstat[i] < 0, so we have to negate the values */
2136  for( i = 0; i < nrows; ++i )
2137  dstat[i] *= -1;
2138 
2139  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->removeRows(dstat) );
2140 
2141  return SCIP_OKAY;
2142 }
2143 
2144 /** clears the whole LP */
2146  SCIP_LPI* lpi /**< LP interface structure */
2147  )
2149  SCIPdebugMessage("calling SCIPlpiClear()\n");
2150 
2151  assert(lpi != NULL);
2152  assert(lpi->spx != NULL);
2153 
2154  invalidateSolution(lpi);
2155 
2156  assert( lpi->spx->preStrongbranchingBasisFreed() );
2157  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->clear() );
2158 
2159  return SCIP_OKAY;
2160 }
2161 
2162 /** changes lower and upper bounds of columns */
2164  SCIP_LPI* lpi, /**< LP interface structure */
2165  int ncols, /**< number of columns to change bounds for */
2166  const int* ind, /**< column indices or NULL if ncols is zero */
2167  const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
2168  const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
2169  )
2170 {
2171  int i;
2172 
2173  SCIPdebugMessage("calling SCIPlpiChgBounds()\n");
2174 
2175  assert(lpi != NULL);
2176  assert(lpi->spx != NULL);
2177  assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
2178  if( ncols <= 0 )
2179  return SCIP_OKAY;
2180 
2181  invalidateSolution(lpi);
2182 
2183  assert( lpi->spx->preStrongbranchingBasisFreed() );
2184 
2185  try
2186  {
2187  for( i = 0; i < ncols; ++i )
2188  {
2189  assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2190 
2191  if ( SCIPlpiIsInfinity(lpi, lb[i]) )
2192  {
2193  SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
2194  return SCIP_LPERROR;
2195  }
2196  if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
2197  {
2198  SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
2199  return SCIP_LPERROR;
2200  }
2201 
2202  lpi->spx->changeBounds(ind[i], lb[i], ub[i]);
2203  assert(lpi->spx->lower(ind[i]) <= lpi->spx->upper(ind[i]) + Param::epsilon());
2204  }
2205  }
2206 #ifndef NDEBUG
2207  catch( const SPxException& x )
2208  {
2209  std::string s = x.what();
2210  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2211 #else
2212  catch( const SPxException& )
2213  {
2214 #endif
2215  return SCIP_LPERROR;
2216  }
2217 
2218  return SCIP_OKAY;
2219 }
2220 
2221 /** changes left and right hand sides of rows */
2223  SCIP_LPI* lpi, /**< LP interface structure */
2224  int nrows, /**< number of rows to change sides for */
2225  const int* ind, /**< row indices */
2226  const SCIP_Real* lhs, /**< new values for left hand sides */
2227  const SCIP_Real* rhs /**< new values for right hand sides */
2228  )
2229 {
2230  int i;
2231 
2232  SCIPdebugMessage("calling SCIPlpiChgSides()\n");
2233 
2234  assert(lpi != NULL);
2235  assert(lpi->spx != NULL);
2236  assert(ind != NULL);
2237  assert(lhs != NULL);
2238  assert(rhs != NULL);
2239  if( nrows <= 0 )
2240  return SCIP_OKAY;
2241 
2242  invalidateSolution(lpi);
2243 
2244  assert( lpi->spx->preStrongbranchingBasisFreed() );
2245 
2246  try
2247  {
2248  for( i = 0; i < nrows; ++i )
2249  {
2250  assert(0 <= ind[i] && ind[i] < lpi->spx->nRows());
2251  lpi->spx->changeRange(ind[i], lhs[i], rhs[i]);
2252  assert(lpi->spx->lhs(ind[i]) <= lpi->spx->rhs(ind[i]) + Param::epsilon());
2253  }
2254  }
2255 #ifndef NDEBUG
2256  catch( const SPxException& x )
2257  {
2258  std::string s = x.what();
2259  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2260 #else
2261  catch( const SPxException& )
2262  {
2263 #endif
2264  return SCIP_LPERROR;
2265  }
2266 
2267  return SCIP_OKAY;
2268 }
2269 
2270 /** changes a single coefficient */
2272  SCIP_LPI* lpi, /**< LP interface structure */
2273  int row, /**< row number of coefficient to change */
2274  int col, /**< column number of coefficient to change */
2275  SCIP_Real newval /**< new value of coefficient */
2276  )
2277 {
2278  SCIPdebugMessage("calling SCIPlpiChgCoef()\n");
2279 
2280  assert(lpi != NULL);
2281  assert(lpi->spx != NULL);
2282  assert(0 <= row && row < lpi->spx->nRows());
2283  assert(0 <= col && col < lpi->spx->nCols());
2284 
2285  invalidateSolution(lpi);
2286 
2287  assert( lpi->spx->preStrongbranchingBasisFreed() );
2288 
2289  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->changeElement(row, col, newval) );
2290 
2291  return SCIP_OKAY;
2292 }
2293 
2294 /** changes the objective sense */
2296  SCIP_LPI* lpi, /**< LP interface structure */
2297  SCIP_OBJSEN objsen /**< new objective sense */
2298  )
2299 {
2300  SCIPdebugMessage("calling SCIPlpiChgObjsen()\n");
2301 
2302  assert(lpi != NULL);
2303  assert(lpi->spx != NULL);
2304 
2305  invalidateSolution(lpi);
2306 
2307  assert( lpi->spx->preStrongbranchingBasisFreed() );
2308 
2309  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setSense(spxObjsen(objsen)) );
2310 
2311  return SCIP_OKAY;
2312 }
2313 
2314 /** changes objective values of columns in the LP */
2316  SCIP_LPI* lpi, /**< LP interface structure */
2317  int ncols, /**< number of columns to change objective value for */
2318  const int* ind, /**< column indices to change objective value for */
2319  const SCIP_Real* obj /**< new objective values for columns */
2320  )
2321 {
2322  int i;
2323 
2324  SCIPdebugMessage("calling SCIPlpiChgObj()\n");
2325 
2326  assert(lpi != NULL);
2327  assert(lpi->spx != NULL);
2328  assert(ind != NULL);
2329  assert(obj != NULL);
2330 
2331  invalidateSolution(lpi);
2332 
2333  assert( lpi->spx->preStrongbranchingBasisFreed() );
2334 
2335  try
2336  {
2337  for( i = 0; i < ncols; ++i )
2338  {
2339  assert(0 <= ind[i] && ind[i] < lpi->spx->nCols());
2340  lpi->spx->changeObj(ind[i], obj[i]);
2341  }
2342  }
2343 #ifndef NDEBUG
2344  catch( const SPxException& x )
2345  {
2346  std::string s = x.what();
2347  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2348 #else
2349  catch( const SPxException& )
2350  {
2351 #endif
2352  return SCIP_LPERROR;
2353  }
2354 
2355  return SCIP_OKAY;
2356 }
2357 
2358 /** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
2360  SCIP_LPI* lpi, /**< LP interface structure */
2361  int row, /**< row number to scale */
2362  SCIP_Real scaleval /**< scaling multiplier */
2363  )
2364 {
2365  SCIP_Real lhs;
2366  SCIP_Real rhs;
2367 
2368  SCIPdebugMessage("calling SCIPlpiScaleRow()\n");
2369 
2370  assert(lpi != NULL);
2371  assert(lpi->spx != NULL);
2372  assert(scaleval != 0.0);
2373 
2374  try
2375  {
2376  invalidateSolution(lpi);
2377 
2378  assert( lpi->spx->preStrongbranchingBasisFreed() );
2379 
2380  /* get the row vector and the row's sides */
2381  SVector rowvec = lpi->spx->rowVector(row);
2382  lhs = lpi->spx->lhs(row);
2383  rhs = lpi->spx->rhs(row);
2384 
2385  /* scale the row vector */
2386  rowvec *= scaleval;
2387 
2388  /* adjust the sides */
2389  if( lhs > -soplex::infinity )
2390  lhs *= scaleval;
2391  else if( scaleval < 0.0 )
2392  lhs = soplex::infinity;
2393  if( rhs < soplex::infinity )
2394  rhs *= scaleval;
2395  else if( scaleval < 0.0 )
2396  rhs = -soplex::infinity;
2397  if( scaleval < 0.0 )
2398  {
2399  SCIP_Real oldlhs = lhs;
2400  lhs = rhs;
2401  rhs = oldlhs;
2402  }
2403 
2404  /* create the new row */
2405  LPRow lprow(lhs, rowvec, rhs);
2406 
2407  /* change the row in the LP */
2408  lpi->spx->changeRow(row, lprow);
2409  assert(lpi->spx->lhs(row) <= lpi->spx->rhs(row));
2410  }
2411 #ifndef NDEBUG
2412  catch( const SPxException& x )
2413  {
2414  std::string s = x.what();
2415  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2416 #else
2417  catch( const SPxException& )
2418  {
2419 #endif
2420  return SCIP_LPERROR;
2421  }
2422 
2423  return SCIP_OKAY;
2424 }
2425 
2426 /** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
2427  * are divided by the scalar; for negative scalars, the column's bounds are switched
2428  */
2430  SCIP_LPI* lpi, /**< LP interface structure */
2431  int col, /**< column number to scale */
2432  SCIP_Real scaleval /**< scaling multiplier */
2433  )
2434 {
2435  SCIP_Real obj;
2436  SCIP_Real lb;
2437  SCIP_Real ub;
2438 
2439  SCIPdebugMessage("calling SCIPlpiScaleCol()\n");
2440 
2441  assert(lpi != NULL);
2442  assert(lpi->spx != NULL);
2443  assert(scaleval != 0.0);
2444 
2445  try
2446  {
2447  invalidateSolution(lpi);
2448 
2449  assert( lpi->spx->preStrongbranchingBasisFreed() );
2450 
2451  /* get the col vector and the col's bounds and objective value */
2452  SVector colvec = lpi->spx->colVector(col);
2453  obj = lpi->spx->obj(col);
2454  lb = lpi->spx->lower(col);
2455  ub = lpi->spx->upper(col);
2456 
2457  /* scale the col vector */
2458  colvec *= scaleval;
2459 
2460  /* scale the objective value */
2461  obj *= scaleval;
2462 
2463  /* adjust the bounds */
2464  if( lb > -soplex::infinity )
2465  lb /= scaleval;
2466  else if( scaleval < 0.0 )
2467  lb = soplex::infinity;
2468  if( ub < soplex::infinity )
2469  ub /= scaleval;
2470  else if( scaleval < 0.0 )
2471  ub = -soplex::infinity;
2472  if( scaleval < 0.0 )
2473  {
2474  SCIP_Real oldlb = lb;
2475  lb = ub;
2476  ub = oldlb;
2477  }
2478 
2479  /* create the new col (in LPCol's constructor, the upper bound is given first!) */
2480  LPCol lpcol(obj, colvec, ub, lb);
2481 
2482  /* change the col in the LP */
2483  lpi->spx->changeCol(col, lpcol);
2484  assert(lpi->spx->lower(col) <= lpi->spx->upper(col));
2485  }
2486 #ifndef NDEBUG
2487  catch( const SPxException& x )
2488  {
2489  std::string s = x.what();
2490  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
2491 #else
2492  catch( const SPxException& )
2493  {
2494 #endif
2495  return SCIP_LPERROR;
2496  }
2497 
2498  return SCIP_OKAY;
2499 }
2500 
2501 /**@} */
2502 
2503 
2504 
2505 
2506 /*
2507  * Data Accessing Methods
2508  */
2509 
2510 /**@name Data Accessing Methods */
2511 /**@{ */
2512 
2513 /** gets the number of rows in the LP */
2515  SCIP_LPI* lpi, /**< LP interface structure */
2516  int* nrows /**< pointer to store the number of rows */
2517  )
2518 {
2519  SCIPdebugMessage("calling SCIPlpiGetNRows()\n");
2520 
2521  assert(lpi != NULL);
2522  assert(lpi->spx != NULL);
2523  assert(nrows != NULL);
2524 
2525  *nrows = lpi->spx->nRows();
2526 
2527  return SCIP_OKAY;
2528 }
2529 
2530 /** gets the number of columns in the LP */
2532  SCIP_LPI* lpi, /**< LP interface structure */
2533  int* ncols /**< pointer to store the number of cols */
2534  )
2535 {
2536  SCIPdebugMessage("calling SCIPlpiGetNCols()\n");
2537 
2538  assert(lpi != NULL);
2539  assert(lpi->spx != NULL);
2540  assert(ncols != NULL);
2541 
2542  *ncols = lpi->spx->nCols();
2543 
2544  return SCIP_OKAY;
2545 }
2546 
2547 /** gets the number of nonzero elements in the LP constraint matrix */
2549  SCIP_LPI* lpi, /**< LP interface structure */
2550  int* nnonz /**< pointer to store the number of nonzeros */
2551  )
2552 {
2553  int i;
2554 
2555  SCIPdebugMessage("calling SCIPlpiGetNNonz()\n");
2556 
2557  assert(lpi != NULL);
2558  assert(lpi->spx != NULL);
2559  assert(nnonz != NULL);
2560 
2561  /* SoPlex has no direct method to return the number of nonzeros, so we have to count them manually */
2562  *nnonz = 0;
2563  if( lpi->spx->nRows() < lpi->spx->nCols() )
2564  {
2565  for( i = 0; i < lpi->spx->nRows(); ++i )
2566  (*nnonz) += lpi->spx->rowVector(i).size();
2567  }
2568  else
2569  {
2570  for( i = 0; i < lpi->spx->nCols(); ++i )
2571  (*nnonz) += lpi->spx->colVector(i).size();
2572  }
2573 
2574  return SCIP_OKAY;
2575 }
2576 
2577 /** gets columns from LP problem object; the arrays have to be large enough to store all values
2578  * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
2579  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2580  */
2582  SCIP_LPI* lpi, /**< LP interface structure */
2583  int firstcol, /**< first column to get from LP */
2584  int lastcol, /**< last column to get from LP */
2585  SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
2586  SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
2587  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2588  int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
2589  int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
2590  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2591  )
2592 {
2593  int i;
2594  int j;
2595 
2596  SCIPdebugMessage("calling SCIPlpiGetCols()\n");
2597 
2598  assert(lpi != NULL);
2599  assert(lpi->spx != NULL);
2600  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2601  assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
2602  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2603 
2604  if( lb != NULL )
2605  {
2606  const Vector& lbvec = lpi->spx->lower();
2607  const Vector& ubvec = lpi->spx->upper();
2608  for( i = firstcol; i <= lastcol; ++i )
2609  {
2610  lb[i-firstcol] = lbvec[i];
2611  ub[i-firstcol] = ubvec[i];
2612  }
2613  }
2614 
2615  if( nnonz != NULL )
2616  {
2617  *nnonz = 0;
2618  for( i = firstcol; i <= lastcol; ++i )
2619  {
2620  beg[i-firstcol] = *nnonz;
2621  const SVector& cvec = lpi->spx->colVector(i);
2622  for( j = 0; j < cvec.size(); ++j )
2623  {
2624  ind[*nnonz] = cvec.index(j);
2625  val[*nnonz] = cvec.value(j);
2626  (*nnonz)++;
2627  }
2628  }
2629  }
2630 
2631  return SCIP_OKAY;
2632 }
2633 
2634 /** gets rows from LP problem object; the arrays have to be large enough to store all values.
2635  * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
2636  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
2637  */
2639  SCIP_LPI* lpi, /**< LP interface structure */
2640  int firstrow, /**< first row to get from LP */
2641  int lastrow, /**< last row to get from LP */
2642  SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
2643  SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
2644  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
2645  int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
2646  int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
2647  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
2648  )
2649 {
2650  int i;
2651  int j;
2652 
2653  SCIPdebugMessage("calling SCIPlpiGetRows()\n");
2654 
2655  assert(lpi != NULL);
2656  assert(lpi->spx != NULL);
2657  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2658  assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
2659  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
2660 
2661  if( lhs != NULL )
2662  {
2663  const Vector& lhsvec = lpi->spx->lhs();
2664  const Vector& rhsvec = lpi->spx->rhs();
2665  for( i = firstrow; i <= lastrow; ++i )
2666  {
2667  lhs[i-firstrow] = lhsvec[i];
2668  rhs[i-firstrow] = rhsvec[i];
2669  }
2670  }
2671 
2672  if( nnonz != NULL )
2673  {
2674  *nnonz = 0;
2675  for( i = firstrow; i <= lastrow; ++i )
2676  {
2677  beg[i-firstrow] = *nnonz;
2678  const SVector& rvec = lpi->spx->rowVector(i);
2679  for( j = 0; j < rvec.size(); ++j )
2680  {
2681  ind[*nnonz] = rvec.index(j);
2682  val[*nnonz] = rvec.value(j);
2683  (*nnonz)++;
2684  }
2685  }
2686  }
2687 
2688  return SCIP_OKAY;
2689 }
2690 
2691 /** gets column names */
2693  SCIP_LPI* lpi, /**< LP interface structure */
2694  int firstcol, /**< first column to get name from LP */
2695  int lastcol, /**< last column to get name from LP */
2696  char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
2697  char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
2698  int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
2699  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2700  )
2701 {
2702  assert( lpi != NULL );
2703  assert( lpi->spx != NULL );
2704  assert( colnames != NULL || namestoragesize == 0 );
2705  assert( namestorage != NULL || namestoragesize == 0 );
2706  assert( namestoragesize >= 0 );
2707  assert( storageleft != NULL );
2708  assert( 0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols() );
2709 
2710  SCIPdebugMessage("getting column names %d to %d\n", firstcol, lastcol);
2711 
2712  lpi->spx->getColNames(firstcol, lastcol, colnames, namestorage, namestoragesize, storageleft);
2713 
2714  return SCIP_OKAY;
2715 }
2716 
2717 /** gets row names */
2719  SCIP_LPI* lpi, /**< LP interface structure */
2720  int firstrow, /**< first row to get name from LP */
2721  int lastrow, /**< last row to get name from LP */
2722  char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
2723  char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
2724  int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
2725  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
2726  )
2727 {
2728  assert( lpi != NULL );
2729  assert( lpi->spx != NULL );
2730  assert( rownames != NULL || namestoragesize == 0 );
2731  assert( namestorage != NULL || namestoragesize == 0 );
2732  assert( namestoragesize >= 0 );
2733  assert( storageleft != NULL );
2734  assert( 0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows() );
2735 
2736  SCIPdebugMessage("getting row names %d to %d\n", firstrow, lastrow);
2737 
2738  lpi->spx->getRowNames(firstrow, lastrow, rownames, namestorage, namestoragesize, storageleft);
2739 
2740  return SCIP_OKAY;
2741 }
2742 
2743 /** gets objective sense of the LP */
2745  SCIP_LPI* lpi, /**< LP interface structure */
2746  SCIP_OBJSEN* objsen /**< pointer to store objective sense */
2747  )
2748 {
2749  SCIPdebugMessage("calling SCIPlpiGetObjsen()\n");
2750 
2751  assert(lpi != NULL);
2752  assert(lpi->spx != NULL);
2753  assert(objsen != NULL);
2754 
2755  *objsen = (lpi->spx->getSense() == SPxLP::MINIMIZE) ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE;
2756 
2757  return SCIP_OKAY;
2758 }
2759 
2760 /** gets objective coefficients from LP problem object */
2762  SCIP_LPI* lpi, /**< LP interface structure */
2763  int firstcol, /**< first column to get objective coefficient for */
2764  int lastcol, /**< last column to get objective coefficient for */
2765  SCIP_Real* vals /**< array to store objective coefficients */
2766  )
2767 {
2768  int i;
2769 
2770  SCIPdebugMessage("calling SCIPlpiGetObj()\n");
2771 
2772  assert(lpi != NULL);
2773  assert(lpi->spx != NULL);
2774  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2775  assert(vals != NULL);
2776 
2777  for( i = firstcol; i <= lastcol; ++i )
2778  vals[i-firstcol] = lpi->spx->obj(i);
2779 
2780  return SCIP_OKAY;
2781 }
2782 
2783 /** gets current bounds from LP problem object */
2785  SCIP_LPI* lpi, /**< LP interface structure */
2786  int firstcol, /**< first column to get objective value for */
2787  int lastcol, /**< last column to get objective value for */
2788  SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
2789  SCIP_Real* ubs /**< array to store upper bound values, or NULL */
2790  )
2791 {
2792  int i;
2793 
2794  SCIPdebugMessage("calling SCIPlpiGetBounds()\n");
2795 
2796  assert(lpi != NULL);
2797  assert(lpi->spx != NULL);
2798  assert(0 <= firstcol && firstcol <= lastcol && lastcol < lpi->spx->nCols());
2799 
2800  for( i = firstcol; i <= lastcol; ++i )
2801  {
2802  if( lbs != NULL )
2803  lbs[i-firstcol] = lpi->spx->lower(i);
2804  if( ubs != NULL )
2805  ubs[i-firstcol] = lpi->spx->upper(i);
2806  }
2807 
2808  return SCIP_OKAY;
2809 }
2810 
2811 /** gets current row sides from LP problem object */
2813  SCIP_LPI* lpi, /**< LP interface structure */
2814  int firstrow, /**< first row to get sides for */
2815  int lastrow, /**< last row to get sides for */
2816  SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2817  SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2818  )
2819 {
2820  int i;
2821 
2822  SCIPdebugMessage("calling SCIPlpiGetSides()\n");
2823 
2824  assert(lpi != NULL);
2825  assert(lpi->spx != NULL);
2826  assert(0 <= firstrow && firstrow <= lastrow && lastrow < lpi->spx->nRows());
2827 
2828  for( i = firstrow; i <= lastrow; ++i )
2829  {
2830  if( lhss != NULL )
2831  lhss[i-firstrow] = lpi->spx->lhs(i);
2832  if( rhss != NULL )
2833  rhss[i-firstrow] = lpi->spx->rhs(i);
2834  }
2835 
2836  return SCIP_OKAY;
2837 }
2838 
2839 /** gets a single coefficient */
2841  SCIP_LPI* lpi, /**< LP interface structure */
2842  int row, /**< row number of coefficient */
2843  int col, /**< column number of coefficient */
2844  SCIP_Real* val /**< pointer to store the value of the coefficient */
2845  )
2846 {
2847  SCIPdebugMessage("calling SCIPlpiGetCoef()\n");
2848 
2849  assert(lpi != NULL);
2850  assert(lpi->spx != NULL);
2851  assert(0 <= col && col < lpi->spx->nCols());
2852  assert(0 <= row && row < lpi->spx->nRows());
2853  assert(val != NULL);
2854 
2855  *val = lpi->spx->colVector(col)[row];
2856 
2857  return SCIP_OKAY;
2858 }
2859 
2860 /**@} */
2861 
2862 
2863 
2864 
2865 /*
2866  * Solving Methods
2867  */
2868 
2869 /**@name Solving Methods */
2870 /**@{ */
2871 
2872 /** solves LP -- used for both, primal and dual simplex, because SoPlex doesn't distinct the two cases */
2873 static
2875  SCIP_LPI* lpi, /**< LP interface structure */
2876  SPxSolver::Representation rep, /**< basis representation */
2877  SPxSolver::Type type /**< algorithm type */
2878  )
2879 {
2880  assert( lpi != NULL );
2881  assert( lpi->spx != NULL );
2882  assert( rep == SPxSolver::ROW || rep == SPxSolver::COLUMN );
2883  assert( type == SPxSolver::ENTER || type == SPxSolver::LEAVE );
2884 
2885  SCIPdebugMessage("calling SoPlex solve(): %d cols, %d rows, rep=%s\n", lpi->spx->nCols(), lpi->spx->nRows(),
2886  rep == SPxSolver::COLUMN ? "column" : "row");
2887 
2888  invalidateSolution(lpi);
2889 
2890  assert( lpi->spx->preStrongbranchingBasisFreed() );
2891 
2892  /* set basis representation and algorithm type */
2893  lpi->spx->setRep(rep);
2894  lpi->spx->setType(type);
2895 
2896 #ifdef SCIP_WITH_LPSCHECK
2897  lpi->spx->setDoubleCheck(CHECK_SPXSOLVE);
2898 #endif
2899 
2900  SPxSolver::Status status = lpi->spx->solve();
2901  SCIPdebugMessage(" -> SoPlex status: %d, basis status: %d\n", lpi->spx->getStatus(), lpi->spx->basis().status());
2902  lpi->solved = TRUE;
2903 
2904  switch( status )
2905  {
2906  case SPxSolver::ABORT_TIME:
2907  case SPxSolver::ABORT_ITER:
2908  case SPxSolver::ABORT_VALUE:
2909  case SPxSolver::SINGULAR:
2910  case SPxSolver::REGULAR:
2911  case SPxSolver::UNKNOWN:
2912  case SPxSolver::OPTIMAL:
2913  case SPxSolver::UNBOUNDED:
2914  case SPxSolver::INFEASIBLE:
2915  return SCIP_OKAY;
2916  default:
2917  return SCIP_LPERROR;
2918  } /*lint !e788*/
2919 }
2920 
2921 /** calls primal simplex to solve the LP */
2923  SCIP_LPI* lpi /**< LP interface structure */
2924  )
2926  SCIPdebugMessage("calling SCIPlpiSolvePrimal()\n");
2927 
2928  SCIP_RETCODE retcode;
2929  SCIP_Bool rowrep;
2930 
2931  assert(lpi != NULL);
2932  assert(lpi->spx != NULL);
2933 
2934  /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
2935  factor 1.1 for switching back to column representation */
2936  if( lpi->rowrepswitch >= 0 )
2937  {
2938  rowrep = lpi->spx->rep() == SPxSolver::ROW;
2939 
2940  if( !rowrep )
2941  rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
2942  else
2943  rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
2944  }
2945  else
2946  rowrep = FALSE;
2947 
2948  /* SoPlex doesn't distinct between the primal and dual simplex; however
2949  * we can force SoPlex to start with the desired method:
2950  * If the representation is COLUMN:
2951  * - ENTER = PRIMAL
2952  * - LEAVE = DUAL
2953  *
2954  * If the representation is ROW:
2955  * - ENTER = DUAL
2956  * - LEAVE = PRIMAL
2957  */
2958  retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::LEAVE) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::ENTER);
2959  assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
2960  assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
2961 
2962  return retcode;
2963 }
2964 
2965 /** calls dual simplex to solve the LP */
2967  SCIP_LPI* lpi /**< LP interface structure */
2968  )
2970  SCIPdebugMessage("calling SCIPlpiSolveDual()\n");
2971 
2972  SCIP_RETCODE retcode;
2973  SCIP_Bool rowrep;
2974 
2975  assert(lpi != NULL);
2976  assert(lpi->spx != NULL);
2977 
2978  /* first decide if we want to switch the basis representation; in order to avoid oscillatory behaviour, we add the
2979  factor 1.1 for switching back to column representation */
2980  if( lpi->rowrepswitch >= 0 )
2981  {
2982  rowrep = lpi->spx->rep() == SPxSolver::ROW;
2983 
2984  if( !rowrep )
2985  rowrep = lpi->spx->nRows() > lpi->spx->nCols() * (lpi->rowrepswitch);
2986  else
2987  rowrep = lpi->spx->nRows() * 1.1 > lpi->spx->nCols() * (lpi->rowrepswitch);
2988  }
2989  else
2990  rowrep = FALSE;
2991 
2992  /* SoPlex doesn't distinct between the primal and dual simplex; however
2993  * we can force SoPlex to start with the desired method:
2994  * If the representation is COLUMN:
2995  * - ENTER = PRIMAL
2996  * - LEAVE = DUAL
2997  *
2998  * If the representation is ROW:
2999  * - ENTER = DUAL
3000  * - LEAVE = PRIMAL
3001  */
3002  retcode = rowrep ? spxSolve(lpi, SPxSolver::ROW, SPxSolver::ENTER) : spxSolve(lpi, SPxSolver::COLUMN, SPxSolver::LEAVE);
3003  assert(!rowrep || lpi->spx->rep() == SPxSolver::ROW);
3004  assert(rowrep || lpi->spx->rep() == SPxSolver::COLUMN);
3005 
3006  return retcode;
3007 }
3008 
3009 /** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
3011  SCIP_LPI* lpi, /**< LP interface structure */
3012  SCIP_Bool crossover /**< perform crossover */
3013  )
3014 { /*lint --e{715}*/
3015  assert(lpi != NULL);
3016  assert(lpi->spx != NULL);
3017 
3018  SCIPdebugMessage("calling SCIPlpiSolveBarrier()\n");
3019 
3020  /* SoPlex does not support barrier (yet) */
3021  SCIPerrorMessage("SCIPlpiSolveBarrier() not supported by SoPlex\n");
3022  return SCIP_INVALIDCALL;
3023 }
3024 
3025 /** start strong branching - call before any strongbranching */
3027  SCIP_LPI* lpi /**< LP interface structure */
3028  )
3030  assert(lpi != NULL);
3031  assert(lpi->spx != NULL);
3032 
3033  assert( lpi->spx->preStrongbranchingBasisFreed() );
3034  lpi->spx->savePreStrongbranchingBasis();
3035 
3036  return SCIP_OKAY;
3037 }
3038 
3039 /** end strong branching - call after any strongbranching */
3041  SCIP_LPI* lpi /**< LP interface structure */
3042  )
3044  assert(lpi != NULL);
3045  assert(lpi->spx != NULL);
3046 
3047  assert( ! lpi->spx->preStrongbranchingBasisFreed() );
3048  lpi->spx->restorePreStrongbranchingBasis();
3049  lpi->spx->freePreStrongbranchingBasis();
3050 
3051  return SCIP_OKAY;
3052 }
3053 
3054 /** performs strong branching iterations on one arbitrary candidate */
3055 static
3057  SCIP_LPI* lpi, /**< LP interface structure */
3058  int col, /**< column to apply strong branching on */
3059  SCIP_Real psol, /**< current primal solution value of column */
3060  int itlim, /**< iteration limit for strong branchings */
3061  SCIP_Real* down, /**< stores dual bound after branching column down */
3062  SCIP_Real* up, /**< stores dual bound after branching column up */
3063  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3064  * otherwise, it can only be used as an estimate value */
3065  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3066  * otherwise, it can only be used as an estimate value */
3067  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3068  )
3069 {
3070  SPxSCIP* spx;
3071  SPxSolver::Status status;
3072  SCIP_Real oldlb;
3073  SCIP_Real oldub;
3074  SCIP_Real newlb;
3075  SCIP_Real newub;
3076  bool fromparentbasis;
3077  bool error;
3078  int oldItlim;
3079 
3080  SCIPdebugMessage("calling SCIPlpiStrongbranch() on variable %d (%d iterations)\n", col, itlim);
3081 
3082  assert(lpi != NULL);
3083  assert(lpi->spx != NULL);
3084  /* assert(down != NULL);
3085  * assert(up != NULL); temporary hack for cloud branching */
3086  assert(downvalid != NULL);
3087  assert(upvalid != NULL);
3088 
3089  spx = lpi->spx;
3090  status = SPxSolver::UNKNOWN;
3091  fromparentbasis = false;
3092  error = false;
3093  oldItlim = spx->getIterationLimit();
3094 
3095  /* get current bounds of column */
3096  oldlb = spx->lower(col);
3097  oldub = spx->upper(col);
3098 
3099  *downvalid = FALSE;
3100  *upvalid = FALSE;
3101 
3102  if( iter != NULL )
3103  *iter = 0;
3104 
3105  /* set the algorithm type to use dual simplex */
3106  lpi->spx->setType( lpi->spx->rep() == SPxSolver::ROW ? SPxSolver::ENTER : SPxSolver::LEAVE);
3107 
3108  /* down branch */
3109  newub = EPSCEIL(psol-1.0, lpi->spx->feastol());
3110  if( newub >= oldlb - 0.5 && down != NULL )
3111  {
3112  SCIPdebugMessage("strong branching down on x%d (%g) with %d iterations\n", col, psol, itlim);
3113 
3114  spx->changeUpper(col, newub);
3115  assert(spx->lower(col) <= spx->upper(col));
3116 
3117  spx->setIterationLimit(itlim);
3118  do
3119  {
3120 #ifdef SCIP_WITH_LPSCHECK
3121  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3122 #endif
3123  status = spx->solve();
3124  SCIPdebugMessage(" --> Terminate with status %d\n", status);
3125  switch( status )
3126  {
3127  case SPxSolver::OPTIMAL:
3128  *down = spx->value();
3129  *downvalid = TRUE;
3130  SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3131  break;
3132  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3133  case SPxSolver::ABORT_ITER:
3134  case SPxSolver::ABORT_CYCLING:
3135  *down = spx->value();
3136  break;
3137  case SPxSolver::ABORT_VALUE:
3138  case SPxSolver::INFEASIBLE:
3139  *down = spx->terminationValue();
3140  *downvalid = TRUE;
3141  break;
3142  default:
3143  error = true;
3144  break;
3145  } /*lint !e788*/
3146  if( iter != NULL )
3147  (*iter) += spx->iterations();
3148 
3149 #ifdef STRONGBRANCH_RESTOREBASIS
3150  /* we restore the pre-strong-branching basis by default (and don't solve again) */
3151  assert( ! spx->preStrongbranchingBasisFreed() );
3152  spx->restorePreStrongbranchingBasis();
3153  fromparentbasis = false;
3154 #else
3155  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3156  * pre-strong-branching basis and try again with reduced iteration limit */
3157  if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3158  {
3159  SCIPdebugMessage(" --> Repeat strong branching down with %d iterations after restoring basis\n", itlim - spx->iterations());
3160  spx->setIterationLimit(itlim - spx->iterations());
3161  spx->restorePreStrongbranchingBasis();
3162  fromparentbasis = true;
3163  error = false;
3164  }
3165  /* otherwise don't solve again */
3166  else
3167  fromparentbasis = false;
3168 #endif
3169  }
3170  while( fromparentbasis );
3171 
3172  spx->changeUpper(col, oldub);
3173  assert(spx->lower(col) <= spx->upper(col));
3174  }
3175  else if( down != NULL )
3176  {
3177  *down = spx->terminationValue();
3178  *downvalid = TRUE;
3179  }
3180  else
3181  *downvalid = TRUE;
3182 
3183  /* up branch */
3184  if( !error )
3185  {
3186  newlb = EPSFLOOR(psol+1.0, lpi->spx->feastol());
3187  if( newlb <= oldub + 0.5 && up != NULL )
3188  {
3189  SCIPdebugMessage("strong branching up on x%d (%g) with %d iterations\n", col, psol, itlim);
3190 
3191  spx->changeLower(col, newlb);
3192  assert(spx->lower(col) <= spx->upper(col));
3193 
3194  spx->setIterationLimit(itlim);
3195  do
3196  {
3197 #ifdef SCIP_WITH_LPSCHECK
3198  spx->setDoubleCheck(CHECK_SPXSTRONGBRANCH);
3199 #endif
3200  status = spx->solve();
3201  SCIPdebugMessage(" --> Terminate with status %d\n", status);
3202  switch( status )
3203  {
3204  case SPxSolver::OPTIMAL:
3205  *up = spx->value();
3206  *upvalid = TRUE;
3207  SCIPdebugMessage(" --> Terminate with value %f\n", spx->value());
3208  break;
3209  case SPxSolver::ABORT_TIME: /* SoPlex does not return a proven dual bound, if it is aborted */
3210  case SPxSolver::ABORT_ITER:
3211  case SPxSolver::ABORT_CYCLING:
3212  *up = spx->value();
3213  break;
3214  case SPxSolver::ABORT_VALUE:
3215  case SPxSolver::INFEASIBLE:
3216  *up = spx->terminationValue();
3217  *upvalid = TRUE;
3218  break;
3219  default:
3220  error = true;
3221  break;
3222  } /*lint !e788*/
3223  if( iter != NULL )
3224  (*iter) += spx->iterations();
3225 
3226 #ifdef STRONGBRANCH_RESTOREBASIS
3227  /* we restore the pre-strong-branching basis by default (and don't solve again) */
3228  assert( ! spx->preStrongbranchingBasisFreed() );
3229  spx->restorePreStrongbranchingBasis();
3230  fromparentbasis = false;
3231 #else
3232  /* if cycling or singular basis occured and we started not from the pre-strong-branching basis, then we restore the
3233  * pre-strong-branching basis and try again with reduced iteration limit */
3234  if( (status == SPxSolver::ABORT_CYCLING || status == SPxSolver::SINGULAR) && !fromparentbasis && spx->iterations() < itlim )
3235  {
3236  SCIPdebugMessage(" --> Repeat strong branching up with %d iterations after restoring basis\n", itlim - spx->iterations());
3237  spx->restorePreStrongbranchingBasis();
3238  spx->setIterationLimit(itlim - spx->iterations());
3239  error = false;
3240  fromparentbasis = true;
3241  }
3242  /* otherwise don't solve again */
3243  else
3244  fromparentbasis = false;
3245 #endif
3246  }
3247  while( fromparentbasis );
3248 
3249  spx->changeLower(col, oldlb);
3250  assert(spx->lower(col) <= spx->upper(col));
3251  }
3252  else if( up != NULL )
3253  {
3254  *up = spx->terminationValue();
3255  *upvalid = TRUE;
3256  }
3257  else
3258  *upvalid = TRUE;
3259  }
3260 
3261  /* reset old iteration limit */
3262  spx->setIterationLimit(oldItlim);
3263 
3264  if( error )
3265  {
3266  SCIPdebugMessage("SCIPlpiStrongbranch() returned SoPlex status %d\n", int(status));
3267  return SCIP_LPERROR;
3268  }
3269 
3270  return SCIP_OKAY;
3271 }
3272 
3273 /** performs strong branching iterations on one @b fractional candidate */
3275  SCIP_LPI* lpi, /**< LP interface structure */
3276  int col, /**< column to apply strong branching on */
3277  SCIP_Real psol, /**< fractional current primal solution value of column */
3278  int itlim, /**< iteration limit for strong branchings */
3279  SCIP_Real* down, /**< stores dual bound after branching column down */
3280  SCIP_Real* up, /**< stores dual bound after branching column up */
3281  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3282  * otherwise, it can only be used as an estimate value */
3283  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3284  * otherwise, it can only be used as an estimate value */
3285  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3286  )
3287 {
3288  SCIP_RETCODE retcode;
3289 
3290  /* pass call on to lpiStrongbranch() */
3291  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
3292 
3293  /* pass SCIP_LPERROR to SCIP without a back trace */
3294  if( retcode == SCIP_LPERROR )
3295  return SCIP_LPERROR;
3296 
3297  /* evaluate retcode */
3298  SCIP_CALL( retcode );
3299 
3300  return SCIP_OKAY;
3301 }
3302 
3303 /** performs strong branching iterations on given @b fractional candidates */
3305  SCIP_LPI* lpi, /**< LP interface structure */
3306  int* cols, /**< columns to apply strong branching on */
3307  int ncols, /**< number of columns */
3308  SCIP_Real* psols, /**< fractional current primal solution values of columns */
3309  int itlim, /**< iteration limit for strong branchings */
3310  SCIP_Real* down, /**< stores dual bounds after branching columns down */
3311  SCIP_Real* up, /**< stores dual bounds after branching columns up */
3312  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3313  * otherwise, they can only be used as an estimate values */
3314  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3315  * otherwise, they can only be used as an estimate values */
3316  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3317  )
3318 {
3319  SCIP_RETCODE retcode;
3320 
3321  assert( cols != NULL );
3322  assert( psols != NULL );
3323  assert( down != NULL );
3324  assert( up != NULL );
3325  assert( downvalid != NULL );
3326  assert( upvalid != NULL );
3327  assert( down != NULL );
3328 
3329  if ( iter != NULL )
3330  *iter = 0;
3331 
3332  for (int j = 0; j < ncols; ++j)
3333  {
3334  /* pass call on to lpiStrongbranch() */
3335  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3336 
3337  /* pass SCIP_LPERROR to SCIP without a back trace */
3338  if( retcode == SCIP_LPERROR )
3339  return SCIP_LPERROR;
3340 
3341  /* evaluate retcode */
3342  SCIP_CALL( retcode );
3343  }
3344  return SCIP_OKAY;
3345 }
3346 
3347 /** performs strong branching iterations on one candidate with @b integral value */
3349  SCIP_LPI* lpi, /**< LP interface structure */
3350  int col, /**< column to apply strong branching on */
3351  SCIP_Real psol, /**< current integral primal solution value of column */
3352  int itlim, /**< iteration limit for strong branchings */
3353  SCIP_Real* down, /**< stores dual bound after branching column down */
3354  SCIP_Real* up, /**< stores dual bound after branching column up */
3355  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3356  * otherwise, it can only be used as an estimate value */
3357  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3358  * otherwise, it can only be used as an estimate value */
3359  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3360  )
3361 {
3362  SCIP_RETCODE retcode;
3363 
3364  /* pass call on to lpiStrongbranch() */
3365  retcode = lpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter);
3366 
3367  /* pass SCIP_LPERROR to SCIP without a back trace */
3368  if( retcode == SCIP_LPERROR )
3369  return SCIP_LPERROR;
3370 
3371  /* evaluate retcode */
3372  SCIP_CALL( retcode );
3373 
3374  return SCIP_OKAY;
3375 }
3376 
3377 /** performs strong branching iterations on given candidates with @b integral values */
3379  SCIP_LPI* lpi, /**< LP interface structure */
3380  int* cols, /**< columns to apply strong branching on */
3381  int ncols, /**< number of columns */
3382  SCIP_Real* psols, /**< current integral primal solution values of columns */
3383  int itlim, /**< iteration limit for strong branchings */
3384  SCIP_Real* down, /**< stores dual bounds after branching columns down */
3385  SCIP_Real* up, /**< stores dual bounds after branching columns up */
3386  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3387  * otherwise, they can only be used as an estimate values */
3388  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3389  * otherwise, they can only be used as an estimate values */
3390  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3391  )
3392 {
3393  SCIP_RETCODE retcode;
3394 
3395  assert( cols != NULL );
3396  assert( psols != NULL );
3397  assert( down != NULL );
3398  assert( up != NULL );
3399  assert( downvalid != NULL );
3400  assert( upvalid != NULL );
3401  assert( down != NULL );
3402 
3403  if ( iter != NULL )
3404  *iter = 0;
3405 
3406  for (int j = 0; j < ncols; ++j)
3407  {
3408  /* pass call on to lpiStrongbranch() */
3409  retcode = lpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter);
3410 
3411  /* pass SCIP_LPERROR to SCIP without a back trace */
3412  if( retcode == SCIP_LPERROR )
3413  return SCIP_LPERROR;
3414 
3415  /* evaluate retcode */
3416  SCIP_CALL( retcode );
3417  }
3418 
3419  return SCIP_OKAY;
3420 }
3421 /**@} */
3422 
3423 
3424 
3425 
3426 /*
3427  * Solution Information Methods
3428  */
3429 
3430 /**@name Solution Information Methods */
3431 /**@{ */
3432 
3433 /** returns whether a solve method was called after the last modification of the LP */
3435  SCIP_LPI* lpi /**< LP interface structure */
3436  )
3438  assert(lpi != NULL);
3439 
3440  return lpi->solved;
3441 }
3442 
3443 /** gets information about primal and dual feasibility of the current LP solution
3444  *
3445  * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
3446  * returns true. If the LP is changed, this information might be invalidated.
3447  *
3448  * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
3449  * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
3450  * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
3451  * the problem might actually be feasible).
3452  */
3454  SCIP_LPI* lpi, /**< LP interface structure */
3455  SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
3456  SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
3457  )
3458 {
3459  SCIPdebugMessage("calling SCIPlpiGetSolFeasibility()\n");
3460 
3461  assert(lpi != NULL);
3462  assert(primalfeasible != NULL);
3463  assert(dualfeasible != NULL);
3464 
3465  *primalfeasible = SCIPlpiIsPrimalFeasible(lpi);
3466  *dualfeasible = SCIPlpiIsDualFeasible(lpi);
3467 
3468  return SCIP_OKAY;
3469 }
3470 
3471 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
3472  * this does not necessarily mean, that the solver knows and can return the primal ray
3473  */
3475  SCIP_LPI* lpi /**< LP interface structure */
3476  )
3478  SCIPdebugMessage("calling SCIPlpiExistsPrimalRay()\n");
3479 
3480  assert(lpi != NULL);
3481  assert(lpi->spx != NULL);
3482 
3483  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3484 }
3485 
3486 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
3487  * and the solver knows and can return the primal ray
3488  */
3490  SCIP_LPI* lpi /**< LP interface structure */
3491  )
3493  SCIPdebugMessage("calling SCIPlpiHasPrimalRay()\n");
3494 
3495  assert(lpi != NULL);
3496  assert(lpi->spx != NULL);
3497 
3498 #if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3499  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3500 #else
3501  return FALSE;
3502 #endif
3503 }
3504 
3505 /** returns TRUE iff LP is proven to be primal unbounded */
3507  SCIP_LPI* lpi /**< LP interface structure */
3508  )
3510  SCIPdebugMessage("calling SCIPlpiIsPrimalUnbounded()\n");
3511 
3512  assert(lpi != NULL);
3513  assert(lpi->spx != NULL);
3514 
3515  assert(lpi->spx->getStatus() != SPxSolver::UNBOUNDED || lpi->spx->basis().status() == SPxBasis::UNBOUNDED);
3516 
3517  /* if SoPlex returns unbounded, this may only mean that an unbounded ray is available, not necessarily a primal
3518  * feasible point; hence we have to check the perturbation
3519  */
3520  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED && !lpi->spx->isPerturbed());
3521 }
3522 
3523 /** returns TRUE iff LP is proven to be primal infeasible */
3525  SCIP_LPI* lpi /**< LP interface structure */
3526  )
3528  SCIPdebugMessage("calling SCIPlpiIsPrimalInfeasible()\n");
3529 
3530  assert(lpi != NULL);
3531  assert(lpi->spx != NULL);
3532 
3533  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3534 }
3535 
3536 /** returns TRUE iff LP is proven to be primal feasible */
3538  SCIP_LPI* lpi /**< LP interface structure */
3539  )
3541  SPxBasis::SPxStatus basestatus;
3542 
3543  SCIPdebugMessage("calling SCIPlpiIsPrimalFeasible()\n");
3544 
3545  assert(lpi != NULL);
3546  assert(lpi->spx != NULL);
3547 
3548  basestatus = lpi->spx->basis().status();
3549 
3550  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3551  * still return true as long as perturbation plus violation is within tolerances
3552  */
3553  assert(basestatus == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3554 
3555  return basestatus == SPxBasis::OPTIMAL ||
3556  ((basestatus == SPxBasis::PRIMAL || basestatus == SPxBasis::UNBOUNDED) && !lpi->spx->isPerturbed());
3557 }
3558 
3559 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3560  * this does not necessarily mean, that the solver knows and can return the dual ray
3561  */
3563  SCIP_LPI* lpi /**< LP interface structure */
3564  )
3566  SCIPdebugMessage("calling SCIPlpiExistsDualRay()\n");
3567 
3568  assert(lpi != NULL);
3569  assert(lpi->spx != NULL);
3570 
3571  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3572 }
3573 
3574 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3575  * and the solver knows and can return the dual ray
3576  */
3578  SCIP_LPI* lpi /**< LP interface structure */
3579  )
3581  SCIPdebugMessage("calling SCIPlpiHasDualRay()\n");
3582 
3583  assert(lpi != NULL);
3584  assert(lpi->spx != NULL);
3585 
3586  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE);
3587 }
3588 
3589 /** returns TRUE iff LP is dual unbounded */
3591  SCIP_LPI* lpi /**< LP interface structure */
3592  )
3594  SCIPdebugMessage("calling SCIPlpiIsDualUnbounded()\n");
3595 
3596  assert(lpi != NULL);
3597  assert(lpi->spx != NULL);
3598 
3599  return (lpi->spx->getStatus() == SPxSolver::INFEASIBLE && lpi->spx->basis().status() == SPxBasis::DUAL
3600  && !lpi->spx->isPerturbed());
3601 }
3602 
3603 /** returns TRUE iff LP is dual infeasible */
3605  SCIP_LPI* lpi /**< LP interface structure */
3606  )
3608  SCIPdebugMessage("calling SCIPlpiIsDualInfeasible()\n");
3609 
3610  assert(lpi != NULL);
3611  assert(lpi->spx != NULL);
3612 
3613  return (lpi->spx->getStatus() == SPxSolver::UNBOUNDED);
3614 }
3615 
3616 /** returns TRUE iff LP is proven to be dual feasible */
3618  SCIP_LPI* lpi /**< LP interface structure */
3619  )
3621  SCIPdebugMessage("calling SCIPlpiIsDualFeasible()\n");
3622 
3623  assert(lpi != NULL);
3624  assert(lpi->spx != NULL);
3625 
3626  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3627  * still return true as long as perturbation plus violation is within tolerances
3628  */
3629  assert(lpi->spx->basis().status() == SPxBasis::OPTIMAL || lpi->spx->getStatus() != SPxSolver::OPTIMAL);
3630 
3631  return (lpi->spx->basis().status() == SPxBasis::OPTIMAL) ||
3632  (lpi->spx->basis().status() == SPxBasis::DUAL && !lpi->spx->isPerturbed());
3633 }
3634 
3635 /** returns TRUE iff LP was solved to optimality */
3637  SCIP_LPI* lpi /**< LP interface structure */
3638  )
3640  SCIPdebugMessage("calling SCIPlpiIsOptimal()\n");
3641 
3642  assert(lpi != NULL);
3643  assert(lpi->spx != NULL);
3644  assert((lpi->spx->basis().status() == SPxBasis::OPTIMAL)
3646 
3647  /* note that the solver status may be ABORT_VALUE and the basis status optimal; if we are optimal, isPerturbed() may
3648  * still return true as long as perturbation plus violation is within tolerances
3649  */
3650  return (lpi->spx->basis().status() == SPxBasis::OPTIMAL);
3651 }
3652 
3653 /** returns TRUE iff current LP solution is stable
3654  *
3655  * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3656  * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3657  * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3658  * SCIPlpiIsStable() should return false.
3659  */
3661  SCIP_LPI* lpi /**< LP interface structure */
3662  )
3664  SCIPdebugMessage("calling SCIPlpiIsStable()\n");
3665 
3666  assert(lpi != NULL);
3667  assert(lpi->spx != NULL);
3668 
3669 #if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3670  /* If the condition number of the basis should be checked, everything above the specified threshold is counted
3671  * as instable.
3672  */
3673  if( lpi->checkcondition && (SCIPlpiIsOptimal(lpi) || SCIPlpiIsObjlimExc(lpi)) )
3674  {
3675 #ifndef NDEBUG
3676  SCIP_RETCODE retcode;
3677 #endif
3678  SCIP_Real kappa;
3679 
3680 #ifndef NDEBUG
3681  retcode =
3682 #endif
3684  assert(kappa != SCIP_INVALID); /*lint !e777*/
3685  assert(retcode == SCIP_OKAY);
3686 
3687  if( kappa > lpi->conditionlimit )
3688  return FALSE;
3689  }
3690 #endif
3691 
3692  return (lpi->spx->getStatus() != SPxSolver::ERROR && lpi->spx->getStatus() != SPxSolver::SINGULAR);
3693 }
3694 
3695 /** returns TRUE iff the objective limit was reached */
3697  SCIP_LPI* lpi /**< LP interface structure */
3698  )
3700  SCIPdebugMessage("calling SCIPlpiIsObjlimExc()\n");
3701 
3702  assert(lpi != NULL);
3703  assert(lpi->spx != NULL);
3704 
3705  return (lpi->spx->getStatus() == SPxSolver::ABORT_VALUE);
3706 }
3707 
3708 /** returns TRUE iff the iteration limit was reached */
3710  SCIP_LPI* lpi /**< LP interface structure */
3711  )
3713  SCIPdebugMessage("calling SCIPlpiIsIterlimExc()\n");
3714 
3715  assert(lpi != NULL);
3716  assert(lpi->spx != NULL);
3717 
3718  return (lpi->spx->getStatus() == SPxSolver::ABORT_ITER);
3719 }
3720 
3721 /** returns TRUE iff the time limit was reached */
3723  SCIP_LPI* lpi /**< LP interface structure */
3724  )
3726  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3727 
3728  assert(lpi != NULL);
3729  assert(lpi->spx != NULL);
3730 
3731  return (lpi->spx->getStatus() == SPxSolver::ABORT_TIME);
3732 }
3733 
3734 /** returns the internal solution status of the solver */
3736  SCIP_LPI* lpi /**< LP interface structure */
3737  )
3739  SCIPdebugMessage("calling SCIPlpiIsTimelimExc()\n");
3740 
3741  assert(lpi != NULL);
3742  assert(lpi->spx != NULL);
3743 
3744  return static_cast<int>(lpi->spx->getStatus());
3745 }
3746 
3747 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3749  SCIP_LPI* lpi, /**< LP interface structure */
3750  SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3751  )
3752 { /*lint --e{715}*/
3753  SCIPdebugMessage("calling SCIPlpiIgnoreInstability()\n");
3754 
3755  assert(lpi != NULL);
3756  assert(lpi->spx != NULL);
3757  assert(success != NULL);
3758 
3759  /* instable situations cannot be ignored */
3760  *success = FALSE;
3761 
3762  return SCIP_OKAY;
3763 }
3764 
3765 /** gets objective value of solution */
3767  SCIP_LPI* lpi, /**< LP interface structure */
3768  SCIP_Real* objval /**< stores the objective value */
3769  )
3770 {
3771  SCIPdebugMessage("calling SCIPlpiGetObjval()\n");
3772 
3773  assert(lpi != NULL);
3774  assert(lpi->spx != NULL);
3775  assert(objval != NULL);
3776 
3777  *objval = lpi->spx->value();
3778 
3779  return SCIP_OKAY;
3780 }
3781 
3782 /** gets primal and dual solution vectors for feasible LPs
3783  *
3784  * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3785  * SCIPlpiIsOptimal() returns true.
3786  */
3788  SCIP_LPI* lpi, /**< LP interface structure */
3789  SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3790  SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3791  SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3792  SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3793  SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3794  )
3795 {
3796  SCIPdebugMessage("calling SCIPlpiGetSol()\n");
3797 
3798  assert(lpi != NULL);
3799  assert(lpi->spx != NULL);
3800 
3801  if( objval != NULL )
3802  *objval = lpi->spx->value();
3803 
3804  try
3805  {
3806  if( primsol != NULL )
3807  {
3808  Vector tmp(lpi->spx->nCols(), primsol);
3809  (void)lpi->spx->getPrimal(tmp);
3810  }
3811  if( dualsol != NULL )
3812  {
3813  Vector tmp(lpi->spx->nRows(), dualsol);
3814  (void)lpi->spx->getDual(tmp);
3815  }
3816  if( activity != NULL )
3817  {
3818  Vector tmp(lpi->spx->nRows(), activity);
3819  (void)lpi->spx->getSlacks(tmp); /* in SoPlex, the activities are called "slacks" */
3820  }
3821  if( redcost != NULL )
3822  {
3823  Vector tmp(lpi->spx->nCols(), redcost);
3824  (void)lpi->spx->getRedCost(tmp);
3825  }
3826  }
3827 #ifndef NDEBUG
3828  catch( const SPxException& x )
3829  {
3830  std::string s = x.what();
3831  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3832 #else
3833  catch( const SPxException& )
3834  {
3835 #endif
3836  return SCIP_LPERROR;
3837  }
3838 
3839  return SCIP_OKAY;
3840 }
3841 
3842 /** gets primal ray for unbounded LPs */
3844  SCIP_LPI* lpi, /**< LP interface structure */
3845  SCIP_Real* ray /**< primal ray */
3846  )
3847 { /*lint --e{715}*/
3848  SCIPdebugMessage("calling SCIPlpiGetPrimalRay()\n");
3849 
3850  assert(lpi != NULL);
3851  assert(lpi->spx != NULL);
3852  assert(ray != NULL);
3853 
3854 #if ((SOPLEX_VERSION == 150 && SOPLEX_SUBVERSION >= 2) || SOPLEX_VERSION > 150)
3855  try
3856  {
3857  Vector tmp(lpi->spx->nCols(), ray);
3858  (void)lpi->spx->getPrimalray(tmp);
3859  }
3860 #ifndef NDEBUG
3861  catch( const SPxException& x )
3862  {
3863  std::string s = x.what();
3864  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3865 #else
3866  catch( const SPxException& )
3867  {
3868 #endif
3869  return SCIP_LPERROR;
3870  }
3871 
3872  return SCIP_OKAY;
3873 #else
3874  SCIPerrorMessage("SCIPlpiGetPrimalRay() not supported by SoPlex versions <= 1.5.0\n");
3875  return SCIP_LPERROR;
3876 #endif
3877 }
3878 
3879 /** gets dual farkas proof for infeasibility */
3881  SCIP_LPI* lpi, /**< LP interface structure */
3882  SCIP_Real* dualfarkas /**< dual farkas row multipliers */
3883  )
3884 {
3885  SCIPdebugMessage("calling SCIPlpiGetDualfarkas()\n");
3886 
3887  assert(lpi != NULL);
3888  assert(lpi->spx != NULL);
3889  assert(dualfarkas != NULL);
3890 
3891  try
3892  {
3893  Vector tmp(lpi->spx->nRows(), dualfarkas);
3894  (void)lpi->spx->getDualfarkas(tmp);
3895  }
3896 #ifndef NDEBUG
3897  catch( const SPxException& x )
3898  {
3899  std::string s = x.what();
3900  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
3901 #else
3902  catch( const SPxException& )
3903  {
3904 #endif
3905  return SCIP_LPERROR;
3906  }
3907 
3908  return SCIP_OKAY;
3909 }
3910 
3911 /** gets the number of LP iterations of the last solve call */
3913  SCIP_LPI* lpi, /**< LP interface structure */
3914  int* iterations /**< pointer to store the number of iterations of the last solve call */
3915  )
3916 {
3917  SCIPdebugMessage("calling SCIPlpiGetIterations()\n");
3918 
3919  assert(lpi != NULL);
3920  assert(lpi->spx != NULL);
3921  assert(iterations != NULL);
3922 
3923  *iterations = lpi->spx->iterations();
3924 
3925  return SCIP_OKAY;
3926 }
3927 
3928 /** gets information about the quality of an LP solution
3929  *
3930  * Such information is usually only available, if also a (maybe not optimal) solution is available.
3931  * The LPI should return SCIP_INVALID for @p quality, if the requested quality is not available.
3932  */
3934  SCIP_LPI* lpi, /**< LP interface structure */
3935  SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3936  SCIP_Real* quality /**< pointer to store quality number */
3937  )
3938 {
3939  SCIPdebugMessage("calling SCIPlpiGetRealSolQuality()\n");
3940 
3941  assert(lpi != NULL);
3942  assert(quality != NULL);
3943 
3944 #if ((SOPLEX_VERSION == 172 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 172)
3945  int maxiter;
3946  Real tolerance;
3947 
3948  SCIPdebugMessage("requesting solution quality from SoPlex: quality %d\n", qualityindicator);
3949 
3950  switch( qualityindicator )
3951  {
3953  maxiter = 20;
3954  tolerance = 1e-6;
3955  break;
3956 
3958  maxiter = 10000;
3959  tolerance = 1e-9;
3960  break;
3961 
3962  default:
3963  SCIPerrorMessage("Solution quality %d unknown.\n", qualityindicator);
3964  return SCIP_INVALIDDATA;
3965  }
3966 
3967  *quality = lpi->spx->basis().condition(maxiter, tolerance);
3968 #else
3969  *quality = SCIP_INVALID;
3970 #endif
3971  return SCIP_OKAY;
3972 }
3973 
3974 /**@} */
3975 
3976 
3977 
3978 
3979 /*
3980  * LP Basis Methods
3981  */
3982 
3983 /**@name LP Basis Methods */
3984 /**@{ */
3985 
3986 /** Return reduced cost of column @c col if this is readily available, otherwise return 0.0 */
3987 static
3988 SCIP_RETCODE getRedCostEst(SPxSCIP* spx, int col, SCIP_Real* val)
3989 {
3990  assert( spx != NULL );
3991  assert( val != NULL );
3992 
3993  *val = 0.0;
3994 
3995  /* Return if the vectors are not set up. The vectors are not set up if for instance we preformed
3996  * strong branching before. */
3997  if (! spx->isInitialized() )
3998  return SCIP_OKAY;
3999 
4000  assert( 0 <= col && col < spx->nCols() );
4001 
4002  if( spx->rep() == SPxSolver::COLUMN )
4003  {
4004  /* in column case the reduced costs are available: */
4005  if (spx->getSense() == SPxLP::MINIMIZE)
4006  *val = spx->pVec()[col] - spx->maxObj()[col];
4007  else
4008  *val = spx->maxObj()[col] - spx->pVec()[col];
4009  }
4010  else
4011  {
4012  assert( spx->rep() == SPxSolver::ROW );
4013 
4014  /* In row case for computing the reduced costs one needs to pass through the basis. We skip this expensive part. */
4015 #ifdef SCIP_DISABLED_CODE
4016  /* Here is the code necessary to compute the reduced costs for row representation: */
4017  SCIP_Real sign = 1.0;
4018  if ( spx->getSense() == SPxLP::MINIMIZE )
4019  sign = -1.0;
4020 
4021  if ( spx->isColBasic(col) )
4022  {
4023  /* It seems necessary to search through the basis in order to find the correct position */
4024  for (int i = spx->dim() - 1; i >= 0; --i)
4025  {
4026  SPxId id = spx->basis().baseId(i);
4027  if ( id.isSPxColId() && col == spx->number(SPxColId(id)) )
4028  {
4029  *val = sign * spx->fVec()[i];
4030  break;
4031  }
4032  }
4033  }
4034 #endif
4035  }
4036 
4037  return SCIP_OKAY;
4038 }
4039 
4040 
4041 
4042 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
4044  SCIP_LPI* lpi, /**< LP interface structure */
4045  int* cstat, /**< array to store column basis status, or NULL */
4046  int* rstat /**< array to store row basis status, or NULL */
4047  )
4048 {
4049  int i;
4050 
4051  SCIPdebugMessage("calling SCIPlpiGetBase()\n");
4052 
4053  assert(lpi != NULL);
4054  assert(lpi->spx != NULL);
4055 
4056  assert( lpi->spx->preStrongbranchingBasisFreed() );
4057 
4058  if( rstat != NULL )
4059  {
4060  for( i = 0; i < lpi->spx->nRows(); ++i )
4061  {
4062  switch( lpi->spx->getBasisRowStatus(i) )
4063  {
4064  case SPxSolver::BASIC:
4065  rstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4066  break;
4067  case SPxSolver::FIXED:
4068  case SPxSolver::ON_LOWER:
4069  rstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4070  break;
4071  case SPxSolver::ON_UPPER:
4072  rstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4073  break;
4074  case SPxSolver::ZERO:
4075  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4076  return SCIP_LPERROR;
4077  case SPxSolver::UNDEFINED:
4078  default:
4079  SCIPerrorMessage("invalid basis status\n");
4080  SCIPABORT();
4081  return SCIP_INVALIDDATA; /*lint !e527*/
4082  }
4083  }
4084  }
4085 
4086  if( cstat != NULL )
4087  {
4088  for( i = 0; i < lpi->spx->nCols(); ++i )
4089  {
4090  SCIP_Real val = 0.0;
4091  switch( lpi->spx->getBasisColStatus(i) )
4092  {
4093  case SPxSolver::BASIC:
4094  cstat[i] = SCIP_BASESTAT_BASIC; /*lint !e641*/
4095  break;
4096  case SPxSolver::FIXED:
4097  /* Get reduced cost estimation. If the estimation is not correct this should not hurt:
4098  * If the basis is loaded into SoPlex again, the status is converted to FIXED again; in
4099  * this case there is no problem at all. If the basis is saved and/or used in some other
4100  * solver, it usually is very cheap to perform the pivots necessary to get an optimal
4101  * basis. */
4102  SCIP_CALL( getRedCostEst(lpi->spx, i, &val) );
4103  if( val < 0.0 ) /* reduced costs < 0 => UPPER else => LOWER */
4104  cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4105  else
4106  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4107  break;
4108  case SPxSolver::ON_LOWER:
4109  cstat[i] = SCIP_BASESTAT_LOWER; /*lint !e641*/
4110  break;
4111  case SPxSolver::ON_UPPER:
4112  cstat[i] = SCIP_BASESTAT_UPPER; /*lint !e641*/
4113  break;
4114  case SPxSolver::ZERO:
4115  cstat[i] = SCIP_BASESTAT_ZERO; /*lint !e641*/
4116  break;
4117  case SPxSolver::UNDEFINED:
4118  default:
4119  SCIPerrorMessage("invalid basis status\n");
4120  SCIPABORT();
4121  return SCIP_INVALIDDATA; /*lint !e527*/
4122  }
4123  }
4124  }
4125 
4126  return SCIP_OKAY;
4127 }
4128 
4129 /** sets current basis status for columns and rows */
4131  SCIP_LPI* lpi, /**< LP interface structure */
4132  const int* cstat, /**< array with column basis status */
4133  const int* rstat /**< array with row basis status */
4134  )
4135 {
4136  int i;
4137  int ncols;
4138  int nrows;
4139 
4140  SCIPdebugMessage("calling SCIPlpiSetBase()\n");
4141 
4142  assert(lpi != NULL);
4143  assert(lpi->spx != NULL);
4144 
4145  SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
4146  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
4147 
4148  assert(cstat != NULL || ncols == 0);
4149  assert(rstat != NULL || nrows == 0);
4150 
4151  assert( lpi->spx->preStrongbranchingBasisFreed() );
4152  invalidateSolution(lpi);
4153 
4154  DataArray<SPxSolver::VarStatus>& m_colstat = lpi->spx->colStat();
4155  DataArray<SPxSolver::VarStatus>& m_rowstat = lpi->spx->rowStat();
4156 
4157  m_colstat.reSize(ncols);
4158  m_rowstat.reSize(nrows);
4159 
4160  for( i = 0; i < nrows; ++i )
4161  {
4162  assert( rstat != 0 ); /* for lint */
4163  switch( rstat[i] )
4164  {
4165  case SCIP_BASESTAT_LOWER:
4166  m_rowstat[i] = SPxSolver::ON_LOWER;
4167  break;
4168  case SCIP_BASESTAT_BASIC:
4169  m_rowstat[i] = SPxSolver::BASIC;
4170  break;
4171  case SCIP_BASESTAT_UPPER:
4172  m_rowstat[i] = SPxSolver::ON_UPPER;
4173  break;
4174  case SCIP_BASESTAT_ZERO:
4175  SCIPerrorMessage("slack variable has basis status ZERO (should not occur)\n");
4176  return SCIP_LPERROR; /*lint !e429*/
4177  default:
4178  SCIPerrorMessage("invalid basis status\n");
4179  SCIPABORT();
4180  return SCIP_INVALIDDATA; /*lint !e527*/
4181  }
4182  }
4183 
4184  for( i = 0; i < ncols; ++i )
4185  {
4186  assert( cstat != 0 ); /* for lint */
4187  switch( cstat[i] )
4188  {
4189  case SCIP_BASESTAT_LOWER:
4190  m_colstat[i] = SPxSolver::ON_LOWER;
4191  break;
4192  case SCIP_BASESTAT_BASIC:
4193  m_colstat[i] = SPxSolver::BASIC;
4194  break;
4195  case SCIP_BASESTAT_UPPER:
4196  m_colstat[i] = SPxSolver::ON_UPPER;
4197  break;
4198  case SCIP_BASESTAT_ZERO:
4199  m_colstat[i] = SPxSolver::ZERO;
4200  break;
4201  default:
4202  SCIPerrorMessage("invalid basis status\n");
4203  SCIPABORT();
4204  return SCIP_INVALIDDATA; /*lint !e527*/
4205  }
4206  }
4207 
4208  SOPLEX_TRY( lpi->messagehdlr, lpi->spx->setBasis(m_rowstat.get_const_ptr(), m_colstat.get_const_ptr()) );
4209  (void) lpi->spx->updateStatus();
4210 
4211  lpi->spx->freePreStrongbranchingBasis();
4212 
4213  return SCIP_OKAY;
4214 }
4215 
4216 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
4218  SCIP_LPI* lpi, /**< LP interface structure */
4219  int* bind /**< pointer to store basis indices ready to keep number of rows entries */
4220  )
4221 {
4222  SCIPdebugMessage("calling SCIPlpiGetBasisInd()\n");
4223 
4224  SPxSolver* spx;
4225 
4226  assert(lpi != NULL);
4227  assert(lpi->spx != NULL);
4228  assert(bind != NULL);
4229 
4230  assert( lpi->spx->preStrongbranchingBasisFreed() );
4231 
4232  /* the LPi defines the basis as column basis, i.e., as the set of (indices of) non-fixed columns and rows; if SoPlex
4233  * uses row representation, this is just the complement of the basis
4234  */
4235  spx = lpi->spx;
4236 
4237  /* for column representation, return the basis */
4238  if( spx->rep() == SPxSolver::COLUMN )
4239  {
4240  for( int i = 0; i < spx->nRows(); ++i )
4241  {
4242  SPxId id = spx->basis().baseId(i);
4243 
4244  bind[i] = (id.isSPxColId() ? spx->number(id) : - 1 - spx->number(id));
4245  }
4246  }
4247  /* for row representation, return the complement of the basis; for this, we need to loop through all rows and columns */
4248  else
4249  {
4250  int k = 0;
4251  int nrows = spx->nRows();
4252  int ncols = spx->nCols();
4253 
4254  assert( spx->rep() == SPxSolver::ROW );
4255 
4256  for( int i = 0; i < nrows; ++i )
4257  {
4258  if( !spx->isRowBasic(i) )
4259  {
4260  bind[k++] = -1 - i;
4261  if( k >= nrows )
4262  break;
4263  }
4264  }
4265 
4266  for( int j = 0; j < ncols && k < nrows; ++j )
4267  {
4268  if( !spx->isColBasic(j) )
4269  bind[k++] = j;
4270  }
4271 
4272  assert(k == nrows);
4273  }
4274 
4275  return SCIP_OKAY;
4276 }
4277 
4278 #ifdef OLD_BINV
4279 /* prepare a factorization of the basis matrix in column representation */
4280 static
4281 SCIP_RETCODE prepareFactorization(
4282  SCIP_LPI* lpi
4283  )
4284 {
4285  SCIPdebugMessage("Preparing factorization for computation of basis inverse.\n");
4286 
4287  try
4288  {
4289  /* if the factorization has not been set up, we compute a new factorization */
4290  if ( lpi->factorization == 0 )
4291  {
4292  SPxSolver* spx = lpi->spx;
4293 
4294  /* matrix to store columns */
4295  DataArray <const SVector*> matrix(spx->nRows());
4296 
4297  int k = 0;
4298  for (int i = 0; i < spx->nRows(); ++i)
4299  {
4300  if ( ! spx->isRowBasic(i) )
4301  matrix[k++] = new UnitVector(i);
4302  }
4303  for (int j = 0; j < spx->nCols(); ++j)
4304  {
4305  if ( ! spx->isColBasic(j) )
4306  matrix[k++] = &spx->colVector(j);
4307  }
4308  assert( k == spx->nRows() );
4309  assert( k == matrix.size() );
4310 
4311  /* compute factorization */
4312  lpi->factorization = new SLUFactor;
4313 #ifndef NDEBUG
4314  SLinSolver::Status status = lpi->factorization->load(matrix.get_ptr(), k);
4315 #else
4316  (void) lpi->factorization->load(matrix.get_ptr(), k);
4317 #endif
4318  assert( status == SLinSolver::OK );
4319  assert( k == lpi->factorization->dim() );
4320 
4321  /* delete matrix columns corresponding to unit vectors */
4322  k = 0;
4323  for (int i = 0; i < spx->nRows(); ++i)
4324  {
4325  if ( ! spx->isRowBasic(i) )
4326  delete matrix[k++];
4327  }
4328  }
4329  }
4330 #ifndef NDEBUG
4331  catch( const SPxException& x )
4332  {
4333  std::string s = x.what();
4334  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4335 #else
4336  catch( const SPxException& )
4337  {
4338 #endif
4339  return SCIP_LPERROR;
4340  }
4341 
4342  return SCIP_OKAY;
4343 }
4344 #endif
4345 
4346 /** get row of inverse basis matrix B^-1
4347  *
4348  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4349  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4350  * see also the explanation in lpi.h.
4351  */
4353  SCIP_LPI* lpi, /**< LP interface structure */
4354  int r, /**< row number */
4355  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
4356  int* inds, /**< array to store the non-zero indices, or NULL */
4357  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4358  * (-1: if we do not store sparsity information) */
4359  )
4360 {
4361  SCIPdebugMessage("calling SCIPlpiGetBInvRow()\n");
4362 
4363  assert( lpi != NULL );
4364  assert( lpi->spx != NULL );
4365  assert( lpi->spx->preStrongbranchingBasisFreed() );
4366  assert(coef != NULL);
4367 
4368  int nCols = lpi->spx->nCols();
4369  int nRows = lpi->spx->nRows();
4370 
4371  assert(r >= 0);
4372  assert(r < nRows);
4373 
4374  try
4375  {
4376  SPxSolver* spx = lpi->spx;
4377 
4378  /* in the column case use the existing factorization */
4379  if ( spx->rep() == SPxSolver::COLUMN )
4380  {
4381  SSVector x(nRows);
4382  spx->basis().coSolve(x, spx->unitVector(r));
4383 
4384  /* copy sparse data to dense result vector based on coef array */
4385  if( ninds != NULL && inds != NULL )
4386  {
4387  int idx;
4388  /* during solving SoPlex may have destroyed the sparsity structure so we need to restore it */
4389  x.setup();
4390  *ninds = x.size();
4391  for( int i = 0; i < *ninds; ++i )
4392  {
4393  idx = x.index(i);
4394  coef[idx] = x[idx];
4395  /* set sparsity pattern of coef array */
4396  inds[i] = idx;
4397  }
4398  }
4399  else
4400  {
4401  /* @todo check whether we only need to copy nonzeros to coef - is coef cleared? */
4402  Vector y(nRows, coef);
4403  y = x;
4404  if( ninds != NULL )
4405  *ninds = -1;
4406  }
4407  }
4408  else
4409  {
4410  assert(spx->rep() == SPxSolver::ROW);
4411 
4412 #ifdef OLD_BINV
4413  DVector e(nRows);
4414 
4415  /* prepare unit vector */
4416  e.clear();
4417  e[r] = 1.0;
4418 
4419  /* factorization is deleted in invalidateSolution() */
4420  SCIP_CALL( prepareFactorization(lpi) );
4421  assert( lpi->factorization != 0 );
4422  assert( lpi->factorization->dim() == nRows );
4423 
4424  /* solve system "x = e_r^T * B^-1" to get r'th row of B^-1 */
4425  lpi->factorization->solveLeft(x, e);
4426 #else
4427  Vector x(nRows, coef); /* row of B^-1 has nrows entries - note that x is based on coef */
4428  /**@todo should rhs be a reference? */
4429  DSVector rhs(nCols);
4430  SSVector y(nCols);
4431  int* bind;
4432  int idx;
4433 
4434  bind = NULL;
4435 
4436  /**@todo should bind be stored globally in lpi? */
4437  /* get ordering of column basis matrix */
4438  SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4439  SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4440 
4441  /* get vector corresponding to requested index r */
4442  idx = bind[r];
4443 
4444  /* r corresponds to a row vector */
4445  if( idx < 0 )
4446  {
4447  idx = -idx-1;
4448 
4449  /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4450  assert(idx >= 0);
4451  assert(idx < nRows);
4452  assert(!spx->isRowBasic(idx));
4453 
4454  /* get row vector */
4455  rhs = spx->rowVector(idx);
4456  rhs *= -1.0;
4457  }
4458  /* r corresponds to a column vector */
4459  else
4460  {
4461  /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4462  assert(idx < nCols);
4463  assert(!spx->isColBasic(idx));
4464 
4465  /* get unit vector */
4466  rhs = spx->unitVector(idx);
4467  }
4468 
4469  /* solve system "y B = rhs", where B is the row basis matrix */
4470  spx->basis().solve(y, rhs);
4471 
4472  /* initialize result vector x as zero */
4473  BMSclearMemoryArray(coef, nRows);
4474 
4475  /* add nonzero entries */
4476  for( int i = 0; i < nCols; ++i )
4477  {
4478  SPxId id = spx->basis().baseId(i);
4479 
4480  if( id.isSPxRowId() )
4481  {
4482  assert(spx->number(id) >= 0);
4483  assert(spx->number(id) < nRows);
4484  assert(bind[r] >= 0 || spx->number(id) != idx);
4485 
4486  x[spx->number(id)] = y[i];
4487  }
4488  }
4489 
4490  /* if r corresponds to a row vector, we have to add a 1 at position r */
4491  if( bind[r] < 0 )
4492  {
4493  assert(x[idx] == 0.0);
4494  x[idx] = 1.0;
4495  }
4496 
4497  /* @todo implement returning of sparsity information like in column wise case */
4498  if( ninds != NULL )
4499  *ninds = -1;
4500 
4501  /* free memory */
4502  BMSfreeMemoryArray(&bind);
4503 #endif
4504  }
4505  }
4506 #ifndef NDEBUG
4507  catch( const SPxException& x )
4508  {
4509  std::string s = x.what();
4510  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4511 #else
4512  catch( const SPxException& )
4513  {
4514 #endif
4515  return SCIP_LPERROR;
4516  }
4517 
4518  return SCIP_OKAY;
4519 }
4520 
4521 /** get solution of basis matrix B * coef = rhs */
4522 static
4524  SCIP_LPI* lpi, /**< LP interface structure */
4525  SCIP_Real* rhs, /**< right-hand side vector */
4526  SCIP_Real* coef /**< vector to return coefficients */
4527  )
4528 {
4529  SCIPdebugMessage("calling SCIPlpiGetBInvVec()\n");
4530 
4531  assert(lpi != NULL);
4532  assert(lpi->spx != NULL);
4533  assert(lpi->spx->preStrongbranchingBasisFreed());
4534  assert(rhs != NULL);
4535  assert(coef != NULL);
4536 
4537  int nCols = lpi->spx->nCols();
4538  int nRows = lpi->spx->nRows();
4539 
4540  try
4541  {
4542  SPxSolver* spx = lpi->spx;
4543  Vector v(nRows, rhs);
4544  Vector x(nRows, coef);
4545 
4546  /* in the column case use the existing factorization */
4547  if( spx->rep() == SPxSolver::COLUMN )
4548  {
4549  /* solve system "x = B^-1 * A_c" to get c'th column of B^-1 * A */
4550  spx->basis().solve(x, v);
4551  }
4552  else
4553  {
4554  assert(spx->rep() == SPxSolver::ROW);
4555 
4556 #ifdef OLD_BINV
4557  /* factorization is deleted in invalidateSolution() */
4558  SCIP_CALL( prepareFactorization(lpi) );
4559  assert(lpi->factorization != 0);
4560  assert(lpi->factorization->dim() == spx->nRows());
4561 
4562  /* solve system B * x = v */
4563  lpi->factorization->solveRight(x, v);
4564 #else
4565  DSVector rowrhs(nCols);
4566  SSVector y(nCols);
4567  int* bind;
4568 
4569  bind = NULL;
4570 
4571  /**@todo should bind be stored globally in lpi? */
4572  /* get ordering of column basis matrix */
4573  SCIP_ALLOC( BMSallocMemoryArray(&bind, nRows) ); /*lint !e530*/
4574  SCIP_CALL( SCIPlpiGetBasisInd(lpi, bind) );
4575 
4576  /* fill right-hand side for row-based system */
4577  for( int i = 0; i < nCols; ++i )
4578  {
4579  SPxId id = spx->basis().baseId(i);
4580 
4581  if( id.isSPxRowId() )
4582  {
4583  assert(spx->number(id) >= 0);
4584  assert(spx->number(id) < nRows);
4585 
4586  rowrhs.add(i, v[spx->number(id)]);
4587  }
4588  else
4589  {
4590  assert(rowrhs[i] == 0.0);
4591  }
4592  }
4593 
4594  /* solve system "B y = rowrhs", where B is the row basis matrix */
4595  spx->basis().coSolve(y, rowrhs);
4596 
4597  /* fill result w.r.t. order given by bind */
4598  for( int i = 0; i < nRows; ++i )
4599  {
4600  int idx;
4601 
4602  idx = bind[i];
4603 
4604  if( idx < 0 )
4605  {
4606  idx = -idx-1;
4607 
4608  /* should be a valid row index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4609  assert(idx >= 0);
4610  assert(idx < nRows);
4611  assert(!spx->isRowBasic(idx));
4612 
4613  x[i] = v[idx] - (spx->rowVector(idx) * Vector(nCols, y.get_ptr())); /*lint !e1702*/
4614  }
4615  else
4616  {
4617  /* should be a valid column index and in the column basis matrix, i.e., not basic w.r.t. row representation */
4618  assert(idx >= 0);
4619  assert(idx < nCols);
4620  assert(!spx->isColBasic(idx));
4621 
4622  x[i] = y[idx];
4623  }
4624  }
4625 
4626  /* free memory */
4627  BMSfreeMemoryArray(&bind);
4628 #endif
4629  }
4630  }
4631 #ifndef NDEBUG
4632  catch( const SPxException& x )
4633  {
4634  std::string s = x.what();
4635  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4636 #else
4637  catch( const SPxException& )
4638  {
4639 #endif
4640  return SCIP_LPERROR;
4641  }
4642 
4643  return SCIP_OKAY;
4644 }
4645 
4646 /** get column of inverse basis matrix B^-1
4647  *
4648  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4649  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4650  * see also the explanation in lpi.h.
4651  */
4653  SCIP_LPI* lpi, /**< LP interface structure */
4654  int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
4655  * you have to call SCIPlpiGetBasisInd() to get the array which links the
4656  * B^-1 column numbers to the row and column numbers of the LP!
4657  * c must be between 0 and nrows-1, since the basis has the size
4658  * nrows * nrows */
4659  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
4660  int* inds, /**< array to store the non-zero indices, or NULL */
4661  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4662  * (-1: if we do not store sparsity information) */
4663  )
4664 { /*lint --e{715}*/
4665  SCIPdebugMessage("calling SCIPlpiGetBInvCol()\n");
4666 
4667  assert( lpi != NULL );
4668  assert( lpi->spx != NULL );
4669  assert( lpi->spx->preStrongbranchingBasisFreed() );
4670  assert(coef != NULL);
4671 
4672  /* mark sparsity pattern as invalid */
4673  if( ninds != NULL )
4674  *ninds = -1;
4675 
4676  /* prepare unit vector */
4677  DVector e(lpi->spx->nRows());
4678 
4679  e.clear();
4680 
4681  assert(c >= 0);
4682  assert(c < lpi->spx->nRows());
4683  e[c] = 1.0;
4684 
4685  /* solve */
4686  SCIP_CALL( lpiGetBInvVec(lpi, e.get_ptr(), coef) );
4687 
4688  return SCIP_OKAY;
4689 }
4690 
4691 /** get row of inverse basis matrix times constraint matrix B^-1 * A
4692  *
4693  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4694  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4695  * see also the explanation in lpi.h.
4696  */
4698  SCIP_LPI* lpi, /**< LP interface structure */
4699  int r, /**< row number */
4700  const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
4701  SCIP_Real* coef, /**< vector to return coefficients of the row */
4702  int* inds, /**< array to store the non-zero indices, or NULL */
4703  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4704  * (-1: if we do not store sparsity information) */
4705  )
4706 {
4707  SCIP_Real* buf;
4708  SCIP_Real* binv;
4709  int nrows;
4710  int ncols;
4711  int c;
4712 
4713  SCIPdebugMessage("calling SCIPlpiGetBInvARow()\n");
4714 
4715  assert(lpi != NULL);
4716  assert(lpi->spx != NULL);
4717  assert( lpi->spx->preStrongbranchingBasisFreed() );
4718  assert(coef != NULL);
4719 
4720  nrows = lpi->spx->nRows();
4721  ncols = lpi->spx->nCols();
4722  buf = NULL;
4723 
4724  /* get (or calculate) the row in B^-1 */
4725  if( binvrow == NULL )
4726  {
4727  SCIP_ALLOC( BMSallocMemoryArray(&buf, nrows) );
4728  SCIP_CALL( SCIPlpiGetBInvRow(lpi, r, buf, inds, ninds) );
4729  binv = buf;
4730  }
4731  else
4732  binv = const_cast<SCIP_Real*>(binvrow);
4733 
4734  assert(binv != NULL);
4735 
4736  /* mark sparsity pattern as invalid */
4737  if( ninds != NULL )
4738  *ninds = -1;
4739 
4740  /* calculate the scalar product of the row in B^-1 and A */
4741  soplex::Vector binvvec(nrows, binv);
4742  for( c = 0; c < ncols; ++c )
4743  coef[c] = binvvec * lpi->spx->colVector(c); /* scalar product */ /*lint !e1702*/
4744 
4745  /* free memory if it was temporarily allocated */
4746  BMSfreeMemoryArrayNull(&buf);
4747 
4748  return SCIP_OKAY;
4749 }
4750 
4751 /** get column of inverse basis matrix times constraint matrix B^-1 * A
4752  *
4753  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4754  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4755  * see also the explanation in lpi.h.
4756  */
4758  SCIP_LPI* lpi, /**< LP interface structure */
4759  int c, /**< column number */
4760  SCIP_Real* coef, /**< vector to return coefficients of the column */
4761  int* inds, /**< array to store the non-zero indices, or NULL */
4762  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4763  * (-1: if we do not store sparsity information) */
4764  )
4765 { /*lint --e{715}*/
4766  DVector col(lpi->spx->nRows());
4767 
4768  SCIPdebugMessage("calling SCIPlpiGetBInvACol()\n");
4769 
4770  assert( lpi != NULL );
4771  assert( lpi->spx != NULL );
4772  assert( lpi->spx->preStrongbranchingBasisFreed() );
4773  assert(coef != NULL);
4774 
4775  /* extract column c of A */
4776  assert(c >= 0);
4777  assert(c < lpi->spx->nCols());
4778 
4779  /* mark sparsity pattern as invalid */
4780  if( ninds != NULL )
4781  *ninds = -1;
4782 
4783  col.clear();
4784  col = lpi->spx->colVector(c);
4785  col.reDim(lpi->spx->nRows());
4786 
4787  /* solve */
4788  SCIP_CALL( lpiGetBInvVec(lpi, col.get_ptr(), coef) );
4789 
4790  return SCIP_OKAY;
4791 }
4792 
4793 /**@} */
4794 
4795 
4796 
4797 
4798 /*
4799  * LP State Methods
4800  */
4801 
4802 /**@name LP State Methods */
4803 /**@{ */
4804 
4805 /** stores LPi state (like basis information) into lpistate object */
4807  SCIP_LPI* lpi, /**< LP interface structure */
4808  BMS_BLKMEM* blkmem, /**< block memory */
4809  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4810  )
4811 {
4812  int ncols;
4813  int nrows;
4814 
4815  SCIPdebugMessage("calling SCIPlpiGetState()\n");
4816 
4817  assert(blkmem != NULL);
4818  assert(lpi != NULL);
4819  assert(lpi->spx != NULL);
4820  assert(lpistate != NULL);
4821 
4822  assert( lpi->spx->preStrongbranchingBasisFreed() );
4823 
4824  ncols = lpi->spx->nCols();
4825  nrows = lpi->spx->nRows();
4826  assert(ncols >= 0);
4827  assert(nrows >= 0);
4828 
4829  /* allocate lpistate data */
4830  SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
4831 
4832  /* allocate enough memory for storing uncompressed basis information */
4833  SCIP_CALL( ensureCstatMem(lpi, ncols) );
4834  SCIP_CALL( ensureRstatMem(lpi, nrows) );
4835 
4836  /* get unpacked basis information */
4837  SCIP_CALL( SCIPlpiGetBase(lpi, lpi->cstat, lpi->rstat) );
4838 
4839  /* pack LPi state data */
4840  (*lpistate)->ncols = ncols;
4841  (*lpistate)->nrows = nrows;
4842  lpistatePack(*lpistate, lpi->cstat, lpi->rstat);
4843 
4844  return SCIP_OKAY;
4845 }
4846 
4847 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
4848  * columns and rows since the state was stored with SCIPlpiGetState()
4849  */
4851  SCIP_LPI* lpi, /**< LP interface structure */
4852  BMS_BLKMEM* /*blkmem*/, /**< block memory */
4853  const SCIP_LPISTATE* lpistate /**< LPi state information (like basis information), or NULL */
4854  )
4855 {
4856  int lpncols;
4857  int lpnrows;
4858  int i;
4859 
4860  SCIPdebugMessage("calling SCIPlpiSetState()\n");
4861 
4862  assert(lpi != NULL);
4863  assert(lpi->spx != NULL);
4864  assert(lpistate != NULL);
4865  /* assert(blkmem != NULL); */
4866 
4867  assert( lpi->spx->preStrongbranchingBasisFreed() );
4868 
4869  lpncols = lpi->spx->nCols();
4870  lpnrows = lpi->spx->nRows();
4871  assert(lpistate->ncols <= lpncols);
4872  assert(lpistate->nrows <= lpnrows);
4873 
4874  /* allocate enough memory for storing uncompressed basis information */
4875  SCIP_CALL( ensureCstatMem(lpi, lpncols) );
4876  SCIP_CALL( ensureRstatMem(lpi, lpnrows) );
4877 
4878  /* unpack LPi state data */
4879  lpistateUnpack(lpistate, lpi->cstat, lpi->rstat);
4880 
4881  /* extend the basis to the current LP beyond the previously existing columns */
4882  for( i = lpistate->ncols; i < lpncols; ++i )
4883  {
4884  SCIP_Real bnd = lpi->spx->lower(i);
4885  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4886  {
4887  /* if lower bound is +/- infinity -> try upper bound */
4888  bnd = lpi->spx->lower(i);
4889  if ( SCIPlpiIsInfinity(lpi, REALABS(bnd)) )
4890  lpi->cstat[i] = (int) SCIP_BASESTAT_ZERO; /* variable is free */
4891  else
4892  lpi->cstat[i] = (int) SCIP_BASESTAT_UPPER; /* use finite upper bound */
4893  }
4894  else
4895  lpi->cstat[i] = (int) SCIP_BASESTAT_LOWER; /* use finite lower bound */
4896  }
4897  for( i = lpistate->nrows; i < lpnrows; ++i )
4898  lpi->rstat[i] = (int) SCIP_BASESTAT_BASIC; /*lint !e641*/
4899 
4900  /* load basis information */
4901  SCIP_CALL( SCIPlpiSetBase(lpi, lpi->cstat, lpi->rstat) );
4902 
4903  return SCIP_OKAY;
4904 }
4905 
4906 /** clears current LPi state (like basis information) of the solver */
4908  SCIP_LPI* lpi /**< LP interface structure */
4909  )
4910 { /*lint --e{715}*/
4911  SCIPdebugMessage("calling SCIPlpiClearState()\n");
4912 
4913  assert(lpi != NULL);
4914  assert(lpi->spx != NULL);
4915 
4916  try
4917  {
4918  lpi->spx->reLoad();
4919  }
4920 #ifndef NDEBUG
4921  catch( const SPxException& x )
4922  {
4923  std::string s = x.what();
4924  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
4925 #else
4926  catch( const SPxException& )
4927  {
4928 #endif
4929  assert( lpi->spx->getStatus() != SPxSolver::OPTIMAL );
4930  return SCIP_LPERROR;
4931  }
4932 
4933  return SCIP_OKAY;
4934 }
4935 
4936 /** frees LPi state information */
4938  SCIP_LPI* lpi, /**< LP interface structure */
4939  BMS_BLKMEM* blkmem, /**< block memory */
4940  SCIP_LPISTATE** lpistate /**< pointer to LPi state information (like basis information) */
4941  )
4942 { /*lint --e{715}*/
4943  SCIPdebugMessage("calling SCIPlpiFreeState()\n");
4944 
4945  assert(lpi != NULL);
4946  assert(lpistate != NULL);
4947  assert(blkmem != NULL);
4948 
4949  if ( *lpistate != NULL )
4950  lpistateFree(lpistate, blkmem);
4951 
4952  return SCIP_OKAY;
4953 }
4954 
4955 /** checks, whether the given LP state contains simplex basis information */
4957  SCIP_LPI* lpi, /**< LP interface structure */
4958  SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4959  )
4960 { /*lint --e{715}*/
4961  assert(lpi != NULL);
4962  return TRUE;
4963 }
4964 
4965 /** reads LP state (like basis information from a file */
4967  SCIP_LPI* lpi, /**< LP interface structure */
4968  const char* fname /**< file name */
4969  )
4970 {
4971  SCIPdebugMessage("calling SCIPlpiReadState()\n");
4972  assert(lpi != NULL);
4973  assert(lpi->spx != NULL);
4974  assert(fname != NULL);
4975 
4976  assert( lpi->spx->preStrongbranchingBasisFreed() );
4977 
4978  bool success;
4979  SOPLEX_TRY( lpi->messagehdlr, success = lpi->spx->readBasisFile(fname, 0, 0) );
4980 
4981  return success ? SCIP_OKAY : SCIP_LPERROR;
4982 }
4983 
4984 /** writes LPi state (i.e. basis information) to a file */
4986  SCIP_LPI* lpi, /**< LP interface structure */
4987  const char* fname /**< file name */
4988  )
4989 {
4990  assert(lpi != NULL);
4991  assert(lpi->spx != NULL);
4992  assert(fname != NULL);
4993  SCIPdebugMessage("calling SCIPlpiWriteState()\n");
4994 
4995  assert( lpi->spx->preStrongbranchingBasisFreed() );
4996 
4997  bool res;
4998  SOPLEX_TRY( lpi->messagehdlr, res = lpi->spx->writeBasisFile(fname, 0, 0) );
4999 
5000  if ( ! res )
5001  return SCIP_LPERROR;
5002 
5003  return SCIP_OKAY;
5004 }
5005 
5006 /**@} */
5007 
5008 
5009 
5010 
5011 /*
5012  * LP Pricing Norms Methods
5013  */
5014 
5015 /**@name LP Pricing Norms Methods */
5016 /**@{ */
5017 
5018 /** stores LPi pricing norms information
5019  * @todo should we store norm information?
5020  */
5022  SCIP_LPI* lpi, /**< LP interface structure */
5023  BMS_BLKMEM* blkmem, /**< block memory */
5024  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
5025  )
5026 {
5027 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5028  int nrows;
5029  int ncols;
5030 
5031  assert(blkmem != NULL);
5032  assert(lpi != NULL);
5033  assert(lpi->spx != NULL);
5034  assert(lpinorms != NULL);
5035 
5036  lpi->spx->getNdualNorms(nrows, ncols);
5037 
5038  if( nrows == 0 && ncols == 0)
5039  {
5040  (*lpinorms = NULL);
5041  return SCIP_OKAY;
5042  }
5043 
5044  /* allocate lpinorms data */
5045  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpinorms) );
5046  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols) );
5047  (*lpinorms)->nrows = 0;
5048  (*lpinorms)->ncols = 0;
5049 
5050  SCIPdebugMessage("storing SoPlex LPi pricing norms in %p (%d rows, %d cols)\n", (void *) *lpinorms, nrows, ncols);
5051 
5052  if( !lpi->spx->getDualNorms((*lpinorms)->nrows, (*lpinorms)->ncols, (*lpinorms)->norms) )
5053  {
5054  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5055  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, nrows + ncols);
5056  BMSfreeBlockMemory(blkmem, lpinorms);
5057  assert(*lpinorms == NULL);
5058  }
5059 #ifndef NDEBUG
5060  else
5061  {
5062  assert(nrows == (*lpinorms)->nrows);
5063  assert(ncols == (*lpinorms)->ncols);
5064  }
5065 #endif
5066 #else
5067  (*lpinorms) = NULL;
5068 #endif
5069 
5070  return SCIP_OKAY;
5071 }
5072 
5073 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
5074  * columns and rows since the state was stored with SCIPlpiGetNorms()
5075  */
5077  SCIP_LPI* lpi, /**< LP interface structure */
5078  BMS_BLKMEM* blkmem, /**< block memory */
5079  const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
5080  )
5081 {
5082 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5083  assert(blkmem != NULL);
5084  assert(lpi != NULL);
5085  assert(lpi->spx != NULL);
5086 
5087  /* if there was no pricing norms information available, the LPi norms were not stored */
5088  if( lpinorms == NULL )
5089  return SCIP_OKAY;
5090 
5091  assert(lpinorms->nrows <= lpi->spx->nRows());
5092  assert(lpinorms->ncols <= lpi->spx->nCols());
5093 
5094  if( lpinorms->nrows == 0 )
5095  return SCIP_OKAY;
5096 
5097  SCIPdebugMessage("loading LPi simplex norms %p (%d rows, %d cols) into SoPlex LP with %d rows and %d cols\n",
5098  (const void *) lpinorms, lpinorms->nrows, lpinorms->ncols, lpi->spx->nRows(), lpi->spx->nCols());
5099 
5100  if( !lpi->spx->setDualNorms(lpinorms->nrows, lpinorms->ncols, lpinorms->norms) )
5101  SCIPdebugMessage("loading of LPi norms failed\n");
5102 #endif
5103 
5104  return SCIP_OKAY;
5105 }
5106 
5107 /** frees pricing norms information */
5109  SCIP_LPI* lpi, /**< LP interface structure */
5110  BMS_BLKMEM* blkmem, /**< block memory */
5111  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
5112  )
5113 {
5114 #if ((SOPLEX_VERSION == 201 && SOPLEX_SUBVERSION >= 3) || SOPLEX_VERSION > 201)
5115  assert(lpi != NULL);
5116  assert(lpinorms != NULL);
5117 
5118  SCIPdebugMessage("freeing norms at %p\n", (void *) *lpinorms);
5119 
5120  BMSfreeBlockMemoryArray(blkmem, &(*lpinorms)->norms, (*lpinorms)->nrows + (*lpinorms)->ncols);
5121  BMSfreeBlockMemory(blkmem, lpinorms);
5122  assert(*lpinorms == NULL);
5123 #endif
5124 
5125  return SCIP_OKAY;
5126 }
5127 
5128 /**@} */
5129 
5130 
5131 
5132 
5133 /*
5134  * Parameter Methods
5135  */
5136 
5137 /**@name Parameter Methods */
5138 /**@{ */
5139 
5140 /** gets integer parameter of LP */
5142  SCIP_LPI* lpi, /**< LP interface structure */
5143  SCIP_LPPARAM type, /**< parameter number */
5144  int* ival /**< buffer to store the parameter value */
5145  )
5146 {
5147  SCIPdebugMessage("calling SCIPlpiGetIntpar()\n");
5148 
5149  assert(lpi != NULL);
5150  assert(lpi->spx != NULL);
5151  assert(ival != NULL);
5152 
5153  switch( type )
5154  {
5156  *ival = lpi->spx->getFromScratch();
5157  break;
5158  case SCIP_LPPAR_LPINFO:
5159  *ival = lpi->spx->getLpInfo();
5160  break;
5161  case SCIP_LPPAR_LPITLIM:
5162  *ival = lpi->spx->getIterationLimit();
5163  if( *ival == -1 )
5164  *ival = INT_MAX;
5165  break;
5166  case SCIP_LPPAR_PRESOLVING:
5167  *ival = lpi->spx->getPresolving();
5168  break;
5169  case SCIP_LPPAR_PRICING:
5170  *ival = (int)lpi->pricing;
5171  break;
5172  case SCIP_LPPAR_SCALING:
5173  *ival = lpi->spx->getScaling();
5174  break;
5175 #if SOPLEX_VERSION >= 201
5176  case SCIP_LPPAR_TIMING:
5177  *ival = (int) lpi->spx->getTiming();
5178  break;
5179 #endif
5180 #if SOPLEX_VERSION >= 230 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 3)
5181  case SCIP_LPPAR_RANDOMSEED:
5182  *ival = (int) lpi->spx->random.getSeed();
5183  break;
5184 #endif
5185  default:
5186  return SCIP_PARAMETERUNKNOWN;
5187  } /*lint !e788*/
5188 
5189  return SCIP_OKAY;
5190 }
5191 
5192 /** sets integer parameter of LP */
5194  SCIP_LPI* lpi, /**< LP interface structure */
5195  SCIP_LPPARAM type, /**< parameter number */
5196  int ival /**< parameter value */
5197  )
5198 {
5199  SCIPdebugMessage("calling SCIPlpiSetIntpar()\n");
5200 
5201  assert(lpi != NULL);
5202  assert(lpi->spx != NULL);
5203 
5204  switch( type )
5205  {
5207  assert(ival == TRUE || ival == FALSE);
5208  lpi->spx->setFromScratch(bool(ival));
5209  break;
5210  case SCIP_LPPAR_LPINFO:
5211  assert(ival == TRUE || ival == FALSE);
5212  lpi->spx->setLpInfo(bool(ival));
5213  break;
5214  case SCIP_LPPAR_LPITLIM:
5215  assert( ival >= 0 );
5216  /* -1 <= ival, -1 meaning no time limit, 0 stopping immediately */
5217  if( ival >= INT_MAX )
5218  ival = -1;
5219  lpi->spx->setIterationLimit(ival);
5220  break;
5221  case SCIP_LPPAR_PRESOLVING:
5222  assert(ival == TRUE || ival == FALSE);
5223  lpi->spx->setPresolving(bool(ival));
5224  break;
5225  case SCIP_LPPAR_PRICING:
5226  lpi->pricing = (SCIP_PRICING)ival;
5227  switch( lpi->pricing )
5228  {
5230  case SCIP_PRICING_AUTO:
5231  lpi->spx->setAutoPricer();
5232  break;
5233  case SCIP_PRICING_FULL:
5234  lpi->spx->setFullPricer();
5235  break;
5236  case SCIP_PRICING_PARTIAL:
5237  lpi->spx->setParmultPricer();
5238  break;
5239  case SCIP_PRICING_STEEP:
5240  lpi->spx->setSteepPricer();
5241  break;
5243  lpi->spx->setSteepQStartPricer();
5244  break;
5245  case SCIP_PRICING_DEVEX:
5246  lpi->spx->setDevexPricer();
5247  break;
5248  default:
5249  return SCIP_LPERROR;
5250  }
5251  break;
5252  case SCIP_LPPAR_SCALING:
5253  assert(ival == TRUE || ival == FALSE);
5254  lpi->spx->setScaling(ival);
5255  break;
5256 #if SOPLEX_VERSION >= 201
5257  case SCIP_LPPAR_TIMING:
5258  assert(ival >= 0 && ival < 3);
5259  lpi->spx->setTiming((Timer::TYPE) ival);
5260  break;
5261 #endif
5262 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 220 && SOPLEX_SUBVERSION >= 2)
5263  case SCIP_LPPAR_RANDOMSEED:
5264  lpi->spx->random.setSeed((unsigned int) ival);
5265  break;
5266 #endif
5267 #if SOPLEX_VERSION > 221 || (SOPLEX_VERSION == 221 && SOPLEX_SUBVERSION >= 3)
5268  case SCIP_LPPAR_POLISHING:
5269  assert(ival >= 0 && ival < 3);
5270  lpi->spx->setSolutionPolishing((SPxSolver::SolutionPolish) ival);
5271  break;
5272 #endif
5273 
5274  default:
5275  return SCIP_PARAMETERUNKNOWN;
5276  } /*lint !e788*/
5277 
5278  return SCIP_OKAY;
5279 }
5280 
5281 /** gets floating point parameter of LP */
5283  SCIP_LPI* lpi, /**< LP interface structure */
5284  SCIP_LPPARAM type, /**< parameter number */
5285  SCIP_Real* dval /**< buffer to store the parameter value */
5286  )
5287 {
5288  SCIPdebugMessage("calling SCIPlpiGetRealpar()\n");
5289 
5290  assert(lpi != NULL);
5291  assert(lpi->spx != NULL);
5292  assert(dval != NULL);
5293 
5294  switch( type )
5295  {
5296  case SCIP_LPPAR_FEASTOL:
5297  *dval = lpi->spx->feastol();
5298  break;
5299 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5301  *dval = lpi->spx->opttol();
5302  break;
5303 #endif
5304  case SCIP_LPPAR_OBJLIM:
5305  if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5306  *dval = lpi->spx->getObjUpLimit();
5307  else
5308  *dval = lpi->spx->getObjLoLimit();
5309  break;
5310  case SCIP_LPPAR_LPTILIM:
5311  *dval = lpi->spx->terminationTime();
5312  break;
5314  *dval = lpi->rowrepswitch;
5315  break;
5317  *dval = lpi->conditionlimit;
5318  break;
5319  default:
5320  return SCIP_PARAMETERUNKNOWN;
5321  } /*lint !e788*/
5322 
5323  return SCIP_OKAY;
5324 }
5325 
5326 /** sets floating point parameter of LP */
5328  SCIP_LPI* lpi, /**< LP interface structure */
5329  SCIP_LPPARAM type, /**< parameter number */
5330  SCIP_Real dval /**< parameter value */
5331  )
5332 {
5333  SCIPdebugMessage("calling SCIPlpiSetRealpar()\n");
5334 
5335  assert(lpi != NULL);
5336  assert(lpi->spx != NULL);
5337 
5338  switch( type )
5339  {
5340  case SCIP_LPPAR_FEASTOL:
5341  /* 0 < dval */
5342  assert( dval > 0.0 );
5343  lpi->spx->setFeastol(dval);
5344  break;
5345 #if ((SOPLEX_VERSION == 160 && SOPLEX_SUBVERSION >= 5) || SOPLEX_VERSION > 160)
5347  /* 0 < dval */
5348  assert( dval > 0.0 );
5349  lpi->spx->setOpttol(dval);
5350  break;
5351 #endif
5352  case SCIP_LPPAR_OBJLIM:
5353  if ( lpi->spx->getSense() == SPxLP::MINIMIZE )
5354  lpi->spx->setObjUpLimit(dval);
5355  else
5356  lpi->spx->setObjLoLimit(dval);
5357  break;
5358  case SCIP_LPPAR_LPTILIM:
5359  assert( dval > 0.0 );
5360  /* soplex requires 0 <= dval
5361  *
5362  * However for consistency we assert the timelimit to be strictly positive.
5363  */
5364  lpi->spx->setTerminationTime(dval);
5365  break;
5367  assert( dval >= 0.0 || dval == -1.0 );
5368  lpi->rowrepswitch = dval;
5369  break;
5371  lpi->conditionlimit = dval;
5372  lpi->checkcondition = (dval >= 0.0);
5373  break;
5374  default:
5375  return SCIP_PARAMETERUNKNOWN;
5376  } /*lint !e788*/
5377 
5378  return SCIP_OKAY;
5379 }
5380 
5381 /** interrupts the currently ongoing lp solve or disables the interrupt */
5383  SCIP_LPI* lpi, /**< LP interface structure */
5384  SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
5385  )
5386 {
5387  /*lint --e{715}*/
5388  assert(lpi != NULL);
5389 
5390  return SCIP_OKAY;
5391 }
5392 
5393 /**@} */
5394 
5395 
5396 
5397 
5398 /*
5399  * Numerical Methods
5400  */
5401 
5402 /**@name Numerical Methods */
5403 /**@{ */
5404 
5405 /** returns value treated as infinity in the LP solver */
5407  SCIP_LPI* /*lpi*/ /**< LP interface structure */
5408  )
5410  SCIPdebugMessage("calling SCIPlpiInfinity()\n");
5411 
5412  return soplex::infinity;
5413 }
5414 
5415 /** checks if given value is treated as infinity in the LP solver */
5417  SCIP_LPI* /*lpi*/, /**< LP interface structure */
5418  SCIP_Real val
5419  )
5420 {
5421  SCIPdebugMessage("calling SCIPlpiIsInfinity()\n");
5422 
5423  return (val >= soplex::infinity);
5424 }
5425 
5426 /**@} */
5427 
5428 
5429 
5430 
5431 /*
5432  * File Interface Methods
5433  */
5434 
5435 /**@name File Interface Methods */
5436 /**@{ */
5437 
5438 /** returns, whether the given file exists */
5439 static
5441  const char* filename /**< file name */
5442  )
5444  FILE* f;
5445 
5446  f = fopen(filename, "r");
5447  if( f == NULL )
5448  return FALSE;
5449 
5450  fclose(f);
5451 
5452  return TRUE;
5453 }
5454 
5455 /** reads LP from a file */
5457  SCIP_LPI* lpi, /**< LP interface structure */
5458  const char* fname /**< file name */
5459  )
5460 {
5461  SCIPdebugMessage("calling SCIPlpiReadLP()\n");
5462 
5463  assert(lpi != NULL);
5464  assert(lpi->spx != NULL);
5465  assert(fname != NULL);
5466 
5467  assert( lpi->spx->preStrongbranchingBasisFreed() );
5468 
5469  if( !fileExists(fname) )
5470  return SCIP_NOFILE;
5471 
5472  try
5473  {
5474  if( !lpi->spx->readLP(fname) )
5475  return SCIP_READERROR;
5476  }
5477 #ifndef NDEBUG
5478  catch( const SPxException& x )
5479  {
5480  std::string s = x.what();
5481  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5482 #else
5483  catch( const SPxException& )
5484  {
5485 #endif
5486  return SCIP_READERROR;
5487  }
5488 
5489  return SCIP_OKAY;
5490 }
5491 
5492 /** writes LP to a file */
5494  SCIP_LPI* lpi, /**< LP interface structure */
5495  const char* fname /**< file name */
5496  )
5497 {
5498  SCIPdebugMessage("calling SCIPlpiWriteLP()\n");
5499 
5500  assert(lpi != NULL);
5501  assert(lpi->spx != NULL);
5502  assert(fname != NULL);
5503 
5504  try
5505  {
5506  lpi->spx->writeFile(fname);
5507  }
5508 #ifndef NDEBUG
5509  catch( const SPxException& x )
5510  {
5511  std::string s = x.what();
5512  SCIPmessagePrintWarning(lpi->messagehdlr, "SoPlex threw an exception: %s\n", s.c_str());
5513 #else
5514  catch( const SPxException& )
5515  {
5516 #endif
5517  return SCIP_WRITEERROR;
5518  }
5519 
5520  return SCIP_OKAY;
5521 }
5522 
5523 /**@} */
static SCIP_RETCODE lpiGetBInvVec(SCIP_LPI *lpi, SCIP_Real *rhs, SCIP_Real *coef)
Definition: lpi_spx1.cpp:4526
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4655
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_spx1.cpp:2517
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition: type_lpi.h:95
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_spx1.cpp:1770
SCIP_Real conditionlimit
Definition: lpi_cpx.c:164
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *, const SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4853
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *, SCIP_Real val)
Definition: lpi_spx1.cpp:5419
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:141
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3593
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_spx1.cpp:5079
ROWPACKET * packrstat
Definition: lpi_clp.cpp:128
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_spx1.cpp:3883
SCIP_PRICING pricing
Definition: lpi_clp.cpp:103
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3029
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:3790
#define infinity
Definition: gastrans.c:71
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_spx1.cpp:5196
enum SCIP_ObjSen SCIP_OBJSEN
Definition: type_lpi.h:36
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2925
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:1670
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:4046
SCIP_Bool solved
Definition: lpi_clp.cpp:105
void SCIPdecodeDualBit(const SCIP_DUALPACKET *inp, int *out, int count)
Definition: bitencode.c:299
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_spx1.cpp:2225
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_spx1.cpp:5144
interface methods for specific LP solvers
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_spx1.cpp:3915
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_RETCODE SCIPlpiGetNNonz(SCIP_LPI *lpi, int *nnonz)
Definition: lpi_spx1.cpp:2551
SCIP_Real rowrepswitch
Definition: lpi_spx1.cpp:1406
#define FALSE
Definition: def.h:87
#define AUTOPRICING_ITERSWITCH
Definition: lpi_spx1.cpp:34
static int rowpacketNum(int nrows)
Definition: lpi_spx1.cpp:1496
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:3991
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
int rstatsize
Definition: lpi_clp.cpp:101
SCIP_Bool checkcondition
Definition: lpi_cpx.c:165
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_spx1.cpp:5330
static SCIP_RETCODE spxSolve(SCIP_LPI *lpi, SPxSolver::Representation rep, SPxSolver::Type type)
Definition: lpi_spx1.cpp:2877
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3492
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5024
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:64
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_spx1.cpp:2534
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:116
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:4969
#define SCIPdebugMessage
Definition: pub_message.h:87
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_spx1.cpp:1703
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_spx1.cpp:2787
SCIP_RETCODE SCIPlpiClear(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2148
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI *lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real *quality)
Definition: lpi_spx1.cpp:3936
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2432
SCIP_RETCODE SCIPlpiGetObjsen(SCIP_LPI *lpi, SCIP_OBJSEN *objsen)
Definition: lpi_spx1.cpp:2747
#define SOPLEX_VERBLEVEL
Definition: lpi_spx1.cpp:145
#define BMSfreeMemory(ptr)
Definition: memory.h:138
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_spx1.cpp:1678
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:77
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
Definition: lpi_spx1.cpp:1561
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:4910
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:2584
SCIP_VAR ** x
Definition: circlepacking.c:54
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1731
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 SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4700
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:1881
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3509
#define ROWS_PER_PACKET
Definition: lpi_spx1.cpp:1391
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3738
#define SOPLEX_TRY(messagehdlr, x)
Definition: lpi_spx1.cpp:166
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:2969
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3663
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:2017
polyscip::Polyscip::PolyscipStatus Status
abbreviation
Definition: main.cpp:29
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5496
#define COLS_PER_PACKET
Definition: lpi_spx1.cpp:1389
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:140
static int colpacketNum(int ncols)
Definition: lpi_spx1.cpp:1487
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_spx1.cpp:4220
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:3307
static SPxLP::SPxSense spxObjsen(SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:1587
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4940
static SCIP_RETCODE pricing(SCIP *scip, SCIP_PRICER *pricer, SCIP_Real *lowerbound, SCIP_Bool farkas)
Definition: pricer_stp.c:176
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3527
static char * spxdesc
Definition: lpi_spx1.cpp:1636
static const char spxname[20]
Definition: lpi_spx1.cpp:1633
SCIP_RETCODE SCIPlpiGetColNames(SCIP_LPI *lpi, int firstcol, int lastcol, char **colnames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2695
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:3277
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:418
#define NULL
Definition: lpi_spx1.cpp:155
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:3381
int * rstat
Definition: lpi_clp.cpp:99
#define REALABS(x)
Definition: def.h:201
const char * SCIPlpiGetSolverDesc(void)
Definition: lpi_spx1.cpp:1662
int cstatsize
Definition: lpi_clp.cpp:100
#define SCIP_CALL(x)
Definition: def.h:384
SCIP_Bool SCIPlpiHasBarrierSolve(void)
Definition: lpi_spx1.cpp:1711
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_spx1.cpp:3456
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:3059
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_spx1.cpp:5111
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_spx1.cpp:2095
static SCIP_Bool fileExists(const char *filename)
Definition: lpi_spx1.cpp:5443
void SCIPencodeDualBit(const int *inp, SCIP_DUALPACKET *out, int count)
Definition: bitencode.c:229
SCIP_RETCODE SCIPlpiReadLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:5459
#define EPSCEIL(x, eps)
Definition: def.h:211
#define SOPLEX_SUBVERSION
Definition: lpi_spx1.cpp:92
SCIP_Bool SCIPlpiWasSolved(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3437
COLPACKET * packcstat
Definition: lpi_clp.cpp:127
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:458
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3477
unsigned int SCIP_DUALPACKET
Definition: bitencode.h:33
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_spx1.cpp:3769
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:2117
#define SCIP_Bool
Definition: def.h:84
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_spx1.cpp:4959
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_spx1.cpp:1963
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:447
SCIP_RETCODE SCIPlpiWriteState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_spx1.cpp:4988
SCIP_Real SCIPlpiInfinity(SCIP_LPI *)
Definition: lpi_spx1.cpp:5409
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_spx1.cpp:2274
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3620
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_spx1.cpp:4809
SCIP_Bool SCIPlpiIsDualInfeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3607
#define BMSallocMemoryCPP(size)
Definition: memory.h:114
unsigned short Type
Definition: cons_xor.c:121
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:460
#define MAX(x, y)
Definition: tclique_def.h:83
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_spx1.cpp:2721
static void lpistatePack(SCIP_LPISTATE *lpistate, const int *cstat, const int *rstat)
Definition: lpi_spx1.cpp:1505
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_spx1.cpp:4133
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3639
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_spx1.cpp:1695
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_spx1.cpp:2166
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3725
SCIP_Real * r
Definition: circlepacking.c:50
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:2641
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:3351
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_spx1.cpp:3013
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_spx1.cpp:3846
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3043
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:1803
SLUFactor * factorization
Definition: lpi_spx1.cpp:1405
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_spx1.cpp:2362
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_spx1.cpp:2815
char * initSpxDesc()
Definition: lpi_spx1.cpp:1638
static void lpistateUnpack(const SCIP_LPISTATE *lpistate, int *cstat, int *rstat)
Definition: lpi_spx1.cpp:1521
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3580
public methods for message output
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4760
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_spx1.cpp:2764
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3699
SCIP_DUALPACKET COLPACKET
Definition: lpi_spx1.cpp:1388
#define SCIP_Real
Definition: def.h:177
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3540
SCIP_VAR ** y
Definition: circlepacking.c:55
SPxSCIP * spx
Definition: lpi_spx1.cpp:1398
#define BMSallocMemory(ptr)
Definition: memory.h:111
#define SCIP_INVALID
Definition: def.h:197
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:120
SCIP_DUALPACKET ROWPACKET
Definition: lpi_spx1.cpp:1390
#define SOPLEX_TRY_ABORT(x)
Definition: lpi_spx1.cpp:211
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_spx1.cpp:2318
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3565
SCIP_MESSAGEHDLR * messagehdlr
Definition: lpi_cpx.c:175
#define UNKNOWN
Definition: sepa_mcf.c:4095
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:444
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_spx1.cpp:5385
struct fixed_graph_components FIXED
Definition: graphdefs.h:119
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_spx1.cpp:3712
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_spx1.cpp:2843
#define EPSFLOOR(x, eps)
Definition: def.h:210
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:123
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:430
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_spx1.cpp:2298
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_spx1.cpp:4355
#define SCIP_ALLOC(x)
Definition: def.h:395
#define SCIPABORT()
Definition: def.h:356
const char * SCIPlpiGetSolverName(void)
Definition: lpi_spx1.cpp:1653
int * cstat
Definition: lpi_clp.cpp:98
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_spx1.cpp:3751
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_spx1.cpp:5285
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_spx1.cpp:1985