PersistentLaplacians
Filtered_Boundary_Matrix.hpp
Go to the documentation of this file.
1 #ifndef FBM_H
2 #define FBM_H
3 
4 #include "../typedefs.hpp"
5 // #include "../PersistentLaplacians.hpp"
6 
7 #include <vector>
8 #include <cassert>
9 #include <iostream>
10 
11 namespace PersistentLaplacians{
15 template<typename FBMcoeff = int>
17  /*********************************************************/
18  /* Template: FBMcoeff: the type of entries in the matrix */
19  /*********************************************************/
20  private:
21  /********************/
22  /* Member variables */
23  /********************/
24  std::vector<filtration_type> domain_filtrations;
25  std::vector<filtration_type> range_filtrations;
26  Eigen::SparseMatrix<FBMcoeff, Eigen::ColMajor> matrix;
27  int num_rows;
28  int num_cols;
29 
30  public:
37  Filtered_Boundary_Matrix(Eigen::SparseMatrix<FBMcoeff, Eigen::ColMajor> _matrix,
38  std::vector<filtration_type> _domain_filtrations,
39  std::vector<filtration_type> _range_filtrations){
40  matrix = _matrix;
41  domain_filtrations = _domain_filtrations;
42  range_filtrations = _range_filtrations;
43  num_rows = _range_filtrations.size();
44  num_cols = _domain_filtrations.size();
45  }
46 
47  /***********************/
48  /* Getters and setters */
49  /***********************/
50 
54  std::vector<filtration_type> get_domain_filtrations(){return domain_filtrations;}
55 
59  std::vector<filtration_type> get_range_filtrations(){return range_filtrations;}
60 
61  /*********************/
62  /* useful operations */
63  /*********************/
64 
69  return Filtered_Boundary_Matrix(matrix.transpose(),range_filtrations,domain_filtrations);
70  }
71 
79  int index_of_filtration(bool use_domain_filtrations, filtration_type a){
80  int index = 0;
81  int filtration_size;
82  if (use_domain_filtrations){
83  filtration_size = domain_filtrations.size();
84  while (index < filtration_size && domain_filtrations[index] <= a){
85  index++;
86  }
87  } else{ //range_filtrations
88  filtration_size = range_filtrations.size();
89  while (index < filtration_size && range_filtrations[index] <= a){
90  index++;
91  }
92  }
93  return index-1;
94  }
95 
96  // TODO: deprecated
97  int get_low(SparseMatrix_PL &matrix, int col_index){
98  //TODO: can probably get the low in constant time via https://eigen.tuxfamily.org/dox/classEigen_1_1DenseBase.html#ae71d079e16d91360d10066b316b48485
99  int low_index = -1;
100  matrix.makeCompressed();
101  for(SparseMatrix_PL::InnerIterator it(matrix,col_index); it; ++it){
102  assert(it.value() != 0);
103  low_index = it.index();
104  }
105  return low_index;
106  }
107 
113  void submatrix_at_filtration(filtration_type a, Eigen::SparseMatrix<FBMcoeff,Eigen::ColMajor> &M){
114  int col_index = index_of_filtration(true,a);
115  int row_index = index_of_filtration(false,a);
116  M = matrix.block(0,0,row_index+1,col_index+1);
117  }
118 
119  // TODO: deprecated
120  std::tuple<SparseMatrix_PL,SparseMatrix_PL,std::vector<int>, int> reduce(int a_row_index,int b_row_index, int b_col_index){
121  int lower_num_rows = b_row_index - a_row_index;
122  // For explaining usage of .template see https://eigen.tuxfamily.org/dox-devel/TopicTemplateKeyword.html
123  SparseMatrix_PL working_boundary = matrix.block(0,0,b_row_index+1,b_col_index+1).template cast<coefficient_type>();
124 
125 
126  SparseMatrix_PL lower_working_boundary = working_boundary.block(a_row_index+1,0,lower_num_rows,b_col_index+1);
127 
128 
129  SparseMatrix_PL augmented(b_col_index+1, b_col_index+1);
130  augmented.setIdentity();
131 
132  //this is the big reduce loop
133  //A column is reduced if it's low is unique among lows
134  std::vector<int> lows(b_col_index+1);
135  std::vector<int> zero_cols;
136  if (lower_num_rows == 0){
137  return std::make_tuple(working_boundary, augmented,zero_cols,a_row_index);
138  } else {
139  assert(lower_num_rows > 0);
140  }
141 
142  lows[0] = 0;
143  for (unsigned long int col_index = 0; col_index <= (unsigned long int) b_col_index; col_index++){
144 
145  bool unique_pivot = false;
146  int current_low;
147  while (!unique_pivot){
148  current_low = get_low(lower_working_boundary,col_index);
149  if (current_low == -1){//column is a zero-column
150  lows[col_index] = current_low;
151  zero_cols.push_back(col_index);
152  break;//while !unique_pivot
153  }
154 
155  unique_pivot = true;
156  coefficient_type pivot_val = lower_working_boundary.coeffRef(current_low,col_index);
157 
158  for(unsigned long int left_col_index = 0; left_col_index < col_index; left_col_index++){
159  if (lows[left_col_index] == current_low){
160  coefficient_type conflicting_pivot = lower_working_boundary.coeffRef(lows[left_col_index],left_col_index);
161  coefficient_type scale_factor = pivot_val/conflicting_pivot;
162  // TODO: speed and single precision tradeoff?
163 
164  // ************ TODO: DETERMINE PRUNE CUTOFF VALUE *************
165  augmented.col(col_index) = (augmented.col(col_index) - scale_factor * augmented.col(left_col_index)).pruned(PRUNE_CONSTANT);
166 
167  lower_working_boundary.col(col_index) = (lower_working_boundary.col(col_index) - scale_factor * lower_working_boundary.col(left_col_index)).pruned(PRUNE_CONSTANT);
168  unique_pivot = false;
169  break;
170  } //end if lows[left_col_index] == current_low
171 
172  }//end for left_col_index
173  }// end while !unique_pivot
174  lows[col_index] = current_low;
175  }//end for col_index
176  return std::make_tuple(working_boundary, augmented,zero_cols,a_row_index); //TODO: replace 2nd with Y
177 
178  }
179 
180 
181  /**********************************/
182  /* Helpful input/output functions */
183  /**********************************/
184 
189  std::cout << "\n[";
190  for (unsigned long int i = 0; i < range_filtrations.size(); i++){
191  std::cout << range_filtrations[i] << ",";
192  }
193  std::cout << "]\n";
194  }
195 
200  std::cout << "\n[";
201  for (unsigned long int i = 0; i < domain_filtrations.size(); i++){
202  std::cout << domain_filtrations[i] << ",";
203  }
204  std::cout << "]\n";
205  }
209  void print(){
210  Eigen::IOFormat HeavyFmt(Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
211  std::cout << Eigen::Matrix<FBMcoeff,Eigen::Dynamic, Eigen::Dynamic>(matrix).format(HeavyFmt) <<std::endl;
212  }
213 };
214 }
215 #endif
Definition: Filtered_Boundary_Matrix.hpp:16
Filtered_Boundary_Matrix transpose()
Definition: Filtered_Boundary_Matrix.hpp:68
Filtered_Boundary_Matrix(Eigen::SparseMatrix< FBMcoeff, Eigen::ColMajor > _matrix, std::vector< filtration_type > _domain_filtrations, std::vector< filtration_type > _range_filtrations)
Definition: Filtered_Boundary_Matrix.hpp:37
void print_domain_filtration()
Definition: Filtered_Boundary_Matrix.hpp:199
void print()
Definition: Filtered_Boundary_Matrix.hpp:209
int index_of_filtration(bool use_domain_filtrations, filtration_type a)
Definition: Filtered_Boundary_Matrix.hpp:79
void print_range_filtration()
Definition: Filtered_Boundary_Matrix.hpp:188
void submatrix_at_filtration(filtration_type a, Eigen::SparseMatrix< FBMcoeff, Eigen::ColMajor > &M)
Definition: Filtered_Boundary_Matrix.hpp:113
std::tuple< SparseMatrix_PL, SparseMatrix_PL, std::vector< int >, int > reduce(int a_row_index, int b_row_index, int b_col_index)
Definition: Filtered_Boundary_Matrix.hpp:120
std::vector< filtration_type > get_domain_filtrations()
Definition: Filtered_Boundary_Matrix.hpp:54
std::vector< filtration_type > get_range_filtrations()
Definition: Filtered_Boundary_Matrix.hpp:59
int get_low(SparseMatrix_PL &matrix, int col_index)
Definition: Filtered_Boundary_Matrix.hpp:97
Definition: PersistentLaplacians.cpp:7
float coefficient_type
Definition: typedefs.hpp:13
#define PRUNE_CONSTANT
Definition: typedefs.hpp:40
Eigen::SparseMatrix< coefficient_type, Eigen::ColMajor > SparseMatrix_PL
Definition: typedefs.hpp:23
double filtration_type
Definition: typedefs.hpp:34