Scippy

SoPlex

Sequential object-oriented simPlex

svsetbase.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 svsetbase.h
17  * @brief Set of sparse vectors.
18  */
19 
20 #ifndef _SVSETBASE_H_
21 #define _SVSETBASE_H_
22 
23 /* undefine SOPLEX_DEBUG flag from including files; if SOPLEX_DEBUG should be defined in this file, do so below */
24 #ifdef SOPLEX_DEBUG
25 #define SOPLEX_DEBUG_SVSETBASE
26 #undef SOPLEX_DEBUG
27 #endif
28 
29 #include <assert.h>
30 
31 #include "spxdefines.h"
32 #include "svectorbase.h"
33 #include "classarray.h"
34 #include "dataset.h"
35 #include "datakey.h"
36 #include "idlist.h"
37 
38 namespace soplex
39 {
40 /**@brief Sparse vector set.
41  * @ingroup Algebra
42  *
43  * Class SVSetBase provides a set of sparse vectors SVectorBase. All SVectorBase%s in an SVSetBase share one big
44  * memory block for their nonzeros. This memory is reffered to as the \em nonzero \em memory. The SVectorBase%s
45  * themselves are saved in another memory block refered to as the \em vector \em memory. Both memory blocks will grow
46  * automatically if required, when adding more SVectorBase%s to the set or enlarging SVectorBase%s within the set. For
47  * controlling memory consumption, methods are provided to inquire and reset the size of the memory blocks used for
48  * vectors and nonzeros.
49  *
50  * SVectorBase%s in an SVSetBase are numbered from 0 thru num()-1. They can be accessed using the index
51  * operator[](). When removing SVectorBase%s of a SVSetBase the remaining ones will be renumbered. However, all
52  * SVectorBase with a smaller number than the lowest number of the removed SVectorBase%s will remain unchanged.
53  *
54  * For providing a uniform access to SVectorBase%s in a %set even if others are removed or added, SVSetBase assigns a
55  * DataKey to each SVectorBase in the %set. Such a DataKey remains unchanged as long as the corresponding SVectorBase
56  * is in the SVSetBase, no matter what other SVectorBase%s are added to or removed from the SVSetBase. Methods are
57  * provided for getting the DataKey to a SVectorBase or its number and vice versa. Further, each add() method for
58  * enlarging an SVSetBase is provided with two signatures. One of them returns the DataKey%s assigned to the
59  * SVectorBase%s added to the SVSetBase.
60  */
61 template < class R >
62 class SVSetBase : protected ClassArray < Nonzero<R> >
63 {
64  template < class S > friend class SVSetBase;
65 
66 private:
67 
69 
70  /**@class DLPSV
71  * @brief SVectorBase with prev/next pointers
72  * @todo Check whether SVSetBase::DLPSV can be implemented as IdElement<SVectorBase>
73  *
74  * The management of the SVectorBase%s is implemented by a DataSet<DLPSV>, the keys used externally are DataKey%s.
75  *
76  * The management of nonzeros is done by a Real linked list IdList<DLPSV>, where the SVectorBase%s are kept in the
77  * order in which their indices occurr in the Array. The SVectorBase%s are kept without holes: If one is removed or
78  * moved to the end, the SVectorBase preceeding it obtains the space for all the nonzeros that previously belonged
79  * to the (re-)moved one. However, the nonzeros in use are uneffected by this.
80  */
81  class DLPSV : public SVectorBase<R>
82  {
83  private:
84 
85  // ---------------------------------------------------------------------------------------------------------------
86  /**@name Data */
87  //@{
88 
89  DLPSV* thenext; ///< next SVectorBase
90  DLPSV* theprev; ///< previous SVectorBase
91 
92  //@}
93 
94  public:
95 
96  // ---------------------------------------------------------------------------------------------------------------
97  /**@name Construction / destruction */
98  //@{
99 
100  /// Default constructor.
102  : SVectorBase<R>()
103  {}
104 
105  /// Copy constructor.
106  DLPSV(const DLPSV& copy)
107  : SVectorBase<R>(copy)
108  {}
109 
110  //@}
111 
112  // ---------------------------------------------------------------------------------------------------------------
113  /**@name Successor / predecessor */
114  //@{
115 
116  /// Next SVectorBase.
118  {
119  return thenext;
120  }
121 
122  /// Next SVectorBase.
123  DLPSV* const& next() const
124  {
125  return thenext;
126  }
127 
128  /// Previous SVectorBase.
129  DLPSV* const& prev() const
130  {
131  return theprev;
132  }
133 
134  /// Previous SVectorBase.
136  {
137  return theprev;
138  }
139 
140  //@}
141  };
142 
143  // ------------------------------------------------------------------------------------------------------------------
144  /**@name Data */
145  //@{
146 
147  DataSet < DLPSV > set; ///< %set of SVectorBase%s
148  IdList < DLPSV > list; ///< doubly linked list for non-zero management
149  int unusedMem; ///< an estimate of the unused memory (the difference of max() and size() summed up over all vectors) due to deleteVec() and xtend()
150  int numUnusedMemUpdates; ///< counter for how often unusedMem has been updated since last exact value
151 
152  //@}
153 
154  // ------------------------------------------------------------------------------------------------------------------
155  /**@name Control Parameters */
156  //@{
157 
158  double factor; ///< sparse vector memory enlargment factor
159 
160  //@}
161 
162  // ------------------------------------------------------------------------------------------------------------------
163  /**@name Helpers */
164  //@{
165 
166  /// count size of unused memory exactly
168  {
169 #ifdef SOPLEX_DEBUG
170  MSG_DEBUG( std::cout << "counting unused memory (unusedMem = " << unusedMem << ", numUnusedMemUpdates = " << numUnusedMemUpdates << ", this = " << (void*)this << ")\n" );
171 #endif
172 
173  unusedMem = memSize();
174  for( DLPSV* ps = list.first(); ps; ps = list.next(ps) )
175  unusedMem -= ps->size();
176 
178 
179 #ifdef SOPLEX_DEBUG
180  MSG_DEBUG( std::cout << " --> NEW: unusedMem = " << unusedMem << "\n" );
181 #endif
182  }
183 
184  /// update estimation of unused memory
185  void updateUnusedMemEstimation(int change)
186  {
187  unusedMem += change;
189 
190  if( unusedMem < 0 || unusedMem > memSize() || numUnusedMemUpdates >= 1000000 )
191  countUnusedMem();
192  }
193 
194  /// Provides enough vector memory for \p n more SVectorBase%s.
195  void ensurePSVec(int n)
196  {
197  if( num() + n > max() )
198  {
199  assert(factor > 1);
200 
201  reMax(int(factor*max()) + 8 + n);
202  }
203  }
204 
205  /// Provides enough nonzero memory for \p n more Nonzero%s.
206  void ensureMem(int n, bool shortenLast = true)
207  {
208  if( memSize() + n <= memMax() )
209  return;
210 
211  if( list.last() && shortenLast )
212  {
213  // get last vector and compute its unused memory
214  DLPSV* ps = list.last();
215  int unusedPsMem = ps->max() - ps->size();
216  assert(unusedPsMem >= 0);
217 
218  // return vector's unused memory to common memory
219  SVSetBaseArray::removeLast(unusedPsMem);
220  ps->set_max(ps->size());
221 
222  // decrease counter of unused memory
223 #ifdef SOPLEX_DEBUG
224  MSG_DEBUG( std::cout << "ensureMem, this = " << (void*)this << ": updateUnusedMemEstimation -= " << unusedPsMem << "\n" );
225 #endif
226  updateUnusedMemEstimation(-unusedPsMem);
227  }
228 
229  // if the missing memory can be acquired by packing the memory, we prefer this to allocating new memory
230  int missingMem = (memSize() + n - memMax());
231  ///@todo use an independent parameter "memwastefactor" here
232  if( missingMem > 0 && missingMem <= unusedMem && unusedMem > (SVSetBaseArray::memFactor - 1.0) * memMax() )
233  memPack();
234 
235  // if the unused memory was overestimated and packing did not help, we need to reallocate
236  if( memSize() + n > memMax() )
237  {
238  int newMax = int(SVSetBaseArray::memFactor * memMax());
239 
240  if( memSize() + n > newMax )
241  newMax = memSize() + n;
242 
243  memRemax(newMax);
244  }
245  }
246 
247  /// Deleting a vector from the data array and the list.
248  void deleteVec(DLPSV* ps)
249  {
250  /* delete last entries */
251  if( ps == list.last() )
252  {
253  SVSetBaseArray::removeLast(ps->max());
254 
255  // decrease counter of unused memory
256 #ifdef SOPLEX_DEBUG
257  MSG_DEBUG( std::cout << "deleteVec (1), this = " << (void*)this << ": updateUnusedMemEstimation -= " << ps->max() - ps->size() << "\n" );
258 #endif
259  updateUnusedMemEstimation(ps->size() - ps->max());
260  }
261  /* merge space of predecessor with position which will be deleted, therefore we do not need to delete any memory
262  * or do an expensive memory reallocation
263  */
264  else if( ps != list.first() )
265  {
266  SVectorBase<R>* prev = ps->prev();
267  int sz = prev->size();
268 
269  prev->setMem(prev->max() + ps->max(), prev->mem());
270  prev->set_size(sz);
271 
272  // increase counter of unused memory
273 #ifdef SOPLEX_DEBUG
274  MSG_DEBUG( std::cout << "deleteVec (2), this = " << (void*)this << ": updateUnusedMemEstimation += " << ps->size() << "\n" );
275 #endif
276  updateUnusedMemEstimation(ps->size());
277  }
278  /* simply remove the front entries; we do not shift the second vector to the front, because we count the unused
279  * memory exactly and rely on the automatic call of memPack()
280  */
281  else
282  {
283  // increase counter of unused memory
284 #ifdef SOPLEX_DEBUG
285  MSG_DEBUG( std::cout << "deleteVec (3), this = " << (void*)this << ": updateUnusedMemEstimation += " << ps->size() << "\n" );
286 #endif
287  updateUnusedMemEstimation(ps->size());
288  }
289 
290  list.remove(ps);
291  }
292 
293  //@}
294 
295 public:
296 
297  // ------------------------------------------------------------------------------------------------------------------
298  /**@name Extension */
299  //@{
300 
301  /// Adds \p svec to the %set.
302  /** This includes copying its nonzeros to the sets nonzero memory and creating an additional SVectorBase entry in
303  * vector memory. If neccessary, the memory blocks are enlarged appropriately.
304  */
305  void add(const SVectorBase<R>& svec)
306  {
307  // create empty vector
308  ensurePSVec(1);
309  SVectorBase<R>* new_svec = create(svec.size());
310 
311  // assign values
312  *new_svec = svec;
313  }
314 
315  /// Adds \p svec to SVSetBase.
316  /** Adds SVectorBase \p svec to the %set. This includes copying its nonzeros to the sets nonzero memory and creating
317  * an additional SVectorBase entry in vector memory. If neccessary, the memory blocks are enlarged appropriately.
318  *
319  * @return \p nkey contains the DataKey, that the SVSetBase has assosicated to the new SVectorBase.
320  */
321  void add(DataKey& nkey, const SVectorBase<R>& svec)
322  {
323  // create empty vector
324  ensurePSVec(1);
325  SVectorBase<R>* new_svec = create(nkey, svec.size());
326 
327  // assign values
328  *new_svec = svec;
329  }
330 
331  /// Adds \p svec to SVSetBase.
332  /** Adds SVectorBase \p svec to the %set. This includes copying its nonzeros to the sets nonzero memory and creating
333  * an additional SVectorBase entry in vector memory. If neccessary, the memory blocks are enlarged appropriately.
334  *
335  * @return \p nkey contains the DataKey, that the SVSetBase has assosicated to the new SVectorBase.
336  */
337  template < class S >
338  void add(DataKey& nkey, const S* rowValues, const int* rowIndices, int rowSize)
339  {
340  assert(rowSize <= 0 || rowIndices != 0);
341  assert(rowSize <= 0 || rowValues != 0);
342 
343  // create empty vector
344  ensurePSVec(1);
345  SVectorBase<R>* new_svec = create(nkey, rowSize);
346 
347  // assign values
348  if( rowSize > 0 )
349  new_svec->assignArray(rowValues, rowIndices, rowSize);
350  }
351 
352  /// Adds all \p n SVectorBase%s in the array \p svec to the %set.
353  /** @pre \p svec must hold at least \p n entries.
354  */
355  void add(const SVectorBase<R> svec[], int n)
356  {
357  assert(n >= 0);
358 
359  int i;
360  int len;
361 
362  for( i = len = 0; i < n; ++i )
363  len += svec[i].size();
364 
365  ensurePSVec(n);
366  ensureMem(len);
367 
368  for( i = 0; i < n; ++i )
369  *create(svec[i].size()) = svec[i];
370  }
371 
372  /// Adds n SVectorBase%s to SVSetBase.
373  /** Adds all \p n SVectorBase%s in the array \p svec to the %set.
374  *
375  * @return \p nkey contains the DataKey%s, that the SVSetBase has assosicated to the new SVectorBase%s.
376  *
377  * @pre \p nkey must be large enough to fit \p n DataKey%s.
378  */
379  void add(DataKey nkey[], const SVectorBase<R> svec[], int n)
380  {
381  add(svec, n);
382 
383  for( int i = num() - 1; --n; --i )
384  nkey[n] = key(i);
385  }
386 
387  /// Adds all SVectorBase%s in \p pset to SVSetBase.
388  template < class S >
389  void add(const SVSetBase<S>& pset)
390  {
391  int i;
392  int n;
393  int len;
394 
395  n = pset.num();
396  for( i = len = 0; i < n; ++i )
397  len += pset[i].size();
398 
399  ensurePSVec(n);
400  ensureMem(len);
401 
402  for( i = 0; i < n; ++i )
403  *create(pset[i].size()) = pset[i];
404  }
405 
406  /// Adds all SVectorBase%s of \p pset to SVSetBase.
407  /** Adds all \p n SVectorBase%s in the \p pset to an SVSetBase.
408  *
409  * @return \p nkey contains the DataKey%s, that the SVSetBase has assosicated to the new SVectorBase%s.
410  *
411  * @pre \p nkey must be large enough to fit \p pset.num() DataKey%s.
412  */
413  template < class S >
414  void add(DataKey nkey[], const SVSetBase<S>& pset)
415  {
416  add(pset);
417 
418  int i = num();
419  int n = pset.num();
420 
421  while( n > 0 )
422  nkey[--n] = key(--i);
423  }
424 
425  /// Creates new SVectorBase in %set.
426  /** The new SVectorBase will be ready to fit at least \p idxmax nonzeros.
427  */
428  SVectorBase<R>* create(int idxmax = 0)
429  {
430  DLPSV* ps;
431 
432  if( idxmax < 0 )
433  idxmax = 0;
434 
435  if( memSize() == 0 && idxmax <= 0 )
436  idxmax = 1;
437 
438  ensureMem(idxmax);
439 
440  // resize the data array
441 #ifndef NDEBUG
442  Nonzero<R>* olddata = SVSetBaseArray::data;
443  SVSetBaseArray::reSize(memSize() + idxmax);
444  assert(olddata == SVSetBaseArray::data);
445 #else
446  SVSetBaseArray::reSize(memSize() + idxmax);
447 #endif
448 
449  ensurePSVec(1);
450  ps = set.create();
451  list.append(ps);
452 
453  ps->setMem(idxmax, &SVSetBaseArray::last() - idxmax + 1);
454 
455  return ps;
456  }
457 
458  /// Creates new SVectorBase in %set.
459  /** The new SVectorBase will be ready to fit at least \p idxmax nonzeros.
460  *
461  * @return \p nkey contains the DataKey associated to the new SVectorBase.
462  */
463  SVectorBase<R>* create(DataKey& nkey, int idxmax = -1)
464  {
465  SVectorBase<R>* ps = create(idxmax);
466 
467  nkey = key(num() - 1);
468 
469  return ps;
470  }
471 
472  /// Extends \p svec to fit \p newmax nonzeros.
473  /** @pre \p svec must be an SVectorBase of the SVSetBase.
474  */
475  void xtend(SVectorBase<R>& svec, int newmax)
476  {
477  if( svec.max() < newmax )
478  {
479  assert(has(&svec));
480 
481  DLPSV* ps = static_cast<DLPSV*>(&svec);
482  int sz = ps->size();
483 
484  if( ps == list.last() )
485  {
486  // because we want to extend the last vector we must not shrink its max memory usage
487  // in order to ensure the missing memory
488  ensureMem(newmax - ps->max(), false);
489 #ifndef NDEBUG
490  Nonzero<R>* olddata = SVSetBaseArray::data;
491  SVSetBaseArray::insert(memSize(), newmax - ps->max());
492  assert(olddata == SVSetBaseArray::data);
493 #else
494  SVSetBaseArray::insert(memSize(), newmax - ps->max());
495 #endif
496 
497  // decrease counter of unused memory (assume that new entries will be used)
498 #ifdef SOPLEX_DEBUG
499  MSG_DEBUG( std::cout << "xtend (1), this = " << (void*)this << ": updateUnusedMemEstimation -= " << ps->max() - sz << "\n" );
500 #endif
501  updateUnusedMemEstimation(sz - ps->max());
502 
503  ps->setMem(newmax, ps->mem());
504  ps->set_size(sz);
505  }
506  else
507  {
508  ensureMem(newmax);
509  SVectorBase<R> newps(newmax, &SVSetBaseArray::last() + 1);
510 #ifndef NDEBUG
511  Nonzero<R>* olddata = SVSetBaseArray::data;
512  SVSetBaseArray::insert(memSize(), newmax);
513  assert(olddata == SVSetBaseArray::data);
514 #else
515  SVSetBaseArray::insert(memSize(), newmax);
516 #endif
517 
518  newps = svec;
519 
520  if( ps != list.first() )
521  {
522  SVectorBase<R>* prev = ps->prev();
523  int prevsz = prev->size();
524  prev->setMem(prev->max() + ps->max(), prev->mem());
525  prev->set_size(prevsz);
526  }
527 
528  // increase counter of unused memory (assume that new entries will be used)
529 #ifdef SOPLEX_DEBUG
530  MSG_DEBUG( std::cout << "xtend (2), this = " << (void*)this << ": updateUnusedMemEstimation += " << ps->size() << "\n" );
531 #endif
532  updateUnusedMemEstimation(ps->size());
533 
534  list.remove(ps);
535  list.append(ps);
536 
537  ps->setMem(newmax, newps.mem());
538  ps->set_size(sz);
539  }
540  }
541  }
542 
543  /// Adds nonzero (\p idx, \p val) to \p svec of this SVSetBase.
544  /** Adds one nonzero (\p idx, \p val) to SVectorBase \p svec in the SVSetBase. If \p svec is not large enough to
545  * hold the additional nonzero, it will be automatically enlarged within the %set.
546  *
547  * @pre \p svec must be an SVectorBase of the SVSetBase.
548  */
549  void add2(SVectorBase<R> &svec, int idx, R val)
550  {
551  xtend(svec, svec.size() + 1);
552  svec.add(idx, val);
553  }
554 
555  /// Adds \p n nonzeros to \p svec of this SVSetBase.
556  /** Adds \p n nonzeros to SVectorBase \p svec in the SVSetBase. If \p svec is not large enough to hold the additional
557  * nonzeros, it will be automatically enlarged within the %set.
558  *
559  * @pre \p svec must be an SVectorBase of the SVSetBase.
560  */
561  void add2(SVectorBase<R> &svec, int n, const int idx[], const R val[])
562  {
563  xtend(svec, svec.size() + n);
564  svec.add(n, idx, val);
565  }
566 
567  /// Adds \p n nonzeros to \p svec of this SVSetBase.
568  /** Adds \p n nonzeros to SVectorBase \p svec in the SVSetBase. If \p svec is not large enough to hold the additional
569  * nonzeros, it will be automatically enlarged within the %set.
570  *
571  * @pre \p svec must be an SVectorBase of the SVSetBase.
572  */
573  template < class S >
574  void add2(SVectorBase<R> &svec, int n, const int idx[], const S val[])
575  {
576  xtend(svec, svec.size() + n);
577  svec.add(n, idx, val);
578  }
579 
580  //@}
581 
582  // ------------------------------------------------------------------------------------------------------------------
583  /**@name Shrinking */
584  //@{
585 
586  /// Removes the vector with key \p removekey from the %set.
587  /** @pre \p removekey must be a key from SVSetBase
588  */
589  void remove(const DataKey& removekey)
590  {
591  deleteVec(&set[removekey]);
592  set.remove(removekey);
593  }
594 
595  /// Removes the vector with number \p removenum from the %set.
596  /** @pre \p removenum must be a valid vector number from SVSetBase
597  */
598  void remove(int removenum)
599  {
600  remove(key(removenum));
601  }
602 
603  /// Removes one SVectorBase from %set.
604  /** @pre \p svec must be from SVSetBase
605  */
606  void remove(const SVectorBase<R> *svec)
607  {
608  remove(key(svec));
609  }
610 
611  /// Removes multiple elements.
612  /** Removes all SVectorBase%s for the SVSetBase with an index \c i such that \p perm[i] < 0. Upon completion, \p
613  * perm[i] >= 0 indicates the new index where the \c i 'th SVectorBase has been moved to due to this removal.
614  *
615  * @pre \p perm must point to an array of at least num() integers.
616  */
617  void remove(int perm[])
618  {
619  int j = num();
620 
621  /* due to performance reasons we use a backwards loop to delete entries, because it could result instead of only
622  * decreasing the number of elements j times in memmoving the whole array j times
623  */
624  for( int i = j - 1; i >= 0; --i )
625  {
626  if( perm[i] < 0 )
627  {
628  deleteVec(&set[i]);
629  }
630  }
631 
632  set.remove(perm);
633  }
634 
635  /// Removes \p n SVectorBase%s from %set.
636  /** @pre \p keys must be at least of size \p n and valid keys
637  */
638  void remove(const DataKey keys[], int n)
639  {
640  DataArray < int > perm(num());
641  remove(keys, n, perm.get_ptr());
642  }
643 
644  /// Removes \p n SVectorBase%s from %set.
645  /** @pre \p nums must be at least of size \p n and valid vector numbers
646  */
647  void remove(const int nums[], int n)
648  {
649  DataArray < int > perm(num());
650  remove(nums, n, perm.get_ptr());
651  }
652 
653  ///
654  void remove(const DataKey keys[], int n, int* perm)
655  {
656  for( int i = num() - 1; i >= 0; --i )
657  perm[i] = i;
658 
659  while( n-- )
660  perm[number(*keys++)] = -1;
661 
662  remove(perm);
663  }
664 
665  /** Removes \p n SVectorBase%s from %set.
666  * @pre \p nums must be at least of size \p n
667  * @pre \p perm must be at least of size num()
668  * @return \p perm is the permutations resulting from this removal: \p perm[i] < 0 indicates
669  * that the element to index \p i has been removed. Otherwise, \p perm[i] is the new
670  * index of the element with index \p i before the removal.
671  */
672  void remove(const int nums[], int n, int* perm)
673  {
674  for( int i = num() - 1; i >= 0; --i )
675  perm[i] = i;
676 
677  while( n-- )
678  perm[*nums++] = -1;
679 
680  remove(perm);
681  }
682 
683  /// Removes all SVectorBase%s from %set.
684  void clear(int minNewSize = -1)
685  {
687 
688  if( minNewSize <= 0 )
689  {
690  if( SVSetBaseArray::max() > 10000 )
691  SVSetBaseArray::reMax(10000);
692  }
693  else
694  {
695  if( SVSetBaseArray::max() > minNewSize + 10000 )
696  SVSetBaseArray::reMax(minNewSize);
697  }
698 
699  set.clear();
700  list.clear();
701  unusedMem = 0;
703  }
704 
705  //@}
706 
707  // ------------------------------------------------------------------------------------------------------------------
708  /**@name Access */
709  //@{
710 
711  /// Gets SVectorBase by number, writeable.
713  {
714  return set[n];
715  }
716 
717  /// Gets SVectorBase by number.
718  const SVectorBase<R>& operator[](int n) const
719  {
720  return set[n];
721  }
722 
723  /// Gets SVectorBase by DataKey, writeable.
725  {
726  return set[k];
727  }
728 
729  /// Gets SVectorBase by DataKey.
730  const SVectorBase<R>& operator[](const DataKey& k) const
731  {
732  return set[k];
733  }
734 
735  //@}
736 
737  // ------------------------------------------------------------------------------------------------------------------
738  /**@name Inquiry */
739  //@{
740 
741  /// Current number of SVectorBase%s.
742  int num() const
743  {
744  return set.num();
745  }
746 
747  /// Current maximum number of SVectorBase%s.
748  int max() const
749  {
750  return set.max();
751  }
752 
753  /// Gets DataKey of vector number.
754  DataKey key(int n) const
755  {
756  return set.key(n);
757  }
758 
759  /// Gets DataKey of SVectorBase.
760  DataKey key(const SVectorBase<R>* svec) const
761  {
762  return set.key(static_cast<const DLPSV*>(svec));
763  }
764 
765  /// Gets vector number of DataKey.
766  int number(const DataKey& k) const
767  {
768  return set.number(k);
769  }
770 
771  /// Gets vector number of SVectorBase.
772  int number(const SVectorBase<R>* svec) const
773  {
774  return set.number(static_cast<const DLPSV*>(svec));
775  }
776 
777  /// True iff SVSetBase contains a SVectorBase for DataKey \p k.
778  bool has(const DataKey& k) const
779  {
780  return set.has(k);
781  }
782 
783  /// True iff SVSetBase contains a SVectorBase for vector number n.
784  bool has(int n) const
785  {
786  return set.has(n);
787  }
788 
789  /// Is an SVectorBase in the %set?
790  bool has(const SVectorBase<R>* svec) const
791  {
792  return set.has(static_cast<const DLPSV*>(svec));
793  }
794 
795  //@}
796 
797  // ------------------------------------------------------------------------------------------------------------------
798  /**@name Memory Management */
799  //@{
800 
801  /// Used nonzero memory.
802  int memSize() const
803  {
804  return SVSetBaseArray::size();
805  }
806 
807  /// Length of nonzero memory.
808  int memMax() const
809  {
810  return SVSetBaseArray::max();
811  }
812 
813  /// Reset length of nonzero memory.
814  void memRemax(int newmax)
815  {
816  ptrdiff_t delta = SVSetBaseArray::reMax(newmax);
817 
818  if( delta != 0 )
819  {
820 #ifdef SOPLEX_DEBUG
821  MSG_DEBUG( std::cout << "counting unused memory (unusedMem = " << unusedMem << ", numUnusedMemUpdates = " << numUnusedMemUpdates << ", this = " << (void*)this << ")\n" );
822 #endif
823 
824  int used = 0;
825  for( DLPSV* ps = list.first(); ps; ps = list.next(ps) )
826  {
827  // get new shifted nonzero memory of the SVectorBase
828  Nonzero<R>* newmem = reinterpret_cast<Nonzero<R>*>(reinterpret_cast<char*>(ps->mem()) + delta);
829 
830  // get the size and maximum capacity of the SVectorBase
831  int sz = ps->size();
832  int l_max = ps->max();
833  assert(l_max >= sz);
834 
835  // set new nonzero memory
836  ps->setMem(l_max, newmem);
837  ps->set_size(sz);
838 
839  // count used memory
840  used += sz;
841  }
842 
843  // update estimation of unused memory to exact value
844  unusedMem = memSize() - used;
846 
847 #ifdef SOPLEX_DEBUG
848  MSG_DEBUG( std::cout << " --> NEW: unusedMem = " << unusedMem << " after memRemax(" << newmax << ")\n" );
849 #endif
850  }
851  }
852 
853  /// Garbage collection in nonzero memory.
854  /** Pack the svectors together as tightly as possible. This removes all additional unused memory, i.e., size = max
855  * for every svector after the call.
856  *
857  * Note: do *not* call isConsistent() here, because the following might happen: In SPxLP::doAddRows(const LPRowSet&
858  * p_set), when adding rows, the sizes of the vectors for the columns of the LP are increased (without yet filling
859  * in the data) to recieve the additional entries. This is done by calling xtend() above. xtend() in turn might call
860  * this method, which checks the yet unfilled positions, i.e., isConsistent() is likely to fail. In general,
861  * isConsistent() should not be called within this class, but in classes further up in the hierarchy.
862  */
863  void memPack()
864  {
865  DLPSV* ps;
866  int used;
867  int j;
868 
869  for( used = 0, ps = list.first(); ps; ps = list.next(ps) )
870  {
871  const int sz = ps->size();
872 
873  if( ps->mem() != &this->SVSetBaseArray::operator[](used) )
874  {
875  // cannot use memcpy, because the memory might overlap
876  for( j = 0; j < sz; ++j )
877  this->SVSetBaseArray::operator[](used + j) = ps->mem()[j];
878 
879  ps->setMem(sz, &this->SVSetBaseArray::operator[](used));
880  ps->set_size(sz);
881  }
882  else
883  ps->set_max(sz);
884 
885  used += sz;
886  }
887 
888 #ifdef SOPLEX_DEBUG
889  MSG_DEBUG( std::cout << "counting unused memory (unusedMem = " << unusedMem << ", numUnusedMemUpdates = " << numUnusedMemUpdates << ", this = " << (void*)this << ")\n" );
890  MSG_DEBUG( std::cout << " --> NEW: unusedMem = " << memSize() - used << ", zero after memPack() at memMax() = "<< memMax() << "\n" );
891 #endif
892 #ifndef NDEBUG
893  Nonzero<R>* olddata = SVSetBaseArray::data;
895  assert(olddata == SVSetBaseArray::data);
896 #else
898 #endif
899 
900  unusedMem = 0;
902  }
903 
904  //@}
905 
906  // ------------------------------------------------------------------------------------------------------------------
907  /**@name Miscellaneous */
908  //@{
909 
910  /// Resets maximum number of SVectorBase%s.
911  void reMax(int newmax = 0)
912  {
913  list.move(set.reMax(newmax));
914  }
915 
916  /// Consistency check.
917  bool isConsistent() const
918  {
919 #ifdef ENABLE_CONSISTENCY_CHECKS
920  DLPSV* ps;
921  DLPSV* next;
922 
923  for( ps = list.first(); ps; ps = next )
924  {
925  if( !ps->isConsistent() )
926  return MSGinconsistent("SVSetBase");
927 
928  if( ps->mem() > &SVSetBaseArray::last() )
929  return MSGinconsistent("SVSetBase");
930 
931  next = list.next(ps);
932 
933  if( next && ps->mem() + ps->max() != next->mem() )
934  return MSGinconsistent("SVSetBase");
935  }
936 
937  return SVSetBaseArray::isConsistent() && set.isConsistent() && list.isConsistent();
938 #else
939  return true;
940 #endif
941  }
942 
943  //@}
944 
945  // ------------------------------------------------------------------------------------------------------------------
946  /**@name Constructors / destructors */
947  //@{
948 
949  /// Default constructor.
950  explicit
951  SVSetBase<R>(int pmax = -1, int pmemmax = -1, double pfac = 1.1, double pmemFac = 1.2)
952  : SVSetBaseArray(0, (pmemmax > 0) ? pmemmax : 8 * ((pmax > 0) ? pmax : 8), pmemFac)
953  , set((pmax > 0) ? pmax : 8)
954  , unusedMem(0)
956  , factor(pfac)
957  {
958  assert(isConsistent());
959  }
960 
961  /// Destructor
962  virtual ~SVSetBase<R>()
963  {}
964 
965  /// Assignment operator.
967  {
968  if( this != &rhs )
969  {
970  clear(rhs.size());
971 
972  if( rhs.size() > 0 )
973  {
975  set = rhs.set;
976 
977  DLPSV* ps;
978  DLPSV* newps;
979 
980  void* delta0 = &(*(static_cast<SVSetBaseArray*>(this)))[0];
981  void* delta1 = &(*(static_cast<SVSetBaseArray*>(const_cast<SVSetBase<R>*>(&rhs))))[0];
982  ptrdiff_t delta = reinterpret_cast<char*>(delta0) - reinterpret_cast<char*>(delta1);
983 
984  for( ps = rhs.list.first(); ps; ps = rhs.list.next(ps) )
985  {
986  newps = &set[rhs.number(ps)];
987  list.append(newps);
988  newps->setMem(ps->max(),
989  reinterpret_cast<Nonzero<R>*>(reinterpret_cast<char*>(ps->mem()) + delta));
990  newps->set_size(ps->size());
991  }
992  }
993  }
994 
995  assert(isConsistent());
996 
997  return *this;
998  }
999 
1000  /// Assignment operator.
1001  template < class S >
1003  {
1004  if( this != (const SVSetBase<R>*)(&rhs) )
1005  {
1006  clear(rhs.size());
1007 
1008  if( rhs.size() > 0 )
1009  this->add(rhs);
1010  }
1011 
1012  assert(isConsistent());
1013 
1014  return *this;
1015  }
1016 
1017  /// Copy constructor.
1019  : SVSetBaseArray()
1020  , unusedMem(old.unusedMem)
1021  , numUnusedMemUpdates(old.numUnusedMemUpdates)
1022  , factor(old.factor)
1023  {
1024  *this = old;
1025 
1026  assert(SVSetBase::isConsistent());
1027  }
1028 
1029  /// Copy constructor.
1030  template < class S >
1032  : SVSetBaseArray()
1033  , unusedMem(old.unusedMem)
1034  , numUnusedMemUpdates(old.numUnusedMemUpdates)
1035  , factor(old.factor)
1036  {
1037  *this = old;
1038 
1039  assert(SVSetBase::isConsistent());
1040  }
1041 
1042  //@}
1043 };
1044 
1045 } // namespace soplex
1046 
1047 /* reset the SOPLEX_DEBUG flag to its original value */
1048 #undef SOPLEX_DEBUG
1049 #ifdef SOPLEX_DEBUG_SVSETBASE
1050 #define SOPLEX_DEBUG
1051 #undef SOPLEX_DEBUG_SVSETBASE
1052 #endif
1053 
1054 #endif // _SVSETBASE_H_