1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*    Copyright (C) 1996-2022 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   	/**@file  spxlpbase.h
17   	 * @brief Saving LPs in a form suitable for SoPlex.
18   	 */
19   	#ifndef _SPXLPBASE_H_
20   	#define _SPXLPBASE_H_
21   	
22   	/* undefine SOPLEX_DEBUG flag from including files; if SOPLEX_DEBUG should be defined in this file, do so below */
23   	#ifdef SOPLEX_DEBUG
24   	#define SOPLEX_DEBUG_SPXLPBASE
25   	#undef SOPLEX_DEBUG
26   	#endif
27   	
28   	#include <assert.h>
29   	#include <iostream>
30   	#include <iomanip>
31   	#include <typeinfo>
32   	
33   	#include "soplex/spxdefines.h"
34   	#include "soplex/basevectors.h"
35   	#include "soplex/dataarray.h"
36   	#include "soplex/datakey.h"
37   	#include "soplex/spxid.h"
38   	#include "soplex/lprowbase.h"
39   	#include "soplex/lpcolbase.h"
40   	#include "soplex/lprowsetbase.h"
41   	#include "soplex/lpcolsetbase.h"
42   	#include "soplex/nameset.h"
43   	#include "soplex/didxset.h"
44   	#include "soplex/spxfileio.h"
45   	#include "soplex/spxscaler.h"
46   	#include "soplex/rational.h"
47   	
48   	namespace soplex
49   	{
50   	// Declarations to fix errors of the form "SPxMainSM is not a type"
51   	template <class R>
52   	class SPxSolverBase;
53   	template <class R>
54   	class SPxMainSM;
55   	template <class R>
56   	class SPxLPBase;
57   	template <class R>
58   	class SPxBasisBase;
59   	
60   	template <class R>
61   	class SPxEquiliSC;
62   	template <class R>
63   	class SPxLeastSqSC;
64   	template <class R>
65   	class SPxGeometSC;
66   	template <class R>
67   	class SPxMainSM;
68   	
69   	
70   	/**@brief   Saving LPs in a form suitable for SoPlex.
71   	 * @ingroup Algo
72   	 *
73   	 *  Class SPxLPBase provides the data structures required for saving a linear program in the form
74   	 *  \f[
75   	 *  \begin{array}{rl}
76   	 *      \hbox{max}  & c^T x              \\
77   	 *      \hbox{s.t.} & l_r \le Ax \le u_r \\
78   	 *                  & l_c \le x \le u_c
79   	 *  \end{array}
80   	 *  \f]
81   	 *  suitable for solving with SoPlex. This includes:
82   	 *  - SVSetBase%s for both columns and rows
83   	 *  - objective Vector
84   	 *  - upper and lower bound Vectors for variables (\f$l_c\f$ and \f$u_c\f$)
85   	 *  - upper and lower bound Vectors for inequalities (\f$l_r\f$ and \f$u_r\f$)
86   	 *
87   	 *  Note, that the optimization sense is not saved directly. Instead, the objective function are multiplied by -1 to
88   	 *  transform the LP to our standard form maximizing the objective function. However, the sense of the loaded LP can be
89   	 *  retrieved with method #spxSense().
90   	 *
91   	 *  Further, equality constraints are modeled by \f$l_r = u_r\f$.  Analogously, fixed variables have \f$l_c = u_c\f$.
92   	 *
93   	 *  #SPxLPBase%s are saved as an SVSet, both for columns and rows. Note that this is redundant but eases the access.
94   	 */
95   	
96   	
97   	template <class R>
98   	class SPxLPBase : protected LPRowSetBase<R>, protected LPColSetBase<R>
99   	{
100  	   template <class S> friend class SPxLPBase;
101  	   friend SPxBasisBase<R>;
102  	   friend SPxScaler<R>;
103  	   friend SPxEquiliSC<R>;
104  	   friend SPxLeastSqSC<R>;
105  	   friend SPxGeometSC<R>;
106  	   friend SPxMainSM<R>;
107  	
108  	public:
109  	
110  	   // ------------------------------------------------------------------------------------------------------------------
111  	   /**@name Types */
112  	   ///@{
113  	
114  	   /// Optimization sense.
115  	   enum SPxSense
116  	   {
117  	      MAXIMIZE = 1,
118  	      MINIMIZE = -1
119  	   };
120  	
121  	   ///@}
122  	
123  	private:
124  	
125  	   // ------------------------------------------------------------------------------------------------------------------
126  	   /**@name Data */
127  	   ///@{
128  	
129  	   SPxSense thesense;                ///< optimization sense.
130  	   R offset;                         ///< offset computed, e.g., in simplification step
131  	   bool _isScaled;                   ///< true, if scaling has been performed
132  	   SPxScaler<R>*
133  	   lp_scaler;             ///< points to the scaler if the lp has been scaled, to nullptr otherwise
134  	
135  	   ///@}
136  	
137  	public:
138  	
139  	   // message handler
140  	   SPxOut* spxout;
141  	
142  	public:
143  	
144  	   void setOutstream(SPxOut& newOutstream)
145  	   {
146  	      spxout = &newOutstream;
147  	   }
148  	
149  	   // ------------------------------------------------------------------------------------------------------------------
150  	
151  	   /// unscales the lp and clears basis
152  	   void unscaleLP();
153  	
154  	   /**@name Inquiry */
155  	   ///@{
156  	
157  	   /// Returns true if and only if the LP is scaled
158  	   bool isScaled() const
159  	   {
160  	      return _isScaled;
161  	   }
162  	
163  	   /// set whether the LP is scaled or not
164  	   void setScalingInfo(bool scaled)
165  	   {
166  	      _isScaled = scaled;
167  	   }
168  	
169  	   /// Returns number of rows in LP.
170  	   int nRows() const
171  	   {
172  	      return LPRowSetBase<R>::num();
173  	   }
174  	
175  	   /// Returns number of columns in LP.
176  	   int nCols() const
177  	   {
178  	      return LPColSetBase<R>::num();
179  	   }
180  	
181  	   /// Returns number of nonzeros in LP.
182  	   int nNzos() const
183  	   {
184  	
185  	      int n = 0;
186  	
187  	      for(int i = 0; i < nCols(); ++i)
188  	         n += colVector(i).size();
189  	
190  	      return n;
191  	   }
192  	
193  	   /// Absolute smallest non-zero element in (possibly scaled) LP.
194  	   virtual R minAbsNzo(bool unscaled = true) const;
195  	
196  	   /// Absolute biggest non-zero element in (in rational case possibly scaled) LP.
197  	   virtual R maxAbsNzo(bool unscaled = true) const;
198  	
199  	   /// Gets \p i 'th row.
200  	   void getRow(int i, LPRowBase<R>& row) const
201  	   {
202  	      row.setLhs(lhs(i));
203  	      row.setRhs(rhs(i));
204  	      row.setObj(rowObj(i));
205  	      row.setRowVector(DSVectorBase<R>(rowVector(i)));
206  	   }
207  	
208  	   /// Gets row with identifier \p id.
209  	   void getRow(const SPxRowId& id, LPRowBase<R>& row) const
210  	   {
211  	      getRow(number(id), row);
212  	   }
213  	
214  	   /// Gets rows \p start, ... \p end.
215  	   void getRows(int start, int end, LPRowSetBase<R>& set) const
216  	   {
217  	      set.clear();
218  	
219  	      for(int i = start; i <= end; i++)
220  	         set.add(lhs(i), rowVector(i), rhs(i), rowObj(i));
221  	   }
222  	
223  	   /// Gets row vector of row \p i.
224  	   const SVectorBase<R>& rowVector(int i) const
225  	   {
226  	      return LPRowSetBase<R>::rowVector(i);
227  	   }
228  	
229  	   /// Gets row vector of row with identifier \p id.
230  	   const SVectorBase<R>& rowVector(const SPxRowId& id) const
231  	   {
232  	      return LPRowSetBase<R>::rowVector(id);
233  	   }
234  	
235  	   /// Gets unscaled row vector of row \p i.
236  	   void getRowVectorUnscaled(int i, DSVectorBase<R>& vec) const;
237  	
238  	   /// Returns right hand side vector.
239  	   const VectorBase<R>& rhs() const
240  	   {
241  	      return LPRowSetBase<R>::rhs();
242  	   }
243  	
244  	   /// Returns right hand side of row number \p i.
245  	   const R& rhs(int i) const
246  	   {
247  	      return LPRowSetBase<R>::rhs(i);
248  	   }
249  	
250  	
251  	   /// Returns right hand side of row with identifier \p id.
252  	   const R& rhs(const SPxRowId& id) const
253  	   {
254  	      return LPRowSetBase<R>::rhs(id);
255  	   }
256  	
257  	   /// Gets (internal and possibly scaled) right hand side vector.
258  	   void getRhs(VectorBase<R>& vec) const
259  	   {
260  	      vec = LPRowSetBase<R>::rhs();
261  	   }
262  	
263  	   /// Gets unscaled right hand side vector.
264  	   void getRhsUnscaled(VectorBase<R>& vec) const;
265  	
266  	   /// Returns unscaled right hand side of row number \p i.
267  	   R rhsUnscaled(int i) const;
268  	
269  	   /// Returns unscaled right hand side of row with identifier \p id.
270  	   R rhsUnscaled(const SPxRowId& id) const;
271  	
272  	   /// Returns left hand side vector.
273  	   const VectorBase<R>& lhs() const
274  	   {
275  	      return LPRowSetBase<R>::lhs();
276  	   }
277  	
278  	   /// Returns left hand side of row number \p i.
279  	   const R& lhs(int i) const
280  	   {
281  	      return LPRowSetBase<R>::lhs(i);
282  	   }
283  	
284  	   /// Returns left hand side of row with identifier \p id.
285  	   const R& lhs(const SPxRowId& id) const
286  	   {
287  	      return LPRowSetBase<R>::lhs(id);
288  	   }
289  	
290  	   /// Gets row objective function vector.
291  	   void getRowObj(VectorBase<R>& prowobj) const
292  	   {
293  	      prowobj = LPRowSetBase<R>::obj();
294  	
295  	      if(spxSense() == MINIMIZE)
296  	         prowobj *= -1.0;
297  	   }
298  	
299  	   ///
300  	   R rowObj(int i) const
301  	   {
302  	      if(spxSense() == MINIMIZE)
303  	         return -maxRowObj(i);
304  	      else
305  	         return maxRowObj(i);
306  	   }
307  	
308  	   /// Returns row objective function value of row with identifier \p id.
309  	   R rowObj(const SPxRowId& id) const
310  	   {
311  	      if(spxSense() == MINIMIZE)
312  	         return -maxRowObj(id);
313  	      else
314  	         return maxRowObj(id);
315  	   }
316  	
317  	   ///
318  	   const VectorBase<R>& maxRowObj() const
319  	   {
320  	      return LPRowSetBase<R>::obj();
321  	   }
322  	
323  	   ///
324  	   const R& maxRowObj(int i) const
325  	   {
326  	      return LPRowSetBase<R>::obj(i);
327  	   }
328  	
329  	   /// Returns row objective function value of row with identifier \p id.
330  	   const R& maxRowObj(const SPxRowId& id) const
331  	   {
332  	      return LPRowSetBase<R>::obj(id);
333  	   }
334  	
335  	   /// Returns unscaled left hand side vector.
336  	   void getLhsUnscaled(VectorBase<R>& vec) const;
337  	
338  	   /// Returns unscaled left hand side of row number \p i.
339  	   R lhsUnscaled(int i) const;
340  	
341  	   /// Returns left hand side of row with identifier \p id.
342  	   R lhsUnscaled(const SPxRowId& id) const;
343  	
344  	   /// Returns the inequality type of the \p i'th LPRow.
345  	   typename LPRowBase<R>::Type rowType(int i) const
346  	   {
347  	      return LPRowSetBase<R>::type(i);
348  	   }
349  	
350  	   /// Returns the inequality type of the row with identifier \p key.
351  	   typename LPRowBase<R>::Type rowType(const SPxRowId& id) const
352  	   {
353  	      return LPRowSetBase<R>::type(id);
354  	   }
355  	
356  	   /// Gets \p i 'th column.
357  	   void getCol(int i, LPColBase<R>& col) const
358  	   {
359  	      col.setUpper(upper(i));
360  	      col.setLower(lower(i));
361  	      col.setObj(obj(i));
362  	      col.setColVector(colVector(i));
363  	   }
364  	
365  	   /// Gets column with identifier \p id.
366  	   void getCol(const SPxColId& id, LPColBase<R>& col) const
367  	   {
368  	      getCol(number(id), col);
369  	   }
370  	
371  	   /// Gets columns \p start, ..., \p end.
372  	   void getCols(int start, int end, LPColSetBase<R>& set) const
373  	   {
374  	      if(_isScaled)
375  	      {
376  	         LPColBase<R> lpcol;
377  	
378  	         for(int i = start; i <= end; i++)
379  	         {
380  	            getCol(i, lpcol);
381  	            set.add(lpcol);
382  	         }
383  	
384  	      }
385  	      else
386  	      {
387  	         set.clear();
388  	
389  	         for(int i = start; i <= end; i++)
390  	            set.add(obj(i), lower(i), colVector(i), upper(i));
391  	      }
392  	   }
393  	
394  	   /// Returns column vector of column \p i.
395  	   const SVectorBase<R>& colVector(int i) const
396  	   {
397  	      return LPColSetBase<R>::colVector(i);
398  	   }
399  	
400  	   /// Returns column vector of column with identifier \p id.
401  	   const SVectorBase<R>& colVector(const SPxColId& id) const
402  	   {
403  	      return LPColSetBase<R>::colVector(id);
404  	   }
405  	
406  	   /// Gets column vector of column \p i.
407  	   void getColVectorUnscaled(int i, DSVectorBase<R>& vec) const;
408  	
409  	   /// Gets column vector of column with identifier \p id.
410  	   void getColVectorUnscaled(const SPxColId& id, DSVectorBase<R>& vec) const;
411  	
412  	   /// Gets unscaled objective vector.
413  	   void getObjUnscaled(VectorBase<R>& pobj) const;
414  	
415  	   /// Gets objective vector.
416  	   void getObj(VectorBase<R>& pobj) const
417  	   {
418  	      pobj = LPColSetBase<R>::maxObj();
419  	
420  	      if(spxSense() == MINIMIZE)
421  	         pobj *= -1.0;
422  	   }
423  	
424  	   /// Returns objective value of column \p i.
425  	   R obj(int i) const
426  	   {
427  	      R res = maxObj(i);
428  	
429  	      if(spxSense() == MINIMIZE)
430  	         res *= -1;
431  	
432  	      return res;
433  	   }
434  	
435  	   /// Returns objective value of column with identifier \p id.
436  	   R obj(const SPxColId& id) const
437  	   {
438  	      return obj(number(id));
439  	   }
440  	
441  	   /// Returns unscaled objective value of column \p i.
442  	   R objUnscaled(int i) const;
443  	
444  	   /// Returns unscaled objective value of column with identifier \p id.
445  	   R objUnscaled(const SPxColId& id) const;
446  	
447  	   /// Returns objective vector for maximization problem.
448  	   /** Methods #maxObj() return the objective vector or its elements, after transformation to a maximization
449  	    *  problem. Since this is how SPxLPBase internally stores any LP these methods are generally faster. The following
450  	    *  condition holds: #obj() = #spxSense() * maxObj().
451  	    */
452  	   const VectorBase<R>& maxObj() const
453  	   {
454  	      return LPColSetBase<R>::maxObj();
455  	   }
456  	
457  	   /// Returns objective value of column \p i for maximization problem.
458  	   const R& maxObj(int i) const
459  	   {
460  	      return LPColSetBase<R>::maxObj(i);
461  	   }
462  	
463  	   /// Returns objective value of column with identifier \p id for maximization problem.
464  	   const R& maxObj(const SPxColId& id) const
465  	   {
466  	      return maxObj(number(id));
467  	   }
468  	
469  	   /// Returns unscaled objective vector for maximization problem.
470  	   void maxObjUnscaled(VectorBase<R>& vec) const;
471  	
472  	   /// Returns unscaled objective value of column \p i for maximization problem.
473  	   R maxObjUnscaled(int i) const;
474  	
475  	   /// Returns unscaled objective value of column with identifier \p id for maximization problem.
476  	   R maxObjUnscaled(const SPxColId& id) const;
477  	
478  	   /// Returns upper bound vector.
479  	   const VectorBase<R>& upper() const
480  	   {
481  	      return LPColSetBase<R>::upper();
482  	   }
483  	
484  	   /// Returns upper bound of column \p i.
485  	   const R& upper(int i) const
486  	   {
487  	      return LPColSetBase<R>::upper(i);
488  	   }
489  	
490  	   /// Returns upper bound of column with identifier \p id.
491  	   const R& upper(const SPxColId& id) const
492  	   {
493  	      return LPColSetBase<R>::upper(id);
494  	   }
495  	
496  	   /// Gets unscaled upper bound vector
497  	   void getUpperUnscaled(VectorBase<R>& vec) const;
498  	
499  	   /// Returns unscaled upper bound of column \p i.
500  	   R upperUnscaled(int i) const;
501  	
502  	   /// Returns unscaled upper bound of column with identifier \p id.
503  	   R upperUnscaled(const SPxColId& id) const;
504  	
505  	   /// Returns (internal and possibly scaled) lower bound vector.
506  	   const VectorBase<R>& lower() const
507  	   {
508  	      return LPColSetBase<R>::lower();
509  	   }
510  	
511  	   /// Returns (internal and possibly scaled) lower bound of column \p i.
512  	   const R& lower(int i) const
513  	   {
514  	      return LPColSetBase<R>::lower(i);
515  	   }
516  	
517  	   /// Returns (internal and possibly scaled) lower bound of column with identifier \p id.
518  	   const R& lower(const SPxColId& id) const
519  	   {
520  	      return LPColSetBase<R>::lower(id);
521  	   }
522  	
523  	   /// Gets unscaled lower bound vector.
524  	   void getLowerUnscaled(VectorBase<R>& vec) const;
525  	
526  	   /// Returns unscaled lower bound of column \p i.
527  	   R lowerUnscaled(int i) const;
528  	
529  	   /// Returns unscaled lower bound of column with identifier \p id.
530  	   R lowerUnscaled(const SPxColId& id) const;
531  	
532  	   /// Returns the optimization sense.
533  	   SPxSense spxSense() const
534  	   {
535  	      return thesense;
536  	   }
537  	
538  	   /// Returns the objective function value offset
539  	   const R& objOffset() const
540  	   {
541  	      return offset;
542  	   }
543  	
544  	   /// Returns the row number of the row with identifier \p id.
545  	   int number(const SPxRowId& id) const
546  	   {
547  	      return LPRowSetBase<R>::number(id);
548  	   }
549  	
550  	   /// Returns the column number of the column with identifier \p id.
551  	   int number(const SPxColId& id) const
552  	   {
553  	      return LPColSetBase<R>::number(id);
554  	   }
555  	
556  	   /// Returns the row or column number for identifier \p id.
557  	   int number(const SPxId& id) const
558  	   {
559  	      return (id.type() == SPxId::COL_ID)
560  	             ? LPColSetBase<R>::number(id)
561  	             : LPRowSetBase<R>::number(id);
562  	   }
563  	
564  	   /// Returns the row number of the row with identifier \p id.
565  	   bool has(const SPxRowId& id) const
566  	   {
567  	      return LPRowSetBase<R>::has(id);
568  	   }
569  	
570  	   /// Returns the column number of the column with identifier \p id.
571  	   bool has(const SPxColId& id) const
572  	   {
573  	      return LPColSetBase<R>::has(id);
574  	   }
575  	
576  	   /// Returns the row or column number for identifier \p id.
577  	   bool has(const SPxId& id) const
578  	   {
579  	      return (id.type() == SPxId::COL_ID)
580  	             ? LPColSetBase<R>::has(id)
581  	             : LPRowSetBase<R>::has(id);
582  	   }
583  	
584  	   /// Returns the row identifier for row \p n.
585  	   SPxRowId rId(int n) const
586  	   {
587  	      return SPxRowId(LPRowSetBase<R>::key(n));
588  	   }
589  	
590  	   /// Returns the column identifier for column \p n.
591  	   SPxColId cId(int n) const
592  	   {
593  	      return SPxColId(LPColSetBase<R>::key(n));
594  	   }
595  	
596  	   ///@}
597  	
598  	   // ------------------------------------------------------------------------------------------------------------------
599  	   /**@name Extension */
600  	   ///@{
601  	
602  	   ///
603  	   virtual void addRow(const LPRowBase<R>& row, bool scale = false)
604  	   {
605  	      doAddRow(row, scale);
606  	   }
607  	
608  	   ///
609  	   virtual void addRow(const R& lhsValue, const SVectorBase<R>& rowVec, const R& rhsValue,
610  	                       bool scale = false)
611  	   {
612  	      doAddRow(lhsValue, rowVec, rhsValue, scale);
613  	   }
614  	
615  	   ///
616  	   template < class S >
617  	   void addRow(const S* lhsValue, const S* rowValues, const int* rowIndices, int rowSize,
618  	               const S* rhsValue)
619  	   {
620  	      assert(lhsValue != 0);
621  	      assert(rowSize <= 0 || rowValues != 0);
622  	      assert(rowSize <= 0 || rowIndices != 0);
623  	      assert(rhsValue != 0);
624  	
625  	      int idx = nRows();
626  	      int oldColNumber = nCols();
627  	
628  	      LPRowSetBase<R>::add(lhsValue, rowValues, rowIndices, rowSize, rhsValue);
629  	
630  	      // now insert nonzeros to column file also
631  	      for(int j = rowSize - 1; j >= 0; --j)
632  	      {
633  	         const S& val = rowValues[j];
634  	         int i = rowIndices[j];
635  	
636  	         // create new columns if required
637  	         if(i >= nCols())
638  	         {
639  	            LPColBase<R> empty;
640  	
641  	            for(int k = nCols(); k <= i; ++k)
642  	               LPColSetBase<R>::add(empty);
643  	         }
644  	
645  	         assert(i < nCols());
646  	         LPColSetBase<R>::add2(i, 1, &idx, &val);
647  	      }
648  	
649  	      addedRows(1);
650  	      addedCols(nCols() - oldColNumber);
651  	   }
652  	
653  	   /// Adds \p row to LPRowSetBase.
654  	   virtual void addRow(SPxRowId& id, const LPRowBase<R>& row, bool scale = false)
655  	   {
656  	      addRow(row, scale);
657  	      id = rId(nRows() - 1);
658  	   }
659  	
660  	   ///
661  	   virtual void addRows(const LPRowSetBase<R>& pset, bool scale = false)
662  	   {
663  	      doAddRows(pset, scale);
664  	   }
665  	
666  	   ///
667  	   template < class S >
668  	   void addRows(const S* lhsValues, const S* rowValues, const int* rowIndices, const int* rowStarts,
669  	                const int* rowLengths, const int numRows, const int numValues, const S* rhsValues)
670  	   {
671  	      assert(lhsValues != 0);
672  	      assert(numValues <= 0 || rowValues != 0);
673  	      assert(numValues <= 0 || rowIndices != 0);
674  	      assert(numValues <= 0 || rowStarts != 0);
675  	      assert(numValues <= 0 || rowLengths != 0);
676  	      assert(rhsValues != 0);
677  	
678  	      int i, j, k, idx;
679  	      SVectorBase<R>* col;
680  	      DataArray < int > newCols(nCols());
681  	      int oldRowNumber = nRows();
682  	      int oldColNumber = nCols();
683  	
684  	      LPRowSetBase<R>::memRemax(oldRowNumber + numRows);
685  	
686  	      for(i = 0; i < numRows; i++)
687  	      {
688  	         assert(numValues <= 0 || rowStarts[i] + rowLengths[i] <= numValues);
689  	
690  	         if(numValues <= 0)
691  	            LPRowSetBase<R>::add(&(lhsValues[i]), (S*)0, (int*)0, 0, &(rhsValues[i]));
692  	         else
693  	            LPRowSetBase<R>::add(&(lhsValues[i]), &(rowValues[rowStarts[i]]), &(rowIndices[rowStarts[i]]),
694  	                                 rowLengths[i], &(rhsValues[i]));
695  	      }
696  	
697  	      assert(LPRowSetBase<R>::isConsistent());
698  	      assert(LPColSetBase<R>::isConsistent());
699  	
700  	      // count additional nonzeros per column
701  	      for(i = nCols() - 1; i >= 0; --i)
702  	         newCols[i] = 0;
703  	
704  	      if(numValues > 0)
705  	      {
706  	         for(i = 0; i < numRows; i++)
707  	         {
708  	            for(j = rowStarts[i]; j < rowStarts[i] + rowLengths[i]; j++)
709  	            {
710  	               ///@todo implement the addition of new columns as in doAddRows()
711  	               assert(rowIndices[j] >= 0);
712  	               assert(rowIndices[j] < oldColNumber);
713  	               newCols[rowIndices[j]]++;
714  	            }
715  	         }
716  	      }
717  	
718  	      // extend columns as required (backward because of memory efficiency reasons)
719  	      for(i = nCols() - 1; i >= 0; --i)
720  	      {
721  	         if(newCols[i] > 0)
722  	         {
723  	            int len = newCols[i] + colVector(i).size();
724  	            LPColSetBase<R>::xtend(i, len);
725  	
726  	            /* preset the sizes: beware that this can irritate a consistency check call from xtend(). We need to set the
727  	             * sizes here, because a possible garbage collection called from xtend might destroy the sizes again. */
728  	            colVector_w(i).set_size(len);
729  	         }
730  	      }
731  	
732  	      // insert new elements to column file
733  	      for(i = nRows() - 1; i >= oldRowNumber; --i)
734  	      {
735  	         const SVectorBase<R>& vec = rowVector(i);
736  	
737  	         for(j = vec.size() - 1; j >= 0; --j)
738  	         {
739  	            k = vec.index(j);
740  	            col = &colVector_w(k);
741  	            idx = col->size() - newCols[k];
742  	            assert(newCols[k] > 0);
743  	            assert(idx >= 0);
744  	            newCols[k]--;
745  	            col->index(idx) = i;
746  	            col->value(idx) = vec.value(j);
747  	         }
748  	      }
749  	
750  	#ifndef NDEBUG
751  	
752  	      for(i = 0; i < nCols(); ++i)
753  	         assert(newCols[i] == 0);
754  	
755  	#endif
756  	
757  	      assert(SPxLPBase<R>::isConsistent());
758  	
759  	      assert(numRows == nRows() - oldRowNumber);
760  	      addedRows(nRows() - oldRowNumber);
761  	      addedCols(nCols() - oldColNumber);
762  	   }
763  	
764  	   /// adds all LPRowBase%s of \p pset to LPRowSetBase.
765  	   virtual void addRows(SPxRowId id[], const LPRowSetBase<R>& set, bool scale = false)
766  	   {
767  	      int i = nRows();
768  	      addRows(set, scale);
769  	
770  	      for(int j = 0; i < nRows(); ++i, ++j)
771  	         id[j] = rId(i);
772  	   }
773  	
774  	   ///
775  	   virtual void addCol(const LPColBase<R>& col, bool scale = false)
776  	   {
777  	      doAddCol(col, scale);
778  	   }
779  	
780  	   ///
781  	   virtual void addCol(const R& objValue, const R& lowerValue, const SVectorBase<R>& colVec,
782  	                       const R& upperValue, bool scale = false)
783  	   {
784  	      doAddCol(objValue, lowerValue, colVec, upperValue, scale);
785  	   }
786  	
787  	   ///
788  	   template < class S >
789  	   void addCol(const S* objValue, const S* lowerValue, const S* colValues, const int* colIndices,
790  	               int colSize, const S* upperValue)
791  	   {
792  	      int idx = nCols();
793  	      int oldRowNumber = nRows();
794  	
795  	      LPColSetBase<R>::add(objValue, lowerValue, colValues, colIndices, colSize, upperValue);
796  	
797  	      if(thesense != MAXIMIZE)
798  	         LPColSetBase<R>::maxObj_w(idx) *= -1;
799  	
800  	      // now insert nonzeros to column file also
801  	      for(int j = colSize - 1; j >= 0; --j)
802  	      {
803  	         const S& val = colValues[j];
804  	         int i = colIndices[j];
805  	
806  	         // create new rows if required
807  	         if(i >= nRows())
808  	         {
809  	            LPRowBase<R> empty;
810  	
811  	            for(int k = nRows(); k <= i; ++k)
812  	               LPRowSetBase<R>::add(empty);
813  	         }
814  	
815  	         assert(i < nRows());
816  	         LPRowSetBase<R>::add2(i, 1, &idx, &val);
817  	      }
818  	
819  	      addedCols(1);
820  	      addedRows(nRows() - oldRowNumber);
821  	   }
822  	
823  	   /// Adds \p col to LPColSetVBase.
824  	   virtual void addCol(SPxColId& id, const LPColBase<R>& col, bool scale = false)
825  	   {
826  	      addCol(col, scale);
827  	      id = cId(nCols() - 1);
828  	   }
829  	
830  	   ///
831  	   virtual void addCols(const LPColSetBase<R>& pset, bool scale = false)
832  	   {
833  	      doAddCols(pset, scale);
834  	   }
835  	
836  	   ///
837  	   template < class S >
838  	   void addCols(const S* objValue, const S* lowerValues, const S* colValues, const int* colIndices,
839  	                const int* colStarts, const int* colLengths, const int numCols, const int numValues,
840  	                const S* upperValues)
841  	   {
842  	      assert(lowerValues != 0);
843  	      assert(numValues <= 0 || colValues != 0);
844  	      assert(numValues <= 0 || colIndices != 0);
845  	      assert(numValues <= 0 || colStarts != 0);
846  	      assert(numValues <= 0 || colLengths != 0);
847  	      assert(upperValues != 0);
848  	
849  	      int i, j, k, idx;
850  	      SVectorBase<R>* row;
851  	      DataArray < int > newRows(nRows());
852  	      int oldColNumber = nCols();
853  	      int oldRowNumber = nRows();
854  	      idx = nCols();
855  	
856  	      LPColSetBase<R>::memRemax(oldColNumber + numCols);
857  	
858  	      for(i = 0; i < numCols; i++)
859  	      {
860  	         assert(numValues <= 0 || colStarts[i] + colLengths[i] <= numValues);
861  	
862  	         if(numValues <= 0)
863  	            LPColSetBase<R>::add(&(objValue[i]), &(lowerValues[i]), (S*)0, (int*)0, 0, &(upperValues[i]));
864  	         else
865  	            LPColSetBase<R>::add(&(objValue[i]), &(lowerValues[i]), &(colValues[colStarts[i]]),
866  	                                 &(colIndices[colStarts[i]]), colLengths[i], &(upperValues[i]));
867  	
868  	         if(thesense != MAXIMIZE)
869  	            LPColSetBase<R>::maxObj_w(idx + i) *= -1;
870  	      }
871  	
872  	      assert(LPColSetBase<R>::isConsistent());
873  	      assert(LPRowSetBase<R>::isConsistent());
874  	
875  	      // count additional nonzeros per rows
876  	      for(i = nRows() - 1; i >= 0; --i)
877  	         newRows[i] = 0;
878  	
879  	      for(i = numValues - 1; i >= 0; --i)
880  	      {
881  	         ///@todo implement the addition of new rows as in doAddCols()
882  	         assert(colIndices[i] >= 0);
883  	         assert(colIndices[i] < oldRowNumber);
884  	         newRows[colIndices[i]]++;
885  	      }
886  	
887  	      // extend rows as required (backward because of memory efficiency reasons)
888  	      for(i = nRows() - 1; i >= 0; --i)
889  	      {
890  	         if(newRows[i] > 0)
891  	         {
892  	            int len = newRows[i] + rowVector(i).size();
893  	            LPRowSetBase<R>::xtend(i, len);
894  	
895  	            /* preset the sizes: beware that this can irritate a consistency check call from xtend(). We need to set the
896  	             * sizes here, because a possible garbage collection called from xtend might destroy the sizes again. */
897  	            rowVector_w(i).set_size(len);
898  	         }
899  	      }
900  	
901  	      // insert new elements to row file
902  	      for(i = nCols() - 1; i >= oldColNumber; --i)
903  	      {
904  	         const SVectorBase<R>& vec = colVector(i);
905  	
906  	         for(j = vec.size() - 1; j >= 0; --j)
907  	         {
908  	            k = vec.index(j);
909  	            row = &rowVector_w(k);
910  	            idx = row->size() - newRows[k];
911  	            assert(newRows[k] > 0);
912  	            assert(idx >= 0);
913  	            newRows[k]--;
914  	            row->index(idx) = i;
915  	            row->value(idx) = vec.value(j);
916  	         }
917  	      }
918  	
919  	#ifndef NDEBUG
920  	
921  	      for(i = 0; i < nRows(); ++i)
922  	         assert(newRows[i] == 0);
923  	
924  	#endif
925  	
926  	      assert(SPxLPBase<R>::isConsistent());
927  	
928  	      assert(numCols == nCols() - oldColNumber);
929  	      addedCols(nCols() - oldColNumber);
930  	      addedRows(nRows() - oldRowNumber);
931  	   }
932  	
933  	   /// Adds all LPColBase%s of \p set to LPColSetBase.
934  	   virtual void addCols(SPxColId id[], const LPColSetBase<R>& set, bool scale = false)
935  	   {
936  	
937  	      int i = nCols();
938  	      addCols(set, scale);
939  	
940  	      for(int j = 0; i < nCols(); ++i, ++j)
941  	         id[j] = cId(i);
942  	   }
943  	
944  	   ///@}
945  	
946  	   // ------------------------------------------------------------------------------------------------------------------
947  	   /**@name Shrinking */
948  	   ///@{
949  	
950  	   /// Removes \p i 'th row.
951  	   virtual void removeRow(int i)
952  	   {
953  	      if(i < 0)
954  	         return;
955  	
956  	      doRemoveRow(i);
957  	   }
958  	
959  	   /// Removes row with identifier \p id.
960  	   virtual void removeRow(SPxRowId id)
961  	   {
962  	      removeRow(number(id));
963  	   }
964  	
965  	   /// Removes multiple rows.
966  	   /** This method removes all LPRowBase%s from the SPxLPBase with an index \p i such that \p perm[i] < 0. Upon
967  	    *  completion, \p perm[i] >= 0 indicates the new index where the \p i'th LPRowBase<R> has been moved to due to this
968  	    *  removal. Note that \p perm must point to an array of at least #nRows() ints.
969  	    */
970  	   virtual void removeRows(int perm[])
971  	   {
972  	      doRemoveRows(perm);
973  	   }
974  	
975  	   ///
976  	   virtual void removeRows(SPxRowId id[], int n, int perm[] = 0)
977  	   {
978  	
979  	      if(perm == 0)
980  	      {
981  	         DataArray < int > p(nRows());
982  	         removeRows(id, n, p.get_ptr());
983  	         return;
984  	      }
985  	
986  	      for(int i = nRows() - 1; i >= 0; --i)
987  	         perm[i] = i;
988  	
989  	      while(n--)
990  	         perm[number(id[n])] = -1;
991  	
992  	      removeRows(perm);
993  	   }
994  	
995  	   /// Removes \p n LPRowBase%s.
996  	   /** Removing multiple rows with one method invocation is available in two flavours. An array \p perm can be passed as
997  	    *  third argument or not. If given, \p perm must be an array at least of size #nRows(). It is used to return the
998  	    *  permutations resulting from this removal: \p perm[i] < 0 indicates, that the element to index \p i has been
999  	    *  removed.  Otherwise, \p perm[i] is the new index of the element with index \p i before the removal.
1000 	    */
1001 	   virtual void removeRows(int nums[], int n, int perm[] = 0)
1002 	   {
1003 	
1004 	      if(perm == 0)
1005 	      {
1006 	         DataArray < int > p(nRows());
1007 	         removeRows(nums, n, p.get_ptr());
1008 	         return;
1009 	      }
1010 	
1011 	      for(int i = nRows() - 1; i >= 0; --i)
1012 	         perm[i] = i;
1013 	
1014 	      while(n--)
1015 	         perm[nums[n]] = -1;
1016 	
1017 	      removeRows(perm);
1018 	   }
1019 	
1020 	   /// Removes rows from \p start to \p end (including both).
1021 	   virtual void removeRowRange(int start, int end, int perm[] = 0)
1022 	   {
1023 	
1024 	      if(perm == 0)
1025 	      {
1026 	         int i = end - start + 1;
1027 	         DataArray < int > p(i);
1028 	
1029 	         while(--i >= 0)
1030 	            p[i] = start + i;
1031 	
1032 	         removeRows(p.get_ptr(), end - start + 1);
1033 	         return;
1034 	      }
1035 	
1036 	      int i;
1037 	
1038 	      for(i = 0; i < start; ++i)
1039 	         perm[i] = i;
1040 	
1041 	      for(; i <= end; ++i)
1042 	         perm[i] = -1;
1043 	
1044 	      for(; i < nRows(); ++i)
1045 	         perm[i] = i;
1046 	
1047 	      removeRows(perm);
1048 	   }
1049 	
1050 	   /// Removes \p i 'th column.
1051 	   virtual void removeCol(int i)
1052 	   {
1053 	      if(i < 0)
1054 	         return;
1055 	
1056 	      doRemoveCol(i);
1057 	   }
1058 	
1059 	   /// Removes column with identifier \p id.
1060 	   virtual void removeCol(SPxColId id)
1061 	   {
1062 	      removeCol(number(id));
1063 	   }
1064 	
1065 	   /// Removes multiple columns.
1066 	   /** This method removes all LPColBase%s from the SPxLPBase with an index \p i such that \p perm[i] < 0. Upon
1067 	    *  completion, \p perm[i] >= 0 indicates the new index where the \p i 'th LPColBase has been moved to due to this
1068 	    *  removal. Note, that \p perm must point to an array of at least #nCols() ints.
1069 	    */
1070 	   virtual void removeCols(int perm[])
1071 	   {
1072 	      doRemoveCols(perm);
1073 	   }
1074 	
1075 	   ///
1076 	   virtual void removeCols(SPxColId id[], int n, int perm[] = 0)
1077 	   {
1078 	
1079 	      if(perm == 0)
1080 	      {
1081 	         DataArray < int > p(nCols());
1082 	         removeCols(id, n, p.get_ptr());
1083 	         return;
1084 	      }
1085 	
1086 	      for(int i = nCols() - 1; i >= 0; --i)
1087 	         perm[i] = i;
1088 	
1089 	      while(n--)
1090 	         perm[number(id[n])] = -1;
1091 	
1092 	      removeCols(perm);
1093 	   }
1094 	
1095 	   /// Removes \p n LPCols.
1096 	   /** Removing multiple columns with one method invocation is available in two flavours. An array \p perm can be passed
1097 	    *  as third argument or not. If given, \p perm must be an array at least of size #nCols(). It is used to return the
1098 	    *  permutations resulting from this removal: \p perm[i] < 0 indicates, that the element to index \p i has been
1099 	    *  removed.  Otherwise, \p perm[i] is the new index of the element with index \p i before the removal.
1100 	    */
1101 	   virtual void removeCols(int nums[], int n, int perm[] = 0)
1102 	   {
1103 	
1104 	      if(perm == 0)
1105 	      {
1106 	         DataArray < int > p(nCols());
1107 	         removeCols(nums, n, p.get_ptr());
1108 	         return;
1109 	      }
1110 	
1111 	      for(int i = nCols() - 1; i >= 0; --i)
1112 	         perm[i] = i;
1113 	
1114 	      while(n--)
1115 	         perm[nums[n]] = -1;
1116 	
1117 	      removeCols(perm);
1118 	   }
1119 	
1120 	   /// Removes columns from \p start to \p end (including both).
1121 	   virtual void removeColRange(int start, int end, int perm[] = 0)
1122 	   {
1123 	
1124 	      if(perm == 0)
1125 	      {
1126 	         int i = end - start + 1;
1127 	         DataArray < int > p(i);
1128 	
1129 	         while(--i >= 0)
1130 	            p[i] = start + i;
1131 	
1132 	         removeCols(p.get_ptr(), end - start + 1);
1133 	         return;
1134 	      }
1135 	
1136 	      int i;
1137 	
1138 	      for(i = 0; i < start; ++i)
1139 	         perm[i] = i;
1140 	
1141 	      for(; i <= end; ++i)
1142 	         perm[i] = -1;
1143 	
1144 	      for(; i < nCols(); ++i)
1145 	         perm[i] = i;
1146 	
1147 	      removeCols(perm);
1148 	   }
1149 	
1150 	   /// clears the LP.
1151 	   virtual void clear()
1152 	   {
1153 	
1154 	      LPRowSetBase<R>::clear();
1155 	      LPColSetBase<R>::clear();
1156 	      thesense = MAXIMIZE;
1157 	      offset = 0;
1158 	      _isScaled = false;
1159 	      lp_scaler = nullptr;
1160 	      LPColSetBase<R>::scaleExp.clear();
1161 	      LPRowSetBase<R>::scaleExp.clear();
1162 	   }
1163 	
1164 	   ///@}
1165 	
1166 	   // ------------------------------------------------------------------------------------------------------------------
1167 	   /**@name IO */
1168 	   ///@{
1169 	
1170 	   /// Reads LP in LP format from input stream \p in.
1171 	   virtual bool readLPF(std::istream& in, NameSet* rowNames = 0, NameSet* colNames = 0,
1172 	                        DIdxSet* intVars = 0);
1173 	
1174 	   /// Reads an LP in MPS format from input stream \p in.
1175 	   virtual bool readMPS(std::istream& in, NameSet* rowNames = 0, NameSet* colNames = 0,
1176 	                        DIdxSet* intVars = 0);
1177 	
1178 	   /// Reads LP in LP or MPS format from input stream \p in.
1179 	   /**@param in       input stream.
1180 	    * @param rowNames contains after the call the names of the constraints (rows) in the same order as the rows in the
1181 	    *                 LP.  Constraints without a name (only possible with LPF files) are automatically assigned a name.
1182 	    *                 Maybe 0 if the names are not needed.
1183 	    * @param colNames contains after the call the names of the variables (columns) in the same order as the columns in
1184 	    *                 the LP.  Maybe 0 if the names are not needed.
1185 	    * @param intVars contains after the call the indices of those variables that where marked as beeing integer in the
1186 	    *                 file.  Maybe 0 if the information is not needed.
1187 	    * @todo Make sure the Id's in the NameSet%s are the same as in the LP.
1188 	    */
1189 	   virtual bool read(std::istream& in, NameSet* rowNames = 0, NameSet* colNames = 0,
1190 	                     DIdxSet* intVars  = 0)
1191 	   {
1192 	      bool ok;
1193 	      char c;
1194 	
1195 	      in.get(c);
1196 	      in.putback(c);
1197 	
1198 	      /* MPS starts either with a comment mark '*' or with the keyword 'NAME' at the first column.  LPF starts either
1199 	       * with blanks, a comment mark '\' or with the keyword "MAX" or "MIN" in upper or lower case.  There is no
1200 	       * possible valid LPF file starting with a '*' or 'N'.
1201 	       */
1202 	      ok = ((c == '*') || (c == 'N'))
1203 	           ? readMPS(in, rowNames, colNames, intVars)
1204 	           : readLPF(in, rowNames, colNames, intVars);
1205 	
1206 	      return ok;
1207 	   }
1208 	
1209 	   /// Reads LP from a file.
1210 	   virtual bool readFile(const char* filename, NameSet* rowNames = 0, NameSet* colNames = 0,
1211 	                         DIdxSet* intVars = 0)
1212 	   {
1213 	
1214 	      spxifstream file(filename);
1215 	
1216 	      if(!file)
1217 	         return false;
1218 	
1219 	      return read(file, rowNames, colNames, intVars);
1220 	   }
1221 	
1222 	   /** Writes a file in LP format to \p out. If \p rowNames and \p colNames are \c NULL, default names are used for the
1223 	    *  constraints and variables. If \p intVars is not \c NULL, the variables contained in it are marked as integer in
1224 	    *  the output.
1225 	    */
1226 	   virtual void writeLPF(std::ostream&  out, const NameSet* rowNames, const NameSet* colNames,
1227 	                         const DIdxSet* p_intvars = 0) const;
1228 	
1229 	   /// Writes a file in MPS format to \p out.
1230 	   virtual void writeMPS(std::ostream&  out, const NameSet* rowNames, const NameSet* colNames,
1231 	                         const DIdxSet* p_intvars = 0) const;
1232 	
1233 	   /// Write loaded LP to \p filename.
1234 	   virtual void writeFileLPBase(const char* filename, const NameSet* rowNames = 0,
1235 	                                const NameSet* colNames = 0, const DIdxSet* p_intvars = 0) const
1236 	   {
1237 	
1238 	      std::ofstream tmp(filename);
1239 	      size_t len_f = strlen(filename);
1240 	
1241 	      if(len_f > 4 && filename[len_f - 1] == 's' && filename[len_f - 2] == 'p'
1242 	            && filename[len_f - 3] == 'm' && filename[len_f - 4] == '.')
1243 	      {
1244 	         writeMPS(tmp, rowNames, colNames, p_intvars);
1245 	      }
1246 	      else
1247 	      {
1248 	         writeLPF(tmp, rowNames, colNames, p_intvars);
1249 	      }
1250 	   }
1251 	
1252 	   /** prints problem statistics */
1253 	   void printProblemStatistics(std::ostream& os)
1254 	   {
1255 	      int countLower = 0;
1256 	      int countUpper = 0;
1257 	      int countBoxed = 0;
1258 	      int countFreeCol = 0;
1259 	
1260 	      int countEqual = 0;
1261 	      int countLhs = 0;
1262 	      int countRhs = 0;
1263 	      int countRanged = 0;
1264 	      int countFreeRow = 0;
1265 	
1266 	      for(int i = 0; i < nCols(); i++)
1267 	      {
1268 	         bool hasLower = false;
1269 	         bool hasUpper = false;
1270 	
1271 	         if(lower(i) > R(-infinity))
1272 	         {
1273 	            countLower++;
1274 	            hasLower = true;
1275 	         }
1276 	
1277 	         if(upper(i) < R(infinity))
1278 	         {
1279 	            countUpper++;
1280 	            hasUpper = true;
1281 	         }
1282 	
1283 	         if(hasUpper && hasLower)
1284 	         {
1285 	            countBoxed++;
1286 	            countLower--;
1287 	            countUpper--;
1288 	         }
1289 	
1290 	         if(!hasUpper && !hasLower)
1291 	            countFreeCol++;
1292 	      }
1293 	
1294 	      for(int i = 0; i < nRows(); i++)
1295 	      {
1296 	         bool hasRhs = false;
1297 	         bool hasLhs = false;
1298 	
1299 	         if(lhs(i) > R(-infinity))
1300 	         {
1301 	            countLhs++;
1302 	            hasLhs = true;
1303 	         }
1304 	
1305 	         if(rhs(i) < R(infinity))
1306 	         {
1307 	            countRhs++;
1308 	            hasRhs = true;
1309 	         }
1310 	
1311 	         if(hasRhs && hasLhs)
1312 	         {
1313 	            if(EQ(lhs(i), rhs(i)))
1314 	               countEqual++;
1315 	            else
1316 	               countRanged++;
1317 	
1318 	            countLhs--;
1319 	            countRhs--;
1320 	         }
1321 	
1322 	         if(!hasRhs && !hasLhs)
1323 	            countFreeRow++;
1324 	      }
1325 	
1326 	      SPxOut::setFixed(os);
1327 	      os << "  Columns           : " << nCols() << "\n"
1328 	         << "              boxed : " << countBoxed << "\n"
1329 	         << "        lower bound : " << countLower << "\n"
1330 	         << "        upper bound : " << countUpper << "\n"
1331 	         << "               free : " << countFreeCol << "\n"
1332 	         << "  Rows              : " << nRows() << "\n"
1333 	         << "              equal : " << countEqual << "\n"
1334 	         << "             ranged : " << countRanged << "\n"
1335 	         << "                lhs : " << countLhs << "\n"
1336 	         << "                rhs : " << countRhs << "\n"
1337 	         << "               free : " << countFreeRow << "\n"
1338 	         << "  Nonzeros          : " << nNzos() << "\n"
1339 	         << "         per column : " << R(nNzos()) / R(nCols()) << "\n"
1340 	         << "            per row : " << R(nNzos()) / R(nRows()) << "\n"
1341 	         << "           sparsity : " << R(nNzos()) / R(nCols()) / R(nRows()) << "\n"
1342 	         << "    min. abs. value : " << R(minAbsNzo()) << "\n"
1343 	         << "    max. abs. value : " << R(maxAbsNzo()) << "\n";
1344 	   }
1345 	
1346 	   ///@}
1347 	
1348 	   // ------------------------------------------------------------------------------------------------------------------
1349 	   /**@name Manipulation */
1350 	   ///@{
1351 	
1352 	   /// Changes objective vector to \p newObj. \p scale determines whether the new data should be scaled
1353 	   virtual void changeObj(const VectorBase<R>& newObj, bool scale = false)
1354 	   {
1355 	      changeMaxObj(newObj, scale);
1356 	
1357 	      if(spxSense() == MINIMIZE)
1358 	         LPColSetBase<R>::maxObj_w() *= -1;
1359 	   }
1360 	
1361 	   /// changes \p i 'th objective vector element to \p newVal. \p scale determines whether the new data should be scaled
1362 	   virtual void changeObj(int i, const R& newVal, bool scale = false)
1363 	   {
1364 	      changeMaxObj(i, newVal, scale);
1365 	
1366 	      if(spxSense() == MINIMIZE)
1367 	         LPColSetBase<R>::maxObj_w(i) *= -1;
1368 	   }
1369 	
1370 	   /// changes \p i 'th objective vector element to \p newVal.
1371 	   template < class S >
1372 	   void changeObj(int i, const S* newVal)
1373 	   {
1374 	      LPColSetBase<R>::maxObj_w(i) = *newVal;
1375 	
1376 	      if(spxSense() == MINIMIZE)
1377 	         LPColSetBase<R>::maxObj_w(i) *= -1;
1378 	
1379 	      assert(isConsistent());
1380 	   }
1381 	
1382 	   /// Changes objective value of column with identifier \p id to \p newVal. \p scale determines whether the new data should be scaled
1383 	   virtual void changeObj(SPxColId id, const R& newVal, bool scale = false)
1384 	   {
1385 	      this->changeObj(number(id), newVal, scale);
1386 	   }
1387 	
1388 	   /// Changes objective vector to \p newObj. \p scale determines whether the new data should be scaled
1389 	   virtual void changeMaxObj(const VectorBase<R>& newObj, bool scale = false)
1390 	   {
1391 	      assert(maxObj().dim() == newObj.dim());
1392 	
1393 	      if(scale)
1394 	      {
1395 	         assert(_isScaled);
1396 	         assert(lp_scaler);
1397 	
1398 	         for(int i = 0; i < maxObj().dim(); i++)
(6) Event copy_assignment: Example 5: Copy assignment is performed on an object (rvalue) of type "Rational".
Also see events: [missing_move_assignment][copy_assignment][copy_assignment][copy_assignment][copy_assignment]
1399 	            LPColSetBase<R>::maxObj_w(i) = lp_scaler->scaleObj(*this, i, newObj[i]);
1400 	      }
1401 	      else
1402 	         LPColSetBase<R>::maxObj_w() = newObj;
1403 	
1404 	      assert(isConsistent());
1405 	   }
1406 	
1407 	   /// changes \p i 'th objective vector element to \p newVal. \p scale determines whether the new data should be scaled
1408 	   virtual void changeMaxObj(int i, const R& newVal, bool scale = false)
1409 	   {
1410 	      if(scale)
1411 	      {
1412 	         assert(_isScaled);
1413 	         assert(lp_scaler);
1414 	         LPColSetBase<R>::maxObj_w(i) = lp_scaler->scaleObj(*this, i, newVal);
1415 	      }
1416 	      else
1417 	         LPColSetBase<R>::maxObj_w(i) = newVal;
1418 	
1419 	      assert(isConsistent());
1420 	   }
1421 	
1422 	   /// changes \p i 'th objective vector element to \p newVal.
1423 	   template < class S >
1424 	   void changeMaxObj(int i, const S* newVal)
1425 	   {
1426 	      LPColSetBase<R>::maxObj_w(i) = *newVal;
1427 	      assert(isConsistent());
1428 	   }
1429 	
1430 	   /// Changes objective value of column with identifier \p id to \p newVal. \p scale determines whether the new data should be scaled
1431 	   virtual void changeMaxObj(SPxColId id, const R& newVal, bool scale = false)
1432 	   {
1433 	      changeMaxObj(number(id), newVal, scale);
1434 	   }
1435 	
1436 	   /// Changes vector of lower bounds to \p newLower. \p scale determines whether the new data should be scaled
1437 	   virtual void changeLower(const VectorBase<R>& newLower, bool scale = false)
1438 	   {
1439 	      assert(lower().dim() == newLower.dim());
1440 	
1441 	      if(scale)
1442 	      {
1443 	         assert(_isScaled);
1444 	         assert(lp_scaler);
1445 	
1446 	         for(int i = 0; i < lower().dim(); i++)
(3) Event copy_assignment: Example 2: Copy assignment is performed on an object (rvalue) of type "Rational".
Also see events: [missing_move_assignment][copy_assignment][copy_assignment][copy_assignment][copy_assignment]
1447 	            LPColSetBase<R>::lower_w(i) = lp_scaler->scaleLower(*this, i, newLower[i]);
1448 	      }
1449 	      else
1450 	         LPColSetBase<R>::lower_w() = newLower;
1451 	
1452 	      assert(isConsistent());
1453 	   }
1454 	
1455 	   /// changes \p i 'th lower bound to \p newLower. \p scale determines whether the new data should be scaled
1456 	   virtual void changeLower(int i, const R& newLower, bool scale = false)
1457 	   {
1458 	      if(scale && newLower > R(-infinity))
1459 	      {
1460 	         assert(_isScaled);
1461 	         assert(lp_scaler);
1462 	         LPColSetBase<R>::lower_w(i) = lp_scaler->scaleLower(*this, i, newLower);
1463 	      }
1464 	      else
1465 	         LPColSetBase<R>::lower_w(i) = newLower;
1466 	
1467 	      assert(isConsistent());
1468 	   }
1469 	
1470 	   /// changes \p i 'th lower bound to \p newLower.
1471 	   template < class S >
1472 	   void changeLower(int i, const S* newLower)
1473 	   {
1474 	      LPColSetBase<R>::lower_w(i) = *newLower;
1475 	      assert(isConsistent());
1476 	   }
1477 	
1478 	   /// changes lower bound of column with identifier \p id to \p newLower. \p scale determines whether the new data should be scaled
1479 	   virtual void changeLower(SPxColId id, const R& newLower, bool scale = false)
1480 	   {
1481 	      changeLower(number(id), newLower, scale);
1482 	   }
1483 	
1484 	   /// Changes vector of upper bounds to \p newUpper. \p scale determines whether the new data should be scaled
1485 	   virtual void changeUpper(const VectorBase<R>& newUpper, bool scale = false)
1486 	   {
1487 	      assert(upper().dim() == newUpper.dim());
1488 	
1489 	      if(scale)
1490 	      {
1491 	         assert(_isScaled);
1492 	         assert(lp_scaler);
1493 	
1494 	         for(int i = 0; i < upper().dim(); i++)
(4) Event copy_assignment: Example 3: Copy assignment is performed on an object (rvalue) of type "Rational".
Also see events: [missing_move_assignment][copy_assignment][copy_assignment][copy_assignment][copy_assignment]
1495 	            LPColSetBase<R>::upper_w(i) = lp_scaler->scaleUpper(*this, i, newUpper[i]);
1496 	      }
1497 	      else
1498 	         LPColSetBase<R>::upper_w() = newUpper;
1499 	
1500 	      assert(isConsistent());
1501 	   }
1502 	
1503 	   /// Changes \p i 'th upper bound to \p newUpper. \p scale determines whether the new data should be scaled
1504 	   virtual void changeUpper(int i, const R& newUpper, bool scale = false)
1505 	   {
1506 	      if(scale && newUpper < R(infinity))
1507 	      {
1508 	         assert(_isScaled);
1509 	         assert(lp_scaler);
1510 	         LPColSetBase<R>::upper_w(i) = lp_scaler->scaleUpper(*this, i, newUpper);
1511 	      }
1512 	      else
1513 	         LPColSetBase<R>::upper_w(i) = newUpper;
1514 	
1515 	      assert(isConsistent());
1516 	   }
1517 	
1518 	   /// Changes \p i 'th upper bound to \p newUpper.
1519 	   template < class S >
1520 	   void changeUpper(int i, const S* newUpper)
1521 	   {
1522 	      LPColSetBase<R>::upper_w(i) = *newUpper;
1523 	      assert(isConsistent());
1524 	   }
1525 	
1526 	   /// Changes upper bound of column with identifier \p id to \p newLower. \p scale determines whether the new data should be scaled
1527 	   virtual void changeUpper(SPxColId id, const R& newUpper, bool scale = false)
1528 	   {
1529 	      changeUpper(number(id), newUpper, scale);
1530 	   }
1531 	
1532 	   /// Changes variable bounds to \p newLower and \p newUpper. \p scale determines whether the new data should be scaled
1533 	   virtual void changeBounds(const VectorBase<R>& newLower, const VectorBase<R>& newUpper,
1534 	                             bool scale = false)
1535 	   {
1536 	      changeLower(newLower, scale);
1537 	      changeUpper(newUpper, scale);
1538 	      assert(isConsistent());
1539 	   }
1540 	
1541 	   /// Changes bounds of column \p i to \p newLower and \p newUpper. \p scale determines whether the new data should be scaled
1542 	   virtual void changeBounds(int i, const R& newLower, const R& newUpper, bool scale = false)
1543 	   {
1544 	      changeLower(i, newLower, scale);
1545 	      changeUpper(i, newUpper, scale);
1546 	      assert(isConsistent());
1547 	   }
1548 	
1549 	   /// Changes bounds of column \p i to \p newLower and \p newUpper.
1550 	   template < class S >
1551 	   void changeBounds(int i, const S* newLower, const S* newUpper)
1552 	   {
1553 	      LPColSetBase<R>::lower_w(i) = *newLower;
1554 	      LPColSetBase<R>::upper_w(i) = *newUpper;
1555 	      assert(isConsistent());
1556 	   }
1557 	
1558 	   /// Changes bounds of column with identifier \p id. \p scale determines whether the new data should be scaled
1559 	   virtual void changeBounds(SPxColId id, const R& newLower, const R& newUpper, bool scale = false)
1560 	   {
1561 	      changeBounds(number(id), newLower, newUpper, scale);
1562 	   }
1563 	
1564 	   /// Changes left hand side vector for constraints to \p newLhs. \p scale determines whether the new data should be scaled
1565 	   virtual void changeLhs(const VectorBase<R>& newLhs, bool scale = false)
1566 	   {
1567 	      assert(lhs().dim() == newLhs.dim());
1568 	
1569 	      if(scale)
1570 	      {
1571 	         assert(_isScaled);
1572 	         assert(lp_scaler);
1573 	
1574 	         for(int i = 0; i < lhs().dim(); i++)
(5) Event copy_assignment: Example 4: Copy assignment is performed on an object (rvalue) of type "Rational".
Also see events: [missing_move_assignment][copy_assignment][copy_assignment][copy_assignment][copy_assignment]
1575 	            LPRowSetBase<R>::lhs_w(i) = lp_scaler->scaleLhs(*this, i, newLhs[i]);
1576 	      }
1577 	      else
1578 	         LPRowSetBase<R>::lhs_w() = newLhs;
1579 	
1580 	      assert(isConsistent());
1581 	   }
1582 	
1583 	   /// Changes \p i 'th left hand side value to \p newLhs. \p scale determines whether the new data should be scaled
1584 	   virtual void changeLhs(int i, const R& newLhs, bool scale = false)
1585 	   {
1586 	      if(scale && newLhs > R(-infinity))
1587 	      {
1588 	         assert(_isScaled);
1589 	         assert(lp_scaler);
1590 	         LPRowSetBase<R>::lhs_w(i) = lp_scaler->scaleLhs(*this, i, newLhs);
1591 	      }
1592 	      else
1593 	         LPRowSetBase<R>::lhs_w(i) = newLhs;
1594 	
1595 	      assert(isConsistent());
1596 	   }
1597 	
1598 	   /// Changes \p i 'th left hand side value to \p newLhs.
1599 	   template < class S >
1600 	   void changeLhs(int i, const S* newLhs)
1601 	   {
1602 	      LPRowSetBase<R>::lhs_w(i) = *newLhs;
1603 	      assert(isConsistent());
1604 	   }
1605 	
1606 	   /// Changes left hand side value for row with identifier \p id. \p scale determines whether the new data should be scaled
1607 	   virtual void changeLhs(SPxRowId id, const R& newLhs, bool scale = false)
1608 	   {
1609 	      changeLhs(number(id), newLhs, scale);
1610 	   }
1611 	
1612 	   /// Changes right hand side vector for constraints to \p newRhs. \p scale determines whether the new data should be scaled
1613 	   virtual void changeRhs(const VectorBase<R>& newRhs, bool scale = false)
1614 	   {
1615 	      assert(rhs().dim() == newRhs.dim());
1616 	
1617 	      if(scale)
1618 	      {
1619 	         assert(_isScaled);
1620 	         assert(lp_scaler);
1621 	
1622 	         for(int i = 0; i < rhs().dim(); i++)
1623 	            LPRowSetBase<R>::rhs_w(i) = lp_scaler->scaleRhs(*this, i, newRhs[i]);
1624 	      }
1625 	      else
1626 	         LPRowSetBase<R>::rhs_w() = newRhs;
1627 	
1628 	      assert(isConsistent());
1629 	   }
1630 	
1631 	   /// Changes \p i 'th right hand side value to \p newRhs. \p scale determines whether the new data should be scaled
1632 	   virtual void changeRhs(int i, const R& newRhs, bool scale = false)
1633 	   {
1634 	      if(scale && newRhs < R(infinity))
1635 	      {
1636 	         assert(_isScaled);
1637 	         assert(lp_scaler);
1638 	         LPRowSetBase<R>::rhs_w(i) = lp_scaler->scaleRhs(*this, i, newRhs);
1639 	      }
1640 	      else
1641 	         LPRowSetBase<R>::rhs_w(i) = newRhs;
1642 	
1643 	      assert(isConsistent());
1644 	   }
1645 	
1646 	   /// Changes right hand side value for row with identifier \p id. \p scale determines whether the new data should be scaled
1647 	   virtual void changeRhs(SPxRowId id, const R& newRhs, bool scale = false)
1648 	   {
1649 	      changeRhs(number(id), newRhs, scale);
1650 	   }
1651 	
1652 	   /// Changes left and right hand side vectors. \p scale determines whether the new data should be scaled
1653 	   virtual void changeRange(const VectorBase<R>& newLhs, const VectorBase<R>& newRhs,
1654 	                            bool scale = false)
1655 	   {
1656 	      changeLhs(newLhs, scale);
1657 	      changeRhs(newRhs, scale);
1658 	      assert(isConsistent());
1659 	   }
1660 	
1661 	   /// Changes left and right hand side of row \p i. \p scale determines whether the new data should be scaled
1662 	   virtual void changeRange(int i, const R& newLhs, const R& newRhs, bool scale = false)
1663 	   {
1664 	      changeLhs(i, newLhs, scale);
1665 	      changeRhs(i, newRhs, scale);
1666 	      assert(isConsistent());
1667 	   }
1668 	
1669 	   /// Changes left and right hand side of row \p i.
1670 	   template < class S >
1671 	   void changeRange(int i, const S* newLhs, const S* newRhs)
1672 	   {
1673 	      LPRowSetBase<R>::lhs_w(i) = *newLhs;
1674 	      LPRowSetBase<R>::rhs_w(i) = *newRhs;
1675 	      assert(isConsistent());
1676 	   }
1677 	
1678 	   /// Changes left and right hand side of row with identifier \p id. \p scale determines whether the new data should be scaled
1679 	   virtual void changeRange(SPxRowId id, const R& newLhs, const R& newRhs, bool scale = false)
1680 	   {
1681 	      changeRange(number(id), newLhs, newRhs, scale);
1682 	   }
1683 	
1684 	   /// Changes row objective function vector to \p newRowObj. \p scale determines whether the new data should be scaled
1685 	   virtual void changeRowObj(const VectorBase<R>& newRowObj, bool scale = false)
1686 	   {
1687 	      assert(maxRowObj().dim() == newRowObj.dim());
1688 	      LPRowSetBase<R>::obj_w() = newRowObj;
1689 	
1690 	      if(spxSense() == MINIMIZE)
1691 	         LPRowSetBase<R>::obj_w() *= -1;
1692 	
1693 	      assert(isConsistent());
1694 	   }
1695 	
1696 	   /// Changes \p i 'th row objective function value to \p newRowObj. \p scale determines whether the new data should be scaled
1697 	   virtual void changeRowObj(int i, const R& newRowObj, bool scale = false)
1698 	   {
1699 	      LPRowSetBase<R>::obj_w(i) = newRowObj;
1700 	
1701 	      if(spxSense() == MINIMIZE)
1702 	         LPRowSetBase<R>::obj_w(i) *= -1;
1703 	
1704 	      assert(isConsistent());
1705 	   }
1706 	
1707 	   /// Changes row objective function value for row with identifier \p id. \p scale determines whether the new data should be scaled
1708 	   virtual void changeRowObj(SPxRowId id, const R& newRowObj, bool scale = false)
1709 	   {
1710 	      changeRowObj(number(id), newRowObj, scale);
1711 	   }
1712 	
1713 	   /// Clears row objective function values for all rows
1714 	   virtual void clearRowObjs()
1715 	   {
1716 	      LPRowSetBase<R>::obj_w().clear();
1717 	   }
1718 	
1719 	   /// Replaces \p i 'th row of LP with \p newRow. \p scale determines whether the new data should be scaled
1720 	   virtual void changeRow(int n, const LPRowBase<R>& newRow, bool scale = false)
1721 	   {
1722 	      if(n < 0)
1723 	         return;
1724 	
1725 	      int j;
1726 	      SVectorBase<R>& row = rowVector_w(n);
1727 	
1728 	      for(j = row.size() - 1; j >= 0; --j)
1729 	      {
1730 	         SVectorBase<R>& col = colVector_w(row.index(j));
1731 	         int position = col.pos(n);
1732 	
1733 	         assert(position != -1);
1734 	
1735 	         if(position >= 0)
1736 	            col.remove(position);
1737 	      }
1738 	
1739 	      row.clear();
1740 	
1741 	      changeLhs(n, newRow.lhs(), scale);
1742 	      changeRhs(n, newRow.rhs(), scale);
1743 	      changeRowObj(n, newRow.obj(), scale);
1744 	
1745 	      const SVectorBase<R>& newrow = newRow.rowVector();
1746 	
1747 	      for(j = newrow.size() - 1; j >= 0; --j)
1748 	      {
1749 	         int idx = newrow.index(j);
1750 	         R val = newrow.value(j);
1751 	
1752 	         if(scale)
1753 	            val = spxLdexp(val, LPRowSetBase<R>::scaleExp[n] + LPColSetBase<R>::scaleExp[idx]);
1754 	
1755 	         LPRowSetBase<R>::add2(n, 1, &idx, &val);
1756 	         LPColSetBase<R>::add2(idx, 1, &n, &val);
1757 	      }
1758 	
1759 	      assert(isConsistent());
1760 	   }
1761 	
1762 	   /// Replaces row with identifier \p id with \p newRow. \p scale determines whether the new data should be scaled
1763 	   virtual void changeRow(SPxRowId id, const LPRowBase<R>& newRow, bool scale = false)
1764 	   {
1765 	      changeRow(number(id), newRow, scale);
1766 	   }
1767 	
1768 	   /// Replaces \p i 'th column of LP with \p newCol. \p scale determines whether the new data should be scaled
1769 	   virtual void changeCol(int n, const LPColBase<R>& newCol, bool scale = false)
1770 	   {
1771 	      if(n < 0)
1772 	         return;
1773 	
1774 	      int j;
1775 	      SVectorBase<R>& col = colVector_w(n);
1776 	
1777 	      for(j = col.size() - 1; j >= 0; --j)
1778 	      {
1779 	         SVectorBase<R>& row = rowVector_w(col.index(j));
1780 	         int position = row.pos(n);
1781 	
1782 	         assert(position != -1);
1783 	
1784 	         if(position >= 0)
1785 	            row.remove(position);
1786 	      }
1787 	
1788 	      col.clear();
1789 	
1790 	      changeUpper(n, newCol.upper(), scale);
1791 	      changeLower(n, newCol.lower(), scale);
1792 	      changeObj(n, newCol.obj(), scale);
1793 	
1794 	      const SVectorBase<R>& newcol = newCol.colVector();
1795 	
1796 	      for(j = newcol.size() - 1; j >= 0; --j)
1797 	      {
1798 	         int idx = newcol.index(j);
1799 	         R val = newcol.value(j);
1800 	
1801 	         if(scale)
1802 	            val = spxLdexp(val, LPColSetBase<R>::scaleExp[n] + LPRowSetBase<R>::scaleExp[idx]);
1803 	
1804 	         LPColSetBase<R>::add2(n, 1, &idx, &val);
1805 	         LPRowSetBase<R>::add2(idx, 1, &n, &val);
1806 	      }
1807 	
1808 	      assert(isConsistent());
1809 	   }
1810 	
1811 	   /// Replaces column with identifier \p id with \p newCol. \p scale determines whether the new data should be scaled
1812 	   virtual void changeCol(SPxColId id, const LPColBase<R>& newCol, bool scale = false)
1813 	   {
1814 	      changeCol(number(id), newCol, scale);
1815 	   }
1816 	
1817 	   /// Changes LP element (\p i, \p j) to \p val. \p scale determines whether the new data should be scaled
1818 	   virtual void changeElement(int i, int j, const R& val, bool scale = false)
1819 	   {
1820 	      if(i < 0 || j < 0)
1821 	         return;
1822 	
1823 	      SVectorBase<R>& row = rowVector_w(i);
1824 	      SVectorBase<R>& col = colVector_w(j);
1825 	
1826 	      if(isNotZero(val))
1827 	      {
1828 	         R newVal;
1829 	
1830 	         if(scale)
1831 	         {
1832 	            assert(_isScaled);
1833 	            assert(lp_scaler);
1834 	            newVal = lp_scaler->scaleElement(*this, i, j, val);
1835 	         }
1836 	         else
1837 	            newVal = val;
1838 	
1839 	         if(row.pos(j) >= 0 && col.pos(i) >= 0)
1840 	         {
1841 	            row.value(row.pos(j)) = newVal;
1842 	            col.value(col.pos(i)) = newVal;
1843 	         }
1844 	         else
1845 	         {
1846 	            LPRowSetBase<R>::add2(i, 1, &j, &newVal);
1847 	            LPColSetBase<R>::add2(j, 1, &i, &newVal);
1848 	         }
1849 	      }
1850 	      else if(row.pos(j) >= 0 && col.pos(i) >= 0)
1851 	      {
1852 	         row.remove(row.pos(j));
1853 	         col.remove(col.pos(i));
1854 	      }
1855 	
1856 	      assert(isConsistent());
1857 	   }
1858 	
1859 	   /// Changes LP element (\p i, \p j) to \p val.
1860 	   template < class S >
1861 	   void changeElement(int i, int j, const S* val)
1862 	   {
1863 	      if(i < 0 || j < 0)
1864 	         return;
1865 	
1866 	      SVectorBase<R>& row = rowVector_w(i);
1867 	      SVectorBase<R>& col = colVector_w(j);
1868 	
1869 	      if(mpq_get_d(*val) != R(0))
1870 	      {
1871 	         if(row.pos(j) >= 0 && col.pos(i) >= 0)
1872 	         {
1873 	            row.value(row.pos(j)) = *val;
1874 	            col.value(col.pos(i)) = *val;
1875 	         }
1876 	         else
1877 	         {
1878 	            LPRowSetBase<R>::add2(i, 1, &j, val);
1879 	            LPColSetBase<R>::add2(j, 1, &i, val);
1880 	         }
1881 	      }
1882 	      else if(row.pos(j) >= 0 && col.pos(i) >= 0)
1883 	      {
1884 	         row.remove(row.pos(j));
1885 	         col.remove(col.pos(i));
1886 	      }
1887 	
1888 	      assert(isConsistent());
1889 	   }
1890 	
1891 	   /// Changes LP element identified by (\p rid, \p cid) to \p val. \p scale determines whether the new data should be scaled
1892 	   virtual void changeElement(SPxRowId rid, SPxColId cid, const R& val, bool scale = false)
1893 	   {
1894 	      changeElement(number(rid), number(cid), val, scale);
1895 	   }
1896 	
1897 	   /// Changes optimization sense to \p sns.
1898 	   virtual void changeSense(SPxSense sns)
1899 	   {
1900 	      if(sns != thesense)
1901 	      {
1902 	         LPColSetBase<R>::maxObj_w() *= -1;
1903 	         LPRowSetBase<R>::obj_w() *= -1;
1904 	      }
1905 	
1906 	      thesense = sns;
1907 	   }
1908 	
1909 	   template <typename T>
1910 	   void changeObjOffset(const T& o)
1911 	   {
1912 	      offset = o;               // Converts o into type R. Example Rational into
1913 	      // R
1914 	   }
1915 	
1916 	   /// Computes activity of the rows for a given primal vector; activity does not need to be zero
1917 	   /// @throw SPxInternalCodeException if the dimension of primal vector does not match number of columns or if the
1918 	   ///        dimension of the activity vector does not match the number of rows
1919 	   /// \p unscaled determines whether the returned data should be unscaled (if scaling was applied prior)
1920 	   virtual void computePrimalActivity(const VectorBase<R>& primal, VectorBase<R>& activity,
1921 	                                      const bool unscaled = true) const;
1922 	
1923 	   /// Updates activity of the rows for a given primal vector; activity does not need to be zero
1924 	   /// @throw SPxInternalCodeException if the dimension of primal vector does not match number of columns or if the
1925 	   ///        dimension of the activity vector does not match the number of rows
1926 	   virtual void addPrimalActivity(const SVectorBase<R>& primal, VectorBase<R>& activity) const
1927 	   {
1928 	      if(activity.dim() != nRows())
1929 	      {
1930 	         throw SPxInternalCodeException("XSPXLP03 Activity vector computing row activity has wrong dimension");
1931 	      }
1932 	
1933 	      for(int i = primal.size() - 1; i >= 0; i--)
1934 	      {
1935 	         assert(primal.index(i) >= 0);
1936 	         assert(primal.index(i) < nCols());
1937 	         activity.multAdd(primal.value(i), colVector(primal.index(i)));
1938 	      }
1939 	   }
1940 	
1941 	   /// Computes "dual" activity of the columns for a given dual vector, i.e., y^T A; activity does not need to be zero
1942 	   /// @throw SPxInternalCodeException if dimension of dual vector does not match number of rows or if the dimension of
1943 	   ///        the activity vector does not match the number of columns
1944 	   virtual void computeDualActivity(const VectorBase<R>& dual, VectorBase<R>& activity,
1945 	                                    const bool unscaled = true) const;
1946 	
1947 	   /// Updates "dual" activity of the columns for a given dual vector, i.e., y^T A; activity does not need to be zero
1948 	   /// @throw SPxInternalCodeException if dimension of dual vector does not match number of rows or if the dimension of
1949 	   ///        the activity vector does not match the number of columns
1950 	   virtual void addDualActivity(const SVectorBase<R>& dual, VectorBase<R>& activity) const
1951 	   {
1952 	      if(activity.dim() != nCols())
1953 	      {
1954 	         throw SPxInternalCodeException("XSPXLP04 Activity vector computing dual activity has wrong dimension");
1955 	      }
1956 	
1957 	      for(int i = dual.size() - 1; i >= 0; i--)
1958 	      {
1959 	         assert(dual.index(i) >= 0);
1960 	         assert(dual.index(i) < nRows());
1961 	         activity.multAdd(dual.value(i), rowVector(dual.index(i)));
1962 	      }
1963 	   }
1964 	
1965 	   /// Updates "dual" activity of the columns for a given dual vector, i.e., y^T A; activity does not need to be zero
1966 	   /// @throw SPxInternalCodeException if dimension of dual vector does not match number of rows or if the dimension of
1967 	   ///        the activity vector does not match the number of columns
1968 	   virtual void subDualActivity(const VectorBase<R>& dual, VectorBase<R>& activity) const
1969 	   {
1970 	      if(dual.dim() != nRows())
1971 	      {
1972 	         throw SPxInternalCodeException("XSPXLP02 Dual vector for computing dual activity has wrong dimension");
1973 	      }
1974 	
1975 	      if(activity.dim() != nCols())
1976 	      {
1977 	         throw SPxInternalCodeException("XSPXLP04 Activity vector computing dual activity has wrong dimension");
1978 	      }
1979 	
1980 	      for(int r = 0; r < nRows(); r++)
1981 	      {
1982 	         if(dual[r] != 0)
1983 	            activity.multSub(dual[r], rowVector(r));
1984 	      }
1985 	   }
1986 	
1987 	   ///@}
1988 	
1989 	   // ------------------------------------------------------------------------------------------------------------------
1990 	   /**@name Construction of dual problem */
1991 	   ///@{
1992 	
1993 	   /// Building the dual problem from a given LP
1994 	   /// @note primalRows must be as large as the number of unranged primal rows + 2 * the number of ranged primal rows.
1995 	   ///       dualCols must have the identical size to the primal rows.
1996 	   virtual void buildDualProblem(SPxLPBase<R>& dualLP, SPxRowId primalRowIds[] = 0,
1997 	                                 SPxColId primalColIds[] = 0,
1998 	                                 SPxRowId dualRowIds[] = 0, SPxColId dualColIds[] = 0, int* nprimalrows = 0, int* nprimalcols = 0,
1999 	                                 int* ndualrows = 0, int* ndualcols = 0);
2000 	
2001 	   ///@}
2002 	
2003 	   // ------------------------------------------------------------------------------------------------------------------
2004 	   /**@name Miscellaneous */
2005 	   ///@{
2006 	
2007 	   /// Consistency check.
2008 	   bool isConsistent() const
2009 	   {
2010 	#ifdef ENABLE_CONSISTENCY_CHECKS
2011 	
2012 	      for(int i = nCols() - 1; i >= 0; --i)
2013 	      {
2014 	         const SVectorBase<R>& v = colVector(i);
2015 	
2016 	         for(int j = v.size() - 1; j >= 0; --j)
2017 	         {
2018 	            const SVectorBase<R>& w = rowVector(v.index(j));
2019 	            int n = w.pos(i);
2020 	
2021 	            if(n < 0)
2022 	               return MSGinconsistent("SPxLPBase");
2023 	
2024 	            if(v.value(j) != w.value(n))
2025 	               return MSGinconsistent("SPxLPBase");
2026 	         }
2027 	      }
2028 	
2029 	      for(int i = nRows() - 1; i >= 0; --i)
2030 	      {
2031 	         const SVectorBase<R>& v = rowVector(i);
2032 	
2033 	         for(int j = v.size() - 1; j >= 0; --j)
2034 	         {
2035 	            const SVectorBase<R>& w = colVector(v.index(j));
2036 	            int n = w.pos(i);
2037 	
2038 	            if(n < 0)
2039 	               return MSGinconsistent("SPxLPBase");
2040 	
2041 	            if(v.value(j) != w.value(n))
2042 	               return MSGinconsistent("SPxLPBase");
2043 	         }
2044 	      }
2045 	
2046 	      return LPRowSetBase<R>::isConsistent() && LPColSetBase<R>::isConsistent();
2047 	#else
2048 	      return true;
2049 	#endif
2050 	   }
2051 	
2052 	   ///@}
2053 	
2054 	protected:
2055 	
2056 	   // ------------------------------------------------------------------------------------------------------------------
2057 	   /**@name Protected write access */
2058 	   ///@{
2059 	
2060 	   /// Returns right hand side of row \p i.
2061 	   R& rhs_w(int i)
2062 	   {
2063 	      return LPRowSetBase<R>::rhs_w(i);
2064 	   }
2065 	
2066 	   /// Returns left hand side of row \p i.
2067 	   R& lhs_w(int i)
2068 	   {
2069 	      return LPRowSetBase<R>::lhs_w(i);
2070 	   }
2071 	
2072 	   /// Returns objective function value of row \p i.
2073 	   R& maxRowObj_w(int i)
2074 	   {
2075 	      return LPRowSetBase<R>::obj_w(i);
2076 	   }
2077 	
2078 	   /// Returns objective value of column \p i for maximization problem.
2079 	   R& maxObj_w(int i)
2080 	   {
2081 	      return LPColSetBase<R>::maxObj_w(i);
2082 	   }
2083 	
2084 	   /// Returns upper bound of column \p i.
2085 	   R& upper_w(int i)
2086 	   {
2087 	      return LPColSetBase<R>::upper_w(i);
2088 	   }
2089 	
2090 	   /// Returns lower bound of column \p i.
2091 	   R& lower_w(int i)
2092 	   {
2093 	      return LPColSetBase<R>::lower_w(i);
2094 	   }
2095 	
2096 	   ///@}
2097 	
2098 	   // ------------------------------------------------------------------------------------------------------------------
2099 	   /**@name Protected helpers */
2100 	   ///@{
2101 	
2102 	   /// Returns the LP as an LPRowSetBase.
2103 	   const LPRowSetBase<R>* lprowset() const
2104 	   {
2105 	      return static_cast<const LPRowSetBase<R>*>(this);
2106 	   }
2107 	
2108 	   /// Returns the LP as an LPColSetBase.
2109 	   const LPColSetBase<R>* lpcolset() const
2110 	   {
2111 	      return static_cast<const LPColSetBase<R>*>(this);
2112 	   }
2113 	
2114 	   /// Internal helper method.
2115 	   virtual void doRemoveRow(int j)
2116 	   {
2117 	
2118 	      const SVectorBase<R>& vec = rowVector(j);
2119 	
2120 	      // remove row vector from column file
2121 	      for(int i = vec.size() - 1; i >= 0; --i)
2122 	      {
2123 	         SVectorBase<R>& remvec = colVector_w(vec.index(i));
2124 	         int position = remvec.pos(j);
2125 	
2126 	         if(position >= 0)
2127 	            remvec.remove(position);
2128 	      }
2129 	
2130 	      // move last row to removed position
2131 	      int idx = nRows() - 1;
2132 	
2133 	      if(j != idx)
2134 	      {
2135 	         const SVectorBase<R>& l_vec = rowVector(idx);
2136 	
2137 	         for(int i = l_vec.size() - 1; i >= 0; --i)
2138 	         {
2139 	            SVectorBase<R>& movevec = colVector_w(l_vec.index(i));
2140 	            int position = movevec.pos(idx);
2141 	
2142 	            assert(position != -1);
2143 	
2144 	            if(position >= 0)
2145 	               movevec.index(position) = j;
2146 	         }
2147 	      }
2148 	
2149 	      LPRowSetBase<R>::remove(j);
2150 	   }
2151 	
2152 	   /// Internal helper method.
2153 	   virtual void doRemoveRows(int perm[])
2154 	   {
2155 	      int j = nCols();
2156 	
2157 	      LPRowSetBase<R>::remove(perm);
2158 	
2159 	      for(int i = 0; i < j; ++i)
2160 	      {
2161 	         SVectorBase<R>& vec = colVector_w(i);
2162 	
2163 	         for(int k = vec.size() - 1; k >= 0; --k)
2164 	         {
2165 	            int idx = vec.index(k);
2166 	
2167 	            if(perm[idx] < 0)
2168 	               vec.remove(k);
2169 	            else
2170 	               vec.index(k) = perm[idx];
2171 	         }
2172 	      }
2173 	   }
2174 	
2175 	   /// Internal helper method.
2176 	   virtual void doRemoveCol(int j)
2177 	   {
2178 	
2179 	      const SVectorBase<R>& vec = colVector(j);
2180 	      int i;
2181 	
2182 	      // remove column vector from row file
2183 	      for(i = vec.size() - 1; i >= 0; --i)
2184 	      {
2185 	         SVectorBase<R>& remvec = rowVector_w(vec.index(i));
2186 	         int position = remvec.pos(j);
2187 	
2188 	         assert(position != -1);
2189 	
2190 	         if(position >= 0)
2191 	            remvec.remove(position);
2192 	      }
2193 	
2194 	      // move last column to removed position
2195 	      int idx = nCols() - 1;
2196 	
2197 	      if(j != idx)
2198 	      {
2199 	         const SVectorBase<R>& l_vec = colVector(idx);
2200 	
2201 	         for(i = l_vec.size() - 1; i >= 0; --i)
2202 	         {
2203 	            SVectorBase<R>& movevec = rowVector_w(l_vec.index(i));
2204 	            int position = movevec.pos(idx);
2205 	
2206 	            assert(position != -1);
2207 	
2208 	            if(position >= 0)
2209 	               movevec.index(position) = j;
2210 	         }
2211 	      }
2212 	
2213 	      LPColSetBase<R>::remove(j);
2214 	   }
2215 	
2216 	   /// Internal helper method.
2217 	   virtual void doRemoveCols(int perm[])
2218 	   {
2219 	      int nrows = nRows();
2220 	
2221 	      LPColSetBase<R>::remove(perm);
2222 	
2223 	      for(int i = 0; i < nrows; ++i)
2224 	      {
2225 	         SVectorBase<R>& vec = rowVector_w(i);
2226 	
2227 	         for(int k = vec.size() - 1; k >= 0; --k)
2228 	         {
2229 	            int idx = vec.index(k);
2230 	
2231 	            if(perm[idx] < 0)
2232 	               vec.remove(k);
2233 	            else
2234 	               vec.index(k) = perm[idx];
2235 	         }
2236 	      }
2237 	   }
2238 	
2239 	   /// Called after the last \p n rows have just been added.
2240 	   virtual void addedRows(int newrows)
2241 	   {}
2242 	
2243 	   /// Called after the last \p n columns have just been added.
2244 	   virtual void addedCols(int newcols)
2245 	   {}
2246 	
2247 	   ///
2248 	   void added2Set(SVSetBase<R>& set, const SVSetBase<R>& addset, int n)
2249 	   {
2250 	
2251 	      if(n == 0)
2252 	         return;
2253 	
2254 	      DataArray<int> moreArray(set.num());
2255 	      int* more = moreArray.get_ptr();
2256 	
2257 	      for(int i = set.num() - 1; i >= 0; --i)
2258 	         more[i] = 0;
2259 	
2260 	      int tot = 0;
2261 	      int end = addset.num();
2262 	
2263 	      for(int i = addset.num() - n; i < end; ++i)
2264 	      {
2265 	         const SVectorBase<R>& vec = addset[i];
2266 	
2267 	         tot += vec.size();
2268 	
2269 	         for(int j = vec.size() - 1; j >= 0; --j)
2270 	            more[vec.index(j)]++;
2271 	      }
2272 	
2273 	      if(set.memMax() < tot)
2274 	         set.memRemax(tot);
2275 	
2276 	      for(int i = set.num() - 1; i >= 0; --i)
2277 	      {
2278 	         int j = set[i].size();
2279 	         set.xtend(set[i], j + more[i]);
2280 	         set[i].set_size(j + more[i]);
2281 	         more[i] = j;
2282 	      }
2283 	
2284 	      for(int i = addset.num() - n; i < addset.num(); ++i)
2285 	      {
2286 	         const SVectorBase<R>& vec = addset[i];
2287 	
2288 	         for(int j = vec.size() - 1; j >= 0; --j)
2289 	         {
2290 	            int k = vec.index(j);
2291 	            int m = more[k]++;
2292 	            SVectorBase<R>& l_xtend = set[k];
2293 	            l_xtend.index(m) = i;
2294 	            l_xtend.value(m) = vec.value(j);
2295 	         }
2296 	      }
2297 	   }
2298 	
2299 	   ///@}
2300 	
2301 	
2302 	private:
2303 	
2304 	   // ------------------------------------------------------------------------------------------------------------------
2305 	   /**@name Private helpers */
2306 	   ///@{
2307 	
2308 	   /// Returns the LP as an LPRowBase<R>Set.
2309 	   SVectorBase<R>& colVector_w(int i)
2310 	   {
2311 	      return LPColSetBase<R>::colVector_w(i);
2312 	   }
2313 	
2314 	   ///
2315 	   SVectorBase<R>& rowVector_w(int i)
2316 	   {
2317 	      return LPRowSetBase<R>::rowVector_w(i);
2318 	   }
2319 	
2320 	   ///
2321 	   void doAddRow(const LPRowBase<R>& row, bool scale = false)
2322 	   {
2323 	      int idx = nRows();
2324 	      int oldColNumber = nCols();
2325 	      int newRowScaleExp = 0;
2326 	
2327 	      LPRowSetBase<R>::add(row);
2328 	
2329 	      SVectorBase<R>& vec = rowVector_w(idx);
2330 	
2331 	      DataArray <int>& colscaleExp = LPColSetBase<R>::scaleExp;
2332 	
2333 	      // compute new row scaling factor and apply it to the sides
2334 	      if(scale && lp_scaler)
2335 	      {
2336 	         newRowScaleExp = lp_scaler->computeScaleExp(vec, colscaleExp);
2337 	
2338 	         if(rhs(idx) < R(infinity))
2339 	            rhs_w(idx) = spxLdexp(rhs_w(idx), newRowScaleExp);
2340 	
2341 	         if(lhs(idx) > R(-infinity))
2342 	            lhs_w(idx) = spxLdexp(lhs_w(idx), newRowScaleExp);
2343 	
2344 	         maxRowObj_w(idx) = spxLdexp(maxRowObj_w(idx), newRowScaleExp);
2345 	
2346 	         LPRowSetBase<R>::scaleExp[idx] = newRowScaleExp;
2347 	      }
2348 	
2349 	      // now insert nonzeros to column file also
2350 	      for(int j = vec.size() - 1; j >= 0; --j)
2351 	      {
2352 	         int i = vec.index(j);
2353 	
2354 	         // apply new row and existing column scaling factors to new values in RowSet
2355 	         if(scale)
2356 	            vec.value(j) = spxLdexp(vec.value(j), newRowScaleExp + colscaleExp[i]);
2357 	
2358 	         R val = vec.value(j);
2359 	
2360 	         // create new columns if required
2361 	         if(i >= nCols())
2362 	         {
2363 	            LPColBase<R> empty;
2364 	
2365 	            for(int k = nCols(); k <= i; ++k)
2366 	               LPColSetBase<R>::add(empty);
2367 	         }
2368 	
2369 	         assert(i < nCols());
2370 	         LPColSetBase<R>::add2(i, 1, &idx, &val);
2371 	      }
2372 	
2373 	      addedRows(1);
2374 	      addedCols(nCols() - oldColNumber);
2375 	   }
2376 	
2377 	   ///
2378 	   void doAddRow(const R& lhsValue, const SVectorBase<R>& rowVec, const R& rhsValue,
2379 	                 bool scale = false)
2380 	   {
2381 	      int idx = nRows();
2382 	      int oldColNumber = nCols();
2383 	      int newRowScaleExp = 0;
2384 	
2385 	      LPRowSetBase<R>::add(lhsValue, rowVec, rhsValue);
2386 	
2387 	      DataArray <int>& colscaleExp = LPColSetBase<R>::scaleExp;
2388 	
2389 	      // compute new row scaling factor and apply it to the sides
2390 	      if(scale)
2391 	      {
2392 	         newRowScaleExp = lp_scaler->computeScaleExp(rowVec, colscaleExp);
2393 	
2394 	         if(rhs(idx) < R(infinity))
2395 	            rhs_w(idx) = spxLdexp(rhs_w(idx), newRowScaleExp);
2396 	
2397 	         if(lhs(idx) > R(-infinity))
2398 	            lhs_w(idx) = spxLdexp(lhs_w(idx), newRowScaleExp);
2399 	
2400 	         maxRowObj_w(idx) = spxLdexp(maxRowObj_w(idx), newRowScaleExp);
2401 	
2402 	         LPRowSetBase<R>::scaleExp[idx] = newRowScaleExp;
2403 	      }
2404 	
2405 	      SVectorBase<R>& vec = rowVector_w(idx);
2406 	
2407 	      // now insert nonzeros to column file also
2408 	      for(int j = vec.size() - 1; j >= 0; --j)
2409 	      {
2410 	         int i = vec.index(j);
2411 	
2412 	         // apply new row and existing column scaling factors to new values in RowSet
2413 	         if(scale)
2414 	            vec.value(j) = spxLdexp(vec.value(j), newRowScaleExp + colscaleExp[i]);
2415 	
2416 	         R val = vec.value(j);
2417 	
2418 	         // create new columns if required
2419 	         if(i >= nCols())
2420 	         {
2421 	            LPColBase<R> empty;
2422 	
2423 	            for(int k = nCols(); k <= i; ++k)
2424 	               LPColSetBase<R>::add(empty);
2425 	         }
2426 	
2427 	         assert(i < nCols());
2428 	         LPColSetBase<R>::add2(i, 1, &idx, &val);
2429 	      }
2430 	
2431 	      addedRows(1);
2432 	      addedCols(nCols() - oldColNumber);
2433 	   }
2434 	
2435 	   ///
2436 	   void doAddRows(const LPRowSetBase<R>& set, bool scale = false)
2437 	   {
2438 	      int i, j, k, ii, idx;
2439 	      SVectorBase<R>* col;
2440 	      DataArray < int > newCols(nCols());
2441 	      int oldRowNumber = nRows();
2442 	      int oldColNumber = nCols();
2443 	
2444 	      if(&set != this)
2445 	         LPRowSetBase<R>::add(set);
2446 	
2447 	      assert(LPRowSetBase<R>::isConsistent());
2448 	      assert(LPColSetBase<R>::isConsistent());
2449 	
2450 	      // count additional nonzeros per column
2451 	      for(i = nCols() - 1; i >= 0; --i)
2452 	         newCols[i] = 0;
2453 	
2454 	      for(i = set.num() - 1; i >= 0; --i)
2455 	      {
2456 	         const SVectorBase<R>& vec = set.rowVector(i);
2457 	
2458 	         for(j = vec.size() - 1; j >= 0; --j)
2459 	         {
2460 	            // create new columns if required
2461 	            ii = vec.index(j);
2462 	
2463 	            if(ii >= nCols())
2464 	            {
2465 	               LPColBase<R> empty;
2466 	               newCols.reSize(ii + 1);
2467 	
2468 	               for(k = nCols(); k <= ii; ++k)
2469 	               {
2470 	                  newCols[k] = 0;
2471 	                  LPColSetBase<R>::add(empty);
2472 	               }
2473 	            }
2474 	
2475 	            assert(ii < nCols());
2476 	            newCols[ii]++;
2477 	         }
2478 	      }
2479 	
2480 	      // extend columns as required (backward because of memory efficiency reasons)
2481 	      for(i = nCols() - 1; i >= 0; --i)
2482 	      {
2483 	         if(newCols[i] > 0)
2484 	         {
2485 	            int len = newCols[i] + colVector(i).size();
2486 	            LPColSetBase<R>::xtend(i, len);
2487 	
2488 	            /* preset the sizes: beware that this can irritate a consistency check call from xtend(). We need to set the
2489 	             * sizes here, because a possible garbage collection called from xtend might destroy the sizes again. */
2490 	            colVector_w(i).set_size(len);
2491 	         }
2492 	      }
2493 	
2494 	      // compute new row scaling factor and insert new elements to column file
2495 	      for(i = nRows() - 1; i >= oldRowNumber; --i)
2496 	      {
2497 	         SVectorBase<R>& vec = rowVector_w(i);
2498 	         int newRowScaleExp = 0;
2499 	
2500 	         DataArray <int>& colscaleExp = LPColSetBase<R>::scaleExp;
2501 	
2502 	         // compute new row scaling factor and apply it to the sides
2503 	         if(scale)
2504 	         {
2505 	            newRowScaleExp = lp_scaler->computeScaleExp(vec, colscaleExp);
2506 	
2507 	            if(rhs(i) < R(infinity))
2508 	               rhs_w(i) = spxLdexp(rhs_w(i), newRowScaleExp);
2509 	
2510 	            if(lhs(i) > R(-infinity))
2511 	               lhs_w(i) = spxLdexp(lhs_w(i), newRowScaleExp);
2512 	
2513 	            maxRowObj_w(i) = spxLdexp(maxRowObj_w(i), newRowScaleExp);
2514 	
2515 	            LPRowSetBase<R>::scaleExp[i] = newRowScaleExp;
2516 	         }
2517 	
2518 	         for(j = vec.size() - 1; j >= 0; --j)
2519 	         {
2520 	            k = vec.index(j);
2521 	            col = &colVector_w(k);
2522 	            idx = col->size() - newCols[k];
2523 	            assert(newCols[k] > 0);
2524 	            assert(idx >= 0);
2525 	            newCols[k]--;
2526 	            col->index(idx) = i;
2527 	
2528 	            // apply new row and existing column scaling factors to both ColSet and RowSet
2529 	            if(scale)
2530 	               vec.value(j) = spxLdexp(vec.value(j), newRowScaleExp + colscaleExp[k]);
2531 	
2532 	            col->value(idx) = vec.value(j);
2533 	         }
2534 	      }
2535 	
2536 	#ifndef NDEBUG
2537 	
2538 	      for(i = 0; i < nCols(); ++i)
2539 	         assert(newCols[i] == 0);
2540 	
2541 	#endif
2542 	
2543 	      assert(SPxLPBase<R>::isConsistent());
2544 	
2545 	      assert(set.num() == nRows() - oldRowNumber);
2546 	      addedRows(nRows() - oldRowNumber);
2547 	      addedCols(nCols() - oldColNumber);
2548 	   }
2549 	
2550 	   ///
2551 	   void doAddCol(const LPColBase<R>& col, bool scale = false)
2552 	   {
2553 	      int idx = nCols();
2554 	      int oldRowNumber = nRows();
2555 	      int newColScaleExp = 0;
2556 	
2557 	      LPColSetBase<R>::add(col);
2558 	
2559 	      if(thesense != MAXIMIZE)
2560 	         LPColSetBase<R>::maxObj_w(idx) *= -1;
2561 	
2562 	      SVectorBase<R>& vec = colVector_w(idx);
2563 	
2564 	      DataArray <int>& rowscaleExp = LPRowSetBase<R>::scaleExp;
2565 	
2566 	      // compute new column scaling factor and apply it to the bounds
2567 	      if(scale)
2568 	      {
2569 	         newColScaleExp = lp_scaler->computeScaleExp(vec, rowscaleExp);
2570 	
2571 	         if(upper(idx) < R(infinity))
2572 	            upper_w(idx) = spxLdexp(upper_w(idx), - newColScaleExp);
2573 	
2574 	         if(lower(idx) > R(-infinity))
2575 	            lower_w(idx) = spxLdexp(lower_w(idx), - newColScaleExp);
2576 	
2577 	         maxObj_w(idx) = spxLdexp(maxObj_w(idx), newColScaleExp);
2578 	
2579 	         LPColSetBase<R>::scaleExp[idx] = newColScaleExp;
2580 	      }
2581 	
2582 	      // now insert nonzeros to row file also
2583 	      for(int j = vec.size() - 1; j >= 0; --j)
2584 	      {
2585 	         int i = vec.index(j);
2586 	
2587 	         // apply new column and existing row scaling factors to new values in ColSet
2588 	         if(scale)
2589 	            vec.value(j) = spxLdexp(vec.value(j), newColScaleExp + rowscaleExp[i]);
2590 	
2591 	         R val = vec.value(j);
2592 	
2593 	         // create new rows if required
2594 	         if(i >= nRows())
2595 	         {
2596 	            LPRowBase<R> empty;
2597 	
2598 	            for(int k = nRows(); k <= i; ++k)
2599 	               LPRowSetBase<R>::add(empty);
2600 	         }
2601 	
2602 	         assert(i < nRows());
2603 	         LPRowSetBase<R>::add2(i, 1, &idx, &val);
2604 	      }
2605 	
2606 	      addedCols(1);
2607 	      addedRows(nRows() - oldRowNumber);
2608 	   }
2609 	
2610 	   ///
2611 	   void doAddCol(const R& objValue, const R& lowerValue, const SVectorBase<R>& colVec,
2612 	                 const R& upperValue, bool scale = false)
2613 	   {
2614 	      int idx = nCols();
2615 	      int oldRowNumber = nRows();
2616 	      int newColScaleExp = 0;
2617 	
2618 	      LPColSetBase<R>::add(objValue, lowerValue, colVec, upperValue);
2619 	
2620 	      if(thesense != MAXIMIZE)
2621 	         LPColSetBase<R>::maxObj_w(idx) *= -1;
2622 	
2623 	      DataArray <int>& rowscaleExp = LPRowSetBase<R>::scaleExp;
2624 	
2625 	      // compute new column scaling factor and apply it to the bounds
2626 	      if(scale)
2627 	      {
2628 	         newColScaleExp = lp_scaler->computeScaleExp(colVec, rowscaleExp);
2629 	
2630 	         if(upper(idx) < R(infinity))
2631 	            upper_w(idx) = spxLdexp(upper_w(idx), - newColScaleExp);
2632 	
2633 	         if(lower(idx) > R(-infinity))
2634 	            lower_w(idx) = spxLdexp(lower_w(idx), - newColScaleExp);
2635 	
2636 	         maxObj_w(idx) = spxLdexp(maxObj_w(idx), newColScaleExp);
2637 	
2638 	         LPColSetBase<R>::scaleExp[idx] = newColScaleExp;
2639 	      }
2640 	
2641 	      SVectorBase<R>& vec = colVector_w(idx);
2642 	
2643 	      // now insert nonzeros to row file also
2644 	      for(int j = vec.size() - 1; j >= 0; --j)
2645 	      {
2646 	         int i = vec.index(j);
2647 	
2648 	         if(scale)
2649 	            vec.value(j) = spxLdexp(vec.value(j), newColScaleExp + rowscaleExp[i]);
2650 	
2651 	         R val = vec.value(j);
2652 	
2653 	         // create new rows if required
2654 	         if(i >= nRows())
2655 	         {
2656 	            LPRowBase<R> empty;
2657 	
2658 	            for(int k = nRows(); k <= i; ++k)
2659 	               LPRowSetBase<R>::add(empty);
2660 	         }
2661 	
2662 	         assert(i < nRows());
2663 	         LPRowSetBase<R>::add2(i, 1, &idx, &val);
2664 	      }
2665 	
2666 	      addedCols(1);
2667 	      addedRows(nRows() - oldRowNumber);
2668 	   }
2669 	
2670 	   ///
2671 	   void doAddCols(const LPColSetBase<R>& set, bool scale = false)
2672 	   {
2673 	      int i, j;
2674 	      int oldColNumber = nCols();
2675 	      int oldRowNumber = nRows();
2676 	      DataArray < int > newRows(nRows());
2677 	
2678 	      if(&set != this)
2679 	         LPColSetBase<R>::add(set);
2680 	
2681 	      assert(LPColSetBase<R>::isConsistent());
2682 	      assert(LPRowSetBase<R>::isConsistent());
2683 	
2684 	      // count additional nonzeros per row
2685 	      for(i = nRows() - 1; i >= 0; --i)
2686 	         newRows[i] = 0;
2687 	
2688 	      for(i = set.num() - 1; i >= 0; --i)
2689 	      {
2690 	         const SVectorBase<R>& vec = set.colVector(i);
2691 	
2692 	         for(j = vec.size() - 1; j >= 0; --j)
2693 	         {
2694 	            // create new rows if required
2695 	            int l = vec.index(j);
2696 	
2697 	            if(l >= nRows())
2698 	            {
2699 	               LPRowBase<R> empty;
2700 	               newRows.reSize(l + 1);
2701 	
2702 	               for(int k = nRows(); k <= l; ++k)
2703 	               {
2704 	                  newRows[k] = 0;
2705 	                  LPRowSetBase<R>::add(empty);
2706 	               }
2707 	
2708 	            }
2709 	
2710 	            assert(l < nRows());
2711 	            newRows[l]++;
2712 	         }
2713 	      }
2714 	
2715 	      // extend rows as required
2716 	      for(i = 0; i < nRows(); ++i)
2717 	      {
2718 	         if(newRows[i] > 0)
2719 	         {
2720 	            int len = newRows[i] + rowVector(i).size();
2721 	            LPRowSetBase<R>::xtend(i, len);
2722 	            rowVector_w(i).set_size(len);
2723 	         }
2724 	      }
2725 	
2726 	      // insert new elements to row file
2727 	      for(i = oldColNumber; i < nCols(); ++i)
2728 	      {
2729 	         // @todo: Is there a better way to write the following if, else?
2730 	         if(thesense == MAXIMIZE)
2731 	         {
2732 	            LPColSetBase<R>::maxObj_w(i) *= 1;
2733 	         }
2734 	         else                  // thesense is MINIMIZE = -1
2735 	         {
2736 	            LPColSetBase<R>::maxObj_w(i) *= -1;
2737 	         }
2738 	
2739 	         SVectorBase<R>& vec = colVector_w(i);
2740 	         int newColScaleExp = 0;
2741 	
2742 	         DataArray <int>& rowscaleExp = LPRowSetBase<R>::scaleExp;
2743 	
2744 	         // compute new column scaling factor and apply it to the bounds
2745 	         if(scale)
2746 	         {
2747 	            newColScaleExp = lp_scaler->computeScaleExp(vec, rowscaleExp);
2748 	
2749 	            if(upper(i) < R(infinity))
2750 	               upper_w(i) = spxLdexp(upper_w(i), - newColScaleExp);
2751 	
2752 	            if(lower(i) > R(-infinity))
2753 	               lower_w(i) = spxLdexp(lower_w(i), - newColScaleExp);
2754 	
2755 	            maxObj_w(i) = spxLdexp(maxObj_w(i), newColScaleExp);
2756 	
2757 	            LPColSetBase<R>::scaleExp[i] = newColScaleExp;
2758 	         }
2759 	
2760 	         for(j = vec.size() - 1; j >= 0; --j)
2761 	         {
2762 	            int k = vec.index(j);
2763 	            SVectorBase<R>& row = rowVector_w(k);
2764 	            int idx = row.size() - newRows[k];
2765 	            assert(newRows[k] > 0);
2766 	            newRows[k]--;
2767 	            row.index(idx) = i;
2768 	
2769 	            // apply new column and existing row scaling factors to both ColSet and RowSet
2770 	            if(scale)
2771 	               vec.value(j) = spxLdexp(vec.value(j), newColScaleExp + rowscaleExp[k]);
2772 	
2773 	            row.value(idx) = vec.value(j);
2774 	         }
2775 	      }
2776 	
2777 	#ifndef NDEBUG
2778 	
2779 	      for(i = 0; i < nRows(); ++i)
2780 	         assert(newRows[i] == 0);
2781 	
2782 	#endif
2783 	
2784 	      assert(SPxLPBase<R>::isConsistent());
2785 	
2786 	      assert(set.num() == nCols() - oldColNumber);
2787 	      addedCols(nCols() - oldColNumber);
2788 	      addedRows(nRows() - oldRowNumber);
2789 	   }
2790 	
2791 	   ///@}
2792 	
2793 	public:
2794 	
2795 	   // ------------------------------------------------------------------------------------------------------------------
2796 	   /**@name Constructors / Destructors */
2797 	   ///@{
2798 	
2799 	   /// Default constructor.
2800 	   SPxLPBase<R>()
2801 	   {
2802 	      SPxLPBase<R>::clear(); // clear is virtual.
2803 	
2804 	      assert(isConsistent());
2805 	   }
2806 	
2807 	   /// Destructor.
2808 	   virtual ~SPxLPBase<R>()
2809 	   {}
2810 	
2811 	   /// Copy constructor.
2812 	   SPxLPBase<R>(const SPxLPBase<R>& old)
2813 	      : LPRowSetBase<R>(old)
2814 	      , LPColSetBase<R>(old)
2815 	      , thesense(old.thesense)
2816 	      , offset(old.offset)
2817 	      , _isScaled(old._isScaled)
2818 	      , lp_scaler(old.lp_scaler)
2819 	      , spxout(old.spxout)
2820 	   {
2821 	      assert(isConsistent());
2822 	   }
2823 	
2824 	   /// Copy constructor.
2825 	   template < class S >
2826 	   SPxLPBase<R>(const SPxLPBase<S>& old)
2827 	      : LPRowSetBase<R>(old)
2828 	      , LPColSetBase<R>(old)
2829 	      , thesense(old.thesense == SPxLPBase<S>::MINIMIZE ? SPxLPBase<R>::MINIMIZE : SPxLPBase<R>::MAXIMIZE)
2830 	      , offset(old.offset)
2831 	      , _isScaled(old._isScaled)
2832 	      , spxout(old.spxout)
2833 	   {
2834 	      lp_scaler = nullptr;
2835 	      assert(isConsistent());
2836 	   }
2837 	
2838 	   /// Assignment operator.
2839 	   SPxLPBase<R>& operator=(const SPxLPBase<R>& old)
2840 	   {
2841 	      if(this != &old)
2842 	      {
2843 	         LPRowSetBase<R>::operator=(old);
2844 	         LPColSetBase<R>::operator=(old);
2845 	         thesense = old.thesense;
2846 	         offset = old.offset;
2847 	         _isScaled = old._isScaled;
2848 	         lp_scaler = old.lp_scaler;
2849 	         spxout = old.spxout;
2850 	
2851 	         assert(isConsistent());
2852 	      }
2853 	
2854 	      return *this;
2855 	   }
2856 	
2857 	   /// Assignment operator.
2858 	   template < class S >
2859 	   SPxLPBase<R>& operator=(const SPxLPBase<S>& old)
2860 	   {
2861 	      if(this != (const SPxLPBase<R>*)(&old))
2862 	      {
2863 	         // The value of old.lp_scaler has to be nullptr
2864 	         // Refer to issue #161 in soplex gitlab
2865 	         assert(old.lp_scaler == nullptr);
2866 	
2867 	         LPRowSetBase<R>::operator=(old);
2868 	         LPColSetBase<R>::operator=(old);
2869 	         thesense = (old.thesense) == SPxLPBase<S>::MINIMIZE ? SPxLPBase<R>::MINIMIZE :
2870 	                    SPxLPBase<R>::MAXIMIZE;
2871 	         offset = R(old.offset);
2872 	         _isScaled = old._isScaled;
2873 	
2874 	         // this may have un-intended consequences in the future
2875 	         lp_scaler = nullptr;
2876 	         spxout = old.spxout;
2877 	
2878 	         assert(isConsistent());
2879 	      }
2880 	
2881 	      return *this;
2882 	   }
2883 	
2884 	   ///@}
2885 	};
2886 	
2887 	} // namespace soplex
2888 	
2889 	// For the general templated functions
2890 	#include "spxlpbase_real.hpp"
2891 	#include "spxlpbase_rational.hpp"
2892 	
2893 	/* reset the SOPLEX_DEBUG flag to its original value */
2894 	#undef SOPLEX_DEBUG
2895 	#ifdef SOPLEX_DEBUG_SPXLPBASE
2896 	#define SOPLEX_DEBUG
2897 	#undef SOPLEX_DEBUG_SPXLPBASE
2898 	#endif
2899 	
2900 	#endif // _SPXLPBASE_H_
2901