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-2024 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
48namespace 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 */
71template < class R >
72class SVSetBase : protected ClassArray < Nonzero<R> >
73{
74 template < class S > friend class SVSetBase;
75
76private:
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.
124 DLPSV(DLPSV&& copy)
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
219
220#ifdef SOPLEX_DEBUG
221 SPxOut::debug(this, " --> NEW: unusedMem = {}\n", unusedMem);
222#endif
223 }
224
225 /// update estimation of unused memory
227 {
228 unusedMem += change;
230
231 if(unusedMem < 0 || unusedMem > memSize() || numUnusedMemUpdates >= 1000000)
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
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 {
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
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
335 }
336
337 list.remove(ps);
338 }
339
340 ///@}
341
342public:
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 * At 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 * At 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 != nullptr);
388 assert(rowSize <= 0 || rowValues != nullptr);
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 * At return, 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 * At 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
492 assert(olddata == SVSetBaseArray::data);
493#else
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
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, nullptr);
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
568 assert(olddata == SVSetBaseArray::data);
569#else
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
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 * At 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)
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;
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;
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
959 assert(olddata == SVSetBaseArray::data);
960#else
962#endif
963
964 unusedMem = 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)
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)
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)
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_
Save arrays of data objects.
Set of class objects.
Safe arrays of class objects.
Definition: classarray.h:65
bool isConsistent() const
Consistency check.
Definition: classarray.h:324
ClassArray & operator=(const ClassArray &rhs)
Assignment operator.
Definition: classarray.h:308
Nonzero< R > * get_ptr()
Gets a C pointer to the data.
Definition: classarray.h:111
int max() const
Returns maximum number of elements.
Definition: classarray.h:243
void insert(int i, int n)
Inserts n uninitialized elements before i 'th element.
Definition: classarray.h:141
ptrdiff_t reMax(int newMax=1, int newSize=-1)
Resets maximum number of elements.
Definition: classarray.h:257
void reSize(int newsize)
Resets size to newsize.
Definition: classarray.h:227
void removeLast(int m=1)
Removes m last elements.
Definition: classarray.h:202
Nonzero< R > * data
the array of elements
Definition: classarray.h:69
void clear()
Removes all elements.
Definition: classarray.h:211
double memFactor
memory extension factor.
Definition: classarray.h:76
Nonzero< R > & last()
Reference to last element.
Definition: classarray.h:97
int size() const
Returns number of elements.
Definition: classarray.h:217
Set of class objects.
Definition: classset.h:95
T * get_ptr()
get a C pointer to the data.
Definition: dataarray.h:123
Entry identifier class for items of a DataSet.
Definition: datakey.h:56
Generic Real linked list.
Definition: idlist.h:133
Sparse vector nonzero element.
Definition: svectorbase.h:47
static void debug(const T *, Args &&... args)
Definition: spxout.h:203
SVectorBase with prev/next pointers.
Definition: svsetbase.h:92
DLPSV()
Default constructor.
Definition: svsetbase.h:111
DLPSV * thenext
next SVectorBase
Definition: svsetbase.h:99
DLPSV(DLPSV &&copy)
move constructor.
Definition: svsetbase.h:124
DLPSV *const & prev() const
Previous SVectorBase.
Definition: svsetbase.h:167
DLPSV *& prev()
Previous SVectorBase.
Definition: svsetbase.h:173
DLPSV *const & next() const
Next SVectorBase.
Definition: svsetbase.h:161
DLPSV * theprev
previous SVectorBase
Definition: svsetbase.h:100
DLPSV *& next()
Next SVectorBase.
Definition: svsetbase.h:155
DLPSV & operator=(DLPSV &&rhs)
move assignment operator.
Definition: svsetbase.h:129
DLPSV & operator=(const DLPSV &rhs)
Assignment operator.
Definition: svsetbase.h:143
DLPSV(const DLPSV &copy)
Copy constructor.
Definition: svsetbase.h:119
Sparse vector set.
Definition: svsetbase.h:73
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
void countUnusedMem()
count size of unused memory exactly
Definition: svsetbase.h:205
void remove(int removenum)
Removes the vector with number removenum from the set.
Definition: svsetbase.h:654
bool has(int n) const
True iff SVSetBase contains a SVectorBase for vector number n.
Definition: svsetbase.h:840
void updateUnusedMemEstimation(int change)
update estimation of unused memory
Definition: svsetbase.h:226
void remove(const DataKey keys[], int n, int *perm)
Definition: svsetbase.h:710
void add(const SVectorBase< R > svec[], int n)
Adds all n SVectorBases in the array svec to the set.
Definition: svsetbase.h:402
void add(const SVSetBase< S > &pset)
Adds all SVectorBases in pset to SVSetBase.
Definition: svsetbase.h:436
int numUnusedMemUpdates
counter for how often unusedMem has been updated since last exact value
Definition: svsetbase.h:188
SVectorBase< R > * create(DataKey &nkey, int idxmax=-1)
Creates new SVectorBase in set.
Definition: svsetbase.h:511
void remove(const DataKey &removekey)
Removes the vector with key removekey from the set.
Definition: svsetbase.h:645
double factor
sparse vector memory enlargment factor
Definition: svsetbase.h:196
void xtend(SVectorBase< R > &svec, int newmax)
Extends svec to fit newmax nonzeros.
Definition: svsetbase.h:523
IdList< DLPSV > list
doubly linked list for non-zero management
Definition: svsetbase.h:186
void remove(const DataKey keys[], int n)
Removes n SVectorBases from set.
Definition: svsetbase.h:694
bool isConsistent() const
Consistency check.
Definition: svsetbase.h:981
void ensureMem(int n, bool shortenLast=true)
Provides enough nonzero memory for n more Nonzeros.
Definition: svsetbase.h:247
void add2(SVectorBase< R > &svec, int idx, R val)
Adds nonzero (idx, val) to svec of this SVSetBase.
Definition: svsetbase.h:605
void ensurePSVec(int n)
Provides enough vector memory for n more SVectorBases.
Definition: svsetbase.h:236
const SVectorBase< R > & operator[](int n) const
Gets SVectorBase by number.
Definition: svsetbase.h:774
int memSize() const
Used nonzero memory.
Definition: svsetbase.h:858
void remove(int perm[])
Removes multiple elements.
Definition: svsetbase.h:673
SVectorBase< R > & operator[](int n)
Gets SVectorBase by number, writeable.
Definition: svsetbase.h:768
int number(const DataKey &k) const
Gets vector number of DataKey.
Definition: svsetbase.h:822
int max() const
Current maximum number of SVectorBases.
Definition: svsetbase.h:804
ClassSet< DLPSV > set
set of SVectorBases
Definition: svsetbase.h:185
void remove(const int nums[], int n, int *perm)
Definition: svsetbase.h:728
int unusedMem
an estimate of the unused memory (the difference of max() and size() summed up over all vectors) due ...
Definition: svsetbase.h:187
void deleteVec(DLPSV *ps)
Deleting a vector from the data array and the list.
Definition: svsetbase.h:292
SVectorBase< R > & operator[](const DataKey &k)
Gets SVectorBase by DataKey, writeable.
Definition: svsetbase.h:780
int number(const SVectorBase< R > *svec) const
Gets vector number of SVectorBase.
Definition: svsetbase.h:828
int memMax() const
Length of nonzero memory.
Definition: svsetbase.h:864
void memRemax(int newmax)
Reset length of nonzero memory.
Definition: svsetbase.h:870
int num() const
Current number of SVectorBases.
Definition: svsetbase.h:798
void add(DataKey &nkey, const S *rowValues, const int *rowIndices, int rowSize)
Adds svec to SVSetBase.
Definition: svsetbase.h:385
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
SVSetBase< R > & operator=(const SVSetBase< R > &rhs)
Assignment operator.
Definition: svsetbase.h:1030
SVSetBase(int pmax=-1, int pmemmax=-1, double pfac=1.1, double pmemFac=1.2)
Default constructor.
Definition: svsetbase.h:1015
bool has(const SVectorBase< R > *svec) const
Is an SVectorBase in the set?
Definition: svsetbase.h:846
SVSetBase< R > & operator=(const SVSetBase< S > &rhs)
Assignment operator.
Definition: svsetbase.h:1066
bool has(const DataKey &k) const
True iff SVSetBase contains a SVectorBase for DataKey k.
Definition: svsetbase.h:834
void add(DataKey nkey[], const SVectorBase< R > svec[], int n)
Adds n SVectorBases to SVSetBase.
Definition: svsetbase.h:426
void clear(int minNewSize=-1)
Removes all SVectorBases from set.
Definition: svsetbase.h:740
DataKey key(const SVectorBase< R > *svec) const
Gets DataKey of SVectorBase.
Definition: svsetbase.h:816
void reMax(int newmax=0)
Resets maximum number of SVectorBases.
Definition: svsetbase.h:975
SVSetBase(const SVSetBase< R > &old)
Copy constructor.
Definition: svsetbase.h:1082
void remove(const int nums[], int n)
Removes n SVectorBases from set.
Definition: svsetbase.h:703
void add(DataKey nkey[], const SVSetBase< S > &pset)
Adds all SVectorBases of pset to SVSetBase.
Definition: svsetbase.h:462
void memPack()
Garbage collection in nonzero memory.
Definition: svsetbase.h:923
DataKey key(int n) const
Gets DataKey of vector number.
Definition: svsetbase.h:810
SVSetBase(const SVSetBase< S > &old)
Copy constructor.
Definition: svsetbase.h:1095
virtual ~SVSetBase()
Destructor.
Definition: svsetbase.h:1026
SVectorBase< R > * create(int idxmax=0)
Creates new SVectorBase in set.
Definition: svsetbase.h:476
void remove(const SVectorBase< R > *svec)
Removes one SVectorBase from set.
Definition: svsetbase.h:662
ClassArray< Nonzero< R > > SVSetBaseArray
Definition: svsetbase.h:78
void add(const SVectorBase< R > &svec)
Adds svec to the set.
Definition: svsetbase.h:352
void add(DataKey &nkey, const SVectorBase< R > &svec)
Adds svec to SVSetBase.
Definition: svsetbase.h:368
const SVectorBase< R > & operator[](const DataKey &k) const
Gets SVectorBase by DataKey.
Definition: svsetbase.h:786
Sparse vectors.
Definition: svectorbase.h:140
bool isConsistent() const
Consistency check.
Definition: svectorbase.h:830
void setMem(int n, Nonzero< R > *elmem)
Set the memory area where the nonzeros will be stored.
Definition: svectorbase.h:813
void add(int i, const R &v)
Append one nonzero (i,v).
Definition: svectorbase.h:282
int max() const
Maximal number of indices.
Definition: svectorbase.h:171
void set_size(int s)
Set size of the vector.
Definition: svectorbase.h:799
SVectorBase< R > & assignArray(const S *rowValues, const int *rowIndices, int rowSize)
Assignment operator.
Definition: svectorbase.h:765
Nonzero< R > * mem() const
get pointer to internal memory.
Definition: svectorbase.h:793
SVectorBase< R > & operator=(const VectorBase< S > &vec)
Assignment operator.
Definition: basevectors.h:951
void set_max(int m)
Set the maximum number of nonzeros in the vector.
Definition: svectorbase.h:806
int size() const
Number of used indices.
Definition: svectorbase.h:164
Entry identifier class for items of a DataSet.
Set of data objects.
Generic Real linked list.
Everything should be within this namespace.
Debugging, floating point type and parameter definitions.
#define SPX_MSG_INCONSISTENT(name)
Definition: spxdefines.h:175
Sparse vectors.