23 #ifndef PERSISTENT_COHOMOLOGY_H_
24 #define PERSISTENT_COHOMOLOGY_H_
26 #include <gudhi/Persistent_cohomology/Persistent_cohomology_column.h>
27 #include <gudhi/Persistent_cohomology/Field_Zp.h>
28 #include <gudhi/Simple_object_pool.h>
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>
48 namespace persistent_cohomology {
202 template<
class FilteredComplex,
class CoefficientField>
213 typedef Persistent_cohomology_column<Simplex_key, Arith_element> Column;
215 typedef typename Column::Cell Cell;
217 typedef boost::intrusive::list<Cell,
218 boost::intrusive::constant_time_size<false>,
219 boost::intrusive::base_hook<base_hook_cam_h> > Hcell;
221 typedef boost::intrusive::set<Column,
222 boost::intrusive::constant_time_size<false> > Cam;
224 typedef std::vector<std::pair<Simplex_key, Arith_element> > A_ds_type;
226 typedef boost::tuple<Simplex_handle, Simplex_handle, Arith_element> Persistent_interval;
235 dim_max_(cpx.dimension()),
237 num_simplices_(cpx_->num_simplices()),
238 ds_rank_(num_simplices_),
239 ds_parent_(num_simplices_),
240 ds_repr_(num_simplices_, NULL),
241 dsets_(&ds_rank_[0], &ds_parent_[0]),
246 interval_length_policy(&cpx, 0),
249 Simplex_key idx_fil = 0;
253 dsets_.make_set(cpx_->
key(sh));
267 if (persistence_dim_max) {
274 for (
auto & transverse_ref : transverse_idx_) {
276 transverse_ref.second.row_->clear_and_dispose([&](Cell*p){p->~Cell();});
277 delete transverse_ref.second.row_;
282 struct length_interval {
283 length_interval(Complex_ds * cpx, Filtration_value min_length)
285 min_length_(min_length) {
289 return cpx_->filtration(sh2) - cpx_->filtration(sh1) > min_length_;
292 void set_length(Filtration_value new_length) {
293 min_length_ = new_length;
297 Filtration_value min_length_;
303 coeff_field_.init(charac);
307 coeff_field_.init(charac_min, charac_max);
319 interval_length_policy.set_length(min_interval_length);
323 switch (dim_simplex) {
327 update_cohomology_groups_edge(sh);
330 update_cohomology_groups(sh, dim_simplex);
336 for (
auto v_sh : cpx_->skeleton_simplex_range(0)) {
337 key = cpx_->
key(v_sh);
339 if (ds_parent_[key] == key
340 && zero_cocycles_.find(key) == zero_cocycles_.end()) {
341 persistent_pairs_.emplace_back(
345 for (
auto zero_idx : zero_cocycles_) {
346 persistent_pairs_.emplace_back(
350 for (
auto cocycle : transverse_idx_) {
351 persistent_pairs_.emplace_back(
363 boost::tie(u, v) = cpx_->endpoints(sigma);
365 Simplex_key ku = dsets_.find_set(cpx_->
key(u));
366 Simplex_key kv = dsets_.find_set(cpx_->
key(v));
372 Simplex_key idx_coc_u, idx_coc_v;
373 auto map_it_u = zero_cocycles_.find(ku);
375 if (map_it_u == zero_cocycles_.end()) {
378 idx_coc_u = map_it_u->second;
381 auto map_it_v = zero_cocycles_.find(kv);
383 if (map_it_v == zero_cocycles_.end()) {
386 idx_coc_v = map_it_v->second;
391 if (interval_length_policy(cpx_->
simplex(idx_coc_v), sigma)) {
392 persistent_pairs_.emplace_back(
396 if (kv != idx_coc_v) {
397 zero_cocycles_.erase(map_it_v);
399 if (kv == dsets_.find_set(kv)) {
400 if (ku != idx_coc_u) {
401 zero_cocycles_.erase(map_it_u);
403 zero_cocycles_[kv] = idx_coc_u;
406 if (interval_length_policy(cpx_->
simplex(idx_coc_u), sigma)) {
407 persistent_pairs_.emplace_back(
411 if (ku != idx_coc_u) {
412 zero_cocycles_.erase(map_it_u);
414 if (ku == dsets_.find_set(ku)) {
415 if (kv != idx_coc_v) {
416 zero_cocycles_.erase(map_it_v);
418 zero_cocycles_[ku] = idx_coc_v;
430 void annotation_of_the_boundary(
431 std::map<Simplex_key, Arith_element> & map_a_ds,
Simplex_handle sigma,
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);
446 curr_col = ds_repr_[dsets_.find_set(key)];
447 if (curr_col != NULL) {
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;
458 std::pair<typename std::map<Simplex_key, Arith_element>::iterator,
bool> result_insert_a_ds;
460 for (
auto ann_ref : annotations_in_boundary) {
462 for (
auto cell_ref : ann_ref.first->col_) {
463 Arith_element w_y = coeff_field_.times(cell_ref.coefficient_, ann_ref.second);
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)) {
468 result_insert_a_ds.first->second = coeff_field_.
plus_equal(result_insert_a_ds.first->second, w_y);
470 map_a_ds.erase(result_insert_a_ds.first);
482 void update_cohomology_groups(
Simplex_handle sigma,
int dim_sigma) {
484 std::map<Simplex_key, Arith_element> map_a_ds;
485 annotation_of_the_boundary(map_a_ds, sigma, dim_sigma);
487 if (map_a_ds.empty()) {
488 if (dim_sigma < dim_max_) {
495 for (
auto map_a_ds_ref : map_a_ds) {
497 std::pair<Simplex_key, Arith_element>(map_a_ds_ref.first,
498 map_a_ds_ref.second));
501 Arith_element inv_x, charac;
503 for (
auto a_ds_rit = a_ds.rbegin();
504 (a_ds_rit != a_ds.rend())
506 std::tie(inv_x, charac) = coeff_field_.inverse(a_ds_rit->second, prod);
509 destroy_cocycle(sigma, a_ds, a_ds_rit->first, inv_x, charac);
514 && dim_sigma < dim_max_) {
528 Arith_element charac) {
529 Simplex_key key = cpx_->
key(sigma);
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);
537 cam_.insert(cam_.end(), *new_col);
539 Hcell * new_hcell =
new Hcell;
540 new_hcell->push_back(*new_cell);
541 transverse_idx_[key] = cocycle(charac, new_hcell);
542 ds_repr_[key] = new_col;
554 Simplex_key death_key, Arith_element inv_x,
555 Arith_element charac) {
557 if (interval_length_policy(cpx_->
simplex(death_key), sigma)) {
558 persistent_pairs_.emplace_back(cpx_->
simplex(death_key)
563 auto death_key_row = transverse_idx_.find(death_key);
564 std::pair<typename Cam::iterator, bool> result_insert_cam;
566 auto row_cell_it = death_key_row->second.row_->begin();
568 while (row_cell_it != death_key_row->second.row_->end()) {
570 Arith_element w = coeff_field_.times_minus(inv_x, row_cell_it->coefficient_);
573 Column * curr_col = row_cell_it->self_col_;
576 for (
auto& col_cell : curr_col->col_) {
577 col_cell.base_hook_cam_h::unlink();
581 cam_.erase(cam_.iterator_to(*curr_col));
583 plus_equal_column(*curr_col, a_ds, w);
585 if (curr_col->col_.empty()) {
586 ds_repr_[curr_col->class_key_] = NULL;
587 column_pool_.destroy(curr_col);
590 result_insert_cam = cam_.insert(*curr_col);
591 if (result_insert_cam.second) {
592 for (
auto& col_cell : curr_col->col_) {
594 transverse_idx_[col_cell.key_].row_->push_front(col_cell);
598 dsets_.link(curr_col->class_key_,
599 result_insert_cam.first->class_key_);
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;
605 curr_col->col_.clear_and_dispose([&](Cell*p){cell_pool_.destroy(p);});
606 column_pool_.destroy(curr_col);
618 if (death_key_row->second.characteristics_ == charac) {
619 delete death_key_row->second.row_;
620 transverse_idx_.erase(death_key_row);
622 death_key_row->second.characteristics_ /= charac;
629 void plus_equal_column(Column & target, A_ds_type
const& other
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) {
637 if (target_it->key_ > other_it->first) {
638 Cell * cell_tmp = cell_pool_.construct(Cell(other_it->first
641 cell_tmp->coefficient_ = coeff_field_.plus_times_equal(cell_tmp->coefficient_, other_it->second, w);
643 target.col_.insert(target_it, *cell_tmp);
648 target_it->coefficient_ = coeff_field_.plus_times_equal(target_it->coefficient_, other_it->second, w);
650 auto tmp_it = target_it;
653 Cell * tmp_cell_ptr = &(*tmp_it);
654 target.col_.erase(tmp_it);
656 cell_pool_.destroy(tmp_cell_ptr);
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);
676 struct cmp_intervals_by_length {
677 explicit cmp_intervals_by_length(Complex_ds * sc)
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)));
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_) {
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;
709 ostream << get<2>(pair) <<
" " << cpx_->
dimension(get<0>(pair)) <<
" "
711 << cpx_->
filtration(get<1>(pair)) <<
" " << std::endl;
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)) <<
" "
723 << cpx_->
filtration(get<1>(pair)) << std::endl;
734 cocycle(Arith_element characteristics, Hcell * row)
736 characteristics_(characteristics) {
740 Arith_element characteristics_;
747 size_t num_simplices_;
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_;
762 std::map<Simplex_key, Simplex_key> zero_cocycles_;
764 std::map<Simplex_key, cocycle> transverse_idx_;
766 std::vector<Persistent_interval> persistent_pairs_;
767 length_interval interval_length_policy;
769 Simple_object_pool<Column> column_pool_;
770 Simple_object_pool<Cell> cell_pool_;
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
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...