Bitmap_cubical_complex_base.h
1 /* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2  * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3  * Author(s): Pawel Dlotko
4  *
5  * Copyright (C) 2015 Inria
6  *
7  * Modification(s):
8  * - YYYY/MM Author: Description of the modification
9  */
10 
11 #ifndef BITMAP_CUBICAL_COMPLEX_BASE_H_
12 #define BITMAP_CUBICAL_COMPLEX_BASE_H_
13 
14 #include <gudhi/Debug_utils.h>
15 
16 #include <boost/config.hpp>
17 #include <boost/iterator/counting_iterator.hpp>
18 #include <boost/range/iterator_range.hpp>
19 
20 #include <iostream>
21 #include <vector>
22 #include <string>
23 #include <fstream>
24 #include <algorithm>
25 #include <iterator>
26 #include <limits>
27 #include <utility>
28 #include <stdexcept>
29 #include <cstddef>
30 #include <numeric>
31 #include <functional>
32 
33 namespace Gudhi {
34 
35 namespace cubical_complex {
36 
56 template <typename T>
58  public:
59  typedef T filtration_type;
60 
71  explicit Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes);
78  explicit Bitmap_cubical_complex_base(const char* perseus_style_file);
83  Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions, const std::vector<T>& cells, bool input_top_cells = true);
84 
89 
101  virtual inline std::vector<std::size_t> get_boundary_of_a_cell(std::size_t cell) const;
116  virtual inline std::vector<std::size_t> get_coboundary_of_a_cell(std::size_t cell) const;
117 
126  inline size_t get_top_dimensional_coface_of_a_cell(size_t splx);
127 
136  inline size_t get_vertex_of_a_cell(size_t splx);
137 
157  virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) const {
158  // first get the counters for coface and face:
159  std::vector<unsigned> coface_counter = this->compute_counter_for_given_cell(coface);
160  std::vector<unsigned> face_counter = this->compute_counter_for_given_cell(face);
161 
162  // coface_counter and face_counter should agree at all positions except from one:
163  int number_of_position_in_which_counters_do_not_agree = -1;
164  std::size_t number_of_full_faces_that_comes_before = 0;
165  for (std::size_t i = 0; i != coface_counter.size(); ++i) {
166  if ((coface_counter[i] % 2 == 1) && (number_of_position_in_which_counters_do_not_agree == -1)) {
167  ++number_of_full_faces_that_comes_before;
168  }
169  if (coface_counter[i] != face_counter[i]) {
170  if (number_of_position_in_which_counters_do_not_agree != -1) {
171  std::cerr << "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.\n";
172  throw std::logic_error(
173  "Cells given to compute_incidence_between_cells procedure do not form a pair of coface-face.");
174  }
175  number_of_position_in_which_counters_do_not_agree = i;
176  }
177  }
178 
179  int incidence = 1;
180  if (number_of_full_faces_that_comes_before % 2) incidence = -1;
181  // if the face cell is on the right from coface cell:
182  if (coface_counter[number_of_position_in_which_counters_do_not_agree] + 1 ==
183  face_counter[number_of_position_in_which_counters_do_not_agree]) {
184  incidence *= -1;
185  }
186 
187  return incidence;
188  }
189 
198  inline unsigned get_dimension_of_a_cell(std::size_t cell) const;
199 
206  inline T& get_cell_data(std::size_t cell);
207 
216  void impose_lower_star_filtration(); // assume that top dimensional cells are already set.
217 
222  void impose_lower_star_filtration_from_vertices(); // assume that vertices are already set.
223 
227  inline unsigned dimension() const { return sizes.size(); }
228 
232  inline std::size_t size() const { return this->data.size(); }
233 
242  void put_data_to_bins(std::size_t number_of_bins);
243 
254  void put_data_to_bins(T diameter_of_bin);
255 
259  std::pair<T, T> min_max_filtration();
260 
261  // ITERATORS
262 
267  typedef boost::counting_iterator<std::size_t> All_cells_iterator;
268 
273 
278 
282  typedef boost::iterator_range<All_cells_iterator> All_cells_range;
283 
286 
290  typedef typename std::vector<std::size_t>::const_iterator Boundary_iterator;
291  typedef typename std::vector<std::size_t> Boundary_range;
292 
297  Boundary_range boundary_range(std::size_t sh) { return this->get_boundary_of_a_cell(sh); }
298 
302  typedef typename std::vector<std::size_t>::const_iterator Coboundary_iterator;
303  typedef typename std::vector<std::size_t> Coboundary_range;
304 
309  Coboundary_range coboundary_range(std::size_t sh) { return this->get_coboundary_of_a_cell(sh); }
310 
316  public:
317  typedef std::input_iterator_tag iterator_category;
318  typedef std::size_t value_type;
319  typedef std::ptrdiff_t difference_type;
320  typedef value_type* pointer;
321  typedef value_type reference;
322 
324 
325  Top_dimensional_cells_iterator operator++() {
326  // first find first element of the counter that can be increased:
327  std::size_t dim = 0;
328  while ((dim != this->b->dimension()) && (this->counter[dim] == this->b->sizes[dim] - 1)) ++dim;
329 
330  if (dim != this->b->dimension()) {
331  ++this->counter[dim];
332  for (std::size_t i = 0; i != dim; ++i) {
333  this->counter[i] = 0;
334  }
335  } else {
336  ++this->counter[0];
337  }
338  return *this;
339  }
340 
341  Top_dimensional_cells_iterator operator++(int) {
342  Top_dimensional_cells_iterator result = *this;
343  ++(*this);
344  return result;
345  }
346 
347  bool operator==(const Top_dimensional_cells_iterator& rhs) const {
348  if (this->b != rhs.b) return false;
349  if (this->counter.size() != rhs.counter.size()) return false;
350  for (std::size_t i = 0; i != this->counter.size(); ++i) {
351  if (this->counter[i] != rhs.counter[i]) return false;
352  }
353  return true;
354  }
355 
356  bool operator!=(const Top_dimensional_cells_iterator& rhs) const { return !(*this == rhs); }
357 
358  /*
359  * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
360  * an argument of the following functions:
361  * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
362  * boundary and coboundary and dimension
363  * and in function get_cell_data to get a filtration of a cell.
364  */
365  std::size_t operator*() { return this->compute_index_in_bitmap(); }
366 
367  std::size_t compute_index_in_bitmap() const {
368  std::size_t index = 0;
369  for (std::size_t i = 0; i != this->counter.size(); ++i) {
370  index += (2 * this->counter[i] + 1) * this->b->multipliers[i];
371  }
372  return index;
373  }
374 
375  void print_counter() const {
376  for (std::size_t i = 0; i != this->counter.size(); ++i) {
377  std::clog << this->counter[i] << " ";
378  }
379  }
380  friend class Bitmap_cubical_complex_base;
381 
382  protected:
383  std::vector<std::size_t> counter;
385  };
386 
392  return a;
393  }
394 
400  for (std::size_t i = 0; i != this->dimension(); ++i) {
401  a.counter[i] = this->sizes[i] - 1;
402  }
403  a.counter[0]++;
404  return a;
405  }
406 
411  public:
413 
415 
417 
418  private:
420  };
421 
424 
425  //****************************************************************************************************************//
426  //****************************************************************************************************************//
427  //****************************************************************************************************************//
428  //****************************************************************************************************************//
429  class Vertices_iterator {
430  public:
431  typedef std::input_iterator_tag iterator_category;
432  typedef std::size_t value_type;
433  typedef std::ptrdiff_t difference_type;
434  typedef value_type* pointer;
435  typedef value_type reference;
436 
437  Vertices_iterator(Bitmap_cubical_complex_base* b) : counter(b->dimension()), b(b) {}
438 
439  Vertices_iterator operator++() {
440  // first find first element of the counter that can be increased:
441  std::size_t dim = 0;
442  while ((dim != this->b->dimension()) && (this->counter[dim] == this->b->sizes[dim])) ++dim;
443 
444  if (dim != this->b->dimension()) {
445  ++this->counter[dim];
446  for (std::size_t i = 0; i != dim; ++i) {
447  this->counter[i] = 0;
448  }
449  } else {
450  ++this->counter[0];
451  }
452  return *this;
453  }
454 
455  Vertices_iterator operator++(int) {
456  Vertices_iterator result = *this;
457  ++(*this);
458  return result;
459  }
460 
461  bool operator==(const Vertices_iterator& rhs) const {
462  if (this->b != rhs.b) return false;
463  GUDHI_CHECK(this->counter.size() == rhs.counter.size(), "impossible");
464  for (std::size_t i = 0; i != this->counter.size(); ++i) {
465  if (this->counter[i] != rhs.counter[i]) return false;
466  }
467  return true;
468  }
469 
470  bool operator!=(const Vertices_iterator& rhs) const { return !(*this == rhs); }
471 
472  /*
473  * The operator * returns position of a cube in the structure of cubical complex. This position can be then used as
474  * an argument of the following functions:
475  * get_boundary_of_a_cell, get_coboundary_of_a_cell, get_dimension_of_a_cell to get information about the cell
476  * boundary and coboundary and dimension
477  * and in function get_cell_data to get a filtration of a cell.
478  */
479  std::size_t operator*() const { return this->compute_index_in_bitmap(); }
480 
481  std::size_t compute_index_in_bitmap() const {
482  std::size_t index = 0;
483  for (std::size_t i = 0; i != this->counter.size(); ++i) {
484  index += 2 * this->counter[i] * this->b->multipliers[i];
485  }
486  return index;
487  }
488 
489  void print_counter() const {
490  for (std::size_t i = 0; i != this->counter.size(); ++i) {
491  std::clog << this->counter[i] << " ";
492  }
493  }
494  friend class Bitmap_cubical_complex_base;
495 
496  protected:
497  std::vector<std::size_t> counter;
499  };
500 
501  /*
502  * Function returning a Vertices_iterator to the first vertex of the bitmap.
503  */
504  Vertices_iterator vertices_iterator_begin() {
505  Vertices_iterator a(this);
506  return a;
507  }
508 
509  /*
510  * Function returning a Vertices_iterator to the last vertex of the bitmap.
511  */
512  Vertices_iterator vertices_iterator_end() {
513  Vertices_iterator a(this);
514  for (std::size_t i = 0; i != this->dimension(); ++i) {
515  a.counter[i] = this->sizes[i];
516  }
517  a.counter[0]++;
518  return a;
519  }
520 
521  /*
522  * @brief Vertices_iterator_range class provides ranges for Vertices_iterator_range
523  */
524  class Vertices_range {
525  public:
526  Vertices_range(Bitmap_cubical_complex_base* b) : b(b) {}
527 
528  Vertices_iterator begin() { return b->vertices_iterator_begin(); }
529 
530  Vertices_iterator end() { return b->vertices_iterator_end(); }
531 
532  private:
534  };
535 
536  /* Returns a range over all vertices. */
537  Vertices_range vertices_range() { return Vertices_range(this); }
538 
539  //****************************************************************************************************************//
540  //****************************************************************************************************************//
541  //****************************************************************************************************************//
542  //****************************************************************************************************************//
543 
544  inline std::size_t number_cells() const { return this->data.size(); }
545 
546  //****************************************************************************************************************//
547  //****************************************************************************************************************//
548  //****************************************************************************************************************//
549  //****************************************************************************************************************//
550 
552  template <class F> void for_each_vertex(F&&f) {
553  for_each_vertex_rec(f, 0, multipliers.size()-1);
554  }
555 
556  protected:
557  std::vector<unsigned> sizes;
558  std::vector<unsigned> multipliers;
559  std::vector<T> data;
560 
561  template <class F> void for_each_vertex_rec(F&&f, std::size_t base, int dim);
562  void propagate_from_vertices_rec(int special_dim, int current_dim, std::size_t base);
563 
564  void set_up_containers(const std::vector<unsigned>& sizes, bool is_pos_inf) {
565  // The fact that multipliers[0]=1 is relied on by optimizations in other functions
566  unsigned multiplier = 1;
567  for (std::size_t i = 0; i != sizes.size(); ++i) {
568  this->sizes.push_back(sizes[i]);
569  this->multipliers.push_back(multiplier);
570  multiplier *= 2 * sizes[i] + 1;
571  }
572  if(is_pos_inf)
573  this->data = std::vector<T>(multiplier, std::numeric_limits<T>::infinity());
574  else
575  this->data = std::vector<T>(multiplier, -std::numeric_limits<T>::infinity());
576  }
577 
578  std::size_t compute_position_in_bitmap(const std::vector<unsigned>& counter) {
579  std::size_t position = 0;
580  for (std::size_t i = 0; i != this->multipliers.size(); ++i) {
581  position += this->multipliers[i] * counter[i];
582  }
583  return position;
584  }
585 
586  std::vector<unsigned> compute_counter_for_given_cell(std::size_t cell) const {
587  std::vector<unsigned> counter;
588  counter.reserve(this->sizes.size());
589  for (std::size_t dim = this->sizes.size(); dim > 1; --dim) {
590  std::size_t quot = cell / this->multipliers[dim - 1];
591  cell = cell % this->multipliers[dim - 1];
592  counter.push_back(quot);
593  }
594  // Split out the last iteration to save a costly division by multipliers[0]=1
595  counter.push_back(cell);
596  std::reverse(counter.begin(), counter.end());
597  return counter;
598  }
599  void read_perseus_style_file(const char* perseus_style_file);
600  void setup_bitmap_based_on_top_dimensional_cells_list(const std::vector<unsigned>& sizes_in_following_directions,
601  const std::vector<T>& top_dimensional_cells);
602  void setup_bitmap_based_on_vertices(const std::vector<unsigned>& sizes_in_following_directions,
603  const std::vector<T>& vertices);
604  Bitmap_cubical_complex_base(const char* perseus_style_file, const std::vector<bool>& directions);
605  Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes, const std::vector<bool>& directions);
606  Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions, const std::vector<T>& cells,
607  const std::vector<bool>& directions, bool input_top_cells);
608 };
609 
610 template <typename T>
611 void Bitmap_cubical_complex_base<T>::put_data_to_bins(std::size_t number_of_bins) {
612 
613  std::pair<T, T> min_max = this->min_max_filtration();
614  T dx = (min_max.second - min_max.first) / (T)number_of_bins;
615 
616  // now put the data into the appropriate bins:
617  for (std::size_t i = 0; i != this->data.size(); ++i) {
618 #ifdef DEBUG_TRACES
619  std::clog << "Before binning : " << this->data[i] << std::endl;
620 #endif
621  this->data[i] = min_max.first + dx * (this->data[i] - min_max.first) / number_of_bins;
622 #ifdef DEBUG_TRACES
623  std::clog << "After binning : " << this->data[i] << std::endl;
624 #endif
625  }
626 }
627 
628 template <typename T>
630  std::pair<T, T> min_max = this->min_max_filtration();
631 
632  std::size_t number_of_bins = (min_max.second - min_max.first) / diameter_of_bin;
633  // now put the data into the appropriate bins:
634  for (std::size_t i = 0; i != this->data.size(); ++i) {
635 #ifdef DEBUG_TRACES
636  std::clog << "Before binning : " << this->data[i] << std::endl;
637 #endif
638  this->data[i] = min_max.first + diameter_of_bin * (this->data[i] - min_max.first) / number_of_bins;
639 #ifdef DEBUG_TRACES
640  std::clog << "After binning : " << this->data[i] << std::endl;
641 #endif
642  }
643 }
644 
645 template <typename T>
647  std::pair<T, T> min_max(std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity());
648  for (std::size_t i = 0; i != this->data.size(); ++i) {
649  if (this->data[i] < min_max.first) min_max.first = this->data[i];
650  if (this->data[i] > min_max.second) min_max.second = this->data[i];
651  }
652  return min_max;
653 }
654 
655 template <typename T>
657  this->set_up_containers(sizes, true);
658 }
659 
660 template <typename T>
662  const std::vector<unsigned>& sizes_in_following_directions, const std::vector<T>& top_dimensional_cells) {
663  this->set_up_containers(sizes_in_following_directions, true);
664  std::size_t number_of_top_dimensional_elements = std::accumulate(std::begin(sizes_in_following_directions),
665  std::end(sizes_in_following_directions), std::size_t(1),
666  std::multiplies<std::size_t>());
667  if (number_of_top_dimensional_elements != top_dimensional_cells.size()) {
668  std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector<unsigned> "
669  << "sizes_in_following_directions, std::vector<T> top_dimensional_cells ). Number of top dimensional "
670  << "elements that follow from sizes_in_following_directions vector is different from the size of "
671  << "top_dimensional_cells vector."
672  << std::endl;
673  throw std::invalid_argument(
674  "Error in constructor Bitmap_cubical_complex_base( std::vector<unsigned> sizes_in_following_directions,"
675  "std::vector<T> top_dimensional_cells ). Number of top dimensional elements that follow from "
676  "sizes_in_following_directions vector is different from the size of top_dimensional_cells vector.");
677  }
678 
679  std::size_t index = 0;
680  for (auto it = this->top_dimensional_cells_iterator_begin();
681  it != this->top_dimensional_cells_iterator_end(); ++it) {
682  this->get_cell_data(*it) = top_dimensional_cells[index];
683  ++index;
684  }
685  this->impose_lower_star_filtration();
686 }
687 
688 template <typename T>
689 void Bitmap_cubical_complex_base<T>::setup_bitmap_based_on_vertices(const std::vector<unsigned>& sizes_in_following_directions,
690  const std::vector<T>& vertices) {
691  std::vector<unsigned> top_cells_sizes;
692  std::transform (sizes_in_following_directions.begin(), sizes_in_following_directions.end(), std::back_inserter(top_cells_sizes),
693  [](int i){ return i-1;});
694  this->set_up_containers(top_cells_sizes, false);
695  std::size_t number_of_vertices = std::accumulate(std::begin(sizes_in_following_directions),
696  std::end(sizes_in_following_directions), (std::size_t)1,
697  std::multiplies<std::size_t>());
698  if (number_of_vertices != vertices.size()) {
699  std::cerr << "Error in constructor Bitmap_cubical_complex_base ( std::vector<unsigned> "
700  << "sizes_in_following_directions, std::vector<T> vertices ). Number of vertices "
701  << "elements that follow from sizes_in_following_directions vector is different from the size of "
702  << "vertices vector."
703  << std::endl;
704  throw std::invalid_argument(
705  "Error in constructor Bitmap_cubical_complex_base( std::vector<unsigned> sizes_in_following_directions,"
706  "std::vector<T> vertices ). Number of vertices elements that follow from "
707  "sizes_in_following_directions vector is different from the size of vertices vector.");
708  }
709 
710  for_each_vertex([this, &vertices, index=(std::size_t)0] (auto cell) mutable { get_cell_data(cell) = vertices[index++]; });
711  this->impose_lower_star_filtration_from_vertices();
712 }
713 
714 template <typename T>
716  if (this->get_dimension_of_a_cell(splx) == this->dimension()){return splx;}
717  else {
718  for (auto v : this->get_coboundary_of_a_cell(splx)){
719  if(this->get_cell_data(v) == this->get_cell_data(splx)){
720  return this->get_top_dimensional_coface_of_a_cell(v);
721  }
722  }
723  }
724  BOOST_UNREACHABLE_RETURN(-2);
725 }
726 
727 template <typename T>
729  if (this->get_dimension_of_a_cell(splx) == 0){return splx;}
730  else {
731  for (auto v : this->get_boundary_of_a_cell(splx)){
732  if(this->get_cell_data(v) == this->get_cell_data(splx)){
733  return this->get_vertex_of_a_cell(v);
734  }
735  }
736  }
737  BOOST_UNREACHABLE_RETURN(-2);
738 }
739 
740 template <typename T>
741 Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes_in_following_directions,
742  const std::vector<T>& cells, bool input_top_cells) {
743  if (input_top_cells) {
744  this->setup_bitmap_based_on_top_dimensional_cells_list(sizes_in_following_directions, cells);
745  } else {
746  this->setup_bitmap_based_on_vertices(sizes_in_following_directions, cells);
747  }
748 }
749 
750 template <typename T>
751 void Bitmap_cubical_complex_base<T>::read_perseus_style_file(const char* perseus_style_file) {
752  std::ifstream inFiltration(perseus_style_file);
753  if(!inFiltration) throw std::ios_base::failure(std::string("Could not open the file ") + perseus_style_file);
754  unsigned dimensionOfData;
755  inFiltration >> dimensionOfData;
756 
757 #ifdef DEBUG_TRACES
758  std::clog << "dimensionOfData : " << dimensionOfData << std::endl;
759 #endif
760 
761  std::vector<unsigned> sizes;
762  sizes.reserve(dimensionOfData);
763  // all dimensions multiplied
764  std::size_t dimensions = 1;
765  for (std::size_t i = 0; i != dimensionOfData; ++i) {
766  unsigned size_in_this_dimension;
767  inFiltration >> size_in_this_dimension;
768  sizes.push_back(size_in_this_dimension);
769  dimensions *= size_in_this_dimension;
770 #ifdef DEBUG_TRACES
771  std::clog << "size_in_this_dimension : " << size_in_this_dimension << std::endl;
772 #endif
773  }
774  this->set_up_containers(sizes, true);
775 
776  Bitmap_cubical_complex_base<T>::Top_dimensional_cells_iterator it = this->top_dimensional_cells_iterator_begin();
777 
778  T filtrationLevel = 0.;
779  std::size_t filtration_counter = 0;
780  while (!inFiltration.eof()) {
781  std::string line;
782  getline(inFiltration, line);
783  if (line.length() != 0) {
784  int n = sscanf(line.c_str(), "%lf", &filtrationLevel);
785  if (n != 1) {
786  std::string perseus_error("Bad Perseus file format. This line is incorrect : " + line);
787  throw std::ios_base::failure(perseus_error.c_str());
788  }
789 
790 #ifdef DEBUG_TRACES
791  std::clog << "Cell of an index : " << it.compute_index_in_bitmap()
792  << " and dimension: " << this->get_dimension_of_a_cell(it.compute_index_in_bitmap())
793  << " get the value : " << filtrationLevel << std::endl;
794 #endif
795  this->get_cell_data(*it) = filtrationLevel;
796  ++it;
797  ++filtration_counter;
798  }
799  }
800 
801  if (filtration_counter != dimensions) {
802  std::string perseus_error("Bad Perseus file format. Read " + std::to_string(filtration_counter) + " expected " + \
803  std::to_string(dimensions) + " values");
804  throw std::ios_base::failure(perseus_error);
805  }
806 
807  inFiltration.close();
808  this->impose_lower_star_filtration();
809 }
810 
811 template <typename T>
813  const std::vector<bool>& directions) {
814  // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
815  // conditions.
816  // It ignores the last parameter of the function.
817  this->read_perseus_style_file(perseus_style_file);
818 }
819 
820 template <typename T>
821 Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& sizes,
822  const std::vector<bool>& directions) {
823  // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
824  // conditions.
825  // It ignores the last parameter of the function.
826  this->set_up_containers(sizes, true);
827 }
828 
829 template <typename T>
830 Bitmap_cubical_complex_base<T>::Bitmap_cubical_complex_base(const std::vector<unsigned>& dimensions,
831  const std::vector<T>& cells,
832  const std::vector<bool>& directions,
833  bool input_top_cells) {
834  // this constructor is here just for compatibility with a class that creates cubical complexes with periodic boundary
835  // conditions.
836  // It ignores the last parameter of the function.
837  if (input_top_cells) {
838  this->setup_bitmap_based_on_top_dimensional_cells_list(dimensions, cells);
839  } else {
840  this->setup_bitmap_based_on_vertices(dimensions, cells);
841  }
842 }
843 
844 template <typename T>
846  this->read_perseus_style_file(perseus_style_file);
847 }
848 
849 template <typename T>
850 std::vector<std::size_t> Bitmap_cubical_complex_base<T>::get_boundary_of_a_cell(std::size_t cell) const {
851  std::vector<std::size_t> boundary_elements;
852 
853  // Speed traded of for memory. Check if it is better in practice.
854  boundary_elements.reserve(this->dimension() * 2);
855 
856  std::size_t sum_of_dimensions = 0;
857  std::size_t cell1 = cell;
858  for (std::size_t i = this->multipliers.size(); i > 1; --i) {
859  unsigned position = cell1 / this->multipliers[i - 1];
860  cell1 = cell1 % this->multipliers[i - 1];
861  if (position % 2 == 1) {
862  if (sum_of_dimensions % 2) {
863  boundary_elements.push_back(cell + this->multipliers[i - 1]);
864  boundary_elements.push_back(cell - this->multipliers[i - 1]);
865  } else {
866  boundary_elements.push_back(cell - this->multipliers[i - 1]);
867  boundary_elements.push_back(cell + this->multipliers[i - 1]);
868  }
869  ++sum_of_dimensions;
870  }
871  }
872  // Split out the last iteration to save a costly division by multipliers[0]=1
873  if (cell1 % 2 == 1) {
874  if (sum_of_dimensions % 2) {
875  boundary_elements.push_back(cell + 1);
876  boundary_elements.push_back(cell - 1);
877  } else {
878  boundary_elements.push_back(cell - 1);
879  boundary_elements.push_back(cell + 1);
880  }
881  ++sum_of_dimensions;
882  }
883 
884  return boundary_elements;
885 }
886 
887 template <typename T>
888 std::vector<std::size_t> Bitmap_cubical_complex_base<T>::get_coboundary_of_a_cell(std::size_t cell) const {
889  std::vector<unsigned> counter = this->compute_counter_for_given_cell(cell);
890  std::vector<std::size_t> coboundary_elements;
891  std::size_t cell1 = cell;
892  for (std::size_t i = this->multipliers.size(); i > 1; --i) {
893  // It is a bit sad to recompute those divisions when we just did them in compute_counter_for_given_cell.
894  unsigned position = cell1 / this->multipliers[i - 1];
895  cell1 = cell1 % this->multipliers[i - 1];
896  if (position % 2 == 0) {
897  if ((cell > this->multipliers[i - 1]) && (counter[i - 1] != 0)) {
898  coboundary_elements.push_back(cell - this->multipliers[i - 1]);
899  }
900  if ((cell + this->multipliers[i - 1] < this->data.size()) && (counter[i - 1] != 2 * this->sizes[i - 1])) {
901  coboundary_elements.push_back(cell + this->multipliers[i - 1]);
902  }
903  }
904  }
905  if (cell1 % 2 == 0) {
906  if ((cell > 1) && (counter[0] != 0)) {
907  coboundary_elements.push_back(cell - 1);
908  }
909  if ((cell + 1 < this->data.size()) && (counter[0] != 2 * this->sizes[0])) {
910  coboundary_elements.push_back(cell + 1);
911  }
912  }
913  return coboundary_elements;
914 }
915 
916 template <typename T>
918 #ifdef DEBUG_TRACES
919  std::clog << "\n\n\n Computing position o a cell of an index : " << cell << std::endl;
920 #endif
921  unsigned dimension = 0;
922  for (std::size_t i = this->multipliers.size(); i > 1; --i) {
923  unsigned position = cell / this->multipliers[i - 1];
924  std::size_t newcell = cell % this->multipliers[i - 1];
925 
926 #ifdef DEBUG_TRACES
927  std::clog << "i-1 :" << i - 1 << std::endl;
928  std::clog << "cell : " << cell << std::endl;
929  std::clog << "position : " << position << std::endl;
930  std::clog << "multipliers[" << i - 1 << "] = " << this->multipliers[i - 1] << std::endl;
931 #endif
932 
933  if (position % 2 == 1) {
934 #ifdef DEBUG_TRACES
935  std::clog << "Nonzero length in this direction \n";
936 #endif
937  dimension++;
938  }
939  cell = newcell;
940  }
941  // Split out the last iteration to save a costly division by multipliers[0]=1
942 #ifdef DEBUG_TRACES
943  std::clog << "i-1 :" << 0 << std::endl;
944  std::clog << "cell : " << cell << std::endl;
945  std::clog << "position : " << cell << std::endl;
946  std::clog << "multipliers[" << 0 << "] = " << 1 << std::endl;
947 #endif
948 
949  if (cell % 2 == 1) {
950 #ifdef DEBUG_TRACES
951  std::clog << "Nonzero length in this direction \n";
952 #endif
953  dimension++;
954  }
955 
956  return dimension;
957 }
958 
959 template <typename T>
961  return this->data[cell];
962 }
963 
964 template <typename T>
966  // this vector will be used to check which elements have already been taken care of in imposing lower star filtration
967  std::vector<bool> is_this_cell_considered(this->data.size(), false);
968 
969  std::vector<std::size_t> indices_to_consider;
970  // we assume here that we already have a filtration on the top dimensional cells and
971  // we have to extend it to lower ones.
972  for (auto it = this->top_dimensional_cells_iterator_begin();
973  it != this->top_dimensional_cells_iterator_end(); ++it) {
974  indices_to_consider.push_back(it.compute_index_in_bitmap());
975  }
976 
977  while (indices_to_consider.size()) {
978 #ifdef DEBUG_TRACES
979  std::clog << "indices_to_consider in this iteration \n";
980  for (auto index : indices_to_consider) {
981  std::clog << index << " ";
982  }
983 #endif
984  std::vector<std::size_t> new_indices_to_consider;
985  for (auto index : indices_to_consider) {
986  std::vector<std::size_t> bd = this->get_boundary_of_a_cell(index);
987  for (auto boundary : bd) {
988 #ifdef DEBUG_TRACES
989  std::clog << "filtration of a cell : " << boundary << " is : " << this->data[boundary]
990  << " while of a cell: " << index << " is: " << this->data[index]
991  << std::endl;
992 #endif
993  if (this->data[boundary] > this->data[index]) {
994  this->data[boundary] = this->data[index];
995 #ifdef DEBUG_TRACES
996  std::clog << "Setting the value of a cell : " << boundary
997  << " to : " << this->data[index] << std::endl;
998 #endif
999  }
1000  if (is_this_cell_considered[boundary] == false) {
1001  new_indices_to_consider.push_back(boundary);
1002  is_this_cell_considered[boundary] = true;
1003  }
1004  }
1005  }
1006  indices_to_consider.swap(new_indices_to_consider);
1007  }
1008 }
1009 
1010 template <typename T>
1011 template <class F>
1012 void Bitmap_cubical_complex_base<T>::for_each_vertex_rec(F&&f, std::size_t base, int dim) {
1013  if (dim > 0)
1014  for(std::size_t i = 0; i < sizes[dim] + 1; ++i)
1015  for_each_vertex_rec(f, base + multipliers[dim] * 2 * i, dim - 1);
1016  else
1017  for(std::size_t i = 0; i < sizes[0] + 1; ++i)
1018  f(base + 2 * i);
1019 }
1020 
1021 template <typename T>
1023  int max_dim = multipliers.size()-1;
1024  for (int dim = max_dim; dim >= 0; --dim)
1025  propagate_from_vertices_rec(dim, max_dim, 0);
1026 }
1027 
1028 template <typename T>
1029 void Bitmap_cubical_complex_base<T>::propagate_from_vertices_rec (int special_dim, int current_dim, std::size_t base) {
1030  if (special_dim == current_dim) {
1031  propagate_from_vertices_rec(special_dim, current_dim - 1, base);
1032  return;
1033  }
1034  if (current_dim < 0) {
1035  std::size_t step = multipliers[special_dim];
1036  for(std::size_t i = 0; i < sizes[special_dim]; ++i) {
1037  std::size_t ref = base + step * 2 * i;
1038  data[ref + step] = std::max(data[ref], data[ref + 2 * step]);
1039  }
1040  return;
1041  }
1042  if (current_dim < special_dim)
1043  for(std::size_t i = 0; i < sizes[current_dim] + 1; ++i)
1044  propagate_from_vertices_rec(special_dim, current_dim - 1, base + multipliers[current_dim] * 2 * i);
1045  else
1046  for(std::size_t i = 0; i < 2 * sizes[current_dim] + 1; ++i)
1047  propagate_from_vertices_rec(special_dim, current_dim - 1, base + multipliers[current_dim] * i);
1048 }
1049 
1050 template <typename T>
1051 bool compareFirstElementsOfTuples(const std::pair<std::pair<T, std::size_t>, char>& first,
1052  const std::pair<std::pair<T, std::size_t>, char>& second) {
1053  if (first.first.first < second.first.first) {
1054  return true;
1055  } else {
1056  if (first.first.first > second.first.first) {
1057  return false;
1058  }
1059  // in this case first.first.first == second.first.first, so we need to compare dimensions
1060  return first.second < second.second;
1061  }
1062 }
1063 
1064 } // namespace cubical_complex
1065 
1066 namespace Cubical_complex = cubical_complex;
1067 
1068 } // namespace Gudhi
1069 
1070 #endif // BITMAP_CUBICAL_COMPLEX_BASE_H_
Iterator through top dimensional cells of the complex. The cells appear in order they are stored in t...
Definition: Bitmap_cubical_complex_base.h:315
Range corresponding to Top_dimensional_cells_iterator.
Definition: Bitmap_cubical_complex_base.h:410
Cubical complex represented as a bitmap, class with basic implementation.
Definition: Bitmap_cubical_complex_base.h:57
std::vector< std::size_t >::const_iterator Coboundary_iterator
Definition: Bitmap_cubical_complex_base.h:302
Bitmap_cubical_complex_base()
Definition: Bitmap_cubical_complex_base.h:64
void put_data_to_bins(std::size_t number_of_bins)
Definition: Bitmap_cubical_complex_base.h:611
void impose_lower_star_filtration()
Definition: Bitmap_cubical_complex_base.h:965
boost::counting_iterator< std::size_t > All_cells_iterator
Iterator through all cells in the complex (in order they appear in the structure – i....
Definition: Bitmap_cubical_complex_base.h:267
std::size_t size() const
Definition: Bitmap_cubical_complex_base.h:232
boost::iterator_range< All_cells_iterator > All_cells_range
Range corresponding to All_cells_iterator.
Definition: Bitmap_cubical_complex_base.h:282
virtual std::vector< std::size_t > get_coboundary_of_a_cell(std::size_t cell) const
Definition: Bitmap_cubical_complex_base.h:888
unsigned get_dimension_of_a_cell(std::size_t cell) const
Definition: Bitmap_cubical_complex_base.h:917
unsigned dimension() const
Definition: Bitmap_cubical_complex_base.h:227
Top_dimensional_cells_iterator top_dimensional_cells_iterator_begin()
Definition: Bitmap_cubical_complex_base.h:390
Top_dimensional_cells_range top_dimensional_cells_range()
Definition: Bitmap_cubical_complex_base.h:423
virtual std::vector< std::size_t > get_boundary_of_a_cell(std::size_t cell) const
Definition: Bitmap_cubical_complex_base.h:850
Coboundary_range coboundary_range(std::size_t sh)
Definition: Bitmap_cubical_complex_base.h:309
All_cells_range all_cells_range() const
Definition: Bitmap_cubical_complex_base.h:285
std::pair< T, T > min_max_filtration()
Definition: Bitmap_cubical_complex_base.h:646
Top_dimensional_cells_iterator top_dimensional_cells_iterator_end()
Definition: Bitmap_cubical_complex_base.h:398
std::vector< std::size_t >::const_iterator Boundary_iterator
Definition: Bitmap_cubical_complex_base.h:290
size_t get_top_dimensional_coface_of_a_cell(size_t splx)
Definition: Bitmap_cubical_complex_base.h:715
All_cells_iterator all_cells_iterator_end() const
Definition: Bitmap_cubical_complex_base.h:277
T & get_cell_data(std::size_t cell)
Definition: Bitmap_cubical_complex_base.h:960
void impose_lower_star_filtration_from_vertices()
Definition: Bitmap_cubical_complex_base.h:1022
Boundary_range boundary_range(std::size_t sh)
Definition: Bitmap_cubical_complex_base.h:297
virtual int compute_incidence_between_cells(std::size_t coface, std::size_t face) const
Definition: Bitmap_cubical_complex_base.h:157
size_t get_vertex_of_a_cell(size_t splx)
Definition: Bitmap_cubical_complex_base.h:728
All_cells_iterator all_cells_iterator_begin() const
Definition: Bitmap_cubical_complex_base.h:272
virtual ~Bitmap_cubical_complex_base()
Definition: Bitmap_cubical_complex_base.h:88
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14