Scippy

SoPlex

Sequential object-oriented simPlex

svectorbase.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-2016 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 svectorbase.h
17  * @brief Sparse vectors.
18  */
19 #ifndef _SVECTORBASE_H_
20 #define _SVECTORBASE_H_
21 
22 #include <iostream>
23 #include <assert.h>
24 #include <math.h>
25 
26 namespace soplex
27 {
28 template < class R > class VectorBase;
29 template < class R > class SSVectorBase;
30 
31 /// Sparse vector nonzero element.
32 /** SVectorBase keeps its nonzeros in an array of Nonzero%s providing members for saving the index and value.
33  */
34 template < class R >
35 class Nonzero
36 {
37 public:
38 
39  R val; ///< Value of nonzero element.
40  int idx; ///< Index of nonzero element.
41 
42  template < class S >
44  {
45  val = vec.val;
46  idx = vec.idx;
47  return *this;
48  }
49 
50  template < class S >
51  Nonzero<R>(const Nonzero<S>& vec)
52  : val(vec.val)
53  , idx(vec.idx)
54  {
55  }
56 
58  : val()
59  , idx(0)
60  {
61  }
62 };
63 
64 
65 
66 // specialized assignment operator
67 template <>
68 template < class S >
70 {
71  val = Real(vec.val);
72  idx = vec.idx;
73  return *this;
74 }
75 
76 
77 /**@brief Sparse vectors.
78  * @ingroup Algebra
79  *
80  * Class SVectorBase provides packed sparse vectors. Such are a sparse vectors, with a storage scheme that keeps all
81  * data in one contiguous block of memory. This is best suited for using them for parallel computing on a distributed
82  * memory multiprocessor.
83  *
84  * SVectorBase does not provide any memory management (this will be done by class DSVectorBase). This means, that the
85  * constructor of SVectorBase expects memory where to save the nonzeros. Further, adding nonzeros to an SVectorBase may
86  * fail if no more memory is available for saving them (see also DSVectorBase).
87  *
88  * When nonzeros are added to an SVectorBase, they are appended to the set of nonzeros, i.e., they recieve numbers
89  * size(), size()+1 ... . An SVectorBase can hold atmost max() nonzeros, where max() is given in the constructor. When
90  * removing nonzeros, the remaining nonzeros are renumbered. However, only the numbers greater than the number of the
91  * first removed nonzero are affected.
92  *
93  * The following mathematical operations are provided by class SVectorBase (SVectorBase \p a, \p b, \p c; R \p x):
94  *
95  * <TABLE>
96  * <TR><TD>Operation</TD><TD>Description </TD><TD></TD>&nbsp;</TR>
97  * <TR><TD>\c -= </TD><TD>subtraction </TD><TD>\c a \c -= \c b </TD></TR>
98  * <TR><TD>\c += </TD><TD>addition </TD><TD>\c a \c += \c b </TD></TR>
99  * <TR><TD>\c * </TD><TD>skalar product</TD>
100  * <TD>\c x = \c a \c * \c b </TD></TR>
101  * <TR><TD>\c *= </TD><TD>scaling </TD><TD>\c a \c *= \c x </TD></TR>
102  * <TR><TD>maxAbs() </TD><TD>infinity norm </TD>
103  * <TD>\c a.maxAbs() == \f$\|a\|_{\infty}\f$ </TD></TR>
104  * <TR><TD>length() </TD><TD>eucledian norm</TD>
105  * <TD>\c a.length() == \f$\sqrt{a^2}\f$ </TD></TR>
106  * <TR><TD>length2()</TD><TD>square norm </TD>
107  * <TD>\c a.length2() == \f$a^2\f$ </TD></TR>
108  * </TABLE>
109  *
110  * Operators \c += and \c -= should be used with caution, since no efficient implementation is available. One should
111  * think of assigning the left handside vector to a dense VectorBase first and perform the addition on it. The same
112  * applies to the scalar product \c *.
113  *
114  * There are two numberings of the nonzeros of an SVectorBase. First, an SVectorBase is supposed to act like a linear
115  * algebra VectorBase. An \em index refers to this view of an SVectorBase: operator[]() is provided which returns the
116  * value at the given index of the vector, i.e., 0 for all indices which are not in the set of nonzeros. The other view
117  * of SVectorBase%s is that of a set of nonzeros. The nonzeros are numbered from 0 to size()-1. The methods index(int
118  * n) and value(int n) allow to access the index and value of the \p n 'th nonzero. \p n is referred to as the \em
119  * number of a nonzero.
120  *
121  * @todo SVectorBase should get a new implementation. There maybe a lot of memory lost due to padding the Nonzero
122  * structure. A better idea seems to be class SVectorBase { int size; int used; int* idx; R* val; }; which for
123  * several reasons could be faster or slower. If SVectorBase is changed, also DSVectorBase and SVSet have to be
124  * modified.
125  */
126 template < class R >
127 class SVectorBase
128 {
129  template < class S > friend class SVectorBase;
130 
131 private:
132 
133  // ------------------------------------------------------------------------------------------------------------------
134  /**@name Data */
135  //@{
136 
138  int memsize;
139  int memused;
140 
141  //@}
142 
143 public:
144 
146 
147  // ------------------------------------------------------------------------------------------------------------------
148  /**@name Access */
149  //@{
150 
151  /// Number of used indices.
152  int size() const
153  {
154  assert(m_elem != 0 || memused == 0);
155  return memused;
156  }
157 
158  /// Maximal number of indices.
159  int max() const
160  {
161  assert(m_elem != 0 || memused == 0);
162  return memsize;
163  }
164 
165  /// Dimension of the vector defined as maximal index + 1
166  int dim() const
167  {
168  const Nonzero<R>* e = m_elem;
169  int d = -1;
170  int n = size();
171 
172  while( n-- )
173  {
174  d = (d > e->idx) ? d : e->idx;
175  e++;
176  }
177 
178  return d+1;
179  }
180 
181  /// Number of index \p i.
182  /** @return The number of the first index \p i. If no index \p i is available in the IdxSet, -1 is
183  * returned. Otherwise, index(number(i)) == i holds.
184  */
185  int number(int i) const
186  {
187  if( m_elem != 0 )
188  {
189  int n = size();
190  Nonzero<R>* e = &(m_elem[n]);
191 
192  while( n-- )
193  {
194  --e;
195  if( e->idx == i )
196  {
197  assert(index(n) == i);
198  return n;
199  }
200  }
201  }
202 
203  return -1;
204  }
205 
206  /// Value to index \p i.
207  R operator[](int i) const
208  {
209  int n = number(i);
210 
211  if( n >= 0 )
212  return m_elem[n].val;
213 
214  return 0;
215  }
216 
217  /// Reference to the \p n 'th nonzero element.
219  {
220  assert(n >= 0);
221  assert(n < max());
222 
223  return m_elem[n];
224  }
225 
226  /// The \p n 'th nonzero element.
227  const Nonzero<R>& element(int n) const
228  {
229  assert(n >= 0);
230  assert(n < size());
231 
232  return m_elem[n];
233  }
234 
235  /// Reference to index of \p n 'th nonzero.
236  int& index(int n)
237  {
238  assert(n >= 0);
239  assert(n < size());
240 
241  return m_elem[n].idx;
242  }
243 
244  /// Index of \p n 'th nonzero.
245  int index(int n) const
246  {
247  assert(n >= 0);
248  assert(n < size());
249 
250  return m_elem[n].idx;
251  }
252 
253  /// Reference to value of \p n 'th nonzero.
254  R& value(int n)
255  {
256  assert(n >= 0);
257  assert(n < size());
258 
259  return m_elem[n].val;
260  }
261 
262  /// Value of \p n 'th nonzero.
263  const R& value(int n) const
264  {
265  assert(n >= 0);
266  assert(n < size());
267 
268  return m_elem[n].val;
269  }
270 
271  /// Append one nonzero \p (i,v).
272  void add(int i, const R& v)
273  {
274  assert(m_elem != 0);
275  assert(size() < max());
276 
277  int n = size();
278 
279  m_elem[n].idx = i;
280  m_elem[n].val = v;
281  set_size( n + 1 );
282 
283  assert(size() <= max());
284  }
285 
286  /// Append one uninitialized nonzero.
287  void add(int i)
288  {
289  assert(m_elem != 0);
290  assert(size() < max());
291 
292  int n = size();
293 
294  m_elem[n].idx = i;
295  set_size( n + 1 );
296 
297  assert(size() <= max());
298  }
299 
300  /// Append nonzeros of \p sv.
301  void add(const SVectorBase& sv)
302  {
303  add(sv.size(), sv.m_elem);
304  }
305 
306  /// Append \p n nonzeros.
307  void add(int n, const int i[], const R v[])
308  {
309  assert(n + size() <= max());
310 
311  if( n <= 0 )
312  return;
313 
314  Nonzero<R>* e = m_elem + size();
315 
316  set_size( size() + n );
317  while( n-- )
318  {
319  e->idx = *i++;
320  e->val = *v++;
321  e++;
322  }
323  }
324 
325  /// Append \p n nonzeros.
326  template < class S >
327  void add(int n, const int i[], const S v[])
328  {
329  assert(n + size() <= max());
330 
331  if( n <= 0 )
332  return;
333 
334  Nonzero<R>* e = m_elem + size();
335 
336  set_size( size() + n );
337  while( n-- )
338  {
339  e->idx = *i++;
340  e->val = *v++;
341  e++;
342  }
343  }
344 
345  /// Append \p n nonzeros.
346  void add(int n, const Nonzero<R> e[])
347  {
348  assert(n + size() <= max());
349 
350  if( n <= 0 )
351  return;
352 
353  Nonzero<R>* ee = m_elem + size();
354 
355  set_size( size() + n );
356  while( n-- )
357  *ee++ = *e++;
358  }
359 
360  /// Remove nonzeros \p n thru \p m.
361  void remove(int n, int m)
362  {
363  assert(n <= m);
364  assert(m < size());
365  assert(n >= 0);
366 
367  ++m;
368 
369  int cpy = m - n;
370  cpy = (size() - m >= cpy) ? cpy : size() - m;
371 
372  Nonzero<R>* e = &m_elem[size() - 1];
373  Nonzero<R>* r = &m_elem[n];
374 
375  set_size(size() - cpy);
376  do
377  {
378  *r++ = *e--;
379  }
380  while( --cpy );
381  }
382 
383  /// Remove \p n 'th nonzero.
384  void remove(int n)
385  {
386  assert(n >= 0);
387  assert(n < size());
388 
389  int newsize = size() - 1;
390  set_size(newsize);
391  if( n < newsize )
392  m_elem[n] = m_elem[newsize];
393  }
394 
395  /// Remove all indices.
396  void clear()
397  {
398  set_size(0);
399  }
400 
401  /// Sort nonzeros to increasing indices.
402  void sort()
403  {
404  if( m_elem != 0 )
405  {
406  Nonzero<R> dummy;
407  Nonzero<R>* w;
408  Nonzero<R>* l;
409  Nonzero<R>* s = &(m_elem[0]);
410  Nonzero<R>* e = s + size();
411 
412  for( l = s, w = s + 1; w < e; l = w, ++w )
413  {
414  if( l->idx > w->idx )
415  {
416  dummy = *w;
417 
418  do
419  {
420  l[1] = *l;
421  if( l-- == s )
422  break;
423  }
424  while( l->idx > dummy.idx );
425 
426  l[1] = dummy;
427  }
428  }
429  }
430  }
431 
432  //@}
433 
434  // ------------------------------------------------------------------------------------------------------------------
435  /**@name Arithmetic operations */
436  //@{
437 
438  /// Maximum absolute value, i.e., infinity norm.
439  R maxAbs() const
440  {
441  R maxi = 0;
442 
443  for( int i = size() - 1; i >= 0; --i )
444  {
445  if( spxAbs(m_elem[i].val) > maxi )
446  maxi = spxAbs(m_elem[i].val);
447  }
448 
449  assert(maxi >= 0);
450 
451  return maxi;
452  }
453 
454  /// Minimum absolute value.
455  R minAbs() const
456  {
457  R mini = infinity;
458 
459  for( int i = size() - 1; i >= 0; --i )
460  {
461  if( spxAbs(m_elem[i].val) < mini )
462  mini = spxAbs(m_elem[i].val);
463  }
464 
465  assert(mini >= 0);
466 
467  return mini;
468  }
469 
470  /// Floating point approximation of euclidian norm (without any approximation guarantee).
471  Real length() const
472  {
473  return spxSqrt((Real)length2());
474  }
475 
476  /// Squared norm.
477  R length2() const
478  {
479  R x = 0;
480  int n = size();
481  const Nonzero<R>* e = m_elem;
482 
483  while( n-- )
484  {
485  x += e->val * e->val;
486  e++;
487  }
488 
489  return x;
490  }
491 
492  /// Scaling.
494  {
495  int n = size();
496  Nonzero<R>* e = m_elem;
497 
498  assert(x != 0);
499 
500  while( n-- )
501  {
502  e->val *= x;
503  e++;
504  }
505 
506  return *this;
507  }
508 
509  /// Inner product.
510  R operator*(const VectorBase<R>& w) const;
511 
512  /// inner product for sparse vectors
513  template < class S >
514  R operator*(const SVectorBase<S>& w) const
515  {
516  R x = 0;
517  int n = size();
518  int m = w.size();
519  if( n == 0 || m == 0 )
520  return x;
521  int i = 0;
522  int j = 0;
523  Element* e = m_elem;
524  typename SVectorBase<S>::Element wj = w.element(j);
525 
526  while( true )
527  {
528  if( e->idx == wj.idx )
529  {
530  x += e->val * wj.val;
531  i++;
532  j++;
533  if( i == n || j == m )
534  break;
535  e++;
536  wj = w.element(j);
537  }
538  else if( e->idx < wj.idx )
539  {
540  i++;
541  if( i == n )
542  break;
543  e++;
544  }
545  else
546  {
547  j++;
548  if( j == m )
549  break;
550  wj = w.element(j);
551  }
552  }
553 
554  return x;
555  }
556 
557  //@}
558 
559  // ------------------------------------------------------------------------------------------------------------------
560  /**@name Constructions, destruction, and assignment */
561  //@{
562 
563  /// Default constructor.
564  /** The constructor expects one memory block where to store the nonzero elements. This must be passed to the
565  * constructor, where the \em number of Nonzero%s needs that fit into the memory must be given and a pointer to the
566  * beginning of the memory block. Once this memory has been passed, it shall not be modified until the SVectorBase
567  * is no longer used.
568  */
569  explicit SVectorBase<R>(int n = 0, Nonzero<R>* p_mem = 0)
570  {
571  setMem(n, p_mem);
572  }
573 
574  /// Assignment operator.
575  template < class S >
577 
578  /// Assignment operator.
580  {
581  if( this != &sv )
582  {
583  assert(max() >= sv.size());
584 
585  int i = sv.size();
586  Nonzero<R>* e = m_elem;
587  const Nonzero<R>* s = sv.m_elem;
588 
589  while( i-- )
590  {
591  assert(e != 0);
592  *e++ = *s++;
593  }
594 
595  set_size(sv.size());
596  }
597 
598  return *this;
599  }
600 
601  /// Assignment operator.
602  template < class S >
604  {
605  if( this != (const SVectorBase<R>*)(&sv) )
606  {
607  assert(max() >= sv.size());
608 
609  int i = sv.size();
610  Nonzero<R>* e = m_elem;
611  const Nonzero<S>* s = sv.m_elem;
612 
613  while( i-- )
614  {
615  assert(e != 0);
616  *e++ = *s++;
617  }
618 
619  set_size(sv.size());
620  }
621 
622  return *this;
623  }
624 
625  /// Assignment operator.
626  template < class S >
627  SVectorBase<R>& assignArray(const S* rowValues, const int* rowIndices, int rowSize)
628  {
629  assert(max() >= rowSize);
630 
631  int i;
632  for( i = 0; i < rowSize && i < max(); i++ )
633  {
634  m_elem[i].val = rowValues[i];
635  m_elem[i].idx = rowIndices[i];
636  }
637 
638  set_size(i);
639 
640  return *this;
641  }
642 
643  /// Assignment operator.
644  template < class S >
646 
647  //@}
648 
649  // ------------------------------------------------------------------------------------------------------------------
650  /**@name Memory */
651  //@{
652 
653  /// get pointer to internal memory.
654  Nonzero<R>* mem() const
655  {
656  return m_elem;
657  }
658 
659  /// Set size of the vector.
660  void set_size(int s)
661  {
662  assert(m_elem != 0 || s == 0);
663  memused = s;
664  }
665 
666  /// Set the maximum number of nonzeros in the vector.
667  void set_max(int m)
668  {
669  assert(m_elem != 0 || m == 0);
670  memsize = m;
671  }
672 
673  /// Set the memory area where the nonzeros will be stored.
674  void setMem(int n, Nonzero<R>* elmem)
675  {
676  assert(n >= 0);
677  assert(n == 0 || elmem != 0);
678 
679  m_elem = elmem;
680  set_size(0);
681  set_max(n);
682  }
683 
684  //@}
685 
686  // ------------------------------------------------------------------------------------------------------------------
687  /**@name Utilities */
688  //@{
689 
690  /// Consistency check.
691  bool isConsistent() const
692  {
693 #ifdef ENABLE_CONSISTENCY_CHECKS
694  if( m_elem != 0 )
695  {
696  const int my_size = size();
697  const int my_max = max();
698 
699  if( my_size < 0 || my_max < 0 || my_size > my_max )
700  return MSGinconsistent("SVectorBase");
701 
702  for( int i = 1; i < my_size; ++i )
703  {
704  for( int j = 0; j < i; ++j )
705  {
706  // allow trailing zeros
707  if( m_elem[i].idx == m_elem[j].idx && m_elem[i].val != 0 )
708  return MSGinconsistent("SVectorBase");
709  }
710  }
711  }
712 #endif
713 
714  return true;
715  }
716 
717  //@}
718 };
719 
720 
721 
722 /// specialization for inner product for sparse vectors
723 template <>
724 template < class S >
726 {
727  Real x = 0;
728  int n = size();
729  int m = w.size();
730  if( n == 0 || m == 0 )
731  return x;
732  int i = 0;
733  int j = 0;
734  SVectorBase<Real>::Element* e = m_elem;
735  typename SVectorBase<S>::Element wj = w.element(j);
736 
737  while( true )
738  {
739  if( e->idx == wj.idx )
740  {
741  x += e->val * Real(wj.val);
742  i++;
743  j++;
744  if( i == n || j == m )
745  break;
746  e++;
747  wj = w.element(j);
748  }
749  else if( e->idx < wj.idx )
750  {
751  i++;
752  if( i == n )
753  break;
754  e++;
755  }
756  else
757  {
758  j++;
759  if( j == m )
760  break;
761  wj = w.element(j);
762  }
763  }
764 
765  return x;
766 }
767 
768 } // namespace soplex
769 #endif // _SVECTORBASE_H_
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:3925
Nonzero< R > * m_elem
Definition: svectorbase.h:137
Nonzero< R > * mem() const
get pointer to internal memory.
Definition: svectorbase.h:654
Sparse vector nonzero element.
Definition: svectorbase.h:35
Dense vector.Class VectorBase provides dense linear algebra vectors. It does not provide memory manag...
Definition: dsvectorbase.h:28
void setMem(int n, Nonzero< R > *elmem)
Set the memory area where the nonzeros will be stored.
Definition: svectorbase.h:674
void set_max(int m)
Set the maximum number of nonzeros in the vector.
Definition: svectorbase.h:667
SVectorBase< R > & operator=(const SVectorBase< R > &sv)
Assignment operator.
Definition: svectorbase.h:579
int max() const
Maximal number of indices.
Definition: svectorbase.h:159
Nonzero< R > & element(int n)
Reference to the n &#39;th nonzero element.
Definition: svectorbase.h:218
void add(int n, const int i[], const R v[])
Append n nonzeros.
Definition: svectorbase.h:307
void set_size(int s)
Set size of the vector.
Definition: svectorbase.h:660
int size() const
Number of used indices.
Definition: svectorbase.h:152
R operator[](int i) const
Value to index i.
Definition: svectorbase.h:207
void add(int n, const Nonzero< R > e[])
Append n nonzeros.
Definition: svectorbase.h:346
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:254
SVectorBase< R > & operator=(const SVectorBase< S > &sv)
Assignment operator.
Definition: svectorbase.h:603
R minAbs() const
Minimum absolute value.
Definition: svectorbase.h:455
int idx
Index of nonzero element.
Definition: svectorbase.h:40
Semi sparse vector.This class implements semi-sparse vectors. Such are DVectorBases where the indices...
Definition: dsvectorbase.h:29
Nonzero< R > Element
Definition: svectorbase.h:145
SVectorBase< R > & operator*=(const R &x)
Scaling.
Definition: svectorbase.h:493
int dim() const
Dimension of the vector defined as maximal index + 1.
Definition: svectorbase.h:166
int index(int n) const
Index of n &#39;th nonzero.
Definition: svectorbase.h:245
double Real
SOPLEX_DEBUG.
Definition: spxdefines.h:200
R operator*(const SVectorBase< S > &w) const
inner product for sparse vectors
Definition: svectorbase.h:514
Real length() const
Floating point approximation of euclidian norm (without any approximation guarantee).
Definition: svectorbase.h:471
int number(int i) const
Number of index i.
Definition: svectorbase.h:185
int & index(int n)
Reference to index of n &#39;th nonzero.
Definition: svectorbase.h:236
DVectorBase< R > operator*(const VectorBase< R > &v, R x)
Scaling.
Definition: basevectors.h:1210
Real spxSqrt(Real a)
returns square root
Definition: spxdefines.h:325
R operator*(const VectorBase< R > &w) const
Inner product.
Definition: basevectors.h:990
bool isConsistent() const
Consistency check.
Definition: svectorbase.h:691
void add(int i, const R &v)
Append one nonzero (i,v).
Definition: svectorbase.h:272
const R & value(int n) const
Value of n &#39;th nonzero.
Definition: svectorbase.h:263
Everything should be within this namespace.
void clear()
Remove all indices.
Definition: svectorbase.h:396
R length2() const
Squared norm.
Definition: svectorbase.h:477
Nonzero< R > & operator=(const Nonzero< S > &vec)
Definition: svectorbase.h:43
R maxAbs() const
Maximum absolute value, i.e., infinity norm.
Definition: svectorbase.h:439
const Nonzero< R > & element(int n) const
The n &#39;th nonzero element.
Definition: svectorbase.h:227
void add(const SVectorBase &sv)
Append nonzeros of sv.
Definition: svectorbase.h:301
SVectorBase< R > & assignArray(const S *rowValues, const int *rowIndices, int rowSize)
Assignment operator.
Definition: svectorbase.h:627
void sort()
Sort nonzeros to increasing indices.
Definition: svectorbase.h:402
const Real infinity
Definition: spxdefines.cpp:26
R val
Value of nonzero element.
Definition: svectorbase.h:39
void add(int i)
Append one uninitialized nonzero.
Definition: svectorbase.h:287
Sparse vectors.Class SVectorBase provides packed sparse vectors. Such are a sparse vectors...
Definition: dvectorbase.h:31
#define MSGinconsistent(name)
Definition: spxdefines.h:121
void add(int n, const int i[], const S v[])
Append n nonzeros.
Definition: svectorbase.h:327