Gudhi  1.2.0
 All Classes Functions Variables Typedefs Friends Groups Pages
Persistent_cohomology.h
1 /* This file is part of the Gudhi Library. The Gudhi library
2  * (Geometric Understanding in Higher Dimensions) is a generic C++
3  * library for computational topology.
4  *
5  * Author(s): Clément Maria
6  *
7  * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef PERSISTENT_COHOMOLOGY_H_
24 #define PERSISTENT_COHOMOLOGY_H_
25 
26 #include <gudhi/Persistent_cohomology/Persistent_cohomology_column.h>
27 #include <gudhi/Persistent_cohomology/Field_Zp.h>
28 #include <gudhi/Simple_object_pool.h>
29 
30 #include <boost/tuple/tuple.hpp>
31 #include <boost/intrusive/set.hpp>
32 #include <boost/pending/disjoint_sets.hpp>
33 #include <boost/intrusive/list.hpp>
34 
35 #include <map>
36 #include <utility>
37 #include <list>
38 #include <vector>
39 #include <set>
40 #include <fstream> // std::ofstream
41 #include <limits> // for numeric_limits<>
42 #include <tuple>
43 #include <algorithm>
44 #include <string>
45 
46 namespace Gudhi {
47 
48 namespace persistent_cohomology {
49 
201 // Memory allocation policy: classic, use a mempool, etc.*/
202 template<class FilteredComplex, class CoefficientField> // to do mem allocation policy: classic, mempool, etc.
204  public:
205  typedef FilteredComplex Complex_ds;
206  // Data attached to each simplex to interface with a Property Map.
207  typedef typename Complex_ds::Simplex_key Simplex_key;
208  typedef typename Complex_ds::Simplex_handle Simplex_handle;
209  typedef typename Complex_ds::Filtration_value Filtration_value;
210  typedef typename CoefficientField::Element Arith_element;
211 // Compressed Annotation Matrix types:
212  // Column type
213  typedef Persistent_cohomology_column<Simplex_key, Arith_element> Column; // contains 1 set_hook
214  // Cell type
215  typedef typename Column::Cell Cell; // contains 2 list_hooks
216  // Remark: constant_time_size must be false because base_hook_cam_h has auto_unlink link_mode
217  typedef boost::intrusive::list<Cell,
218  boost::intrusive::constant_time_size<false>,
219  boost::intrusive::base_hook<base_hook_cam_h> > Hcell;
220 
221  typedef boost::intrusive::set<Column,
222  boost::intrusive::constant_time_size<false> > Cam;
223 // Sparse column type for the annotation of the boundary of an element.
224  typedef std::vector<std::pair<Simplex_key, Arith_element> > A_ds_type;
225 // Persistent interval type. The Arith_element field is used for the multi-field framework.
226  typedef boost::tuple<Simplex_handle, Simplex_handle, Arith_element> Persistent_interval;
227 
234  : cpx_(&cpx),
235  dim_max_(cpx.dimension()), // upper bound on the dimension of the simplices
236  coeff_field_(), // initialize the field coefficient structure.
237  num_simplices_(cpx_->num_simplices()), // num_simplices save to avoid to call thrice the function
238  ds_rank_(num_simplices_), // union-find
239  ds_parent_(num_simplices_), // union-find
240  ds_repr_(num_simplices_, NULL), // union-find -> annotation vectors
241  dsets_(&ds_rank_[0], &ds_parent_[0]), // union-find
242  cam_(), // collection of annotation vectors
243  zero_cocycles_(), // union-find -> Simplex_key of creator for 0-homology
244  transverse_idx_(), // key -> row
245  persistent_pairs_(),
246  interval_length_policy(&cpx, 0),
247  column_pool_(), // memory pools for the CAM
248  cell_pool_() {
249  Simplex_key idx_fil = 0;
250  for (auto sh : cpx_->filtration_simplex_range()) {
251  cpx_->assign_key(sh, idx_fil);
252  ++idx_fil;
253  dsets_.make_set(cpx_->key(sh));
254  }
255  }
256 
265  Persistent_cohomology(Complex_ds& cpx, bool persistence_dim_max)
266  : Persistent_cohomology(cpx) {
267  if (persistence_dim_max) {
268  ++dim_max_;
269  }
270  }
271 
273  // Clean the transversal lists
274  for (auto & transverse_ref : transverse_idx_) {
275  // Destruct all the cells
276  transverse_ref.second.row_->clear_and_dispose([&](Cell*p){p->~Cell();});
277  delete transverse_ref.second.row_;
278  }
279  }
280 
281  private:
282  struct length_interval {
283  length_interval(Complex_ds * cpx, Filtration_value min_length)
284  : cpx_(cpx),
285  min_length_(min_length) {
286  }
287 
288  bool operator()(Simplex_handle sh1, Simplex_handle sh2) {
289  return cpx_->filtration(sh2) - cpx_->filtration(sh1) > min_length_;
290  }
291 
292  void set_length(Filtration_value new_length) {
293  min_length_ = new_length;
294  }
295 
296  Complex_ds * cpx_;
297  Filtration_value min_length_;
298  };
299 
300  public:
302  void init_coefficients(int charac) {
303  coeff_field_.init(charac);
304  }
306  void init_coefficients(int charac_min, int charac_max) {
307  coeff_field_.init(charac_min, charac_max);
308  }
309 
318  void compute_persistent_cohomology(Filtration_value min_interval_length = 0) {
319  interval_length_policy.set_length(min_interval_length);
320  // Compute all finite intervals
321  for (auto sh : cpx_->filtration_simplex_range()) {
322  int dim_simplex = cpx_->dimension(sh);
323  switch (dim_simplex) {
324  case 0:
325  break;
326  case 1:
327  update_cohomology_groups_edge(sh);
328  break;
329  default:
330  update_cohomology_groups(sh, dim_simplex);
331  break;
332  }
333  }
334  // Compute infinite intervals of dimension 0
335  Simplex_key key;
336  for (auto v_sh : cpx_->skeleton_simplex_range(0)) { // for all 0-dimensional simplices
337  key = cpx_->key(v_sh);
338 
339  if (ds_parent_[key] == key // root of its tree
340  && zero_cocycles_.find(key) == zero_cocycles_.end()) {
341  persistent_pairs_.emplace_back(
342  cpx_->simplex(key), cpx_->null_simplex(), coeff_field_.characteristic());
343  }
344  }
345  for (auto zero_idx : zero_cocycles_) {
346  persistent_pairs_.emplace_back(
347  cpx_->simplex(zero_idx.second), cpx_->null_simplex(), coeff_field_.characteristic());
348  }
349 // Compute infinite interval of dimension > 0
350  for (auto cocycle : transverse_idx_) {
351  persistent_pairs_.emplace_back(
352  cpx_->simplex(cocycle.first), cpx_->null_simplex(), cocycle.second.characteristics_);
353  }
354  }
355 
356  private:
361  void update_cohomology_groups_edge(Simplex_handle sigma) {
362  Simplex_handle u, v;
363  boost::tie(u, v) = cpx_->endpoints(sigma);
364 
365  Simplex_key ku = dsets_.find_set(cpx_->key(u));
366  Simplex_key kv = dsets_.find_set(cpx_->key(v));
367 
368  if (ku != kv) { // Destroy a connected component
369  dsets_.link(ku, kv);
370  // Keys of the simplices which created the connected components containing
371  // respectively u and v.
372  Simplex_key idx_coc_u, idx_coc_v;
373  auto map_it_u = zero_cocycles_.find(ku);
374  // If the index of the cocycle representing the class is already ku.
375  if (map_it_u == zero_cocycles_.end()) {
376  idx_coc_u = ku;
377  } else {
378  idx_coc_u = map_it_u->second;
379  }
380 
381  auto map_it_v = zero_cocycles_.find(kv);
382  // If the index of the cocycle representing the class is already kv.
383  if (map_it_v == zero_cocycles_.end()) {
384  idx_coc_v = kv;
385  } else {
386  idx_coc_v = map_it_v->second;
387  }
388 
389  if (cpx_->filtration(cpx_->simplex(idx_coc_u))
390  < cpx_->filtration(cpx_->simplex(idx_coc_v))) { // Kill cocycle [idx_coc_v], which is younger.
391  if (interval_length_policy(cpx_->simplex(idx_coc_v), sigma)) {
392  persistent_pairs_.emplace_back(
393  cpx_->simplex(idx_coc_v), sigma, coeff_field_.characteristic());
394  }
395  // Maintain the index of the 0-cocycle alive.
396  if (kv != idx_coc_v) {
397  zero_cocycles_.erase(map_it_v);
398  }
399  if (kv == dsets_.find_set(kv)) {
400  if (ku != idx_coc_u) {
401  zero_cocycles_.erase(map_it_u);
402  }
403  zero_cocycles_[kv] = idx_coc_u;
404  }
405  } else { // Kill cocycle [idx_coc_u], which is younger.
406  if (interval_length_policy(cpx_->simplex(idx_coc_u), sigma)) {
407  persistent_pairs_.emplace_back(
408  cpx_->simplex(idx_coc_u), sigma, coeff_field_.characteristic());
409  }
410  // Maintain the index of the 0-cocycle alive.
411  if (ku != idx_coc_u) {
412  zero_cocycles_.erase(map_it_u);
413  }
414  if (ku == dsets_.find_set(ku)) {
415  if (kv != idx_coc_v) {
416  zero_cocycles_.erase(map_it_v);
417  }
418  zero_cocycles_[ku] = idx_coc_v;
419  }
420  }
421  cpx_->assign_key(sigma, cpx_->null_key());
422  } else { // If ku == kv, same connected component: create a 1-cocycle class.
423  create_cocycle(sigma, coeff_field_.multiplicative_identity(), coeff_field_.characteristic());
424  }
425  }
426 
427  /*
428  * Compute the annotation of the boundary of a simplex.
429  */
430  void annotation_of_the_boundary(
431  std::map<Simplex_key, Arith_element> & map_a_ds, Simplex_handle sigma,
432  int dim_sigma) {
433  // traverses the boundary of sigma, keeps track of the annotation vectors,
434  // with multiplicity, in a map.
435  std::map<Column *, int> annotations_in_boundary;
436  std::pair<typename std::map<Column *, int>::iterator, bool> result_insert_bound;
437  int sign = 1 - 2 * (dim_sigma % 2); // \in {-1,1} provides the sign in the
438  // alternate sum in the boundary.
439  Simplex_key key;
440  Column * curr_col;
441 
442  for (auto sh : cpx_->boundary_simplex_range(sigma)) {
443  key = cpx_->key(sh);
444  if (key != cpx_->null_key()) { // A simplex with null_key is a killer, and have null annotation
445  // Find its annotation vector
446  curr_col = ds_repr_[dsets_.find_set(key)];
447  if (curr_col != NULL) { // and insert it in annotations_in_boundary with multyiplicative factor "sign".
448  result_insert_bound = annotations_in_boundary.insert(std::pair<Column *, int>(curr_col, sign));
449  if (!(result_insert_bound.second)) {
450  result_insert_bound.first->second += sign;
451  }
452  }
453  }
454  sign = -sign;
455  }
456  // Sum the annotations with multiplicity, using a map<key,coeff>
457  // to represent a sparse vector.
458  std::pair<typename std::map<Simplex_key, Arith_element>::iterator, bool> result_insert_a_ds;
459 
460  for (auto ann_ref : annotations_in_boundary) {
461  if (ann_ref.second != coeff_field_.additive_identity()) { // For all columns in the boundary,
462  for (auto cell_ref : ann_ref.first->col_) { // insert every cell in map_a_ds with multiplicity
463  Arith_element w_y = coeff_field_.times(cell_ref.coefficient_, ann_ref.second); // coefficient * multiplicity
464 
465  if (w_y != coeff_field_.additive_identity()) { // if != 0
466  result_insert_a_ds = map_a_ds.insert(std::pair<Simplex_key, Arith_element>(cell_ref.key_, w_y));
467  if (!(result_insert_a_ds.second)) { // if cell_ref.key_ already a Key in map_a_ds
468  result_insert_a_ds.first->second = coeff_field_.plus_equal(result_insert_a_ds.first->second, w_y);
469  if (result_insert_a_ds.first->second == coeff_field_.additive_identity()) {
470  map_a_ds.erase(result_insert_a_ds.first);
471  }
472  }
473  }
474  }
475  }
476  }
477  }
478 
479  /*
480  * Update the cohomology groups under the insertion of a simplex.
481  */
482  void update_cohomology_groups(Simplex_handle sigma, int dim_sigma) {
483 // Compute the annotation of the boundary of sigma:
484  std::map<Simplex_key, Arith_element> map_a_ds;
485  annotation_of_the_boundary(map_a_ds, sigma, dim_sigma);
486 // Update the cohomology groups:
487  if (map_a_ds.empty()) { // sigma is a creator in all fields represented in coeff_field_
488  if (dim_sigma < dim_max_) {
489  create_cocycle(sigma, coeff_field_.multiplicative_identity(),
490  coeff_field_.characteristic());
491  }
492  } else { // sigma is a destructor in at least a field in coeff_field_
493  // Convert map_a_ds to a vector
494  A_ds_type a_ds; // admits reverse iterators
495  for (auto map_a_ds_ref : map_a_ds) {
496  a_ds.push_back(
497  std::pair<Simplex_key, Arith_element>(map_a_ds_ref.first,
498  map_a_ds_ref.second));
499  }
500 
501  Arith_element inv_x, charac;
502  Arith_element prod = coeff_field_.characteristic(); // Product of characteristic of the fields
503  for (auto a_ds_rit = a_ds.rbegin();
504  (a_ds_rit != a_ds.rend())
505  && (prod != coeff_field_.multiplicative_identity()); ++a_ds_rit) {
506  std::tie(inv_x, charac) = coeff_field_.inverse(a_ds_rit->second, prod);
507 
508  if (inv_x != coeff_field_.additive_identity()) {
509  destroy_cocycle(sigma, a_ds, a_ds_rit->first, inv_x, charac);
510  prod /= charac;
511  }
512  }
513  if (prod != coeff_field_.multiplicative_identity()
514  && dim_sigma < dim_max_) {
515  create_cocycle(sigma, coeff_field_.multiplicative_identity(prod), prod);
516  }
517  }
518  }
519 
520  /* \brief Create a new cocycle class.
521  *
522  * The class is created by the insertion of the simplex sigma.
523  * The methods adds a cocycle, representing the new cocycle class,
524  * to the matrix representing the cohomology groups.
525  * The new cocycle has value 0 on every simplex except on sigma
526  * where it worths 1.*/
527  void create_cocycle(Simplex_handle sigma, Arith_element x,
528  Arith_element charac) {
529  Simplex_key key = cpx_->key(sigma);
530  // Create a column containing only one cell,
531  Column * new_col = column_pool_.construct(key);
532  Cell * new_cell = cell_pool_.construct(key, x, new_col);
533  new_col->col_.push_back(*new_cell);
534  // and insert it in the matrix, in constant time thanks to the hint cam_.end().
535  // Indeed *new_col has the biggest lexicographic value because key is the
536  // biggest key used so far.
537  cam_.insert(cam_.end(), *new_col);
538  // Update the disjoint sets data structure.
539  Hcell * new_hcell = new Hcell;
540  new_hcell->push_back(*new_cell);
541  transverse_idx_[key] = cocycle(charac, new_hcell); // insert the new row
542  ds_repr_[key] = new_col;
543  }
544 
545  /* \brief Destroy a cocycle class.
546  *
547  * The cocycle class is destroyed by the insertion of sigma.
548  * The methods proceeds to a reduction of the matrix representing
549  * the cohomology groups using Gauss pivoting. The reduction zeros-out
550  * the row containing the cell with highest key in
551  * a_ds, the annotation of the boundary of simplex sigma. This key
552  * is "death_key".*/
553  void destroy_cocycle(Simplex_handle sigma, A_ds_type const& a_ds,
554  Simplex_key death_key, Arith_element inv_x,
555  Arith_element charac) {
556  // Create a finite persistent interval for which the interval exists
557  if (interval_length_policy(cpx_->simplex(death_key), sigma)) {
558  persistent_pairs_.emplace_back(cpx_->simplex(death_key) // creator
559  , sigma // destructor
560  , charac); // fields
561  }
562 
563  auto death_key_row = transverse_idx_.find(death_key); // Find the beginning of the row.
564  std::pair<typename Cam::iterator, bool> result_insert_cam;
565 
566  auto row_cell_it = death_key_row->second.row_->begin();
567 
568  while (row_cell_it != death_key_row->second.row_->end()) { // Traverse all cells in
569  // the row at index death_key.
570  Arith_element w = coeff_field_.times_minus(inv_x, row_cell_it->coefficient_);
571 
572  if (w != coeff_field_.additive_identity()) {
573  Column * curr_col = row_cell_it->self_col_;
574  ++row_cell_it;
575  // Disconnect the column from the rows in the CAM.
576  for (auto& col_cell : curr_col->col_) {
577  col_cell.base_hook_cam_h::unlink();
578  }
579 
580  // Remove the column from the CAM before modifying its value
581  cam_.erase(cam_.iterator_to(*curr_col));
582  // Proceed to the reduction of the column
583  plus_equal_column(*curr_col, a_ds, w);
584 
585  if (curr_col->col_.empty()) { // If the column is null
586  ds_repr_[curr_col->class_key_] = NULL;
587  column_pool_.destroy(curr_col); // delete curr_col;
588  } else {
589  // Find whether the column obtained is already in the CAM
590  result_insert_cam = cam_.insert(*curr_col);
591  if (result_insert_cam.second) { // If it was not in the CAM before: insertion has succeeded
592  for (auto& col_cell : curr_col->col_) {
593  // re-establish the row links
594  transverse_idx_[col_cell.key_].row_->push_front(col_cell);
595  }
596  } else { // There is already an identical column in the CAM:
597  // merge two disjoint sets.
598  dsets_.link(curr_col->class_key_,
599  result_insert_cam.first->class_key_);
600 
601  Simplex_key key_tmp = dsets_.find_set(curr_col->class_key_);
602  ds_repr_[key_tmp] = &(*(result_insert_cam.first));
603  result_insert_cam.first->class_key_ = key_tmp;
604  // intrusive containers don't own their elements, we have to release them manually
605  curr_col->col_.clear_and_dispose([&](Cell*p){cell_pool_.destroy(p);});
606  column_pool_.destroy(curr_col); // delete curr_col;
607  }
608  }
609  } else {
610  ++row_cell_it;
611  } // If w == 0, pass.
612  }
613 
614  // Because it is a killer simplex, set the data of sigma to null_key().
615  if (charac == coeff_field_.characteristic()) {
616  cpx_->assign_key(sigma, cpx_->null_key());
617  }
618  if (death_key_row->second.characteristics_ == charac) {
619  delete death_key_row->second.row_;
620  transverse_idx_.erase(death_key_row);
621  } else {
622  death_key_row->second.characteristics_ /= charac;
623  }
624  }
625 
626  /*
627  * Assign: target <- target + w * other.
628  */
629  void plus_equal_column(Column & target, A_ds_type const& other // value_type is pair<Simplex_key,Arith_element>
630  , Arith_element w) {
631  auto target_it = target.col_.begin();
632  auto other_it = other.begin();
633  while (target_it != target.col_.end() && other_it != other.end()) {
634  if (target_it->key_ < other_it->first) {
635  ++target_it;
636  } else {
637  if (target_it->key_ > other_it->first) {
638  Cell * cell_tmp = cell_pool_.construct(Cell(other_it->first // key
639  , coeff_field_.additive_identity(), &target));
640 
641  cell_tmp->coefficient_ = coeff_field_.plus_times_equal(cell_tmp->coefficient_, other_it->second, w);
642 
643  target.col_.insert(target_it, *cell_tmp);
644 
645  ++other_it;
646  } else { // it1->key == it2->key
647  // target_it->coefficient_ <- target_it->coefficient_ + other_it->second * w
648  target_it->coefficient_ = coeff_field_.plus_times_equal(target_it->coefficient_, other_it->second, w);
649  if (target_it->coefficient_ == coeff_field_.additive_identity()) {
650  auto tmp_it = target_it;
651  ++target_it;
652  ++other_it; // iterators remain valid
653  Cell * tmp_cell_ptr = &(*tmp_it);
654  target.col_.erase(tmp_it); // removed from column
655 
656  cell_pool_.destroy(tmp_cell_ptr); // delete from memory
657  } else {
658  ++target_it;
659  ++other_it;
660  }
661  }
662  }
663  }
664  while (other_it != other.end()) {
665  Cell * cell_tmp = cell_pool_.construct(Cell(other_it->first, coeff_field_.additive_identity(), &target));
666  cell_tmp->coefficient_ = coeff_field_.plus_times_equal(cell_tmp->coefficient_, other_it->second, w);
667  target.col_.insert(target.col_.end(), *cell_tmp);
668 
669  ++other_it;
670  }
671  }
672 
673  /*
674  * Compare two intervals by length.
675  */
676  struct cmp_intervals_by_length {
677  explicit cmp_intervals_by_length(Complex_ds * sc)
678  : sc_(sc) {
679  }
680  bool operator()(const Persistent_interval & p1, const Persistent_interval & p2) {
681  return (sc_->filtration(get < 1 > (p1)) - sc_->filtration(get < 0 > (p1))
682  > sc_->filtration(get < 1 > (p2)) - sc_->filtration(get < 0 > (p2)));
683  }
684  Complex_ds * sc_;
685  };
686 
687  public:
698  void output_diagram(std::ostream& ostream = std::cout) {
699 
700  cmp_intervals_by_length cmp(cpx_);
701  std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp);
702  bool has_infinity = std::numeric_limits<Filtration_value>::has_infinity;
703  for (auto pair : persistent_pairs_) {
704  // Special case on windows, inf is "1.#INF" (cf. unitary tests and R package TDA)
705  if (has_infinity && cpx_->filtration(get<1>(pair)) == std::numeric_limits<Filtration_value>::infinity()) {
706  ostream << get<2>(pair) << " " << cpx_->dimension(get<0>(pair)) << " "
707  << cpx_->filtration(get<0>(pair)) << " inf " << std::endl;
708  } else {
709  ostream << get<2>(pair) << " " << cpx_->dimension(get<0>(pair)) << " "
710  << cpx_->filtration(get<0>(pair)) << " "
711  << cpx_->filtration(get<1>(pair)) << " " << std::endl;
712  }
713  }
714  }
715 
716  void write_output_diagram(std::string diagram_name) {
717  std::ofstream diagram_out(diagram_name.c_str());
718  cmp_intervals_by_length cmp(cpx_);
719  std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp);
720  for (auto pair : persistent_pairs_) {
721  diagram_out << cpx_->dimension(get<0>(pair)) << " "
722  << cpx_->filtration(get<0>(pair)) << " "
723  << cpx_->filtration(get<1>(pair)) << std::endl;
724  }
725  }
726 
727  private:
728  /*
729  * Structure representing a cocycle.
730  */
731  struct cocycle {
732  cocycle() {
733  }
734  cocycle(Arith_element characteristics, Hcell * row)
735  : row_(row),
736  characteristics_(characteristics) {
737  }
738 
739  Hcell * row_; // points to the corresponding row in the CAM
740  Arith_element characteristics_; // product of field characteristics for which the cocycle exist
741  };
742 
743  public:
744  Complex_ds * cpx_;
745  int dim_max_;
746  CoefficientField coeff_field_;
747  size_t num_simplices_;
748 
749  /* Disjoint sets data structure to link the model of FilteredComplex
750  * with the compressed annotation matrix.
751  * ds_rank_ is a property map Simplex_key -> int, ds_parent_ is a property map
752  * Simplex_key -> simplex_key_t */
753  std::vector<int> ds_rank_;
754  std::vector<Simplex_key> ds_parent_;
755  std::vector<Column *> ds_repr_;
756  boost::disjoint_sets<int *, Simplex_key *> dsets_;
757  /* The compressed annotation matrix fields.*/
758  Cam cam_;
759  /* Dictionary establishing the correspondance between the Simplex_key of
760  * the root vertex in the union-find ds and the Simplex_key of the vertex which
761  * created the connected component as a 0-dimension homology feature.*/
762  std::map<Simplex_key, Simplex_key> zero_cocycles_;
763  /* Key -> row. */
764  std::map<Simplex_key, cocycle> transverse_idx_;
765  /* Persistent intervals. */
766  std::vector<Persistent_interval> persistent_pairs_;
767  length_interval interval_length_policy;
768 
769  Simple_object_pool<Column> column_pool_;
770  Simple_object_pool<Cell> cell_pool_;
771 };
772  // end defgroup persistent_cohomology
774 
775 } // namespace persistent_cohomology
776 
777 } // namespace Gudhi
778 
779 #endif // PERSISTENT_COHOMOLOGY_H_
void init_coefficients(int charac)
Initializes the coefficient field.
Definition: Persistent_cohomology.h:302
unspecified Element
Type of element of the field.
Definition: CoefficientField.h:31
unspecified Simplex_key
Key associated to each simplex.
Definition: FilteredComplex.h:35
Computes the persistent cohomology of a filtered complex.
Definition: Persistent_cohomology.h:203
void assign_key(Simplex_handle sh, Simplex_key key)
Assign a key to a simplex.
Persistent_cohomology(Complex_ds &cpx)
Initializes the Persistent_cohomology class.
Definition: Persistent_cohomology.h:233
Simplex_key null_key()
Returns a key that is different from the keys associated to the simplices.
Simplex_key key(Simplex_handle sh)
Returns the key associated to a simplex.
Simplex_handle null_simplex()
void output_diagram(std::ostream &ostream=std::cout)
Output the persistence diagram in ostream.
Definition: Persistent_cohomology.h:698
Filtration_simplex_range filtration_simplex_range()
Returns a range over the simplices of the complex in the order of the filtration. ...
void init_coefficients(int charac_min, int charac_max)
Initializes the coefficient field for multi-field persistent homology.
Definition: Persistent_cohomology.h:306
unspecified Simplex_handle
Definition: FilteredComplex.h:31
Element additive_identity()
Filtration_value filtration(Simplex_handle sh)
Returns the filtration value of a simplex.
Element multiplicative_identity()
Persistent_cohomology(Complex_ds &cpx, bool persistence_dim_max)
Initializes the Persistent_cohomology class.
Definition: Persistent_cohomology.h:265
Abstract simplex used in Skeleton blockers data-structure.
Definition: Skeleton_blocker_simplex.h:50
int dimension(Simplex_handle sh)
Returns the dimension of a simplex.
Simplex_handle simplex(Simplex_key key)
Returns the simplex associated to a key.
Concept describing the requirements for a class to represent a field of coefficients to compute persi...
Definition: CoefficientField.h:26
Element characteristic()
void plus_equal(Element x, Element y)
void compute_persistent_cohomology(Filtration_value min_interval_length=0)
Compute the persistent homology of the filtered simplicial complex.
Definition: Persistent_cohomology.h:318
The concept FilteredComplex describes the requirements for a type to implement a filtered cell comple...
Definition: FilteredComplex.h:28
unspecified Filtration_value
Type for the value of the filtration function.
Definition: FilteredComplex.h:39
Boundary_simplex_range boundary_simplex_range(Simplex_handle sh)
Returns a range giving access to all simplices of the boundary of a simplex, i.e. the set of codimens...