diff options
Diffstat (limited to 'src/Nerve_GIC')
-rw-r--r-- | src/Nerve_GIC/doc/Intro_graph_induced_complex.h | 2 | ||||
-rw-r--r-- | src/Nerve_GIC/example/GIC.cpp | 68 | ||||
-rw-r--r-- | src/Nerve_GIC/example/GICvoronoi.cpp | 68 | ||||
-rw-r--r-- | src/Nerve_GIC/example/MapperDeltaCoord.cpp | 72 | ||||
-rw-r--r-- | src/Nerve_GIC/example/MapperDeltaFunc.cpp | 72 | ||||
-rw-r--r-- | src/Nerve_GIC/example/MapperDeltaFunc.dot | 10 | ||||
-rw-r--r-- | src/Nerve_GIC/example/MapperDeltaFunc.txt | 10 | ||||
-rw-r--r-- | src/Nerve_GIC/example/Nerve.cpp | 74 | ||||
-rw-r--r-- | src/Nerve_GIC/include/gudhi/GIC.h | 127 | ||||
-rw-r--r-- | src/Nerve_GIC/test/test_GIC.cpp | 4 |
10 files changed, 307 insertions, 200 deletions
diff --git a/src/Nerve_GIC/doc/Intro_graph_induced_complex.h b/src/Nerve_GIC/doc/Intro_graph_induced_complex.h index 3a6c6c85..95c0ca40 100644 --- a/src/Nerve_GIC/doc/Intro_graph_induced_complex.h +++ b/src/Nerve_GIC/doc/Intro_graph_induced_complex.h @@ -173,7 +173,7 @@ namespace graph_induced_complex { * * the program output is: * - * \include MapperDeltaFunc.txt + * \include MapperDeltaFunc.dot * * \copyright GNU General Public License v3. * \verbatim Contact: gudhi-users@lists.gforge.inria.fr \endverbatim diff --git a/src/Nerve_GIC/example/GIC.cpp b/src/Nerve_GIC/example/GIC.cpp index 1889cb33..0f50f712 100644 --- a/src/Nerve_GIC/example/GIC.cpp +++ b/src/Nerve_GIC/example/GIC.cpp @@ -1,3 +1,25 @@ +/* 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): Mathieu Carrière + * + * Copyright (C) 2017 INRIA Saclay (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/>. + */ + #include <gudhi/GIC.h> void usage(int nbArgs, char * const progName) { @@ -24,40 +46,44 @@ int main(int argc, char **argv) { Gudhi::graph_induced_complex::Graph_induced_complex GIC; GIC.set_verbose(verb); - GIC.read_point_cloud(off_file_name); + bool check = GIC.read_point_cloud(off_file_name); - GIC.set_color_from_coordinate(coord); - GIC.set_function_from_coordinate(coord); + if(!check) std::cout << "Incorrect OFF file." << std::endl; + else{ - GIC.set_graph_from_rips(threshold); + GIC.set_color_from_coordinate(coord); + GIC.set_function_from_coordinate(coord); - GIC.set_resolution_double(resolution); GIC.set_gain(gain); - GIC.set_cover_from_function(1); + GIC.set_graph_from_rips(threshold); - GIC.find_GIC_simplices(); + GIC.set_resolution_double(resolution); GIC.set_gain(gain); + GIC.set_cover_from_function(1); - GIC.plot_with_KeplerMapper(); + GIC.find_GIC_simplices(); - Simplex_tree stree; GIC.create_complex(stree); + GIC.plot_txt(); - std::streambuf* streambufffer = std::cout.rdbuf(); - std::ostream output_stream(streambufffer); + Simplex_tree stree; GIC.create_complex(stree); - // ---------------------------------------------------------------------------- - // Display information about the graph induced complex - // ---------------------------------------------------------------------------- + std::streambuf* streambufffer = std::cout.rdbuf(); + std::ostream output_stream(streambufffer); + + // ---------------------------------------------------------------------------- + // Display information about the graph induced complex + // ---------------------------------------------------------------------------- - if(verb){ - output_stream << "Graph induced complex is of dimension " << stree.dimension() << + if(verb){ + output_stream << "Graph induced complex is of dimension " << stree.dimension() << " - " << stree.num_simplices() << " simplices - " << stree.num_vertices() << " vertices." << std::endl; - output_stream << "Iterator on graph induced complex simplices" << std::endl; - for (auto f_simplex : stree.filtration_simplex_range()) { - for (auto vertex : stree.simplex_vertex_range(f_simplex)) { - output_stream << vertex << " "; + output_stream << "Iterator on graph induced complex simplices" << std::endl; + for (auto f_simplex : stree.filtration_simplex_range()) { + for (auto vertex : stree.simplex_vertex_range(f_simplex)) { + output_stream << vertex << " "; + } + output_stream << std::endl; } - output_stream << std::endl; } } diff --git a/src/Nerve_GIC/example/GICvoronoi.cpp b/src/Nerve_GIC/example/GICvoronoi.cpp index 9bf3de5e..8061c42d 100644 --- a/src/Nerve_GIC/example/GICvoronoi.cpp +++ b/src/Nerve_GIC/example/GICvoronoi.cpp @@ -1,3 +1,25 @@ +/* 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): Mathieu Carrière + * + * Copyright (C) 2017 INRIA Saclay (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/>. + */ + #include <gudhi/GIC.h> void usage(int nbArgs, char * const progName) { @@ -21,38 +43,42 @@ int main(int argc, char **argv) { Gudhi::graph_induced_complex::Graph_induced_complex GIC; GIC.set_verbose(verb); - GIC.read_point_cloud(off_file_name); + bool check = GIC.read_point_cloud(off_file_name); - GIC.set_color_from_coordinate(); + if(!check) std::cout << "Incorrect OFF file." << std::endl; + else{ - GIC.set_graph_from_OFF(off_file_name); + GIC.set_color_from_coordinate(); - GIC.set_cover_from_Voronoi(m); + GIC.set_graph_from_OFF(off_file_name); - GIC.find_GIC_simplices(); + GIC.set_cover_from_Voronoi(m); - GIC.plot_with_Geomview(); + GIC.find_GIC_simplices(); - Simplex_tree stree; GIC.create_complex(stree); + GIC.plot_OFF(); - std::streambuf* streambufffer = std::cout.rdbuf(); - std::ostream output_stream(streambufffer); + Simplex_tree stree; GIC.create_complex(stree); - // ---------------------------------------------------------------------------- - // Display information about the graph induced complex - // ---------------------------------------------------------------------------- + std::streambuf* streambufffer = std::cout.rdbuf(); + std::ostream output_stream(streambufffer); + + // ---------------------------------------------------------------------------- + // Display information about the graph induced complex + // ---------------------------------------------------------------------------- - if(verb){ - output_stream << "Graph induced complex is of dimension " << stree.dimension() << - " - " << stree.num_simplices() << " simplices - " << - stree.num_vertices() << " vertices." << std::endl; + if(verb){ + output_stream << "Graph induced complex is of dimension " << stree.dimension() << + " - " << stree.num_simplices() << " simplices - " << + stree.num_vertices() << " vertices." << std::endl; - output_stream << "Iterator on graph induced complex simplices" << std::endl; - for (auto f_simplex : stree.filtration_simplex_range()) { - for (auto vertex : stree.simplex_vertex_range(f_simplex)) { - output_stream << vertex << " "; + output_stream << "Iterator on graph induced complex simplices" << std::endl; + for (auto f_simplex : stree.filtration_simplex_range()) { + for (auto vertex : stree.simplex_vertex_range(f_simplex)) { + output_stream << vertex << " "; + } + output_stream << std::endl; } - output_stream << std::endl; } } diff --git a/src/Nerve_GIC/example/MapperDeltaCoord.cpp b/src/Nerve_GIC/example/MapperDeltaCoord.cpp index 9445e988..84a25bad 100644 --- a/src/Nerve_GIC/example/MapperDeltaCoord.cpp +++ b/src/Nerve_GIC/example/MapperDeltaCoord.cpp @@ -1,3 +1,25 @@ +/* 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): Mathieu Carrière + * + * Copyright (C) 2017 INRIA Saclay (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/>. + */ + #include <gudhi/GIC.h> void usage(int nbArgs, char * const progName) { @@ -21,40 +43,44 @@ int main(int argc, char **argv) { Gudhi::graph_induced_complex::Graph_induced_complex GIC; GIC.set_verbose(verb); - GIC.read_point_cloud(off_file_name); + bool check = GIC.read_point_cloud(off_file_name); + + if(!check) std::cout << "Incorrect OFF file." << std::endl; + else{ - GIC.set_color_from_coordinate(coord); - GIC.set_function_from_coordinate(coord); + GIC.set_color_from_coordinate(coord); + GIC.set_function_from_coordinate(coord); - GIC.set_graph_from_automatic_rips(); + GIC.set_graph_from_automatic_rips(); - GIC.set_automatic_resolution_for_GICMAP(); GIC.set_gain(); - GIC.set_cover_from_function(1); + GIC.set_automatic_resolution_for_GICMAP(); GIC.set_gain(); + GIC.set_cover_from_function(1); - GIC.find_GICMAP_simplices_with_functional_minimal_cover(); + GIC.find_GICMAP_simplices_with_functional_minimal_cover(); - GIC.plot_with_KeplerMapper(); + GIC.plot_txt(); - Simplex_tree stree; GIC.create_complex(stree); + Simplex_tree stree; GIC.create_complex(stree); - std::streambuf* streambufffer = std::cout.rdbuf(); - std::ostream output_stream(streambufffer); + std::streambuf* streambufffer = std::cout.rdbuf(); + std::ostream output_stream(streambufffer); - // ------------------------------------------ - // Display information about the Mapper Delta - // ------------------------------------------ + // ------------------------------------------ + // Display information about the Mapper Delta + // ------------------------------------------ - if(verb){ - output_stream << "Mapper Delta is of dimension " << stree.dimension() << - " - " << stree.num_simplices() << " simplices - " << - stree.num_vertices() << " vertices." << std::endl; + if(verb){ + output_stream << "Mapper Delta is of dimension " << stree.dimension() << + " - " << stree.num_simplices() << " simplices - " << + stree.num_vertices() << " vertices." << std::endl; - output_stream << "Iterator on Mapper Delta simplices" << std::endl; - for (auto f_simplex : stree.filtration_simplex_range()) { - for (auto vertex : stree.simplex_vertex_range(f_simplex)) { - output_stream << vertex << " "; + output_stream << "Iterator on Mapper Delta simplices" << std::endl; + for (auto f_simplex : stree.filtration_simplex_range()) { + for (auto vertex : stree.simplex_vertex_range(f_simplex)) { + output_stream << vertex << " "; + } + output_stream << std::endl; } - output_stream << std::endl; } } diff --git a/src/Nerve_GIC/example/MapperDeltaFunc.cpp b/src/Nerve_GIC/example/MapperDeltaFunc.cpp index 448323b1..fa95ca58 100644 --- a/src/Nerve_GIC/example/MapperDeltaFunc.cpp +++ b/src/Nerve_GIC/example/MapperDeltaFunc.cpp @@ -1,3 +1,25 @@ +/* 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): Mathieu Carrière + * + * Copyright (C) 2017 INRIA Saclay (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/>. + */ + #include <gudhi/GIC.h> void usage(int nbArgs, char * const progName) { @@ -21,40 +43,44 @@ int main(int argc, char **argv) { Gudhi::graph_induced_complex::Graph_induced_complex GIC; GIC.set_verbose(verb); - GIC.read_point_cloud(off_file_name); + bool check = GIC.read_point_cloud(off_file_name); + + if(!check) std::cout << "Incorrect OFF file." << std::endl; + else{ - GIC.set_color_from_file(func_file_name); - GIC.set_function_from_file(func_file_name); + GIC.set_color_from_file(func_file_name); + GIC.set_function_from_file(func_file_name); - GIC.set_graph_from_automatic_rips(); + GIC.set_graph_from_automatic_rips(); - GIC.set_automatic_resolution_for_GICMAP(); GIC.set_gain(); - GIC.set_cover_from_function(1); + GIC.set_automatic_resolution_for_GICMAP(); GIC.set_gain(); + GIC.set_cover_from_function(1); - GIC.find_GICMAP_simplices_with_functional_minimal_cover(); + GIC.find_GICMAP_simplices_with_functional_minimal_cover(); - GIC.plot_with_KeplerMapper(); + GIC.plot_pdf(); - Simplex_tree stree; GIC.create_complex(stree); + Simplex_tree stree; GIC.create_complex(stree); - std::streambuf* streambufffer = std::cout.rdbuf(); - std::ostream output_stream(streambufffer); + std::streambuf* streambufffer = std::cout.rdbuf(); + std::ostream output_stream(streambufffer); - // ------------------------------------------ - // Display information about the Mapper Delta - // ------------------------------------------ + // ------------------------------------------ + // Display information about the Mapper Delta + // ------------------------------------------ - if(verb){ - output_stream << "Mapper Delta is of dimension " << stree.dimension() << - " - " << stree.num_simplices() << " simplices - " << - stree.num_vertices() << " vertices." << std::endl; + if(verb){ + output_stream << "Mapper Delta is of dimension " << stree.dimension() << + " - " << stree.num_simplices() << " simplices - " << + stree.num_vertices() << " vertices." << std::endl; - output_stream << "Iterator on Mapper Delta simplices" << std::endl; - for (auto f_simplex : stree.filtration_simplex_range()) { - for (auto vertex : stree.simplex_vertex_range(f_simplex)) { - output_stream << vertex << " "; + output_stream << "Iterator on Mapper Delta simplices" << std::endl; + for (auto f_simplex : stree.filtration_simplex_range()) { + for (auto vertex : stree.simplex_vertex_range(f_simplex)) { + output_stream << vertex << " "; + } + output_stream << std::endl; } - output_stream << std::endl; } } diff --git a/src/Nerve_GIC/example/MapperDeltaFunc.dot b/src/Nerve_GIC/example/MapperDeltaFunc.dot new file mode 100644 index 00000000..beafa7f1 --- /dev/null +++ b/src/Nerve_GIC/example/MapperDeltaFunc.dot @@ -0,0 +1,10 @@ +graph Mapper { +0[shape=circle fontcolor=black color=black label="0:26" style=filled fillcolor="0, 1, 1"] +1[shape=circle fontcolor=black color=black label="1:4" style=filled fillcolor="0.240095, 1, 1"] +2[shape=circle fontcolor=black color=black label="2:11" style=filled fillcolor="0.209621, 1, 1"] +3[shape=circle fontcolor=black color=black label="3:42" style=filled fillcolor="0.6, 1, 1"] + 0 -- 1 [weight=15]; + 0 -- 2 [weight=15]; + 1 -- 3 [weight=15]; + 2 -- 3 [weight=15]; +}
\ No newline at end of file diff --git a/src/Nerve_GIC/example/MapperDeltaFunc.txt b/src/Nerve_GIC/example/MapperDeltaFunc.txt deleted file mode 100644 index d13d0695..00000000 --- a/src/Nerve_GIC/example/MapperDeltaFunc.txt +++ /dev/null @@ -1,10 +0,0 @@ -Mapper Delta is of dimension 1 - 8 simplices - 4 vertices. -Iterator on Mapper Delta simplices -0 -1 -1 0 -2 -2 0 -3 -3 1 -3 2 diff --git a/src/Nerve_GIC/example/Nerve.cpp b/src/Nerve_GIC/example/Nerve.cpp index 84f74625..8f8037d4 100644 --- a/src/Nerve_GIC/example/Nerve.cpp +++ b/src/Nerve_GIC/example/Nerve.cpp @@ -1,9 +1,31 @@ +/* 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): Mathieu Carrière + * + * Copyright (C) 2017 INRIA Saclay (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/>. + */ + #include <gudhi/GIC.h> void usage(int nbArgs, char * const progName) { std::cerr << "Error: Number of arguments (" << nbArgs << ") is not correct\n"; std::cerr << "Usage: " << progName << " filename.off coordinate resolution gain [--v] \n"; - std::cerr << " i.e.: " << progName << " ../../../../data/human.off 2 10 0.3 --v \n"; + std::cerr << " i.e.: " << progName << " ../../../../data/points/human.off 2 10 0.3 --v \n"; exit(-1); // ----- >> } @@ -23,40 +45,44 @@ int main(int argc, char **argv) { Gudhi::graph_induced_complex::Graph_induced_complex GIC; GIC.set_verbose(verb); - GIC.read_point_cloud(off_file_name); + bool check = GIC.read_point_cloud(off_file_name); + + if(!check) std::cout << "Incorrect OFF file." << std::endl; + else{ - GIC.set_color_from_coordinate(coord); - GIC.set_function_from_coordinate(coord); + GIC.set_color_from_coordinate(coord); + GIC.set_function_from_coordinate(coord); - GIC.set_graph_from_OFF(off_file_name); + GIC.set_graph_from_OFF(off_file_name); - GIC.set_resolution_int(resolution); GIC.set_gain(gain); - GIC.set_cover_from_function(0); + GIC.set_resolution_int(resolution); GIC.set_gain(gain); + GIC.set_cover_from_function(0); - GIC.find_Nerve_simplices(); + GIC.find_Nerve_simplices(); - GIC.plot_with_KeplerMapper(); + GIC.plot_txt(); - Simplex_tree stree; GIC.create_complex(stree); + Simplex_tree stree; GIC.create_complex(stree); - std::streambuf* streambufffer = std::cout.rdbuf(); - std::ostream output_stream(streambufffer); + std::streambuf* streambufffer = std::cout.rdbuf(); + std::ostream output_stream(streambufffer); - // ---------------------------------------------------------------------------- - // Display information about the graph induced complex - // ---------------------------------------------------------------------------- + // ---------------------------------------------------------------------------- + // Display information about the graph induced complex + // ---------------------------------------------------------------------------- - if(verb){ - output_stream << "Nerve is of dimension " << stree.dimension() << - " - " << stree.num_simplices() << " simplices - " << - stree.num_vertices() << " vertices." << std::endl; + if(verb){ + output_stream << "Nerve is of dimension " << stree.dimension() << + " - " << stree.num_simplices() << " simplices - " << + stree.num_vertices() << " vertices." << std::endl; - output_stream << "Iterator on Nerve simplices" << std::endl; - for (auto f_simplex : stree.filtration_simplex_range()) { - for (auto vertex : stree.simplex_vertex_range(f_simplex)) { - output_stream << vertex << " "; + output_stream << "Iterator on Nerve simplices" << std::endl; + for (auto f_simplex : stree.filtration_simplex_range()) { + for (auto vertex : stree.simplex_vertex_range(f_simplex)) { + output_stream << vertex << " "; + } + output_stream << std::endl; } - output_stream << std::endl; } } diff --git a/src/Nerve_GIC/include/gudhi/GIC.h b/src/Nerve_GIC/include/gudhi/GIC.h index d763b636..d670cef6 100644 --- a/src/Nerve_GIC/include/gudhi/GIC.h +++ b/src/Nerve_GIC/include/gudhi/GIC.h @@ -30,10 +30,6 @@ #include <gudhi/Rips_complex.h> #include <gudhi/Points_off_io.h> #include <gudhi/distance_functions.h> -#include <gudhi/Kd_tree_search.h> -#include <CGAL/Epick_d.h> - -#include <boost/graph/adjacency_list.hpp> #include <iostream> #include <vector> @@ -41,11 +37,7 @@ #include <string> #include <limits> // for numeric_limits #include <utility> // for pair<> -#include <functional> // for greater<> -#include <stdexcept> -#include <initializer_list> #include <algorithm> // for std::max -#include <cstdint> // for std::uint32_t #include <random> #include <cassert> @@ -111,25 +103,16 @@ class Graph_induced_complex { std::string point_cloud_name; std::string color_name; - // Simplex comparator - private: - bool simplex_comp(const std::vector<Cover_t>& s1, const std::vector<Cover_t>& s2){ - if(s1.size() == s2.size()){ - return s1[0] < s2[0]; - } - else return s1.size() < s2.size(); - } - // Point comparator private: - static bool functional_comp(const int& a, const int& b){ + static bool functional_comp(int a, int b){ if(func[a] == func[b]) return a < b; else return func[a] < func[b]; } // DFS private: - void dfs(std::map<int,std::vector<int> >& G, const int& p, std::vector<int>& cc, std::map<int,bool>& visit){ + void dfs(std::map<int,std::vector<int> >& G, int p, std::vector<int>& cc, std::map<int,bool>& visit){ cc.push_back(p); visit[p] = true; int neighb = G[p].size(); for (int i = 0; i < neighb; i++) @@ -161,12 +144,16 @@ class Graph_induced_complex { void set_verbose(bool verb = 0){verbose = verb;} public: - void read_point_cloud(const std::string& off_file_name){ + bool read_point_cloud(std::string off_file_name){ Gudhi::Points_off_reader<Point> off_reader = Points_off_reader<Point>(off_file_name); - point_cloud = off_reader.get_point_cloud(); - point_cloud_name = off_file_name; - n = point_cloud.size(); - data_dimension = point_cloud[0].size(); + bool check = off_reader.is_valid(); + if(check){ + point_cloud = off_reader.get_point_cloud(); + point_cloud_name = off_file_name; + n = point_cloud.size(); + data_dimension = point_cloud[0].size(); + return check; + } else return check; } // ******************************************************************************************************************* @@ -179,7 +166,7 @@ class Graph_induced_complex { * @param[in] graph_file_name name of the input graph file. * */ - void set_graph_from_file(const std::string& graph_file_name){ + void set_graph_from_file(std::string graph_file_name){ int neighb; int vid; std::ifstream input(graph_file_name); std::string line; std::vector<int> edge(2); int n = 0; while(std::getline(input,line)){ std::stringstream stream(line); stream >> vid; edge[0] = vid; @@ -204,7 +191,7 @@ class Graph_induced_complex { * @param[in] off_file_name name of the input .OFF file. * */ - void set_graph_from_OFF(const std::string& off_file_name){ + void set_graph_from_OFF(std::string off_file_name){ int numedges, numfaces, i; std::vector<int> edge(2); double x; int num; std::vector<int> simplex; std::ifstream input(off_file_name); std::string line; getline(input, line); input >> n; input >> numfaces; input >> numedges; @@ -238,7 +225,7 @@ class Graph_induced_complex { * @param[in] threshold threshold value for the Rips complex. * */ - void set_graph_from_rips(const double& threshold){ + void set_graph_from_rips(double threshold){ Rips_complex rips_complex_from_points(point_cloud, threshold, Euclidean_distance()); rips_complex_from_points.create_complex(st, 1); @@ -259,9 +246,9 @@ class Graph_induced_complex { */ void compute_pairwise_distances(){ - double d; std::vector<double> dumb(n); for(int i = 0; i < n; i++) distances.push_back(dumb); - char distance[100]; sprintf(distance,"%s_dist",(char*) point_cloud_name.c_str()); - std::ifstream input(distance, std::ios::out | std::ios::binary); + double d; std::vector<double> zeros(n); for(int i = 0; i < n; i++) distances.push_back(zeros); + std::string distance = point_cloud_name; distance.append("_dist"); + std::ifstream input(distance.c_str(), std::ios::out | std::ios::binary); if(input.good()){ if(verbose) std::cout << "Reading distances..." << std::endl; @@ -277,8 +264,8 @@ class Graph_induced_complex { if(verbose) std::cout << "Computing distances..." << std::endl; input.close(); std::ofstream output(distance, std::ios::out | std::ios::binary); for(int i = 0; i < n; i++){ - if( (int) floor( 100*(i*1.0+1)/(n*1.0) ) %10 == 0 ) - if(verbose) std::cout << "\r" << floor( 100*(i*1.0+1)/(n*1.0) ) << "%" << std::flush; + int state = (int) floor( 100*(i*1.0+1)/n ) %10; + if( state == 0 && verbose) std::cout << "\r" << state << "%" << std::flush; for (int j = i; j < n; j++){ double dis = 0; for(int k = 0; k < data_dimension; k++) dis += pow(point_cloud[i][k]-point_cloud[j][k],2); @@ -347,7 +334,7 @@ class Graph_induced_complex { * @param[in] func_file_name name of the input function file. * */ - void set_function_from_file(const std::string& func_file_name){ + void set_function_from_file(std::string func_file_name){ int vertex_id = 0; std::ifstream input(func_file_name); std::string line; double f; while(std::getline(input,line)){ std::stringstream stream(line); stream >> f; @@ -362,7 +349,7 @@ class Graph_induced_complex { * @param[in] k coordinate to use (start at 0). * */ - void set_function_from_coordinate(const int& k){ + void set_function_from_coordinate(int k){ for(int i = 0; i < n; i++) func.insert(std::pair<int,double>(i,point_cloud[i][k])); char coordinate[100]; sprintf(coordinate, "coordinate %d", k); cover_name = coordinate; @@ -374,7 +361,7 @@ class Graph_induced_complex { * @param[in] function input vector of values. * */ - void set_function_from_vector(const std::vector<double>& function){ + void set_function_from_vector(std::vector<double> function){ for(int i = 0; i < n; i++) func.insert(std::pair<int,double>(i, function[i])); } @@ -389,7 +376,7 @@ class Graph_induced_complex { * @param[in] cover_file_name name of the input cover file. * */ - void set_cover_from_file(const std::string& cover_file_name){ + void set_cover_from_file(std::string cover_file_name){ int vertex_id = 0; Cover_t cov; std::vector<Cover_t> cov_elts, cov_number; std::ifstream input(cover_file_name); std::string line; while(std::getline(input,line)){ @@ -413,7 +400,7 @@ class Graph_induced_complex { * @param[in] m number of points in the subsample. * */ - void set_cover_from_Voronoi(const int& m){ + void set_cover_from_Voronoi(int m = 100){ voronoi_subsamples.resize(m); SampleWithoutReplacement(n,m,voronoi_subsamples); if(distances.size() == 0) compute_pairwise_distances(); @@ -497,7 +484,7 @@ class Graph_induced_complex { public: // Automatic tuning of resolution for Mapper Point. /** \brief Computes the optimal length of intervals for a standard Mapper. */ - void set_automatic_resolution_for_MAP(const double& gain){ + void set_automatic_resolution_for_MAP(double gain){ double reso = 0; for (auto simplex : st.complex_simplex_range()) { if(st.dimension(simplex) == 1){ @@ -516,7 +503,7 @@ class Graph_induced_complex { * @param[in] token boolean specifying whether we use the length or the number of intervals for the cover of im(f). * */ - void set_cover_from_function(const bool& token){ + void set_cover_from_function(bool token){ // Read function values and compute min and max std::map<int, double>::iterator it; @@ -537,8 +524,8 @@ class Graph_induced_complex { } x = minf + (resolution_int-1)*incr - alpha; y = maxf; std::pair<double, double> interM(x,y); intervals.push_back(interM); res = intervals.size(); - for(int i = 0; i < res; i++) - if(verbose) std::cout << "Interval " << i << " = [" << intervals[i].first << ", " << intervals[i].second << "]" << std::endl; + if(verbose) + for(int i = 0; i < res; i++) std::cout << "Interval " << i << " = [" << intervals[i].first << ", " << intervals[i].second << "]" << std::endl; } else{ // Case we use a double for the length of the intervals. @@ -549,8 +536,8 @@ class Graph_induced_complex { y = x + resolution_double; } std::pair<double, double> interM(x,maxf); intervals.push_back(interM); res = intervals.size(); - for(int i = 0; i < res; i++) if(verbose) std::cout << "Interval " << i << " = [" << \ - intervals[i].first << ", " << intervals[i].second << "]" << std::endl; + if(verbose) + for(int i = 0; i < res; i++) std::cout << "Interval " << i << " = [" << intervals[i].first << ", " << intervals[i].second << "]" << std::endl; } // Sort points according to function values @@ -562,7 +549,7 @@ class Graph_induced_complex { for(int i = 0; i < res; i++){ // Find points in the preimage - std::map<int,std::vector<int> > prop; prop.clear(); + std::map<int,std::vector<int> > prop; std::pair<double, double> inter1 = intervals[i]; int tmp = pos; @@ -571,20 +558,20 @@ class Graph_induced_complex { if(i != 0){ std::pair<double, double> inter3 = intervals[i-1]; while(func[points[tmp]] < inter3.second && tmp != n){ - prop.insert(std::pair<int,std::vector<int> >(points[tmp],adjacency_matrix[points[tmp]])); + prop.insert(std::make_pair(points[tmp],adjacency_matrix[points[tmp]])); tmp++; } } std::pair<double, double> inter2 = intervals[i+1]; while(func[points[tmp]] < inter2.first && tmp != n){ - prop.insert(std::pair<int,std::vector<int> >(points[tmp],adjacency_matrix[points[tmp]])); + prop.insert(std::make_pair(points[tmp],adjacency_matrix[points[tmp]])); tmp++; } pos = tmp; while(func[points[tmp]] < inter1.second && tmp != n){ - prop.insert(std::pair<int,std::vector<int> >(points[tmp],adjacency_matrix[points[tmp]])); + prop.insert(std::make_pair(points[tmp],adjacency_matrix[points[tmp]])); tmp++; } @@ -594,12 +581,12 @@ class Graph_induced_complex { std::pair<double, double> inter3 = intervals[i-1]; while(func[points[tmp]] < inter3.second && tmp != n){ - prop.insert(std::pair<int,std::vector<int> >(points[tmp],adjacency_matrix[points[tmp]])); + prop.insert(std::make_pair(points[tmp],adjacency_matrix[points[tmp]])); tmp++; } while(tmp != n){ - prop.insert(std::pair<int,std::vector<int> >(points[tmp],adjacency_matrix[points[tmp]])); + prop.insert(std::make_pair(points[tmp],adjacency_matrix[points[tmp]])); tmp++; } @@ -638,7 +625,7 @@ class Graph_induced_complex { * @param[in] color_file_name name of the input color file. * */ - void set_color_from_file(const std::string& color_file_name){ + void set_color_from_file(std::string color_file_name){ int vertex_id = 0; std::ifstream input(color_file_name); std::string line; double f; while(std::getline(input,line)){ std::stringstream stream(line); stream >> f; @@ -656,8 +643,7 @@ class Graph_induced_complex { */ void set_color_from_coordinate(int k = 0){ for(int i = 0; i < n; i++) func_color.insert(std::pair<int,double>(i, point_cloud[i][k])); - char coordinate[100]; sprintf(coordinate, "coordinate %d", k); - color_name = coordinate; + color_name = "coordinate "; color_name.append(std::to_string(k)); } public: // Set color from vector. @@ -666,7 +652,7 @@ class Graph_induced_complex { * @param[in] color input vector of values. * */ - void set_color_from_vector(const std::vector<double>& color){ + void set_color_from_vector(std::vector<double> color){ for(unsigned int i = 0; i < color.size(); i++) func_color.insert(std::pair<int,double>(i, color[i])); } @@ -674,7 +660,7 @@ class Graph_induced_complex { /** \brief Creates a .dot file for neato once the simplicial complex is computed to get a nice visualization * of its 1-skeleton in a .pdf file. */ - void plot_with_neato(){ + void plot_pdf(){ char mapp[11] = "SC.dot"; std::ofstream graphic(mapp); graphic << "graph Mapper {" << std::endl; double maxv, minv; maxv = std::numeric_limits<double>::min(); minv = std::numeric_limits<double>::max(); for (std::map<Cover_t,std::pair<int,double> >::iterator iit = cover_color.begin(); iit != cover_color.end(); iit++){ @@ -696,16 +682,14 @@ class Graph_induced_complex { if (cover_color[simplices[i][0]].first > MASK && cover_color[simplices[i][1]].first > MASK){ graphic << " " << simplices[i][0] << " -- " << simplices[i][1] << " [weight=15];" << std::endl; ke++;} graphic << "}"; graphic.close(); - char command[100]; sprintf(command, "neato SC.dot -Tpdf -o SC_visu.pdf && rm SC.dot"); - int systemRet = system(command); - if(systemRet == -1) std::cout << "Visualization failed. Do you have neato?" << std::endl; + std::cout << "SC.dot generated. It can be visualized with e.g. neato." << std::endl; } public: // Create a .txt file that can be compiled with KeplerMapper to produce a .html file. /** \brief Creates a .txt file for KeplerMapper once the simplicial complex is computed to get a nice visualization * of its 1-skeleton in browser. */ - void plot_with_KeplerMapper(){ + void plot_txt(){ int num_simplices = simplices.size(); int num_edges = 0; char mapp[11] = "SC.txt"; std::ofstream graphic(mapp); @@ -728,17 +712,15 @@ class Graph_induced_complex { if (cover_color[simplices[i][0]].first > MASK && cover_color[simplices[i][1]].first > MASK) graphic << simplices[i][0] << " " << simplices[i][1] << std::endl; graphic.close(); - char command[100]; sprintf(command, "python visu.py && firefox SC.html"); - int systemRet = system(command); - if(systemRet == -1) std::cout << "Visualization failed. Do you have python and firefox?" << std::endl; + std::cout << "SC.txt generated. It can be visualized with e.g. python visu.py and firefox." << std::endl; } - public: // Create a .off file that can be visualized with Geomview. - /** \brief Creates a .off file for visualization with Geomview. + public: // Create a .off file that can be visualized (e.g. with Geomview). + /** \brief Creates a .off file for visualization. * For GIC computed with Voronoi only. */ - void plot_with_Geomview(){ + void plot_OFF(){ assert(data_dimension <= 3); char gic[11] = "SC.off"; std::ofstream graphic(gic); @@ -759,10 +741,7 @@ class Graph_induced_complex { for(int i = 0; i < numedges; i++) graphic << 2 << " " << edges[i][0] << " " << edges[i][1] << std::endl; for(int i = 0; i < numfaces; i++) graphic << 3 << " " << faces[i][0] << " " << faces[i][1] << " " << faces[i][2] << std::endl; graphic.close(); - - char command[100]; sprintf(command, "geomview SC.off"); - int systemRet = system(command); - if(systemRet == -1) std::cout << "Visualization failed. Do you have geomview?" << std::endl; + std::cout << "SC.off generated. It can be visualized with e.g. geomview." << std::endl; } @@ -792,7 +771,7 @@ class Graph_induced_complex { * @param[in] cover_elts vector of points represented by vectors of cover elements (the ones to which they belong). * */ - void find_all_simplices(const std::vector<std::vector<Cover_t> > & cover_elts){ + void find_all_simplices(std::vector<std::vector<Cover_t> > cover_elts){ int num_nodes = cover_elts.size(); std::vector<Cover_t> simplex; for(int i = 0; i < num_nodes; i++) @@ -824,7 +803,7 @@ class Graph_induced_complex { if(st.dimension(simplex) == 1){ std::vector<std::vector<Cover_t> > comp; for(auto vertex : st.simplex_vertex_range(simplex)) comp.push_back(cover[vertex]); - if(comp[0].size() == 1 && comp[1].size() == 1 && comp[0] == comp[1]) simplex_to_remove.push_back(simplex_id); + if(comp[0].size() == 1 && comp[0] == comp[1]) simplex_to_remove.push_back(simplex_id); } simplex_id++; } @@ -863,13 +842,15 @@ class Graph_induced_complex { * and adding the corresponding edges in the Mapper Delta if the images of the endpoints belong * to consecutive intervals. * - * \remark WARNING: the output of this function is correct ONLY if the cover is minimal, i.e. - * the gain is less than 0.5!!! + * @exception std::invalid_argument In case the gain is greater or equal to 0.5 (causes incorrect output). * */ void find_GICMAP_simplices_with_functional_minimal_cover(){ - int v1, v2; assert(gain < 0.5); + if (gain >= 0.5) + throw std::invalid_argument("the output of this function is correct ONLY if the cover is minimal, i.e. the gain is less than 0.5."); + + int v1, v2; // Loop on all points. for(std::map<int,std::vector<Cover_t> >::iterator it = cover.begin(); it != cover.end(); it++){ diff --git a/src/Nerve_GIC/test/test_GIC.cpp b/src/Nerve_GIC/test/test_GIC.cpp index e8051cf0..6b6621fd 100644 --- a/src/Nerve_GIC/test/test_GIC.cpp +++ b/src/Nerve_GIC/test/test_GIC.cpp @@ -33,10 +33,6 @@ #include <gudhi/distance_functions.h> #include <gudhi/reader_utils.h> -bool are_almost_the_same(float a, float b) { - return std::fabs(a - b) < std::numeric_limits<float>::epsilon(); -} - BOOST_AUTO_TEST_CASE(check_nerve) { Gudhi::graph_induced_complex::Graph_induced_complex GIC; |