SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SparseRowMatrix.h
Go to the documentation of this file.
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2012 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27 */
28 
29 
30 #ifndef CORE_DATATYPES_SPARSE_MATRIX_H
31 #define CORE_DATATYPES_SPARSE_MATRIX_H
32 
33 #include <Core/Datatypes/Matrix.h>
34 #include <Core/Math/MiscMath.h>
35 #define register
36 #include <Eigen/SparseCore>
37 #undef register
38 
39 namespace SCIRun {
40 namespace Core {
41 namespace Datatypes {
42 
43  template <typename T>
44  class SparseRowMatrixGeneric : public MatrixBase<T>, public Eigen::SparseMatrix<T, Eigen::RowMajor, index_type>
45  {
46  public:
47  typedef T value_type;
49  typedef Eigen::SparseMatrix<T, Eigen::RowMajor, index_type> EigenBase;
50  typedef Eigen::Triplet<T> Triplet;
51 
52  /// @todo: need C++11
53  //using Base::Base;
54 
56  SparseRowMatrixGeneric(int nrows, int ncols) : EigenBase(nrows, ncols) {}
57 
58  ///Legacy construction compatibility. Useful for converting old code, but should be avoided in new code.
59  SparseRowMatrixGeneric(int nrows, int ncols, const index_type* rowCounter, const index_type* columnCounter, size_t nnz) : EigenBase(nrows, ncols)
60  {
61  if (rowCounter[nrows] != nnz)
62  THROW_INVALID_ARGUMENT("Invalid sparse row matrix array: row accumulator array does not match number of non-zero elements.");
63  std::vector<Triplet> triplets;
64  triplets.reserve(nnz);
65 
66  int i = 0;
67  int j = 0;
68  while (i < nrows)
69  {
70  while (j < rowCounter[i + 1])
71  {
72  index_type column = columnCounter[j];
73  if (column >= ncols)
74  THROW_INVALID_ARGUMENT("Invalid sparse row matrix array: column index out of bounds.");
75  triplets.push_back(Triplet(i, columnCounter[j], 0));
76  j++;
77  }
78  i++;
79  }
80  this->setFromTriplets(triplets.begin(), triplets.end());
81  }
82 
83  /// This constructor allows you to construct SparseRowMatrixGeneric from Eigen expressions
84  template<typename OtherDerived>
85  SparseRowMatrixGeneric(const Eigen::SparseMatrixBase<OtherDerived>& other)
86  : EigenBase(other)
87  { }
88 
89  /// This method allows you to assign Eigen expressions to SparseRowMatrixGeneric
90  template<typename OtherDerived>
91  SparseRowMatrixGeneric& operator=(const Eigen::SparseMatrixBase<OtherDerived>& other)
92  {
93  this->EigenBase::operator=(other);
94  return *this;
95  }
96 
97  virtual SparseRowMatrixGeneric* clone() const
98  {
99  return new SparseRowMatrixGeneric(*this);
100  }
101 
102  virtual size_t nrows() const { return this->rows(); }
103  virtual size_t ncols() const { return this->cols(); }
104 
105  const index_type* get_rows() const { return this->outerIndexPtr(); }
106  const index_type* get_cols() const { return this->innerIndexPtr(); }
107 
108  virtual void accept(MatrixVisitorGeneric<T>& visitor)
109  {
110  visitor.visit(*this);
111  }
112 
113  bool isSymmetric() const
114  {
115  if (this->cols() != this->rows())
116  return false;
117 
118  if (this->rows() * this->cols() > 1e7)
119  THROW_INVALID_ARGUMENT("Dangerous call! This poorly implememented method will convert your sparse matrix to dense. It needs to be rewritten. To avoid memory wastage, throwing an exception here.");
120 
121  return this->isApprox(this->transpose(),1e-16);
122  }
123 
124  virtual T get(int i, int j) const override
125  {
126  return this->coeff(i,j);
127  }
128  virtual void put(int i, int j, const T& val) override
129  {
130  this->coeffRef(i,j) = val;
131  }
132 
133  /// @todo!
134 #if 0
135  class NonZeroIterator : public std::iterator<std::forward_iterator_tag, value_type>
136  {
137  public:
138  typedef NonZeroIterator my_type;
139  typedef this_type matrix_type;
140  typedef typename std::iterator<std::forward_iterator_tag, value_type> my_base;
141  //typedef typename my_base::value_type value_type;
142  typedef typename my_base::pointer pointer;
143 
144  private:
145  const matrix_type* matrix_;
146  typedef typename matrix_type::EigenBase::InnerIterator IteratorPrivate;
147  boost::scoped_ptr<IteratorPrivate> impl_;
148  //size_type block_i_, block_j_, rowInBlock_;
149 
150  //typedef typename ElementType::ImplType block_impl_type;
151  //typedef typename boost::numeric::ublas::matrix_row<const block_impl_type> block_row_type;
152  //typedef typename block_row_type::iterator block_row_iterator;
153 
154  //boost::shared_ptr<block_row_type> currentRow_;
155  //block_row_iterator rowIter_;
156  //size_type numRowPartitions_, numColPartitions_;
157  int currentRow_;
158  bool isEnd_;
159 
160  public:
161  explicit NonZeroIterator(const matrix_type* matrix = 0) : matrix_(matrix),
162  currentRow_(0)
163  //block_i_(0), block_j_(0), rowInBlock_(0)
164  {
165  if (matrix && matrix->nonZeros() > 0)
166  {
167  impl_.reset(new IteratorPrivate(matrix,0));
168  isEnd_ = !*impl_;
169  }
170  else
171  {
172  isEnd_ = true;
173  }
174  }
175  //private:
176  // void resetRow()
177  // {
178  // currentRow_.reset(new block_row_type((*blockMatrix_)(block_i_, block_j_).impl_, rowInBlock_));
179  // rowIter_ = currentRow_->begin();
180  // }
181 
182  // void setCurrentBlockRows()
183  // {
184  // currentBlockRows_ = (*blockMatrix_)(block_i_, block_j_).rows();
185  // }
186 
187  public:
188  const value_type& operator*() const
189  {
190  if (isEnd_)
191  throw std::out_of_range("Cannot dereference end iterator");
192 
193  if (impl_)
194  return impl_->value();
195  throw std::logic_error("null iterator impl");
196  }
197 
198  const pointer operator->() const
199  {
200  return &(**this);
201  }
202 
203  my_type& operator++()
204  {
205  if (!isEnd_)
206  {
207  ++(*impl_);
208  if (!*impl_ && )
209  {
210  // move to next row.
211 
212  }
213  }
214 
215  return *this;
216  }
217 
218  my_type operator++(int)
219  {
220  my_type orig(*this);
221  ++(*this);
222  return orig;
223  }
224 
225  bool operator==(const my_type& rhs)
226  {
227  if (isEnd_ && rhs.isEnd_)
228  return true;
229 
230  if (isEnd_ != rhs.isEnd_)
231  return false;
232 
233  return matrix_ == rhs.matrix_
234  && impl_ == rhs.impl_;
235  }
236 
237  bool operator!=(const my_type& rhs)
238  {
239  return !(*this == rhs);
240  }
241 
242  /*SparseMatrix<double> mat(rows,cols);
243  for (int k=0; k<mat.outerSize(); ++k)
244  for (SparseMatrix<double>::InnerIterator it(mat,k); it; ++it)
245  {
246  it.value();
247  }*/
248  };
249 
250  NonZeroIterator nonZerosBegin() { return NonZeroIterator(this); }
251  NonZeroIterator nonZerosEnd() { return NonZeroIterator(); }
252 #endif
253 
254  const MatrixBase<T>& castForPrinting() const { return *this; } /// @todo: lame...figure out a better way
255 
256  /// Persistent representation...
257  virtual std::string dynamic_type_name() const { return type_id.type; }
258  virtual void io(Piostream&);
260 
262 
263  private:
264  virtual void print(std::ostream& o) const
265  {
266  o << static_cast<const EigenBase&>(*this);
267  }
268  };
269 
270  template <typename T>
272  {
273  return new SparseRowMatrixGeneric<T>;
274  }
275 
276 
277  template <typename T>
278  PersistentTypeID SparseRowMatrixGeneric<T>::type_id("SparseRowMatrix", "MatrixBase",
280 
281 }}}
282 
283 template <typename T>
285 {
286  for (int k = 0; k < m.outerSize(); ++k)
287  {
289  {
290  double tmp = it.value();
291  if (!SCIRun::IsFinite(tmp) || SCIRun::IsNan(tmp))
292  return false;
293  }
294  }
295  return true;
296 }
297 
298 template <typename T>
300 {
301  if (m.rows() != m.cols())
302  return false;
303 
304  for (int k = 0; k < m.outerSize(); ++k)
305  {
307  {
308  if (m.coeff(it.col(), it.row()) != it.value())
309  return false;
310  }
311  }
312  return true;
313 }
314 
315 template <typename T>
317 {
318  if (!isSymmetricMatrix(m))
319  return false; //a matrix must be symmetric to be positive definite
320 
321  if ( !ContainsValidValues(m) )
322  return false;
323 
324  for (int k = 0; k < m.outerSize(); ++k) //all diagonal elements are positive?
325  if ( m.coeff(k, k) <= 0 )
326  return false;
327 
328  for (int k = 0; k < m.outerSize(); ++k)
329  {
330  double tmp1 = 0.0, tmp2 = 0.0;
332  {
333  if (it.col() != it.row())
334  {
335  tmp1 += std::fabs(it.value()); //abs. sum over col
336  tmp2 += std::fabs(m.coeff(it.col(),it.row())); //abs. sum over row
337  }
338  }
339 
340  if ( !((tmp1 < m.coeff(k, k)) && (tmp2 < m.coeff(k, k))) )
341  return false;
342  }
343 
344  return true;
345 }
346 
347 #include <Core/Datatypes/MatrixIO.h>
348 
349 #endif
bool isSymmetricMatrix(const SCIRun::Core::Datatypes::SparseRowMatrixGeneric< T > &m)
Definition: SparseRowMatrix.h:299
static PersistentTypeID type_id
Definition: SparseRowMatrix.h:259
bool isPositiveDefiniteMatrix(const SCIRun::Core::Datatypes::SparseRowMatrixGeneric< T > &m)
Definition: SparseRowMatrix.h:316
bool IsNan(double val)
Definition: MiscMath.h:538
Definition: Persistent.h:89
bool ContainsValidValues(const SCIRun::Core::Datatypes::SparseRowMatrixGeneric< T > &m)
Definition: SparseRowMatrix.h:284
Definition: Persistent.h:187
bool operator!=(const DenseMatrixGeneric< T > &lhs, const DenseMatrixGeneric< T > &rhs)
Definition: MatrixComparison.h:64
const index_type * get_cols() const
Definition: SparseRowMatrix.h:106
virtual void accept(MatrixVisitorGeneric< T > &visitor)
Definition: SparseRowMatrix.h:108
virtual size_t ncols() const
Definition: SparseRowMatrix.h:103
static Persistent * SparseRowMatrixGenericMaker()
Definition: SparseRowMatrix.h:271
#define THROW_INVALID_ARGUMENT(message)
Definition: Exception.h:71
std::vector< CellIndex< T > > operator*(const std::vector< CellIndex< T > > &r, double &)
Definition: FieldIndex.h:110
SparseRowMatrixGeneric(int nrows, int ncols)
Definition: SparseRowMatrix.h:56
virtual void put(int i, int j, const T &val) override
Definition: SparseRowMatrix.h:128
SparseRowMatrixGeneric< T > this_type
Definition: SparseRowMatrix.h:48
const index_type * get_rows() const
Definition: SparseRowMatrix.h:105
std::string type
Definition: Persistent.h:72
SparseRowMatrixGeneric(int nrows, int ncols, const index_type *rowCounter, const index_type *columnCounter, size_t nnz)
Legacy construction compatibility. Useful for converting old code, but should be avoided in new code...
Definition: SparseRowMatrix.h:59
virtual void io(Piostream &)
Definition: MatrixIO.h:214
virtual std::string dynamic_type_name() const
Persistent representation...
Definition: SparseRowMatrix.h:257
Eigen::SparseMatrix< T, Eigen::RowMajor, index_type > EigenBase
Definition: SparseRowMatrix.h:49
SparseRowMatrixGeneric(const Eigen::SparseMatrixBase< OtherDerived > &other)
This constructor allows you to construct SparseRowMatrixGeneric from Eigen expressions.
Definition: SparseRowMatrix.h:85
virtual SparseRowMatrixGeneric * clone() const
Definition: SparseRowMatrix.h:97
virtual size_t nrows() const
Definition: SparseRowMatrix.h:102
const MatrixBase< T > & castForPrinting() const
Definition: SparseRowMatrix.h:254
bool isSymmetric() const
Definition: SparseRowMatrix.h:113
long long index_type
Definition: Types.h:39
bool IsFinite(double val)
Definition: MiscMath.h:543
virtual void visit(DenseMatrixGeneric< T > &)=0
SparseRowMatrixGeneric & operator=(const Eigen::SparseMatrixBase< OtherDerived > &other)
This method allows you to assign Eigen expressions to SparseRowMatrixGeneric.
Definition: SparseRowMatrix.h:91
Definition: Persistent.h:64
bool operator==(const DenseMatrixGeneric< T > &lhs, const DenseMatrixGeneric< T > &rhs)
Definition: MatrixComparison.h:44
Eigen::Triplet< T > Triplet
Definition: SparseRowMatrix.h:50
T value_type
Definition: SparseRowMatrix.h:47
SparseRowMatrixGeneric()
Definition: SparseRowMatrix.h:55