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-2017 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 referred to as the \em nonzero \em memory. The SVectorBase%s
45  * themselves are saved in another memory block referred 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 
177  numUnusedMemUpdates = 0;
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;
188  numUnusedMemUpdates++;
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(0,0);
510  if( SVSetBaseArray::size() > 0 )
511  newps.setMem(newmax, &SVSetBaseArray::last() + 1);
512  else
513  newps.setMem(newmax, SVSetBaseArray::get_ptr());
514 #ifndef NDEBUG
515  Nonzero<R>* olddata = SVSetBaseArray::data;
516  SVSetBaseArray::insert(memSize(), newmax);
517  assert(olddata == SVSetBaseArray::data);
518 #else
519  SVSetBaseArray::insert(memSize(), newmax);
520 #endif
521 
522  newps = svec;
523 
524  if( ps != list.first() )
525  {
526  SVectorBase<R>* prev = ps->prev();
527  int prevsz = prev->size();
528  prev->setMem(prev->max() + ps->max(), prev->mem());
529  prev->set_size(prevsz);
530  }
531 
532  // increase counter of unused memory (assume that new entries will be used)
533 #ifdef SOPLEX_DEBUG
534  MSG_DEBUG( std::cout << "xtend (2), this = " << (void*)this << ": updateUnusedMemEstimation += " << ps->size() << "\n" );
535 #endif
536  updateUnusedMemEstimation(ps->size());
537 
538  list.remove(ps);
539  list.append(ps);
540 
541  ps->setMem(newmax, newps.mem());
542  ps->set_size(sz);
543  }
544  }
545  }
546 
547  /// Adds nonzero (\p idx, \p val) to \p svec of this SVSetBase.
548  /** Adds one nonzero (\p idx, \p val) to SVectorBase \p svec in the SVSetBase. If \p svec is not large enough to
549  * hold the additional nonzero, it will be automatically enlarged within the %set.
550  *
551  * @pre \p svec must be an SVectorBase of the SVSetBase.
552  */
553  void add2(SVectorBase<R> &svec, int idx, R val)
554  {
555  xtend(svec, svec.size() + 1);
556  svec.add(idx, val);
557  }
558 
559  /// Adds \p n nonzeros to \p svec of this SVSetBase.
560  /** Adds \p n nonzeros to SVectorBase \p svec in the SVSetBase. If \p svec is not large enough to hold the additional
561  * nonzeros, it will be automatically enlarged within the %set.
562  *
563  * @pre \p svec must be an SVectorBase of the SVSetBase.
564  */
565  void add2(SVectorBase<R> &svec, int n, const int idx[], const R val[])
566  {
567  xtend(svec, svec.size() + n);
568  svec.add(n, idx, val);
569  }
570 
571  /// Adds \p n nonzeros to \p svec of this SVSetBase.
572  /** Adds \p n nonzeros to SVectorBase \p svec in the SVSetBase. If \p svec is not large enough to hold the additional
573  * nonzeros, it will be automatically enlarged within the %set.
574  *
575  * @pre \p svec must be an SVectorBase of the SVSetBase.
576  */
577  template < class S >
578  void add2(SVectorBase<R> &svec, int n, const int idx[], const S val[])
579  {
580  xtend(svec, svec.size() + n);
581  svec.add(n, idx, val);
582  }
583 
584  //@}
585 
586  // ------------------------------------------------------------------------------------------------------------------
587  /**@name Shrinking */
588  //@{
589 
590  /// Removes the vector with key \p removekey from the %set.
591  /** @pre \p removekey must be a key from SVSetBase
592  */
593  void remove(const DataKey& removekey)
594  {
595  deleteVec(&set[removekey]);
596  set.remove(removekey);
597  }
598 
599  /// Removes the vector with number \p removenum from the %set.
600  /** @pre \p removenum must be a valid vector number from SVSetBase
601  */
602  void remove(int removenum)
603  {
604  remove(key(removenum));
605  }
606 
607  /// Removes one SVectorBase from %set.
608  /** @pre \p svec must be from SVSetBase
609  */
610  void remove(const SVectorBase<R> *svec)
611  {
612  remove(key(svec));
613  }
614 
615  /// Removes multiple elements.
616  /** Removes all SVectorBase%s for the SVSetBase with an index \c i such that \p perm[i] < 0. Upon completion, \p
617  * perm[i] >= 0 indicates the new index where the \c i 'th SVectorBase has been moved to due to this removal.
618  *
619  * @pre \p perm must point to an array of at least num() integers.
620  */
621  void remove(int perm[])
622  {
623  int j = num();
624 
625  /* due to performance reasons we use a backwards loop to delete entries, because it could result instead of only
626  * decreasing the number of elements j times in memmoving the whole array j times
627  */
628  for( int i = j - 1; i >= 0; --i )
629  {
630  if( perm[i] < 0 )
631  {
632  deleteVec(&set[i]);
633  }
634  }
635 
636  set.remove(perm);
637  }
638 
639  /// Removes \p n SVectorBase%s from %set.
640  /** @pre \p keys must be at least of size \p n and valid keys
641  */
642  void remove(const DataKey keys[], int n)
643  {
644  DataArray < int > perm(num());
645  remove(keys, n, perm.get_ptr());
646  }
647 
648  /// Removes \p n SVectorBase%s from %set.
649  /** @pre \p nums must be at least of size \p n and valid vector numbers
650  */
651  void remove(const int nums[], int n)
652  {
653  DataArray < int > perm(num());
654  remove(nums, n, perm.get_ptr());
655  }
656 
657  ///
658  void remove(const DataKey keys[], int n, int* perm)
659  {
660  for( int i = num() - 1; i >= 0; --i )
661  perm[i] = i;
662 
663  while( n-- )
664  perm[number(*keys++)] = -1;
665 
666  remove(perm);
667  }
668 
669  /** Removes \p n SVectorBase%s from %set.
670  * @pre \p nums must be at least of size \p n
671  * @pre \p perm must be at least of size num()
672  * @return \p perm is the permutations resulting from this removal: \p perm[i] < 0 indicates
673  * that the element to index \p i has been removed. Otherwise, \p perm[i] is the new
674  * index of the element with index \p i before the removal.
675  */
676  void remove(const int nums[], int n, int* perm)
677  {
678  for( int i = num() - 1; i >= 0; --i )
679  perm[i] = i;
680 
681  while( n-- )
682  perm[*nums++] = -1;
683 
684  remove(perm);
685  }
686 
687  /// Removes all SVectorBase%s from %set.
688  void clear(int minNewSize = -1)
689  {
691 
692  if( minNewSize <= 0 )
693  {
694  if( SVSetBaseArray::max() > 10000 )
695  SVSetBaseArray::reMax(10000);
696  }
697  else
698  {
699  if( SVSetBaseArray::max() > minNewSize + 10000 )
700  SVSetBaseArray::reMax(minNewSize);
701  }
702 
703  set.clear();
704  list.clear();
705  unusedMem = 0;
706  numUnusedMemUpdates = 0;
707  }
708 
709  //@}
710 
711  // ------------------------------------------------------------------------------------------------------------------
712  /**@name Access */
713  //@{
714 
715  /// Gets SVectorBase by number, writeable.
717  {
718  return set[n];
719  }
720 
721  /// Gets SVectorBase by number.
722  const SVectorBase<R>& operator[](int n) const
723  {
724  return set[n];
725  }
726 
727  /// Gets SVectorBase by DataKey, writeable.
729  {
730  return set[k];
731  }
732 
733  /// Gets SVectorBase by DataKey.
734  const SVectorBase<R>& operator[](const DataKey& k) const
735  {
736  return set[k];
737  }
738 
739  //@}
740 
741  // ------------------------------------------------------------------------------------------------------------------
742  /**@name Inquiry */
743  //@{
744 
745  /// Current number of SVectorBase%s.
746  int num() const
747  {
748  return set.num();
749  }
750 
751  /// Current maximum number of SVectorBase%s.
752  int max() const
753  {
754  return set.max();
755  }
756 
757  /// Gets DataKey of vector number.
758  DataKey key(int n) const
759  {
760  return set.key(n);
761  }
762 
763  /// Gets DataKey of SVectorBase.
764  DataKey key(const SVectorBase<R>* svec) const
765  {
766  return set.key(static_cast<const DLPSV*>(svec));
767  }
768 
769  /// Gets vector number of DataKey.
770  int number(const DataKey& k) const
771  {
772  return set.number(k);
773  }
774 
775  /// Gets vector number of SVectorBase.
776  int number(const SVectorBase<R>* svec) const
777  {
778  return set.number(static_cast<const DLPSV*>(svec));
779  }
780 
781  /// True iff SVSetBase contains a SVectorBase for DataKey \p k.
782  bool has(const DataKey& k) const
783  {
784  return set.has(k);
785  }
786 
787  /// True iff SVSetBase contains a SVectorBase for vector number n.
788  bool has(int n) const
789  {
790  return set.has(n);
791  }
792 
793  /// Is an SVectorBase in the %set?
794  bool has(const SVectorBase<R>* svec) const
795  {
796  return set.has(static_cast<const DLPSV*>(svec));
797  }
798 
799  //@}
800 
801  // ------------------------------------------------------------------------------------------------------------------
802  /**@name Memory Management */
803  //@{
804 
805  /// Used nonzero memory.
806  int memSize() const
807  {
808  return SVSetBaseArray::size();
809  }
810 
811  /// Length of nonzero memory.
812  int memMax() const
813  {
814  return SVSetBaseArray::max();
815  }
816 
817  /// Reset length of nonzero memory.
818  void memRemax(int newmax)
819  {
820  ptrdiff_t delta = SVSetBaseArray::reMax(newmax);
821 
822  if( delta != 0 )
823  {
824 #ifdef SOPLEX_DEBUG
825  MSG_DEBUG( std::cout << "counting unused memory (unusedMem = " << unusedMem << ", numUnusedMemUpdates = " << numUnusedMemUpdates << ", this = " << (void*)this << ")\n" );
826 #endif
827 
828  int used = 0;
829  for( DLPSV* ps = list.first(); ps; ps = list.next(ps) )
830  {
831  // get new shifted nonzero memory of the SVectorBase
832  Nonzero<R>* newmem = reinterpret_cast<Nonzero<R>*>(reinterpret_cast<char*>(ps->mem()) + delta);
833 
834  // get the size and maximum capacity of the SVectorBase
835  int sz = ps->size();
836  int l_max = ps->max();
837  assert(l_max >= sz);
838 
839  // set new nonzero memory
840  ps->setMem(l_max, newmem);
841  ps->set_size(sz);
842 
843  // count used memory
844  used += sz;
845  }
846 
847  // update estimation of unused memory to exact value
848  unusedMem = memSize() - used;
849  numUnusedMemUpdates = 0;
850 
851 #ifdef SOPLEX_DEBUG
852  MSG_DEBUG( std::cout << " --> NEW: unusedMem = " << unusedMem << " after memRemax(" << newmax << ")\n" );
853 #endif
854  }
855  }
856 
857  /// Garbage collection in nonzero memory.
858  /** Pack the svectors together as tightly as possible. This removes all additional unused memory, i.e., size = max
859  * for every svector after the call.
860  *
861  * Note: do *not* call isConsistent() here, because the following might happen: In SPxLP::doAddRows(const LPRowSet&
862  * p_set), when adding rows, the sizes of the vectors for the columns of the LP are increased (without yet filling
863  * in the data) to recieve the additional entries. This is done by calling xtend() above. xtend() in turn might call
864  * this method, which checks the yet unfilled positions, i.e., isConsistent() is likely to fail. In general,
865  * isConsistent() should not be called within this class, but in classes further up in the hierarchy.
866  */
867  void memPack()
868  {
869  DLPSV* ps;
870  int used;
871  int j;
872 
873  for( used = 0, ps = list.first(); ps; ps = list.next(ps) )
874  {
875  const int sz = ps->size();
876 
877  if( ps->mem() != &this->SVSetBaseArray::operator[](used) )
878  {
879  // cannot use memcpy, because the memory might overlap
880  for( j = 0; j < sz; ++j )
881  this->SVSetBaseArray::operator[](used + j) = ps->mem()[j];
882 
883  ps->setMem(sz, &this->SVSetBaseArray::operator[](used));
884  ps->set_size(sz);
885  }
886  else
887  ps->set_max(sz);
888 
889  used += sz;
890  }
891 
892 #ifdef SOPLEX_DEBUG
893  MSG_DEBUG( std::cout << "counting unused memory (unusedMem = " << unusedMem << ", numUnusedMemUpdates = " << numUnusedMemUpdates << ", this = " << (void*)this << ")\n" );
894  MSG_DEBUG( std::cout << " --> NEW: unusedMem = " << memSize() - used << ", zero after memPack() at memMax() = "<< memMax() << "\n" );
895 #endif
896 #ifndef NDEBUG
897  Nonzero<R>* olddata = SVSetBaseArray::data;
899  assert(olddata == SVSetBaseArray::data);
900 #else
902 #endif
903 
904  unusedMem = 0;
905  numUnusedMemUpdates = 0;
906  }
907 
908  //@}
909 
910  // ------------------------------------------------------------------------------------------------------------------
911  /**@name Miscellaneous */
912  //@{
913 
914  /// Resets maximum number of SVectorBase%s.
915  void reMax(int newmax = 0)
916  {
917  list.move(set.reMax(newmax));
918  }
919 
920  /// Consistency check.
921  bool isConsistent() const
922  {
923 #ifdef ENABLE_CONSISTENCY_CHECKS
924  DLPSV* ps;
925  DLPSV* next;
926 
927  for( ps = list.first(); ps; ps = next )
928  {
929  if( !ps->isConsistent() )
930  return MSGinconsistent("SVSetBase");
931 
932  if( ps->mem() > &SVSetBaseArray::last() )
933  return MSGinconsistent("SVSetBase");
934 
935  next = list.next(ps);
936 
937  if( next && ps->mem() + ps->max() != next->mem() )
938  return MSGinconsistent("SVSetBase");
939  }
940 
941  return SVSetBaseArray::isConsistent() && set.isConsistent() && list.isConsistent();
942 #else
943  return true;
944 #endif
945  }
946 
947  //@}
948 
949  // ------------------------------------------------------------------------------------------------------------------
950  /**@name Constructors / destructors */
951  //@{
952 
953  /// Default constructor.
954  explicit
955  SVSetBase<R>(int pmax = -1, int pmemmax = -1, double pfac = 1.1, double pmemFac = 1.2)
956  : SVSetBaseArray(0, (pmemmax > 0) ? pmemmax : 8 * ((pmax > 0) ? pmax : 8), pmemFac)
957  , set((pmax > 0) ? pmax : 8)
958  , unusedMem(0)
959  , numUnusedMemUpdates(0)
960  , factor(pfac)
961  {
962  assert(isConsistent());
963  }
964 
965  /// Destructor
966  virtual ~SVSetBase<R>()
967  {}
968 
969  /// Assignment operator.
971  {
972  if( this != &rhs )
973  {
974  clear(rhs.size());
975 
976  if( rhs.size() > 0 )
977  {
979  set = rhs.set;
980 
981  DLPSV* ps;
982  DLPSV* newps;
983 
984  void* delta0 = &(*(static_cast<SVSetBaseArray*>(this)))[0];
985  void* delta1 = &(*(static_cast<SVSetBaseArray*>(const_cast<SVSetBase<R>*>(&rhs))))[0];
986  ptrdiff_t delta = reinterpret_cast<char*>(delta0) - reinterpret_cast<char*>(delta1);
987 
988  for( ps = rhs.list.first(); ps; ps = rhs.list.next(ps) )
989  {
990  newps = &set[rhs.number(ps)];
991  list.append(newps);
992  newps->setMem(ps->max(),
993  reinterpret_cast<Nonzero<R>*>(reinterpret_cast<char*>(ps->mem()) + delta));
994  newps->set_size(ps->size());
995  }
996  }
997  }
998 
999  assert(isConsistent());
1000 
1001  return *this;
1002  }
1003 
1004  /// Assignment operator.
1005  template < class S >
1007  {
1008  if( this != (const SVSetBase<R>*)(&rhs) )
1009  {
1010  clear(rhs.size());
1011 
1012  if( rhs.size() > 0 )
1013  this->add(rhs);
1014  }
1015 
1016  assert(isConsistent());
1017 
1018  return *this;
1019  }
1020 
1021  /// Copy constructor.
1023  : SVSetBaseArray()
1024  , unusedMem(old.unusedMem)
1025  , numUnusedMemUpdates(old.numUnusedMemUpdates)
1026  , factor(old.factor)
1027  {
1028  *this = old;
1029 
1030  assert(SVSetBase::isConsistent());
1031  }
1032 
1033  /// Copy constructor.
1034  template < class S >
1036  : SVSetBaseArray()
1037  , unusedMem(old.unusedMem)
1038  , numUnusedMemUpdates(old.numUnusedMemUpdates)
1039  , factor(old.factor)
1040  {
1041  *this = old;
1042 
1043  assert(SVSetBase::isConsistent());
1044  }
1045 
1046  //@}
1047 };
1048 
1049 } // namespace soplex
1050 
1051 /* reset the SOPLEX_DEBUG flag to its original value */
1052 #undef SOPLEX_DEBUG
1053 #ifdef SOPLEX_DEBUG_SVSETBASE
1054 #define SOPLEX_DEBUG
1055 #undef SOPLEX_DEBUG_SVSETBASE
1056 #endif
1057 
1058 #endif // _SVSETBASE_H_
DataSet< DLPSV > set
set of SVectorBases
Definition: svsetbase.h:147
void clear(bool pDestroyElements=false)
removes all elements from an IsList.
Definition: islist.h:283
void append(T *elem)
appends elem to end of list.
Definition: idlist.h:160
Sparse vector nonzero element.
Definition: svectorbase.h:35
SVSetBase< R > & operator=(const SVSetBase< R > &rhs)
Assignment operator.
Definition: svsetbase.h:970
int unusedMem
an estimate of the unused memory (the difference of max() and size() summed up over all vectors) due ...
Definition: svsetbase.h:149
Generic Real linked list.
Entry identifier class for items of a DataSet.
SVectorBase< R > & operator[](const DataKey &k)
Gets SVectorBase by DataKey, writeable.
Definition: svsetbase.h:728
void reMax(int newmax=0)
Resets maximum number of SVectorBases.
Definition: svsetbase.h:915
void ensurePSVec(int n)
Provides enough vector memory for n more SVectorBases.
Definition: svsetbase.h:195
void setMem(int n, Nonzero< R > *elmem)
Set the memory area where the nonzeros will be stored.
Definition: svectorbase.h:724
T * get_ptr()
get a C pointer to the data.
Definition: dataarray.h:110
void deleteVec(DLPSV *ps)
Deleting a vector from the data array and the list.
Definition: svsetbase.h:248
int size() const
Number of used indices.
Definition: svectorbase.h:152
Generic Real linked list.Class IdList implements an intrusive Real linked list as a template class...
Definition: idlist.h:123
DataKey key(const SVectorBase< R > *svec) const
Gets DataKey of SVectorBase.
Definition: svsetbase.h:764
void set_size(int s)
Set size of the vector.
Definition: svectorbase.h:710
DLPSV *const & next() const
Next SVectorBase.
Definition: svsetbase.h:123
void move(ptrdiff_t delta)
adjusts list pointers to a new memory address.
Definition: idlist.h:301
int number(const DataKey &k) const
Gets vector number of DataKey.
Definition: svsetbase.h:770
void countUnusedMem()
count size of unused memory exactly
Definition: svsetbase.h:167
double memFactor
memory extension factor.
Definition: classarray.h:67
bool isConsistent() const
Consistency check.
Definition: classarray.h:314
int memSize() const
Used nonzero memory.
Definition: svsetbase.h:806
bool has(const SVectorBase< R > *svec) const
Is an SVectorBase in the set?
Definition: svsetbase.h:794
void add(DataKey &nkey, const S *rowValues, const int *rowIndices, int rowSize)
Adds svec to SVSetBase.
Definition: svsetbase.h:338
SVectorBase< R > * create(int idxmax=0)
Creates new SVectorBase in set.
Definition: svsetbase.h:428
void add(DataKey nkey[], const SVSetBase< S > &pset)
Adds all SVectorBases of pset to SVSetBase.
Definition: svsetbase.h:414
Nonzero< R > & last()
Reference to last element.
Definition: classarray.h:88
Nonzero< R > * mem() const
get pointer to internal memory.
Definition: svectorbase.h:704
Entry identifier class for items of a DataSet.Every item in a DataSet is assigned a DataKey by which ...
Definition: datakey.h:46
DataKey key(int n) const
Gets DataKey of vector number.
Definition: svsetbase.h:758
Save arrays of data objects.
Set of data objects.Class DataSet manages of sets of data objects of a template type DATA...
Definition: dataset.h:86
DLPSV * thenext
next SVectorBase
Definition: svsetbase.h:89
Set of data objects.
void add(DataKey nkey[], const SVectorBase< R > svec[], int n)
Adds n SVectorBases to SVSetBase.
Definition: svsetbase.h:379
bool has(int n) const
True iff SVSetBase contains a SVectorBase for vector number n.
Definition: svsetbase.h:788
void add(const SVectorBase< R > &svec)
Adds svec to the set.
Definition: svsetbase.h:305
int numUnusedMemUpdates
counter for how often unusedMem has been updated since last exact value
Definition: svsetbase.h:150
#define MSG_DEBUG(x)
Definition: spxdefines.h:129
SVectorBase< R > * create(DataKey &nkey, int idxmax=-1)
Creates new SVectorBase in set.
Definition: svsetbase.h:463
ClassArray< Nonzero< R > > SVSetBaseArray
Definition: svsetbase.h:68
void updateUnusedMemEstimation(int change)
update estimation of unused memory
Definition: svsetbase.h:185
const SVectorBase< R > & operator[](int n) const
Gets SVectorBase by number.
Definition: svsetbase.h:722
int memMax() const
Length of nonzero memory.
Definition: svsetbase.h:812
SVectorBase< R > & operator[](int n)
Gets SVectorBase by number, writeable.
Definition: svsetbase.h:716
int size() const
Returns number of elements.
Definition: classarray.h:208
void remove(T *elem)
removes elem from list.
Definition: idlist.h:246
bool has(const DataKey &k) const
True iff SVSetBase contains a SVectorBase for DataKey k.
Definition: svsetbase.h:782
bool isConsistent() const
Consistency check.
Definition: svsetbase.h:921
double factor
sparse vector memory enlargment factor
Definition: svsetbase.h:158
SVectorBase with prev/next pointers.
Definition: svsetbase.h:81
void add(const SVectorBase< R > svec[], int n)
Adds all n SVectorBases in the array svec to the set.
Definition: svsetbase.h:355
Safe arrays of class objects.Class ClassArray provides safe arrays of general C++ objects (in contras...
Definition: classarray.h:55
DLPSV()
Default constructor.
Definition: svsetbase.h:101
DLPSV *& next()
Next SVectorBase.
Definition: svsetbase.h:117
int max() const
Returns maximum number of elements.
Definition: classarray.h:234
void add(DataKey &nkey, const SVectorBase< R > &svec)
Adds svec to SVSetBase.
Definition: svsetbase.h:321
void reSize(int newsize)
Resets size to newsize.
Definition: classarray.h:218
T * next(const T *elem) const
returns successor of elem or 0, if elem is the last element.
Definition: idlist.h:143
void memRemax(int newmax)
Reset length of nonzero memory.
Definition: svsetbase.h:818
void memPack()
Garbage collection in nonzero memory.
Definition: svsetbase.h:867
void add(int i, const R &v)
Append one nonzero (i,v).
Definition: svectorbase.h:272
Debugging, floating point type and parameter definitions.
ClassArray & operator=(const ClassArray &rhs)
Assignment operator.
Definition: classarray.h:298
bool isConsistent() const
Consistency check.
Definition: svectorbase.h:741
DLPSV * theprev
previous SVectorBase
Definition: svsetbase.h:90
SVSetBase< R > & operator=(const SVSetBase< S > &rhs)
Assignment operator.
Definition: svsetbase.h:1006
Nonzero< R > * get_ptr()
Gets a C pointer to the data.
Definition: classarray.h:102
void removeLast(int m=1)
Removes m last elements.
Definition: classarray.h:193
Everything should be within this namespace.
int max() const
Maximal number of indices.
Definition: svectorbase.h:159
void clear()
Remove all indices.
Definition: svectorbase.h:396
void add2(SVectorBase< R > &svec, int n, const int idx[], const S val[])
Adds n nonzeros to svec of this SVSetBase.
Definition: svsetbase.h:578
Nonzero< R > & operator[](int n)
Reference to n &#39;th element.
Definition: classarray.h:72
DLPSV(const DLPSV &copy)
Copy constructor.
Definition: svsetbase.h:106
Sparse vectors.
ptrdiff_t reMax(int newMax=1, int newSize=-1)
Resets maximum number of elements.
Definition: classarray.h:248
SVectorBase< R > & assignArray(const S *rowValues, const int *rowIndices, int rowSize)
Assignment operator.
Definition: svectorbase.h:677
Nonzero< R > * data
the array of elements
Definition: classarray.h:60
void clear(int minNewSize=-1)
Removes all SVectorBases from set.
Definition: svsetbase.h:688
void ensureMem(int n, bool shortenLast=true)
Provides enough nonzero memory for n more Nonzeros.
Definition: svsetbase.h:206
DLPSV *& prev()
Previous SVectorBase.
Definition: svsetbase.h:135
void insert(int i, int n)
Inserts n uninitialized elements before i &#39;th element.
Definition: classarray.h:132
void add2(SVectorBase< R > &svec, int idx, R val)
Adds nonzero (idx, val) to svec of this SVSetBase.
Definition: svsetbase.h:553
void add2(SVectorBase< R > &svec, int n, const int idx[], const R val[])
Adds n nonzeros to svec of this SVSetBase.
Definition: svsetbase.h:565
void xtend(SVectorBase< R > &svec, int newmax)
Extends svec to fit newmax nonzeros.
Definition: svsetbase.h:475
bool isConsistent() const
consistency check.
Definition: idlist.h:315
void add(const SVSetBase< S > &pset)
Adds all SVectorBases in pset to SVSetBase.
Definition: svsetbase.h:389
Sparse vectors.Class SVectorBase provides packed sparse vectors. Such are a sparse vectors...
Definition: dvectorbase.h:31
DLPSV *const & prev() const
Previous SVectorBase.
Definition: svsetbase.h:129
#define MSGinconsistent(name)
Definition: spxdefines.h:123
const SVectorBase< R > & operator[](const DataKey &k) const
Gets SVectorBase by DataKey.
Definition: svsetbase.h:734
T * last() const
returns last element in list.
Definition: idlist.h:137
T * first() const
returns first element in list.
Definition: idlist.h:131
int max() const
Current maximum number of SVectorBases.
Definition: svsetbase.h:752
int num() const
Current number of SVectorBases.
Definition: svsetbase.h:746
IdList< DLPSV > list
doubly linked list for non-zero management
Definition: svsetbase.h:148
int number(const SVectorBase< R > *svec) const
Gets vector number of SVectorBase.
Definition: svsetbase.h:776
Sparse vector set.Class SVSetBase provides a set of sparse vectors SVectorBase. All SVectorBases in a...
Definition: ssvectorbase.h:33
void clear()
Removes all elements.
Definition: classarray.h:202