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