OOCholmod
 All Classes Functions
sparse_matrix.h
1 //
2 // sparse_matrix.h
3 // OOCholmod
4 //
5 // Created by Morten Nobel-Jørgensen / Asger Nyman Christiansen
6 // Copyright (c) 2013 DTU Compute. All rights reserved.
7 // License: LGPL 3.0
8 
9 #pragma once
10 
11 #include <map>
12 #include <string>
13 #include <cholmod.h>
14 
15 #include "config_singleton.h"
16 
17 namespace oocholmod {
18 
19  // forward declaration
20  class DenseMatrix;
21  class Factor;
22 
23  enum Symmetry {
24  SYMMETRIC_LOWER = -1, // Lower triangular part stored
25  ASYMMETRIC = 0,
26  SYMMETRIC_UPPER = 1, // Upper triangular part stored
27  };
28 
29  enum MatrixState {
30  UNINITIALIZED,
31  INIT,
32  BUILT,
33  DESTROYED
34  };
35 
36  class SparseMatrix;
37 
39  public:
40  SparseMatrixIter(const SparseMatrix* sparseMatrix, int pos);
41 
42  bool operator!= (const SparseMatrixIter& other) const{
43  return pos != other.pos;
44  }
45 
46  inline double &operator* () const;
47 
48  const SparseMatrixIter& operator++() {
49  ++pos;
50  return *this;
51  }
52  private:
53  const SparseMatrix* sparseMatrix;
54  int pos;
55  };
56 
62  class SparseMatrix {
63  friend class Factor;
64  public:
68  SparseMatrix(unsigned int nrow = 0, unsigned int ncol = 1, bool symmetric = false, int initialNumberOfElements = 200);
69  SparseMatrix(cholmod_sparse *sparse);
70  SparseMatrix(SparseMatrix&& move);
71  SparseMatrix& operator=(SparseMatrix&& other);
72 
73  ~SparseMatrix();
74 
75  SparseMatrixIter begin();
76  SparseMatrixIter end();
77 
78  void symmetrize();
79 
80  DenseMatrix toDense() const;
81 
82  MatrixState getMatrixState() const;
83 
84  // Addition
85  friend SparseMatrix operator+(const SparseMatrix& LHS, const SparseMatrix& RHS);
86  friend SparseMatrix&& operator+(SparseMatrix&& LHS, const SparseMatrix& RHS);
87  friend SparseMatrix&& operator+(const SparseMatrix& LHS, SparseMatrix&& RHS);
88  friend SparseMatrix&& operator+(SparseMatrix&& LHS, SparseMatrix&& RHS);
89 
90  // Subtraction
91  friend SparseMatrix operator-(const SparseMatrix& M);
92  friend SparseMatrix&& operator-(SparseMatrix&& M);
93 
94  friend SparseMatrix operator-(const SparseMatrix& LHS, const SparseMatrix& RHS);
95  friend SparseMatrix&& operator-(SparseMatrix&& LHS, const SparseMatrix& RHS);
96  friend SparseMatrix&& operator-(const SparseMatrix& LHS, SparseMatrix&& RHS);
97  friend SparseMatrix&& operator-(SparseMatrix&& LHS, SparseMatrix&& RHS);
98 
99  // Multiplication
100  friend SparseMatrix operator*(const SparseMatrix& LHS, double RHS);
101  friend SparseMatrix&& operator*(SparseMatrix&& LHS, double RHS);
102  friend SparseMatrix operator*(double LHS, const SparseMatrix& RHS);
103  friend SparseMatrix&& operator*(double LHS, SparseMatrix&& RHS);
104 
105  friend SparseMatrix operator*(const SparseMatrix& LHS, const SparseMatrix& RHS);
106 
107  friend DenseMatrix operator*(const DenseMatrix& LHS, const SparseMatrix& RHS);
108  friend DenseMatrix operator*(const SparseMatrix& LHS, const DenseMatrix& RHS);
109 
110  // Print
111  friend std::ostream& operator<<(std::ostream& os, const SparseMatrix& A);
112 
113  // hasElement only valid on built matrix
114  bool hasElement(unsigned int row, unsigned int column) const;
115 
118  void append(const SparseMatrix& m);
119 
122  double norm(int norm) const;
123 
127  void dropSmallEntries(double tol = 1e-7f);
128 
129  // in init state return the number of triplets
130  // in built state returns the number of elements
131  size_t getNumberOfElements();
132 
133  // Computes Y = alpha*(A*X) + beta*Y (where this == A) or Y = alpha*(transposed(A)*X) + beta*Y when transpose is true
134  // transpose is ignores if matrix is symmetric of Hermitian
135  void multiply(bool transpose, double alpha, double beta, const DenseMatrix& X, DenseMatrix& Y);
136  // Computes result = alpha*(A*X) (where this == A) or Y = alpha*(transposed(A)*X) when transpose is true
137  // transpose is ignores if matrix is symmetric of Hermitian
138  DenseMatrix multiply(bool transpose, double alpha, const DenseMatrix& X);
139 
140  // Transpose
141  void transpose();
142  friend SparseMatrix transposed(const SparseMatrix& M);
143  friend SparseMatrix&& transposed(SparseMatrix&& M);
144 
145  // Solve
146  friend DenseMatrix solve(const SparseMatrix& A, const DenseMatrix& b);
147  friend SparseMatrix solve(const SparseMatrix& A, const SparseMatrix& b);
148  friend SparseMatrix solve(const Factor& F, const SparseMatrix& b);
149 
150  // Sum the rows and return a vector
151  void sumRows(DenseMatrix& outVector);
152 
153  // Hard coded method to perform: sparse = spdiags(N)^T * sparse * spdiags(N) - (spdiags(N) - speye())
154  void setNullSpace( DenseMatrix& N);
155 
156  void build();
157 
158  SparseMatrix copy() const;
159 
160  Factor analyze() const;
161 
162  void zero();
163 
164  void setSymmetry(Symmetry symmetry);
165  Symmetry getSymmetry() const { return symmetry; }
166 
167  unsigned int getRows() const { return nrow; }
168 
169  unsigned int getColumns() const { return ncol; }
170 
171  void swap(SparseMatrix& other);
172 
173  double operator()(unsigned int row, unsigned int column = 0) const;
174 
175  double& operator()(unsigned int row, unsigned int column = 0);
176 
177  bool operator==(const SparseMatrix& RHS) const;
178  bool operator!=(const SparseMatrix& RHS) const;
179 
180  friend class SparseMatrixIter;
181  private:
182  SparseMatrix(const SparseMatrix& that); // prevent copy constructor (no implementation)
183  SparseMatrix operator=(const SparseMatrix& other); // prevent copy assignment operator (no implementation)
184  long key(unsigned int row, unsigned int column) const;
185  void assertValidIndex(unsigned int row, unsigned int column) const;
186  void assertHasSparse() const;
187  void increaseTripletCapacity();
188  void assertValidInitAddValue(unsigned int row, unsigned int column) const;
189 
190  int binarySearch(int *array, int low, int high, unsigned int value) const;
191 
192  int getIndex(unsigned int row, unsigned int column) const;
193 
194  void createTriplet();
195 
196  double& initAddValue(unsigned int row, unsigned int column);
197 
198  double& getValue(unsigned int row, unsigned int column);
199 
200  double getValue(unsigned int row, unsigned int column) const;
201 
202  cholmod_sparse *sparse;
203  cholmod_triplet *triplet;
204  unsigned int nrow;
205  unsigned int ncol;
206  double *values;
207  int *iRow;
208  int *jColumn;
209  Symmetry symmetry;
210  int maxTripletElements;
211  };
212 
213  // ----------- inline functions ------------
214 
215  double& SparseMatrixIter::operator* () const{
216  if (sparseMatrix->getMatrixState() == INIT){
217  double * ptr = static_cast<double*>(sparseMatrix->triplet->x);
218  return *(ptr + pos);
219  } else if (sparseMatrix->getMatrixState() == BUILT){
220  double * ptr = static_cast<double*>(sparseMatrix->sparse->x);
221  return *(ptr + pos);
222  } else {
223  throw std::runtime_error("Invalid matrix state");
224  }
225  }
226 
227 
228 
229  inline double SparseMatrix::operator()(unsigned int row, unsigned int column) const
230  {
231  return getValue(row, column);
232  }
233 
234  inline double& SparseMatrix::operator()(unsigned int row, unsigned int column)
235  {
236  if (sparse != nullptr){
237  return getValue(row, column);
238  } else {
239  return initAddValue(row, column);
240  }
241  }
242 
243  inline int SparseMatrix::binarySearch(int *array, int low, int high, unsigned int value) const {
244  while (low <= high)
245  {
246  // http://googleresearch.blogspot.dk/2006/06/extra-extra-read-all-about-it-nearly.html
247  int midpoint = (((unsigned int)high + (unsigned int)low) >> 1);
248  int midpointValue = array[midpoint];
249  if (value == midpointValue) {
250  return midpoint;
251  } else if (value < midpointValue) {
252  high = midpoint - 1;
253  } else {
254  low = midpoint + 1;
255  }
256  }
257  return -1;
258  }
259 
260  inline int SparseMatrix::getIndex(unsigned int row, unsigned int column) const
261  {
262 #if DEBUG
263  assertValidIndex(row, column);
264 #endif
265  if ((symmetry == SYMMETRIC_UPPER && row > column) || (symmetry == SYMMETRIC_LOWER && row < column)) {
266  std::swap(row, column);
267  }
268 
269  int iFrom = jColumn[column];
270  int iTo = jColumn[column+1]-1;
271 
272  return binarySearch(iRow, iFrom, iTo, row);
273  }
274 
275  inline long SparseMatrix::key(unsigned int row, unsigned int column) const {
276  int shiftBits = sizeof(long)*8/2; // shift half of the bits of a long
277  return (((long)row)<<shiftBits)+column;
278  }
279 
280  inline void SparseMatrix::createTriplet(){
281  triplet = cholmod_allocate_triplet(nrow, ncol, maxTripletElements, symmetry, CHOLMOD_REAL, ConfigSingleton::getCommonPtr());
282  values = (double *)triplet->x;
283  iRow = (int *)triplet->i;
284  jColumn = (int *)triplet->j;
285  }
286 
287  inline double& SparseMatrix::initAddValue(unsigned int row, unsigned int column)
288  {
289  if (!triplet){
290  createTriplet();
291  } else if (triplet->nnz == maxTripletElements ){
292  increaseTripletCapacity();
293  }
294  assertValidInitAddValue(row, column);
295  iRow[triplet->nnz] = row;
296  jColumn[triplet->nnz] = column;
297  values[triplet->nnz] = 0;
298 
299  triplet->nnz++;
300  return values[triplet->nnz - 1];
301  }
302 
303  inline double& SparseMatrix::getValue(unsigned int row, unsigned int column)
304  {
305 #ifdef DEBUG
306  assertHasSparse();
307 #endif
308  int index = getIndex(row, column);
309  if (index == -1){
310  static double zero = 0;
311  zero = 0;
312  return zero;
313  }
314  return values[index];
315  }
316 
317  inline double SparseMatrix::getValue(unsigned int row, unsigned int column) const
318  {
319 #ifdef DEBUG
320  assertHasSparse();
321 #endif
322  int index = getIndex(row, column);
323  if (index == -1){
324  return 0;
325  }
326  return values[index];
327  }
328 }
329 
Definition: dense_matrix.h:31
void dropSmallEntries(double tol=1e-7f)
Definition: sparse_matrix.cpp:163
SparseMatrix(unsigned int nrow=0, unsigned int ncol=1, bool symmetric=false, int initialNumberOfElements=200)
Definition: sparse_matrix.cpp:23
void append(const SparseMatrix &m)
Definition: sparse_matrix.cpp:138
Definition: factor.h:22
Definition: sparse_matrix.h:62
double norm(int norm) const
Definition: sparse_matrix.cpp:363
Definition: sparse_matrix.h:38