LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiSparseMatrix.h

00001 /*
00002  * Copyright (C) 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiSparseMatrix.h
00027  * authors ....: Bastian Ibach
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 26.04.02
00030  * revisions ..: $Id: ltiSparseMatrix.h,v 1.5 2006/02/08 12:45:53 ltilib Exp $
00031  */
00032 
00033 
00034 #ifndef _LTI_SPARSEMATRIX_H_
00035 #define _LTI_SPARSEMATRIX_H_
00036 
00037 #include "ltiMathObject.h"
00038 #include "ltiVector.h"
00039 #include "ltiMatrix.h"
00040 #include <vector>
00041 #include <map>
00042 #include <iostream>
00043 
00044 namespace lti {
00045   /**
00046    * SparseMatrix container class.
00047    *
00048    * The lti::sparseMatrix class allows the representation
00049    * of \e n x \e m matrices as sparse matrices (SM).
00050    *
00051    * The SM class is a container class implemented as template.
00052    *
00053    * All types defined in ltiTypes.h  except \c bool can be contained.
00054    *
00055    * A matrix is normaly defined as sparse if it contains a lot of zeros, in
00056    * this class you can use an arbitrary value denoted with \e sparseValue.
00057    *
00058    * Only the non-sparse values of the matrix are saved in the container
00059    * using the Compressed Row Storage format.
00060    *
00061    * Due to the characteristics of the storage, the method at() is here
00062    * a read-only one.  To write values into the matrix use the setAt() or
00063    * forceAt() methods.
00064    *
00065    * The Compressed Row Storage (CRS) format puts the subsequent nonsparse
00066    * values of the matrix rows in contiguous memory locations.
00067    *
00068    * The CRS format uses three vectors to store the non sparse values:
00069    * - values, type of T
00070    * - colIndex, type of int
00071    * - rowPtr, type of int
00072    *
00073    * In the \b values vector are saved the values of the non sparse elements
00074    * of the matrix, as they are traversed in a row-wise fashion.
00075    *
00076    * The \b colIndex vector stores the column indices of the elements
00077    * in the values vector.
00078    *
00079    * The \b rowPtr vector stores the position in the values vector that start a
00080    * new row. The vector size is equal number of rows plus one. The last value
00081    * in the rowPtr vector is needed to calculate the number of elements in the
00082    * last row of the matrix.
00083    *
00084    * Example:
00085    *
00086    * \code
00087    * matrix A = ( 0  2  5  0
00088    *              1  0  0  0
00089    *              0  4  0  6 )
00090    * \endcode
00091    *
00092    *
00093    * The CRS format for the matrix A is specified by the vectors given below:
00094    *
00095    * \code
00096    * values   = ( 2  5  1  4  6 )
00097    * colIndex = ( 1  2  0  1  3 )
00098    *
00099    * rowPtr   = ( 0  2  3  5 )
00100    * \endcode
00101    *
00102    * The \b iterators of the sparse matrices visit only the non sparse values,
00103    * as this is usually the required task.
00104    *
00105    * You can use the getPosition() methods to gain the index of the element
00106    * pointed by an iterator.  If for each non-sparse element you need to
00107    * compute its index, it is more efficient to avoid iterators and using the
00108    * data structures of the CRS directly:
00109    *
00110    * \code
00111    *
00112    * // assume you are in a template class/method of type T, or that type
00113    * // T is somehow defined (for example typedef float T)
00114    *
00115    * lti::point p; // the coordinates
00116    * lti::sparseMatrix<T> smat; 
00117    *
00118    * // ... fill the sparse matrix with data here
00119    *
00120    * const lti::ivector& rows     = smat.getRowPtr();
00121    * const std::vector<int>& cols = smat.getColIndex();
00122    * const std::vector<T>& vals   = smat.getValues();
00123    *
00124    * int i,f,l;
00125    * T val; 
00126    *
00127    * // for each row
00128    * for (p.y=0;p.y<rows.lastIdx();++p.y) {
00129    *   f=rows.at(p.y);       // first row element
00130    *   l=rows.at(p.y+1);     // last row element
00131    *   for (i=f;i<l;++i) { // for each element in row
00132    *     p.x=cols[i];
00133    *     val=vals[i];
00134    *     // the matrix element at \c p contains value \c val
00135    *     // here you can do whatever you need to...
00136    *   }
00137    * }
00138    *
00139    * \endcode
00140    *
00141    * @ingroup gAggregate
00142    * @ingroup gLinearAlgebra
00143    */
00144   template<class T>
00145   class sparseMatrix : public mathObject {
00146   public:
00147 
00148     /**
00149      * type of the contained data
00150      */
00151     typedef T value_type;
00152 
00153     /**
00154      * iterator
00155      * the iterator points to one element of the values vector
00156      * you only have access to these values, not to the sparseValues
00157      */
00158     typedef typename std::vector<T>::iterator iterator;
00159 
00160 
00161     /**
00162      * const_iterator
00163      * the const_iterator points to one element of the values vector
00164      * you only have access to these values, not to the sparseValues
00165      */
00166     typedef typename std::vector<T>::const_iterator const_iterator;
00167 
00168 
00169     /**
00170      * default constructor creates an empty sparseMatrix
00171      */
00172     sparseMatrix();
00173 
00174     /**
00175      * construct a sparse matrix of the given size and fill it
00176      * with the given value (i.e. use the given value as sparse value).
00177      */
00178     sparseMatrix(const int theRows,const int theCols,const T& sparseVal=T());
00179 
00180     /**
00181      * construct a sparse matrix of the given size and fill it
00182      * with the given value (i.e. use the given value as sparse value).
00183      */
00184     sparseMatrix(const point& size,const T& sparseVal=T());
00185 
00186     /**
00187      * copy constructor.
00188      *
00189      * create this sparseMatrix as a connected copy of another sparseMatrix
00190      * for this const version, the data will be always copied!
00191      *
00192      * @param other the sparseMatrix to be copied.
00193      */
00194     sparseMatrix(const sparseMatrix<T>& other);
00195 
00196     /**
00197      * destructor
00198      */
00199     virtual ~sparseMatrix();
00200 
00201     /**
00202      * resize the given sparse matrix and fill it with the given
00203      * value.
00204      * It is not possible to keep the old data when resizing
00205      * the matrix.
00206      */
00207     bool resize(const int rows,const int cols,const T& sparseVal);
00208 
00209     /**
00210      * resize the given sparse matrix and fill it with the given
00211      * value.
00212      * It is not possible to keep the old data when resizing
00213      * the matrix.
00214      */
00215     bool resize(const point& size,const T& sparseVal);
00216 
00217     /**
00218      * convert matrix to SparseMatrix
00219      *
00220      * @param srcMatrix the matrix converted to sparseMatrix
00221      * @param sValue the value of srcMatrix used as sparseValue
00222      * in the sparseMatrix
00223      * @return a reference to this object.
00224      */
00225     sparseMatrix<T>& castFrom(const matrix<T>& srcMatrix, const T& sValue);
00226 
00227     /**
00228      * convert matrix to SparseMatrix
00229      *
00230      * The value of the srcMatrix used as sparseValue is chosen by
00231      * statistical evaluation  (the most used one), which of course
00232      * cost some time.
00233      *
00234      * @param srcMatrix the matrix to be converted into a sparseMatrix
00235      * @return a reference to this object.
00236      */
00237     sparseMatrix<T>& castFrom(const matrix<T>& srcMatrix);
00238 
00239     /**
00240      * convert the other sparse matrix of type U to this sparse matrix
00241      * of type T
00242      */
00243     template<class U>
00244     sparseMatrix<T>& castFrom(const sparseMatrix<U>& other) {
00245       if(&other == this) { // Caution could be the same Matrix
00246         return(*this);
00247       }
00248 
00249       theSize = other.size();
00250       typename std::vector<U>::const_iterator oit;
00251       typename std::vector<T>::iterator it;
00252       values.resize(other.getValues().size());
00253       for (oit=other.values.begin(),it=values.begin();
00254            it!=values.end();
00255            ++it,++oit) {
00256         *it = static_cast<T>(*oit);
00257       }
00258 
00259       colIndex = other.getColIndex();
00260       rowPtr = other.getRowPtr();
00261       numNonSparseValues = other.getNumNonSparseValues();
00262       sparseValue = static_cast<T>(other.sparseValue);
00263       return (*this);
00264     }
00265 
00266     /**
00267      * convert SparseMatrix to matrix
00268      * @param destMatrix the lti::matrix where this sparseMatrix will be
00269      *        copied into.
00270      */
00271     bool castTo(matrix<T>& destMatrix);
00272 
00273     /**
00274      * copy the contents of other to this object
00275      * @param other the matrix to be copied
00276      */
00277     sparseMatrix<T>& copy(const sparseMatrix<T>& other);
00278 
00279     /**
00280      * iterator begin
00281      */
00282     iterator begin();
00283 
00284     /**
00285      * iterator end
00286      */
00287     iterator end();
00288 
00289     /**
00290      * const_iterator begin
00291      */
00292     const_iterator begin() const;
00293 
00294     /**
00295      * const_iterator end
00296      */
00297     const_iterator end() const;
00298 
00299     /**
00300      * access element at the given row and column
00301      * @param row the row of the element
00302      * @param col the column of the element
00303      * @return a reference to the matrix element
00304      */
00305     inline const T& at(const int row, const int col) const {
00306       return getAt(row,col);
00307     }
00308 
00309     /**
00310      * access element at the given row and column
00311      * @param row the row of the element
00312      * @param col the column of the element
00313      * @return the value of the matrix element
00314      */
00315     const T& getAt(const int row, const int col) const;
00316 
00317     /**
00318      * get a read-write reference to the given element, and in case
00319      * the element was a "sparse" one, insert it first (with the sparse
00320      * value.
00321      *
00322      * You can for example use this method, when you want to increment the
00323      * elements in a sparse matrix:
00324      * \code
00325      * sparseMatrix<int> sparseMat(1000,1000,0);
00326      * sparseMat.setAt(row,col,getAt(row,col)+1);
00327      * \endcode
00328      * is very inefficient, because the element at (row,col) must be
00329      * search twice.
00330      * On the other hand
00331      * \code
00332      * sparseMat.forceAt(row,col)++;
00333      * \endcode
00334      * makes just one access to the point and returns a reference.
00335      *
00336      * Note that if you just call forceAt without explicitelly changing
00337      * the value thereafter, you will have sparseElement as normal elements
00338      * in your matrix.  So, please use with care.  The normal way to
00339      * reset a value with the sparseValue is using setAt(row,col,sparseValue).
00340      */
00341     T& forceAt(const int row, const int col);
00342 
00343     /**
00344      * get a read-write reference to the given element, and in case
00345      * the element was a "sparse" one, insert it first.
00346      */
00347     inline T& forceAt(const point& p) {
00348       return forceAt(p.y,p.x);
00349     }
00350 
00351     /**
00352      * modify element at the given row and column
00353      * @param row the row of the element
00354      * @param col the column of the element
00355      * @param newValue new value for a matrix element
00356      * @return true if existing value is changed or
00357      * false if sparseValue is replaced by element
00358      */
00359     bool setAt(const int row, const int col, const T newValue);
00360 
00361     /**
00362      * modify element at point
00363      * @param position index of the element in sparseMatrix to be set
00364      * @param newValue new value for a matrix element
00365      * @return true if existing value is changed or false if
00366      * sparseValue is replaced by element
00367      */
00368     inline bool setAt(const point& position, const T newValue) {
00369       return setAt(position.y,position.x,newValue);
00370     }
00371 
00372     /**
00373      * insert element at the given row and column
00374      * @param iniValue the value to fill the (sub-)matrix with
00375      * @param fromRow the row to begin fill
00376      * @param fromCol the column to begin fill
00377      * @param toRow the last row to fill
00378      * @param toCol the last col to fill
00379      */
00380     void fill(const T& iniValue,
00381               const int& fromRow=0,
00382               const int& fromCol=0,
00383               const int& toRow=MaxInt32,
00384               const int& toCol=MaxInt32);
00385 
00386     /**
00387      * clear sparseMatrix to get a empty sparseMatrix
00388      * sparseValue is set to zero
00389      */
00390     void clear();
00391 
00392     /**
00393      * returns true if there are only "sparse values" on
00394      * the matrix.
00395      */
00396     bool empty() const;
00397 
00398     /**
00399      * get the position in the matrix of the iterator
00400      * @param iter iterator that points to a non-sparse element
00401      * @return point with index of the pointed element
00402      */
00403     point getPosition(const iterator& iter);
00404 
00405     /**
00406      * get the position in the matrix of the const_iterator
00407      * @param iter const_iterator that points to a non-sparse element
00408      * @return point with index of the pointed element
00409      */
00410     point getPosition(const const_iterator& iter);
00411 
00412     /**
00413      * get a copy of the row of the matrix
00414      * @param row the row to be accessed
00415      * @return a vector with the contents of the row of the matrix
00416      */
00417     lti::vector<T> getRowCopy(const int& row) const;
00418 
00419     /**
00420      * get a copy of the column of the matrix
00421      * @param col the column to be accessed
00422      * @return a vector with the contents of the column of the matrix
00423      */
00424     lti::vector<T> getColumnCopy(const int& col) const;
00425 
00426     /**
00427      * @return the name of this class: "sparseMatrix"
00428      */
00429     virtual const char* getTypeName() const;
00430 
00431     /**
00432      * create a clone of this matrix
00433      * @return a pointer to a copy of this matrix
00434      */
00435     virtual mathObject* clone() const;
00436 
00437     /**
00438      * assignment operator (alias for copy(other))
00439      *
00440      * @param other the matrix to be copied
00441      * @returns a reference to the actual matrix
00442      */
00443     sparseMatrix<T>& operator=(const sparseMatrix<T>& other);
00444 
00445     /**
00446      * compare this sparseMatrix with other
00447      *
00448      * @param other the sparseMatrix to be compared with
00449      * @return true if both sparseMatrices have the same SparseValue
00450      * the same values-, colIndex- and rowPtr-vector
00451      */
00452     bool operator==(const sparseMatrix<T> other) const;
00453 
00454     /**
00455      * returns size of the sparseMatrix
00456      */
00457     const point& size() const;
00458 
00459     /**
00460      * returns the number of non-sparse valued elements in the sparseMatrix
00461      */
00462     int getNumNonSparseValues() const;
00463 
00464     /**
00465      * return the used sparse value
00466      */
00467     T getSparseValue() const;
00468 
00469     /**
00470      * return the number of columns of the matrix
00471      */
00472     inline const int& columns() const {
00473       return numCols;
00474     }
00475 
00476     /**
00477      * return the number of columns of the matrix
00478      */
00479     inline const int& rows() const {
00480       return numRows;
00481     }
00482 
00483     /**
00484      * @name Arithmetical Operations
00485      */
00486     //@{
00487 
00488     /**
00489      * alias for add(const T value)
00490      *
00491      * @param value the value added to each element of the matrix
00492      * @returns a reference to the actual matrix
00493      */
00494     sparseMatrix<T>& operator+=(const T value);
00495 
00496     /**
00497      * add a constant value to this matrix and leave result in new matrix
00498      *
00499      * @param value the value added to each element of the matrix
00500      * @returns a new matrix with the result
00501      */
00502     sparseMatrix<T> operator+(const T value) const;
00503 
00504     /**
00505      * alias for multiply(const T value)
00506      *
00507      * @param value the constant value
00508      * @return a reference to the actual matrix
00509      */
00510     sparseMatrix<T>& operator*=(const T value);
00511 
00512     /**
00513      * add a constant value to all elements of the matrix
00514      * and leave the result here
00515      * @param value the constant value
00516      * @return return a reference to the actual matrix
00517      */
00518     sparseMatrix<T>& add(const T value);
00519 
00520     /**
00521      * devide the elements of the matrix by a constant value
00522      * and leave the result here
00523      * @param value the constant value (divisor)
00524      * @return return a reference to the actual matrix
00525      */
00526     sparseMatrix<T>& divide(const T value);
00527 
00528     /**
00529      * multiply the elements of the matrix by a constant value
00530      * and leave the result there
00531      * @param value the constant value
00532      * @return a reference to the actual matrix
00533      */
00534     sparseMatrix<T>& multiply(const T value);
00535 
00536     /**
00537      * multiply sparseMatrix with vector, write result
00538      * to a new vector
00539      *
00540      * @param srcVec vector to be multiplied with,
00541      * Its dimension must be equal to the number of columns of the matrix.
00542      * @param destVec vector to write result to
00543      * Its dimension will be equal to the number of rows of the matrix.
00544      */
00545     void multiply(const vector<T>& srcVec, vector<T>& destVec) const;
00546 
00547     /**
00548      * transpose sparseMatrix
00549      *
00550      * @return return a reference to the sparseMatrix
00551      */
00552     sparseMatrix<T> transpose();
00553 
00554     /**
00555      * get maximum value of the matrix
00556      * @return return a copy of this value
00557      */
00558     T maximum() const;
00559 
00560     /**
00561      * get index of maximum value of the matrix
00562      * @return return a copy of the index as a point
00563      */
00564     point getIndexOfMaximum() const;
00565 
00566     /**
00567      * get minimum value of the matrix
00568      * @return return a copy of this value
00569      */
00570     T minimum() const;
00571 
00572     /**
00573      * get index of minimum value of the matrix
00574      * @return return a copy of the index as a point
00575      */
00576     point getIndexOfMinimum() const;
00577     //@}
00578 
00579     /**
00580      * @name Input and Output
00581      */
00582     //@{
00583 
00584     /**
00585      * write the object in the given ioHandler
00586      */
00587     virtual bool write(ioHandler& handler,const bool complete = true) const;
00588 
00589     /**
00590      * read the object from the given ioHandler
00591      */
00592     virtual bool read(ioHandler& handler,const bool complete = true);
00593 
00594     //@}
00595 
00596     /**
00597      * Following methods allow the access to the internal data structures,
00598      * which can be used to access very efficiently the non-sparse elements
00599      * in the rows of the matrix.
00600      */
00601     //@{
00602     /**
00603      * returns values vector
00604      */
00605     const std::vector<T>& getValues() const;
00606 
00607     /**
00608      * returns colIndex vector
00609      * vector of int
00610      */
00611     const std::vector<int>& getColIndex() const;
00612 
00613     /**
00614      * returns rowPtr vector
00615      * vector of int
00616      */
00617     const lti::vector<int>& getRowPtr() const;
00618     //@}
00619 
00620   private:
00621 
00622     /**
00623      * theSize.x is equal numColumns and theSize.y is equal numRows
00624      */
00625     point theSize;
00626 
00627     /**
00628      * number of rows of the sparseMatrix
00629      */
00630     int& numRows;
00631 
00632     /**
00633      * number of columns of the sparseMatrix
00634      */
00635     int& numCols;
00636 
00637     /**
00638      * number of non zero values
00639      */
00640     int numNonSparseValues;
00641 
00642     /**
00643      * value which is sparse, normaly this is zero
00644      */
00645     T sparseValue;
00646 
00647     /**
00648      * vector of type T, containing the non-sparse values of the sparseMatrix
00649      * Format: Compressed Row Storage
00650      */
00651     std::vector<T> values;
00652 
00653     /**
00654      * vector of int, containing the column indices of the non Zero values
00655      * must have the same size as the vector with the values
00656      */
00657     std::vector<int> colIndex;
00658 
00659     /**
00660      * vector of int, containing the position in the values vector, where
00661      * a new row begins
00662      */
00663     lti::vector<int> rowPtr;
00664 
00665     /*
00666      * !!! for internal use only !!
00667      *
00668      * setSparseValue, insert sparseValue at given row and column
00669      *
00670      *
00671     bool setSparseValue(const int& row, const int&col,
00672                         const T& value);
00673   */
00674 
00675     /**
00676      * !!! for internal use only !!
00677      *
00678      * setSparseValue, insert sparseValue at given row and column
00679      *
00680      */
00681     bool setSparseValue(const int& row, const int& col);
00682 
00683     /**
00684      * !!! for internal use only !!
00685      *
00686      * fillSparseValue, fill region of sparseMatrix with sparseValue
00687      *
00688      */
00689     bool fillSparseValue(const int& fromRow, const int& fromCol,
00690                          const int& toRow, const int& toCol);
00691 
00692   };
00693 
00694 }
00695 
00696 namespace std {
00697 
00698   /**
00699    * outputs the elements of the vector on a stream
00700    */
00701   template <class T>
00702   ostream& operator<<(ostream& outStr, const lti::sparseMatrix<T>& sMatrix);
00703 }
00704 
00705 
00706 #endif

Generated on Sat Apr 10 15:26:14 2010 for LTI-Lib by Doxygen 1.6.1