/* 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 . */ #ifndef GUDHI_SKELETON_BLOCKER_SIMPLEX_H #define GUDHI_SKELETON_BLOCKER_SIMPLEX_H #include #include #include #include #include namespace Gudhi{ namespace skbl { /** *@brief Abstract simplex used in Skeleton blockers data-structure. * * An abstract simplex is represented as an ordered set of T elements, * each element representing a vertex. * * The element representing a vertex can be SkeletonBlockerDS::Vertex_handle or SkeletonBlockerDS::Root_vertex_handle. * * */ template class Skeleton_blocker_simplex { private : std::set simplex_set; public: typedef typename T::boost_vertex_handle boost_vertex_handle; typedef T Vertex_handle; typedef typename std::set::const_iterator Simplex_vertex_const_iterator; typedef typename std::set::iterator Simplex_vertex_iterator; /** @name Constructors / Destructors / Initialization */ //@{ // Skeleton_blocker_simplex():simplex_set() {} /** * Clear the simplex */ void clear() { simplex_set.clear(); } Skeleton_blocker_simplex(std::initializer_list& list) { for_each(list.begin(),list.end(),add_vertex); } template Skeleton_blocker_simplex(Args... args){ add_vertices(args...); } template void add_vertices(T v,Args... args){ add_vertex(v); add_vertices(args...); } void add_vertices(T v){ add_vertex(v); } void add_vertices(){ } /** * Initialize a simplex with a string such as {0,1,2} */ Skeleton_blocker_simplex(std::string token){ clear(); if ((token[0] == '{') && (token[token.size()-1] == '}' ) ) { token.erase(0,1); token.erase(token.size()-1,1); while(token.size()!=0 ){ int coma_position=token.find_first_of(','); //cout << "coma_position:"< v; v.reserve(std::min(simplex_set.size(), a.simplex_set.size())); set_intersection(simplex_set.begin(),simplex_set.end(), a.simplex_set.begin(),a.simplex_set.end(), std::back_inserter(v)); clear(); for (auto i:v) simplex_set.insert(i); } /** * Substracts a from the simplex: * \f$ (*this) \leftarrow (*this) \setminus a \f$ */ void difference(const Skeleton_blocker_simplex & a){ std::vector v; v.reserve(simplex_set.size()); set_difference(simplex_set.begin(),simplex_set.end(), a.simplex_set.begin(),a.simplex_set.end(), std::back_inserter(v)); clear(); for (auto i:v) simplex_set.insert(i); } /** * Add vertices of a to the simplex: * \f$ (*this) \leftarrow (*this) \cup a \f$ */ void union_vertices(const Skeleton_blocker_simplex & a){ std::vector v; v.reserve(simplex_set.size() + a.simplex_set.size()); set_union(simplex_set.begin(),simplex_set.end(), a.simplex_set.begin(),a.simplex_set.end(), std::back_inserter(v)); clear(); simplex_set.insert(v.begin(),v.end()); } typename std::set::const_iterator begin() const{ return simplex_set.cbegin(); } typename std::set::const_iterator end() const{ return simplex_set.cend(); } typename std::set::iterator begin(){ return simplex_set.begin(); } typename std::set::iterator end(){ return simplex_set.end(); } //@} /** @name Queries */ //@{ /** * Returns the dimension of the simplex. */ int dimension() const{ return (simplex_set.size() - 1); } bool empty() const{ return simplex_set.empty(); } /** * Returns the first vertex of the (oriented) simplex. * * Be careful : assumes the simplex is non-empty. */ T first_vertex() const{ assert(!empty()); return *(begin()); } /** * Returns the last vertex of the (oriented) simplex. * * Be careful : assumes the simplex is non-empty. */ T last_vertex() const { assert(!empty()); return *(simplex_set.rbegin()); } /** * @return true iff the simplex contains the simplex a, i.e. iff \f$ a \subset (*this) \f$. */ bool contains(const Skeleton_blocker_simplex & a) const{ return includes(simplex_set.cbegin(),simplex_set.cend(),a.simplex_set.cbegin(),a.simplex_set.cend()); } /** * @return true iff the simplex contains the difference \f$ a \setminus b \f$. */ bool contains_difference(const Skeleton_blocker_simplex& a, const Skeleton_blocker_simplex& b) const{ auto first1 = begin(); auto last1 = end(); auto first2 = a.begin(); auto last2 = a.end(); while (first2!=last2) { // we ignore vertices of b if(b.contains(*first2)){ ++first2; } else{ if ( (first1==last1) || (*first2<*first1) ) return false; if (!(*first1<*first2)) ++first2; ++first1; } } return true; } /** * @return true iff the simplex contains the difference \f$ a \setminus \{ x \} \f$. */ bool contains_difference(const Skeleton_blocker_simplex& a, T x) const{ auto first1 = begin(); auto last1 = end(); auto first2 = a.begin(); auto last2 = a.end(); while (first2!=last2) { // we ignore vertices of b if(x == *first2){ ++first2; } else{ if ( (first1==last1) || (*first2<*first1) ) return false; if (!(*first1<*first2)) ++first2; ++first1; } } return true; } /** * @return true iff the simplex contains the difference \f$ a \setminus \{ x \} \f$. */ bool contains_difference(const Skeleton_blocker_simplex& a, T x, T y) const{ auto first1 = begin(); auto last1 = end(); auto first2 = a.begin(); auto last2 = a.end(); while (first2!=last2) { // we ignore vertices of b if(x == *first2 || y == *first2){ ++first2; } else{ if ( (first1==last1) || (*first2<*first1) ) return false; if (!(*first1<*first2)) ++first2; ++first1; } } return true; } /** * @return true iff the simplex contains the vertex v, i.e. iff \f$ v \in (*this) \f$. */ bool contains(T v) const{ return (simplex_set.find(v) != simplex_set.end()); } /** * @return \f$ (*this) \cap a = \emptyset \f$. */ bool disjoint(const Skeleton_blocker_simplex& a) const{ std::vector v; v.reserve(std::min(simplex_set.size(), a.simplex_set.size())); set_intersection(simplex_set.cbegin(),simplex_set.cend(), a.simplex_set.cbegin(),a.simplex_set.cend(), std::back_inserter(v)); return (v.size()==0); } bool operator==(const Skeleton_blocker_simplex& other) const{ return (this->simplex_set == other.simplex_set); } bool operator!=(const Skeleton_blocker_simplex& other) const{ return (this->simplex_set != other.simplex_set); } bool operator<(const Skeleton_blocker_simplex& other) const{ return (std::lexicographical_compare(this->simplex_set.begin(),this->simplex_set.end(), other.begin(),other.end())); } //@} /** * Display a simplex */ friend std::ostream& operator << (std::ostream& o, const Skeleton_blocker_simplex & sigma) { bool first = true; o << "{"; for(auto i : sigma) { if(first) first = false ; else o << ","; o << i; } o << "}"; return o; } }; } } // namespace GUDHI #endif