Loading...
Searching...
No Matches
boundary_matrix.h
Go to the documentation of this file.
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): Hannah Schreiber
4 *
5 * Copyright (C) 2022-24 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
17#ifndef PM_BOUNDARY_MATRIX_H
18#define PM_BOUNDARY_MATRIX_H
19
20#include <cassert>
21#include <iostream> //print() only
22#include <vector>
23#include <utility> //std::swap, std::move & std::exchange
24
25namespace Gudhi {
26namespace persistence_matrix {
27
28// TODO: factorize/inheritate/compose with @ref basematrix "base matrix"?
39template <class Master_matrix>
40class Boundary_matrix : public Master_matrix::Matrix_dimension_option,
41 public Master_matrix::template Base_swap_option<Boundary_matrix<Master_matrix> >,
42 public Master_matrix::Base_pairing_option,
43 public Master_matrix::Matrix_row_access_option
44{
45 public:
46 using index = typename Master_matrix::index;
47 using id_index = typename Master_matrix::id_index;
48 using dimension_type = typename Master_matrix::dimension_type;
52 using Field_operators = typename Master_matrix::Field_operators;
53 using Field_element_type = typename Master_matrix::element_type;
54 using Column_type = typename Master_matrix::Column_type;
55 using boundary_type = typename Master_matrix::boundary_type;
56 using Row_type = typename Master_matrix::Row_type;
58 using Cell_constructor = typename Master_matrix::Cell_constructor;
59 using Column_settings = typename Master_matrix::Column_settings;
68 Boundary_matrix(Column_settings* colSettings);
90 template <class Boundary_type = boundary_type>
91 Boundary_matrix(const std::vector<Boundary_type>& orderedBoundaries,
92 Column_settings* colSettings);
100 Boundary_matrix(unsigned int numberOfColumns, Column_settings* colSettings);
110 Boundary_matrix(const Boundary_matrix& matrixToCopy,
111 Column_settings* colSettings = nullptr);
117 Boundary_matrix(Boundary_matrix&& other) noexcept;
118
141 template <class Boundary_type = boundary_type>
142 index insert_boundary(const Boundary_type& boundary, dimension_type dim = -1);
160 template <class Boundary_type = boundary_type>
161 index insert_boundary(id_index faceIndex, const Boundary_type& boundary, dimension_type dim = -1);
173 Column_type& get_column(index columnIndex);
186 Row_type& get_row(index rowIndex);
209 void erase_empty_row(index rowIndex);
210
217
224 dimension_type get_column_dimension(index columnIndex) const;
225
236 void add_to(index sourceColumnIndex, index targetColumnIndex);
249 void multiply_target_and_add_to(index sourceColumnIndex,
250 const Field_element_type& coefficient,
251 index targetColumnIndex);
264 void multiply_source_and_add_to(const Field_element_type& coefficient,
265 index sourceColumnIndex,
266 index targetColumnIndex);
267
277 void zero_cell(index columnIndex, index rowIndex);
286 void zero_column(index columnIndex);
295 bool is_zero_cell(index columnIndex, index rowIndex) const;
303 bool is_zero_column(index columnIndex);
304
311 index get_pivot(index columnIndex);
312
319 void reset(Column_settings* colSettings) {
320 matrix_.clear();
321 nextInsertIndex_ = 0;
322 colSettings_ = colSettings;
323 }
324
332 friend void swap(Boundary_matrix& matrix1, Boundary_matrix& matrix2) {
333 swap(static_cast<typename Master_matrix::Matrix_dimension_option&>(matrix1),
334 static_cast<typename Master_matrix::Matrix_dimension_option&>(matrix2));
335 swap(static_cast<typename Master_matrix::template Base_swap_option<Boundary_matrix<Master_matrix> >&>(matrix1),
336 static_cast<typename Master_matrix::template Base_swap_option<Boundary_matrix<Master_matrix> >&>(matrix2));
337 swap(static_cast<typename Master_matrix::Base_pairing_option&>(matrix1),
338 static_cast<typename Master_matrix::Base_pairing_option&>(matrix2));
339 matrix1.matrix_.swap(matrix2.matrix_);
340 std::swap(matrix1.nextInsertIndex_, matrix2.nextInsertIndex_);
341 std::swap(matrix1.colSettings_, matrix2.colSettings_);
342
343 if constexpr (Master_matrix::Option_list::has_row_access) {
344 swap(static_cast<typename Master_matrix::Matrix_row_access_option&>(matrix1),
345 static_cast<typename Master_matrix::Matrix_row_access_option&>(matrix2));
346 }
347 }
348
349 void print(); // for debug
350
351 private:
352 using dim_opt = typename Master_matrix::Matrix_dimension_option;
353 using swap_opt = typename Master_matrix::template Base_swap_option<Boundary_matrix<Master_matrix> >;
354 using pair_opt = typename Master_matrix::Base_pairing_option;
355 using ra_opt = typename Master_matrix::Matrix_row_access_option;
356 using matrix_type = typename Master_matrix::column_container_type;
357
358 friend swap_opt;
359 friend pair_opt;
360
361 matrix_type matrix_;
362 index nextInsertIndex_;
363 Column_settings* colSettings_;
365 static constexpr bool activeDimOption =
366 Master_matrix::Option_list::has_matrix_maximal_dimension_access || Master_matrix::maxDimensionIsNeeded;
367 static constexpr bool activeSwapOption =
368 Master_matrix::Option_list::has_column_and_row_swaps || Master_matrix::Option_list::has_vine_update;
369 static constexpr bool activePairingOption = Master_matrix::Option_list::has_column_pairings &&
370 !Master_matrix::Option_list::has_vine_update &&
371 !Master_matrix::Option_list::can_retrieve_representative_cycles;
372
373 void _orderRowsIfNecessary();
374 const Column_type& _get_column(index columnIndex) const;
375 Column_type& _get_column(index columnIndex);
376 index _get_real_row_index(index rowIndex) const;
377 template <class Container_type>
378 void _container_insert(const Container_type& column, index pos, dimension_type dim);
379 void _container_insert(const Column_type& column, [[maybe_unused]] index pos = 0);
380};
381
382template <class Master_matrix>
384 : dim_opt(-1),
385 swap_opt(),
386 pair_opt(),
387 ra_opt(),
388 nextInsertIndex_(0),
389 colSettings_(colSettings)
390{}
391
392template <class Master_matrix>
393template <class Boundary_type>
394inline Boundary_matrix<Master_matrix>::Boundary_matrix(const std::vector<Boundary_type>& orderedBoundaries,
395 Column_settings* colSettings)
396 : dim_opt(-1),
397 swap_opt(orderedBoundaries.size()),
398 pair_opt(),
399 ra_opt(orderedBoundaries.size()),
400 nextInsertIndex_(orderedBoundaries.size()),
401 colSettings_(colSettings)
402{
403 matrix_.reserve(orderedBoundaries.size());
404
405 for (index i = 0; i < orderedBoundaries.size(); i++) {
406 _container_insert(orderedBoundaries[i], i, orderedBoundaries[i].size() == 0 ? 0 : orderedBoundaries[i].size() - 1);
407 }
408}
409
410template <class Master_matrix>
411inline Boundary_matrix<Master_matrix>::Boundary_matrix(unsigned int numberOfColumns,
412 Column_settings* colSettings)
413 : dim_opt(-1),
414 swap_opt(numberOfColumns),
415 pair_opt(),
416 ra_opt(numberOfColumns),
417 matrix_(!Master_matrix::Option_list::has_map_column_container && Master_matrix::Option_list::has_row_access
418 ? 0
419 : numberOfColumns),
420 nextInsertIndex_(0),
421 colSettings_(colSettings)
422{
423 if constexpr (!Master_matrix::Option_list::has_map_column_container && Master_matrix::Option_list::has_row_access)
424 matrix_.reserve(numberOfColumns);
425}
426
427template <class Master_matrix>
429 Column_settings* colSettings)
430 : dim_opt(static_cast<const dim_opt&>(matrixToCopy)),
431 swap_opt(static_cast<const swap_opt&>(matrixToCopy)),
432 pair_opt(static_cast<const pair_opt&>(matrixToCopy)),
433 ra_opt(static_cast<const ra_opt&>(matrixToCopy)),
434 nextInsertIndex_(matrixToCopy.nextInsertIndex_),
435 colSettings_(colSettings == nullptr ? matrixToCopy.colSettings_ : colSettings)
436{
437 matrix_.reserve(matrixToCopy.matrix_.size());
438 for (const auto& cont : matrixToCopy.matrix_){
439 if constexpr (Master_matrix::Option_list::has_map_column_container){
440 _container_insert(cont.second, cont.first);
441 } else {
442 _container_insert(cont);
443 }
444 }
445}
446
447template <class Master_matrix>
449 : dim_opt(std::move(static_cast<dim_opt&>(other))),
450 swap_opt(std::move(static_cast<swap_opt&>(other))),
451 pair_opt(std::move(static_cast<pair_opt&>(other))),
452 ra_opt(std::move(static_cast<ra_opt&>(other))),
453 matrix_(std::move(other.matrix_)),
454 nextInsertIndex_(std::exchange(other.nextInsertIndex_, 0)),
455 colSettings_(std::exchange(other.colSettings_, nullptr))
456{}
457
458template <class Master_matrix>
459template <class Boundary_type>
461 const Boundary_type& boundary, dimension_type dim)
462{
463 return insert_boundary(nextInsertIndex_, boundary, dim);
464}
465
466template <class Master_matrix>
467template <class Boundary_type>
469 id_index faceIndex, const Boundary_type& boundary, dimension_type dim)
470{
471 if (dim == -1) dim = boundary.size() == 0 ? 0 : boundary.size() - 1;
472
473 _orderRowsIfNecessary();
474
475 //updates container sizes
476 if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_removable_rows) {
477 id_index pivot;
478 if constexpr (Master_matrix::Option_list::is_z2) {
479 pivot = *std::prev(boundary.end());
480 } else {
481 pivot = std::prev(boundary.end())->first;
482 }
483 //row container
484 if (ra_opt::rows_->size() <= pivot) ra_opt::rows_->resize(pivot + 1);
485 }
486
487 //row swap map containers
488 if constexpr (Master_matrix::Option_list::has_map_column_container) {
489 if constexpr (activeSwapOption) {
490 swap_opt::indexToRow_.emplace(faceIndex, faceIndex);
491 swap_opt::rowToIndex_.emplace(faceIndex, faceIndex);
492 }
493 } else {
494 if constexpr (activeSwapOption) {
495 for (index i = swap_opt::indexToRow_.size(); i <= faceIndex; ++i) {
496 swap_opt::indexToRow_.push_back(i);
497 swap_opt::rowToIndex_.push_back(i);
498 }
499 }
500 }
501
502 _container_insert(boundary, nextInsertIndex_, dim);
503
504 return nextInsertIndex_++;
505}
506
507template <class Master_matrix>
509 index columnIndex)
510{
511 _orderRowsIfNecessary();
512
513 return _get_column(columnIndex);
514}
515
516template <class Master_matrix>
518{
519 static_assert(Master_matrix::Option_list::has_row_access, "'get_row' is not implemented for the chosen options.");
520
521 _orderRowsIfNecessary();
522
523 return ra_opt::get_row(rowIndex);
524}
525
526template <class Master_matrix>
528{
529 static_assert(Master_matrix::Option_list::has_removable_columns,
530 "'remove_last' is not implemented for the chosen options.");
531
532 if (nextInsertIndex_ == 0) return -1; // empty matrix
533 --nextInsertIndex_;
534
535 //updates dimension max
536 if constexpr (activeDimOption) {
537 dim_opt::update_down(matrix_.at(nextInsertIndex_).get_dimension());
538 }
539
540 //computes pivot and removes column from matrix_
541 id_index pivot;
542 if constexpr (Master_matrix::Option_list::has_map_column_container) {
543 auto it = matrix_.find(nextInsertIndex_);
544 pivot = it->second.get_pivot();
545 if constexpr (activeSwapOption) {
546 // if the removed column is positive, the pivot won't change value
547 if (swap_opt::rowSwapped_ && pivot != static_cast<id_index>(-1)) {
548 swap_opt::_orderRows();
549 pivot = it->second.get_pivot();
550 }
551 }
552 matrix_.erase(it);
553 } else {
554 pivot = matrix_[nextInsertIndex_].get_pivot();
555 if constexpr (activeSwapOption) {
556 // if the removed column is positive, the pivot won't change value
557 if (swap_opt::rowSwapped_ && pivot != static_cast<id_index>(-1)) {
558 swap_opt::_orderRows();
559 pivot = matrix_[nextInsertIndex_].get_pivot();
560 }
561 }
562 if constexpr (Master_matrix::Option_list::has_row_access) {
563 GUDHI_CHECK(nextInsertIndex_ == matrix_.size() - 1,
564 std::logic_error("Boundary_matrix::remove_last - Indexation problem."));
565 matrix_.pop_back();
566 } else {
567 matrix_[nextInsertIndex_].clear();
568 }
569 }
570
571 erase_empty_row(nextInsertIndex_); // maximal, so empty
572
573 //updates barcode
574 if constexpr (activePairingOption) {
575 pair_opt::_remove_last(nextInsertIndex_);
576 }
577
578 return pivot;
579}
580
581template <class Master_matrix>
583{
584 //computes real row index and erases it if necessary from the row swap map containers
585 id_index rowID = rowIndex;
586 if constexpr (activeSwapOption) {
587 if constexpr (Master_matrix::Option_list::has_map_column_container) {
588 auto it = swap_opt::indexToRow_.find(rowIndex);
589 rowID = it->second;
590 swap_opt::rowToIndex_.erase(rowID);
591 swap_opt::indexToRow_.erase(it);
592 } else {
593 rowID = swap_opt::indexToRow_[rowIndex];
594 }
595 }
596
597 if constexpr (Master_matrix::Option_list::has_row_access && Master_matrix::Option_list::has_removable_rows) {
598 ra_opt::erase_empty_row(rowID);
599 }
600}
601
602template <class Master_matrix>
604{
605 if constexpr (Master_matrix::Option_list::has_map_column_container) {
606 return matrix_.size();
607 } else {
608 return nextInsertIndex_; // matrix could have been resized much bigger while insert
609 }
610}
611
612template <class Master_matrix>
614 index columnIndex) const
615{
616 return _get_column(columnIndex).get_dimension();
617}
618
619template <class Master_matrix>
620inline void Boundary_matrix<Master_matrix>::add_to(index sourceColumnIndex, index targetColumnIndex)
621{
622 _get_column(targetColumnIndex) += _get_column(sourceColumnIndex);
623}
624
625template <class Master_matrix>
627 const Field_element_type& coefficient,
628 index targetColumnIndex)
629{
630 _get_column(targetColumnIndex).multiply_target_and_add(coefficient, _get_column(sourceColumnIndex));
631}
632
633template <class Master_matrix>
635 index sourceColumnIndex,
636 index targetColumnIndex)
637{
638 _get_column(targetColumnIndex).multiply_source_and_add(_get_column(sourceColumnIndex), coefficient);
639}
640
641template <class Master_matrix>
642inline void Boundary_matrix<Master_matrix>::zero_cell(index columnIndex, index rowIndex)
643{
644 _get_column(columnIndex).clear(_get_real_row_index(rowIndex));
645}
646
647template <class Master_matrix>
649{
650 _get_column(columnIndex).clear();
651}
652
653template <class Master_matrix>
654inline bool Boundary_matrix<Master_matrix>::is_zero_cell(index columnIndex, index rowIndex) const
655{
656 return !(_get_column(columnIndex).is_non_zero(_get_real_row_index(rowIndex)));
657}
658
659template <class Master_matrix>
661{
662 return _get_column(columnIndex).is_empty();
663}
664
665template <class Master_matrix>
667{
668 _orderRowsIfNecessary();
669
670 return _get_column(columnIndex).get_pivot();
671}
672
673template <class Master_matrix>
675{
676 dim_opt::operator=(other);
677 swap_opt::operator=(other);
678 pair_opt::operator=(other);
679 ra_opt::operator=(other);
680
681 matrix_.clear();
682 nextInsertIndex_ = other.nextInsertIndex_;
683 colSettings_ = other.colSettings_;
684
685 matrix_.reserve(other.matrix_.size());
686 for (const auto& cont : other.matrix_){
687 if constexpr (Master_matrix::Option_list::has_map_column_container){
688 _container_insert(cont.second, cont.first);
689 } else {
690 _container_insert(cont);
691 }
692 }
693
694 return *this;
695}
696
697template <class Master_matrix>
699{
700 if constexpr (activeSwapOption) {
701 if (swap_opt::rowSwapped_) swap_opt::_orderRows();
702 }
703 std::cout << "Boundary_matrix:\n";
704 for (index i = 0; i < nextInsertIndex_; ++i) {
705 Column_type& col = matrix_[i];
706 for (auto e : col.get_content(nextInsertIndex_)) {
707 if (e == 0u)
708 std::cout << "- ";
709 else
710 std::cout << e << " ";
711 }
712 std::cout << "\n";
713 }
714 std::cout << "\n";
715 if constexpr (Master_matrix::Option_list::has_row_access) {
716 std::cout << "Row Matrix:\n";
717 for (id_index i = 0; i < nextInsertIndex_; ++i) {
718 const auto& row = ra_opt::rows_[i];
719 for (const auto& cell : row) {
720 std::cout << cell.get_column_index() << " ";
721 }
722 std::cout << "(" << i << ")\n";
723 }
724 std::cout << "\n";
725 }
726}
727
728template <class Master_matrix>
729inline void Boundary_matrix<Master_matrix>::_orderRowsIfNecessary()
730{
731 if constexpr (activeSwapOption) {
732 if (swap_opt::rowSwapped_) swap_opt::_orderRows();
733 }
734}
735
736template <class Master_matrix>
737inline const typename Boundary_matrix<Master_matrix>::Column_type& Boundary_matrix<Master_matrix>::_get_column(
738 index columnIndex) const
739{
740 if constexpr (Master_matrix::Option_list::has_map_column_container) {
741 return matrix_.at(columnIndex);
742 } else {
743 return matrix_[columnIndex];
744 }
745}
746
747template <class Master_matrix>
748inline typename Boundary_matrix<Master_matrix>::Column_type& Boundary_matrix<Master_matrix>::_get_column(
749 index columnIndex)
750{
751 if constexpr (Master_matrix::Option_list::has_map_column_container) {
752 return matrix_.at(columnIndex);
753 } else {
754 return matrix_[columnIndex];
755 }
756}
757
758template <class Master_matrix>
759inline typename Boundary_matrix<Master_matrix>::index Boundary_matrix<Master_matrix>::_get_real_row_index(
760 index rowIndex) const
761{
762 if constexpr (Master_matrix::Option_list::has_column_and_row_swaps || Master_matrix::Option_list::has_vine_update) {
763 if constexpr (Master_matrix::Option_list::has_map_column_container) {
764 return swap_opt::indexToRow_.at(rowIndex);
765 } else {
766 return swap_opt::indexToRow_[rowIndex];
767 }
768 } else {
769 return rowIndex;
770 }
771}
772
773template <class Master_matrix>
774template <class Container_type>
775inline void Boundary_matrix<Master_matrix>::_container_insert(const Container_type& column,
776 index pos,
777 dimension_type dim)
778{
779 if constexpr (Master_matrix::Option_list::has_map_column_container) {
780 if constexpr (Master_matrix::Option_list::has_row_access) {
781 matrix_.try_emplace(pos, Column_type(pos, column, dim, ra_opt::rows_, colSettings_));
782 } else {
783 matrix_.try_emplace(pos, Column_type(column, dim, colSettings_));
784 }
785 } else {
786 if constexpr (Master_matrix::Option_list::has_row_access) {
787 matrix_.emplace_back(pos, column, dim, ra_opt::rows_, colSettings_);
788 } else {
789 if (matrix_.size() <= pos) {
790 matrix_.emplace_back(column, dim, colSettings_);
791 } else {
792 matrix_[pos] = Column_type(column, dim, colSettings_);
793 }
794 }
795 }
796 if constexpr (activeDimOption) {
797 dim_opt::update_up(dim);
798 }
799}
800
801template <class Master_matrix>
802inline void Boundary_matrix<Master_matrix>::_container_insert(const Column_type& column, [[maybe_unused]] index pos)
803{
804 if constexpr (Master_matrix::Option_list::has_map_column_container) {
805 if constexpr (Master_matrix::Option_list::has_row_access) {
806 matrix_.try_emplace(pos, Column_type(column, column.get_column_index(), ra_opt::rows_, colSettings_));
807 } else {
808 matrix_.try_emplace(pos, Column_type(column, colSettings_));
809 }
810 } else {
811 if constexpr (Master_matrix::Option_list::has_row_access) {
812 matrix_.emplace_back(column, column.get_column_index(), ra_opt::rows_, colSettings_);
813 } else {
814 matrix_.emplace_back(column, colSettings_);
815 }
816 }
817}
818
819} // namespace persistence_matrix
820} // namespace Gudhi
821
822#endif // PM_BOUNDARY_MATRIX_H
Matrix structure to store the ordered boundary matrix of a filtered complex in order to compute its ...
Definition boundary_matrix.h:44
typename Master_matrix::Cell_constructor Cell_constructor
Definition boundary_matrix.h:58
dimension_type get_column_dimension(index columnIndex) const
Returns the dimension of the given column.
Definition boundary_matrix.h:613
void multiply_source_and_add_to(const Field_element_type &coefficient, index sourceColumnIndex, index targetColumnIndex)
Multiplies the source column with the coefficiant before adding it to the target column....
Definition boundary_matrix.h:634
typename Master_matrix::Column_settings Column_settings
Definition boundary_matrix.h:60
bool is_zero_cell(index columnIndex, index rowIndex) const
Indicates if the cell at given coordinates has value zero.
Definition boundary_matrix.h:654
void zero_column(index columnIndex)
Zeroes the column at the given index.
Definition boundary_matrix.h:648
void multiply_target_and_add_to(index sourceColumnIndex, const Field_element_type &coefficient, index targetColumnIndex)
Multiplies the target column with the coefficiant and then adds the source column to it....
Definition boundary_matrix.h:626
void erase_empty_row(index rowIndex)
If PersistenceMatrixOptions::has_row_access and PersistenceMatrixOptions::has_removable_rows are true...
Definition boundary_matrix.h:582
bool is_zero_column(index columnIndex)
Indicates if the column at given index has value zero.
Definition boundary_matrix.h:660
friend void swap(Boundary_matrix &matrix1, Boundary_matrix &matrix2)
Swap operator.
Definition boundary_matrix.h:332
typename Master_matrix::Column_type Column_type
Definition boundary_matrix.h:54
Row_type & get_row(index rowIndex)
Only available if PersistenceMatrixOptions::has_row_access is true. Returns the row at the given row ...
Definition boundary_matrix.h:517
void add_to(index sourceColumnIndex, index targetColumnIndex)
Adds column at sourceColumnIndex onto the column at targetColumnIndex in the matrix.
Definition boundary_matrix.h:620
typename Master_matrix::element_type Field_element_type
Definition boundary_matrix.h:53
index get_pivot(index columnIndex)
Returns the pivot of the given column.
Definition boundary_matrix.h:666
typename Master_matrix::dimension_type dimension_type
Definition boundary_matrix.h:48
void reset(Column_settings *colSettings)
Resets the matrix to an empty matrix.
Definition boundary_matrix.h:319
typename Master_matrix::boundary_type boundary_type
Definition boundary_matrix.h:55
typename Master_matrix::index index
Definition boundary_matrix.h:46
void zero_cell(index columnIndex, index rowIndex)
Zeroes the cell at the given coordinates.
Definition boundary_matrix.h:642
typename Master_matrix::id_index id_index
Definition boundary_matrix.h:47
index insert_boundary(const Boundary_type &boundary, dimension_type dim=-1)
Inserts at the end of the matrix a new ordered column corresponding to the given boundary....
Definition boundary_matrix.h:460
Column_type & get_column(index columnIndex)
Returns the column at the given MatIdx index. The type of the column depends on the choosen options,...
Definition boundary_matrix.h:508
Boundary_matrix(Column_settings *colSettings)
Constructs an empty matrix.
Definition boundary_matrix.h:383
typename Master_matrix::Row_type Row_type
Definition boundary_matrix.h:57
index get_number_of_columns() const
Returns the current number of columns in the matrix.
Definition boundary_matrix.h:603
typename Master_matrix::Field_operators Field_operators
Field operators class. Necessary only if PersistenceMatrixOptions::is_z2 is false.
Definition boundary_matrix.h:52
Boundary_matrix & operator=(const Boundary_matrix &other)
Assign operator.
Definition boundary_matrix.h:674
index remove_last()
Only available if PersistenceMatrixOptions::has_removable_columns is true. Removes the last face in t...
Definition boundary_matrix.h:527
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14