1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*  Copyright (c) 1996-2023 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 SoPlex; see the file LICENSE. If not email to soplex@zib.de.  */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	#include <assert.h>
26   	#include <iostream>
27   	#include <sstream>
28   	
29   	#include "soplex/spxdefines.h"
30   	// #include "soplex.h"
31   	#include "soplex/spxpricer.h"
32   	#include "soplex/spxratiotester.h"
33   	#include "soplex/spxstarter.h"
34   	#include "soplex/spxout.h"
35   	#include "soplex/timerfactory.h"
36   	
37   	namespace soplex
38   	{
39   	template <class R>
40   	bool SPxSolverBase<R>::read(std::istream& in, NameSet* rowNames,
41   	                            NameSet* colNames, DIdxSet* intVars)
42   	{
43   	   if(initialized)
44   	   {
45   	      clear();
46   	      unInit();
47   	
48   	      if(thepricer)
49   	         thepricer->clear();
50   	
51   	      if(theratiotester)
52   	         theratiotester->clear();
53   	   }
54   	
55   	   this->unLoad();
56   	
57   	   if(!SPxLPBase<R>::read(in, rowNames, colNames, intVars))
58   	      return false;
59   	
60   	   this->theLP = this;
61   	
62   	   return true;
63   	}
64   	
65   	template <class R>
66   	void SPxSolverBase<R>::reLoad()
67   	{
68   	   forceRecompNonbasicValue();
69   	   unInit();
70   	   this->unLoad();
71   	   this->theLP = this;
72   	   m_status = SPxSolverBase<R>::UNKNOWN;
73   	
74   	   if(thepricer)
75   	      thepricer->clear();
76   	
77   	   if(theratiotester)
78   	      theratiotester->clear();
79   	}
80   	
81   	template <class R>
82   	void SPxSolverBase<R>::loadLP(const SPxLPBase<R>& lp, bool initSlackBasis)
83   	{
84   	   clear();
85   	   unInit();
86   	   this->unLoad();
87   	   resetClockStats();
88   	
89   	   if(thepricer)
90   	      thepricer->clear();
91   	
92   	   if(theratiotester)
93   	      theratiotester->clear();
94   	
95   	   SPxLPBase<R>::operator=(lp);
96   	   reDim();
97   	   SPxBasisBase<R>::load(this, initSlackBasis);
98   	}
99   	
100  	template <class R>
101  	void SPxSolverBase<R>::setBasisSolver(SLinSolver<R>* slu, const bool destroy)
102  	{
103  	   // we need to set the outstream before we load the solver to ensure that the basis
104  	   // can be initialized with this pointer in loadSolver()
105  	   assert(spxout != 0);
106  	   slu->spxout = spxout;
107  	   SPxBasisBase<R>::loadBasisSolver(slu, destroy);
108  	}
109  	
110  	template <class R>
111  	void SPxSolverBase<R>::loadBasis(const typename SPxBasisBase<R>::Desc& p_desc)
112  	{
113  	   unInit();
114  	
115  	   if(SPxBasisBase<R>::status() == SPxBasisBase<R>::NO_PROBLEM)
116  	   {
117  	      SPxBasisBase<R>::load(this, false);
118  	   }
119  	
120  	   setBasisStatus(SPxBasisBase<R>::REGULAR);
121  	   SPxBasisBase<R>::loadDesc(p_desc);
122  	}
123  	
124  	template <class R>
125  	void SPxSolverBase<R>::setPricer(SPxPricer<R>* x, const bool destroy)
126  	{
127  	
128  	   assert(!freePricer || thepricer != 0);
129  	
130  	   if(freePricer)
131  	   {
132  	      delete thepricer;
133  	      thepricer = 0;
134  	   }
135  	
136  	   if(x != 0 && x != thepricer)
137  	   {
138  	      setPricing(FULL);
139  	
140  	      if(isInitialized())
141  	         x->load(this);
142  	      else
143  	         x->clear();
144  	   }
145  	
146  	   if(thepricer && thepricer != x)
147  	      thepricer->clear();
148  	
149  	   thepricer = x;
150  	   thepricer->setTolerances(this->tolerances());
151  	
152  	   freePricer = destroy;
153  	}
154  	
155  	template <class R>
156  	void SPxSolverBase<R>::setTester(SPxRatioTester<R>* x, const bool destroy)
157  	{
158  	   assert(!freeRatioTester || theratiotester != 0);
159  	
160  	   if(freeRatioTester)
161  	   {
162  	      delete theratiotester;
163  	      theratiotester = 0;
164  	   }
165  	
166  	   theratiotester = x;
167  	
168  	   // set the solver pointer inside the ratiotester
169  	   if(theratiotester != 0)
170  	   {
171  	      if(isInitialized())
172  	         theratiotester->load(this);
173  	      else
174  	         theratiotester->clear();
175  	   }
176  	
177  	   theratiotester->setTolerances(this->tolerances());
178  	
179  	   freeRatioTester = destroy;
180  	}
181  	
182  	template <class R>
183  	void SPxSolverBase<R>::setStarter(SPxStarter<R>* x, const bool destroy)
184  	{
185  	
186  	   assert(!freeStarter || thestarter != 0);
187  	
188  	   if(freeStarter)
189  	   {
190  	      delete thestarter;
191  	      thestarter = nullptr;
192  	   }
193  	
194  	   thestarter = x;
195  	
196  	   if(thestarter != nullptr)
197  	      thestarter->setTolerances(this->tolerances());
198  	
199  	   freeStarter = destroy;
200  	}
201  	
202  	template <class R>
203  	void SPxSolverBase<R>::setType(Type tp)
204  	{
205  	
206  	   if(theType != tp)
207  	   {
208  	      theType = tp;
209  	
210  	      forceRecompNonbasicValue();
211  	
212  	      unInit();
213  	#if 0
214  	      else
215  	      {
216  	         if(!matrixIsSetup)
217  	         {
218  	            SPxBasisBase<R>::load(this);
219  	            // SPxBasisBase<R>::load(desc());
220  	            // not needed, because load(this) allready loads descriptor
221  	         }
222  	
223  	         factorized = false;
224  	         m_numCycle = 0;
225  	#endif
226  	         SPX_MSG_INFO3((*spxout), (*spxout) << "Switching to "
227  	                       << static_cast<const char*>((tp == LEAVE)
228  	                             ? "leaving" : "entering")
229  	                       << " algorithm" << std::endl;)
230  	      }
231  	   }
232  	
233  	   template <class R>
234  	   void SPxSolverBase<R>::initRep(Representation p_rep)
235  	   {
236  	      theRep = p_rep;
237  	
238  	      if(theRep == COLUMN)
239  	      {
240  	         thevectors   = this->colSet();
241  	         thecovectors = this->rowSet();
242  	         theFrhs      = &primRhs;
243  	         theFvec      = &primVec;
244  	         theCoPrhs    = &dualRhs;
245  	         theCoPvec    = &dualVec;
246  	         thePvec      = &addVec;
247  	         theRPvec     = theCoPvec;
248  	         theCPvec     = thePvec;
249  	         theUbound    = &theUCbound;
250  	         theLbound    = &theLCbound;
251  	         theCoUbound  = &theURbound;
252  	         theCoLbound  = &theLRbound;
253  	      }
254  	      else
255  	      {
256  	         assert(theRep == ROW);
257  	
258  	         thevectors   = this->rowSet();
259  	         thecovectors = this->colSet();
260  	         theFrhs      = &dualRhs;
261  	         theFvec      = &dualVec;
262  	         theCoPrhs    = &primRhs;
263  	         theCoPvec    = &primVec;
264  	         thePvec      = &addVec;
265  	         theRPvec     = thePvec;
266  	         theCPvec     = theCoPvec;
267  	         theUbound    = &theURbound;
268  	         theLbound    = &theLRbound;
269  	         theCoUbound  = &theUCbound;
270  	         theCoLbound  = &theLCbound;
271  	      }
272  	
273  	      unInit();
274  	      reDim();
275  	
276  	      forceRecompNonbasicValue();
277  	
278  	      SPxBasisBase<R>::setRep();
279  	
280  	      if(SPxBasisBase<R>::status() > SPxBasisBase<R>::NO_PROBLEM)
281  	         SPxBasisBase<R>::loadDesc(this->desc());
282  	
283  	      if(thepricer && thepricer->solver() == this)
284  	         thepricer->setRep(p_rep);
285  	   }
286  	
287  	   template <class R>
288  	   void SPxSolverBase<R>::setRep(Representation p_rep)
289  	   {
290  	
291  	      if(p_rep != theRep)
292  	         initRep(p_rep);
293  	   }
294  	
295  	   // needed for strongbranching. use carefully
296  	   template <class R>
297  	   void SPxSolverBase<R>::reinitializeVecs()
298  	   {
299  	
300  	      initialized = true;
301  	
302  	      if(type() == ENTER)
303  	      {
304  	         if(rep() == COLUMN)
305  	            setPrimalBounds();
306  	         else
307  	            setDualRowBounds();
308  	
309  	         setEnterBounds();
310  	         computeEnterCoPrhs();
311  	      }
312  	      else
313  	      {
314  	         if(rep() == ROW)
315  	            setPrimalBounds();
316  	         else
317  	            setDualColBounds();
318  	
319  	         setLeaveBounds();
320  	         computeLeaveCoPrhs();
321  	      }
322  	
323  	      SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
324  	      computePvec();
325  	      computeFrhs();
326  	      SPxBasisBase<R>::solve(*theFvec, *theFrhs);
327  	
328  	      theShift  = 0.0;
329  	      lastShift = 0.0;
330  	
331  	      if(type() == ENTER)
332  	      {
333  	         computeCoTest();
334  	         computeTest();
335  	      }
336  	      else
337  	      {
338  	         computeFtest();
339  	      }
340  	
341  	      assert((testBounds(), 1));
342  	   }
343  	
344  	   template <class R>
345  	   void SPxSolverBase<R>::resetClockStats()
346  	   {
347  	      nClckSkipsLeft = 0;
348  	      nCallsToTimelim = 0;
349  	      theCumulativeTime = 0.0;
350  	   }
351  	
352  	   template <class R>
353  	   void SPxSolverBase<R>::init()
354  	   {
355  	
356  	      assert(thepricer      != 0);
357  	      assert(theratiotester != 0);
358  	
359  	      if(!initialized)
360  	      {
361  	         initialized = true;
362  	         clearUpdateVecs();
363  	         reDim();
364  	
365  	         if(SPxBasisBase<R>::status() <= SPxBasisBase<R>::NO_PROBLEM || this->solver() != this)
366  	            SPxBasisBase<R>::load(this);
367  	
368  	         initialized = false;
369  	      }
370  	
371  	      if(!this->matrixIsSetup)
372  	         SPxBasisBase<R>::loadDesc(this->desc());
373  	
374  	      // Inna/Tobi: don't "upgrade" a singular basis to a regular one
375  	      if(SPxBasisBase<R>::status() == SPxBasisBase<R>::SINGULAR)
376  	         return;
377  	
378  	      // catch pathological case for LPs with zero constraints
379  	      if(dim() == 0)
380  	      {
381  	         this->factorized = true;
382  	      }
383  	
384  	      // we better factorize explicitly before solving
385  	      if(!this->factorized)
386  	      {
387  	         try
388  	         {
389  	            SPxBasisBase<R>::factorize();
390  	         }
391  	         catch(const SPxException&)
392  	         {
393  	            // reload inital slack basis in case the factorization failed
394  	            assert(SPxBasisBase<R>::status() <= SPxBasisBase<R>::SINGULAR);
395  	            SPxBasisBase<R>::restoreInitialBasis();
396  	            SPxBasisBase<R>::factorize();
397  	            assert(this->factorized);
398  	         }
399  	      }
400  	
401  	      m_numCycle = 0;
402  	
403  	      if(type() == ENTER)
404  	      {
405  	         if(rep() == COLUMN)
406  	         {
407  	            setPrimalBounds();
408  	            setBasisStatus(SPxBasisBase<R>::PRIMAL);
409  	         }
410  	         else
411  	         {
412  	            setDualRowBounds();
413  	            setBasisStatus(SPxBasisBase<R>::DUAL);
414  	         }
415  	
416  	         setEnterBounds();
417  	         computeEnterCoPrhs();
418  	         // prepare support vectors for sparse pricing
419  	         infeasibilities.setMax(dim());
420  	         infeasibilitiesCo.setMax(coDim());
421  	         isInfeasible.reSize(dim());
422  	         isInfeasibleCo.reSize(coDim());
423  	         theratiotester->setDelta(entertol());
424  	      }
425  	      else
426  	      {
427  	         if(rep() == ROW)
428  	         {
429  	            setPrimalBounds();
430  	            setBasisStatus(SPxBasisBase<R>::PRIMAL);
431  	         }
432  	         else
433  	         {
434  	            setDualColBounds();
435  	            setBasisStatus(SPxBasisBase<R>::DUAL);
436  	         }
437  	
438  	         setLeaveBounds();
439  	         computeLeaveCoPrhs();
440  	         // prepare support vectors for sparse pricing
441  	         infeasibilities.setMax(dim());
442  	         isInfeasible.reSize(dim());
443  	         theratiotester->setDelta(leavetol());
444  	      }
445  	
446  	      SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
447  	      computePvec();
448  	      computeFrhs();
449  	      SPxBasisBase<R>::solve(*theFvec, *theFrhs);
450  	
451  	      theShift = 0.0;
452  	
453  	      if(type() == ENTER)
454  	      {
455  	         shiftFvec();
456  	         lastShift = theShift + entertol();
457  	
458  	         computeCoTest();
459  	         computeTest();
460  	      }
461  	      else
462  	      {
463  	         shiftPvec();
464  	         lastShift = theShift + leavetol();
465  	
466  	         computeFtest();
467  	      }
468  	
469  	      if(!initialized)
470  	      {
471  	         // if(thepricer->solver() != this)
472  	         thepricer->load(this);
473  	         // if(theratiotester->solver() != this)
474  	         theratiotester->load(this);
475  	         initialized = true;
476  	      }
477  	   }
478  	
479  	   template <class R>
480  	   void SPxSolverBase<R>::setPricing(Pricing pr)
481  	   {
482  	      thePricing = pr;
483  	
484  	      if(initialized && type() == ENTER)
485  	      {
486  	         computePvec();
487  	         computeCoTest();
488  	         computeTest();
489  	      }
490  	   }
491  	
492  	   template <class R>
493  	   void SPxSolverBase<R>::setDecompStatus(DecompStatus decomp_stat)
494  	   {
495  	      if(decomp_stat == FINDSTARTBASIS)
496  	         getStartingDecompBasis = true;
497  	      else
498  	         getStartingDecompBasis = false;
499  	   }
500  	
501  	   /*
502  	     The following method resizes all vectors and arrays of |SoPlex|
503  	     (excluding inherited vectors).
504  	   */
505  	   template <class R>
506  	   void SPxSolverBase<R>::reDim()
507  	   {
508  	
509  	      int newsize = SPxLPBase<R>::nCols() > SPxLPBase<R>::nRows() ? SPxLPBase<R>::nCols() :
510  	                    SPxLPBase<R>::nRows();
511  	
512  	      if(newsize > unitVecs.size())
513  	      {
514  	         unitVecs.reSize(newsize);
515  	
516  	         while(newsize-- > 0)
517  	            unitVecs[newsize] = UnitVectorBase<R>(newsize);
518  	      }
519  	
520  	      if(isInitialized())
521  	      {
522  	         theFrhs->reDim(dim());
523  	         theFvec->reDim(dim());
524  	         thePvec->reDim(coDim());
525  	
526  	         theCoPrhs->reDim(dim());
527  	         theCoPvec->reDim(dim());
528  	
529  	         theTest.reDim(coDim());
530  	         theCoTest.reDim(dim());
531  	
532  	         theURbound.reDim(SPxLPBase<R>::nRows());
533  	         theLRbound.reDim(SPxLPBase<R>::nRows());
534  	         theUCbound.reDim(SPxLPBase<R>::nCols());
535  	         theLCbound.reDim(SPxLPBase<R>::nCols());
536  	         theUBbound.reDim(dim());
537  	         theLBbound.reDim(dim());
538  	      }
539  	   }
540  	
541  	   template <class R>
542  	   void SPxSolverBase<R>::clear()
543  	   {
544  	      unitVecs.reSize(0);
545  	
546  	      dualRhs.clear();
547  	      dualVec.clear();
548  	      primRhs.clear();
549  	      primVec.clear();
550  	      addVec.clear();
551  	      theURbound.clear();
552  	      theLRbound.clear();
553  	      theUCbound.clear();
554  	      theLCbound.clear();
555  	      theTest.clear();
556  	      theCoTest.clear();
557  	
558  	      forceRecompNonbasicValue();
559  	      unInit();
560  	      SPxLPBase<R>::clear();
561  	      setBasisStatus(SPxBasisBase<R>::NO_PROBLEM);
562  	
563  	      // clear the basis only when theLP is present, because LP data (nrows, ncols) is used in reDim()
564  	      if(this->theLP != 0)
565  	         SPxBasisBase<R>::reDim();
566  	
567  	      infeasibilities.clear();
568  	      infeasibilitiesCo.clear();
569  	      isInfeasible.clear();
570  	      isInfeasibleCo.clear();
571  	   }
572  	
573  	   template <class R>
574  	   void SPxSolverBase<R>::unscaleLPandReloadBasis()
575  	   {
576  	      SPxLPBase<R>::unscaleLP();
577  	      SPxBasisBase<R>::invalidate();
578  	      unInit();
579  	      init();
580  	   }
581  	
582  	   template <class R>
583  	   void SPxSolverBase<R>::invalidateBasis()
584  	   {
585  	      SPxBasisBase<R>::invalidate();
586  	      unInit();
587  	      init();
588  	   }
589  	
590  	   template <class R>
591  	   void SPxSolverBase<R>::clearUpdateVecs(void)
592  	   {
593  	      theFvec->clearUpdate();
594  	      thePvec->clearUpdate();
595  	      theCoPvec->clearUpdate();
596  	      solveVector2 = 0;
597  	      solveVector3 = 0;
598  	      coSolveVector2 = 0;
599  	      coSolveVector3 = 0;
600  	   }
601  	
602  	   /*
603  	     When the basis matrix factorization is recomputed from scratch,
604  	     we also recompute the vectors.
605  	   */
606  	   template <class R>
607  	   void SPxSolverBase<R>::factorize()
608  	   {
609  	
610  	      SPX_MSG_INFO3((*spxout), (*spxout) << " --- refactorizing basis matrix" << std::endl;)
611  	
612  	      try
613  	      {
614  	         SPxBasisBase<R>::factorize();
615  	      }
616  	      catch(const SPxStatusException&)
617  	      {
618  	         assert(SPxBasisBase<R>::status() == SPxBasisBase<R>::SINGULAR);
619  	         m_status = SINGULAR;
620  	         std::stringstream s;
621  	         s << "Basis is singular (numerical troubles, feastol = "
622  	           << tolerances()->floatingPointFeastol()
623  	           << ", opttol = " << tolerances()->floatingPointOpttol() << ")";
624  	         throw SPxStatusException(s.str());
625  	      }
626  	
627  	      if(!initialized)
628  	      {
629  	         init();  // not sure if init() is neccessary here
630  	         // we must not go on here because not all vectors (e.g. fVec) may be set up correctly
631  	         return;
632  	      }
633  	
634  	      if(SPxBasisBase<R>::status() >= SPxBasisBase<R>::REGULAR)
635  	      {
636  	#ifndef NDEBUG
637  	         VectorBase<R> ftmp(fVec());
638  	         VectorBase<R> ptmp(pVec());
639  	         VectorBase<R> ctmp(coPvec());
640  	#endif  // NDEBUG
641  	
642  	         if(type() == LEAVE)
643  	         {
644  	            /* we have to recompute theFrhs, because roundoff errors can occur during updating, especially when
645  	             * columns/rows with large bounds are present
646  	             */
647  	            computeFrhs();
648  	            SPxBasisBase<R>::solve(*theFvec, *theFrhs);
649  	            SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
650  	
651  	#ifndef NDEBUG
652  	            ftmp -= fVec();
653  	            ptmp -= pVec();
654  	            ctmp -= coPvec();
655  	
656  	            if(ftmp.length() > SOPLEX_DEFAULT_BND_VIOL)
657  	            {
658  	               SPxOut::debug(this, "DSOLVE21 fVec:   {}\n", ftmp.length());
659  	               ftmp = fVec();
660  	               this->multBaseWith(ftmp);
661  	               ftmp -= fRhs();
662  	
663  	               if(ftmp.length() > SOPLEX_DEFAULT_BND_VIOL)
664  	                  SPX_MSG_INFO1((*spxout), (*spxout) << "ESOLVE29 " << this->iteration() << ": fVec error = "
665  	                                << ftmp.length() << " exceeding SOPLEX_DEFAULT_BND_VIOL = " << SOPLEX_DEFAULT_BND_VIOL << std::endl;
666  	                               )
667  	               }
668  	
669  	            if(ctmp.length() > SOPLEX_DEFAULT_BND_VIOL)
670  	            {
671  	               SPxOut::debug(this, "DSOLVE23 coPvec: {}\n", ctmp.length());
672  	               ctmp = coPvec();
673  	               this->multWithBase(ctmp);
674  	               ctmp -= coPrhs();
675  	
676  	               if(ctmp.length() > SOPLEX_DEFAULT_BND_VIOL)
677  	                  SPX_MSG_INFO1((*spxout), (*spxout) << "ESOLVE30 " << this->iteration() << ": coPvec error = "
678  	                                << ctmp.length() << " exceeding SOPLEX_DEFAULT_BND_VIOL = " << SOPLEX_DEFAULT_BND_VIOL << std::endl;
679  	                               )
680  	               }
681  	
682  	            if(ptmp.length() > SOPLEX_DEFAULT_BND_VIOL)
683  	            {
684  	               SPxOut::debug(this, "DSOLVE24 pVec:   {}\n", ptmp.length());
685  	            }
686  	
687  	#endif  // NDEBUG
688  	
689  	            computeFtest();
690  	         }
691  	         else
692  	         {
693  	            assert(type() == ENTER);
694  	
695  	            SPxBasisBase<R>::coSolve(*theCoPvec, *theCoPrhs);
696  	            computeCoTest();
697  	
698  	            if(pricing() == FULL)
699  	            {
700  	               /* to save time only recompute the row activities (in row rep) when we are already nearly optimal to
701  	                * avoid missing any violations from previous updates */
702  	               if(rep() == ROW && m_pricingViolCo < entertol() && m_pricingViol < entertol())
703  	                  computePvec();
704  	
705  	               /* was deactivated, but this leads to warnings in testVecs() */
706  	               computeTest();
707  	            }
708  	         }
709  	      }
710  	
711  	#ifdef ENABLE_ADDITIONAL_CHECKS
712  	
713  	      /* 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 */
714  	      if(SPxBasisBase<R>::status() > SPxBasisBase<R>::SINGULAR)
715  	         testVecs();
716  	
717  	#endif
718  	   }
719  	
720  	   /* We compute how much the current solution violates (primal or dual) feasibility. In the
721  	      row/enter or column/leave algorithm the maximum violation of dual feasibility is
722  	      computed. In the row/leave or column/enter algorithm the primal feasibility is checked.
723  	      Additionally, the violation from pricing is taken into account. */
724  	   template <class R>
725  	   R SPxSolverBase<R>::maxInfeas() const
726  	   {
727  	      R inf = 0.0;
728  	
729  	      if(type() == ENTER)
730  	      {
731  	         if(m_pricingViolUpToDate && m_pricingViolCoUpToDate)
732  	            inf = m_pricingViol + m_pricingViolCo;
733  	
734  	         for(int i = 0; i < dim(); i++)
735  	         {
736  	            if((*theFvec)[i] > theUBbound[i])
737  	               inf = SOPLEX_MAX(inf, (*theFvec)[i] - theUBbound[i]);
738  	            else if((*theFvec)[i] < theLBbound[i])
739  	               inf = SOPLEX_MAX(inf, theLBbound[i] - (*theFvec)[i]);
740  	         }
741  	      }
742  	      else
743  	      {
744  	         assert(type() == LEAVE);
745  	
746  	         if(m_pricingViolUpToDate)
747  	            inf = m_pricingViol;
748  	
749  	         for(int i = 0; i < dim(); i++)
750  	         {
751  	            if((*theCoPvec)[i] > (*theCoUbound)[i])
752  	               inf = SOPLEX_MAX(inf, (*theCoPvec)[i] - (*theCoUbound)[i]);
753  	            else if((*theCoPvec)[i] < (*theCoLbound)[i])
754  	               inf = SOPLEX_MAX(inf, (*theCoLbound)[i] - (*theCoPvec)[i]);
755  	         }
756  	
757  	         for(int i = 0; i < coDim(); i++)
758  	         {
759  	            if((*thePvec)[i] > (*theUbound)[i])
760  	               inf = SOPLEX_MAX(inf, (*thePvec)[i] - (*theUbound)[i]);
761  	            else if((*thePvec)[i] < (*theLbound)[i])
762  	               inf = SOPLEX_MAX(inf, (*theLbound)[i] - (*thePvec)[i]);
763  	         }
764  	      }
765  	
766  	      return inf;
767  	   }
768  	
769  	   /* check for (dual) violations above tol and immediately return false w/o checking the remaining values
770  	      This method is useful for verifying whether an objective limit can be used as termination criterion */
771  	   template <class R>
772  	   bool SPxSolverBase<R>::noViols(R tol) const
773  	   {
774  	      assert(tol >= R(0.0));
775  	
776  	      if(type() == ENTER)
777  	      {
778  	         for(int i = 0; i < dim(); i++)
779  	         {
780  	            if((*theFvec)[i] - theUBbound[i] > tol)
781  	               return false;
782  	
783  	            if(theLBbound[i] - (*theFvec)[i] > tol)
784  	               return false;
785  	         }
786  	      }
787  	      else
788  	      {
789  	         assert(type() == LEAVE);
790  	
791  	         for(int i = 0; i < dim(); i++)
792  	         {
793  	            if((*theCoPvec)[i] - (*theCoUbound)[i] > tol)
794  	               return false;
795  	
796  	            if((*theCoLbound)[i] - (*theCoPvec)[i] > tol)
797  	               return false;
798  	         }
799  	
800  	         for(int i = 0; i < coDim(); i++)
801  	         {
802  	            if((*thePvec)[i] - (*theUbound)[i] > tol)
803  	               return false;
804  	
805  	            if((*theLbound)[i] - (*thePvec)[i] > tol)
806  	               return false;
807  	         }
808  	      }
809  	
810  	      return true;
811  	   }
812  	
813  	   template <class R>
814  	   R SPxSolverBase<R>::nonbasicValue()
815  	   {
816  	      int i;
817  	      StableSum<R> val;
818  	      const typename SPxBasisBase<R>::Desc& ds = this->desc();
819  	
820  	#ifndef ENABLE_ADDITIONAL_CHECKS
821  	
822  	      // if the value is available we don't need to recompute it
823  	      if(m_nonbasicValueUpToDate)
824  	         return m_nonbasicValue;
825  	
826  	#endif
827  	
828  	      if(rep() == COLUMN)
829  	      {
830  	         if(type() == LEAVE)
831  	         {
832  	            for(i = this->nCols() - 1; i >= 0; --i)
833  	            {
834  	               switch(ds.colStatus(i))
835  	               {
836  	               case SPxBasisBase<R>::Desc::P_ON_UPPER :
837  	                  val += theUCbound[i] * SPxLPBase<R>::upper(i);
838  	                  //@ val += maxObj(i) * SPxLPBase<R>::upper(i);
839  	                  break;
840  	
841  	               case SPxBasisBase<R>::Desc::P_ON_LOWER :
842  	                  val += theLCbound[i] * SPxLPBase<R>::lower(i);
843  	                  //@ val += maxObj(i) * SPxLPBase<R>::lower(i);
844  	                  break;
845  	
846  	               case SPxBasisBase<R>::Desc::P_FIXED :
847  	                  assert(EQ(SPxLPBase<R>::lower(i), SPxLPBase<R>::upper(i), this->epsilon()));
848  	                  val += this->maxObj(i) * SPxLPBase<R>::lower(i);
849  	                  break;
850  	
851  	               default:
852  	                  break;
853  	               }
854  	            }
855  	
856  	            for(i = this->nRows() - 1; i >= 0; --i)
857  	            {
858  	               switch(ds.rowStatus(i))
859  	               {
860  	               case SPxBasisBase<R>::Desc::P_ON_UPPER :
861  	                  val += theLRbound[i] * SPxLPBase<R>::rhs(i);
862  	                  break;
863  	
864  	               case SPxBasisBase<R>::Desc::P_ON_LOWER :
865  	                  val += theURbound[i] * SPxLPBase<R>::lhs(i);
866  	                  break;
867  	
868  	               case SPxBasisBase<R>::Desc::P_FIXED :
869  	                  assert(EQ(SPxLPBase<R>::lhs(i), SPxLPBase<R>::rhs(i), this->epsilon()));
870  	                  val += this->maxRowObj(i) * SPxLPBase<R>::lhs(i);
871  	                  break;
872  	
873  	               default:
874  	                  break;
875  	               }
876  	            }
877  	         }
878  	         else
879  	         {
880  	            assert(type() == ENTER);
881  	
882  	            for(i = this->nCols() - 1; i >= 0; --i)
883  	            {
884  	               switch(ds.colStatus(i))
885  	               {
886  	               case SPxBasisBase<R>::Desc::P_ON_UPPER :
887  	                  val += this->maxObj(i) * theUCbound[i];
888  	                  break;
889  	
890  	               case SPxBasisBase<R>::Desc::P_ON_LOWER :
891  	                  val += this->maxObj(i) * theLCbound[i];
892  	                  break;
893  	
894  	               case SPxBasisBase<R>::Desc::P_FIXED :
895  	                  assert(EQ(theLCbound[i], theUCbound[i], this->epsilon()));
896  	                  val += this->maxObj(i) * theLCbound[i];
897  	                  break;
898  	
899  	               default:
900  	                  break;
901  	               }
902  	            }
903  	
904  	            for(i = this->nRows() - 1; i >= 0; --i)
905  	            {
906  	               switch(ds.rowStatus(i))
907  	               {
908  	               case SPxBasisBase<R>::Desc::P_ON_UPPER :
909  	                  val += this->maxRowObj(i) * theLRbound[i];
910  	                  break;
911  	
912  	               case SPxBasisBase<R>::Desc::P_ON_LOWER :
913  	                  val += this->maxRowObj(i) * theURbound[i];
914  	                  break;
915  	
916  	               case SPxBasisBase<R>::Desc::P_FIXED :
917  	                  assert(EQ(theLRbound[i], theURbound[i], this->epsilon()));
918  	                  val += this->maxRowObj(i) * theURbound[i];
919  	                  break;
920  	
921  	               default:
922  	                  break;
923  	               }
924  	            }
925  	         }
926  	      }
927  	      else
928  	      {
929  	         assert(rep() == ROW);
930  	         assert(type() == ENTER);
931  	
932  	         for(i = this->nCols() - 1; i >= 0; --i)
933  	         {
934  	            switch(ds.colStatus(i))
935  	            {
936  	            case SPxBasisBase<R>::Desc::D_ON_UPPER :
937  	               val += theUCbound[i] * this->lower(i);
938  	               break;
939  	
940  	            case SPxBasisBase<R>::Desc::D_ON_LOWER :
941  	               val += theLCbound[i] * this->upper(i);
942  	               break;
943  	
944  	            case SPxBasisBase<R>::Desc::D_ON_BOTH :
945  	               val += theLCbound[i] * this->upper(i);
946  	               val += theUCbound[i] * this->lower(i);
947  	               break;
948  	
949  	            default:
950  	               break;
951  	            }
952  	         }
953  	
954  	         for(i = this->nRows() - 1; i >= 0; --i)
955  	         {
956  	            switch(ds.rowStatus(i))
957  	            {
958  	            case SPxBasisBase<R>::Desc::D_ON_UPPER :
959  	               val += theURbound[i] * this->lhs(i);
960  	               break;
961  	
962  	            case SPxBasisBase<R>::Desc::D_ON_LOWER :
963  	               val += theLRbound[i] * this->rhs(i);
964  	               break;
965  	
966  	            case SPxBasisBase<R>::Desc::D_ON_BOTH :
967  	               val += theLRbound[i] * this->rhs(i);
968  	               val += theURbound[i] * this->lhs(i);
969  	               break;
970  	
971  	            default:
972  	               break;
973  	            }
974  	         }
975  	      }
976  	
977  	#ifdef ENABLE_ADDITIONAL_CHECKS
978  	
979  	      if(m_nonbasicValueUpToDate && NE(m_nonbasicValue, val))
980  	      {
981  	         SPX_MSG_ERROR(std::cerr << "stored nonbasic value: " << m_nonbasicValue
982  	                       << ", correct nonbasic value: " << val
983  	                       << ", violation: " << val - m_nonbasicValue << std::endl;)
984  	         assert(EQrel(m_nonbasicValue, val, 1e-12));
985  	      }
986  	
987  	#endif
988  	
989  	      if(!m_nonbasicValueUpToDate)
990  	      {
991  	         m_nonbasicValue = R(val);
992  	         m_nonbasicValueUpToDate = true;
993  	      }
994  	
995  	      return val;
996  	   }
997  	
998  	   template <class R>
999  	   R SPxSolverBase<R>::value()
1000 	   {
1001 	      assert(isInitialized());
1002 	
1003 	      R x;
1004 	
1005 	      // calling value() without having a suitable status is an error.
1006 	      if(!isInitialized())
1007 	         return R(infinity);
1008 	
1009 	      if(rep() == ROW)
1010 	      {
1011 	         if(type() == LEAVE)
1012 	            x = int(SPxLPBase<R>::spxSense()) * (coPvec() *
1013 	                                                 fRhs()); // the contribution of maxRowObj() is missing
1014 	         else
1015 	            x = int(SPxLPBase<R>::spxSense()) * (nonbasicValue() + (coPvec() * fRhs()));
1016 	      }
1017 	      else
1018 	         x = int(SPxLPBase<R>::spxSense()) * (nonbasicValue() + fVec() * coPrhs());
1019 	
1020 	      return x + this->objOffset();
1021 	   }
1022 	
1023 	   template <class R>
1024 	   bool SPxSolverBase<R>::updateNonbasicValue(R objChange)
1025 	   {
1026 	      if(m_nonbasicValueUpToDate)
1027 	         m_nonbasicValue += objChange;
1028 	
1029 	      SPxOut::debug(this, "Iteration: {} updated objValue: {} new value: {} correct value: {}\n",
1030 	                    this->iteration(), objChange, m_nonbasicValue, m_nonbasicValueUpToDate ? nonbasicValue() : -1e100);
1031 	
1032 	      return m_nonbasicValueUpToDate;
1033 	   }
1034 	
1035 	   template <class R>
1036 	   void SPxSolverBase<R>::hyperPricing(bool h)
1037 	   {
1038 	      hyperPricingEnter = h;
1039 	      hyperPricingLeave = h;
1040 	
1041 	      if(h)
1042 	      {
1043 	         updateViols.setMax(dim());
1044 	         updateViolsCo.setMax(coDim());
1045 	      }
1046 	   }
1047 	
1048 	   template <class R>
1049 	   SPxSolverBase<R>::SPxSolverBase(
1050 	      Type            p_type,
1051 	      Representation  p_rep,
1052 	      Timer::TYPE     ttype)
1053 	      : theType(p_type)
1054 	      , thePricing(FULL)
1055 	      , theRep(p_rep)
1056 	      , polishObj(POLISH_OFF)
1057 	      , theTime(nullptr)
1058 	      , timerType(ttype)
1059 	      , theCumulativeTime(0.0)
1060 	      , maxIters(-1)
1061 	      , maxTime(R(infinity))
1062 	      , nClckSkipsLeft(0)
1063 	      , nCallsToTimelim(0)
1064 	      , objLimit(R(infinity))
1065 	      , m_status(UNKNOWN)
1066 	      , m_nonbasicValue(0.0)
1067 	      , m_nonbasicValueUpToDate(false)
1068 	      , m_pricingViol(0.0)
1069 	      , m_pricingViolUpToDate(false)
1070 	      , m_pricingViolCo(0.0)
1071 	      , m_pricingViolCoUpToDate(false)
1072 	      , m_numViol(0)
1073 	      , entertolscale(1.0)
1074 	      , leavetolscale(1.0)
1075 	      , theShift(0)
1076 	      , m_maxCycle(100)
1077 	      , m_numCycle(0)
1078 	      , initialized(false)
1079 	      , solveVector2(0)
1080 	      , solveVector3(0)
1081 	      , coSolveVector2(0)
1082 	      , coSolveVector3(0)
1083 	      , freePricer(false)
1084 	      , freeRatioTester(false)
1085 	      , freeStarter(false)
1086 	      , displayLine(0)
1087 	      , displayFreq(200)
1088 	      , sparsePricingFactor(SOPLEX_SPARSITYFACTOR)
1089 	      , getStartingDecompBasis(false)
1090 	      , computeDegeneracy(false)
1091 	      , degenCompIterOffset(0)
1092 	      , fullPerturbation(false)
1093 	      , printBasisMetric(0)
1094 	      , unitVecs(0)
1095 	      , primVec(0)
1096 	      , dualVec(0)
1097 	      , addVec(0)
1098 	      , thepricer(0)
1099 	      , theratiotester(0)
1100 	      , thestarter(0)
1101 	      , boundrange(0.0)
1102 	      , siderange(0.0)
1103 	      , objrange(0.0)
1104 	      , infeasibilities(0)
1105 	      , infeasibilitiesCo(0)
1106 	      , isInfeasible(0)
1107 	      , isInfeasibleCo(0)
1108 	      , sparsePricingLeave(false)
1109 	      , sparsePricingEnter(false)
1110 	      , sparsePricingEnterCo(false)
1111 	      , hyperPricingLeave(true)
1112 	      , hyperPricingEnter(true)
1113 	      , remainingRoundsLeave(0)
1114 	      , remainingRoundsEnter(0)
1115 	      , remainingRoundsEnterCo(0)
1116 	      , weights(0)
1117 	      , coWeights(0)
1118 	      , weightsAreSetup(false)
1119 	      , multSparseCalls(0)
1120 	      , multFullCalls(0)
1121 	      , multColwiseCalls(0)
1122 	      , multUnsetupCalls(0)
1123 	      , integerVariables(0)
1124 	   {
1125 	      theTime = TimerFactory::createTimer(timerType);
1126 	
1127 	      multTimeSparse = TimerFactory::createTimer(timerType);
1128 	      multTimeFull = TimerFactory::createTimer(timerType);
1129 	      multTimeColwise = TimerFactory::createTimer(timerType);
1130 	      multTimeUnsetup = TimerFactory::createTimer(timerType);
1131 	
1132 	      this->theLP = this;
1133 	      initRep(p_rep);
1134 	
1135 	      // info: SPxBasisBase is not consistent in this moment.
1136 	      //assert(SPxSolverBase<R>::isConsistent());
1137 	   }
1138 	
1139 	   template <class R>
1140 	   SPxSolverBase<R>::~SPxSolverBase()
1141 	   {
1142 	      assert(!freePricer || thepricer != 0);
1143 	      assert(!freeRatioTester || theratiotester != 0);
1144 	      assert(!freeStarter || thestarter != 0);
1145 	
1146 	      if(freePricer)
1147 	      {
1148 	         delete thepricer;
1149 	         thepricer = 0;
1150 	      }
1151 	
1152 	      if(freeRatioTester)
1153 	      {
1154 	         delete theratiotester;
1155 	         theratiotester = 0;
1156 	      }
1157 	
1158 	      if(freeStarter)
1159 	      {
1160 	         delete thestarter;
1161 	         thestarter = 0;
1162 	      }
1163 	
1164 	      // free the timers
1165 	      assert(theTime);
1166 	      assert(multTimeSparse);
1167 	      assert(multTimeFull);
1168 	      assert(multTimeColwise);
1169 	      assert(multTimeUnsetup);
1170 	      theTime->~Timer();
1171 	      multTimeSparse->~Timer();
1172 	      multTimeFull->~Timer();
1173 	      multTimeColwise->~Timer();
1174 	      multTimeUnsetup->~Timer();
1175 	      spx_free(theTime);
1176 	      spx_free(multTimeSparse);
1177 	      spx_free(multTimeFull);
1178 	      spx_free(multTimeColwise);
1179 	      spx_free(multTimeUnsetup);
1180 	   }
1181 	
1182 	
1183 	   template <class R>
1184 	   SPxSolverBase<R>& SPxSolverBase<R>::operator=(const SPxSolverBase<R>& base)
1185 	   {
1186 	      if(this != &base)
1187 	      {
1188 	         SPxLPBase<R>::operator=(base);
1189 	         SPxBasisBase<R>::operator=(base);
1190 	         theType = base.theType;
1191 	         thePricing = base.thePricing;
1192 	         theRep = base.theRep;
1193 	         polishObj = base.polishObj;
1194 	         timerType = base.timerType;
1195 	         maxIters = base.maxIters;
1196 	         maxTime = base.maxTime;
1197 	         objLimit = base.objLimit;
1198 	         m_status = base.m_status;
1199 	         m_nonbasicValue = base.m_nonbasicValue;
1200 	         m_nonbasicValueUpToDate = base.m_nonbasicValueUpToDate;
1201 	         m_pricingViol = base.m_pricingViol;
1202 	         m_pricingViolUpToDate = base.m_pricingViolUpToDate;
1203 	         m_pricingViolCo = base.m_pricingViolCo;
1204 	         m_pricingViolCoUpToDate = base.m_pricingViolCoUpToDate;
1205 	         m_numViol = base.m_numViol;
1206 	         entertolscale = base.entertolscale;
1207 	         leavetolscale = base.leavetolscale;
1208 	         theShift = base.theShift;
1209 	         lastShift = base.lastShift;
1210 	         m_maxCycle = base.m_maxCycle;
1211 	         m_numCycle = base.m_numCycle;
1212 	         initialized = base.initialized;
1213 	         instableLeaveNum = base.instableLeaveNum;
1214 	         instableLeave = base.instableLeave;
1215 	         instableLeaveVal = base.instableLeaveVal;
1216 	         instableEnterId = base.instableEnterId;
1217 	         instableEnter = base.instableEnter;
1218 	         instableEnterVal = base.instableEnterVal;
1219 	         displayLine = base.displayLine;
1220 	         displayFreq = base.displayFreq;
1221 	         sparsePricingFactor = base.sparsePricingFactor;
1222 	         getStartingDecompBasis = base.getStartingDecompBasis;
1223 	         computeDegeneracy = base.computeDegeneracy;
1224 	         degenCompIterOffset = base.degenCompIterOffset;
1225 	         decompIterationLimit = base.decompIterationLimit;
1226 	         fullPerturbation = base.fullPerturbation;
1227 	         printBasisMetric = base.printBasisMetric;
1228 	         unitVecs = base.unitVecs;
1229 	         primRhs = base.primRhs;
1230 	         primVec = base.primVec;
1231 	         dualRhs = base.dualRhs;
1232 	         dualVec = base.dualVec;
1233 	         addVec = base.addVec;
1234 	         theURbound = base.theURbound;
1235 	         theLRbound = base.theLRbound;
1236 	         theUCbound = base.theUCbound;
1237 	         theLCbound = base.theLCbound;
1238 	         theUBbound = base.theUBbound;
1239 	         theLBbound = base.theLBbound;
1240 	         theCoTest = base.theCoTest;
1241 	         theTest = base.theTest;
1242 	         primalRay = base.primalRay;
1243 	         dualFarkas = base.dualFarkas;
1244 	         leaveCount = base.leaveCount;
1245 	         enterCount = base.enterCount;
1246 	         theCumulativeTime = base.theCumulativeTime;
1247 	         primalCount = base.primalCount;
1248 	         polishCount = base.polishCount;
1249 	         boundflips = base.boundflips;
1250 	         totalboundflips = base.totalboundflips;
1251 	         enterCycles = base.enterCycles;
1252 	         leaveCycles = base.leaveCycles;
1253 	         enterDegenCand = base.enterDegenCand;
1254 	         leaveDegenCand = base.leaveDegenCand;
1255 	         primalDegenSum = base.primalDegenSum;
1256 	         boundrange = base.boundrange;
1257 	         siderange = base.siderange;
1258 	         objrange = base.objrange;
1259 	         infeasibilities = base.infeasibilities;
1260 	         infeasibilitiesCo = base.infeasibilitiesCo;
1261 	         isInfeasible = base.isInfeasible;
1262 	         isInfeasibleCo = base.isInfeasibleCo;
1263 	         sparsePricingLeave = base.sparsePricingLeave;
1264 	         sparsePricingEnter = base.sparsePricingEnter;
1265 	         sparsePricingEnterCo = base.sparsePricingEnterCo;
1266 	         sparsePricingFactor = base.sparsePricingFactor;
1267 	         hyperPricingLeave = base.hyperPricingLeave;
1268 	         hyperPricingEnter = base.hyperPricingEnter;
1269 	         remainingRoundsLeave = base.remainingRoundsLeave;
1270 	         remainingRoundsEnter = base.remainingRoundsEnter;
1271 	         remainingRoundsEnterCo = base.remainingRoundsEnterCo;
1272 	         weights = base.weights;
1273 	         coWeights = base.coWeights;
1274 	         weightsAreSetup = base.weightsAreSetup;
1275 	         multSparseCalls = base.multSparseCalls;
1276 	         multFullCalls = base.multFullCalls;
1277 	         multColwiseCalls = base.multColwiseCalls;
1278 	         multUnsetupCalls = base.multUnsetupCalls;
1279 	         spxout = base.spxout;
1280 	         integerVariables = base.integerVariables;
1281 	
1282 	         if(base.theRep == COLUMN)
1283 	         {
1284 	            thevectors   = this->colSet();
1285 	            thecovectors = this->rowSet();
1286 	            theFrhs      = &primRhs;
1287 	            theFvec      = &primVec;
1288 	            theCoPrhs    = &dualRhs;
1289 	            theCoPvec    = &dualVec;
1290 	            thePvec      = &addVec;
1291 	            theRPvec     = theCoPvec;
1292 	            theCPvec     = thePvec;
1293 	            theUbound    = &theUCbound;
1294 	            theLbound    = &theLCbound;
1295 	            theCoUbound  = &theURbound;
1296 	            theCoLbound  = &theLRbound;
1297 	         }
1298 	         else
1299 	         {
1300 	            assert(base.theRep == ROW);
1301 	
1302 	            thevectors   = this->rowSet();
1303 	            thecovectors = this->colSet();
1304 	            theFrhs      = &dualRhs;
1305 	            theFvec      = &dualVec;
1306 	            theCoPrhs    = &primRhs;
1307 	            theCoPvec    = &primVec;
1308 	            thePvec      = &addVec;
1309 	            theRPvec     = thePvec;
1310 	            theCPvec     = theCoPvec;
1311 	            theUbound    = &theURbound;
1312 	            theLbound    = &theLRbound;
1313 	            theCoUbound  = &theUCbound;
1314 	            theCoLbound  = &theLCbound;
1315 	         }
1316 	
1317 	         SPxBasisBase<R>::theLP = this;
1318 	
1319 	         assert(!freePricer || thepricer != 0);
1320 	         assert(!freeRatioTester || theratiotester != 0);
1321 	         assert(!freeStarter || thestarter != 0);
1322 	
1323 	         // thepricer
1324 	         if(freePricer)
1325 	         {
1326 	            delete thepricer;
1327 	            thepricer = 0;
1328 	         }
1329 	
1330 	         if(base.thepricer == 0)
1331 	         {
1332 	            thepricer = 0;
1333 	            freePricer = false;
1334 	         }
1335 	         else
1336 	         {
1337 	            thepricer = base.thepricer->clone();
1338 	            freePricer = true;
1339 	            thepricer->load(this);
1340 	         }
1341 	
1342 	         // theratiotester
1343 	         if(freeRatioTester)
1344 	         {
1345 	            delete theratiotester;
1346 	            theratiotester = 0;
1347 	         }
1348 	
1349 	         if(base.theratiotester == 0)
1350 	         {
1351 	            theratiotester = 0;
1352 	            freeRatioTester = false;
1353 	         }
1354 	         else
1355 	         {
1356 	            theratiotester = base.theratiotester->clone();
1357 	            freeRatioTester = true;
1358 	            theratiotester->setTolerances(this->tolerances());
1359 	            theratiotester->load(this);
1360 	         }
1361 	
1362 	         // thestarter
1363 	         if(freeStarter)
1364 	         {
1365 	            delete thestarter;
1366 	            thestarter = 0;
1367 	         }
1368 	
1369 	         if(base.thestarter == 0)
1370 	         {
1371 	            thestarter = 0;
1372 	            freeStarter = false;
1373 	         }
1374 	         else
1375 	         {
1376 	            thestarter = base.thestarter->clone();
1377 	            freeStarter = true;
1378 	         }
1379 	
1380 	         assert(SPxSolverBase<R>::isConsistent());
1381 	      }
1382 	
1383 	      return *this;
1384 	   }
1385 	
1386 	
1387 	   template <class R>
1388 	   SPxSolverBase<R>::SPxSolverBase(const SPxSolverBase<R>& base)
1389 	      : SPxLPBase<R> (base)
1390 	      , SPxBasisBase<R>(this->basSe)
1391 	      , theType(base.theType)
1392 	      , thePricing(base.thePricing)
1393 	      , theRep(base.theRep)
1394 	      , polishObj(base.polishObj)
1395 	      , timerType(base.timerType)
1396 	      , theCumulativeTime(base.theCumulativeTime)
1397 	      , maxIters(base.maxIters)
1398 	      , maxTime(base.maxTime)
1399 	      , nClckSkipsLeft(base.nClckSkipsLeft)
1400 	      , nCallsToTimelim(base.nCallsToTimelim)
1401 	      , objLimit(base.objLimit)
1402 	      , m_status(base.m_status)
1403 	      , m_nonbasicValue(base.m_nonbasicValue)
1404 	      , m_nonbasicValueUpToDate(base.m_nonbasicValueUpToDate)
1405 	      , m_pricingViol(base.m_pricingViol)
1406 	      , m_pricingViolUpToDate(base.m_pricingViolUpToDate)
1407 	      , m_pricingViolCo(base.m_pricingViolCo)
1408 	      , m_pricingViolCoUpToDate(base.m_pricingViolCoUpToDate)
1409 	      , m_numViol(base.m_numViol)
1410 	      , entertolscale(base.entertolscale)
1411 	      , leavetolscale(base.leavetolscale)
1412 	      , theShift(base.theShift)
1413 	      , lastShift(base.lastShift)
1414 	      , m_maxCycle(base.m_maxCycle)
1415 	      , m_numCycle(base.m_numCycle)
1416 	      , initialized(base.initialized)
1417 	      , solveVector2(0)
1418 	      , solveVector2rhs(base.solveVector2rhs)
1419 	      , solveVector3(0)
1420 	      , solveVector3rhs(base.solveVector3rhs)
1421 	      , coSolveVector2(0)
1422 	      , coSolveVector2rhs(base.coSolveVector2rhs)
1423 	      , coSolveVector3(0)
1424 	      , coSolveVector3rhs(base.coSolveVector3rhs)
1425 	      , instableLeaveNum(base.instableLeaveNum)
1426 	      , instableLeave(base.instableLeave)
1427 	      , instableLeaveVal(base.instableLeaveVal)
1428 	      , instableEnterId(base.instableEnterId)
1429 	      , instableEnter(base.instableEnter)
1430 	      , instableEnterVal(base.instableEnterVal)
1431 	      , displayLine(base.displayLine)
1432 	      , displayFreq(base.displayFreq)
1433 	      , sparsePricingFactor(base.sparsePricingFactor)
1434 	      , getStartingDecompBasis(base.getStartingDecompBasis)
1435 	      , computeDegeneracy(base.computeDegeneracy)
1436 	      , degenCompIterOffset(base.degenCompIterOffset)
1437 	      , decompIterationLimit(base.decompIterationLimit)
1438 	      , fullPerturbation(base.fullPerturbation)
1439 	      , printBasisMetric(base.printBasisMetric)
1440 	      , unitVecs(base.unitVecs)
1441 	      , primRhs(base.primRhs)
1442 	      , primVec(base.primVec)
1443 	      , dualRhs(base.dualRhs)
1444 	      , dualVec(base.dualVec)
1445 	      , addVec(base.addVec)
1446 	      , theURbound(base.theURbound)
1447 	      , theLRbound(base.theLRbound)
1448 	      , theUCbound(base.theUCbound)
1449 	      , theLCbound(base.theLCbound)
1450 	      , theUBbound(base.theUBbound)
1451 	      , theLBbound(base.theLBbound)
1452 	      , theCoTest(base.theCoTest)
1453 	      , theTest(base.theTest)
1454 	      , primalRay(base.primalRay)
1455 	      , dualFarkas(base.dualFarkas)
1456 	      , leaveCount(base.leaveCount)
1457 	      , enterCount(base.enterCount)
1458 	      , primalCount(base.primalCount)
1459 	      , polishCount(base.polishCount)
1460 	      , boundflips(base.boundflips)
1461 	      , totalboundflips(base.totalboundflips)
1462 	      , enterCycles(base.enterCycles)
1463 	      , leaveCycles(base.leaveCycles)
1464 	      , enterDegenCand(base.enterDegenCand)
1465 	      , leaveDegenCand(base.leaveDegenCand)
1466 	      , primalDegenSum(base.primalDegenSum)
1467 	      , dualDegenSum(base.dualDegenSum)
1468 	      , boundrange(base.boundrange)
1469 	      , siderange(base.siderange)
1470 	      , objrange(base.objrange)
1471 	      , infeasibilities(base.infeasibilities)
1472 	      , infeasibilitiesCo(base.infeasibilitiesCo)
1473 	      , isInfeasible(base.isInfeasible)
1474 	      , isInfeasibleCo(base.isInfeasibleCo)
1475 	      , sparsePricingLeave(base.sparsePricingLeave)
1476 	      , sparsePricingEnter(base.sparsePricingEnter)
1477 	      , sparsePricingEnterCo(base.sparsePricingEnterCo)
1478 	      , hyperPricingLeave(base.hyperPricingLeave)
1479 	      , hyperPricingEnter(base.hyperPricingEnter)
1480 	      , remainingRoundsLeave(base.remainingRoundsLeave)
1481 	      , remainingRoundsEnter(base.remainingRoundsEnter)
1482 	      , remainingRoundsEnterCo(base.remainingRoundsEnterCo)
1483 	      , weights(base.weights)
1484 	      , coWeights(base.coWeights)
1485 	      , weightsAreSetup(base.weightsAreSetup)
1486 	      , multSparseCalls(base.multSparseCalls)
1487 	      , multFullCalls(base.multFullCalls)
1488 	      , multColwiseCalls(base.multColwiseCalls)
1489 	      , multUnsetupCalls(base.multUnsetupCalls)
1490 	      , spxout(base.spxout)
1491 	      , integerVariables(base.integerVariables)
1492 	   {
1493 	      theTime = TimerFactory::createTimer(timerType);
1494 	      multTimeSparse = TimerFactory::createTimer(timerType);
1495 	      multTimeFull = TimerFactory::createTimer(timerType);
1496 	      multTimeColwise = TimerFactory::createTimer(timerType);
1497 	      multTimeUnsetup = TimerFactory::createTimer(timerType);
1498 	
1499 	      if(base.theRep == COLUMN)
1500 	      {
1501 	         thevectors   = this->colSet();
1502 	         thecovectors = this->rowSet();
1503 	         theFrhs      = &primRhs;
1504 	         theFvec      = &primVec;
1505 	         theCoPrhs    = &dualRhs;
1506 	         theCoPvec    = &dualVec;
1507 	         thePvec      = &addVec;
1508 	         theRPvec     = theCoPvec;
1509 	         theCPvec     = thePvec;
1510 	         theUbound    = &theUCbound;
1511 	         theLbound    = &theLCbound;
1512 	         theCoUbound  = &theURbound;
1513 	         theCoLbound  = &theLRbound;
1514 	      }
1515 	      else
1516 	      {
1517 	         assert(base.theRep == ROW);
1518 	
1519 	         thevectors   = this->rowSet();
1520 	         thecovectors = this->colSet();
1521 	         theFrhs      = &dualRhs;
1522 	         theFvec      = &dualVec;
1523 	         theCoPrhs    = &primRhs;
1524 	         theCoPvec    = &primVec;
1525 	         thePvec      = &addVec;
1526 	         theRPvec     = thePvec;
1527 	         theCPvec     = theCoPvec;
1528 	         theUbound    = &theURbound;
1529 	         theLbound    = &theLRbound;
1530 	         theCoUbound  = &theUCbound;
1531 	         theCoLbound  = &theLCbound;
1532 	      }
1533 	
1534 	      SPxBasisBase<R>::theLP = this;
1535 	
1536 	      if(base.thepricer == 0)
1537 	      {
1538 	         thepricer = 0;
1539 	         freePricer = false;
1540 	      }
1541 	      else
1542 	      {
1543 	         thepricer = base.thepricer->clone();
1544 	         freePricer = true;
1545 	         thepricer->clear();
1546 	         thepricer->load(this);
1547 	      }
1548 	
1549 	      if(base.theratiotester == 0)
1550 	      {
1551 	         theratiotester = 0;
1552 	         freeRatioTester = false;
1553 	      }
1554 	      else
1555 	      {
1556 	         theratiotester = base.theratiotester->clone();
1557 	         freeRatioTester = true;
1558 	         theratiotester->clear();
1559 	         theratiotester->load(this);
1560 	      }
1561 	
1562 	      if(base.thestarter == 0)
1563 	      {
1564 	         thestarter = 0;
1565 	         freeStarter = false;
1566 	      }
1567 	      else
1568 	      {
1569 	         thestarter = base.thestarter->clone();
1570 	         freeStarter = true;
1571 	      }
1572 	
1573 	      assert(SPxSolverBase<R>::isConsistent());
1574 	   }
1575 	
1576 	   template <class R>
1577 	   bool SPxSolverBase<R>::isConsistent() const
1578 	   {
1579 	#ifdef ENABLE_CONSISTENCY_CHECKS
1580 	
1581 	      if(epsilon() < 0 || tolerances() == nullptr)
1582 	         return SPX_MSG_INCONSISTENT("SPxSolverBase");
1583 	
1584 	      if(primVec.delta().tolerances() != dualVec.delta().tolerances())
1585 	         return SPX_MSG_INCONSISTENT("SPxSolverBase");
1586 	
1587 	      if(dualVec.delta().tolerances() != addVec.delta().tolerances())
1588 	         return SPX_MSG_INCONSISTENT("SPxSolverBase");
1589 	
1590 	      if(unitVecs.size() < SPxLPBase<R>::nCols() || unitVecs.size() < SPxLPBase<R>::nRows())
1591 	         return SPX_MSG_INCONSISTENT("SPxSolverBase");
1592 	
1593 	      if(initialized)
1594 	      {
1595 	         if(theFrhs->dim() != dim())
1596 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1597 	
1598 	         if(theFvec->dim() != dim())
1599 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1600 	
1601 	         if(theCoPrhs->dim() != dim())
1602 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1603 	
1604 	         if(thePvec->dim() != coDim())
1605 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1606 	
1607 	         if(theCoPvec->dim() != dim())
1608 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1609 	
1610 	         if(theTest.dim() != coDim())
1611 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1612 	
1613 	         if(theCoTest.dim() != dim())
1614 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1615 	
1616 	         if(theURbound.dim() != SPxLPBase<R>::nRows())
1617 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1618 	
1619 	         if(theLRbound.dim() != SPxLPBase<R>::nRows())
1620 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1621 	
1622 	         if(theUCbound.dim() != SPxLPBase<R>::nCols())
1623 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1624 	
1625 	         if(theLCbound.dim() != SPxLPBase<R>::nCols())
1626 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1627 	
1628 	         if(theUBbound.dim() != dim())
1629 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1630 	
1631 	         if(theLBbound.dim() != dim())
1632 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1633 	      }
1634 	
1635 	      if(rep() == COLUMN)
1636 	      {
1637 	         if(thecovectors !=
1638 	               reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPRowSetBase<R>*>(this))
1639 	               || thevectors !=
1640 	               reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPColSetBase<R>*>(this))
1641 	               || theFrhs != &primRhs ||
1642 	               theFvec != &primVec ||
1643 	               theCoPrhs != &dualRhs ||
1644 	               theCoPvec != &dualVec ||
1645 	               thePvec != &addVec ||
1646 	               theRPvec != theCoPvec ||
1647 	               theCPvec != thePvec ||
1648 	               theUbound != &theUCbound ||
1649 	               theLbound != &theLCbound ||
1650 	               theCoUbound != &theURbound ||
1651 	               theCoLbound != &theLRbound)
1652 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1653 	      }
1654 	      else
1655 	      {
1656 	         if(thecovectors
1657 	               != reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPColSetBase<R>*>(this))
1658 	               || thevectors
1659 	               != reinterpret_cast<const SVSetBase<R> *>(static_cast<const LPRowSetBase<R>*>(this))
1660 	               || theFrhs != &dualRhs ||
1661 	               theFvec != &dualVec ||
1662 	               theCoPrhs != &primRhs ||
1663 	               theCoPvec != &primVec ||
1664 	               thePvec != &addVec ||
1665 	               theRPvec != thePvec ||
1666 	               theCPvec != theCoPvec ||
1667 	               theUbound != &theURbound ||
1668 	               theLbound != &theLRbound ||
1669 	               theCoUbound != &theUCbound ||
1670 	               theCoLbound != &theLCbound)
1671 	            return SPX_MSG_INCONSISTENT("SPxSolverBase");
1672 	      }
1673 	
1674 	      return SPxLPBase<R>::isConsistent()
1675 	             && primRhs.isConsistent()
1676 	             && primVec.isConsistent()
1677 	             && dualRhs.isConsistent()
1678 	             && dualVec.isConsistent()
1679 	             && addVec.isConsistent()
1680 	             && theTest.isConsistent()
1681 	             && theCoTest.isConsistent()
1682 	             && theURbound.isConsistent()
1683 	             && theLRbound.isConsistent()
1684 	             && theUCbound.isConsistent()
1685 	             && theLCbound.isConsistent()
1686 	             && SPxBasisBase<R>::isConsistent()
1687 	             ;
1688 	#else
1689 	      return true;
1690 	#endif
1691 	   }
1692 	
1693 	
1694 	   template <class R>
1695 	   void SPxSolverBase<R>::setTerminationTime(Real p_time)
1696 	   {
1697 	      if(p_time < 0.0)
1698 	         p_time = 0.0;
1699 	
1700 	      maxTime = p_time;
1701 	   }
1702 	
1703 	   template <class R>
1704 	   Real SPxSolverBase<R>::terminationTime() const
1705 	   {
1706 	      return maxTime;
1707 	   }
1708 	
1709 	   template <class R>
1710 	   void SPxSolverBase<R>::setTerminationIter(int p_iteration)
1711 	   {
1712 	      if(p_iteration < 0)
1713 	         p_iteration = -1;
1714 	
1715 	      maxIters = p_iteration;
1716 	   }
1717 	
1718 	   template <class R>
1719 	   int SPxSolverBase<R>::terminationIter() const
1720 	   {
1721 	      return maxIters;
1722 	   }
1723 	
1724 	   // returns whether current time limit is reached; call to time() may be skipped unless \p forceCheck is true
1725 	   template <class R>
1726 	   bool SPxSolverBase<R>::isTimeLimitReached(const bool forceCheck)
1727 	   {
1728 	      // always update the number of calls, since the user might set a time limit later in the solving process
1729 	      ++nCallsToTimelim;
1730 	
1731 	      // check if a time limit is actually set
1732 	      if(maxTime >= R(infinity))
1733 	         return false;
1734 	
1735 	      // check if the expensive system call to update the time should be skipped again
1736 	      if(forceCheck || nCallsToTimelim < SOPLEX_NINITCALLS ||  nClckSkipsLeft <= 0)
1737 	      {
1738 	         Real currtime = time();
1739 	
1740 	         if(currtime >= maxTime)
1741 	            return true;
1742 	
1743 	         // determine the number of times the clock can be skipped again.
1744 	         int nClckSkips = SOPLEX_MAXNCLCKSKIPS;
1745 	         Real avgtimeinterval = (currtime + cumulativeTime()) / (Real)(nCallsToTimelim);
1746 	
1747 	         // it would not be safe to skip the clock so many times since we are approaching the time limit
1748 	         if(SOPLEX_SAFETYFACTOR * (maxTime - currtime) / (avgtimeinterval + 1e-6) < nClckSkips)
1749 	            nClckSkips = 0;
1750 	
1751 	         nClckSkipsLeft = nClckSkips;
1752 	      }
1753 	      else
1754 	         --nClckSkipsLeft;
1755 	
1756 	      return false;
1757 	   }
1758 	
1759 	
1760 	   /**@todo A first version for the termination value is
1761 	    *       implemented. Currently we check if no bound violations (shifting)
1762 	    *       is present. It might be even possible to use this termination
1763 	    *       value in case of bound violations (shifting) but in this case it
1764 	    *       is quite difficult to determine if we already reached the limit.
1765 	    */
1766 	   template <class R>
1767 	   void SPxSolverBase<R>::setTerminationValue(R p_value)
1768 	   {
1769 	      objLimit = p_value;
1770 	   }
1771 	
1772 	   template <class R>
1773 	   R SPxSolverBase<R>::terminationValue() const
1774 	   {
1775 	      return objLimit;
1776 	   }
1777 	
1778 	   template <class R>
1779 	   typename SPxSolverBase<R>::VarStatus
1780 	   SPxSolverBase<R>::basisStatusToVarStatus(typename SPxBasisBase<R>::Desc::Status stat) const
1781 	   {
1782 	      VarStatus vstat;
1783 	
1784 	      switch(stat)
1785 	      {
1786 	      case SPxBasisBase<R>::Desc::P_ON_LOWER:
1787 	         vstat = ON_LOWER;
1788 	         break;
1789 	
1790 	      case SPxBasisBase<R>::Desc::P_ON_UPPER:
1791 	         vstat = ON_UPPER;
1792 	         break;
1793 	
1794 	      case SPxBasisBase<R>::Desc::P_FIXED:
1795 	         vstat = FIXED;
1796 	         break;
1797 	
1798 	      case SPxBasisBase<R>::Desc::P_FREE:
1799 	         vstat = ZERO;
1800 	         break;
1801 	
1802 	      case SPxBasisBase<R>::Desc::D_ON_UPPER:
1803 	      case SPxBasisBase<R>::Desc::D_ON_LOWER:
1804 	      case SPxBasisBase<R>::Desc::D_ON_BOTH:
1805 	      case SPxBasisBase<R>::Desc::D_UNDEFINED:
1806 	      case SPxBasisBase<R>::Desc::D_FREE:
1807 	         vstat = BASIC;
1808 	         break;
1809 	
1810 	      default:
1811 	         SPX_MSG_ERROR(std::cerr << "ESOLVE26 ERROR: unknown basis status (" << static_cast<int>(stat) << ")"
1812 	                       << std::endl;)
1813 	         throw SPxInternalCodeException("XSOLVE22 This should never happen.");
1814 	      }
1815 	
1816 	      return vstat;
1817 	   }
1818 	
1819 	   template <class R>
1820 	   typename SPxBasisBase<R>::Desc::Status
1821 	   SPxSolverBase<R>::varStatusToBasisStatusRow(int row,
1822 	         typename SPxSolverBase<R>::VarStatus stat) const
1823 	   {
1824 	      typename SPxBasisBase<R>::Desc::Status rstat;
1825 	
1826 	      switch(stat)
1827 	      {
1828 	      case FIXED :
1829 	         assert(EQ(this->rhs(row), this->lhs(row), tolerances()->floatingPointFeastol()));
1830 	         rstat = SPxBasisBase<R>::Desc::P_FIXED;
1831 	         break;
1832 	
1833 	      case ON_UPPER :
1834 	         assert(this->rhs(row) < R(infinity));
1835 	         rstat = this->lhs(row) < this->rhs(row)
1836 	                 ? SPxBasisBase<R>::Desc::P_ON_UPPER
1837 	                 : SPxBasisBase<R>::Desc::P_FIXED;
1838 	         break;
1839 	
1840 	      case ON_LOWER :
1841 	         assert(this->lhs(row) > R(-infinity));
1842 	         rstat = this->lhs(row) < this->rhs(row)
1843 	                 ? SPxBasisBase<R>::Desc::P_ON_LOWER
1844 	                 : SPxBasisBase<R>::Desc::P_FIXED;
1845 	         break;
1846 	
1847 	      case ZERO :
1848 	         /* A 'free' row (i.e., infinite lower & upper bounds) does not really make sense. The user
1849 	          * might (think to) know better, e.g., when temporarily turning off a row. We therefore apply
1850 	          * the same adjustment as in the column case in varStatusToBasisStatusCol(). */
1851 	         rstat = SPxBasisBase<R>::Desc::P_FREE;
1852 	         break;
1853 	
1854 	      case BASIC :
1855 	         rstat = this->dualRowStatus(row);
1856 	         break;
1857 	
1858 	      default:
1859 	         SPX_MSG_ERROR(std::cerr << "ESOLVE27 ERROR: unknown VarStatus (" << int(stat) << ")"
1860 	                       << std::endl;)
1861 	         throw SPxInternalCodeException("XSOLVE23 This should never happen.");
1862 	      }
1863 	
1864 	      return rstat;
1865 	   }
1866 	
1867 	   template <class R>
1868 	   typename SPxBasisBase<R>::Desc::Status
1869 	   SPxSolverBase<R>::varStatusToBasisStatusCol(int col,
1870 	         typename SPxSolverBase<R>::VarStatus stat) const
1871 	   {
1872 	      typename SPxBasisBase<R>::Desc::Status cstat;
1873 	
1874 	      switch(stat)
1875 	      {
1876 	      case FIXED :
1877 	         if(this->upper(col) == this->lower(col))
1878 	            cstat = SPxBasisBase<R>::Desc::P_FIXED;
1879 	         else if(this->maxObj(col) > 0.0)
1880 	            cstat = SPxBasisBase<R>::Desc::P_ON_UPPER;
1881 	         else
1882 	            cstat = SPxBasisBase<R>::Desc::P_ON_LOWER;
1883 	
1884 	         break;
1885 	
1886 	      case ON_UPPER :
1887 	         assert(this->upper(col) < R(infinity));
1888 	         cstat = this->lower(col) < this->upper(col)
1889 	                 ? SPxBasisBase<R>::Desc::P_ON_UPPER
1890 	                 : SPxBasisBase<R>::Desc::P_FIXED;
1891 	         break;
1892 	
1893 	      case ON_LOWER :
1894 	         assert(this->lower(col) > R(-infinity));
1895 	         cstat = this->lower(col) < this->upper(col)
1896 	                 ? SPxBasisBase<R>::Desc::P_ON_LOWER
1897 	                 : SPxBasisBase<R>::Desc::P_FIXED;
1898 	         break;
1899 	
1900 	      case ZERO :
1901 	
1902 	         /* In this case the upper and lower bounds on the variable should be infinite. The bounds
1903 	          * might, however, have changed and we try to recover from this by changing the status to
1904 	          * 'resonable' settings. Since the status should be implicit free we still always set it
1905 	          * to P_FREE to be consistent */
1906 	         cstat = SPxBasisBase<R>::Desc::P_FREE;
1907 	         break;
1908 	
1909 	      case BASIC :
1910 	         cstat = this->dualColStatus(col);
1911 	         break;
1912 	
1913 	      default:
1914 	         SPX_MSG_ERROR(std::cerr << "ESOLVE28 ERROR: unknown VarStatus (" << int(stat) << ")"
1915 	                       << std::endl;)
1916 	         throw SPxInternalCodeException("XSOLVE24 This should never happen.");
1917 	      }
1918 	
1919 	      return cstat;
1920 	   }
1921 	
1922 	   template <class R>
1923 	   typename SPxSolverBase<R>::VarStatus SPxSolverBase<R>::getBasisRowStatus(int row) const
1924 	   {
1925 	      assert(0 <= row && row < this->nRows());
1926 	      return basisStatusToVarStatus(this->desc().rowStatus(row));
1927 	   }
1928 	
1929 	   template <class R>
1930 	   typename SPxSolverBase<R>::VarStatus SPxSolverBase<R>::getBasisColStatus(int col) const
1931 	   {
1932 	      assert(0 <= col && col < this->nCols());
1933 	      return basisStatusToVarStatus(this->desc().colStatus(col));
1934 	   }
1935 	
1936 	   template <class R>
1937 	   typename SPxSolverBase<R>::Status SPxSolverBase<R>::getBasis(VarStatus row[], VarStatus col[],
1938 	         const int rowsSize, const int colsSize) const
1939 	   {
1940 	      const typename SPxBasisBase<R>::Desc& d = this->desc();
1941 	      int i;
1942 	
1943 	      assert(rowsSize < 0 || rowsSize >= this->nRows());
1944 	      assert(colsSize < 0 || colsSize >= this->nCols());
1945 	
1946 	      if(col)
1947 	         for(i = this->nCols() - 1; i >= 0; --i)
1948 	            col[i] = basisStatusToVarStatus(d.colStatus(i));
1949 	
1950 	      if(row)
1951 	         for(i = this->nRows() - 1; i >= 0; --i)
1952 	            row[i] = basisStatusToVarStatus(d.rowStatus(i));
1953 	
1954 	      return status();
1955 	   }
1956 	
1957 	   template <class R>
1958 	   bool SPxSolverBase<R>::isBasisValid(DataArray<VarStatus> p_rows, DataArray<VarStatus> p_cols)
1959 	   {
1960 	
1961 	      int basisdim;
1962 	
1963 	      if(p_rows.size() != this->nRows() || p_cols.size() != this->nCols())
1964 	         return false;
1965 	
1966 	      basisdim = 0;
1967 	
1968 	      for(int row = this->nRows() - 1; row >= 0; --row)
1969 	      {
1970 	         if(p_rows[row] == UNDEFINED)
1971 	            return false;
1972 	         // row is basic
1973 	         else if(p_rows[row] == BASIC)
1974 	         {
1975 	            basisdim++;
1976 	         }
1977 	         // row is nonbasic
1978 	         else
1979 	         {
1980 	            if((p_rows[row] == FIXED && this->lhs(row) != this->rhs(row))
1981 	                  || (p_rows[row] == ON_UPPER && this->rhs(row) >= R(infinity))
1982 	                  || (p_rows[row] == ON_LOWER && this->lhs(row) <= R(-infinity)))
1983 	               return false;
1984 	         }
1985 	      }
1986 	
1987 	      for(int col = this->nCols() - 1; col >= 0; --col)
1988 	      {
1989 	         if(p_cols[col] == UNDEFINED)
1990 	            return false;
1991 	         // col is basic
1992 	         else if(p_cols[col] == BASIC)
1993 	         {
1994 	            basisdim++;
1995 	         }
1996 	         // col is nonbasic
1997 	         else
1998 	         {
1999 	            if((p_cols[col] == FIXED && this->lower(col) != this->upper(col))
2000 	                  || (p_cols[col] == ON_UPPER && this->upper(col) >= R(infinity))
2001 	                  || (p_cols[col] == ON_LOWER && this->lower(col) <= R(-infinity)))
2002 	               return false;
2003 	         }
2004 	      }
2005 	
2006 	      if(basisdim != dim())
2007 	         return false;
2008 	
2009 	      // basis valid
2010 	      return true;
2011 	   }
2012 	
2013 	   template <class R>
2014 	   void SPxSolverBase<R>::setBasis(const VarStatus p_rows[], const VarStatus p_cols[])
2015 	   {
2016 	      if(SPxBasisBase<R>::status() == SPxBasisBase<R>::NO_PROBLEM)
2017 	         SPxBasisBase<R>::load(this, false);
2018 	
2019 	      typename SPxBasisBase<R>::Desc ds = this->desc();
2020 	      int i;
2021 	
2022 	      for(i = 0; i < this->nRows(); i++)
2023 	         ds.rowStatus(i) = varStatusToBasisStatusRow(i, p_rows[i]);
2024 	
2025 	      for(i = 0; i < this->nCols(); i++)
2026 	         ds.colStatus(i) = varStatusToBasisStatusCol(i, p_cols[i]);
2027 	
2028 	      loadBasis(ds);
2029 	      forceRecompNonbasicValue();
2030 	   }
2031 	
2032 	   // NOTE: This only works for the row representation. Need to update to account for column representation.
2033 	   // The degenvec differs relative to the algorithm being used.
2034 	   // For the primal simplex, degenvec is the primal solution values.
2035 	   // For the dual simplex, the degenvec is the feasvec (ROW) and pVec (COLUMN).
2036 	   template <class R>
2037 	   R SPxSolverBase<R>::getDegeneracyLevel(VectorBase<R> degenvec)
2038 	   {
2039 	      int numDegenerate = 0;
2040 	      R degeneracyLevel = 0;
2041 	
2042 	      // iterating over all columns in the basis matrix
2043 	      // this identifies the basis indices and those that have a zero dual multiplier (rows) or zero reduced cost (cols).
2044 	      if(rep() == ROW)
2045 	      {
2046 	         for(int i = 0; i < this->nCols();
2047 	               ++i)   // @todo Check the use of numColsReal for the reduced problem.
2048 	         {
2049 	            // degeneracy in the dual simplex exists if there are rows with a zero dual multiplier or columns with a zero
2050 	            // reduced costs. This requirement is regardless of the objective sense.
2051 	            if(isZero(degenvec[i], tolerances()->floatingPointFeastol()))
2052 	               numDegenerate++;
2053 	         }
2054 	
2055 	         if(type() == ENTER)     // dual simplex
2056 	            degeneracyLevel = R(numDegenerate) / this->nCols();
2057 	         else                    // primal simplex
2058 	         {
2059 	            assert(type() == LEAVE);
2060 	            R degenVars = (numDegenerate > (this->nCols() - this->nRows())) ? R(numDegenerate -
2061 	                          (this->nCols() - this->nRows())) : 0.0;
2062 	            degeneracyLevel = degenVars / this->nRows();
2063 	         }
2064 	      }
2065 	      else
2066 	      {
2067 	         assert(rep() == COLUMN);
2068 	
2069 	         for(int i = 0; i < this->nCols(); i++)
2070 	         {
2071 	            if(type() == LEAVE)     // dual simplex
2072 	            {
2073 	               if(isZero(this->maxObj()[i] - degenvec[i], tolerances()->floatingPointFeastol()))
2074 	                  numDegenerate++;
2075 	            }
2076 	            else                    // primal simplex
2077 	            {
2078 	               assert(type() == ENTER);
2079 	
2080 	               if(isZero(degenvec[i], tolerances()->floatingPointFeastol()))
2081 	                  numDegenerate++;
2082 	            }
2083 	         }
2084 	
2085 	
2086 	         if(type() == LEAVE)     // dual simplex
2087 	         {
2088 	            R degenVars = this->nRows() > numDegenerate ? R(this->nRows() - numDegenerate) : 0.0;
2089 	            degeneracyLevel = degenVars / this->nCols();
2090 	         }
2091 	         else                    // primal simplex
2092 	         {
2093 	            assert(type() == ENTER);
2094 	            R degenVars = (numDegenerate > (this->nCols() - this->nRows())) ? R(numDegenerate -
2095 	                          (this->nCols() - this->nRows())) : 0.0;
2096 	            degeneracyLevel = degenVars / this->nRows();
2097 	         }
2098 	      }
2099 	
2100 	      return degeneracyLevel;
2101 	   }
2102 	
2103 	   template <class R>
2104 	   void SPxSolverBase<R>::getNdualNorms(int& nnormsRow, int& nnormsCol) const
2105 	   {
2106 	      nnormsRow = 0;
2107 	      nnormsCol = 0;
2108 	
2109 	      if(weightsAreSetup)
2110 	      {
2111 	         if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN)
2112 	         {
2113 	            nnormsRow = coWeights.dim();
2114 	            nnormsCol = 0;
2115 	
2116 	            assert(nnormsRow == dim());
2117 	         }
2118 	         else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW)
2119 	         {
2120 	            nnormsRow = weights.dim();
2121 	            nnormsCol = coWeights.dim();
2122 	
2123 	            assert(nnormsRow == coDim());
2124 	            assert(nnormsCol == dim());
2125 	         }
2126 	      }
2127 	   }
2128 	
2129 	   template <class R>
2130 	   bool SPxSolverBase<R>::getDualNorms(int& nnormsRow, int& nnormsCol, R * norms) const
2131 	   {
2132 	      nnormsRow = 0;
2133 	      nnormsCol = 0;
2134 	
2135 	      if(!weightsAreSetup)
2136 	         return false;
2137 	
2138 	      if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN)
2139 	      {
2140 	         nnormsCol = 0;
2141 	         nnormsRow = coWeights.dim();
2142 	
2143 	         assert(nnormsRow == dim());
2144 	
2145 	         for(int i = 0; i < nnormsRow; ++i)
2146 	            norms[i] = coWeights[i];
2147 	      }
2148 	      else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW)
2149 	      {
2150 	         nnormsRow = weights.dim();
2151 	         nnormsCol = coWeights.dim();
2152 	
2153 	         assert(nnormsCol == dim());
2154 	         assert(nnormsRow == coDim());
2155 	
2156 	         for(int i = 0; i < nnormsRow; ++i)
2157 	            norms[i] = weights[i];
2158 	
2159 	         for(int i = 0; i < nnormsCol; ++i)
2160 	            norms[nnormsRow + i] = coWeights[i];
2161 	      }
2162 	      else
2163 	         return false;
2164 	
2165 	      return true;
2166 	   }
2167 	
2168 	   template <class R>
2169 	   bool SPxSolverBase<R>::setDualNorms(int nnormsRow, int nnormsCol, R * norms)
2170 	   {
2171 	      weightsAreSetup = false;
2172 	
2173 	      if(type() == SPxSolverBase<R>::LEAVE && rep() == SPxSolverBase<R>::COLUMN)
2174 	      {
2175 	         coWeights.reDim(dim(), false);
2176 	         assert(coWeights.dim() >= nnormsRow);
2177 	
2178 	         for(int i = 0; i < nnormsRow; ++i)
2179 	            coWeights[i] = norms[i];
2180 	
2181 	         weightsAreSetup = true;
2182 	      }
2183 	      else if(type() == SPxSolverBase<R>::ENTER && rep() == SPxSolverBase<R>::ROW)
2184 	      {
2185 	         weights.reDim(coDim(), false);
2186 	         coWeights.reDim(dim(), false);
2187 	         assert(weights.dim() >= nnormsRow);
2188 	         assert(coWeights.dim() >= nnormsCol);
2189 	
2190 	         for(int i = 0; i < nnormsRow; ++i)
2191 	            weights[i] = norms[i];
2192 	
2193 	         for(int i = 0; i < nnormsCol; ++i)
2194 	            coWeights[i] = norms[nnormsRow + i];
2195 	
2196 	         weightsAreSetup = true;
2197 	      }
2198 	      else
2199 	         return false;
2200 	
2201 	      return true;
2202 	   }
2203 	
2204 	   template <class R>
2205 	   void SPxSolverBase<R>::setIntegralityInformation(int ncols, int* intInfo)
2206 	   {
2207 	      assert(ncols == this->nCols() || (ncols == 0 && intInfo == NULL));
2208 	
2209 	      integerVariables.reSize(ncols);
2210 	
2211 	      for(int i = 0; i < ncols; ++i)
2212 	      {
2213 	         integerVariables[i] = intInfo[i];
2214 	      }
2215 	   }
2216 	
2217 	
2218 	
2219 	   //
2220 	   // Auxiliary functions.
2221 	   //
2222 	
2223 	   // Pretty-printing of variable status.
2224 	   template <class R>
2225 	   std::ostream& operator<<(std::ostream & os,
2226 	                            const typename SPxSolverBase<R>::VarStatus & status)
2227 	   {
2228 	      switch(status)
2229 	      {
2230 	      case SPxSolverBase<R>::BASIC:
2231 	         os << "BASIC";
2232 	         break;
2233 	
2234 	      case SPxSolverBase<R>::FIXED:
2235 	         os << "FIXED";
2236 	         break;
2237 	
2238 	      case SPxSolverBase<R>::ON_LOWER:
2239 	         os << "ON_LOWER";
2240 	         break;
2241 	
2242 	      case SPxSolverBase<R>::ON_UPPER:
2243 	         os << "ON_UPPER";
2244 	         break;
2245 	
2246 	      case SPxSolverBase<R>::ZERO:
2247 	         os << "ZERO";
2248 	         break;
2249 	
2250 	      case SPxSolverBase<R>::UNDEFINED:
2251 	         os << "UNDEFINED";
2252 	         break;
2253 	
2254 	      default:
2255 	         os << "?invalid?";
2256 	         break;
2257 	      }
2258 	
2259 	      return os;
2260 	   }
2261 	
2262 	   // Pretty-printing of solver status.
2263 	   template <class R>
2264 	   std::ostream& operator<<(std::ostream & os,
2265 	                            const typename SPxSolverBase<R>::Status & status)
2266 	   {
2267 	      switch(status)
2268 	      {
2269 	      case SPxSolverBase<R>::ERROR:
2270 	         os << "ERROR";
2271 	         break;
2272 	
2273 	      case SPxSolverBase<R>::NO_RATIOTESTER:
2274 	         os << "NO_RATIOTESTER";
2275 	         break;
2276 	
2277 	      case SPxSolverBase<R>::NO_PRICER:
2278 	         os << "NO_PRICER";
2279 	         break;
2280 	
2281 	      case SPxSolverBase<R>::NO_SOLVER:
2282 	         os << "NO_SOLVER";
2283 	         break;
2284 	
2285 	      case SPxSolverBase<R>::NOT_INIT:
2286 	         os << "NOT_INIT";
2287 	         break;
2288 	
2289 	      case SPxSolverBase<R>::ABORT_CYCLING:
2290 	         os << "ABORT_CYCLING";
2291 	         break;
2292 	
2293 	      case SPxSolverBase<R>::ABORT_TIME:
2294 	         os << "ABORT_TIME";
2295 	         break;
2296 	
2297 	      case SPxSolverBase<R>::ABORT_ITER:
2298 	         os << "ABORT_ITER";
2299 	         break;
2300 	
2301 	      case SPxSolverBase<R>::ABORT_VALUE:
2302 	         os << "ABORT_VALUE";
2303 	         break;
2304 	
2305 	      case SPxSolverBase<R>::SINGULAR:
2306 	         os << "SINGULAR";
2307 	         break;
2308 	
2309 	      case SPxSolverBase<R>::NO_PROBLEM:
2310 	         os << "NO_PROBLEM";
2311 	         break;
2312 	
2313 	      case SPxSolverBase<R>::REGULAR:
2314 	         os << "REGULAR";
2315 	         break;
2316 	
2317 	      case SPxSolverBase<R>::RUNNING:
2318 	         os << "RUNNING";
2319 	         break;
2320 	
2321 	      case SPxSolverBase<R>::UNKNOWN:
2322 	         os << "UNKNOWN";
2323 	         break;
2324 	
2325 	      case SPxSolverBase<R>::OPTIMAL:
2326 	         os << "OPTIMAL";
2327 	         break;
2328 	
2329 	      case SPxSolverBase<R>::UNBOUNDED:
2330 	         os << "UNBOUNDED";
2331 	         break;
2332 	
2333 	      case SPxSolverBase<R>::INFEASIBLE:
2334 	         os << "INFEASIBLE";
2335 	         break;
2336 	
2337 	      default:
2338 	         os << "?other?";
2339 	         break;
2340 	      }
2341 	
2342 	      return os;
2343 	   }
2344 	
2345 	   // Pretty-printing of algorithm.
2346 	   template <class R>
2347 	   std::ostream& operator<<(std::ostream & os,
2348 	                            const typename SPxSolverBase<R>::Type & status)
2349 	   {
2350 	      switch(status)
2351 	      {
2352 	      case SPxSolverBase<R>::ENTER:
2353 	         os << "ENTER";
2354 	         break;
2355 	
2356 	      case SPxSolverBase<R>::LEAVE:
2357 	         os << "LEAVE";
2358 	         break;
2359 	
2360 	      default:
2361 	         os << "?other?";
2362 	         break;
2363 	      }
2364 	
2365 	      return os;
2366 	   }
2367 	
2368 	   // Pretty-printing of representation.
2369 	   template <class R>
2370 	   std::ostream& operator<<(std::ostream & os,
2371 	                            const typename SPxSolverBase<R>::Representation & status)
2372 	   {
2373 	      switch(status)
2374 	      {
2375 	      case SPxSolverBase<R>::ROW:
2376 	         os << "ROW";
2377 	         break;
2378 	
2379 	      case SPxSolverBase<R>::COLUMN:
2380 	         os << "COLUMN";
2381 	         break;
2382 	
2383 	      default:
2384 	         os << "?other?";
2385 	         break;
2386 	      }
2387 	
2388 	      return os;
2389 	   }
2390 	
2391 	
2392 	} // namespace soplex
2393