summaryrefslogtreecommitdiff
path: root/src/Hasse_complex/include/gudhi/Hasse_complex.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Hasse_complex/include/gudhi/Hasse_complex.h')
-rw-r--r--src/Hasse_complex/include/gudhi/Hasse_complex.h236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/Hasse_complex/include/gudhi/Hasse_complex.h b/src/Hasse_complex/include/gudhi/Hasse_complex.h
new file mode 100644
index 00000000..209fd0b9
--- /dev/null
+++ b/src/Hasse_complex/include/gudhi/Hasse_complex.h
@@ -0,0 +1,236 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clément Maria
+ *
+ * Copyright (C) 2014 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef HASSE_COMPLEX_H_
+#define HASSE_COMPLEX_H_
+
+#include <gudhi/allocator.h>
+
+#include <boost/iterator/counting_iterator.hpp>
+
+#include <algorithm>
+#include <utility> // for pair
+#include <vector>
+#include <limits> // for infinity value
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/parallel_for.h>
+#endif
+
+namespace Gudhi {
+
+template < class HasseCpx >
+struct Hasse_simplex {
+ // Complex_ds must verify that cpx->key(sh) is the order of sh in the filtration
+
+ template< class Complex_ds >
+ Hasse_simplex(Complex_ds & cpx
+ , typename Complex_ds::Simplex_handle sh)
+ : filtration_(cpx.filtration(sh))
+ , boundary_() {
+ boundary_.reserve(cpx.dimension(sh) + 1);
+ for (auto b_sh : cpx.boundary_simplex_range(sh)) {
+ boundary_.push_back(cpx.key(b_sh));
+ }
+ }
+
+ Hasse_simplex(typename HasseCpx::Simplex_key key
+ , typename HasseCpx::Filtration_value fil
+ , std::vector<typename HasseCpx::Simplex_handle> const& boundary)
+ : key_(key)
+ , filtration_(fil)
+ , boundary_(boundary) { }
+
+ typename HasseCpx::Simplex_key key_;
+ typename HasseCpx::Filtration_value filtration_;
+ std::vector<typename HasseCpx::Simplex_handle> boundary_;
+};
+
+/** \private
+ * \brief Data structure representing a Hasse diagram, i.e.
+ * a complex where all codimension 1 incidence
+ * relations are explicitly encoded.
+ *
+ * \implements FilteredComplex
+ * \ingroup simplex_tree
+ */
+template < typename FiltrationValue = double
+, typename SimplexKey = int
+, typename VertexHandle = int
+>
+class Hasse_complex {
+ public:
+ typedef Hasse_simplex<Hasse_complex> Hasse_simp;
+ typedef FiltrationValue Filtration_value;
+ typedef SimplexKey Simplex_key;
+ typedef int Simplex_handle; // index in vector complex_
+
+ typedef boost::counting_iterator< Simplex_handle > Filtration_simplex_iterator;
+ typedef boost::iterator_range<Filtration_simplex_iterator> Filtration_simplex_range;
+
+ typedef typename std::vector< Simplex_handle >::iterator Boundary_simplex_iterator;
+ typedef boost::iterator_range<Boundary_simplex_iterator> Boundary_simplex_range;
+
+ typedef typename std::vector< Simplex_handle >::iterator Skeleton_simplex_iterator;
+ typedef boost::iterator_range< Skeleton_simplex_iterator > Skeleton_simplex_range;
+
+ /* only dimension 0 skeleton_simplex_range(...) */
+ Skeleton_simplex_range skeleton_simplex_range(int dim = 0) {
+ if (dim != 0) {
+ std::cerr << "Dimension must be 0 \n";
+ }
+ return Skeleton_simplex_range(vertices_.begin(), vertices_.end());
+ }
+
+ template < class Complex_ds >
+ Hasse_complex(Complex_ds & cpx)
+ : complex_(cpx.num_simplices())
+ , vertices_()
+ , num_vertices_()
+ , dim_max_(cpx.dimension()) {
+ int size = complex_.size();
+#ifdef GUDHI_USE_TBB
+ tbb::parallel_for(0, size, [&](int idx){new (&complex_[idx]) Hasse_simp(cpx, cpx.simplex(idx));});
+ for (int idx=0; idx < size; ++idx)
+ if (complex_[idx].boundary_.empty())
+ vertices_.push_back(idx);
+#else
+ for (int idx=0; idx < size; ++idx) {
+ new (&complex_[idx]) Hasse_simp(cpx, cpx.simplex(idx));
+ if (complex_[idx].boundary_.empty())
+ vertices_.push_back(idx);
+ }
+#endif
+ }
+
+ Hasse_complex()
+ : complex_()
+ , vertices_()
+ , num_vertices_(0)
+ , dim_max_(-1) { }
+
+ size_t num_simplices() {
+ return complex_.size();
+ }
+
+ Filtration_simplex_range filtration_simplex_range() {
+ return Filtration_simplex_range(Filtration_simplex_iterator(0)
+ , Filtration_simplex_iterator(complex_.size()));
+ }
+
+ Simplex_key key(Simplex_handle sh) {
+ return complex_[sh].key_;
+ }
+
+ Simplex_key null_key() {
+ return -1;
+ }
+
+ Simplex_handle simplex(Simplex_key key) {
+ if (key == null_key()) return null_simplex();
+ return key;
+ }
+
+ Simplex_handle null_simplex() {
+ return -1;
+ }
+
+ Filtration_value filtration(Simplex_handle sh) {
+ if (sh == null_simplex()) {
+ return std::numeric_limits<Filtration_value>::infinity();
+ }
+ return complex_[sh].filtration_;
+ }
+
+ int dimension(Simplex_handle sh) {
+ if (complex_[sh].boundary_.empty()) return 0;
+ return complex_[sh].boundary_.size() - 1;
+ }
+
+ int dimension() {
+ return dim_max_;
+ }
+
+ std::pair<Simplex_handle, Simplex_handle> endpoints(Simplex_handle sh) {
+ return std::pair<Simplex_handle, Simplex_handle>(complex_[sh].boundary_[0]
+ , complex_[sh].boundary_[1]);
+ }
+
+ void assign_key(Simplex_handle sh, Simplex_key key) {
+ complex_[sh].key_ = key;
+ }
+
+ Boundary_simplex_range boundary_simplex_range(Simplex_handle sh) {
+ return Boundary_simplex_range(complex_[sh].boundary_.begin()
+ , complex_[sh].boundary_.end());
+ }
+
+ void display_simplex(Simplex_handle sh) {
+ std::cout << dimension(sh) << " ";
+ for (auto sh_b : boundary_simplex_range(sh)) std::cout << sh_b << " ";
+ std::cout << " " << filtration(sh) << " key=" << key(sh);
+ }
+
+ void initialize_filtration() {
+ // Setting the keys is done by pcoh, Simplex_tree doesn't do it either.
+#if 0
+ Simplex_key key = 0;
+ for (auto & h_simp : complex_)
+ h_simp.key_ = key++;
+#endif
+ }
+
+ std::vector< Hasse_simp, Gudhi::no_init_allocator<Hasse_simp> > complex_;
+ std::vector<Simplex_handle> vertices_;
+ size_t num_vertices_;
+ int dim_max_;
+};
+
+template< typename T1, typename T2, typename T3 >
+std::istream& operator>>(std::istream & is
+ , Hasse_complex< T1, T2, T3 > & hcpx) {
+ assert(hcpx.num_simplices() == 0);
+
+ size_t num_simp;
+ is >> num_simp;
+ hcpx.complex_.reserve(num_simp);
+
+ std::vector< typename Hasse_complex<T1, T2, T3>::Simplex_key > boundary;
+ typename Hasse_complex<T1, T2, T3>::Filtration_value fil;
+ typename Hasse_complex<T1, T2, T3>::Filtration_value max_fil = 0;
+ int max_dim = -1;
+ int key = 0;
+ // read all simplices in the file as a list of vertices
+ while (read_hasse_simplex(is, boundary, fil)) {
+ // insert every simplex in the simplex tree
+ hcpx.complex_.emplace_back(key, fil, boundary);
+
+ if (max_dim < hcpx.dimension(key)) {
+ max_dim = hcpx.dimension(key);
+ }
+ if (hcpx.dimension(key) == 0) {
+ hcpx.vertices_.push_back(key);
+ }
+ if (max_fil < fil) {
+ max_fil = fil;
+ }
+
+ ++key;
+ boundary.clear();
+ }
+
+ hcpx.dim_max_ = max_dim;
+
+ return is;
+}
+
+} // namespace Gudhi
+
+#endif // HASSE_COMPLEX_H_