Scippy

SCIP

Solving Constraint Integer Programs

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