Scippy

SCIP

Solving Constraint Integer Programs

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