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