Scippy

SoPlex

Sequential object-oriented simPlex

spxsolver.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2015 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 #include <assert.h>
17 #include <iostream>
18 #include <sstream>
19 
20 #include "spxdefines.h"
21 #include "soplex.h"
22 #include "spxpricer.h"
23 #include "spxratiotester.h"
24 #include "spxstarter.h"
25 #include "spxout.h"
26 #include "timerfactory.h"
27 
28 namespace soplex
29 {
30 #define MAXIMUM(x,y) ((x)>(y) ? (x) : (y))
31 
32 bool SPxSolver::read(std::istream& in, NameSet* rowNames,
33  NameSet* colNames, DIdxSet* intVars)
34 {
35  if( initialized )
36  {
37  clear();
38  unInit();
39 
40  if (thepricer)
41  thepricer->clear();
42 
43  if (theratiotester)
45  }
46 
47  unLoad();
48  if (!SPxLP::read(in, rowNames, colNames, intVars))
49  return false;
50 
51  theLP = this;
52 
53  return true;
54 }
55 
57 {
59  unInit();
60  unLoad();
61  theLP = this;
63  if (thepricer)
64  thepricer->clear();
65  if (theratiotester)
67 }
68 
69 void SPxSolver::loadLP(const SPxLP& lp)
70 {
71  clear();
72  unInit();
73  unLoad();
75  if (thepricer)
76  thepricer->clear();
77  if (theratiotester)
79  SPxLP::operator=(lp);
80  reDim();
81  SPxBasis::load(this);
82 }
83 
84 void SPxSolver::setSolver(SLinSolver* slu, const bool destroy)
85 {
86  // we need to set the outstream before we load the solver to ensure that the basis
87  // can be initialized with this pointer in loadSolver()
88  assert(spxout != 0);
89  slu->spxout = spxout;
90  SPxBasis::loadSolver(slu, destroy);
91 }
92 
94 {
95  unInit();
97  SPxBasis::load(this);
98  SPxBasis::loadDesc(p_desc);
100 }
101 
102 void SPxSolver::setPricer(SPxPricer* x, const bool destroy)
103 {
104 
105  assert(!freePricer || thepricer != 0);
106 
107  if(freePricer)
108  {
109  delete thepricer;
110  thepricer = 0;
111  }
112 
113  if (x != 0 && x != thepricer)
114  {
115  setPricing(FULL);
116  if (isInitialized())
117  x->load(this);
118  else
119  x->clear();
120  }
121 
122  if (thepricer && thepricer != x)
123  thepricer->clear();
124  thepricer = x;
125 
126  freePricer = destroy;
127 }
128 
129 void SPxSolver::setTester(SPxRatioTester* x, const bool destroy)
130 {
131 
132  assert(!freeRatioTester || theratiotester != 0);
133 
134  if(freeRatioTester)
135  {
136  delete theratiotester;
137  theratiotester = 0;
138  }
139 
140  if (x)
141  {
142  if (isInitialized() && x != theratiotester)
143  x->load(this);
144  else
145  x->clear();
146  }
147 
148  if (theratiotester !=0 && theratiotester != x)
150  theratiotester = x;
151 
152  freeRatioTester = destroy;
153 }
154 
155 void SPxSolver::setStarter(SPxStarter* x, const bool destroy)
156 {
157 
158  assert(!freeStarter || thestarter != 0);
159 
160  if(freeStarter)
161  {
162  delete thestarter;
163  thestarter = 0;
164  }
165  thestarter = x;
166 
167  freeStarter = destroy;
168 }
169 
171 {
172 
173  if (theType != tp)
174  {
175  theType = tp;
176 
178 
179  unInit();
180 #if 0
181  else
182  {
183  if (!matrixIsSetup)
184  {
185  SPxBasis::load(this);
186  // SPxBasis::load(desc());
187  // not needed, because load(this) allready loads descriptor
188  }
189  factorized = false;
190  m_numCycle = 0;
191 #endif
192  MSG_INFO3( (*spxout), (*spxout) << "Switching to "
193  << static_cast<const char*>((tp == LEAVE)
194  ? "leaving" : "entering")
195  << " algorithm" << std::endl; )
196  }
197 }
198 
200 {
201 
202  Real tmpfeastol = feastol();
203  Real tmpopttol = opttol();
204 
205  theRep = p_rep;
206 
207  if (theRep == COLUMN)
208  {
209  thevectors = colSet();
210  thecovectors = rowSet();
211  theFrhs = &primRhs;
212  theFvec = &primVec;
213  theCoPrhs = &dualRhs;
214  theCoPvec = &dualVec;
215  thePvec = &addVec;
217  theCPvec = thePvec;
222  }
223  else
224  {
225  assert(theRep == ROW);
226 
227  thevectors = rowSet();
228  thecovectors = colSet();
229  theFrhs = &dualRhs;
230  theFvec = &dualVec;
231  theCoPrhs = &primRhs;
232  theCoPvec = &primVec;
233  thePvec = &addVec;
234  theRPvec = thePvec;
240  }
241  unInit();
242  reDim();
243 
245 
246  setFeastol(tmpfeastol);
247  setOpttol(tmpopttol);
248 
252 
253  if (thepricer && thepricer->solver() == this)
254  thepricer->setRep(p_rep);
255 }
256 
258 {
259 
260  if (p_rep != theRep)
261  initRep(p_rep);
262 }
263 
264 // needed for strongbranching. use carefully
266 {
267 
268  initialized = true;
269 
270  if (type() == ENTER)
271  {
272  if (rep() == COLUMN)
273  setPrimalBounds();
274  else
276 
277  setEnterBounds();
279  }
280  else
281  {
282  if (rep() == ROW)
283  setPrimalBounds();
284  else
286 
287  setLeaveBounds();
289  }
290 
292  computePvec();
293  computeFrhs();
295 
296  theShift = 0.0;
297  lastShift = 0.0;
298 
299  if (type() == ENTER)
300  {
301  computeCoTest();
302  computeTest();
303  }
304  else
305  {
306  computeFtest();
307  }
308  assert((testBounds(), 1));
309 }
310 
312 {
313  nClckSkipsLeft = 0;
314  nCallsToTimelim = 0;
315  theCumulativeTime = 0.0;
316 }
317 
319 {
320 
321  assert(thepricer != 0);
322  assert(theratiotester != 0);
323 
324  if (!initialized)
325  {
326  initialized = true;
327  reDim();
328  if (SPxBasis::status() <= SPxBasis::NO_PROBLEM || solver() != this)
329  SPxBasis::load(this);
330  initialized = false;
331  }
332  if (!matrixIsSetup)
334 
335  // Inna/Tobi: don't "upgrade" a singular basis to a regular one
337  return;
338 
339  //factorized = false;
340  m_numCycle = 0;
341 
342  if (type() == ENTER)
343  {
344  if (rep() == COLUMN)
345  {
346  setPrimalBounds();
348  }
349  else
350  {
353  }
354  setEnterBounds();
356  // prepare support vectors for sparse pricing
362  }
363  else
364  {
365  if (rep() == ROW)
366  {
367  setPrimalBounds();
369  }
370  else
371  {
374  }
375  setLeaveBounds();
377  // prepare support vectors for sparse pricing
381  }
382 
383  // we better factorize explicitly before solving
384  if( !factorized )
386 
387  // we need to abort in case the factorization failed
389  {
390  throw SPxStatusException("XINIT01 Singular basis in initialization detected.");
391  }
392 
394  computePvec();
395  computeFrhs();
397 
398  theShift = 0.0;
399 
400  if (type() == ENTER)
401  {
402  shiftFvec();
404 
405  computeCoTest();
406  computeTest();
407  }
408  else
409  {
410  shiftPvec();
412 
413  computeFtest();
414  }
415 
416  if (!initialized)
417  {
418  // if(thepricer->solver() != this)
419  thepricer->load(this);
420  // if(theratiotester->solver() != this)
421  theratiotester->load(this);
422  initialized = true;
423  }
424 }
425 
427 {
428  thePricing = pr;
429  if (initialized && type() == ENTER)
430  {
431  computePvec();
432  computeCoTest();
433  computeTest();
434  }
435 }
436 
437 /*
438  The following method resizes all vectors and arrays of |SoPlex|
439  (excluding inherited vectors).
440  */
442 {
443 
444  int newsize = SPxLP::nCols() > SPxLP::nRows() ? SPxLP::nCols() : SPxLP::nRows();
445 
446  if (newsize > unitVecs.size())
447  {
448  unitVecs.reSize(newsize);
449 
450  while (newsize-- > 0)
451  unitVecs[newsize] = UnitVector(newsize);
452  }
453 
454  if (isInitialized())
455  {
456  theFrhs->reDim(dim());
457  theFvec->reDim(dim());
458  thePvec->reDim(coDim());
459 
460  theCoPrhs->reDim(dim());
461  theCoPvec->reDim(dim());
462 
463  theTest.reDim(coDim());
464  theCoTest.reDim(dim());
465 
470  theUBbound.reDim(dim());
471  theLBbound.reDim(dim());
472  }
473 }
474 
476 {
477  unitVecs.reSize(0);
478 
479  dualRhs.clear();
480  dualVec.clear();
481  primRhs.clear();
482  primVec.clear();
483  addVec.clear();
484  theURbound.clear();
485  theLRbound.clear();
486  theUCbound.clear();
487  theLCbound.clear();
488  theTest.clear();
489  theCoTest.clear();
490 
492  unInit();
493  SPxLP::clear();
495  // clear the basis only when theLP is present, because LP data (nrows, ncols) is used in reDim()
496  if( theLP != 0 )
497  SPxBasis::reDim();
498 
503 }
504 
506 {
507  theFvec->clearUpdate();
508  thePvec->clearUpdate();
510  solveVector2 = 0;
511  solveVector3 = 0;
512  coSolveVector2 = 0;
513  coSolveVector3 = 0;
514 }
515 
516 /*
517  When the basis matrix factorization is recomputed from scratch,
518  we also recompute the vectors.
519  */
521 {
522 
523  MSG_INFO3( (*spxout), (*spxout) << " --- refactorizing basis matrix" << std::endl; )
524 
525  try
526  {
528  }
529  catch( const SPxStatusException& E )
530  {
532  m_status = SINGULAR;
533  std::stringstream s;
534  s << "Basis is singular (numerical troubles, feastol = " << feastol() << ", opttol = " << opttol() << ")";
535  throw SPxStatusException(s.str());
536  }
537 
538  if( !initialized )
539  {
540  init(); // not sure if init() is neccessary here
541  // we must not go on here because not all vectors (e.g. fVec) may be set up correctly
542  return;
543  }
544 
546  {
547 #ifndef NDEBUG
548  DVector ftmp(fVec());
549  DVector ptmp(pVec());
550  DVector ctmp(coPvec());
551 #endif // NDEBUG
552 
553  if (type() == LEAVE)
554  {
555  /* we have to recompute theFrhs, because roundoff errors can occur during updating, especially when
556  * columns/rows with large bounds are present
557  */
558  computeFrhs();
561 
562 #ifndef NDEBUG
563  ftmp -= fVec();
564  ptmp -= pVec();
565  ctmp -= coPvec();
566  if (ftmp.length() > DEFAULT_BND_VIOL)
567  {
568  MSG_DEBUG( std::cout << "DSOLVE21 fVec: " << ftmp.length() << std::endl; )
569  ftmp = fVec();
570  multBaseWith(ftmp);
571  ftmp -= fRhs();
572  if (ftmp.length() > DEFAULT_BND_VIOL)
573  MSG_ERROR( std::cerr << "ESOLVE29 " << iteration() << ": fVec error = "
574  << ftmp.length() << " exceeding DEFAULT_BND_VIOL = " << DEFAULT_BND_VIOL << std::endl; )
575  }
576  if (ctmp.length() > DEFAULT_BND_VIOL)
577  {
578  MSG_DEBUG( std::cout << "DSOLVE23 coPvec: " << ctmp.length() << std::endl; )
579  ctmp = coPvec();
580  multWithBase(ctmp);
581  ctmp -= coPrhs();
582  if (ctmp.length() > DEFAULT_BND_VIOL)
583  MSG_ERROR( std::cerr << "ESOLVE30 " << iteration() << ": coPvec error = "
584  << ctmp.length() << " exceeding DEFAULT_BND_VIOL = " << DEFAULT_BND_VIOL << std::endl; )
585  }
586  if (ptmp.length() > DEFAULT_BND_VIOL)
587  {
588  MSG_DEBUG( std::cout << "DSOLVE24 pVec: " << ptmp.length() << std::endl; )
589  }
590 #endif // NDEBUG
591 
592  computeFtest();
593 #if 0 /* was deactivated */
594  computePvec();
595 #endif
596  }
597  else
598  {
599  assert(type() == ENTER);
600 
602  computeCoTest();
603 
604  if (pricing() == FULL)
605  {
606 #if 0 /* was deactivated (this is probably too expansive) */
607  computePvec();
608 #endif
609  /* was deactivated, but this leads to warnings in testVecs() */
610  computeTest();
611  }
612  }
613  }
614 
615 #ifdef ENABLE_ADDITIONAL_CHECKS
616  /* moved this test after the computation of fTest and coTest below, since these vectors might not be set up at top, e.g. for an initial basis */
618  testVecs();
619 #endif
620 }
621 
622 /* We compute how much the current solution violates (primal or dual) feasibility. In the
623  row/enter or column/leave algorithm the maximum violation of dual feasibility is
624  computed. In the row/leave or column/enter algorithm the primal feasibility is checked. */
626 {
627  Real inf = 0.0;
628 
629  if (type() == ENTER)
630  {
631  for (int i = 0; i < dim(); i++)
632  {
633  if ((*theFvec)[i] > theUBbound[i])
634  inf = MAXIMUM(inf, (*theFvec)[i] - theUBbound[i]);
635  if (theLBbound[i] > (*theFvec)[i])
636  inf = MAXIMUM(inf, theLBbound[i] - (*theFvec)[i]);
637  }
638  }
639  else
640  {
641  assert(type() == LEAVE);
642 
643  for (int i = 0; i < dim(); i++)
644  {
645  if ((*theCoPvec)[i] > (*theCoUbound)[i])
646  inf = MAXIMUM(inf, (*theCoPvec)[i] - (*theCoUbound)[i]);
647  if ((*theCoLbound)[i] > (*theCoPvec)[i])
648  inf = MAXIMUM(inf, (*theCoLbound)[i] - (*theCoPvec)[i]);
649  }
650  for (int i = 0; i < coDim(); i++)
651  {
652  if ((*thePvec)[i] > (*theUbound)[i])
653  inf = MAXIMUM(inf, (*thePvec)[i] - (*theUbound)[i]);
654  else if ((*thePvec)[i] < (*theLbound)[i])
655  inf = MAXIMUM(inf, (*theLbound)[i] - (*thePvec)[i]);
656  }
657  }
658 
659  return inf;
660 }
661 
663 {
664  int i;
665  Real val = 0;
666  const SPxBasis::Desc& ds = desc();
667 
668 #ifndef ADDITIONAL_CHECKS
669  // if the value is available we don't need to recompute it
671  return m_nonbasicValue;
672 #endif
673 
674  if (rep() == COLUMN)
675  {
676  if (type() == LEAVE)
677  {
678  for (i = nCols() - 1; i >= 0; --i)
679  {
680  switch (ds.colStatus(i))
681  {
683  val += theUCbound[i] * SPxLP::upper(i);
684  //@ val += maxObj(i) * SPxLP::upper(i);
685  break;
687  val += theLCbound[i] * SPxLP::lower(i);
688  //@ val += maxObj(i) * SPxLP::lower(i);
689  break;
691  val += maxObj(i) * SPxLP::lower(i);
692  break;
693  default:
694  break;
695  }
696  }
697  for (i = nRows() - 1; i >= 0; --i)
698  {
699  switch (ds.rowStatus(i))
700  {
702  val += theLRbound[i] * SPxLP::rhs(i);
703  break;
705  val += theURbound[i] * SPxLP::lhs(i);
706  break;
708  val += maxRowObj(i) * SPxLP::lhs(i);
709  break;
710  default:
711  break;
712  }
713  }
714  }
715  else
716  {
717  assert(type() == ENTER);
718  for (i = nCols() - 1; i >= 0; --i)
719  {
720  switch (ds.colStatus(i))
721  {
723  val += maxObj(i) * theUCbound[i];
724  break;
726  val += maxObj(i) * theLCbound[i];
727  break;
729  assert(theLCbound[i] == theUCbound[i]);
730  val += maxObj(i) * theLCbound[i];
731  break;
732  default:
733  break;
734  }
735  }
736  for (i = nRows() - 1; i >= 0; --i)
737  {
738  switch (ds.rowStatus(i))
739  {
741  val += maxRowObj(i) * theLRbound[i];
742  break;
744  val += maxRowObj(i) * theURbound[i];
745  break;
747  val += maxRowObj(i) * theURbound[i];
748  break;
749  default:
750  break;
751  }
752  }
753  }
754  }
755  else
756  {
757  assert(rep() == ROW);
758  assert(type() == ENTER);
759  for (i = nCols() - 1; i >= 0; --i)
760  {
761  switch (ds.colStatus(i))
762  {
764  val += theUCbound[i] * lower(i);
765  break;
767  val += theLCbound[i] * upper(i);
768  break;
770  val += theLCbound[i] * upper(i);
771  val += theUCbound[i] * lower(i);
772  break;
773  default:
774  break;
775  }
776  }
777  for (i = nRows() - 1; i >= 0; --i)
778  {
779  switch (ds.rowStatus(i))
780  {
782  val += theURbound[i] * lhs(i);
783  break;
785  val += theLRbound[i] * rhs(i);
786  break;
788  val += theLRbound[i] * rhs(i);
789  val += theURbound[i] * lhs(i);
790  break;
791  default:
792  break;
793  }
794  }
795  }
796 
797 #ifdef ADDITIONAL_CHECKS
799  {
800  MSG_ERROR( std::cerr << "stored nonbasic value: " << m_nonbasicValue << ", correct nonbasic value: " << val << std::endl; )
801  assert(EQrel(m_nonbasicValue, val,1e-14));
802  }
803 #endif
804 
806  {
807  m_nonbasicValue = val;
809  }
810 
811  return val;
812 }
813 
815 {
816  assert(isInitialized());
817 
818  Real x;
819 
820  // calling value() without having a suitable status is an error.
821  if (!isInitialized())
822  return infinity;
823 
824  if (rep() == ROW)
825  {
826  if (type() == LEAVE)
827  x = SPxLP::spxSense() * (coPvec() * fRhs()); // the contribution of maxRowObj() is missing
828  else
829  x = SPxLP::spxSense() * (nonbasicValue() + (coPvec() * fRhs()));
830  }
831  else
832  x = SPxLP::spxSense() * (nonbasicValue() + fVec() * coPrhs());
833 
834  return x;
835 }
836 
838 {
840  m_nonbasicValue += objChange;
841 
842  MSG_DEBUG( std::cout
843  << "Iteration: " << iteration()
844  << ": updated objValue: " << objChange
845  << ", new value: " << m_nonbasicValue
846  << ", correct value: " << nonbasicValue()
847  << std::endl;
848  )
849 
851 }
852 
853 
854 
856 {
857 
858  if( d <= 0.0 )
859  throw SPxInterfaceException("XSOLVE30 Cannot set feastol less than or equal to zero.");
860 
861  if( theRep == COLUMN )
862  m_entertol = d;
863  else
864  m_leavetol = d;
865 }
866 
868 {
869 
870  if( d <= 0.0 )
871  throw SPxInterfaceException("XSOLVE31 Cannot set opttol less than or equal to zero.");
872 
873  if( theRep == COLUMN )
874  m_leavetol = d;
875  else
876  m_entertol = d;
877 }
878 
880 {
881 
882  if( d <= 0.0 )
883  throw SPxInterfaceException("XSOLVE32 Cannot set delta less than or equal to zero.");
884 
885  m_entertol = d;
886  m_leavetol = d;
887 }
888 
890 {
891  hyperPricingEnter = h;
892  hyperPricingLeave = h;
893  if( h )
894  {
897  }
898 }
899 
901  Type p_type,
902  Representation p_rep,
903  Timer::TYPE ttype)
904  : theType (p_type)
905  , thePricing(FULL)
906  , theRep(p_rep)
907  , theTime(0)
908  , timerType(ttype)
909  , theCumulativeTime(0.0)
910  , maxIters (-1)
911  , maxTime (infinity)
912  , nClckSkipsLeft(0)
913  , nCallsToTimelim(0)
914  , objLimit(infinity)
915  , m_status(UNKNOWN)
916  , m_nonbasicValue(0.0)
917  , m_nonbasicValueUpToDate(false)
918  , theShift (0)
919  , m_maxCycle(100)
920  , m_numCycle(0)
921  , initialized (false)
922  , solveVector2 (0)
923  , solveVector3 (0)
924  , coSolveVector2(0)
925  , coSolveVector3(0)
926  , freePricer (false)
927  , freeRatioTester (false)
928  , freeStarter (false)
929  , displayLine (0)
930  , displayFreq (200)
932  , unitVecs (0)
933  , primVec (0, Param::epsilon())
934  , dualVec (0, Param::epsilon())
935  , addVec (0, Param::epsilon())
936  , thepricer (0)
937  , theratiotester (0)
938  , thestarter (0)
939  , infeasibilities(0)
940  , infeasibilitiesCo(0)
941  , isInfeasible(0)
942  , isInfeasibleCo(0)
943  , sparsePricingLeave(false)
944  , sparsePricingEnter(false)
945  , sparsePricingEnterCo(false)
946  , hyperPricingLeave(true)
947  , hyperPricingEnter(true)
951 {
953 
955 
956  theLP = this;
957  initRep(p_rep);
958 
959  // info: SPxBasis is not consistent in this moment.
960  //assert(SPxSolver::isConsistent());
961 }
962 
964 {
965  assert(!freePricer || thepricer != 0);
966  assert(!freeRatioTester || theratiotester != 0);
967  assert(!freeStarter || thestarter != 0);
968 
969  if(freePricer)
970  {
971  delete thepricer;
972  thepricer = 0;
973  }
974 
975  if(freeRatioTester)
976  {
977  delete theratiotester;
978  theratiotester = 0;
979  }
980 
981  if(freeStarter)
982  {
983  delete thestarter;
984  thestarter = 0;
985  }
986 
987  // free timer
988  theTime->~Timer();
989  spx_free(theTime);
990 }
991 
992 
994 {
995  if(this != &base)
996  {
997  SPxLP::operator=(base);
998  SPxBasis::operator=(base);
999  theType = base.theType;
1000  thePricing = base.thePricing;
1001  theRep = base.theRep;
1002  timerType = base.timerType;
1003  maxIters = base.maxIters;
1004  maxTime = base.maxTime;
1005  objLimit = base.objLimit;
1006  m_status = base.m_status;
1007  m_entertol = base.m_entertol;
1008  m_leavetol = base.m_leavetol;
1009  theShift = base.theShift;
1010  lastShift = base.lastShift;
1011  m_maxCycle = base.m_maxCycle;
1012  m_numCycle = base.m_numCycle;
1013  initialized = base.initialized;
1018  displayFreq = base.displayFreq;
1020  unitVecs = base.unitVecs;
1021  primRhs = base.primRhs;
1022  primVec = base.primVec;
1023  dualRhs = base.dualRhs;
1024  dualVec = base.dualVec;
1025  addVec = base.addVec;
1026  theURbound = base.theURbound;
1027  theLRbound = base.theLRbound;
1028  theUCbound = base.theUCbound;
1029  theLCbound = base.theLCbound;
1030  theUBbound = base.theUBbound;
1031  theLBbound = base.theLBbound;
1032  theCoTest = base.theCoTest;
1033  theTest = base.theTest;
1034  primalRay = base.primalRay;
1035  dualFarkas = base.dualFarkas;
1036  leaveCount = base.leaveCount;
1037  enterCount = base.enterCount;
1041  isInfeasible = base.isInfeasible;
1052 
1053  if (base.theRep == COLUMN)
1054  {
1055  thevectors = colSet();
1056  thecovectors = rowSet();
1057  theFrhs = &primRhs;
1058  theFvec = &primVec;
1059  theCoPrhs = &dualRhs;
1060  theCoPvec = &dualVec;
1061  thePvec = &addVec;
1062  theRPvec = theCoPvec;
1063  theCPvec = thePvec;
1064  theUbound = &theUCbound;
1065  theLbound = &theLCbound;
1068  }
1069  else
1070  {
1071  assert(base.theRep == ROW);
1072 
1073  thevectors = rowSet();
1074  thecovectors = colSet();
1075  theFrhs = &dualRhs;
1076  theFvec = &dualVec;
1077  theCoPrhs = &primRhs;
1078  theCoPvec = &primVec;
1079  thePvec = &addVec;
1080  theRPvec = thePvec;
1081  theCPvec = theCoPvec;
1082  theUbound = &theURbound;
1083  theLbound = &theLRbound;
1086  }
1087 
1088  SPxBasis::theLP = this;
1089 
1090  assert(!freePricer || thepricer != 0);
1091  assert(!freeRatioTester || theratiotester != 0);
1092  assert(!freeStarter || thestarter != 0);
1093 
1094  // thepricer
1095  if(freePricer)
1096  {
1097  delete thepricer;
1098  thepricer = 0;
1099  }
1100  if(base.thepricer == 0)
1101  {
1102  thepricer = 0;
1103  freePricer = false;
1104  }
1105  else
1106  {
1107  thepricer = base.thepricer->clone();
1108  freePricer = true;
1109  thepricer->load(this);
1110  }
1111 
1112  // theratiotester
1113  if(freeRatioTester)
1114  {
1115  delete theratiotester;
1116  theratiotester = 0;
1117  }
1118  if(base.theratiotester == 0)
1119  {
1120  theratiotester = 0;
1121  freeRatioTester = false;
1122  }
1123  else
1124  {
1126  freeRatioTester = true;
1127  theratiotester->load(this);
1128  }
1129 
1130  // thestarter
1131  if(freeStarter)
1132  {
1133  delete thestarter;
1134  thestarter = 0;
1135  }
1136  if(base.thestarter == 0)
1137  {
1138  thestarter = 0;
1139  freeStarter = false;
1140  }
1141  else
1142  {
1143  thestarter = base.thestarter->clone();
1144  freeStarter = true;
1145  }
1146 
1147  assert(SPxSolver::isConsistent());
1148  }
1149 
1150  return *this;
1151 }
1152 
1153 
1155  : SPxLP (base)
1156  , SPxBasis(base)
1157  , theType(base.theType)
1158  , thePricing(base.thePricing)
1159  , theRep(base.theRep)
1160  , timerType(base.timerType)
1161  , theCumulativeTime(base.theCumulativeTime)
1162  , maxIters(base.maxIters)
1163  , maxTime(base.maxTime)
1164  , nClckSkipsLeft(base.nClckSkipsLeft)
1165  , nCallsToTimelim(base.nCallsToTimelim)
1166  , objLimit(base.objLimit)
1167  , m_status(base.m_status)
1168  , m_nonbasicValue(base.m_nonbasicValue)
1169  , m_nonbasicValueUpToDate(base.m_nonbasicValueUpToDate)
1170  , m_entertol(base.m_entertol)
1171  , m_leavetol(base.m_leavetol)
1172  , theShift(base.theShift)
1173  , lastShift(base.lastShift)
1174  , m_maxCycle(base.m_maxCycle)
1175  , m_numCycle(base.m_numCycle)
1176  , initialized(base.initialized)
1177  , solveVector2 (0)
1178  , solveVector2rhs(base.solveVector2rhs)
1179  , solveVector3 (0)
1180  , solveVector3rhs(base.solveVector3rhs)
1181  , coSolveVector2(0)
1182  , coSolveVector2rhs(base.coSolveVector2rhs)
1183  , coSolveVector3(0)
1184  , coSolveVector3rhs(base.coSolveVector3rhs)
1185  , instableLeaveNum(base.instableLeaveNum)
1186  , instableLeave(base.instableLeave)
1187  , instableLeaveVal(base.instableLeaveVal)
1188  , instableEnterId(base.instableEnterId)
1189  , instableEnter(base.instableEnter)
1190  , instableEnterVal(base.instableEnterVal)
1191  , displayLine(base.displayLine)
1192  , displayFreq(base.displayFreq)
1193  , sparsePricingFactor(base.sparsePricingFactor)
1194  , unitVecs(base.unitVecs)
1195  , primRhs(base.primRhs)
1196  , primVec(base.primVec)
1197  , dualRhs(base.dualRhs)
1198  , dualVec(base.dualVec)
1199  , addVec(base.addVec)
1200  , theURbound(base.theURbound)
1201  , theLRbound(base.theLRbound)
1202  , theUCbound(base.theUCbound)
1203  , theLCbound(base.theLCbound)
1204  , theUBbound(base.theUBbound)
1205  , theLBbound(base.theLBbound)
1206  , theCoTest(base.theCoTest)
1207  , theTest(base.theTest)
1208  , primalRay(base.primalRay)
1209  , dualFarkas(base.dualFarkas)
1210  , leaveCount(base.leaveCount)
1211  , enterCount(base.enterCount)
1212  , primalCount(base.primalCount)
1213  , boundflips(base.boundflips)
1214  , totalboundflips(base.totalboundflips)
1215  , infeasibilities(base.infeasibilities)
1216  , infeasibilitiesCo(base.infeasibilitiesCo)
1217  , isInfeasible(base.isInfeasible)
1218  , isInfeasibleCo(base.isInfeasibleCo)
1219  , sparsePricingLeave(base.sparsePricingLeave)
1220  , sparsePricingEnter(base.sparsePricingEnter)
1221  , sparsePricingEnterCo(base.sparsePricingEnterCo)
1222  , hyperPricingLeave(base.hyperPricingLeave)
1223  , hyperPricingEnter(base.hyperPricingEnter)
1224  , remainingRoundsLeave(base.remainingRoundsLeave)
1225  , remainingRoundsEnter(base.remainingRoundsEnter)
1226  , remainingRoundsEnterCo(base.remainingRoundsEnterCo)
1227  , spxout(base.spxout)
1228 {
1230 
1231  if (base.theRep == COLUMN)
1232  {
1233  thevectors = colSet();
1234  thecovectors = rowSet();
1235  theFrhs = &primRhs;
1236  theFvec = &primVec;
1237  theCoPrhs = &dualRhs;
1238  theCoPvec = &dualVec;
1239  thePvec = &addVec;
1240  theRPvec = theCoPvec;
1241  theCPvec = thePvec;
1242  theUbound = &theUCbound;
1243  theLbound = &theLCbound;
1246  }
1247  else
1248  {
1249  assert(base.theRep == ROW);
1250 
1251  thevectors = rowSet();
1252  thecovectors = colSet();
1253  theFrhs = &dualRhs;
1254  theFvec = &dualVec;
1255  theCoPrhs = &primRhs;
1256  theCoPvec = &primVec;
1257  thePvec = &addVec;
1258  theRPvec = thePvec;
1259  theCPvec = theCoPvec;
1260  theUbound = &theURbound;
1261  theLbound = &theLRbound;
1264  }
1265 
1266  SPxBasis::theLP = this;
1267 
1268  if(base.thepricer == 0)
1269  {
1270  thepricer = 0;
1271  freePricer = false;
1272  }
1273  else
1274  {
1275  thepricer = base.thepricer->clone();
1276  freePricer = true;
1277  thepricer->clear();
1278  thepricer->load(this);
1279  }
1280 
1281  if(base.theratiotester == 0)
1282  {
1283  theratiotester = 0;
1284  freeRatioTester = false;
1285  }
1286  else
1287  {
1289  freeRatioTester = true;
1290  theratiotester->clear();
1291  theratiotester->load(this);
1292  }
1293 
1294  if(base.thestarter == 0)
1295  {
1296  thestarter = 0;
1297  freeStarter = false;
1298  }
1299  else
1300  {
1301  thestarter = base.thestarter->clone();
1302  freeStarter = true;
1303  }
1304 
1305  assert(SPxSolver::isConsistent());
1306 }
1307 
1309 {
1310 #ifdef ENABLE_CONSISTENCY_CHECKS
1311  if (epsilon() < 0)
1312  return MSGinconsistent("SPxSolver");
1313 
1315  return MSGinconsistent("SPxSolver");
1316 
1317  if (dualVec.delta().getEpsilon() != addVec.delta().getEpsilon())
1318  return MSGinconsistent("SPxSolver");
1319 
1320  if (unitVecs.size() < SPxLP::nCols() || unitVecs.size() < SPxLP::nRows())
1321  return MSGinconsistent("SPxSolver");
1322 
1323  if (initialized)
1324  {
1325  if (theFrhs->dim() != dim())
1326  return MSGinconsistent("SPxSolver");
1327  if (theFvec->dim() != dim())
1328  return MSGinconsistent("SPxSolver");
1329 
1330  if (theCoPrhs->dim() != dim())
1331  return MSGinconsistent("SPxSolver");
1332  if (thePvec->dim() != coDim())
1333  return MSGinconsistent("SPxSolver");
1334  if (theCoPvec->dim() != dim())
1335  return MSGinconsistent("SPxSolver");
1336 
1337  if (theTest.dim() != coDim())
1338  return MSGinconsistent("SPxSolver");
1339  if (theCoTest.dim() != dim())
1340  return MSGinconsistent("SPxSolver");
1341 
1342  if (theURbound.dim() != SPxLP::nRows())
1343  return MSGinconsistent("SPxSolver");
1344  if (theLRbound.dim() != SPxLP::nRows())
1345  return MSGinconsistent("SPxSolver");
1346  if (theUCbound.dim() != SPxLP::nCols())
1347  return MSGinconsistent("SPxSolver");
1348  if (theLCbound.dim() != SPxLP::nCols())
1349  return MSGinconsistent("SPxSolver");
1350  if (theUBbound.dim() != dim())
1351  return MSGinconsistent("SPxSolver");
1352  if (theLBbound.dim() != dim())
1353  return MSGinconsistent("SPxSolver");
1354  }
1355 
1356  if (rep() == COLUMN)
1357  {
1358  if(thecovectors !=
1359  reinterpret_cast<const SVSet*>(static_cast<const LPRowSet*>(this))
1360  || thevectors !=
1361  reinterpret_cast<const SVSet*>(static_cast<const LPColSet*>(this))
1362  || theFrhs != &primRhs ||
1363  theFvec != &primVec ||
1364  theCoPrhs != &dualRhs ||
1365  theCoPvec != &dualVec ||
1366  thePvec != &addVec ||
1367  theRPvec != theCoPvec ||
1368  theCPvec != thePvec ||
1369  theUbound != &theUCbound ||
1370  theLbound != &theLCbound ||
1371  theCoUbound != &theURbound ||
1372  theCoLbound != &theLRbound)
1373  return MSGinconsistent("SPxSolver");
1374  }
1375  else
1376  {
1377  if (thecovectors
1378  != reinterpret_cast<const SVSet*>(static_cast<const LPColSet*>(this))
1379  || thevectors
1380  != reinterpret_cast<const SVSet*>(static_cast<const LPRowSet*>(this))
1381  || theFrhs != &dualRhs ||
1382  theFvec != &dualVec ||
1383  theCoPrhs != &primRhs ||
1384  theCoPvec != &primVec ||
1385  thePvec != &addVec ||
1386  theRPvec != thePvec ||
1387  theCPvec != theCoPvec ||
1388  theUbound != &theURbound ||
1389  theLbound != &theLRbound ||
1390  theCoUbound != &theUCbound ||
1391  theCoLbound != &theLCbound)
1392  return MSGinconsistent("SPxSolver");
1393  }
1394 
1395  return SPxLP::isConsistent()
1396  && primRhs.isConsistent()
1397  && primVec.isConsistent()
1398  && dualRhs.isConsistent()
1399  && dualVec.isConsistent()
1400  && addVec.isConsistent()
1401  && theTest.isConsistent()
1402  && theCoTest.isConsistent()
1408  ;
1409 #else
1410  return true;
1411 #endif
1412 }
1413 
1414 
1416 {
1417  if( p_time < 0.0 )
1418  p_time = infinity;
1419  maxTime = p_time;
1420 }
1421 
1423 {
1424  return maxTime;
1425 }
1426 
1427 void SPxSolver::setTerminationIter(int p_iteration)
1428 {
1429  if( p_iteration < 0 )
1430  p_iteration = -1;
1431  maxIters = p_iteration;
1432 }
1433 
1435 {
1436  return maxIters;
1437 }
1438 
1439 // returns whether current time limit is reached; call to time() may be skipped unless \p forceCheck is true
1440 bool SPxSolver::isTimeLimitReached(const bool forceCheck)
1441 {
1442  // always update the number of calls, since the user might set a time limit later in the solving process
1443  ++nCallsToTimelim;
1444 
1445  // check if a time limit is actually set
1446  if( maxTime < 0 || maxTime >= infinity )
1447  return false;
1448 
1449  // check if the expensive system call to update the time should be skipped again
1450  if( forceCheck || nCallsToTimelim < NINITCALLS || nClckSkipsLeft <= 0 )
1451  {
1452  Real currtime = time();
1453 
1454  if( currtime >= maxTime )
1455  return true;
1456 
1457  // determine the number of times the clock can be skipped again.
1458  int nClckSkips = MAXNCLCKSKIPS;
1459  Real avgtimeinterval = (currtime + cumulativeTime()) / (Real)(nCallsToTimelim);
1460 
1461  // it would not be safe to skip the clock so many times since we are approaching the time limit
1462  if( SAFETYFACTOR * (maxTime - currtime) / (avgtimeinterval + 1e-6) < nClckSkips )
1463  nClckSkips = 0;
1464  nClckSkipsLeft = nClckSkips;
1465  }
1466  else
1467  --nClckSkipsLeft;
1468 
1469  return false;
1470 }
1471 
1472 
1473 /**@todo A first version for the termination value is
1474  * implemented. Currently we check if no bound violations (shifting)
1475  * is present. It might be even possible to use this termination
1476  * value in case of bound violations (shifting) but in this case it
1477  * is quite difficult to determine if we already reached the limit.
1478  */
1480 {
1481  objLimit = p_value;
1482 }
1483 
1485 {
1486  return objLimit;
1487 }
1488 
1491 {
1492  VarStatus vstat;
1493 
1494  switch( stat )
1495  {
1497  vstat = ON_LOWER;
1498  break;
1500  vstat = ON_UPPER;
1501  break;
1503  vstat = FIXED;
1504  break;
1506  vstat = ZERO;
1507  break;
1513  vstat = BASIC;
1514  break;
1515  default:
1516  MSG_ERROR( std::cerr << "ESOLVE26 ERROR: unknown basis status (" << stat << ")"
1517  << std::endl; )
1518  throw SPxInternalCodeException("XSOLVE22 This should never happen.");
1519  }
1520  return vstat;
1521 }
1522 
1525 {
1526  SPxBasis::Desc::Status rstat;
1527 
1528  switch( stat )
1529  {
1530  case FIXED :
1531  assert(rhs(row) == lhs(row));
1532  rstat = SPxBasis::Desc::P_FIXED;
1533  break;
1534  case ON_UPPER :
1535  assert(rhs(row) < infinity);
1536  rstat = lhs(row) < rhs(row)
1539  break;
1540  case ON_LOWER :
1541  assert(lhs(row) > -infinity);
1542  rstat = lhs(row) < rhs(row)
1545  break;
1546  case ZERO :
1547  /* A 'free' row (i.e., infinite lower & upper bounds) does not really make sense. The user
1548  * might (think to) know better, e.g., when temporarily turning off a row. We therefore apply
1549  * the same adjustment as in the column case in varStatusToBasisStatusCol(). */
1550  if (lhs(row) <= -infinity && rhs(row) >= infinity)
1551  rstat = SPxBasis::Desc::P_FREE;
1552  else
1553  {
1554  if ( lhs(row) == rhs(row) )
1555  {
1556  assert( rhs(row) < infinity );
1557  rstat = SPxBasis::Desc::P_FIXED;
1558  }
1559  else
1560  {
1561  if ( lhs(row) > -infinity )
1563  else
1564  {
1565  assert( rhs(row) < infinity );
1567  }
1568  }
1569  }
1570  break;
1571  case BASIC :
1572  rstat = dualRowStatus(row);
1573  break;
1574  default:
1575  MSG_ERROR( std::cerr << "ESOLVE27 ERROR: unknown VarStatus (" << int(stat) << ")"
1576  << std::endl; )
1577  throw SPxInternalCodeException("XSOLVE23 This should never happen.");
1578  }
1579  return rstat;
1580 }
1581 
1584 {
1585  SPxBasis::Desc::Status cstat;
1586 
1587  switch( stat )
1588  {
1589  case FIXED :
1590  if (upper(col) == lower(col))
1591  cstat = SPxBasis::Desc::P_FIXED;
1592  else if (maxObj(col) > 0.0)
1594  else
1596  break;
1597  case ON_UPPER :
1598  assert(upper(col) < infinity);
1599  cstat = lower(col) < upper(col)
1602  break;
1603  case ON_LOWER :
1604  assert(lower(col) > -infinity);
1605  cstat = lower(col) < upper(col)
1608  break;
1609  case ZERO :
1610  /* In this case the upper and lower bounds on the variable should be infinite. The bounds
1611  * might, however, have changed and we try to recover from this by changing the status to
1612  * 'resonable' settings. A solve has to find the correct values afterwards. Note that the
1613  * approach below is consistent with changesoplex.cpp (e.g., changeUpperStatus() and
1614  * changeLowerStatus() ). */
1615  if (lower(col) <= -infinity && upper(col) >= infinity)
1616  cstat = SPxBasis::Desc::P_FREE;
1617  else
1618  {
1619  if ( lower(col) == upper(col) )
1620  {
1621  assert( upper(col) < infinity );
1622  cstat = SPxBasis::Desc::P_FIXED;
1623  }
1624  else
1625  {
1626  if ( lower(col) > -infinity )
1628  else
1629  {
1630  assert( upper(col) < infinity );
1632  }
1633  }
1634  }
1635  break;
1636  case BASIC :
1637  cstat = dualColStatus(col);
1638  break;
1639  default:
1640  MSG_ERROR( std::cerr << "ESOLVE28 ERROR: unknown VarStatus (" << int(stat) << ")"
1641  << std::endl; )
1642  throw SPxInternalCodeException("XSOLVE24 This should never happen.");
1643  }
1644  return cstat;
1645 }
1646 
1648 {
1649  assert( 0 <= row && row < nRows() );
1650  return basisStatusToVarStatus( desc().rowStatus( row ) );
1651 }
1652 
1654 {
1655  assert( 0 <= col && col < nCols() );
1656  return basisStatusToVarStatus( desc().colStatus( col ) );
1657 }
1658 
1659 SPxSolver::Status SPxSolver::getBasis(VarStatus row[], VarStatus col[], const int rowsSize, const int colsSize) const
1660 {
1661  const SPxBasis::Desc& d = desc();
1662  int i;
1663 
1664  assert(rowsSize < 0 || rowsSize >= nRows());
1665  assert(colsSize < 0 || colsSize >= nCols());
1666 
1667  if (col)
1668  for (i = nCols() - 1; i >= 0; --i)
1669  col[i] = basisStatusToVarStatus( d.colStatus(i) );
1670 
1671  if (row)
1672  for (i = nRows() - 1; i >= 0; --i)
1673  row[i] = basisStatusToVarStatus( d.rowStatus(i) );
1674 
1675  return status();
1676 }
1677 
1679 {
1680 
1681  int basisdim;
1682 
1683  if ( p_rows.size() != nRows() || p_cols.size() != nCols() )
1684  return false;
1685 
1686  basisdim = 0;
1687  for ( int row = nRows()-1; row >= 0; --row )
1688  {
1689  if ( p_rows[row] == UNDEFINED )
1690  return false;
1691  // row is basic
1692  else if ( p_rows[row] == BASIC )
1693  {
1694  basisdim++;
1695  }
1696  // row is nonbasic
1697  else
1698  {
1699  if ( (p_rows[row] == FIXED && lhs(row) != rhs(row))
1700  || (p_rows[row] == ON_UPPER && rhs(row) >= infinity)
1701  || (p_rows[row] == ON_LOWER && lhs(row) <= -infinity) )
1702  return false;
1703  }
1704  }
1705 
1706  for ( int col = nCols()-1; col >= 0; --col )
1707  {
1708  if ( p_cols[col] == UNDEFINED )
1709  return false;
1710  // col is basic
1711  else if ( p_cols[col] == BASIC )
1712  {
1713  basisdim++;
1714  }
1715  // col is nonbasic
1716  else
1717  {
1718  if ( (p_cols[col] == FIXED && lower(col) != upper(col))
1719  || (p_cols[col] == ON_UPPER && upper(col) >= infinity)
1720  || (p_cols[col] == ON_LOWER && lower(col) <= -infinity) )
1721  return false;
1722  }
1723  }
1724 
1725  if ( basisdim != dim() )
1726  return false;
1727 
1728  // basis valid
1729  return true;
1730 }
1731 
1732 void SPxSolver::setBasis(const VarStatus p_rows[], const VarStatus p_cols[])
1733 {
1734 
1736  SPxBasis::load(this);
1737 
1738  SPxBasis::Desc ds = desc();
1739  int i;
1740 
1741  for(i = 0; i < nRows(); i++)
1742  ds.rowStatus(i) = varStatusToBasisStatusRow( i, p_rows[i] );
1743 
1744  for(i = 0; i < nCols(); i++)
1745  ds.colStatus(i) = varStatusToBasisStatusCol( i, p_cols[i] );
1746 
1747  loadBasis(ds);
1749 }
1750 
1751 void SPxSolver::getNdualNorms(int& nnormsRow, int& nnormsCol) const
1752 {
1753  assert(thepricer != NULL);
1754  return thepricer->getNdualNorms(nnormsRow, nnormsCol);
1755 }
1756 
1757 bool SPxSolver::getDualNorms(int& nnormsRow, int& nnormsCol, Real* norms) const
1758 {
1759  assert(thepricer != NULL);
1760  return thepricer->getDualNorms(nnormsRow, nnormsCol, norms);
1761 }
1762 
1763 bool SPxSolver::setDualNorms(int nnormsRow, int nnormsCol, Real* norms)
1764 {
1765  assert(thepricer != NULL);
1766  return thepricer->setDualNorms(nnormsRow, nnormsCol, norms);
1767 }
1768 
1769 
1770 //
1771 // Auxiliary functions.
1772 //
1773 
1774 // Pretty-printing of variable status.
1775 std::ostream& operator<<( std::ostream& os,
1776  const SPxSolver::VarStatus& status )
1777 {
1778  switch( status )
1779  {
1780  case SPxSolver::BASIC:
1781  os << "BASIC";
1782  break;
1783  case SPxSolver::FIXED:
1784  os << "FIXED";
1785  break;
1786  case SPxSolver::ON_LOWER:
1787  os << "ON_LOWER";
1788  break;
1789  case SPxSolver::ON_UPPER:
1790  os << "ON_UPPER";
1791  break;
1792  case SPxSolver::ZERO:
1793  os << "ZERO";
1794  break;
1795  case SPxSolver::UNDEFINED:
1796  os << "UNDEFINED";
1797  break;
1798  default:
1799  os << "?invalid?";
1800  break;
1801  }
1802  return os;
1803 }
1804 
1805 // Pretty-printing of solver status.
1806 std::ostream& operator<<( std::ostream& os,
1807  const SPxSolver::Status& status )
1808 {
1809  switch ( status )
1810  {
1811  case SPxSolver::ERROR:
1812  os << "ERROR";
1813  break;
1815  os << "NO_RATIOTESTER";
1816  break;
1817  case SPxSolver::NO_PRICER:
1818  os << "NO_PRICER";
1819  break;
1820  case SPxSolver::NO_SOLVER:
1821  os << "NO_SOLVER";
1822  break;
1823  case SPxSolver::NOT_INIT:
1824  os << "NOT_INIT";
1825  break;
1827  os << "ABORT_CYCLING";
1828  break;
1829  case SPxSolver::ABORT_TIME:
1830  os << "ABORT_TIME";
1831  break;
1832  case SPxSolver::ABORT_ITER:
1833  os << "ABORT_ITER";
1834  break;
1836  os << "ABORT_VALUE";
1837  break;
1838  case SPxSolver::SINGULAR:
1839  os << "SINGULAR";
1840  break;
1841  case SPxSolver::NO_PROBLEM:
1842  os << "NO_PROBLEM";
1843  break;
1844  case SPxSolver::REGULAR:
1845  os << "REGULAR";
1846  break;
1847  case SPxSolver::RUNNING:
1848  os << "RUNNING";
1849  break;
1850  case SPxSolver::UNKNOWN:
1851  os << "UNKNOWN";
1852  break;
1853  case SPxSolver::OPTIMAL:
1854  os << "OPTIMAL";
1855  break;
1856  case SPxSolver::UNBOUNDED:
1857  os << "UNBOUNDED";
1858  break;
1859  case SPxSolver::INFEASIBLE:
1860  os << "INFEASIBLE";
1861  break;
1862  default:
1863  os << "?other?";
1864  break;
1865  }
1866  return os;
1867 }
1868 
1869 // Pretty-printing of algorithm.
1870 std::ostream& operator<<( std::ostream& os,
1871  const SPxSolver::Type& status )
1872 {
1873  switch ( status )
1874  {
1875  case SPxSolver::ENTER:
1876  os << "ENTER";
1877  break;
1878  case SPxSolver::LEAVE:
1879  os << "LEAVE";
1880  break;
1881  default:
1882  os << "?other?";
1883  break;
1884  }
1885  return os;
1886 }
1887 
1888 // Pretty-printing of representation.
1889 std::ostream& operator<<( std::ostream& os,
1890  const SPxSolver::Representation& status )
1891 {
1892  switch ( status )
1893  {
1894  case SPxSolver::ROW:
1895  os << "ROW";
1896  break;
1897  case SPxSolver::COLUMN:
1898  os << "COLUMN";
1899  break;
1900  default:
1901  os << "?other?";
1902  break;
1903  }
1904  return os;
1905 }
1906 
1907 
1908 } // namespace soplex