78 typedef Persistent_cohomology_column<Simplex_key, Arith_element> Column;
80 typedef typename Column::Cell Cell;
82 typedef boost::intrusive::list<Cell,
83 boost::intrusive::constant_time_size<false>,
84 boost::intrusive::base_hook<base_hook_cam_h> > Hcell;
86 typedef boost::intrusive::set<Column,
87 boost::intrusive::constant_time_size<false> > Cam;
89 typedef std::vector<std::pair<Simplex_key, Arith_element> > A_ds_type;
104 dim_max_(cpx.dimension()),
106 num_simplices_(cpx_->num_simplices()),
107 ds_rank_(num_simplices_),
108 ds_parent_(num_simplices_),
109 ds_repr_(num_simplices_, NULL),
110 dsets_(ds_rank_.data(), ds_parent_.data()),
115 interval_length_policy(&cpx, 0),
118 if (num_simplices_ > std::numeric_limits<Simplex_key>::max()) {
120 throw std::out_of_range(
"The number of simplices is more than Simplex_key type numeric limit.");
122 if (persistence_dim_max) {
129 for (
auto & transverse_ref : transverse_idx_) {
131 transverse_ref.second.row_->clear_and_dispose([&](Cell*p){p->~Cell();});
132 delete transverse_ref.second.row_;
137 struct length_interval {
140 min_length_(min_length) {
144 return cpx_->filtration(sh2) - cpx_->filtration(sh1) > min_length_;
148 min_length_ = new_length;
151 FilteredComplex * cpx_;
158 coeff_field_.init(charac);
162 coeff_field_.init(charac_min, charac_max);
177 interval_length_policy.set_length(min_interval_length);
179 std::vector<Simplex_key> vertices;
181 for (
auto sh : cpx_->filtration_simplex_range()) {
182 cpx_->assign_key(sh, ++idx_fil);
183 dsets_.make_set(cpx_->key(sh));
184 int dim_simplex = cpx_->dimension(sh);
185 switch (dim_simplex) {
187 vertices.push_back(idx_fil);
190 update_cohomology_groups_edge(sh);
193 update_cohomology_groups(sh, dim_simplex);
199 if (ds_parent_[key] == key
200 && zero_cocycles_.find(key) == zero_cocycles_.end()) {
201 persistent_pairs_.emplace_back(
202 cpx_->simplex(key), cpx_->null_simplex(), coeff_field_.characteristic());
205 for (
auto zero_idx : zero_cocycles_) {
206 persistent_pairs_.emplace_back(
207 cpx_->simplex(zero_idx.second), cpx_->null_simplex(), coeff_field_.characteristic());
210 for (
auto cocycle : transverse_idx_) {
211 persistent_pairs_.emplace_back(
212 cpx_->simplex(cocycle.first), cpx_->null_simplex(), cocycle.second.characteristics_);
221 void compute_persistent_cohomology_without_optimizations(Filtration_value min_interval_length = 0) {
225 interval_length_policy.set_length(min_interval_length);
230 dsets_.make_set(cpx_->
key(sh));
232 update_cohomology_groups(sh, dim_simplex);
235 for (
auto cocycle : transverse_idx_) {
236 persistent_pairs_.emplace_back(
248 boost::tie(u, v) = cpx_->endpoints(sigma);
258 auto map_it_u = zero_cocycles_.find(ku);
260 if (map_it_u == zero_cocycles_.end()) {
263 idx_coc_u = map_it_u->second;
266 auto map_it_v = zero_cocycles_.find(kv);
268 if (map_it_v == zero_cocycles_.end()) {
271 idx_coc_v = map_it_v->second;
274 if (cpx_->filtration(cpx_->simplex(idx_coc_u))
275 < cpx_->filtration(cpx_->simplex(idx_coc_v))) {
276 if (interval_length_policy(cpx_->simplex(idx_coc_v), sigma)) {
277 persistent_pairs_.emplace_back(
278 cpx_->simplex(idx_coc_v), sigma, coeff_field_.characteristic());
281 if (kv != idx_coc_v) {
282 zero_cocycles_.erase(map_it_v);
284 if (kv == dsets_.find_set(kv)) {
285 if (ku != idx_coc_u) {
286 zero_cocycles_.erase(map_it_u);
288 zero_cocycles_[kv] = idx_coc_u;
291 if (interval_length_policy(cpx_->simplex(idx_coc_u), sigma)) {
292 persistent_pairs_.emplace_back(
293 cpx_->simplex(idx_coc_u), sigma, coeff_field_.characteristic());
296 if (ku != idx_coc_u) {
297 zero_cocycles_.erase(map_it_u);
299 if (ku == dsets_.find_set(ku)) {
300 if (kv != idx_coc_v) {
301 zero_cocycles_.erase(map_it_v);
303 zero_cocycles_[ku] = idx_coc_v;
306 cpx_->assign_key(sigma, cpx_->null_key());
307 }
else if (dim_max_ > 1) {
308 create_cocycle(sigma, coeff_field_.multiplicative_identity(), coeff_field_.characteristic());
315 void annotation_of_the_boundary(
316 std::map<Simplex_key, Arith_element> & map_a_ds,
Simplex_handle sigma,
321 typedef std::pair<Column *, int> annotation_t;
322 thread_local std::vector<annotation_t> annotations_in_boundary;
323 annotations_in_boundary.clear();
324 int sign = 1 - 2 * (dim_sigma % 2);
329 for (
auto sh : cpx_->boundary_simplex_range(sigma)) {
331 if (key != cpx_->null_key()) {
333 curr_col = ds_repr_[dsets_.find_set(key)];
334 if (curr_col != NULL) {
335 annotations_in_boundary.emplace_back(curr_col, sign);
341 std::sort(annotations_in_boundary.begin(), annotations_in_boundary.end(),
342 [](annotation_t
const& a, annotation_t
const& b) { return a.first < b.first; });
346 std::pair<typename std::map<Simplex_key, Arith_element>::iterator,
bool> result_insert_a_ds;
348 for (
auto ann_it = annotations_in_boundary.begin(); ann_it != annotations_in_boundary.end(); ) {
349 Column* col = ann_it->first;
350 int mult = ann_it->second;
351 while (++ann_it != annotations_in_boundary.end() && ann_it->first == col) {
352 mult += ann_it->second;
355 if (mult != coeff_field_.additive_identity()) {
356 for (
auto&& cell_ref : col->col_) {
357 Arith_element w_y = coeff_field_.times(cell_ref.coefficient_, mult);
359 if (w_y != coeff_field_.additive_identity()) {
360 result_insert_a_ds = map_a_ds.emplace(cell_ref.key_, w_y);
361 if (!(result_insert_a_ds.second)) {
362 result_insert_a_ds.first->second = coeff_field_.plus_equal(result_insert_a_ds.first->second, w_y);
363 if (result_insert_a_ds.first->second == coeff_field_.additive_identity()) {
364 map_a_ds.erase(result_insert_a_ds.first);
376 void update_cohomology_groups(
Simplex_handle sigma,
int dim_sigma) {
378 std::map<Simplex_key, Arith_element> map_a_ds;
379 annotation_of_the_boundary(map_a_ds, sigma, dim_sigma);
381 if (map_a_ds.empty()) {
382 if (dim_sigma < dim_max_) {
383 create_cocycle(sigma, coeff_field_.multiplicative_identity(),
384 coeff_field_.characteristic());
389 for (
auto map_a_ds_ref : map_a_ds) {
390 a_ds.emplace_back(map_a_ds_ref.first, map_a_ds_ref.second);
395 for (
auto a_ds_rit = a_ds.rbegin();
396 (a_ds_rit != a_ds.rend())
397 && (prod != coeff_field_.multiplicative_identity()); ++a_ds_rit) {
398 std::tie(inv_x, charac) = coeff_field_.inverse(a_ds_rit->second, prod);
400 if (inv_x != coeff_field_.additive_identity()) {
401 destroy_cocycle(sigma, a_ds, a_ds_rit->first, inv_x, charac);
405 if (prod != coeff_field_.multiplicative_identity()
406 && dim_sigma < dim_max_) {
407 create_cocycle(sigma, coeff_field_.multiplicative_identity(prod), prod);
423 Column * new_col = column_pool_.construct(key);
424 Cell * new_cell = cell_pool_.construct(key, x, new_col);
425 new_col->col_.push_back(*new_cell);
429 cam_.insert(cam_.end(), *new_col);
431 Hcell * new_hcell =
new Hcell;
432 new_hcell->push_back(*new_cell);
433 transverse_idx_[key] = cocycle(charac, new_hcell);
434 ds_repr_[key] = new_col;
449 if (interval_length_policy(cpx_->simplex(death_key), sigma)) {
450 persistent_pairs_.emplace_back(cpx_->simplex(death_key)
455 auto death_key_row = transverse_idx_.find(death_key);
456 std::pair<typename Cam::iterator, bool> result_insert_cam;
458 auto row_cell_it = death_key_row->second.row_->begin();
460 while (row_cell_it != death_key_row->second.row_->end()) {
462 Arith_element w = coeff_field_.times_minus(inv_x, row_cell_it->coefficient_);
464 if (w != coeff_field_.additive_identity()) {
465 Column * curr_col = row_cell_it->self_col_;
468 for (
auto& col_cell : curr_col->col_) {
469 col_cell.base_hook_cam_h::unlink();
473 cam_.erase(cam_.iterator_to(*curr_col));
475 plus_equal_column(*curr_col, a_ds, w);
477 if (curr_col->col_.empty()) {
478 ds_repr_[curr_col->class_key_] = NULL;
479 column_pool_.destroy(curr_col);
482 result_insert_cam = cam_.insert(*curr_col);
483 if (result_insert_cam.second) {
484 for (
auto& col_cell : curr_col->col_) {
486 transverse_idx_[col_cell.key_].row_->push_front(col_cell);
490 dsets_.link(curr_col->class_key_,
491 result_insert_cam.first->class_key_);
493 Simplex_key key_tmp = dsets_.find_set(curr_col->class_key_);
494 ds_repr_[key_tmp] = &(*(result_insert_cam.first));
495 result_insert_cam.first->class_key_ = key_tmp;
497 curr_col->col_.clear_and_dispose([&](Cell*p){cell_pool_.destroy(p);});
498 column_pool_.destroy(curr_col);
507 if (charac == coeff_field_.characteristic()) {
508 cpx_->assign_key(sigma, cpx_->null_key());
510 if (death_key_row->second.characteristics_ == charac) {
511 delete death_key_row->second.row_;
512 transverse_idx_.erase(death_key_row);
514 death_key_row->second.characteristics_ /= charac;
521 void plus_equal_column(Column & target, A_ds_type
const& other
523 auto target_it = target.col_.begin();
524 auto other_it = other.begin();
525 while (target_it != target.col_.end() && other_it != other.end()) {
526 if (target_it->key_ < other_it->first) {
529 if (target_it->key_ > other_it->first) {
530 Cell * cell_tmp = cell_pool_.construct(Cell(other_it->first
531 , coeff_field_.additive_identity(), &target));
533 cell_tmp->coefficient_ = coeff_field_.plus_times_equal(cell_tmp->coefficient_, other_it->second, w);
535 target.col_.insert(target_it, *cell_tmp);
540 target_it->coefficient_ = coeff_field_.plus_times_equal(target_it->coefficient_, other_it->second, w);
541 if (target_it->coefficient_ == coeff_field_.additive_identity()) {
542 auto tmp_it = target_it;
545 Cell * tmp_cell_ptr = &(*tmp_it);
546 target.col_.erase(tmp_it);
548 cell_pool_.destroy(tmp_cell_ptr);
556 while (other_it != other.end()) {
557 Cell * cell_tmp = cell_pool_.construct(Cell(other_it->first, coeff_field_.additive_identity(), &target));
558 cell_tmp->coefficient_ = coeff_field_.plus_times_equal(cell_tmp->coefficient_, other_it->second, w);
559 target.col_.insert(target.col_.end(), *cell_tmp);
568 struct cmp_intervals_by_length {
569 explicit cmp_intervals_by_length(FilteredComplex * sc)
576 FilteredComplex * sc_;
591 cmp_intervals_by_length cmp(cpx_);
592 std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp);
593 for (
auto pair : persistent_pairs_) {
594 ostream << get<2>(pair) <<
" " << cpx_->dimension(get<0>(pair)) <<
" "
595 << cpx_->filtration(get<0>(pair)) <<
" "
596 << cpx_->filtration(get<1>(pair)) <<
" " << std::endl;
600 void write_output_diagram(std::string diagram_name) {
601 std::ofstream diagram_out(diagram_name.c_str());
602 diagram_out.exceptions(diagram_out.failbit);
603 cmp_intervals_by_length cmp(cpx_);
604 std::sort(std::begin(persistent_pairs_), std::end(persistent_pairs_), cmp);
605 for (
auto pair : persistent_pairs_) {
606 diagram_out << cpx_->
dimension(get<0>(pair)) <<
" "
608 << cpx_->
filtration(get<1>(pair)) << std::endl;
620 for (
auto pair : persistent_pairs_) {
622 if (cpx_->null_simplex() == get<1>(pair)) {
638 for (
auto pair : persistent_pairs_) {
640 if (cpx_->null_simplex() == get<1>(pair)) {
641 if (cpx_->dimension(get<0>(pair)) == dimension) {
659 for (
auto pair : persistent_pairs_) {
663 if (cpx_->filtration(get<0>(pair)) <= from &&
664 (get<1>(pair) == cpx_->null_simplex() || cpx_->filtration(get<1>(pair)) > to)) {
681 for (
auto pair : persistent_pairs_) {
685 if (cpx_->filtration(get<0>(pair)) <= from &&
686 (get<1>(pair) == cpx_->null_simplex() || cpx_->filtration(get<1>(pair)) > to)) {
687 if (cpx_->dimension(get<0>(pair)) == dimension) {
700 return persistent_pairs_;
707 std::vector< std::pair< Filtration_value , Filtration_value > >
709 std::vector< std::pair< Filtration_value , Filtration_value > > result;
711 for (
auto && pair : persistent_pairs_) {
712 if (cpx_->dimension(get<0>(pair)) == dimension) {
713 result.emplace_back(cpx_->filtration(get<0>(pair)), cpx_->filtration(get<1>(pair)));
730 characteristics_(characteristics) {
738 FilteredComplex * cpx_;
740 CoefficientField coeff_field_;
741 size_t num_simplices_;
747 std::vector<int> ds_rank_;
748 std::vector<Simplex_key> ds_parent_;
749 std::vector<Column *> ds_repr_;
750 boost::disjoint_sets<int *, Simplex_key *> dsets_;
753#if BOOST_VERSION >= 108100
757 boost::unordered_flat_map<Simplex_key, Simplex_key> zero_cocycles_;
759 boost::unordered_flat_map<Simplex_key, cocycle> transverse_idx_;
761 boost::unordered_map<Simplex_key, Simplex_key> zero_cocycles_;
762 boost::unordered_map<Simplex_key, cocycle> transverse_idx_;
765 std::vector<Persistent_interval> persistent_pairs_;
766 length_interval interval_length_policy;
768 Simple_object_pool<Column> column_pool_;
769 Simple_object_pool<Cell> cell_pool_;