summaryrefslogtreecommitdiff
path: root/include/gudhi/Skeleton_blocker_complex.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/gudhi/Skeleton_blocker_complex.h')
-rw-r--r--include/gudhi/Skeleton_blocker_complex.h1605
1 files changed, 0 insertions, 1605 deletions
diff --git a/include/gudhi/Skeleton_blocker_complex.h b/include/gudhi/Skeleton_blocker_complex.h
deleted file mode 100644
index addd8104..00000000
--- a/include/gudhi/Skeleton_blocker_complex.h
+++ /dev/null
@@ -1,1605 +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): David Salinas
- *
- * Copyright (C) 2014 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 SKELETON_BLOCKER_COMPLEX_H_
-#define SKELETON_BLOCKER_COMPLEX_H_
-
-#include <gudhi/Skeleton_blocker/iterators/Skeleton_blockers_iterators.h>
-#include <gudhi/Skeleton_blocker_link_complex.h>
-#include <gudhi/Skeleton_blocker/Skeleton_blocker_link_superior.h>
-#include <gudhi/Skeleton_blocker/Skeleton_blocker_sub_complex.h>
-#include <gudhi/Skeleton_blocker/Skeleton_blocker_simplex.h>
-#include <gudhi/Skeleton_blocker/Skeleton_blocker_complex_visitor.h>
-#include <gudhi/Skeleton_blocker/internal/Top_faces.h>
-#include <gudhi/Skeleton_blocker/internal/Trie.h>
-#include <gudhi/Debug_utils.h>
-
-#include <boost/graph/adjacency_list.hpp>
-#include <boost/graph/connected_components.hpp>
-#include <boost/iterator/transform_iterator.hpp>
-#include <boost/range/adaptor/map.hpp>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <memory>
-#include <map>
-#include <list>
-#include <set>
-#include <vector>
-#include <string>
-#include <algorithm>
-#include <utility>
-
-namespace Gudhi {
-
-namespace skeleton_blocker {
-
-/**
- *@class Skeleton_blocker_complex
- *@brief Abstract Simplicial Complex represented with a skeleton/blockers pair.
- *@ingroup skbl
- */
-template<class SkeletonBlockerDS>
-class Skeleton_blocker_complex {
- template<class ComplexType> friend class Vertex_iterator;
- template<class ComplexType> friend class Neighbors_vertices_iterator;
- template<class ComplexType> friend class Edge_iterator;
- template<class ComplexType> friend class Edge_around_vertex_iterator;
-
- template<class ComplexType> friend class Skeleton_blocker_link_complex;
- template<class ComplexType> friend class Skeleton_blocker_link_superior;
- template<class ComplexType> friend class Skeleton_blocker_sub_complex;
-
- public:
- /**
- * @brief The type of stored vertex node, specified by the template SkeletonBlockerDS
- */
- typedef typename SkeletonBlockerDS::Graph_vertex Graph_vertex;
-
- /**
- * @brief The type of stored edge node, specified by the template SkeletonBlockerDS
- */
- typedef typename SkeletonBlockerDS::Graph_edge Graph_edge;
-
- typedef typename SkeletonBlockerDS::Root_vertex_handle Root_vertex_handle;
-
- /**
- * @brief The type of an handle to a vertex of the complex.
- */
- typedef typename SkeletonBlockerDS::Vertex_handle Vertex_handle;
- typedef typename Root_vertex_handle::boost_vertex_handle boost_vertex_handle;
-
- /**
- * @brief A ordered set of integers that represents a simplex.
- */
- typedef Skeleton_blocker_simplex<Vertex_handle> Simplex;
- typedef Skeleton_blocker_simplex<Root_vertex_handle> Root_simplex_handle;
-
- /**
- * @brief Handle to a blocker of the complex.
- */
- typedef Simplex* Blocker_handle;
-
- typedef typename Root_simplex_handle::Simplex_vertex_const_iterator Root_simplex_iterator;
- typedef typename Simplex::Simplex_vertex_const_iterator Simplex_handle_iterator;
-
- protected:
- typedef typename boost::adjacency_list<boost::setS, // edges
- boost::vecS, // vertices
- boost::undirectedS, Graph_vertex, Graph_edge> Graph;
- // todo/remark : edges are not sorted, it heavily penalizes computation for SuperiorLink
- // (eg Link with greater vertices)
- // that burdens simplex iteration / complex initialization via list of simplices.
- // to avoid that, one should modify the graph by storing two lists of adjacency for every
- // vertex, the one with superior and the one with lower vertices, that way there is
- // no more extra cost for computation of SuperiorLink
- typedef typename boost::graph_traits<Graph>::vertex_iterator boost_vertex_iterator;
- typedef typename boost::graph_traits<Graph>::edge_iterator boost_edge_iterator;
-
- protected:
- typedef typename boost::graph_traits<Graph>::adjacency_iterator boost_adjacency_iterator;
-
- public:
- /**
- * @brief Handle to an edge of the complex.
- */
- typedef typename boost::graph_traits<Graph>::edge_descriptor Edge_handle;
-
- protected:
- typedef std::multimap<Vertex_handle, Simplex *> BlockerMap;
- typedef typename std::multimap<Vertex_handle, Simplex *>::value_type BlockerPair;
- typedef typename std::multimap<Vertex_handle, Simplex *>::iterator BlockerMapIterator;
- typedef typename std::multimap<Vertex_handle, Simplex *>::const_iterator BlockerMapConstIterator;
-
- protected:
- size_t num_vertices_;
- size_t num_blockers_;
-
- typedef Skeleton_blocker_complex_visitor<Vertex_handle> Visitor;
- // typedef Visitor* Visitor_ptr;
- Visitor* visitor;
-
- /**
- * @details If 'x' is a Vertex_handle of a vertex in the complex then degree[x] = d is its degree.
- *
- * This quantity is updated when adding/removing edge.
- *
- * This is useful because the operation
- * list.size() is done in linear time.
- */
- std::vector<boost_vertex_handle> degree_;
- Graph skeleton; /** 1-skeleton of the simplicial complex. */
-
- /** Each vertex can access to the blockers passing through it. */
- BlockerMap blocker_map_;
-
- public:
- /////////////////////////////////////////////////////////////////////////////
- /** @name Constructors, Destructors
- */
- //@{
-
- /**
- *@brief constructs a simplicial complex with a given number of vertices and a visitor.
- */
- explicit Skeleton_blocker_complex(size_t num_vertices_ = 0, Visitor* visitor_ = NULL)
- : visitor(visitor_) {
- clear();
- for (size_t i = 0; i < num_vertices_; ++i) {
- add_vertex();
- }
- }
-
- private:
- // typedef Trie<Skeleton_blocker_complex<SkeletonBlockerDS>> STrie;
- typedef Trie<Simplex> STrie;
-
- public:
- /**
- * @brief Constructor with a list of simplices.
- * @details is_flag_complex indicates if the complex is a flag complex or not (to know if blockers have to be computed or not).
- */
- template<typename SimpleHandleOutputIterator>
- Skeleton_blocker_complex(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end,
- bool is_flag_complex = false, Visitor* visitor_ = NULL)
- : num_vertices_(0),
- num_blockers_(0),
- visitor(visitor_) {
- add_vertices_and_edges(simplices_begin, simplices_end);
-
- if (!is_flag_complex)
- // need to compute blockers
- add_blockers(simplices_begin, simplices_end);
- }
-
- private:
- /**
- * Add vertices and edges of a simplex in one pass
- */
- template<typename SimpleHandleOutputIterator>
- void add_vertices_and_edges(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
- std::vector<std::pair<Vertex_handle, Vertex_handle>> edges;
- // first pass to add vertices and edges
- int num_vertex = -1;
- for (auto s_it = simplices_begin; s_it != simplices_end; ++s_it) {
- if (s_it->dimension() == 0) num_vertex = (std::max)(num_vertex, s_it->first_vertex().vertex);
- if (s_it->dimension() == 1) edges.emplace_back(s_it->first_vertex(), s_it->last_vertex());
- }
- while (num_vertex-- >= 0) add_vertex();
-
- for (const auto& e : edges)
- add_edge_without_blockers(e.first, e.second);
- }
-
- template<typename SimpleHandleOutputIterator>
- void add_blockers(SimpleHandleOutputIterator simplices_begin, SimpleHandleOutputIterator simplices_end) {
- Tries<Simplex> tries(num_vertices(), simplices_begin, simplices_end);
- tries.init_next_dimension();
- auto simplices(tries.next_dimension_simplices());
-
- while (!simplices.empty()) {
- simplices = tries.next_dimension_simplices();
- for (auto& sigma : simplices) {
- // common_positive_neighbors is the set of vertices u such that
- // for all s in sigma, us is an edge and u>s
- Simplex common_positive_neighbors(tries.positive_neighbors(sigma.last_vertex()));
- for (auto sigma_it = sigma.rbegin(); sigma_it != sigma.rend(); ++sigma_it)
- if (sigma_it != sigma.rbegin())
- common_positive_neighbors.intersection(tries.positive_neighbors(*sigma_it));
-
- for (auto x : common_positive_neighbors) {
- // first test that all edges sx are here for all s in sigma
- bool all_edges_here = true;
- for (auto s : sigma)
- if (!contains_edge(x, s)) {
- all_edges_here = false;
- break;
- }
- if (!all_edges_here) continue;
-
- // all edges of sigma \cup x are here
- // we have a blocker if all proper faces of sigma \cup x
- // are in the complex and if sigma \cup x is not in the complex
- // the first is equivalent at checking if blocks(sigma \cup x) is true
- // as all blockers of lower dimension have already been computed
- sigma.add_vertex(x);
- if (!tries.contains(sigma) && !blocks(sigma))
- add_blocker(sigma);
- sigma.remove_vertex(x);
- }
- }
- }
- }
-
- public:
- // We cannot use the default copy constructor since we need
- // to make a copy of each of the blockers
-
- Skeleton_blocker_complex(const Skeleton_blocker_complex& copy) {
- visitor = NULL;
- degree_ = copy.degree_;
- skeleton = Graph(copy.skeleton);
- num_vertices_ = copy.num_vertices_;
-
- num_blockers_ = 0;
- // we copy the blockers
- for (auto blocker : copy.const_blocker_range()) {
- add_blocker(*blocker);
- }
- }
-
- /**
- */
- Skeleton_blocker_complex& operator=(const Skeleton_blocker_complex& copy) {
- clear();
- visitor = NULL;
- degree_ = copy.degree_;
- skeleton = Graph(copy.skeleton);
- num_vertices_ = copy.num_vertices_;
-
- num_blockers_ = 0;
- // we copy the blockers
- for (auto blocker : copy.const_blocker_range())
- add_blocker(*blocker);
- return *this;
- }
-
- /**
- * return true if both complexes have the same simplices.
- */
- bool operator==(const Skeleton_blocker_complex& other) const {
- if (other.num_vertices() != num_vertices()) return false;
- if (other.num_edges() != num_edges()) return false;
- if (other.num_blockers() != num_blockers()) return false;
-
- for (auto v : vertex_range())
- if (!other.contains_vertex(v)) return false;
-
- for (auto e : edge_range())
- if (!other.contains_edge(first_vertex(e), second_vertex(e))) return false;
-
- for (const auto b : const_blocker_range())
- if (!other.contains_blocker(*b)) return false;
-
- return true;
- }
-
- bool operator!=(const Skeleton_blocker_complex& other) const {
- return !(*this == other);
- }
-
- /**
- * The destructor delete all blockers allocated.
- */
- virtual ~Skeleton_blocker_complex() {
- clear();
- }
-
- /**
- * @details Clears the simplicial complex. After a call to this function,
- * blockers are destroyed. The 1-skeleton and the set of blockers
- * are both empty.
- */
- virtual void clear() {
- // xxx for now the responsabilty of freeing the visitor is for
- // the user
- visitor = NULL;
-
- degree_.clear();
- num_vertices_ = 0;
-
- remove_blockers();
-
- skeleton.clear();
- }
-
- /**
- *@brief allows to change the visitor.
- */
- void set_visitor(Visitor* other_visitor) {
- visitor = other_visitor;
- }
-
- //@}
-
- /////////////////////////////////////////////////////////////////////////////
- /** @name Vertices operations
- */
- //@{
- public:
- /**
- * @brief Return a local Vertex_handle of a vertex given a global one.
- * @remark Assume that the vertex is present in the complex.
- */
- Vertex_handle operator[](Root_vertex_handle global) const {
- auto local(get_address(global));
- assert(local);
- return *local;
- }
-
- /**
- * @brief Return the vertex node associated to local Vertex_handle.
- * @remark Assume that the vertex is present in the complex.
- */
- Graph_vertex& operator[](Vertex_handle address) {
- assert(
- 0 <= address.vertex && address.vertex < boost::num_vertices(skeleton));
- return skeleton[address.vertex];
- }
-
- /**
- * @brief Return the vertex node associated to local Vertex_handle.
- * @remark Assume that the vertex is present in the complex.
- */
- const Graph_vertex& operator[](Vertex_handle address) const {
- assert(
- 0 <= address.vertex && address.vertex < boost::num_vertices(skeleton));
- return skeleton[address.vertex];
- }
-
- /**
- * @brief Adds a vertex to the simplicial complex and returns its Vertex_handle.
- * @remark Vertex representation is contiguous.
- */
- Vertex_handle add_vertex() {
- Vertex_handle address(boost::add_vertex(skeleton));
- num_vertices_++;
- (*this)[address].activate();
- // safe since we now that we are in the root complex and the field 'address' and 'id'
- // are identical for every vertices
- (*this)[address].set_id(Root_vertex_handle(address.vertex));
- degree_.push_back(0);
- if (visitor)
- visitor->on_add_vertex(address);
- return address;
- }
-
- /**
- * @brief Remove a vertex from the simplicial complex
- * @remark It just deactivates the vertex with a boolean flag but does not
- * remove it from vertices from complexity issues.
- */
- void remove_vertex(Vertex_handle address) {
- assert(contains_vertex(address));
- // We remove b
- boost::clear_vertex(address.vertex, skeleton);
- (*this)[address].deactivate();
- num_vertices_--;
- degree_[address.vertex] = -1;
- if (visitor)
- visitor->on_remove_vertex(address);
- }
-
- /**
- */
- bool contains_vertex(Vertex_handle u) const {
- Vertex_handle num_vertices(boost::num_vertices(skeleton));
- if (u.vertex < 0 || u.vertex >= num_vertices)
- return false;
- return (*this)[u].is_active();
- }
-
- /**
- */
- bool contains_vertex(Root_vertex_handle u) const {
- boost::optional<Vertex_handle> address = get_address(u);
- return address && (*this)[*address].is_active();
- }
-
- /**
- * @return true iff the simplicial complex contains all vertices
- * of simplex sigma
- */
- bool contains_vertices(const Simplex & sigma) const {
- for (auto vertex : sigma)
- if (!contains_vertex(vertex))
- return false;
- return true;
- }
-
- /**
- * @brief Given an Id return the address of the vertex having this Id in the complex.
- * @remark For a simplicial complex, the address is the id but it may not be the case for a SubComplex.
- */
- virtual boost::optional<Vertex_handle> get_address(Root_vertex_handle id) const {
- boost::optional<Vertex_handle> res;
- int num_vertices = boost::num_vertices(skeleton);
- if (id.vertex < num_vertices)
- res = Vertex_handle(id.vertex);
- return res;
- }
-
- /**
- * return the id of a vertex of adress local present in the graph
- */
- Root_vertex_handle get_id(Vertex_handle local) const {
- assert(0 <= local.vertex && local.vertex < boost::num_vertices(skeleton));
- return (*this)[local].get_id();
- }
-
- /**
- * @brief Convert an address of a vertex of a complex to the address in
- * the current complex.
- * @details
- * If the current complex is a sub (or sup) complex of 'other', it converts
- * the address of a vertex v expressed in 'other' to the address of the vertex
- * v in the current one.
- * @remark this methods uses Root_vertex_handle to identify the vertex and
- * assumes the vertex is present in the current complex.
- */
- Vertex_handle convert_handle_from_another_complex(const Skeleton_blocker_complex& other,
- Vertex_handle vh_in_other) const {
- auto vh_in_current_complex = get_address(other.get_id(vh_in_other));
- assert(vh_in_current_complex);
- return *vh_in_current_complex;
- }
-
- /**
- * @brief return the graph degree of a vertex.
- */
- int degree(Vertex_handle local) const {
- assert(0 <= local.vertex && local.vertex < boost::num_vertices(skeleton));
- return degree_[local.vertex];
- }
-
- //@}
-
- /////////////////////////////////////////////////////////////////////////////
- /** @name Edges operations
- */
- //@{
- public:
- /**
- * @brief return an edge handle if the two vertices forms
- * an edge in the complex
- */
- boost::optional<Edge_handle> operator[](
- const std::pair<Vertex_handle, Vertex_handle>& ab) const {
- boost::optional<Edge_handle> res;
- std::pair<Edge_handle, bool> edge_pair(
- boost::edge(ab.first.vertex, ab.second.vertex, skeleton));
- if (edge_pair.second)
- res = edge_pair.first;
- return res;
- }
-
- /**
- * @brief returns the stored node associated to an edge
- */
- Graph_edge& operator[](Edge_handle edge_handle) {
- return skeleton[edge_handle];
- }
-
- /**
- * @brief returns the stored node associated to an edge
- */
- const Graph_edge& operator[](Edge_handle edge_handle) const {
- return skeleton[edge_handle];
- }
-
- /**
- * @brief returns the first vertex of an edge
- * @details it assumes that the edge is present in the complex
- */
- Vertex_handle first_vertex(Edge_handle edge_handle) const {
- return static_cast<Vertex_handle> (source(edge_handle, skeleton));
- }
-
- /**
- * @brief returns the first vertex of an edge
- * @details it assumes that the edge is present in the complex
- */
- Vertex_handle second_vertex(Edge_handle edge_handle) const {
- return static_cast<Vertex_handle> (target(edge_handle, skeleton));
- }
-
- /**
- * @brief returns the simplex made with the two vertices of the edge
- * @details it assumes that the edge is present in the complex
-
- */
- Simplex get_vertices(Edge_handle edge_handle) const {
- auto edge((*this)[edge_handle]);
- return Simplex((*this)[edge.first()], (*this)[edge.second()]);
- }
-
- /**
- * @brief Adds an edge between vertices a and b.
- * @details For instance, the complex contains edge 01 and 12, then calling
- * add_edge with vertex 0 and 2 will create a complex containing
- * the edges 01, 12, 20 but not the triangle 012 (and hence this complex
- * will contains a blocker 012).
- */
- Edge_handle add_edge(Vertex_handle a, Vertex_handle b) {
- // if the edge is already there we musnt go further
- // as we may add blockers that should not be here
- if (contains_edge(a, b))
- return *((*this)[std::make_pair(a, b)]);
- auto res = add_edge_without_blockers(a, b);
- add_blockers_after_simplex_insertion(Simplex(a, b));
- return res;
- }
-
- /**
- * @brief Adds all edges of s in the complex.
- */
- void add_edge(const Simplex& s) {
- for (auto i = s.begin(); i != s.end(); ++i)
- for (auto j = i; ++j != s.end(); /**/)
- add_edge(*i, *j);
- }
-
- /**
- * @brief Adds an edge between vertices a and b without blockers.
- * @details For instance, the complex contains edge 01 and 12, then calling
- * add_edge with vertex 0 and 2 will create a complex containing
- * the triangle 012.
- */
- Edge_handle add_edge_without_blockers(Vertex_handle a, Vertex_handle b) {
- assert(contains_vertex(a) && contains_vertex(b));
- assert(a != b);
-
- auto edge_handle((*this)[std::make_pair(a, b)]);
- if (!edge_handle) {
- edge_handle = boost::add_edge(a.vertex, b.vertex, skeleton).first;
- (*this)[*edge_handle].setId(get_id(a), get_id(b));
- degree_[a.vertex]++;
- degree_[b.vertex]++;
- if (visitor)
- visitor->on_add_edge_without_blockers(a, b);
- }
- return *edge_handle;
- }
-
- /**
- * @brief Adds all edges of s in the complex without adding blockers.
- */
- void add_edge_without_blockers(Simplex s) {
- for (auto i = s.begin(); i != s.end(); ++i) {
- for (auto j = i; ++j != s.end(); /**/)
- add_edge_without_blockers(*i, *j);
- }
- }
-
- /**
- * @brief Removes an edge from the simplicial complex and all its cofaces.
- * @details returns the former Edge_handle representing the edge
- */
- virtual Edge_handle remove_edge(Vertex_handle a, Vertex_handle b) {
- bool found;
- Edge_handle edge;
- tie(edge, found) = boost::edge(a.vertex, b.vertex, skeleton);
- if (found) {
- if (visitor)
- visitor->on_remove_edge(a, b);
- boost::remove_edge(a.vertex, b.vertex, skeleton);
- degree_[a.vertex]--;
- degree_[b.vertex]--;
- }
- return edge;
- }
-
- /**
- * @brief Removes edge and its cofaces from the simplicial complex.
- */
- void remove_edge(Edge_handle edge) {
- assert(contains_vertex(first_vertex(edge)));
- assert(contains_vertex(second_vertex(edge)));
- remove_edge(first_vertex(edge), second_vertex(edge));
- }
-
- /**
- * @brief The complex is reduced to its set of vertices.
- * All the edges and blockers are removed.
- */
- void keep_only_vertices() {
- remove_blockers();
-
- for (auto u : vertex_range()) {
- while (this->degree(u) > 0) {
- Vertex_handle v(*(adjacent_vertices(u.vertex, this->skeleton).first));
- this->remove_edge(u, v);
- }
- }
- }
-
- /**
- * @return true iff the simplicial complex contains an edge between
- * vertices a and b
- */
- bool contains_edge(Vertex_handle a, Vertex_handle b) const {
- // if (a.vertex<0 || b.vertex <0) return false;
- return boost::edge(a.vertex, b.vertex, skeleton).second;
- }
-
- /**
- * @return true iff the simplicial complex contains all vertices
- * and all edges of simplex sigma
- */
- bool contains_edges(const Simplex & sigma) const {
- for (auto i = sigma.begin(); i != sigma.end(); ++i) {
- if (!contains_vertex(*i))
- return false;
- for (auto j = i; ++j != sigma.end();) {
- if (!contains_edge(*i, *j))
- return false;
- }
- }
- return true;
- }
- //@}
-
- /////////////////////////////////////////////////////////////////////////////
- /** @name Blockers operations
- */
- //@{
-
- /**
- * @brief Adds the simplex to the set of blockers and
- * returns a Blocker_handle toward it if was not present before and 0 otherwise.
- */
- Blocker_handle add_blocker(const Simplex& blocker) {
- assert(blocker.dimension() > 1);
- if (contains_blocker(blocker)) {
- return 0;
- } else {
- if (visitor)
- visitor->on_add_blocker(blocker);
- Blocker_handle blocker_pt = new Simplex(blocker);
- num_blockers_++;
- auto vertex = blocker_pt->begin();
- while (vertex != blocker_pt->end()) {
- blocker_map_.insert(BlockerPair(*vertex, blocker_pt));
- ++vertex;
- }
- return blocker_pt;
- }
- }
-
- protected:
- /**
- * @brief Adds the simplex to the set of blockers
- */
- void add_blocker(Blocker_handle blocker) {
- if (contains_blocker(*blocker)) {
- // std::cerr << "ATTEMPT TO ADD A BLOCKER ALREADY THERE ---> BLOCKER IGNORED" << endl;
- return;
- } else {
- if (visitor)
- visitor->on_add_blocker(*blocker);
- num_blockers_++;
- auto vertex = blocker->begin();
- while (vertex != blocker->end()) {
- blocker_map_.insert(BlockerPair(*vertex, blocker));
- ++vertex;
- }
- }
- }
-
- protected:
- /**
- * Removes sigma from the blocker map of vertex v
- */
- void remove_blocker(const Blocker_handle sigma, Vertex_handle v) {
- Complex_blocker_around_vertex_iterator blocker;
- for (blocker = blocker_range(v).begin(); blocker != blocker_range(v).end();
- ++blocker) {
- if (*blocker == sigma)
- break;
- }
- if (*blocker != sigma) {
- std::cerr
- << "bug ((*blocker).second == sigma) ie try to remove a blocker not present\n";
- assert(false);
- } else {
- blocker_map_.erase(blocker.current_position());
- }
- }
-
- public:
- /**
- * @brief Removes the simplex from the set of blockers.
- * @remark sigma has to belongs to the set of blockers
- */
- void remove_blocker(const Blocker_handle sigma) {
- for (auto vertex : *sigma)
- remove_blocker(sigma, vertex);
- num_blockers_--;
- }
-
- /**
- * @brief Remove all blockers, in other words, it expand the simplicial
- * complex to the smallest flag complex that contains it.
- */
- void remove_blockers() {
- // Desallocate the blockers
- while (!blocker_map_.empty()) {
- delete_blocker(blocker_map_.begin()->second);
- }
- num_blockers_ = 0;
- blocker_map_.clear();
- }
-
- protected:
- /**
- * Removes the simplex sigma from the set of blockers.
- * sigma has to belongs to the set of blockers
- *
- * @remark contrarily to delete_blockers does not call the destructor
- */
- void remove_blocker(const Simplex& sigma) {
- assert(contains_blocker(sigma));
- for (auto vertex : sigma)
- remove_blocker(sigma, vertex);
- num_blockers_--;
- }
-
- public:
- /**
- * Removes the simplex s from the set of blockers
- * and desallocate s.
- */
- void delete_blocker(Blocker_handle sigma) {
- if (visitor)
- visitor->on_delete_blocker(sigma);
- remove_blocker(sigma);
- delete sigma;
- }
-
- /**
- * @return true iff s is a blocker of the simplicial complex
- */
- bool contains_blocker(const Blocker_handle s) const {
- if (s->dimension() < 2)
- return false;
-
- Vertex_handle a = s->first_vertex();
-
- for (const auto blocker : const_blocker_range(a)) {
- if (s == *blocker)
- return true;
- }
- return false;
- }
-
- /**
- * @return true iff s is a blocker of the simplicial complex
- */
- bool contains_blocker(const Simplex & s) const {
- if (s.dimension() < 2)
- return false;
-
- Vertex_handle a = s.first_vertex();
-
- for (auto blocker : const_blocker_range(a)) {
- if (s == *blocker)
- return true;
- }
- return false;
- }
-
- private:
- /**
- * @return true iff a blocker of the simplicial complex
- * is a face of sigma.
- */
- bool blocks(const Simplex & sigma) const {
- for (auto s : sigma)
- for (auto blocker : const_blocker_range(s))
- if (sigma.contains(*blocker))
- return true;
- return false;
- }
-
- //@}
-
- protected:
- /**
- * @details Adds to simplex the neighbours of v e.g. \f$ n \leftarrow n \cup N(v) \f$.
- * If keep_only_superior is true then only vertices that are greater than v are added.
- */
- virtual void add_neighbours(Vertex_handle v, Simplex & n,
- bool keep_only_superior = false) const {
- boost_adjacency_iterator ai, ai_end;
- for (tie(ai, ai_end) = adjacent_vertices(v.vertex, skeleton); ai != ai_end;
- ++ai) {
- Vertex_handle value(*ai);
- if (keep_only_superior) {
- if (value > v.vertex) {
- n.add_vertex(value);
- }
- } else {
- n.add_vertex(value);
- }
- }
- }
-
- /**
- * @details Add to simplex res all vertices which are
- * neighbours of alpha: ie \f$ res \leftarrow res \cup N(alpha) \f$.
- *
- * If 'keep_only_superior' is true then only vertices that are greater than alpha are added.
- * todo revoir
- *
- */
- virtual void add_neighbours(const Simplex &alpha, Simplex & res,
- bool keep_only_superior = false) const {
- res.clear();
- auto alpha_vertex = alpha.begin();
- add_neighbours(*alpha_vertex, res, keep_only_superior);
- for (alpha_vertex = (alpha.begin())++; alpha_vertex != alpha.end();
- ++alpha_vertex)
- keep_neighbours(*alpha_vertex, res, keep_only_superior);
- }
-
- /**
- * @details Remove from simplex n all vertices which are
- * not neighbours of v e.g. \f$ res \leftarrow res \cap N(v) \f$.
- * If 'keep_only_superior' is true then only vertices that are greater than v are keeped.
- */
- virtual void keep_neighbours(Vertex_handle v, Simplex& res,
- bool keep_only_superior = false) const {
- Simplex nv;
- add_neighbours(v, nv, keep_only_superior);
- res.intersection(nv);
- }
-
- /**
- * @details Remove from simplex all vertices which are
- * neighbours of v eg \f$ res \leftarrow res \setminus N(v) \f$.
- * If 'keep_only_superior' is true then only vertices that are greater than v are added.
- */
- virtual void remove_neighbours(Vertex_handle v, Simplex & res,
- bool keep_only_superior = false) const {
- Simplex nv;
- add_neighbours(v, nv, keep_only_superior);
- res.difference(nv);
- }
-
- public:
- typedef Skeleton_blocker_link_complex<Skeleton_blocker_complex> Link_complex;
-
- /**
- * Constructs the link of 'simplex' with points coordinates.
- */
- Link_complex link(Vertex_handle v) const {
- return Link_complex(*this, Simplex(v));
- }
-
- /**
- * Constructs the link of 'simplex' with points coordinates.
- */
- Link_complex link(Edge_handle edge) const {
- return Link_complex(*this, edge);
- }
-
- /**
- * Constructs the link of 'simplex' with points coordinates.
- */
- Link_complex link(const Simplex& simplex) const {
- return Link_complex(*this, simplex);
- }
-
- /**
- * @brief Compute the local vertices of 's' in the current complex
- * If one of them is not present in the complex then the return value is uninitialized.
- *
- *
- */
- // xxx rename get_address et place un using dans sub_complex
-
- boost::optional<Simplex> get_simplex_address(
- const Root_simplex_handle& s) const {
- boost::optional<Simplex> res;
-
- Simplex s_address;
- // Root_simplex_const_iterator i;
- for (auto i = s.begin(); i != s.end(); ++i) {
- boost::optional<Vertex_handle> address = get_address(*i);
- if (!address)
- return res;
- else
- s_address.add_vertex(*address);
- }
- res = s_address;
- return res;
- }
-
- /**
- * @brief returns a simplex with vertices which are the id of vertices of the
- * argument.
- */
- Root_simplex_handle get_id(const Simplex& local_simplex) const {
- Root_simplex_handle global_simplex;
- for (auto x = local_simplex.begin(); x != local_simplex.end(); ++x) {
- global_simplex.add_vertex(get_id(*x));
- }
- return global_simplex;
- }
-
- /**
- * @brief returns true iff the simplex s belongs to the simplicial
- * complex.
- */
- virtual bool contains(const Simplex & s) const {
- if (s.dimension() == -1) {
- return false;
- } else if (s.dimension() == 0) {
- return contains_vertex(s.first_vertex());
- } else {
- return (contains_edges(s) && !blocks(s));
- }
- }
-
- /*
- * @brief returnrs true iff the complex is empty.
- */
- bool empty() const {
- return num_vertices() == 0;
- }
-
- /*
- * @brief returns the number of vertices in the complex.
- */
- int num_vertices() const {
- // remark boost::num_vertices(skeleton) counts deactivated vertices
- return num_vertices_;
- }
-
- /*
- * @brief returns the number of edges in the complex.
- * @details currently in O(n)
- */
- // todo cache the value
-
- int num_edges() const {
- return boost::num_edges(skeleton);
- }
-
- int num_triangles() const {
- auto triangles = triangle_range();
- return std::distance(triangles.begin(), triangles.end());
- }
-
- /*
- * @brief returns the number of simplices of a given dimension in the complex.
- */
- size_t num_simplices() const {
- auto simplices = complex_simplex_range();
- return std::distance(simplices.begin(), simplices.end());
- }
-
- /*
- * @brief returns the number of simplices of a given dimension in the complex.
- */
- size_t num_simplices(int dimension) const {
- // TODO(DS): iterator on k-simplices
- size_t res = 0;
- for (const auto& s : complex_simplex_range())
- if (s.dimension() == dimension)
- ++res;
- return res;
- }
-
- /*
- * @brief returns the number of blockers in the complex.
- */
- size_t num_blockers() const {
- return num_blockers_;
- }
-
- /*
- * @brief returns true iff the graph of the 1-skeleton of the complex is complete.
- */
- bool complete() const {
- return (num_vertices() * (num_vertices() - 1)) / 2 == num_edges();
- }
-
- /**
- * @brief returns the number of connected components in the graph of the 1-skeleton.
- */
- int num_connected_components() const {
- int num_vert_collapsed = skeleton.vertex_set().size() - num_vertices();
- std::vector<int> component(skeleton.vertex_set().size());
- return boost::connected_components(this->skeleton, &component[0])
- - num_vert_collapsed;
- }
-
- /**
- * @brief %Test if the complex is a cone.
- * @details Runs in O(n) where n is the number of vertices.
- */
- bool is_cone() const {
- if (num_vertices() == 0)
- return false;
- if (num_vertices() == 1)
- return true;
- for (auto vi : vertex_range()) {
- // xxx todo faire une methode bool is_in_blocker(Vertex_handle)
- if (blocker_map_.find(vi) == blocker_map_.end()) {
- // no blocker passes through the vertex, we just need to
- // check if the current vertex is linked to all others vertices of the complex
- if (degree_[vi.vertex] == num_vertices() - 1)
- return true;
- }
- }
- return false;
- }
-
- //@}
- /** @name Simplification operations
- */
- //@{
-
- /**
- * Returns true iff the blocker 'sigma' is popable.
- * To define popable, let us call 'L' the complex that
- * consists in the current complex without the blocker 'sigma'.
- * A blocker 'sigma' is then "popable" if the link of 'sigma'
- * in L is reducible.
- *
- */
- bool is_popable_blocker(Blocker_handle sigma) const;
-
- /**
- * Removes all the popable blockers of the complex and delete them.
- * @returns the number of popable blockers deleted
- */
- void remove_popable_blockers();
-
- /**
- * Removes all the popable blockers of the complex passing through v and delete them.
- */
- void remove_popable_blockers(Vertex_handle v);
-
- /**
- * @brief Removes all the popable blockers of the complex passing through v and delete them.
- * Also remove popable blockers in the neighborhood if they became popable.
- *
- */
- void remove_all_popable_blockers(Vertex_handle v);
-
- /**
- * Remove the star of the vertex 'v'
- */
- void remove_star(Vertex_handle v);
-
- private:
- /**
- * after removing the star of a simplex, blockers sigma that contains this simplex must be removed.
- * Furthermore, all simplices tau of the form sigma \setminus simplex_to_be_removed must be added
- * whenever the dimension of tau is at least 2.
- */
- void update_blockers_after_remove_star_of_vertex_or_edge(const Simplex& simplex_to_be_removed);
-
- public:
- /**
- * Remove the star of the edge connecting vertices a and b.
- * @returns the number of blocker that have been removed
- */
- void remove_star(Vertex_handle a, Vertex_handle b);
-
- /**
- * Remove the star of the edge 'e'.
- */
- void remove_star(Edge_handle e);
-
- /**
- * Remove the star of the simplex 'sigma' which needs to belong to the complex
- */
- void remove_star(const Simplex& sigma);
-
- /**
- * @brief add a simplex and all its faces.
- * @details the simplex must have dimension greater than one (otherwise use add_vertex or add_edge_without_blockers).
- */
- void add_simplex(const Simplex& sigma);
-
- private:
- void add_blockers_after_simplex_insertion(Simplex s);
-
- /**
- * remove all blockers that contains sigma
- */
- void remove_blocker_containing_simplex(const Simplex& sigma);
-
- /**
- * remove all blockers that contains sigma
- */
- void remove_blocker_include_in_simplex(const Simplex& sigma);
-
- public:
- enum simplifiable_status {
- NOT_HOMOTOPY_EQ, MAYBE_HOMOTOPY_EQ, HOMOTOPY_EQ
- };
-
- simplifiable_status is_remove_star_homotopy_preserving(const Simplex& simplex) {
- // todo write a virtual method 'link' in Skeleton_blocker_complex which will be overloaded by the current one of
- // Skeleton_blocker_geometric_complex
- // then call it there to build the link and return the value of link.is_contractible()
- return MAYBE_HOMOTOPY_EQ;
- }
-
- enum contractible_status {
- NOT_CONTRACTIBLE, MAYBE_CONTRACTIBLE, CONTRACTIBLE
- };
-
- /**
- * @brief %Test if the complex is reducible using a strategy defined in the class
- * (by default it tests if the complex is a cone)
- * @details Note that NO could be returned if some invariant ensures that the complex
- * is not a point (for instance if the euler characteristic is different from 1).
- * This function will surely have to return MAYBE in some case because the
- * associated problem is undecidable but it in practice, it can often
- * be solved with the help of geometry.
- */
- virtual contractible_status is_contractible() const {
- if (this->is_cone()) {
- return CONTRACTIBLE;
- } else {
- return MAYBE_CONTRACTIBLE;
- }
- }
- //@}
-
- /** @name Edge contraction operations
- */
- //@{
-
- /**
- * @return If ignore_popable_blockers is true
- * then the result is true iff the link condition at edge ab is satisfied
- * or equivalently iff no blocker contains ab.
- * If ignore_popable_blockers is false then the
- * result is true iff all blocker containing ab are popable.
- */
- bool link_condition(Vertex_handle a, Vertex_handle b, bool ignore_popable_blockers = false) const {
- for (auto blocker : this->const_blocker_range(a))
- if (blocker->contains(b)) {
- // false if ignore_popable_blockers is false
- // otherwise the blocker has to be popable
- return ignore_popable_blockers && is_popable_blocker(blocker);
- }
- return true;
- }
-
- /**
- * @return If ignore_popable_blockers is true
- * then the result is true iff the link condition at edge ab is satisfied
- * or equivalently iff no blocker contains ab.
- * If ignore_popable_blockers is false then the
- * result is true iff all blocker containing ab are popable.
- */
- bool link_condition(Edge_handle e, bool ignore_popable_blockers = false) const {
- const Graph_edge& edge = (*this)[e];
- assert(this->get_address(edge.first()));
- assert(this->get_address(edge.second()));
- Vertex_handle a(*this->get_address(edge.first()));
- Vertex_handle b(*this->get_address(edge.second()));
- return link_condition(a, b, ignore_popable_blockers);
- }
-
- protected:
- /**
- * Compute simplices beta such that a.beta is an order 0 blocker
- * that may be used to construct a new blocker after contracting ab.
- * It requires that the link condition is satisfied.
- */
- void tip_blockers(Vertex_handle a, Vertex_handle b, std::vector<Simplex> & buffer) const;
-
- private:
- /**
- * @brief "Replace" the edge 'bx' by the edge 'ax'.
- * Assume that the edge 'bx' was present whereas 'ax' was not.
- * Precisely, it does not replace edges, but remove 'bx' and then add 'ax'.
- * The visitor 'on_swaped_edge' is called just after edge 'ax' had been added
- * and just before edge 'bx' had been removed. That way, it can
- * eventually access to information of 'ax'.
- */
- void swap_edge(Vertex_handle a, Vertex_handle b, Vertex_handle x);
-
- private:
- /**
- * @brief removes all blockers passing through the edge 'ab'
- */
- void delete_blockers_around_vertex(Vertex_handle v);
-
- /**
- * @brief removes all blockers passing through the edge 'ab'
- */
- void delete_blockers_around_edge(Vertex_handle a, Vertex_handle b);
-
- public:
- /**
- * Contracts the edge.
- * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
- * it removes first all blockers passing through 'ab'
- */
- void contract_edge(Edge_handle edge) {
- contract_edge(this->first_vertex(edge), this->second_vertex(edge));
- }
-
- /**
- * Contracts the edge connecting vertices a and b.
- * @remark If the link condition Link(ab) = Link(a) inter Link(b) is not satisfied,
- * it removes first all blockers passing through 'ab'
- */
- void contract_edge(Vertex_handle a, Vertex_handle b);
-
- private:
- void get_blockers_to_be_added_after_contraction(Vertex_handle a, Vertex_handle b,
- std::set<Simplex>& blockers_to_add);
- /**
- * delete all blockers that passes through a or b
- */
- void delete_blockers_around_vertices(Vertex_handle a, Vertex_handle b);
- void update_edges_after_contraction(Vertex_handle a, Vertex_handle b);
- void notify_changed_edges(Vertex_handle a);
- //@}
-
- public:
- /////////////////////////////////////////////////////////////////////////////
- /** @name Vertex iterators
- */
- //@{
- typedef Vertex_iterator<Skeleton_blocker_complex> Complex_vertex_iterator;
-
- //
- // Range over the vertices of the simplicial complex.
- // Methods .begin() and .end() return a Complex_vertex_iterator.
- //
- typedef boost::iterator_range<Complex_vertex_iterator> Complex_vertex_range;
-
- /**
- * @brief Returns a Complex_vertex_range over all vertices of the complex
- */
- Complex_vertex_range vertex_range() const {
- auto begin = Complex_vertex_iterator(this);
- auto end = Complex_vertex_iterator(this, 0);
- return Complex_vertex_range(begin, end);
- }
-
- typedef Neighbors_vertices_iterator<Skeleton_blocker_complex> Complex_neighbors_vertices_iterator;
-
-
- typedef boost::iterator_range<Complex_neighbors_vertices_iterator> Complex_neighbors_vertices_range;
-
- /**
- * @brief Returns a Complex_edge_range over all edges of the simplicial complex that passes trough v
- */
- Complex_neighbors_vertices_range vertex_range(Vertex_handle v) const {
- auto begin = Complex_neighbors_vertices_iterator(this, v);
- auto end = Complex_neighbors_vertices_iterator(this, v, 0);
- return Complex_neighbors_vertices_range(begin, end);
- }
-
- //@}
-
- /** @name Edge iterators
- */
- //@{
-
- typedef Edge_iterator<Skeleton_blocker_complex> Complex_edge_iterator;
-
-
- typedef boost::iterator_range<Complex_edge_iterator> Complex_edge_range;
-
- /**
- * @brief Returns a Complex_edge_range over all edges of the simplicial complex
- */
- Complex_edge_range edge_range() const {
- auto begin = Complex_edge_iterator(this);
- auto end = Complex_edge_iterator(this, 0);
- return Complex_edge_range(begin, end);
- }
-
-
- typedef Edge_around_vertex_iterator<Skeleton_blocker_complex> Complex_edge_around_vertex_iterator;
-
-
- typedef boost::iterator_range <Complex_edge_around_vertex_iterator> Complex_edge_around_vertex_range;
-
- /**
- * @brief Returns a Complex_edge_range over all edges of the simplicial complex that passes
- * through 'v'
- */
- Complex_edge_around_vertex_range edge_range(Vertex_handle v) const {
- auto begin = Complex_edge_around_vertex_iterator(this, v);
- auto end = Complex_edge_around_vertex_iterator(this, v, 0);
- return Complex_edge_around_vertex_range(begin, end);
- }
-
- //@}
-
- /** @name Triangles iterators
- */
- //@{
- private:
- typedef Skeleton_blocker_link_complex<Skeleton_blocker_complex<SkeletonBlockerDS> > Link;
- typedef Skeleton_blocker_link_superior<Skeleton_blocker_complex<SkeletonBlockerDS> > Superior_link;
-
- public:
- typedef Triangle_around_vertex_iterator<Skeleton_blocker_complex, Superior_link>
- Superior_triangle_around_vertex_iterator;
- typedef boost::iterator_range < Triangle_around_vertex_iterator<Skeleton_blocker_complex, Link> >
- Complex_triangle_around_vertex_range;
-
- /**
- * @brief Range over triangles around a vertex of the simplicial complex.
- * Methods .begin() and .end() return a Triangle_around_vertex_iterator.
- *
- */
- Complex_triangle_around_vertex_range triangle_range(Vertex_handle v) const {
- auto begin = Triangle_around_vertex_iterator<Skeleton_blocker_complex, Link>(this, v);
- auto end = Triangle_around_vertex_iterator<Skeleton_blocker_complex, Link>(this, v, 0);
- return Complex_triangle_around_vertex_range(begin, end);
- }
-
- typedef boost::iterator_range<Triangle_iterator<Skeleton_blocker_complex> > Complex_triangle_range;
- typedef Triangle_iterator<Skeleton_blocker_complex> Complex_triangle_iterator;
-
- /**
- * @brief Range over triangles of the simplicial complex.
- * Methods .begin() and .end() return a Triangle_around_vertex_iterator.
- *
- */
- Complex_triangle_range triangle_range() const {
- auto end = Triangle_iterator<Skeleton_blocker_complex>(this, 0);
- if (empty()) {
- return Complex_triangle_range(end, end);
- } else {
- auto begin = Triangle_iterator<Skeleton_blocker_complex>(this);
- return Complex_triangle_range(begin, end);
- }
- }
-
- //@}
-
- /** @name Simplices iterators
- */
- //@{
- typedef Simplex_around_vertex_iterator<Skeleton_blocker_complex, Link> Complex_simplex_around_vertex_iterator;
-
- /**
- * @brief Range over the simplices of the simplicial complex around a vertex.
- * Methods .begin() and .end() return a Complex_simplex_around_vertex_iterator.
- */
- typedef boost::iterator_range < Complex_simplex_around_vertex_iterator > Complex_simplex_around_vertex_range;
-
- /**
- * @brief Returns a Complex_simplex_around_vertex_range over all the simplices around a vertex of the complex
- */
- Complex_simplex_around_vertex_range star_simplex_range(Vertex_handle v) const {
- assert(contains_vertex(v));
- return Complex_simplex_around_vertex_range(
- Complex_simplex_around_vertex_iterator(this, v),
- Complex_simplex_around_vertex_iterator(this, v, true));
- }
- typedef Simplex_coboundary_iterator<Skeleton_blocker_complex, Link> Complex_simplex_coboundary_iterator;
-
- /**
- * @brief Range over the simplices of the coboundary of a simplex.
- * Methods .begin() and .end() return a Complex_simplex_coboundary_iterator.
- */
- typedef boost::iterator_range < Complex_simplex_coboundary_iterator > Complex_coboundary_range;
-
- /**
- * @brief Returns a Complex_simplex_coboundary_iterator over the simplices of the coboundary of a simplex.
- */
- Complex_coboundary_range coboundary_range(const Simplex& s) const {
- assert(contains(s));
- return Complex_coboundary_range(Complex_simplex_coboundary_iterator(this, s),
- Complex_simplex_coboundary_iterator(this, s, true));
- }
-
- // typedef Simplex_iterator<Skeleton_blocker_complex,Superior_link> Complex_simplex_iterator;
- typedef Simplex_iterator<Skeleton_blocker_complex> Complex_simplex_iterator;
-
- typedef boost::iterator_range < Complex_simplex_iterator > Complex_simplex_range;
-
- /**
- * @brief Returns a Complex_simplex_range over all the simplices of the complex
- */
- Complex_simplex_range complex_simplex_range() const {
- Complex_simplex_iterator end(this, true);
- if (empty()) {
- return Complex_simplex_range(end, end);
- } else {
- Complex_simplex_iterator begin(this);
- return Complex_simplex_range(begin, end);
- }
- }
-
- //@}
-
- /** @name Blockers iterators
- */
- //@{
- private:
- /**
- * @brief Iterator over the blockers adjacent to a vertex
- */
- typedef Blocker_iterator_around_vertex_internal<
- typename std::multimap<Vertex_handle, Simplex *>::iterator,
- Blocker_handle>
- Complex_blocker_around_vertex_iterator;
-
- /**
- * @brief Iterator over (constant) blockers adjacent to a vertex
- */
- typedef Blocker_iterator_around_vertex_internal<
- typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
- const Blocker_handle>
- Const_complex_blocker_around_vertex_iterator;
-
- typedef boost::iterator_range <Complex_blocker_around_vertex_iterator> Complex_blocker_around_vertex_range;
- typedef boost::iterator_range <Const_complex_blocker_around_vertex_iterator>
- Const_complex_blocker_around_vertex_range;
-
- public:
- /**
- * @brief Returns a range of the blockers of the complex passing through a vertex
- */
- Complex_blocker_around_vertex_range blocker_range(Vertex_handle v) {
- auto begin = Complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
- auto end = Complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
- return Complex_blocker_around_vertex_range(begin, end);
- }
-
- /**
- * @brief Returns a range of the blockers of the complex passing through a vertex
- */
- Const_complex_blocker_around_vertex_range const_blocker_range(Vertex_handle v) const {
- auto begin = Const_complex_blocker_around_vertex_iterator(blocker_map_.lower_bound(v));
- auto end = Const_complex_blocker_around_vertex_iterator(blocker_map_.upper_bound(v));
- return Const_complex_blocker_around_vertex_range(begin, end);
- }
-
- private:
- /**
- * @brief Iterator over the blockers.
- */
- typedef Blocker_iterator_internal<
- typename std::multimap<Vertex_handle, Simplex *>::iterator,
- Blocker_handle>
- Complex_blocker_iterator;
-
- /**
- * @brief Iterator over the (constant) blockers.
- */
- typedef Blocker_iterator_internal<
- typename std::multimap<Vertex_handle, Simplex *>::const_iterator,
- const Blocker_handle>
- Const_complex_blocker_iterator;
-
- typedef boost::iterator_range <Complex_blocker_iterator> Complex_blocker_range;
- typedef boost::iterator_range <Const_complex_blocker_iterator> Const_complex_blocker_range;
-
- public:
- /**
- * @brief Returns a range of the blockers of the complex
- */
- Complex_blocker_range blocker_range() {
- auto begin = Complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end());
- auto end = Complex_blocker_iterator(blocker_map_.end(), blocker_map_.end());
- return Complex_blocker_range(begin, end);
- }
-
- /**
- * @brief Returns a range of the blockers of the complex
- */
- Const_complex_blocker_range const_blocker_range() const {
- auto begin = Const_complex_blocker_iterator(blocker_map_.begin(), blocker_map_.end());
- auto end = Const_complex_blocker_iterator(blocker_map_.end(), blocker_map_.end());
- return Const_complex_blocker_range(begin, end);
- }
-
- //@}
-
- /////////////////////////////////////////////////////////////////////////////
- /** @name Print and IO methods
- */
- //@{
- public:
- std::string to_string() const {
- std::ostringstream stream;
- stream << num_vertices() << " vertices:\n" << vertices_to_string() << std::endl;
- stream << num_edges() << " edges:\n" << edges_to_string() << std::endl;
- stream << num_blockers() << " blockers:\n" << blockers_to_string() << std::endl;
- return stream.str();
- }
-
- std::string vertices_to_string() const {
- std::ostringstream stream;
- for (auto vertex : vertex_range()) {
- stream << "{" << (*this)[vertex].get_id() << "} ";
- }
- stream << std::endl;
- return stream.str();
- }
-
- std::string edges_to_string() const {
- std::ostringstream stream;
- for (auto edge : edge_range())
- stream << "{" << (*this)[edge].first() << "," << (*this)[edge].second() << "} ";
- stream << std::endl;
- return stream.str();
- }
-
- std::string blockers_to_string() const {
- std::ostringstream stream;
-
- for (auto b : const_blocker_range())
- stream << *b << std::endl;
- return stream.str();
- }
- //@}
-};
-
-/**
- * build a simplicial complex from a collection
- * of top faces.
- * return the total number of simplices
- */
-template<typename Complex, typename SimplexHandleIterator>
-Complex make_complex_from_top_faces(SimplexHandleIterator simplices_begin, SimplexHandleIterator simplices_end,
- bool is_flag_complex = false) {
- // TODO(DS): use add_simplex instead! should be more efficient and more elegant :)
- typedef typename Complex::Simplex Simplex;
- std::vector<Simplex> simplices;
- for (auto top_face = simplices_begin; top_face != simplices_end; ++top_face) {
- auto subfaces_topface = subfaces(*top_face);
- simplices.insert(simplices.end(), subfaces_topface.begin(), subfaces_topface.end());
- }
- return Complex(simplices.begin(), simplices.end(), is_flag_complex);
-}
-
-} // namespace skeleton_blocker
-
-namespace skbl = skeleton_blocker;
-
-} // namespace Gudhi
-
-#include "Skeleton_blocker_simplifiable_complex.h"
-
-#endif // SKELETON_BLOCKER_COMPLEX_H_