summaryrefslogtreecommitdiff
path: root/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h')
-rw-r--r--src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h550
1 files changed, 280 insertions, 270 deletions
diff --git a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h
index f3ebfa60..725ecce5 100644
--- a/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h
+++ b/src/Skeleton_blocker/include/gudhi/Skeleton_blocker_link_complex.h
@@ -1,37 +1,36 @@
- /* 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): David Salinas
- *
- * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (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 GUDHI_SKELETON_BLOCKERS_LINK_COMPLEX_H_
-#define GUDHI_SKELETON_BLOCKERS_LINK_COMPLEX_H_
+/* 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): David Salinas
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Mediterranee (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 SRC_SKELETON_BLOCKER_INCLUDE_GUDHI_SKELETON_BLOCKER_LINK_COMPLEX_H_
+#define SRC_SKELETON_BLOCKER_INCLUDE_GUDHI_SKELETON_BLOCKER_LINK_COMPLEX_H_
#include "gudhi/Utils.h"
#include "gudhi/Skeleton_blocker_complex.h"
-namespace Gudhi{
+namespace Gudhi {
namespace skbl {
template<class ComplexType> class Skeleton_blocker_sub_complex;
-
/**
* \brief Class representing the link of a simplicial complex encoded by a skeleton/blockers pair.
* It inherits from Skeleton_blocker_sub_complex because such complex is a sub complex of a
@@ -39,252 +38,263 @@ template<class ComplexType> class Skeleton_blocker_sub_complex;
* \ingroup skbl
*/
template<typename ComplexType>
-class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<ComplexType>
-{
- template <typename T> friend class Skeleton_blocker_link_superior;
- typedef typename ComplexType::Edge_handle Edge_handle;
-
- typedef typename ComplexType::boost_vertex_handle boost_vertex_handle;
-
-
-private:
-
- bool only_superior_vertices_;
-
-public:
- typedef typename ComplexType::Vertex_handle Vertex_handle;
- typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
-
- typedef typename ComplexType::Simplex_handle Simplex_handle;
- typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
-
- typedef typename ComplexType::Blocker_handle Blocker_handle;
-
-
- typedef typename ComplexType::Simplex_handle::Simplex_vertex_const_iterator Simplex_handle_iterator;
- typedef typename ComplexType::Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_handle_iterator;
-
-
- Skeleton_blocker_link_complex(bool only_superior_vertices=false):only_superior_vertices_(only_superior_vertices){
- }
-
- /**
- * If the parameter only_superior_vertices is true,
- * only vertices greater than the one of alpha are added.
- */
- Skeleton_blocker_link_complex(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool only_superior_vertices = false)
- :only_superior_vertices_(only_superior_vertices) {
- if(!alpha_parent_adress.empty())
- build_link(parent_complex,alpha_parent_adress);
-
- }
-
- /**
- * If the parameter only_superior_vertices is true,
- * only vertices greater than the one of the vertex are added.
- */
- Skeleton_blocker_link_complex(const ComplexType & parent_complex, Vertex_handle a_parent_adress, bool only_superior_vertices = false)
- :only_superior_vertices_(only_superior_vertices){
- Simplex_handle alpha_simplex(a_parent_adress);
- build_link(parent_complex,alpha_simplex);
- }
-
-
- /**
- * If the parameter only_superior_vertices is true,
- * only vertices greater than the one of the edge are added.
- */
- Skeleton_blocker_link_complex(const ComplexType & parent_complex, Edge_handle edge, bool only_superior_vertices = false)
- :only_superior_vertices_(only_superior_vertices){
- Simplex_handle alpha_simplex(parent_complex.first_vertex(edge),parent_complex.second_vertex(edge));
- build_link(parent_complex,alpha_simplex);
- }
-
-protected:
-
-
- /**
- * @brief compute vertices of the link.
- * If the boolean only_superior_vertices is true, then only the vertices
- * are greater than vertices of alpha_parent_adress are added.
- */
- void compute_link_vertices(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool only_superior_vertices,bool is_alpha_blocker = false){
- if(alpha_parent_adress.dimension()==0)
- // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector)
- // thus we call a specific function that will reserve a vector with appropriate size
- this->compute_link_vertices(parent_complex,alpha_parent_adress.first_vertex(),only_superior_vertices_);
- else{
- // we compute the intersection of neighbors of alpha and store it in link_vertices
- Simplex_handle link_vertices_parent;
- parent_complex.add_neighbours(alpha_parent_adress,link_vertices_parent,only_superior_vertices);
- // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
- // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
- for (auto v_parent : link_vertices_parent){
- bool new_vertex = true;
- for (auto beta : parent_complex.const_blocker_range(v_parent))
- {
- if(!is_alpha_blocker || *beta!=alpha_parent_adress){
- new_vertex = !(alpha_parent_adress.contains_difference(*beta,v_parent));
- if(!new_vertex) break;
- }
- }
- if (new_vertex)
- this->add_vertex(parent_complex.get_id(v_parent));
- }
- }
- }
-
-
- /**
- * @brief compute vertices of the link.
- * If the boolean only_superior_vertices is true, then only the vertices
- * are greater than vertices of alpha_parent_adress are added.
- */
- void compute_link_vertices(const ComplexType & parent_complex, Vertex_handle alpha_parent_adress,bool only_superior_vertices){
- // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector
- this->skeleton.m_vertices.reserve(parent_complex.degree(alpha_parent_adress));
-
- // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
- // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
- for (auto v_parent : parent_complex.vertex_range(alpha_parent_adress)){
- if(!only_superior_vertices || v_parent.vertex> alpha_parent_adress.vertex)
- this->add_vertex(parent_complex.get_id(v_parent));
- }
-
- }
-
-
- void compute_link_edges(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool is_alpha_blocker = false){
- Simplex_handle_iterator y_link, x_parent , y_parent;
- // ----------------------------
- // Compute edges in the link
- // -------------------------
-
- if(this->num_vertices()<=1) return;
-
- for (auto x_link = this->vertex_range().begin() ;
- x_link!= this->vertex_range().end();
- ++x_link
- )
- {
- for (auto y_link = x_link; ++y_link != this->vertex_range().end(); ){
- Vertex_handle x_parent = *parent_complex.get_address(this->get_id(*x_link));
- Vertex_handle y_parent = *parent_complex.get_address(this->get_id(*y_link));
- if (parent_complex.contains_edge(x_parent,y_parent) ){
- // we check that there is no blocker subset of alpha passing trough x and y
- bool new_edge=true;
- for (auto blocker_parent : parent_complex.const_blocker_range(x_parent))
- {
- if(!is_alpha_blocker || *blocker_parent!=alpha_parent_adress){
- if (blocker_parent->contains(y_parent))
- {
- new_edge = !(alpha_parent_adress.contains_difference(*blocker_parent,x_parent,y_parent));
- if (!new_edge) break;
- }
- }
- }
- if (new_edge)
- this->add_edge(*x_link,*y_link);
- }
- }
- }
- }
-
-
- /**
- * @brief : Given an address in the current complex, it returns the
- * corresponding address in 'other_complex'.
- * It assumes that other_complex have a vertex 'this.get_id(address)'
- */
- boost::optional<Vertex_handle> give_equivalent_vertex(const ComplexType & other_complex,
- Vertex_handle address) const{
- Root_vertex_handle id((*this)[address].get_id());
- return other_complex.get_address(id);
- }
-
- /*
- * compute the blockers of the link if is_alpha_blocker is false.
- * Otherwise, alpha is a blocker, and the link is computed in the complex where
- * the blocker is anticollapsed.
- */
- void compute_link_blockers(const ComplexType & parent_complex,const Simplex_handle& alpha_parent,bool is_alpha_blocker = false){
-
- for (auto x_link : this->vertex_range()){
-
- Vertex_handle x_parent = * this->give_equivalent_vertex(parent_complex,x_link);
-
- for (auto blocker_parent : parent_complex.const_blocker_range(x_parent)){
- if(!is_alpha_blocker || *blocker_parent!=alpha_parent){
- Simplex_handle sigma_parent(*blocker_parent);
-
- sigma_parent.difference(alpha_parent);
-
- if (sigma_parent.dimension()>=2 && sigma_parent.first_vertex() == x_parent){
- Root_simplex_handle sigma_id(parent_complex.get_id(sigma_parent));
- auto sigma_link = this->get_simplex_address(sigma_id);
- // ie if the vertices of sigma are vertices of the link
- if(sigma_link){
- bool is_new_blocker = true;
- for(auto a : alpha_parent){
- for(auto eta_parent : parent_complex.const_blocker_range(a)){
- if(!is_alpha_blocker || *eta_parent!=alpha_parent){
- Simplex_handle eta_minus_alpha(*eta_parent);
- eta_minus_alpha.difference(alpha_parent);
- if(eta_minus_alpha != sigma_parent &&
- sigma_parent.contains_difference(*eta_parent,alpha_parent)){
- is_new_blocker = false;
- break;
- }
- }
- }
- if (!is_new_blocker) break;
- }
- if (is_new_blocker)
- this->add_blocker(new Simplex_handle(*sigma_link));
-
- }
- }
- }
- }
- }
- }
-
-
-public:
- /**
- * @brief compute vertices, edges and blockers of the link.
- * @details If the boolean only_superior_vertices is true, then the link is computed only
- * with vertices that are greater than vertices of alpha_parent_adress.
- */
- void build_link(const ComplexType & parent_complex,const Simplex_handle& alpha_parent_adress,bool is_alpha_blocker = false)
- {
- assert(is_alpha_blocker || parent_complex.contains(alpha_parent_adress));
- compute_link_vertices(parent_complex,alpha_parent_adress,only_superior_vertices_);
- compute_link_edges(parent_complex,alpha_parent_adress,is_alpha_blocker);
- compute_link_blockers(parent_complex,alpha_parent_adress,is_alpha_blocker);
- }
-
-
- /**
- * @brief build the link of a blocker which is the link
- * of the blocker's simplex if this simplex had been
- * removed from the blockers of the complex.
- */
- friend void build_link_of_blocker(
- const ComplexType & parent_complex,
- Simplex_handle& blocker,
- Skeleton_blocker_link_complex & result){
- assert(blocker.dimension()>=2);
- assert(parent_complex.contains_blocker(blocker));
- result.clear();
- result.build_link(parent_complex,blocker,true);
- }
-
-
+class Skeleton_blocker_link_complex : public Skeleton_blocker_sub_complex<
+ ComplexType> {
+ template<typename T> friend class Skeleton_blocker_link_superior;
+ typedef typename ComplexType::Edge_handle Edge_handle;
+
+ typedef typename ComplexType::boost_vertex_handle boost_vertex_handle;
+
+ private:
+ bool only_superior_vertices_;
+
+ public:
+ typedef typename ComplexType::Vertex_handle Vertex_handle;
+ typedef typename ComplexType::Root_vertex_handle Root_vertex_handle;
+
+ typedef typename ComplexType::Simplex_handle Simplex_handle;
+ typedef typename ComplexType::Root_simplex_handle Root_simplex_handle;
+
+ typedef typename ComplexType::Blocker_handle Blocker_handle;
+
+ typedef typename ComplexType::Simplex_handle::Simplex_vertex_const_iterator Simplex_handle_iterator;
+ typedef typename ComplexType::Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_handle_iterator;
+
+ explicit Skeleton_blocker_link_complex(bool only_superior_vertices = false)
+ : only_superior_vertices_(only_superior_vertices) {
+ }
+
+ /**
+ * If the parameter only_superior_vertices is true,
+ * only vertices greater than the one of alpha are added.
+ */
+ Skeleton_blocker_link_complex(const ComplexType & parent_complex,
+ const Simplex_handle& alpha_parent_adress,
+ bool only_superior_vertices = false)
+ : only_superior_vertices_(only_superior_vertices) {
+ if (!alpha_parent_adress.empty())
+ build_link(parent_complex, alpha_parent_adress);
+ }
+
+ /**
+ * If the parameter only_superior_vertices is true,
+ * only vertices greater than the one of the vertex are added.
+ */
+ Skeleton_blocker_link_complex(const ComplexType & parent_complex,
+ Vertex_handle a_parent_adress,
+ bool only_superior_vertices = false)
+ : only_superior_vertices_(only_superior_vertices) {
+ Simplex_handle alpha_simplex(a_parent_adress);
+ build_link(parent_complex, alpha_simplex);
+ }
+
+ /**
+ * If the parameter only_superior_vertices is true,
+ * only vertices greater than the one of the edge are added.
+ */
+ Skeleton_blocker_link_complex(const ComplexType & parent_complex,
+ Edge_handle edge, bool only_superior_vertices =
+ false)
+ : only_superior_vertices_(only_superior_vertices) {
+ Simplex_handle alpha_simplex(parent_complex.first_vertex(edge),
+ parent_complex.second_vertex(edge));
+ build_link(parent_complex, alpha_simplex);
+ }
+
+ protected:
+ /**
+ * @brief compute vertices of the link.
+ * If the boolean only_superior_vertices is true, then only the vertices
+ * are greater than vertices of alpha_parent_adress are added.
+ */
+ void compute_link_vertices(const ComplexType & parent_complex,
+ const Simplex_handle& alpha_parent_adress,
+ bool only_superior_vertices,
+ bool is_alpha_blocker = false) {
+ if (alpha_parent_adress.dimension() == 0) {
+ // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector)
+ // thus we call a specific function that will reserve a vector with appropriate size
+ this->compute_link_vertices(parent_complex,
+ alpha_parent_adress.first_vertex(),
+ only_superior_vertices_);
+ } else {
+ // we compute the intersection of neighbors of alpha and store it in link_vertices
+ Simplex_handle link_vertices_parent;
+ parent_complex.add_neighbours(alpha_parent_adress, link_vertices_parent,
+ only_superior_vertices);
+ // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
+ // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
+ for (auto v_parent : link_vertices_parent) {
+ bool new_vertex = true;
+ for (auto beta : parent_complex.const_blocker_range(v_parent)) {
+ if (!is_alpha_blocker || *beta != alpha_parent_adress) {
+ new_vertex = !(alpha_parent_adress.contains_difference(*beta,
+ v_parent));
+ if (!new_vertex)
+ break;
+ }
+ }
+ if (new_vertex)
+ this->add_vertex(parent_complex.get_id(v_parent));
+ }
+ }
+ }
+
+ /**
+ * @brief compute vertices of the link.
+ * If the boolean only_superior_vertices is true, then only the vertices
+ * are greater than vertices of alpha_parent_adress are added.
+ */
+ void compute_link_vertices(const ComplexType & parent_complex,
+ Vertex_handle alpha_parent_adress,
+ bool only_superior_vertices) {
+ // for a vertex we know exactly the number of vertices of the link (and the size of the corresponding vector
+ this->skeleton.m_vertices.reserve(
+ parent_complex.degree(alpha_parent_adress));
+
+ // For all vertex 'v' in this intersection, we go through all its adjacent blockers.
+ // If one blocker minus 'v' is included in alpha then the vertex is not in the link complex.
+ for (auto v_parent : parent_complex.vertex_range(alpha_parent_adress)) {
+ if (!only_superior_vertices
+ || v_parent.vertex > alpha_parent_adress.vertex)
+ this->add_vertex(parent_complex.get_id(v_parent));
+ }
+ }
+
+ void compute_link_edges(const ComplexType & parent_complex,
+ const Simplex_handle& alpha_parent_adress,
+ bool is_alpha_blocker = false) {
+ Simplex_handle_iterator y_link, x_parent, y_parent;
+ // ----------------------------
+ // Compute edges in the link
+ // -------------------------
+
+ if (this->num_vertices() <= 1)
+ return;
+
+ for (auto x_link = this->vertex_range().begin();
+ x_link != this->vertex_range().end(); ++x_link) {
+ for (auto y_link = x_link; ++y_link != this->vertex_range().end();) {
+ Vertex_handle x_parent = *parent_complex.get_address(
+ this->get_id(*x_link));
+ Vertex_handle y_parent = *parent_complex.get_address(
+ this->get_id(*y_link));
+ if (parent_complex.contains_edge(x_parent, y_parent)) {
+ // we check that there is no blocker subset of alpha passing trough x and y
+ bool new_edge = true;
+ for (auto blocker_parent : parent_complex.const_blocker_range(
+ x_parent)) {
+ if (!is_alpha_blocker || *blocker_parent != alpha_parent_adress) {
+ if (blocker_parent->contains(y_parent)) {
+ new_edge = !(alpha_parent_adress.contains_difference(
+ *blocker_parent, x_parent, y_parent));
+ if (!new_edge)
+ break;
+ }
+ }
+ }
+ if (new_edge)
+ this->add_edge(*x_link, *y_link);
+ }
+ }
+ }
+ }
+
+ /**
+ * @brief : Given an address in the current complex, it returns the
+ * corresponding address in 'other_complex'.
+ * It assumes that other_complex have a vertex 'this.get_id(address)'
+ */
+ boost::optional<Vertex_handle> give_equivalent_vertex(
+ const ComplexType & other_complex, Vertex_handle address) const {
+ Root_vertex_handle id((*this)[address].get_id());
+ return other_complex.get_address(id);
+ }
+
+ /*
+ * compute the blockers of the link if is_alpha_blocker is false.
+ * Otherwise, alpha is a blocker, and the link is computed in the complex where
+ * the blocker is anticollapsed.
+ */
+ void compute_link_blockers(const ComplexType & parent_complex,
+ const Simplex_handle& alpha_parent,
+ bool is_alpha_blocker = false) {
+ for (auto x_link : this->vertex_range()) {
+ Vertex_handle x_parent = *this->give_equivalent_vertex(parent_complex,
+ x_link);
+
+ for (auto blocker_parent : parent_complex.const_blocker_range(x_parent)) {
+ if (!is_alpha_blocker || *blocker_parent != alpha_parent) {
+ Simplex_handle sigma_parent(*blocker_parent);
+
+ sigma_parent.difference(alpha_parent);
+
+ if (sigma_parent.dimension() >= 2
+ && sigma_parent.first_vertex() == x_parent) {
+ Root_simplex_handle sigma_id(parent_complex.get_id(sigma_parent));
+ auto sigma_link = this->get_simplex_address(sigma_id);
+ // ie if the vertices of sigma are vertices of the link
+ if (sigma_link) {
+ bool is_new_blocker = true;
+ for (auto a : alpha_parent) {
+ for (auto eta_parent : parent_complex.const_blocker_range(a)) {
+ if (!is_alpha_blocker || *eta_parent != alpha_parent) {
+ Simplex_handle eta_minus_alpha(*eta_parent);
+ eta_minus_alpha.difference(alpha_parent);
+ if (eta_minus_alpha != sigma_parent
+ && sigma_parent.contains_difference(*eta_parent,
+ alpha_parent)) {
+ is_new_blocker = false;
+ break;
+ }
+ }
+ }
+ if (!is_new_blocker)
+ break;
+ }
+ if (is_new_blocker)
+ this->add_blocker(new Simplex_handle(*sigma_link));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public:
+ /**
+ * @brief compute vertices, edges and blockers of the link.
+ * @details If the boolean only_superior_vertices is true, then the link is computed only
+ * with vertices that are greater than vertices of alpha_parent_adress.
+ */
+ void build_link(const ComplexType & parent_complex,
+ const Simplex_handle& alpha_parent_adress,
+ bool is_alpha_blocker = false) {
+ assert(is_alpha_blocker || parent_complex.contains(alpha_parent_adress));
+ compute_link_vertices(parent_complex, alpha_parent_adress,
+ only_superior_vertices_);
+ compute_link_edges(parent_complex, alpha_parent_adress, is_alpha_blocker);
+ compute_link_blockers(parent_complex, alpha_parent_adress,
+ is_alpha_blocker);
+ }
+
+ /**
+ * @brief build the link of a blocker which is the link
+ * of the blocker's simplex if this simplex had been
+ * removed from the blockers of the complex.
+ */
+ friend void build_link_of_blocker(const ComplexType & parent_complex,
+ Simplex_handle& blocker,
+ Skeleton_blocker_link_complex & result) {
+ assert(blocker.dimension() >= 2);
+ assert(parent_complex.contains_blocker(blocker));
+ result.clear();
+ result.build_link(parent_complex, blocker, true);
+ }
};
-}
+} // namespace skbl
-} // namespace GUDHI
+} // namespace Gudhi
-#endif /* SKELETON_BLOCKERS_LINK_COMPLEX_H_ */
+#endif // SRC_SKELETON_BLOCKER_INCLUDE_GUDHI_SKELETON_BLOCKER_LINK_COMPLEX_H_