summaryrefslogtreecommitdiff
path: root/src/Witness_complex/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/Witness_complex/include')
-rw-r--r--src/Witness_complex/include/gudhi/Active_witness/Active_witness.h67
-rw-r--r--src/Witness_complex/include/gudhi/Active_witness/Active_witness_iterator.h108
-rw-r--r--src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h92
-rw-r--r--src/Witness_complex/include/gudhi/Euclidean_strong_witness_complex.h104
-rw-r--r--src/Witness_complex/include/gudhi/Euclidean_witness_complex.h106
-rw-r--r--src/Witness_complex/include/gudhi/Strong_witness_complex.h186
-rw-r--r--src/Witness_complex/include/gudhi/Witness_complex.h333
-rw-r--r--src/Witness_complex/include/gudhi/Witness_complex/all_faces_in.h55
8 files changed, 764 insertions, 287 deletions
diff --git a/src/Witness_complex/include/gudhi/Active_witness/Active_witness.h b/src/Witness_complex/include/gudhi/Active_witness/Active_witness.h
new file mode 100644
index 00000000..d41a6811
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Active_witness/Active_witness.h
@@ -0,0 +1,67 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2016 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACTIVE_WITNESS_ACTIVE_WITNESS_H_
+#define ACTIVE_WITNESS_ACTIVE_WITNESS_H_
+
+#include <gudhi/Active_witness/Active_witness_iterator.h>
+#include <list>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+ /* \class Active_witness
+ * \brief Class representing a list of nearest neighbors to a given witness.
+ * \details Every element is a pair of a landmark identifier and the squared distance to it.
+ */
+template< typename Id_distance_pair,
+ typename INS_range >
+class Active_witness {
+ public:
+ typedef Active_witness<Id_distance_pair, INS_range> ActiveWitness;
+ typedef typename INS_range::iterator INS_iterator;
+ typedef Active_witness_iterator< ActiveWitness, Id_distance_pair, INS_iterator > iterator;
+ typedef typename std::list<Id_distance_pair> Table;
+
+ Table nearest_landmark_table_;
+ INS_range search_range_;
+ INS_iterator iterator_next_;
+ INS_iterator iterator_end_;
+
+ Active_witness(const INS_range& search_range)
+ : search_range_(search_range), iterator_next_(search_range_.begin()), iterator_end_(search_range_.end()) {
+ }
+
+ iterator begin() {
+ return iterator(this, nearest_landmark_table_.begin());
+ }
+
+ iterator end() {
+ return iterator(this);
+ }
+};
+
+} // namespace witness_complex
+} // namespace Gudhi
+
+#endif // ACTIVE_WITNESS_ACTIVE_WITNESS_H_
diff --git a/src/Witness_complex/include/gudhi/Active_witness/Active_witness_iterator.h b/src/Witness_complex/include/gudhi/Active_witness/Active_witness_iterator.h
new file mode 100644
index 00000000..0a05173a
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Active_witness/Active_witness_iterator.h
@@ -0,0 +1,108 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2016 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_
+#define ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_
+
+#include <boost/iterator/iterator_facade.hpp>
+#include <list>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/* \brief Iterator in the nearest landmark list.
+ * \details After the iterator reaches the end of the list,
+ * the list is augmented by a (nearest landmark, distance) pair if possible.
+ * If all the landmarks are present in the list, iterator returns the specific end value
+ * of the corresponding 'Active_witness' object.
+ */
+template< typename Active_witness,
+ typename Id_distance_pair,
+ typename INS_iterator >
+class Active_witness_iterator
+ : public boost::iterator_facade< Active_witness_iterator <Active_witness, Id_distance_pair, INS_iterator>,
+ Id_distance_pair const,
+ boost::forward_traversal_tag,
+ Id_distance_pair const> {
+ friend class boost::iterator_core_access;
+
+ typedef typename std::list<Id_distance_pair>::iterator Pair_iterator;
+ typedef typename Gudhi::witness_complex::Active_witness_iterator<Active_witness,
+ Id_distance_pair,
+ INS_iterator> Iterator;
+
+ Active_witness *aw_;
+ Pair_iterator lh_; // landmark handle
+ bool is_end_; // true only if the pointer is end and there are no more neighbors to add
+
+ public:
+ Active_witness_iterator(Active_witness* aw)
+ : aw_(aw), lh_(aw_->nearest_landmark_table_.end()), is_end_(true) {
+ }
+
+ Active_witness_iterator(Active_witness* aw, const Pair_iterator& lh)
+ : aw_(aw), lh_(lh) {
+ is_end_ = false;
+ if (lh_ == aw_->nearest_landmark_table_.end()) {
+ if (aw_->iterator_next_ == aw_->iterator_end_) {
+ is_end_ = true;
+ } else {
+ aw_->nearest_landmark_table_.push_back(*aw_->iterator_next_);
+ lh_ = --aw_->nearest_landmark_table_.end();
+ ++(aw_->iterator_next_);
+ }
+ }
+ }
+
+ private :
+ Id_distance_pair& dereference() const {
+ return *lh_;
+ }
+
+ bool equal(const Iterator& other) const {
+ return (is_end_ == other.is_end_) || (lh_ == other.lh_);
+ }
+
+ void increment() {
+ // the neighbor search can't be at the end iterator of a list
+ GUDHI_CHECK(!is_end_ && lh_ != aw_->nearest_landmark_table_.end(),
+ std::logic_error("Wrong active witness increment."));
+ // if the id of the current landmark is the same as the last one
+
+ lh_++;
+ if (lh_ == aw_->nearest_landmark_table_.end()) {
+ if (aw_->iterator_next_ == aw_->iterator_end_) {
+ is_end_ = true;
+ } else {
+ aw_->nearest_landmark_table_.push_back(*aw_->iterator_next_);
+ lh_ = std::prev(aw_->nearest_landmark_table_.end());
+ ++(aw_->iterator_next_);
+ }
+ }
+ }
+};
+
+} // namespace witness_complex
+} // namespace Gudhi
+
+#endif // ACTIVE_WITNESS_ACTIVE_WITNESS_ITERATOR_H_
diff --git a/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h b/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h
deleted file mode 100644
index a8cdd096..00000000
--- a/src/Witness_complex/include/gudhi/Construct_closest_landmark_table.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* This file is part of the Gudhi Library. The Gudhi library
- * (Geometric Understanding in Higher Dimensions) is a generic C++
- * library for computational topology.
- *
- * Author(s): Siargey Kachanovich
- *
- * Copyright (C) 2015 INRIA
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_
-#define CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_
-
-#include <boost/range/size.hpp>
-
-#include <queue> // for priority_queue<>
-#include <utility> // for pair<>
-#include <iterator>
-#include <vector>
-#include <set>
-
-namespace Gudhi {
-
-namespace witness_complex {
-
- /**
- * \ingroup witness_complex
- * \brief Construct the closest landmark tables for all witnesses.
- * \details Output a table 'knn', each line of which represents a witness and
- * consists of landmarks sorted by
- * euclidean distance from the corresponding witness.
- *
- * The type WitnessContainer is a random access range and
- * the type LandmarkContainer is a range.
- * The type KNearestNeighbors can be seen as
- * Witness_range<Closest_landmark_range<Vertex_handle>>, where
- * Witness_range and Closest_landmark_range are random access ranges and
- * Vertex_handle is the label type of a vertex in a simplicial complex.
- * Closest_landmark_range needs to have push_back operation.
- */
-
- template <typename FiltrationValue,
- typename WitnessContainer,
- typename LandmarkContainer,
- typename KNearestNeighbours>
- void construct_closest_landmark_table(WitnessContainer const &points,
- LandmarkContainer const &landmarks,
- KNearestNeighbours &knn) {
- int nbP = boost::size(points);
- assert(nbP >= boost::size(landmarks));
-
- int dim = boost::size(*std::begin(points));
- typedef std::pair<double, int> dist_i;
- typedef bool (*comp)(dist_i, dist_i);
- knn = KNearestNeighbours(nbP);
- for (int points_i = 0; points_i < nbP; points_i++) {
- std::priority_queue<dist_i, std::vector<dist_i>, comp> l_heap([](dist_i j1, dist_i j2) {
- return j1.first > j2.first;
- });
- typename LandmarkContainer::const_iterator landmarks_it;
- int landmarks_i = 0;
- for (landmarks_it = landmarks.begin(), landmarks_i = 0; landmarks_it != landmarks.end();
- ++landmarks_it, landmarks_i++) {
- dist_i dist = std::make_pair(Euclidean_distance()(points[points_i], *landmarks_it),
- landmarks_i);
- l_heap.push(dist);
- }
- for (int i = 0; i < dim + 1; i++) {
- dist_i dist = l_heap.top();
- knn[points_i].push_back(dist.second);
- l_heap.pop();
- }
- }
- }
-
-} // namespace witness_complex
-
-} // namespace Gudhi
-
-#endif // CONSTRUCT_CLOSEST_LANDMARK_TABLE_H_
diff --git a/src/Witness_complex/include/gudhi/Euclidean_strong_witness_complex.h b/src/Witness_complex/include/gudhi/Euclidean_strong_witness_complex.h
new file mode 100644
index 00000000..fb669ef8
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Euclidean_strong_witness_complex.h
@@ -0,0 +1,104 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_
+#define EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_
+
+#include <gudhi/Strong_witness_complex.h>
+#include <gudhi/Active_witness/Active_witness.h>
+#include <gudhi/Kd_tree_search.h>
+
+#include <utility>
+#include <vector>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/**
+ * \private
+ * \class Euclidean_strong_witness_complex
+ * \brief Constructs strong witness complex for given sets of witnesses and landmarks in Euclidean space.
+ * \ingroup witness_complex
+ *
+ * \tparam Kernel_ requires a <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class.
+ */
+template< class Kernel_ >
+class Euclidean_strong_witness_complex
+ : public Strong_witness_complex<std::vector<typename Gudhi::spatial_searching::Kd_tree_search<Kernel_,
+ std::vector<typename Kernel_::Point_d>>::INS_range>> {
+ private:
+ typedef Kernel_ K;
+ typedef typename K::Point_d Point_d;
+ typedef std::vector<Point_d> Point_range;
+ typedef Gudhi::spatial_searching::Kd_tree_search<Kernel_, Point_range> Kd_tree;
+ typedef typename Kd_tree::INS_range Nearest_landmark_range;
+ typedef typename std::vector<Nearest_landmark_range> Nearest_landmark_table;
+
+ typedef typename Nearest_landmark_range::Point_with_transformed_distance Id_distance_pair;
+ typedef typename Id_distance_pair::first_type Landmark_id;
+ typedef Landmark_id Vertex_handle;
+
+ private:
+ Point_range landmarks_;
+ Kd_tree landmark_tree_;
+ using Strong_witness_complex<Nearest_landmark_table>::nearest_landmark_table_;
+
+ public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /* @name Constructor
+ */
+
+ //@{
+
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records landmarks from the range 'landmarks' into a
+ * table internally, as well as witnesses from the range 'witnesses'.
+ * Both ranges should have value_type Kernel_::Point_d.
+ */
+ template< typename LandmarkRange,
+ typename WitnessRange >
+ Euclidean_strong_witness_complex(const LandmarkRange & landmarks,
+ const WitnessRange & witnesses)
+ : landmarks_(std::begin(landmarks), std::end(landmarks)), landmark_tree_(landmarks_) {
+ nearest_landmark_table_.reserve(boost::size(witnesses));
+ for (auto w : witnesses)
+ nearest_landmark_table_.push_back(landmark_tree_.query_incremental_nearest_neighbors(w));
+ }
+
+ /** \brief Returns the point corresponding to the given vertex.
+ */
+ template <typename Vertex_handle>
+ Point_d get_point(Vertex_handle vertex) const {
+ return landmarks_[vertex];
+ }
+
+ //@}
+};
+
+} // namespace witness_complex
+
+} // namespace Gudhi
+
+#endif // EUCLIDEAN_STRONG_WITNESS_COMPLEX_H_
diff --git a/src/Witness_complex/include/gudhi/Euclidean_witness_complex.h b/src/Witness_complex/include/gudhi/Euclidean_witness_complex.h
new file mode 100644
index 00000000..6afe9a5d
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Euclidean_witness_complex.h
@@ -0,0 +1,106 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EUCLIDEAN_WITNESS_COMPLEX_H_
+#define EUCLIDEAN_WITNESS_COMPLEX_H_
+
+#include <gudhi/Witness_complex.h>
+#include <gudhi/Active_witness/Active_witness.h>
+#include <gudhi/Kd_tree_search.h>
+
+#include <utility>
+#include <vector>
+#include <list>
+#include <limits>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/**
+ * \private
+ * \class Euclidean_witness_complex
+ * \brief Constructs (weak) witness complex for given sets of witnesses and landmarks in Euclidean space.
+ * \ingroup witness_complex
+ *
+ * \tparam Kernel_ requires a <a target="_blank"
+ * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class.
+ */
+template< class Kernel_ >
+class Euclidean_witness_complex
+ : public Witness_complex<std::vector<typename Gudhi::spatial_searching::Kd_tree_search<Kernel_,
+ std::vector<typename Kernel_::Point_d>>::INS_range>> {
+ private:
+ typedef Kernel_ K;
+ typedef typename K::Point_d Point_d;
+ typedef std::vector<Point_d> Point_range;
+ typedef Gudhi::spatial_searching::Kd_tree_search<Kernel_, Point_range> Kd_tree;
+ typedef typename Kd_tree::INS_range Nearest_landmark_range;
+ typedef typename std::vector<Nearest_landmark_range> Nearest_landmark_table;
+
+ typedef typename Nearest_landmark_range::Point_with_transformed_distance Id_distance_pair;
+ typedef typename Id_distance_pair::first_type Landmark_id;
+ typedef Landmark_id Vertex_handle;
+
+ private:
+ Point_range landmarks_;
+ Kd_tree landmark_tree_;
+ using Witness_complex<Nearest_landmark_table>::nearest_landmark_table_;
+
+ public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /* @name Constructor
+ */
+
+ //@{
+
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records landmarks from the range 'landmarks' into a
+ * table internally, as well as witnesses from the range 'witnesses'.
+ * Both ranges should have value_type Kernel_::Point_d.
+ */
+ template< typename LandmarkRange,
+ typename WitnessRange >
+ Euclidean_witness_complex(const LandmarkRange & landmarks,
+ const WitnessRange & witnesses)
+ : landmarks_(std::begin(landmarks), std::end(landmarks)), landmark_tree_(landmarks) {
+ nearest_landmark_table_.reserve(boost::size(witnesses));
+ for (auto w : witnesses)
+ nearest_landmark_table_.push_back(landmark_tree_.query_incremental_nearest_neighbors(w));
+ }
+
+ /** \brief Returns the point corresponding to the given vertex.
+ * @param[in] vertex Vertex handle of the point to retrieve.
+ */
+ Point_d get_point(Vertex_handle vertex) const {
+ return landmarks_[vertex];
+ }
+
+ //@}
+};
+
+} // namespace witness_complex
+
+} // namespace Gudhi
+
+#endif // EUCLIDEAN_WITNESS_COMPLEX_H_
diff --git a/src/Witness_complex/include/gudhi/Strong_witness_complex.h b/src/Witness_complex/include/gudhi/Strong_witness_complex.h
new file mode 100644
index 00000000..6708ac29
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Strong_witness_complex.h
@@ -0,0 +1,186 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef STRONG_WITNESS_COMPLEX_H_
+#define STRONG_WITNESS_COMPLEX_H_
+
+#include <gudhi/Active_witness/Active_witness.h>
+#include <gudhi/Kd_tree_search.h>
+
+#include <utility>
+#include <vector>
+#include <list>
+#include <limits>
+
+namespace Gudhi {
+
+namespace witness_complex {
+
+/* \private
+ * \class Strong_witness_complex
+ * \brief Constructs strong witness complex for a given table of nearest landmarks with respect to witnesses.
+ * \ingroup witness_complex
+ *
+ * \tparam Nearest_landmark_table_ needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
+ */
+template< class Nearest_landmark_table_ >
+class Strong_witness_complex {
+ private:
+ typedef typename Nearest_landmark_table_::value_type Nearest_landmark_range;
+ typedef std::size_t Witness_id;
+ typedef std::size_t Landmark_id;
+ typedef std::pair<Landmark_id, double> Id_distance_pair;
+ typedef Active_witness<Id_distance_pair, Nearest_landmark_range> ActiveWitness;
+ typedef std::list< ActiveWitness > ActiveWitnessList;
+ typedef std::vector< Landmark_id > typeVectorVertex;
+ typedef std::vector<Nearest_landmark_range> Nearest_landmark_table_internal;
+ typedef Landmark_id Vertex_handle;
+
+ protected:
+ Nearest_landmark_table_internal nearest_landmark_table_;
+
+ public:
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /* @name Constructor
+ */
+
+ //@{
+
+ Strong_witness_complex() {
+ }
+
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records nearest landmark table.
+ * @param[in] nearest_landmark_table needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
+ */
+ Strong_witness_complex(Nearest_landmark_table_ const & nearest_landmark_table)
+ : nearest_landmark_table_(std::begin(nearest_landmark_table), std::end(nearest_landmark_table)) {
+ }
+
+ /** \brief Outputs the strong witness complex of relaxation 'max_alpha_square'
+ * in a simplicial complex data structure.
+ * \details The function returns true if the construction is successful and false otherwise.
+ * @param[out] complex Simplicial complex data structure, which is a model of
+ * SimplicialComplexForWitness concept.
+ * @param[in] max_alpha_square Maximal squared relaxation parameter.
+ * @param[in] limit_dimension Represents the maximal dimension of the simplicial complex
+ * (default value = no limit).
+ */
+ template < typename SimplicialComplexForWitness >
+ bool create_complex(SimplicialComplexForWitness& complex,
+ double max_alpha_square,
+ Landmark_id limit_dimension = std::numeric_limits<Landmark_id>::max()) const {
+ Landmark_id complex_dim = 0;
+ if (complex.num_vertices() > 0) {
+ std::cerr << "Strong witness complex cannot create complex - complex is not empty.\n";
+ return false;
+ }
+ if (max_alpha_square < 0) {
+ std::cerr << "Strong witness complex cannot create complex - squared relaxation parameter must be "
+ << "non-negative.\n";
+ return false;
+ }
+ if (limit_dimension < 0) {
+ std::cerr << "Strong witness complex cannot create complex - limit dimension must be non-negative.\n";
+ return false;
+ }
+ for (auto w : nearest_landmark_table_) {
+ ActiveWitness aw(w);
+ typeVectorVertex simplex;
+ typename ActiveWitness::iterator aw_it = aw.begin();
+ float lim_dist2 = aw.begin()->second + max_alpha_square;
+ while ((Landmark_id)simplex.size() <= limit_dimension && aw_it != aw.end() && aw_it->second < lim_dist2) {
+ simplex.push_back(aw_it->first);
+ complex.insert_simplex_and_subfaces(simplex, aw_it->second - aw.begin()->second);
+ aw_it++;
+ }
+ // continue inserting limD-faces of the following simplices
+ typeVectorVertex& vertices = simplex; // 'simplex' now will be called vertices
+ while (aw_it != aw.end() && aw_it->second < lim_dist2) {
+ typeVectorVertex facet = {};
+ add_all_faces_of_dimension(limit_dimension, vertices, vertices.begin(), aw_it,
+ aw_it->second - aw.begin()->second, facet, complex);
+ vertices.push_back(aw_it->first);
+ aw_it++;
+ }
+ if ((Landmark_id)simplex.size() - 1 > complex_dim)
+ complex_dim = simplex.size() - 1;
+ }
+ complex.set_dimension(complex_dim);
+ return true;
+ }
+
+ private:
+ /* \brief Adds recursively all the faces of a certain dimension dim-1 witnessed by the same witness.
+ * Iterator is needed to know until how far we can take landmarks to form simplexes.
+ * simplex is the prefix of the simplexes to insert.
+ * The landmark pointed by aw_it is added to all formed simplices.
+ */
+ template < typename SimplicialComplexForWitness >
+ void add_all_faces_of_dimension(Landmark_id dim,
+ typeVectorVertex& vertices,
+ typename typeVectorVertex::iterator curr_it,
+ typename ActiveWitness::iterator aw_it,
+ double filtration_value,
+ typeVectorVertex& simplex,
+ SimplicialComplexForWitness& sc) const {
+ if (dim > 0) {
+ while (curr_it != vertices.end()) {
+ simplex.push_back(*curr_it);
+ ++curr_it;
+ add_all_faces_of_dimension(dim-1,
+ vertices,
+ curr_it,
+ aw_it,
+ filtration_value,
+ simplex,
+ sc);
+ simplex.pop_back();
+ add_all_faces_of_dimension(dim,
+ vertices,
+ curr_it,
+ aw_it,
+ filtration_value,
+ simplex,
+ sc);
+ }
+ } else if (dim == 0) {
+ simplex.push_back(aw_it->first);
+ sc.insert_simplex_and_subfaces(simplex, filtration_value);
+ simplex.pop_back();
+ }
+ }
+ //@}
+};
+
+} // namespace witness_complex
+
+} // namespace Gudhi
+
+#endif // STRONG_WITNESS_COMPLEX_H_
diff --git a/src/Witness_complex/include/gudhi/Witness_complex.h b/src/Witness_complex/include/gudhi/Witness_complex.h
index 1eb126f1..e7adf80f 100644
--- a/src/Witness_complex/include/gudhi/Witness_complex.h
+++ b/src/Witness_complex/include/gudhi/Witness_complex.h
@@ -4,7 +4,7 @@
*
* Author(s): Siargey Kachanovich
*
- * Copyright (C) 2015 INRIA Sophia Antipolis-Méditerranée (France)
+ * Copyright (C) 2015 INRIA (France)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,64 +23,45 @@
#ifndef WITNESS_COMPLEX_H_
#define WITNESS_COMPLEX_H_
-// Needed for the adjacency graph in bad link search
-#include <boost/graph/graph_traits.hpp>
-#include <boost/graph/adjacency_list.hpp>
-#include <boost/graph/connected_components.hpp>
+#include <gudhi/Active_witness/Active_witness.h>
+#include <gudhi/Kd_tree_search.h>
+#include <gudhi/Witness_complex/all_faces_in.h>
-#include <boost/range/size.hpp>
-
-#include <gudhi/distance_functions.h>
-
-#include <algorithm>
#include <utility>
#include <vector>
#include <list>
-#include <set>
-#include <queue>
#include <limits>
-#include <ctime>
-#include <iostream>
namespace Gudhi {
namespace witness_complex {
-// /*
-// * \private
-// \class Witness_complex
-// \brief Constructs the witness complex for the given set of witnesses and landmarks.
-// \ingroup witness_complex
-// */
-template< class SimplicialComplex>
+/**
+ * \private
+ * \class Witness_complex
+ * \brief Constructs (weak) witness complex for a given table of nearest landmarks with respect to witnesses.
+ * \ingroup witness_complex
+ *
+ * \tparam Nearest_landmark_table_ needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
+*/
+template< class Nearest_landmark_table_ >
class Witness_complex {
private:
- struct Active_witness {
- int witness_id;
- int landmark_id;
-
- Active_witness(int witness_id_, int landmark_id_)
- : witness_id(witness_id_),
- landmark_id(landmark_id_) { }
- };
-
- private:
- typedef typename SimplicialComplex::Simplex_handle Simplex_handle;
- typedef typename SimplicialComplex::Vertex_handle Vertex_handle;
-
- typedef std::vector< double > Point_t;
- typedef std::vector< Point_t > Point_Vector;
-
- typedef std::vector< Vertex_handle > typeVectorVertex;
- typedef std::pair< Simplex_handle, bool > typePairSimplexBool;
-
- typedef int Witness_id;
- typedef int Landmark_id;
- typedef std::list< Vertex_handle > ActiveWitnessList;
-
- private:
- int nbL_; // Number of landmarks
- SimplicialComplex& sc_; // Simplicial complex
+ typedef typename Nearest_landmark_table_::value_type Nearest_landmark_range;
+ typedef std::size_t Witness_id;
+ typedef std::size_t Landmark_id;
+ typedef std::pair<Landmark_id, double> Id_distance_pair;
+ typedef Active_witness<Id_distance_pair, Nearest_landmark_range> ActiveWitness;
+ typedef std::list< ActiveWitness > ActiveWitnessList;
+ typedef std::vector< Landmark_id > typeVectorVertex;
+ typedef std::vector<Nearest_landmark_range> Nearest_landmark_table_internal;
+ typedef Landmark_id Vertex_handle;
+
+ protected:
+ Nearest_landmark_table_internal nearest_landmark_table_;
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -89,174 +70,136 @@ class Witness_complex {
//@{
- // Witness_range<Closest_landmark_range<Vertex_handle>>
+ Witness_complex() {
+ }
- /*
- * \brief Iterative construction of the witness complex.
- * \details The witness complex is written in sc_ basing on a matrix knn of
- * nearest neighbours of the form {witnesses}x{landmarks}.
- *
- * The type KNearestNeighbors can be seen as
- * Witness_range<Closest_landmark_range<Vertex_handle>>, where
- * Witness_range and Closest_landmark_range are random access ranges.
- *
- * Constructor takes into account at most (dim+1)
- * first landmarks from each landmark range to construct simplices.
- *
- * Landmarks are supposed to be in [0,nbL_-1]
+ /**
+ * \brief Initializes member variables before constructing simplicial complex.
+ * \details Records nearest landmark table.
+ * @param[in] nearest_landmark_table needs to be a range of a range of pairs of nearest landmarks and distances.
+ * The class Nearest_landmark_table_::value_type must be a copiable range.
+ * The range of pairs must admit a member type 'iterator'. The dereference type
+ * of the pair range iterator needs to be 'std::pair<std::size_t, double>'.
*/
- template< typename KNearestNeighbors >
- Witness_complex(KNearestNeighbors const & knn,
- int nbL,
- int dim,
- SimplicialComplex & sc) : nbL_(nbL), sc_(sc) {
- // Construction of the active witness list
- int nbW = boost::size(knn);
- typeVectorVertex vv;
- int counter = 0;
- /* The list of still useful witnesses
- * it will diminuish in the course of iterations
- */
- ActiveWitnessList active_w; // = new ActiveWitnessList();
- for (Vertex_handle i = 0; i != nbL_; ++i) {
- // initial fill of 0-dimensional simplices
- // by doing it we don't assume that landmarks are necessarily witnesses themselves anymore
- counter++;
- vv = {i};
- sc_.insert_simplex(vv);
- // TODO(SK) Error if not inserted : normally no need here though
+
+ Witness_complex(Nearest_landmark_table_ const & nearest_landmark_table)
+ : nearest_landmark_table_(std::begin(nearest_landmark_table), std::end(nearest_landmark_table)) {
+ }
+
+ /** \brief Outputs the (weak) witness complex of relaxation 'max_alpha_square'
+ * in a simplicial complex data structure.
+ * \details The function returns true if the construction is successful and false otherwise.
+ * @param[out] complex Simplicial complex data structure compatible which is a model of
+ * SimplicialComplexForWitness concept.
+ * @param[in] max_alpha_square Maximal squared relaxation parameter.
+ * @param[in] limit_dimension Represents the maximal dimension of the simplicial complex
+ * (default value = no limit).
+ */
+ template < typename SimplicialComplexForWitness >
+ bool create_complex(SimplicialComplexForWitness& complex,
+ double max_alpha_square,
+ std::size_t limit_dimension = std::numeric_limits<std::size_t>::max()) const {
+ if (complex.num_vertices() > 0) {
+ std::cerr << "Witness complex cannot create complex - complex is not empty.\n";
+ return false;
}
- int k = 1; /* current dimension in iterative construction */
- for (int i = 0; i != nbW; ++i)
- active_w.push_back(i);
- while (!active_w.empty() && k < dim) {
- typename ActiveWitnessList::iterator it = active_w.begin();
- while (it != active_w.end()) {
- typeVectorVertex simplex_vector;
- /* THE INSERTION: Checking if all the subfaces are in the simplex tree*/
- bool ok = all_faces_in(knn, *it, k);
- if (ok) {
- for (int i = 0; i != k + 1; ++i)
- simplex_vector.push_back(knn[*it][i]);
- sc_.insert_simplex(simplex_vector);
- // TODO(SK) Error if not inserted : normally no need here though
- ++it;
- } else {
- active_w.erase(it++); // First increase the iterator and then erase the previous element
- }
+ if (max_alpha_square < 0) {
+ std::cerr << "Witness complex cannot create complex - squared relaxation parameter must be non-negative.\n";
+ return false;
+ }
+ if (limit_dimension < 0) {
+ std::cerr << "Witness complex cannot create complex - limit dimension must be non-negative.\n";
+ return false;
+ }
+ ActiveWitnessList active_witnesses;
+ Landmark_id k = 0; /* current dimension in iterative construction */
+ for (auto w : nearest_landmark_table_)
+ active_witnesses.push_back(ActiveWitness(w));
+ while (!active_witnesses.empty() && k <= limit_dimension) {
+ typename ActiveWitnessList::iterator aw_it = active_witnesses.begin();
+ std::vector<Landmark_id> simplex;
+ simplex.reserve(k+1);
+ while (aw_it != active_witnesses.end()) {
+ bool ok = add_all_faces_of_dimension(k,
+ max_alpha_square,
+ std::numeric_limits<double>::infinity(),
+ aw_it->begin(),
+ simplex,
+ complex,
+ aw_it->end());
+ assert(simplex.empty());
+ if (!ok)
+ active_witnesses.erase(aw_it++); // First increase the iterator and then erase the previous element
+ else
+ aw_it++;
}
k++;
}
+ complex.set_dimension(k-1);
+ return true;
}
//@}
private:
- /* \brief Check if the facets of the k-dimensional simplex witnessed
- * by witness witness_id are already in the complex.
- * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id
+ /* \brief Adds recursively all the faces of a certain dimension dim witnessed by the same witness.
+ * Iterator is needed to know until how far we can take landmarks to form simplexes.
+ * simplex is the prefix of the simplexes to insert.
+ * The output value indicates if the witness rests active or not.
*/
- template <typename KNearestNeighbors>
- bool all_faces_in(KNearestNeighbors const &knn, int witness_id, int k) {
- std::vector< Vertex_handle > facet;
- // CHECK ALL THE FACETS
- for (int i = 0; i != k + 1; ++i) {
- facet = {};
- for (int j = 0; j != k + 1; ++j) {
- if (j != i) {
- facet.push_back(knn[witness_id][j]);
+ template < typename SimplicialComplexForWitness >
+ bool add_all_faces_of_dimension(int dim,
+ double alpha2,
+ double norelax_dist2,
+ typename ActiveWitness::iterator curr_l,
+ std::vector<Landmark_id>& simplex,
+ SimplicialComplexForWitness& sc,
+ typename ActiveWitness::iterator end) const {
+ if (curr_l == end)
+ return false;
+ bool will_be_active = false;
+ typename ActiveWitness::iterator l_it = curr_l;
+ if (dim > 0) {
+ for (; l_it != end && l_it->second - alpha2 <= norelax_dist2; ++l_it) {
+ simplex.push_back(l_it->first);
+ if (sc.find(simplex) != sc.null_simplex()) {
+ typename ActiveWitness::iterator next_it = l_it;
+ will_be_active = add_all_faces_of_dimension(dim-1,
+ alpha2,
+ norelax_dist2,
+ ++next_it,
+ simplex,
+ sc,
+ end) || will_be_active;
}
- } // endfor
- if (sc_.find(facet) == sc_.null_simplex())
- return false;
- } // endfor
- return true;
- }
-
- template <typename T>
- static void print_vector(const std::vector<T>& v) {
- std::cout << "[";
- if (!v.empty()) {
- std::cout << *(v.begin());
- for (auto it = v.begin() + 1; it != v.end(); ++it) {
- std::cout << ",";
- std::cout << *it;
+ assert(!simplex.empty());
+ simplex.pop_back();
+ // If norelax_dist is infinity, change to first omitted distance
+ if (l_it->second <= norelax_dist2)
+ norelax_dist2 = l_it->second;
}
- }
- std::cout << "]";
- }
-
- public:
- // /*
- // * \brief Verification if every simplex in the complex is witnessed by witnesses in knn.
- // * \param print_output =true will print the witnesses for each simplex
- // * \remark Added for debugging purposes.
- // */
- template< class KNearestNeighbors >
- bool is_witness_complex(KNearestNeighbors const & knn, bool print_output) {
- for (Simplex_handle sh : sc_.complex_simplex_range()) {
- bool is_witnessed = false;
- typeVectorVertex simplex;
- int nbV = 0; // number of verticed in the simplex
- for (Vertex_handle v : sc_.simplex_vertex_range(sh))
- simplex.push_back(v);
- nbV = simplex.size();
- for (typeVectorVertex w : knn) {
- bool has_vertices = true;
- for (Vertex_handle v : simplex)
- if (std::find(w.begin(), w.begin() + nbV, v) == w.begin() + nbV) {
- has_vertices = false;
- }
- if (has_vertices) {
- is_witnessed = true;
- if (print_output) {
- std::cout << "The simplex ";
- print_vector(simplex);
- std::cout << " is witnessed by the witness ";
- print_vector(w);
- std::cout << std::endl;
- }
- break;
- }
- }
- if (!is_witnessed) {
- if (print_output) {
- std::cout << "The following simplex is not witnessed ";
- print_vector(simplex);
- std::cout << std::endl;
+ } else if (dim == 0) {
+ for (;l_it != end && l_it->second - alpha2 <= norelax_dist2; ++l_it) {
+ simplex.push_back(l_it->first);
+ double filtration_value = 0;
+ // if norelax_dist is infinite, relaxation is 0.
+ if (l_it->second > norelax_dist2)
+ filtration_value = l_it->second - norelax_dist2;
+ if (all_faces_in(simplex, &filtration_value, sc)) {
+ will_be_active = true;
+ sc.insert_simplex(simplex, filtration_value);
}
- assert(is_witnessed);
- return false;
+ assert(!simplex.empty());
+ simplex.pop_back();
+ // If norelax_dist is infinity, change to first omitted distance
+ if (l_it->second < norelax_dist2)
+ norelax_dist2 = l_it->second;
}
}
- return true;
+ return will_be_active;
}
};
- /**
- * \ingroup witness_complex
- * \brief Iterative construction of the witness complex.
- * \details The witness complex is written in simplicial complex sc_
- * basing on a matrix knn of
- * nearest neighbours of the form {witnesses}x{landmarks}.
- *
- * The type KNearestNeighbors can be seen as
- * Witness_range<Closest_landmark_range<Vertex_handle>>, where
- * Witness_range and Closest_landmark_range are random access ranges.
- *
- * Procedure takes into account at most (dim+1)
- * first landmarks from each landmark range to construct simplices.
- *
- * Landmarks are supposed to be in [0,nbL_-1]
- */
- template <class KNearestNeighbors, class SimplicialComplexForWitness>
- void witness_complex(KNearestNeighbors const & knn,
- int nbL,
- int dim,
- SimplicialComplexForWitness & sc) {
- Witness_complex<SimplicialComplexForWitness>(knn, nbL, dim, sc);
- }
-
} // namespace witness_complex
} // namespace Gudhi
diff --git a/src/Witness_complex/include/gudhi/Witness_complex/all_faces_in.h b/src/Witness_complex/include/gudhi/Witness_complex/all_faces_in.h
new file mode 100644
index 00000000..b68d75a1
--- /dev/null
+++ b/src/Witness_complex/include/gudhi/Witness_complex/all_faces_in.h
@@ -0,0 +1,55 @@
+/* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Siargey Kachanovich
+ *
+ * Copyright (C) 2015 INRIA (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WITNESS_COMPLEX_ALL_FACES_IN_H_
+#define WITNESS_COMPLEX_ALL_FACES_IN_H_
+
+/* \brief Check if the facets of the k-dimensional simplex witnessed
+ * by witness witness_id are already in the complex.
+ * inserted_vertex is the handle of the (k+1)-th vertex witnessed by witness_id
+ */
+template < typename SimplicialComplexForWitness,
+ typename Simplex >
+ bool all_faces_in(Simplex& simplex,
+ double* filtration_value,
+ SimplicialComplexForWitness& sc) {
+ typedef typename SimplicialComplexForWitness::Simplex_handle Simplex_handle;
+
+ if (simplex.size() == 1)
+ return true; /* Add vertices unconditionally */
+
+ Simplex facet;
+ for (typename Simplex::iterator not_it = simplex.begin(); not_it != simplex.end(); ++not_it) {
+ facet.clear();
+ for (typename Simplex::iterator it = simplex.begin(); it != simplex.end(); ++it)
+ if (it != not_it)
+ facet.push_back(*it);
+ Simplex_handle facet_sh = sc.find(facet);
+ if (facet_sh == sc.null_simplex())
+ return false;
+ else if (sc.filtration(facet_sh) > *filtration_value)
+ *filtration_value = sc.filtration(facet_sh);
+ }
+ return true;
+ }
+
+#endif // WITNESS_COMPLEX_ALL_FACES_IN_H_