Scippy

SoPlex

Sequential object-oriented simPlex

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