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