Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

DistanceMatrix.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Mathias Walzer $
00032 // $Authors: $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_DATASTRUCTURES_DISTANCEMATRIX_H
00036 #define OPENMS_DATASTRUCTURES_DISTANCEMATRIX_H
00037 
00038 #include <OpenMS/CONCEPT/Macros.h>
00039 #include <OpenMS/CONCEPT/Types.h>
00040 
00041 #include <cmath>
00042 #include <algorithm>
00043 #include <iomanip>
00044 #include <iostream>
00045 
00046 namespace OpenMS
00047 {
00048 
00056   template <typename Value>
00057   class DistanceMatrix
00058   {
00059 public:
00060 
00062 
00063     typedef Value value_type;
00065 
00067 
00068     typedef Size SizeType;
00069     typedef value_type ValueType;
00071 
00075     DistanceMatrix() :
00076       matrix_(0), init_size_(0), dimensionsize_(0), min_element_(0, 0)
00077     {
00078     }
00079 
00086     DistanceMatrix(SizeType dimensionsize, Value value = Value()) :
00087       matrix_(new ValueType *[dimensionsize]), init_size_(dimensionsize), dimensionsize_(dimensionsize), min_element_(0, 0)
00088     {
00089       matrix_[0] = NULL;
00090       SizeType i = 1;
00091       for (i = 1; i < dimensionsize; ++i)
00092       {
00093         matrix_[i] = new ValueType[i];
00094         if (matrix_[i] == NULL)
00095         {
00096           SizeType j = i;
00097           for (i = 1; i < j; i++)
00098           {
00099             delete[] matrix_[i];
00100           }
00101           delete[] matrix_;
00102           matrix_ = NULL;
00103           dimensionsize_ = 0;
00104           init_size_ = 0;
00105           throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, (UInt)((((dimensionsize - 2) * (dimensionsize - 1)) / 2) * sizeof(ValueType)));
00106         }
00107       }
00108       if (matrix_ != NULL)
00109       {
00110         for (i = 1; i < dimensionsize; ++i)
00111         {
00112           for (SizeType j = 0; j < i; ++j)
00113           {
00114             matrix_[i][j] = value;
00115           }
00116         }
00117         min_element_ = std::make_pair(1, 0);
00118       }
00119     }
00120 
00126     DistanceMatrix(const DistanceMatrix & source) :
00127       matrix_(new ValueType *[source.dimensionsize_]),
00128       init_size_(source.dimensionsize_),
00129       dimensionsize_(source.dimensionsize_),
00130       min_element_(source.min_element_)
00131     {
00132       matrix_[0] = NULL;
00133       SizeType i = 1;
00134       for (i = 1; i < dimensionsize_; ++i)
00135       {
00136         matrix_[i] = new ValueType[i];
00137         if (matrix_[i] == NULL)
00138         {
00139           SizeType j = i;
00140           for (i = 1; i < j; i++)
00141           {
00142             delete[] matrix_[i];
00143           }
00144           delete[] matrix_;
00145           matrix_ = NULL;
00146           dimensionsize_ = 0;
00147           init_size_ = 0;
00148           min_element_ = std::make_pair(0, 0);
00149           throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(ValueType)));
00150         }
00151       }
00152       if (matrix_ != NULL)
00153       {
00154         for (i = 1; i < dimensionsize_; ++i)
00155         {
00156           std::copy(source.matrix_[i], source.matrix_[i] + i, matrix_[i]);
00157         }
00158       }
00159     }
00160 
00162     ~DistanceMatrix()
00163     {
00164       for (SizeType i = 1; i < init_size_; i++)
00165       {
00166         delete[] matrix_[i];
00167       }
00168       delete[] matrix_;
00169     }
00170 
00176     const ValueType operator()(SizeType i, SizeType j) const
00177     {
00178       return getValue(i, j);
00179     }
00180 
00186     ValueType operator()(SizeType i, SizeType j)
00187     {
00188       return getValue(i, j);
00189     }
00190 
00197     const ValueType getValue(SizeType i, SizeType j) const
00198     {
00199       if (i >= dimensionsize_ || j >= dimensionsize_)
00200       {
00201         throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00202       }
00203       // elements on main diagonal are not stored and assumed to be 0
00204       if (i == j)
00205       {
00206         return 0;
00207       }
00208       if (i < j)
00209       {
00210         std::swap(i, j);
00211       }
00212       return (const ValueType)(matrix_[i][j]);
00213     }
00214 
00221     ValueType getValue(SizeType i, SizeType j)
00222     {
00223       if (i >= dimensionsize_ || j >= dimensionsize_)
00224       {
00225         throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00226       }
00227       // elements on main diagonal are not stored and assumed to be 0
00228       if (i == j)
00229       {
00230         return 0;
00231       }
00232       if (i < j)
00233       {
00234         std::swap(i, j);
00235       }
00236       return matrix_[i][j];
00237     }
00238 
00246     void setValue(SizeType i, SizeType j, ValueType value)
00247     {
00248       if (i >= dimensionsize_ || j >= dimensionsize_)
00249       {
00250         throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00251       }
00252       // elements on main diagonal are not stored and assumed to be 0
00253       if (i != j)
00254       {
00255         if (i < j)
00256         {
00257           std::swap(i, j);
00258         }
00259         if (i != min_element_.first && j != min_element_.second)
00260         {
00261           matrix_[i][j] = value;
00262           if (value < matrix_[min_element_.first][min_element_.second])          // keep min_element_ up-to-date
00263           {
00264             min_element_ = std::make_pair(i, j);
00265           }
00266         }
00267         else
00268         {
00269           if (value <= matrix_[min_element_.first][min_element_.second])
00270           {
00271             matrix_[i][j] = value;
00272           }
00273           else
00274           {
00275             matrix_[i][j] = value;
00276             updateMinElement();
00277           }
00278         }
00279       }
00280     }
00281 
00291     void setValueQuick(SizeType i, SizeType j, ValueType value)
00292     {
00293       if (i >= dimensionsize_ || j >= dimensionsize_)
00294       {
00295         throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00296       }
00297       // elements on main diagonal are not stored and assumed to be 0
00298       if (i != j)
00299       {
00300         if (i < j)
00301         {
00302           std::swap(i, j);
00303         }
00304         matrix_[i][j] = value;
00305       }
00306     }
00307 
00309     void clear()
00310     {
00311       for (SizeType i = 1; i < init_size_; i++)
00312       {
00313         delete[] matrix_[i];
00314       }
00315       delete[] matrix_;
00316       matrix_ = NULL;
00317       min_element_ = std::make_pair(0, 0);
00318       dimensionsize_ = 0;
00319       init_size_ = 0;
00320     }
00321 
00330     void resize(SizeType dimensionsize, Value value = Value())
00331     {
00332       for (SizeType j = 1; j < init_size_; j++)
00333       {
00334         delete matrix_[j];
00335       }
00336       delete[] matrix_;
00337       dimensionsize_ = dimensionsize;
00338       init_size_ = dimensionsize;
00339       min_element_ = std::make_pair(0, 0);
00340       matrix_ = new ValueType *[dimensionsize_];
00341       for (SizeType j = 1; j < dimensionsize_; ++j)
00342       {
00343         matrix_[j] = new ValueType[j];
00344         if (matrix_[j] == NULL)
00345         {
00346           for (SizeType k = 1; k < j; ++k)
00347           {
00348             delete[] matrix_[k];
00349           }
00350           delete[] matrix_;
00351           matrix_ = NULL;
00352           dimensionsize_ = 0;
00353           init_size_ = 0;
00354           throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, (UInt)((((dimensionsize_ - 2) * (dimensionsize_ - 1)) / 2) * sizeof(Value)));
00355         }
00356       }
00357       if (matrix_ != NULL)
00358       {
00359         for (SizeType j = 0; j < dimensionsize; ++j)
00360         {
00361           for (SizeType k = 0; k < j; ++k)
00362           {
00363             matrix_[j][k] = value;
00364           }
00365         }
00366         min_element_ = std::make_pair(1, 0);
00367       }
00368     }
00369 
00377     void reduce(SizeType j)
00378     {
00379       if (j >= dimensionsize_)
00380       {
00381         throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00382       }
00383       //delete row j and therefor overwrite with row j+1 and iterate like this to last row
00384       SizeType i = j + 1;
00385       while (i < dimensionsize_ && matrix_[i] != NULL)
00386       {
00387         //left out in the copy is each rows jth element, pointer working here as iterators just fine
00388         std::copy(matrix_[i] + j + 1, matrix_[i] + i, std::copy(matrix_[i], matrix_[i] + j, matrix_[i - 1]));
00389         ++i;
00390       }
00391       //last row is freed and the pointer set to NULL (outer array's size is not changed)
00392       delete[] matrix_[i - 1];
00393       matrix_[i - 1] = NULL;
00394       --dimensionsize_;
00395     }
00396 
00398     SizeType dimensionsize() const
00399     {
00400       return dimensionsize_;
00401     }
00402 
00407     void updateMinElement()
00408     {
00409       min_element_ = std::make_pair(1, 0);
00410       //error if dimensionsize_<1, return if dimensionsize_ == 1, else
00411       if (dimensionsize_ < 1)
00412       {
00413         throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00414       }
00415       if (dimensionsize_ != 1)    //else matrix has one element: (1,0)
00416       {
00417         ValueType * row_min_;
00418         for (SizeType r = 2; r < dimensionsize_ && matrix_[r] != NULL; ++r)
00419         {
00420           row_min_ = std::min_element(matrix_[r], matrix_[r] + r);
00421           if (*row_min_ < matrix_[min_element_.first][min_element_.second])
00422           {
00423             min_element_ = std::make_pair(r, row_min_ - matrix_[r]);
00424           }
00425         }
00426       }
00427     }
00428 
00433     bool operator==(DistanceMatrix<ValueType> const & rhs) const
00434     {
00435       OPENMS_PRECONDITION(dimensionsize_ == rhs.dimensionsize_, "DistanceMatrices have different sizes.");
00436       for (Size i = 1; i < rhs.dimensionsize(); ++i)
00437       {
00438         for (Size j = 0; j < i; ++j)
00439         {
00440           if (matrix_[i][j] != rhs.matrix_[i][j])
00441           {
00442             return false;
00443           }
00444         }
00445       }
00446       return true;
00447     }
00448 
00453     std::pair<SizeType, SizeType> getMinElementCoordinates() const
00454     {
00455       if (dimensionsize_ == 0)
00456       {
00457         throw Exception::OutOfRange(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00458       }
00459       return min_element_;
00460     }
00461 
00462 protected:
00464     ValueType ** matrix_;
00466     SizeType init_size_;     // actual size of outer array
00468     SizeType dimensionsize_;     //number of virtual elements: ((dimensionsize-1)*(dimensionsize))/2
00470     std::pair<SizeType, SizeType> min_element_;
00471 
00472 private:
00474     DistanceMatrix & operator=(const DistanceMatrix & rhs)
00475     {
00476       matrix_ = rhs.matrix_;
00477       init_size_ = rhs.init_size_;
00478       dimensionsize_ = rhs.dimensionsize_;
00479       min_element_ = rhs.min_element_;
00480 
00481       return *this;
00482     }
00483 
00484   };   // class DistanceMatrix
00485 
00490   template <typename Value>
00491   std::ostream & operator<<(std::ostream & os, const DistanceMatrix<Value> & matrix)
00492   {
00493     typedef typename DistanceMatrix<Value>::SizeType SizeType;
00494 
00495     std::ios_base::fmtflags flag_backup = os.setf(std::ios::scientific);
00496     std::streamsize precision_backup = os.precision();
00497     //~ os.precision(15);
00498     os.precision(writtenDigits<DoubleReal>());     // #include <OpenMS/CONCEPT/Types.h>
00499 
00500     //evtl. color lower triangular matrix o.s.l.t.
00501     for (SizeType i = 0; i < matrix.dimensionsize(); ++i)
00502     {
00503       for (SizeType j = 0; j < matrix.dimensionsize(); ++j)
00504       {
00505         os << matrix(i, j) << '\t';
00506       }
00507       os << std::endl;
00508     }
00509     os.flags(flag_backup);
00510     os.precision(precision_backup);
00511     return os;
00512   }
00513 
00514 } // namespace OpenMS
00515 
00516 #endif // OPENMS_DATASTRUCTURES_DISTANCEMATRIX_H

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:38 using doxygen 1.7.1