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