OpenMS
DistanceMatrix.h
Go to the documentation of this file.
1 // Copyright (c) 2002-2023, The OpenMS Team -- EKU Tuebingen, ETH Zurich, and FU Berlin
2 // SPDX-License-Identifier: BSD-3-Clause
3 //
4 // --------------------------------------------------------------------------
5 // $Maintainer: Mathias Walzer $
6 // $Authors: $
7 // --------------------------------------------------------------------------
8 
9 #pragma once
10 
11 #include <OpenMS/CONCEPT/Macros.h>
12 #include <OpenMS/CONCEPT/Types.h>
14 #include <OpenMS/config.h>
15 
16 #include <algorithm>
17 #include <cmath>
18 #include <iomanip>
19 #include <iostream>
20 
21 namespace OpenMS
22 {
23 
40  template <typename Value>
42  {
43 public:
44 
46 
47  typedef Value value_type;
49 
51 
52  typedef Size SizeType;
55 
60  matrix_(nullptr), init_size_(0), dimensionsize_(0), min_element_(0, 0)
61  {
62  }
63 
71  DistanceMatrix(SizeType dimensionsize, Value value = Value()) :
73  {
74  matrix_[0] = NULL;
75  SizeType i = 1;
76  for (i = 1; i < dimensionsize; ++i)
77  {
78  matrix_[i] = new ValueType[i];
79  if (matrix_[i] == NULL)
80  {
81  SizeType j = i;
82  for (i = 1; i < j; i++)
83  {
84  delete[] matrix_[i];
85  }
86  delete[] matrix_;
87  matrix_ = NULL;
88  dimensionsize_ = 0;
89  init_size_ = 0;
90  throw Exception::OutOfMemory(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, (UInt)((((dimensionsize - 2) * (dimensionsize - 1)) / 2) * sizeof(ValueType)));
91  }
92  }
93  if (matrix_ != NULL)
94  {
95  for (i = 1; i < dimensionsize; ++i)
96  {
97  for (SizeType j = 0; j < i; ++j)
98  {
99  matrix_[i][j] = value;
100  }
101  }
102  min_element_ = std::make_pair(1, 0);
103  }
104  }
105 
113  matrix_(new ValueType*[source.dimensionsize_]),
114  init_size_(source.dimensionsize_),
116  min_element_(source.min_element_)
117  {
118  matrix_[0] = NULL;
119  SizeType i = 1;
120  for (i = 1; i < dimensionsize_; ++i)
121  {
122  matrix_[i] = new ValueType[i];
123  if (matrix_[i] == NULL)
124  {
125  SizeType j = i;
126  for (i = 1; i < j; i++)
127  {
128  delete[] matrix_[i];
129  }
130  delete[] matrix_;
131  matrix_ = NULL;
132  dimensionsize_ = 0;
133  init_size_ = 0;
134  min_element_ = std::make_pair(0, 0);
135  throw Exception::OutOfMemory(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(ValueType)));
136  }
137  }
138  if (matrix_ != NULL)
139  {
140  for (i = 1; i < dimensionsize_; ++i)
141  {
142  std::copy(source.matrix_[i], source.matrix_[i] + i, matrix_[i]);
143  }
144  }
145  }
146 
149  {
150  for (SizeType i = 1; i < init_size_; i++)
151  {
152  delete[] matrix_[i];
153  }
154  delete[] matrix_;
155  }
156 
164  {
165  return getValue(i, j);
166  }
167 
175  {
176  return getValue(i, j);
177  }
178 
187  {
188  if (i >= dimensionsize_ || j >= dimensionsize_)
189  {
190  throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
191  }
192  // elements on main diagonal are not stored and assumed to be 0
193  if (i == j)
194  {
195  return 0;
196  }
197  if (i < j)
198  {
199  std::swap(i, j);
200  }
201  return (const ValueType)(matrix_[i][j]);
202  }
203 
212  {
213  if (i >= dimensionsize_ || j >= dimensionsize_)
214  {
215  throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
216  }
217  // elements on main diagonal are not stored and assumed to be 0
218  if (i == j)
219  {
220  return 0;
221  }
222  if (i < j)
223  {
224  std::swap(i, j);
225  }
226  return matrix_[i][j];
227  }
228 
238  {
239  if (i >= dimensionsize_ || j >= dimensionsize_)
240  {
241  throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
242  }
243  // elements on main diagonal are not stored and assumed to be 0
244  if (i != j)
245  {
246  if (i < j)
247  {
248  std::swap(i, j);
249  }
250  if (i != min_element_.first && j != min_element_.second)
251  {
252  matrix_[i][j] = value;
253  if (value < matrix_[min_element_.first][min_element_.second]) // keep min_element_ up-to-date
254  {
255  min_element_ = std::make_pair(i, j);
256  }
257  }
258  else
259  {
260  if (value <= matrix_[min_element_.first][min_element_.second])
261  {
262  matrix_[i][j] = value;
263  }
264  else
265  {
266  matrix_[i][j] = value;
268  }
269  }
270  }
271  }
272 
284  {
285  if (i >= dimensionsize_ || j >= dimensionsize_)
286  {
287  throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
288  }
289  // elements on main diagonal are not stored and assumed to be 0
290  if (i != j)
291  {
292  if (i < j)
293  {
294  std::swap(i, j);
295  }
296  matrix_[i][j] = value;
297  }
298  }
299 
301  void clear()
302  {
303  for (SizeType i = 1; i < init_size_; i++)
304  {
305  delete[] matrix_[i];
306  }
307  delete[] matrix_;
308  matrix_ = nullptr;
309  min_element_ = std::make_pair(0, 0);
310  dimensionsize_ = 0;
311  init_size_ = 0;
312  }
313 
323  void resize(SizeType dimensionsize, Value value = Value())
324  {
325  for (SizeType j = 1; j < init_size_; j++)
326  {
327  delete[] matrix_[j];
328  }
329  delete[] matrix_;
332  min_element_ = std::make_pair(0, 0);
334  for (SizeType j = 1; j < dimensionsize_; ++j)
335  {
336  matrix_[j] = new ValueType[j];
337  if (matrix_[j] == nullptr)
338  {
339  for (SizeType k = 1; k < j; ++k)
340  {
341  delete[] matrix_[k];
342  }
343  delete[] matrix_;
344  matrix_ = nullptr;
345  dimensionsize_ = 0;
346  init_size_ = 0;
347  throw Exception::OutOfMemory(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(Value)));
348  }
349  }
350  if (matrix_ != nullptr)
351  {
352  for (SizeType j = 0; j < dimensionsize; ++j)
353  {
354  for (SizeType k = 0; k < j; ++k)
355  {
356  matrix_[j][k] = value;
357  }
358  }
359  min_element_ = std::make_pair(1, 0);
360  }
361  }
362 
371  void reduce(SizeType j)
372  {
373  if (j >= dimensionsize_)
374  {
375  throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
376  }
377  //delete row j and therefor overwrite with row j+1 and iterate like this to last row
378  SizeType i = j + 1;
379  while (i < dimensionsize_ && matrix_[i] != nullptr)
380  {
381  //left out in the copy is each rows jth element, pointer working here as iterators just fine
382  std::copy(matrix_[i] + j + 1, matrix_[i] + i, std::copy(matrix_[i], matrix_[i] + j, matrix_[i - 1]));
383  ++i;
384  }
385  //last row is freed and the pointer set to NULL (outer array's size is not changed)
386  delete[] matrix_[i - 1];
387  matrix_[i - 1] = nullptr;
388  --dimensionsize_;
389  }
390 
393  {
394  return dimensionsize_;
395  }
396 
403  {
404  min_element_ = std::make_pair(1, 0);
405  //error if dimensionsize_<1, return if dimensionsize_ == 1, else
406  if (dimensionsize_ < 1)
407  {
408  throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
409  }
410  if (dimensionsize_ != 1) //else matrix has one element: (1,0)
411  {
412  ValueType* row_min_;
413  for (SizeType r = 2; r < dimensionsize_ && matrix_[r] != nullptr; ++r)
414  {
415  row_min_ = std::min_element(matrix_[r], matrix_[r] + r);
416  if (*row_min_ < matrix_[min_element_.first][min_element_.second])
417  {
418  min_element_ = std::make_pair(r, row_min_ - matrix_[r]);
419  }
420  }
421  }
422  }
423 
429  bool operator==(DistanceMatrix<ValueType> const& rhs) const
430  {
431  OPENMS_PRECONDITION(dimensionsize_ == rhs.dimensionsize_, "DistanceMatrices have different sizes.");
432  for (Size i = 1; i < rhs.dimensionsize(); ++i)
433  {
434  for (Size j = 0; j < i; ++j)
435  {
436  if (matrix_[i][j] != rhs.matrix_[i][j])
437  {
438  return false;
439  }
440  }
441  }
442  return true;
443  }
444 
450  std::pair<SizeType, SizeType> getMinElementCoordinates() const
451  {
452  if (dimensionsize_ == 0)
453  {
454  throw Exception::OutOfRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
455  }
456  return min_element_;
457  }
458 
459 protected:
463  SizeType init_size_; // actual size of outer array
465  SizeType dimensionsize_; //number of virtual elements: ((dimensionsize-1)*(dimensionsize))/2
467  std::pair<SizeType, SizeType> min_element_;
468 
469 private:
472  {
473  matrix_ = rhs.matrix_;
474  init_size_ = rhs.init_size_;
477 
478  return *this;
479  }
480 
481  }; // class DistanceMatrix
482 
488  template <typename Value>
489  std::ostream& operator<<(std::ostream& os, const DistanceMatrix<Value>& matrix)
490  {
491  typedef typename DistanceMatrix<Value>::SizeType SizeType;
492 
493  std::ios_base::fmtflags flag_backup = os.setf(std::ios::scientific);
494  std::streamsize precision_backup = os.precision();
495  //~ os.precision(15);
496  os.precision(writtenDigits<double>(0.0)); // #include <OpenMS/CONCEPT/Types.h>
497 
498  //evtl. color lower triangular matrix o.s.l.t.
499  for (SizeType i = 0; i < matrix.dimensionsize(); ++i)
500  {
501  for (SizeType j = 0; j < matrix.dimensionsize(); ++j)
502  {
503  os << matrix(i, j) << '\t';
504  }
505  os << std::endl;
506  }
507  os.flags(flag_backup);
508  os.precision(precision_backup);
509  return os;
510  }
511 
512 } // namespace OpenMS
513 
A two-dimensional distance matrix, similar to OpenMS::Matrix.
Definition: DistanceMatrix.h:42
SizeType dimensionsize() const
gives the number of rows (i.e. number of columns)
Definition: DistanceMatrix.h:392
Value value_type
Definition: DistanceMatrix.h:47
std::ostream & operator<<(std::ostream &os, const DistanceMatrix< Value > &matrix)
Print the contents to a stream.
Definition: DistanceMatrix.h:489
DistanceMatrix()
default constructor
Definition: DistanceMatrix.h:59
bool operator==(DistanceMatrix< ValueType > const &rhs) const
Equality comparator.
Definition: DistanceMatrix.h:429
void setValue(SizeType i, SizeType j, ValueType value)
sets a value at a given position:
Definition: DistanceMatrix.h:237
void updateMinElement()
keep track of the actual minimum element after altering the matrix
Definition: DistanceMatrix.h:402
std::pair< SizeType, SizeType > getMinElementCoordinates() const
Indexpair of minimal element.
Definition: DistanceMatrix.h:450
const ValueType getValue(SizeType i, SizeType j) const
gets a value at a given position:
Definition: DistanceMatrix.h:186
ValueType getValue(SizeType i, SizeType j)
gets a value at a given position:
Definition: DistanceMatrix.h:211
const ValueType operator()(SizeType i, SizeType j) const
gets a value at a given position (read only):
Definition: DistanceMatrix.h:163
DistanceMatrix(const DistanceMatrix &source)
copy constructor
Definition: DistanceMatrix.h:112
Size SizeType
Definition: DistanceMatrix.h:52
std::pair< SizeType, SizeType > min_element_
index of minimal element(i.e. number in underlying SparseVector)
Definition: DistanceMatrix.h:467
ValueType operator()(SizeType i, SizeType j)
gets a value at a given position (read only):
Definition: DistanceMatrix.h:174
ValueType ** matrix_
sparse element not to be included in base container
Definition: DistanceMatrix.h:461
void setValueQuick(SizeType i, SizeType j, ValueType value)
sets a value at a given position:
Definition: DistanceMatrix.h:283
value_type ValueType
Definition: DistanceMatrix.h:53
~DistanceMatrix()
destructor
Definition: DistanceMatrix.h:148
SizeType init_size_
number of actually stored rows
Definition: DistanceMatrix.h:463
DistanceMatrix(SizeType dimensionsize, Value value=Value())
detailed constructor
Definition: DistanceMatrix.h:71
DistanceMatrix & operator=(const DistanceMatrix &rhs)
assignment operator (unsafe)
Definition: DistanceMatrix.h:471
void clear()
reset all
Definition: DistanceMatrix.h:301
SizeType dimensionsize_
number of accessibly stored rows (i.e. number of columns)
Definition: DistanceMatrix.h:465
void resize(SizeType dimensionsize, Value value=Value())
resizing the container
Definition: DistanceMatrix.h:323
void reduce(SizeType j)
reduces DistanceMatrix by one dimension. first the jth row, then jth column
Definition: DistanceMatrix.h:371
Out of memory exception.
Definition: Exception.h:435
Out of range exception.
Definition: Exception.h:287
unsigned int UInt
Unsigned integer type.
Definition: Types.h:68
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:101
#define OPENMS_PRECONDITION(condition, message)
Precondition macro.
Definition: openms/include/OpenMS/CONCEPT/Macros.h:94
const double k
Definition: Constants.h:132
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:22
constexpr Int writtenDigits< double >(const double &)
Number of digits commonly used for writing a double (a.k.a. precision).
Definition: Types.h:193