summaryrefslogtreecommitdiff
path: root/src/Tangential_complex/benchmark
diff options
context:
space:
mode:
Diffstat (limited to 'src/Tangential_complex/benchmark')
-rw-r--r--src/Tangential_complex/benchmark/CMakeLists.txt9
-rw-r--r--src/Tangential_complex/benchmark/RIB_exporter.h257
-rw-r--r--src/Tangential_complex/benchmark/XML_exporter.h195
-rw-r--r--src/Tangential_complex/benchmark/benchmark_script.txt221
-rw-r--r--src/Tangential_complex/benchmark/benchmark_tc.cpp781
5 files changed, 1463 insertions, 0 deletions
diff --git a/src/Tangential_complex/benchmark/CMakeLists.txt b/src/Tangential_complex/benchmark/CMakeLists.txt
new file mode 100644
index 00000000..621b0fd7
--- /dev/null
+++ b/src/Tangential_complex/benchmark/CMakeLists.txt
@@ -0,0 +1,9 @@
+project(Tangential_complex_benchmark)
+
+if(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
+ add_executable(Tangential_complex_benchmark benchmark_tc.cpp)
+ target_link_libraries(Tangential_complex_benchmark ${CGAL_LIBRARY})
+ if (TBB_FOUND)
+ target_link_libraries(Tangential_complex_benchmark ${TBB_LIBRARIES})
+ endif(TBB_FOUND)
+endif(NOT CGAL_WITH_EIGEN3_VERSION VERSION_LESS 4.11.0)
diff --git a/src/Tangential_complex/benchmark/RIB_exporter.h b/src/Tangential_complex/benchmark/RIB_exporter.h
new file mode 100644
index 00000000..4cec0603
--- /dev/null
+++ b/src/Tangential_complex/benchmark/RIB_exporter.h
@@ -0,0 +1,257 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#ifndef GUDHI_TC_RIB_EXPORTER_H
+#define GUDHI_TC_RIB_EXPORTER_H
+
+#include <gudhi/Tangential_complex/utilities.h>
+
+#include <tuple>
+#include <string>
+
+template <typename PointRandomAccessRange, typename SimplexRange>
+class RIB_exporter {
+ typedef typename PointRandomAccessRange::value_type Point;
+ typedef typename SimplexRange::value_type Simplex;
+ public:
+
+ typedef std::tuple<double, double, double, double> Color; // RGBA
+ typedef std::tuple<int, int, int> Coords_choice;
+
+ // Constructor
+ RIB_exporter(
+ PointRandomAccessRange const& points,
+ SimplexRange const& simplices,
+ std::ofstream &out,
+ std::string const& rendered_image_filename = "export.tif",
+ bool is_preview = false, // low-quality
+ Coords_choice coords_choice = std::make_tuple(0, 1, 2),
+ int image_width = 1920,
+ int image_height = 1080,
+ Color const& triangle_color = std::make_tuple(1., 1., 1., 1.),
+ bool ambient_light = true,
+ double ambient_intensity = 0.3,
+ bool shadow = true,
+ double shadow_intensity = 0.85,
+ double point_sphere_radius = 0.003)
+ : m_points(points),
+ m_simplices(simplices),
+ m_out(out),
+ m_rendered_image_filename(rendered_image_filename),
+ m_is_preview(is_preview),
+ m_coords_choice(coords_choice),
+ m_image_width(image_width),
+ m_image_height(image_height),
+ m_current_color(0., 0., 0., 0.),
+ m_current_alpha(1),
+ m_triangle_color(triangle_color),
+ m_ambient_light(ambient_light),
+ m_ambient_intensity(ambient_intensity),
+ m_shadow(shadow),
+ m_shadow_intensity(shadow_intensity),
+ m_point_sphere_radius(point_sphere_radius) {
+ m_out.precision(8);
+ }
+
+ void write_file() {
+ write_header();
+ write_lights();
+ /*if (m_point_sphere_radius != 0.)
+ write_point_spheres();*/
+ write_triangles();
+
+ m_out << "WorldEnd\n";
+ }
+
+ private:
+
+ void write_header() {
+ m_out << "Option \"searchpath\" \"shader\" "
+ "\".:./shaders:%PIXIE_SHADERS%:%PIXIEHOME%/shaders\"\n";
+
+ if (m_is_preview) {
+ m_out << "Attribute \"visibility\" \"specular\" 1\n"
+ << "Attribute \"visibility\" \"transmission\" 1\n\n";
+ }
+
+ m_out << "Display \"" << m_rendered_image_filename << "\" \"file\" \"rgb\"\n";
+
+ if (!m_is_preview) {
+ m_out << "Format " << m_image_width << " " << m_image_height << " 1\n";
+ } else {
+ double ratio = double(m_image_height) / double(m_image_width);
+
+ int width = (ratio < 1.) ? 300 : int(300. / ratio);
+ int height = (ratio < 1.) ? int(ratio * 300.) : 300;
+
+ m_out << "Format " << width << " " << height << " 1\n";
+ }
+
+
+ if (m_image_width > m_image_height) {
+ double ratio = double(m_image_height) / double(m_image_width);
+ m_out << "ScreenWindow -1 1 " << -ratio << " " << ratio << "\n";
+ } else if (m_image_height > m_image_width) {
+ double ratio = double(m_image_width) / double(m_image_height);
+ m_out << "ScreenWindow " << -ratio << " " << ratio << " -1 1\n";
+ }
+
+ m_out << "Projection \"perspective\" \"fov\" 45\n"
+ << "Translate 0 0 3\n"
+ << "PixelSamples 4 4\n"
+ << "PixelFilter \"catmull-rom\" 3 3\n"
+ << "ShadingInterpolation \"smooth\"\n"
+ << "Rotate -10 20 0 1\n"
+ << "WorldBegin\n";
+ }
+
+ void write_lights() {
+ if (!m_is_preview) {
+ // ShadowLight
+ m_out << "LightSource \"shadowdistant\" 1 \"from\" [0 0 0] \"to\" [0 0 1]"
+ << " \"shadowname\" \"raytrace\" \"intensity\" "
+ << m_shadow_intensity << "\n";
+
+ // Ambient light
+ m_out << "LightSource \"ambientlight\" 2 \"intensity\" "
+ << m_ambient_intensity << "\n";
+ } else {
+ m_out << "LightSource \"distantLight\" 1 \"from\" [0 0 0] \"to\" [0 0 1]"
+ << " \"intensity\" " << m_shadow_intensity << "\n";
+
+ // Ambient light
+ m_out << "LightSource \"ambientlight\" 2 \"intensity\" "
+ << m_ambient_intensity << "\n";
+ }
+
+ // Background light
+ m_out << "LightSource \"ambientlight\" 99 \"intensity\" 1\n";
+
+ // Turn background light OFF
+ turn_background_light(false);
+ }
+
+ void turn_background_light(bool turn_on) {
+ if (!turn_on) {
+ m_out << "Illuminate 1 1" << std::endl;
+ if (!m_is_preview)
+ m_out << "Illuminate 2 1" << std::endl;
+ m_out << "Illuminate 99 0" << std::endl;
+ } else {
+ m_out << "Illuminate 1 0" << std::endl;
+ if (!m_is_preview)
+ m_out << "Illuminate 2 0" << std::endl;
+ m_out << "Illuminate 99 1" << std::endl;
+ }
+ }
+
+ void write_color(Color const& color, bool use_transparency) {
+ if (m_current_color == color)
+ return;
+
+ m_current_color = color;
+
+ // Write opacity data
+ if (use_transparency)
+ write_opacity(std::get<3>(color));
+
+ // Write color data
+ m_out << "Color [ " << std::get<0>(color) << " " << std::get<1>(color)
+ << " " << std::get<2>(color) << " ]\n";
+ }
+
+ void write_opacity(const double alpha) {
+ if (m_current_alpha == alpha)
+ return;
+
+ m_current_alpha = alpha;
+
+ // Write opacity data
+ m_out << "Opacity " << alpha << " " << alpha << " " << alpha << std::endl;
+ }
+
+ void write_point(Point const& p) {
+ m_out << " " << p[std::get<0>(m_coords_choice)]
+ << " " << p[std::get<1>(m_coords_choice)]
+ << " " << p[std::get<2>(m_coords_choice)] << " ";
+ }
+
+ void write_triangles() {
+ m_out << "Surface \"plastic\" \"Ka\" 0.65 \"Kd\" 0.85 \"Ks\" 0.25 \"roughness\" 0.1" << std::endl;
+
+ for (auto const& simplex : m_simplices) {
+ std::vector<Simplex> triangles;
+ // Get the triangles composing the simplex
+ combinations(simplex, 3, std::back_inserter(triangles));
+ for (auto const& t : triangles)
+ write_triangle(t);
+ }
+ }
+
+ template <typename PointIndexRange>
+ void write_triangle(PointIndexRange const& t) {
+ // Color
+ write_color(m_triangle_color, true);
+
+ // Triangle
+ m_out << "Polygon \"P\" [";
+ for (auto idx : t)
+ write_point(m_points[idx]);
+ m_out << "]" << std::endl;
+
+ // Edges (will be drawn later on)
+ /*add_edge(p, q, edge_color);
+ add_edge(p, r, edge_color);
+ add_edge(q, r, edge_color);
+
+ // Vertices (will be drawn later on)
+ add_vertex(p, edge_color);
+ add_vertex(q, edge_color);
+ add_vertex(r, edge_color);*/
+ }
+
+ void write_point_sphere(Point const& p) {
+ if (m_point_sphere_radius == 0.)
+ return;
+
+ m_out << "Translate " << p[0] << " " << p[1] << " " << p[2] << std::endl;
+ // Sphere radius zmin zmax thetamax
+ m_out << "Sphere " << m_point_sphere_radius << " " << -m_point_sphere_radius
+ << " " << m_point_sphere_radius << " 360" << std::endl;
+ m_out << "Identity" << std::endl;
+ }
+
+ void write_point_spheres() {
+ write_color(std::make_tuple(0.7, 0.7, 0.7, 0.5), true);
+ for (auto const& p : m_points)
+ write_point_sphere(p);
+ }
+
+ //===========================================================================
+
+ PointRandomAccessRange const& m_points;
+ SimplexRange const& m_simplices;
+ std::ofstream &m_out;
+ std::string m_rendered_image_filename;
+ bool m_is_preview;
+ Coords_choice m_coords_choice;
+ int m_image_width;
+ int m_image_height;
+ Color m_current_color;
+ Color m_triangle_color;
+ double m_current_alpha;
+ bool m_ambient_light;
+ double m_ambient_intensity;
+ bool m_shadow;
+ double m_shadow_intensity;
+ double m_point_sphere_radius;
+};
+
+#endif // GUDHI_TC_RIB_EXPORTER_H
diff --git a/src/Tangential_complex/benchmark/XML_exporter.h b/src/Tangential_complex/benchmark/XML_exporter.h
new file mode 100644
index 00000000..16b62eb6
--- /dev/null
+++ b/src/Tangential_complex/benchmark/XML_exporter.h
@@ -0,0 +1,195 @@
+/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
+ * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
+ * Author(s): Clement Jamin
+ *
+ * Copyright (C) 2016 Inria
+ *
+ * Modification(s):
+ * - YYYY/MM Author: Description of the modification
+ */
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <ctime>
+
+template<typename value_type = std::string>
+class Simple_XML_exporter {
+ public:
+ typedef value_type Value_type;
+ typedef std::vector<value_type> Element;
+ typedef std::map<std::string, value_type> Element_with_map;
+ typedef std::vector<Element> List_of_elements;
+
+ Simple_XML_exporter(
+ const std::string &list_name,
+ const std::string &element_name,
+ const std::vector<std::string> &subelement_names,
+ bool add_timestamp = true)
+ : m_list_name(list_name),
+ m_element_name(element_name),
+ m_subelement_names(subelement_names),
+ m_add_timestamp(add_timestamp) { }
+
+ bool add_element(const Element &element) {
+ if (element.size() == m_subelement_names.size()) {
+ m_list_of_elements.push_back(element);
+ return true;
+ } else {
+ std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl;
+ return false;
+ }
+ }
+
+ bool add_element(Element_with_map &element) {
+ Element elt;
+
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+ for (; it_subelement_name != it_subelement_name_end; ++it_subelement_name) {
+ elt.push_back(element[*it_subelement_name]);
+ }
+
+ return add_element(elt);
+ }
+
+ bool export_to_xml(const std::string &filename) const {
+ std::ofstream xmlfile;
+ xmlfile.open(filename.c_str());
+ xmlfile << "<?xml version='1.0'?>" << std::endl;
+ xmlfile << "<" << m_list_name << ">" << std::endl;
+
+ typename List_of_elements::const_iterator it_element = m_list_of_elements.begin();
+ typename List_of_elements::const_iterator it_element_end = m_list_of_elements.end();
+ for (int id = 1; it_element != it_element_end; ++it_element, ++id) {
+ xmlfile << " <" << m_element_name << ">" << std::endl;
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+
+ if (m_add_timestamp)
+ xmlfile << " <id> " << time(NULL) << " </id>" << std::endl;
+
+ for (int i = 0;
+ it_subelement_name != it_subelement_name_end;
+ ++it_subelement_name, ++i) {
+ xmlfile
+ << " <" << *it_subelement_name << "> "
+ << (*it_element)[i]
+ << " </" << *it_subelement_name << ">" << std::endl;
+ }
+ xmlfile << " </" << m_element_name << ">" << std::endl;
+ }
+
+ xmlfile << "</" << m_list_name << ">" << std::endl;
+ xmlfile.close();
+ return 0;
+
+ }
+
+ protected:
+ std::string m_list_name;
+ std::string m_element_name;
+ std::vector<std::string> m_subelement_names;
+ List_of_elements m_list_of_elements;
+ bool m_add_timestamp;
+};
+
+template<typename value_type = std::string>
+class Streaming_XML_exporter {
+ public:
+ typedef value_type Value_type;
+ typedef std::vector<value_type> Element;
+ typedef std::map<std::string, value_type> Element_with_map;
+ typedef std::vector<Element> List_of_elements;
+
+ Streaming_XML_exporter(
+ const std::string &filename,
+ const std::string &list_name,
+ const std::string &element_name,
+ const std::vector<std::string> &subelement_names,
+ bool add_timestamp = true)
+ : m_list_name(list_name),
+ m_element_name(element_name),
+ m_subelement_names(subelement_names),
+ m_add_timestamp(add_timestamp) {
+ m_xml_fstream.open(filename.c_str());
+ if (m_xml_fstream.good()) {
+ m_xml_fstream << "<?xml version='1.0'?>" << std::endl;
+ m_xml_fstream << "<" << m_list_name << ">" << std::endl;
+ } else {
+ std::cerr << "Could not open file '" << filename << "'." << std::endl;
+ }
+ }
+
+ virtual ~Streaming_XML_exporter() {
+ close_file();
+ }
+
+ void close_file() {
+ m_xml_fstream.close();
+ }
+
+ bool add_element(const Element &element) {
+ if (element.size() == m_subelement_names.size()) {
+ m_xml_fstream << " <" << m_element_name << ">" << std::endl;
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+
+ if (m_add_timestamp) {
+ m_xml_fstream << " <id> " << time(NULL) << " </id>" << std::endl;
+ }
+
+ for (int i = 0;
+ it_subelement_name != it_subelement_name_end;
+ ++it_subelement_name, ++i) {
+ m_xml_fstream
+ << " <" << *it_subelement_name << "> "
+ << element[i]
+ << " </" << *it_subelement_name << ">" << std::endl;
+ }
+ m_xml_fstream << " </" << m_element_name << ">" << std::endl;
+
+ // Save current pointer position
+ std::ofstream::streampos pos = m_xml_fstream.tellp();
+ // Close the XML file (temporarily) so that the XML file is always correct
+ m_xml_fstream << "</" << m_list_name << ">" << std::endl;
+ // Restore the pointer position so that the next "add_element" will overwrite
+ // the end of the file
+ m_xml_fstream.seekp(pos);
+
+ m_xml_fstream.flush();
+ return true;
+ } else {
+ std::cerr << "ERROR: element.size() == m_subelement_names.size()" << std::endl;
+ return false;
+ }
+ }
+
+ bool add_element(Element_with_map &element) {
+ Element elt;
+
+ std::vector<std::string>::const_iterator
+ it_subelement_name = m_subelement_names.begin();
+ std::vector<std::string>::const_iterator
+ it_subelement_name_end = m_subelement_names.end();
+ for (; it_subelement_name != it_subelement_name_end; ++it_subelement_name) {
+ elt.push_back(element[*it_subelement_name]);
+ }
+
+ return add_element(elt);
+ }
+
+ protected:
+ std::ofstream m_xml_fstream;
+ std::string m_list_name;
+ std::string m_element_name;
+ std::vector<std::string> m_subelement_names;
+ bool m_add_timestamp;
+};
diff --git a/src/Tangential_complex/benchmark/benchmark_script.txt b/src/Tangential_complex/benchmark/benchmark_script.txt
new file mode 100644
index 00000000..f4ddaac3
--- /dev/null
+++ b/src/Tangential_complex/benchmark/benchmark_script.txt
@@ -0,0 +1,221 @@
+#---------------------------------------------------------------------------------------------------------------------------------------------------------
+# Input PARAM1 PARAM2 PARAM3 NUM_P AMB INTR SPARSITY MAX_PERTURB PERTURB ADD_HDIM COLLAPSE FIX_TIME_LIMIT NUM_ITERATIONS
+#---------------------------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------------------------------- Alpha TC tests ------------------------------------------------------------------------
+#generate_sphere_d 1 0 - 8 2 1 0.01 0.005 N Y N 3 1 #No noise => OK: 6 2d with a perturb sometimes
+#generate_sphere_d 1 0 - 50 2 1 0.01 0.005 N Y N 3 1 #No noise => OK: 49 1d
+#generate_sphere_d 1 1 - 50 2 1 0.01 0.005 N Y N 3 1 #Noise => OK: 45 2d + 3 3d
+#generate_torus_d N - - 15 2 1 0.01 0.05 N Y N 10 1
+#generate_sphere_d 0.302 0 - 8 3 2 0.01 0.005 N Y N 60 1 #No noise => OK: 7 3d with a perturb sometimes
+#generate_sphere_d 0.302 0 - 50 3 2 0.01 0.005 N Y N 60 1 #No noise => no inconsitencies
+#generate_sphere_d 0.302 3 - 50 3 2 0.01 0.005 N Y N 60 1 #Noise => OK: 90 2d + 3 3d
+#generate_sphere_d 1 1 - 500 4 3 0.01 0.005 N Y N 60 1 #Noise 1% => OK: 3113 3d + 35 4d
+#generate_sphere_d 1 2 - 500 4 3 0.01 0.005 N Y N 60 1 #Noise 2% => OK: 2969 3d + 91 4d
+#generate_sphere_d 1 2 - 5000 4 3 0.01 0.005 N Y N 60 1 #Noise 2% => OK: 27905 3d + 2485 4d
+#generate_sphere_d 0.302 2 - 300 2 1 0.01 0.005 N Y N 60 1
+#generate_torus_3D 2 1 N 200 3 2 0.01 0.05 N Y N 600 1 #OK: 1048 3d ~170s
+#generate_torus_3D 2 1 N 2000 3 2 0.01 0.05 N Y N 600 1 #OK: 3545 2d + 27 3d ~35s
+#generate_torus_d N 1 - 50 4 2 0.01 0.05 N Y N 3 1 #OK: 431 4d
+#generate_torus_d N 1 - 500 4 2 0.01 0.05 N Y N 3 1 #OK: 881 2d + 37 3d
+#generate_torus_d Y 1 - 250 4 2 0.01 0.05 N Y N 3 1 #OK: 80 d2 + 185 d3
+#generate_torus_d N - - 50 6 3 0.01 0.05 Y Y N 10 1 #
+#generate_torus_d Y - - 700 6 3 0.01 0.05 Y Y N 100 1 #Grid
+#generate_torus_d N - - 10000 6 3 0.01 0.05 Y Y N 30000 1
+#generate_moment_curve 0 1 - 10 3 1 0.01 0.005 N Y N 60 1
+#generate_two_spheres_d 3 4 - 500 3 2 0.01 0.05 N Y N 10 1 #OK: 320 2d + 1167 3d
+#generate_klein_bottle_4D 40 15 - 500 4 2 0.01 0.2 N Y N 60 1 #OK: 901 d2 + 50 d3 + 1 d4
+#data/SO3_10000.xyz - - - 0 9 3 0.01 0.05 Y Y N 300 1 #Too long. Be careful with the memory consumption!
+#data/buddha_100kv.xyz - - - 0 3 2 0.01 0.005 Y Y N 120 1 #Too long...
+#data/fandisk.xyz - - - 0 3 2 0.01 0.005 Y Y N 5 1 #NOT OK: Tq & V do not intersect
+
+#---------------------------------------------------------- Spatial search benchmarking --------------------------------------------------------------
+#generate_torus_3D 2 1 Y 10000 3 2 0 0 Y N N 600 1
+#data/buddha_100kv.xyz - - - 0 3 2 0 0 N Y N 120 1
+#generate_torus_d N - - 10000 30 15 0 0 Y N N 3600 1
+#generate_torus_d N - - 100000 12 6 0 0 Y N N 3600 1
+#data/SO3_50000.xyz - - - 0 9 3 0 0 Y N N 60 1
+#data/Cy8.xyz - - - 0 24 2 0 0 N Y N 60 1
+#generate_sphere_d 0.5 - - 10000 2 1 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 3 2 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 4 3 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 5 4 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 6 5 0 0 N N Y 60 1
+#generate_sphere_d 0.5 - - 10000 7 6 0 0 N N Y 60 1
+
+#---------------------------------------------------------- Very small cases for Debug mode --------------------------------------------------------------
+#generate_sphere_d 4 - - 20 3 2 0.05 0.025 Y N N 60 1
+generate_sphere_d 3 10 - 70 3 2 0.05 0.025 Y N N 60 1
+#generate_sphere_d 3 - - 1000 3 2 0.05 0.025 Y N N 60 1
+#generate_sphere_d 3 - - 10 4 3 0.05 0.025 Y N N 60 1
+#generate_sphere_d 3 - - 70 5 4 0.05 0.025 Y N N 60 1
+#generate_klein_bottle_4D 4 3 - 70 4 2 0.05 0.025 Y N N 3 1
+#generate_klein_bottle_variant_5D 4 3 - 70 5 2 0.05 0.025 Y N N 3 1
+#data/SO3_10000.xyz - - - 0 9 3 0.7 0.35 Y N N 60 1
+#generate_moment_curve 0 1 - 30 3 1 0.005 0.0025 Y N N 60 1
+
+#------------------------------------------------------------------ From files --------------------------------------------------------------------------
+#data/SO3_50000.xyz - - - 0 9 3 0.05 0.05 Y N N 6000 1
+#data/SO3_10000.xyz - - - 0 9 3 0.1 0.1 Y N N 60000 1
+#data/cube3D_eps_0.1.xyz - - - 0 3 2 0.05 0.05 Y N N 3000 1
+#data/cube4D_eps_0.1.xyz - - - 0 4 3 0.05 0.05 N Y N 3000 1
+#data/cube5D_eps_0.1.xyz - - - 0 5 4 0.05 0.05 N Y N 3000 1
+#data/Cy8.xyz - - - 0 24 2 0.1 0.1 N Y N 60 1
+#data/Kl.xyz - - - 0 5 2 0.05 0.05 N Y N 60 1
+#data/S3.xyz - - - 0 4 3 0.05 0.05 N Y N 60 1
+
+#data/Alvarez_variete_k2_D4_29700p.xyz - - - 0 4 2 0.01 0.01 Y N N 60 1 # points on a "grid"
+#data/Alvarez_variete_k2_D4_10k_1x1_v2.xyz - - - 0 4 2 0.001 0.001 Y N N 200 1
+#data/Alvarez_variete_k2_D4_30k_1x1_v2.xyz - - - 0 4 2 0.001 0.001 Y N N 6000 1
+#data/Alvarez_variete_k2_D4_120k_2x2_denser_in_1x1.xyz - - - 0 4 2 0.002 0.002 Y N N 60000 1
+#data/Alvarez_variete_k2_D4_300k_2x2.xyz - - - 0 4 2 0.005 0.005 Y N N 100000 1
+#data/Alvarez_variete_k2_D4_300k_2x2.xyz - - - 0 4 2 0.05 0.05 Y N N 50000 1 # heavy sparsification (e.g. 0.05 => 33k points)
+#data/Alvarez_variete_k2_D4_90k_2x2.xyz - - - 0 4 2 0.003 0.003 Y N N 6000 1
+#data/Alvarez_variete_k2_D4_30k_10x10.xyz - - - 0 4 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_variete_k2_D4_60k_10x10.xyz - - - 0 4 2 0.01 0.01 Y N N 1800 1
+
+#data/Alvarez_variete_k2_D8_9003p.xyz - - - 0 8 2 0.001 0.001 Y N N 60 1
+#data/Alvarez_variete_k2_D8_90K.xyz - - - 0 8 2 0.001 0.001 Y N N 60 1
+#data/Alvarez_variete_k2_D8_300k_10x10.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1 # heavy sparsification
+#data/Alvarez_variete_k2_D8_900k_2x2.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1 # heavy sparsification
+#data/Alvarez_variete_k2_D8_900k_10x10.xyz - - - 0 8 2 0.02 0.02 Y N N 60 1 # heavy sparsification
+
+#data/Alvarez_courbeElliptique_k2_D8_200K_2x2.xyz - - - 0 8 2 0.006 0.006 Y N N 60 1
+
+#data/Alvarez_surface_deg2_k2_D8_6000K_10x10.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.003 0.003 Y N N 3600 1
+#data/Alvarez_surface_deg4_k2_D8_382K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg5_k2_D8_112K.xyz - - - 0 8 2 0.001 0.001 Y N N 240 1
+#data/Alvarez_surface_deg6_k2_D8_67K.xyz - - - 0 8 2 0.015 0.015 Y N N 60 1
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.025 0.025 Y N N 60 1
+#data/Alvarez_surface_deg9_k2_D8_42K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+#data/Alvarez_surface_deg10_k2_D8_41K.xyz - - - 0 8 2 0.01 0.01 Y N N 60 1
+
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.02 0.02 Y N N 600 1
+#data/sparsified/Alvarez_deg8_k2_D8_32K_sparsified_from_41K_0.01.xyz - - - 0 8 2 0.05 0.05 Y N N 600 1
+
+# PAS VRAIMENT DE DIFFERENCE
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.003 0.007 Y N N 3600 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.014 0.007 Y N N 3600 1
+
+# PAS VRAIMENT DE DIFFERENCE
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.01 0.005 Y N N 120 1
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.005 Y N N 120 1
+
+# PAS VRAIMENT DE DIFFERENCE
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.001 0.01 Y N N 3600 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.02 0.01 Y N N 3600 1
+#data/sparsified/Alvarez_deg3_k2_D8_534k_sparsified_from_902K_0.001.xyz - - - 0 8 2 0.01 0.01 Y N N 3600 1
+
+# PAS TRES CLAIR, MAIS DIFFERENCE EN NOMBRE D'ETAPES (>100 vs 15-20) :
+#data/sparsified/Alvarez_deg8_k2_D8_38K_sparsified_from_41K_0.005.xyz - - - 0 8 2 0.02 0.02 Y N N 600 1
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.001 0.02 Y N N 60 1
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.025 0.02 Y N N 60 1
+
+# With pre-computed tangent spaces
+#data/test.pwt - - - 0 4 2 0.01 0.01 N N N 500000 1
+#data/Alvarez_variete_k2_D4_30000p.xyz - - - 0 4 2 0.01 0.01 Y N N 500000 1
+#data/Alvarez_variete_k2_D4_30000p_with_TSB.pwt - - - 0 4 2 0.01 0.01 Y N N 500000 1
+
+#---------------------------------------------------------------------- 3D meshes -----------------------------------------------------------------------
+#data/buddha_100kv.xyz - - - 0 3 2 0.005 0.005 Y N N 3 1
+#data/fandisk.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/fertility.xyz - - - 0 3 2 0.4 0.4 Y N N 3 1
+#data/bunny.xyz - - - 0 3 2 0.0006 0.0003 Y N N 3000 1
+#data/blob.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/3holes.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/785_hand_2500v.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/785_hand_50kv.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#data/bumpy_sphere.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#D:\INRIA\Data\_Models\Pointclouds\ajax_jotero.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#D:\INRIA\Data\_Models\Pointclouds\house.xyz - - - 0 3 2 0.01 0.01 Y N N 3 1
+#D:\INRIA\Data\_Models\Pointclouds\lucy_14M.xyz - - - 0 3 2 0.6 0.3 Y N N 3 1
+
+#----------------------------------------------------------- Generated point sets -----------------------------------------------------------------------
+#generate_sphere_d 3 - - 4 3 2 0.05 0.05 Y N N 3000 1
+#generate_sphere_d 3 - - 30000 2 1 0.005 0.005 Y N N 3000 1
+#generate_sphere_d 1 - - 500000 3 2 0.005 0.005 Y N N 3000 1
+#generate_sphere_d 3 - - 30000 4 3 0.05 0.05 Y N N 3000 1
+#generate_sphere_d 3 0 - 300 3 2 0.005 0.005 Y N N 60 1
+#generate_sphere_d 3 4 - 3000 3 2 0.005 0.005 Y N N 60 1
+#generate_sphere_d 3 7 - 3000 3 2 0.005 0.005 Y N N 60 1
+#generate_torus_3D 2 1 N 300 3 2 0.05 0.05 Y N N 600 1
+#generate_torus_d N - - 200 4 2 0.05 0.05 Y N N 600 1
+
+#generate_torus_d Y - - 100 6 3 0.1 0.19 Y N N 600 1
+#generate_torus_d Y - - 1000 6 3 0. 0.19 Y N N 600 1
+#generate_torus_d Y - - 10000 6 3 0. 0.19 Y N N 600 1
+#generate_torus_d Y - - 100000 6 3 0. 0.19 Y N N 600 1
+#generate_plane - - - 30000 3 2 0.005 0.005 Y N N 3000 1
+#generate_moment_curve 0 1 - 30000 6 1 0.005 0.005 Y N N 60 1
+#generate_klein_bottle_4D 4 3 - 700 4 2 0.05 0.05 Y N N 500 20
+#generate_klein_bottle_variant_5D 4 3 - 30000 5 2 0.05 0.05 Y N N 600 1
+#generate_klein_bottle_4D 8 5 - 5000 4 2 0.2 0.2 Y N N 60 1 #Takes forever
+#data/sparsified/Flat_torus_195p_sparsified_0.05_from_200p.xyz N - - 0 4 2 -1 0.2 Y N N 600 1
+
+#----------------------------------------------------------- Performance testing ------------------------------------------------------------------------
+# TC: 5.55 / 1st fix step : 0.2
+#data/fertility.xyz - - - 0 3 2 0.1 0.1 Y N N 10 1
+
+#---------------------------------------------------------- 04/04/2016 - for stats ----------------------------------------------------------
+
+#generate_torus_3D 2 1 N 5000 3 2 0.05 0.05 Y N N 120 1
+#generate_torus_d N - - 500 4 2 0.05 0.05 Y N N 120 1
+#data/Alvarez_variete_k2_D8_900k_2x2.xyz - - - 0 8 2 0.005 0.005 Y N N 120 1
+#data/Alvarez_surface_deg3_k2_D8_902K.xyz - - - 0 8 2 0.01 0.01 Y N N 120 1
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.02 Y N N 600 10
+#data/Alvarez_surface_deg8_k2_D8_41K.xyz - - - 0 8 2 0.02 0.02 Y N N 120 1
+#data/Alvarez_surface_deg10_k2_D8_41K.xyz - - - 0 8 2 0.02 0.02 Y N N 120 1
+#generate_torus_d N - - 200000 6 3 0.05 0.05 Y N N 1200 1
+
+#---------------------------------------------------------- 14/04/2016 - stats about noise ----------------------------------------------------------
+
+#generate_torus_d Y 0 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 1 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 2 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 3 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 4 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 5 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 6 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 7 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 8 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 9 - 1000 4 2 0.05 0.19 Y N N 120 4
+#generate_torus_d Y 10 - 1000 4 2 0.05 0.19 Y N N 120 4
+
+#generate_sphere_d 3 0 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 1 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 2 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 3 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 4 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 5 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 6 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 7 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 8 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 9 - 1000 4 3 0.05 0.05 Y N N 120 4
+#generate_sphere_d 3 10 - 1000 4 3 0.05 0.05 Y N N 120 4
+
+#generate_klein_bottle_4D 4 3 0 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.01 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.02 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.03 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.04 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.05 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.06 5000 4 2 0.05 0.05 Y N N 120 4
+#generate_klein_bottle_4D 4 3 0.07 5000 4 2 0.05 0.05 Y N N 120 4
+
+#---------------------------------------------------------- 04/2016 - stats with different perturb techniques ----------------------------------------------------------
+
+# Tangential translation
+#data/SO3_50000.xyz - - - 0 9 3 0 0.05 Y N N 500 10
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.01 Y N N 120 10
+#generate_klein_bottle_4D 4 3 0 5000 4 2 0.05 0.05 Y N N 120 10
+#generate_torus_d Y 0 - 1000 4 2 0.05 0.19 Y N N 120 10
+#generate_sphere_d 3 1 - 1000 4 3 0.05 0.05 Y N N 120 10
+
+# Weight
+#data/SO3_50000.xyz - - - 0 9 3 0.1 0.05 Y N N 500 10
+#data/Alvarez_surface_deg7_k2_D8_48K.xyz - - - 0 8 2 0.02 0.01 Y N N 120 10
+#generate_klein_bottle_4D 4 3 0 5000 4 2 0.05 0.025 Y N N 20000 10
+#generate_torus_d Y 0 - 1000 4 2 0.05 0.025 Y N N 120 10
+#generate_sphere_d 3 1 - 1000 4 3 0.05 0.025 Y N N 12000 10 \ No newline at end of file
diff --git a/src/Tangential_complex/benchmark/benchmark_tc.cpp b/src/Tangential_complex/benchmark/benchmark_tc.cpp
new file mode 100644
index 00000000..e3b2a04f
--- /dev/null
+++ b/src/Tangential_complex/benchmark/benchmark_tc.cpp
@@ -0,0 +1,781 @@
+/******************************************************************************
+This benchmark allows to compute the Tangential Complex from input files or
+generated point sets.
+
+It reads the benchmark_script.txt file (located in the same folder as this
+file) and compute one or several complexes for each line. Unless TC_NO_EXPORT
+is defined, each complex is exported as an OFF file and/or as a RIB file
+(RenderMan). In addition an XML file is created at each run of the benchmark.
+It contains statistics about the complexes that were created. This XML file
+can be processed in Excel, for example.
+ ******************************************************************************/
+
+// Without TBB_USE_THREADING_TOOL Intel Inspector XE will report false positives in Intel TBB
+// (http://software.intel.com/en-us/articles/compiler-settings-for-threading-error-analysis-in-intel-inspector-xe/)
+#ifdef _DEBUG
+#define TBB_USE_THREADING_TOOL
+#endif
+
+#include <cstddef>
+
+//#define GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+//#define TC_INPUT_STRIDES 3 // only take one point every TC_INPUT_STRIDES points
+#define TC_NO_EXPORT // do not output OFF files
+//#define TC_EXPORT_TO_RIB //
+//#define GUDHI_TC_EXPORT_SPARSIFIED_POINT_SET
+//#define GUDHI_TC_EXPORT_ALL_COORDS_IN_OFF
+
+const std::size_t ONLY_LOAD_THE_FIRST_N_POINTS = 20000000;
+
+#include <gudhi/Debug_utils.h>
+#include <gudhi/Clock.h>
+#include <gudhi/Tangential_complex.h>
+#include <gudhi/sparsify_point_set.h>
+#include <gudhi/random_point_generators.h>
+#include <gudhi/Tangential_complex/utilities.h>
+
+#include <CGAL/assertions_behaviour.h>
+#include <CGAL/Epick_d.h>
+#include <CGAL/Random.h>
+
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/algorithm/string/trim_all.hpp>
+#include <boost/range/adaptor/strided.hpp>
+
+#include <cstdlib>
+#include <ctime>
+#include <fstream>
+#include <cmath> // for std::sqrt
+
+#ifdef GUDHI_USE_TBB
+#include <tbb/task_scheduler_init.h>
+#endif
+#include "XML_exporter.h"
+#include "RIB_exporter.h"
+#define GUDHI_TC_EXPORT_PERFORMANCE_DATA
+#define GUDHI_TC_SET_PERFORMANCE_DATA(value_name, value) \
+ XML_perf_data::set(value_name, value);
+
+
+namespace subsampl = Gudhi::subsampling;
+namespace tc = Gudhi::tangential_complex;
+
+const char * const BENCHMARK_SCRIPT_FILENAME = "benchmark_script.txt";
+
+typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> Kernel;
+typedef Kernel::FT FT;
+typedef Kernel::Point_d Point;
+typedef Kernel::Vector_d Vector;
+typedef tc::Tangential_complex<
+Kernel, CGAL::Dynamic_dimension_tag,
+CGAL::Parallel_tag> TC;
+typedef TC::Simplex Simplex;
+typedef TC::Simplex_set Simplex_set;
+
+class XML_perf_data {
+ public:
+ typedef Streaming_XML_exporter<std::string> XML_exporter;
+
+ XML_perf_data(const std::string &filename)
+ : m_xml(filename, "ContainerPerformance", "Perf",
+ construct_subelements_names()) { }
+
+ virtual ~XML_perf_data() { }
+
+ static XML_perf_data &get() {
+ static XML_perf_data singleton(build_filename());
+ return singleton;
+ }
+
+ template <typename Value_type>
+ static void set(const std::string &name, Value_type value) {
+ get().set_data(name, value);
+ }
+
+ static void commit() {
+ get().commit_current_element();
+ }
+
+ protected:
+
+ static std::string build_filename() {
+ std::stringstream sstr;
+ sstr << "perf_logs/Performance_log_" << time(0) << ".xml";
+ return sstr.str();
+ }
+
+ static std::vector<std::string> construct_subelements_names() {
+ std::vector<std::string> subelements;
+ subelements.push_back("Input");
+ subelements.push_back("Param1");
+ subelements.push_back("Param2");
+ subelements.push_back("Param3");
+ subelements.push_back("Intrinsic_dim");
+ subelements.push_back("Ambient_dim");
+ subelements.push_back("Num_threads");
+ subelements.push_back("Sparsity");
+ subelements.push_back("Max_perturb");
+ subelements.push_back("Num_points_in_input");
+ subelements.push_back("Num_points");
+ subelements.push_back("Perturb_technique");
+ subelements.push_back("Perturb_which_points");
+ subelements.push_back("Initial_num_inconsistent_local_tr");
+ subelements.push_back("Best_num_inconsistent_local_tr");
+ subelements.push_back("Final_num_inconsistent_local_tr");
+ subelements.push_back("Init_time");
+ subelements.push_back("Comput_time");
+ subelements.push_back("Perturb_successful");
+ subelements.push_back("Perturb_time");
+ subelements.push_back("Perturb_steps");
+ subelements.push_back("Result_pure_pseudomanifold");
+ subelements.push_back("Result_num_wrong_dim_simplices");
+ subelements.push_back("Result_num_wrong_number_of_cofaces");
+ subelements.push_back("Result_num_unconnected_stars");
+ subelements.push_back("Info");
+
+ return subelements;
+ }
+
+ void set_data(const std::string &name, const std::string &value) {
+ m_current_element[name] = value;
+ }
+
+ template <typename Value_type>
+ void set_data(const std::string &name, Value_type value) {
+ std::stringstream sstr;
+ sstr << value;
+ set_data(name, sstr.str());
+ }
+
+ void commit_current_element() {
+ m_xml.add_element(m_current_element);
+ m_current_element.clear();
+ }
+
+ XML_exporter m_xml;
+ XML_exporter::Element_with_map m_current_element;
+};
+
+template<
+typename Kernel, typename OutputIteratorPoints>
+bool load_points_from_file(
+ const std::string &filename,
+ OutputIteratorPoints points,
+ std::size_t only_first_n_points = (std::numeric_limits<std::size_t>::max)()) {
+ typedef typename Kernel::Point_d Point;
+
+ std::ifstream in(filename);
+ if (!in.is_open()) {
+ std::cerr << "Could not open '" << filename << "'" << std::endl;
+ return false;
+ }
+
+ Kernel k;
+ Point p;
+ int num_ppints;
+ in >> num_ppints;
+
+ std::size_t i = 0;
+ while (i < only_first_n_points && in >> p) {
+ *points++ = p;
+ ++i;
+ }
+
+#ifdef DEBUG_TRACES
+ std::cerr << "'" << filename << "' loaded." << std::endl;
+#endif
+
+ return true;
+}
+
+template<
+typename Kernel, typename Tangent_space_basis,
+typename OutputIteratorPoints, typename OutputIteratorTS>
+bool load_points_and_tangent_space_basis_from_file(
+ const std::string &filename,
+ OutputIteratorPoints points,
+ OutputIteratorTS tangent_spaces,
+ int intrinsic_dim,
+ std::size_t only_first_n_points = (std::numeric_limits<std::size_t>::max)()) {
+ typedef typename Kernel::Point_d Point;
+ typedef typename Kernel::Vector_d Vector;
+
+ std::ifstream in(filename);
+ if (!in.is_open()) {
+ std::cerr << "Could not open '" << filename << "'" << std::endl;
+ return false;
+ }
+
+ Kernel k;
+ Point p;
+ int num_ppints;
+ in >> num_ppints;
+
+ std::size_t i = 0;
+ while (i < only_first_n_points && in >> p) {
+ *points++ = p;
+
+ Tangent_space_basis tsb(i);
+ for (int d = 0; d < intrinsic_dim; ++d) {
+ Vector v;
+ in >> v;
+ tsb.push_back(tc::internal::normalize_vector(v, k));
+ }
+ *tangent_spaces++ = tsb;
+ ++i;
+ }
+
+#ifdef DEBUG_TRACES
+ std::cerr << "'" << filename << "' loaded." << std::endl;
+#endif
+
+ return true;
+}
+
+// color_inconsistencies: only works if p_complex = NULL
+template <typename TC>
+bool export_to_off(
+ TC const& tc,
+ std::string const& input_name_stripped,
+ std::string const& suffix,
+ bool color_inconsistencies = false,
+ typename TC::Simplicial_complex const* p_complex = NULL,
+ Simplex_set const *p_simpl_to_color_in_red = NULL,
+ Simplex_set const *p_simpl_to_color_in_green = NULL,
+ Simplex_set const *p_simpl_to_color_in_blue = NULL) {
+#ifdef TC_NO_EXPORT
+ return true;
+#endif
+
+ CGAL::Identity<Point> proj_functor;
+
+ if (tc.intrinsic_dimension() <= 3) {
+ std::stringstream output_filename;
+ output_filename << "output/" << input_name_stripped << "_"
+ << tc.intrinsic_dimension() << "_in_R"
+ << tc.ambient_dimension() << "_"
+ << tc.number_of_vertices() << "v"
+ << suffix << ".off";
+ std::ofstream off_stream(output_filename.str().c_str());
+
+ if (p_complex) {
+#ifndef TC_NO_EXPORT
+ tc.export_to_off(
+ *p_complex, off_stream,
+ p_simpl_to_color_in_red,
+ p_simpl_to_color_in_green,
+ p_simpl_to_color_in_blue,
+ proj_functor);
+#endif
+ } else {
+ tc.export_to_off(
+ off_stream, color_inconsistencies,
+ p_simpl_to_color_in_red,
+ p_simpl_to_color_in_green,
+ p_simpl_to_color_in_blue,
+ NULL,
+ proj_functor);
+ }
+ return true;
+ }
+ return false;
+}
+
+void make_tc(std::vector<Point> &points,
+ TC::TS_container const& tangent_spaces, // can be empty
+ int intrinsic_dim,
+ double sparsity = 0.01,
+ double max_perturb = 0.005,
+ bool perturb = true,
+ bool add_high_dim_simpl = false,
+ bool collapse = false,
+ double time_limit_for_perturb = 0.,
+ const char *input_name = "tc") {
+ Kernel k;
+
+ if (sparsity > 0. && !tangent_spaces.empty()) {
+ std::cerr << "Error: cannot sparsify point set with pre-computed normals.\n";
+ return;
+ }
+
+ //===========================================================================
+ // Init
+ //===========================================================================
+ Gudhi::Clock t;
+
+ // Get input_name_stripped
+ std::string input_name_stripped(input_name);
+ size_t slash_index = input_name_stripped.find_last_of('/');
+ if (slash_index == std::string::npos)
+ slash_index = input_name_stripped.find_last_of('\\');
+ if (slash_index == std::string::npos)
+ slash_index = 0;
+ else
+ ++slash_index;
+ input_name_stripped = input_name_stripped.substr(
+ slash_index, input_name_stripped.find_last_of('.') - slash_index);
+
+ GUDHI_TC_SET_PERFORMANCE_DATA("Num_points_in_input", points.size());
+
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ std::vector<Point> points_not_sparse = points;
+#endif
+
+ //===========================================================================
+ // Sparsify point set if requested
+ //===========================================================================
+ if (sparsity > 0.) {
+ std::size_t num_points_before = points.size();
+ std::vector<Point> sparsified_points;
+ subsampl::sparsify_point_set(k, points, sparsity*sparsity,
+ std::back_inserter(sparsified_points));
+ sparsified_points.swap(points);
+ std::cerr << "Number of points before/after sparsification: "
+ << num_points_before << " / " << points.size() << "\n";
+
+#ifdef GUDHI_TC_EXPORT_SPARSIFIED_POINT_SET
+ std::ofstream ps_stream("output/sparsified_point_set.txt");
+ tc::internal::export_point_set(k, points, ps_stream);
+#endif
+ }
+
+ GUDHI_TC_SET_PERFORMANCE_DATA("Sparsity", sparsity);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Max_perturb", max_perturb);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Num_points", points.size());
+
+ //===========================================================================
+ // Compute Tangential Complex
+ //===========================================================================
+
+ TC tc(
+ points,
+ intrinsic_dim,
+#ifdef GUDHI_TC_USE_ANOTHER_POINT_SET_FOR_TANGENT_SPACE_ESTIM
+ points_not_sparse.begin(), points_not_sparse.end(),
+#endif
+ k);
+
+ if (!tangent_spaces.empty()) {
+ tc.set_tangent_planes(tangent_spaces);
+ }
+
+ t.end();
+ double init_time = t.num_seconds();
+
+ t.begin();
+ tc.compute_tangential_complex();
+ t.end();
+ double computation_time = t.num_seconds();
+
+ //===========================================================================
+ // Export to OFF
+ //===========================================================================
+
+ // Create complex
+ int max_dim = -1;
+ TC::Simplicial_complex complex;
+ Simplex_set inconsistent_simplices;
+ max_dim = tc.create_complex(complex, true, false, 2, &inconsistent_simplices);
+
+ // TODO(CJ): TEST
+ Gudhi::Simplex_tree<> stree;
+ tc.create_complex(stree, true, false);
+ // std::cerr << stree;
+
+ t.begin();
+ bool ret = export_to_off(
+ tc, input_name_stripped, "_INITIAL_TC", true,
+ &complex, &inconsistent_simplices);
+ t.end();
+ double export_before_time = (ret ? t.num_seconds() : -1);
+
+ unsigned int num_perturb_steps = 0;
+ double perturb_time = -1;
+ double export_after_perturb_time = -1.;
+ bool perturb_success = false;
+ if (perturb) {
+ //=========================================================================
+ // Try to fix inconsistencies by perturbing points
+ //=========================================================================
+ t.begin();
+ auto fix_result =
+ tc.fix_inconsistencies_using_perturbation(max_perturb, time_limit_for_perturb);
+ t.end();
+ perturb_time = t.num_seconds();
+
+ perturb_success = fix_result.success;
+ GUDHI_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr",
+ fix_result.initial_num_inconsistent_stars);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr",
+ fix_result.best_num_inconsistent_stars);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr",
+ fix_result.final_num_inconsistent_stars);
+
+ //=========================================================================
+ // Export to OFF
+ //=========================================================================
+
+ // Re-build the complex
+ Simplex_set inconsistent_simplices;
+ max_dim = tc.create_complex(complex, true, false, 2, &inconsistent_simplices);
+
+ t.begin();
+ bool exported = export_to_off(
+ tc, input_name_stripped, "_AFTER_FIX", true, &complex,
+ &inconsistent_simplices);
+ t.end();
+ export_after_perturb_time = (exported ? t.num_seconds() : -1);
+
+ //std::string fn = "output/inc_stars/";
+ //fn += input_name_stripped;
+ //tc.export_inconsistent_stars_to_OFF_files(fn);
+
+#if !defined(TC_NO_EXPORT) && defined(TC_EXPORT_TO_RIB)
+ std::ofstream rib(std::string("output/") + input_name_stripped + ".rib");
+ RIB_exporter<TC::Points, TC::Simplicial_complex::Simplex_set> rib_exporter(
+ tc.points(),
+ complex.simplex_range(),
+ rib,
+ input_name_stripped + ".tif",
+ false, // is_preview
+ std::make_tuple(2, 4, 6),
+ 1600, 503 // resolution
+ );
+ rib_exporter.write_file();
+
+ std::ofstream rib_LQ(std::string("output/") + input_name_stripped + "_LQ.rib");
+ RIB_exporter<TC::Points, TC::Simplicial_complex::Simplex_set> rib_exporter_LQ(
+ tc.points(),
+ complex.simplex_range(),
+ rib_LQ,
+ input_name_stripped + "_LQ.tif",
+ true, // is_preview
+ std::make_tuple(0, 4, 5)
+ );
+ rib_exporter_LQ.write_file();
+#endif
+ } else {
+ GUDHI_TC_SET_PERFORMANCE_DATA("Initial_num_inconsistent_local_tr", "N/A");
+ GUDHI_TC_SET_PERFORMANCE_DATA("Best_num_inconsistent_local_tr", "N/A");
+ GUDHI_TC_SET_PERFORMANCE_DATA("Final_num_inconsistent_local_tr", "N/A");
+ }
+
+ max_dim = tc.create_complex(complex, true, false, 2);
+
+ complex.display_stats();
+
+ if (intrinsic_dim == 2)
+ complex.euler_characteristic(true);
+
+ //===========================================================================
+ // Collapse
+ //===========================================================================
+ if (collapse) {
+ complex.collapse(max_dim);
+ complex.display_stats();
+ }
+
+ //===========================================================================
+ // Is the result a pure pseudomanifold?
+ //===========================================================================
+ std::size_t num_wrong_dim_simplices,
+ num_wrong_number_of_cofaces,
+ num_unconnected_stars;
+ Simplex_set wrong_dim_simplices;
+ Simplex_set wrong_number_of_cofaces_simplices;
+ Simplex_set unconnected_stars_simplices;
+ bool is_pure_pseudomanifold = complex.is_pure_pseudomanifold(
+ intrinsic_dim, tc.number_of_vertices(),
+ false, // do NOT allow borders
+ false, 1,
+ &num_wrong_dim_simplices, &num_wrong_number_of_cofaces,
+ &num_unconnected_stars,
+ &wrong_dim_simplices, &wrong_number_of_cofaces_simplices,
+ &unconnected_stars_simplices);
+
+ //===========================================================================
+ // Export to OFF
+ //===========================================================================
+
+ double export_after_collapse_time = -1.;
+ if (collapse) {
+ t.begin();
+ bool exported = export_to_off(
+ tc, input_name_stripped, "_AFTER_COLLAPSE", false, &complex,
+ &wrong_dim_simplices, &wrong_number_of_cofaces_simplices,
+ &unconnected_stars_simplices);
+ t.end();
+ std::cerr
+ << " OFF colors:\n"
+ << " * Red: wrong dim simplices\n"
+ << " * Green: wrong number of cofaces simplices\n"
+ << " * Blue: not-connected stars\n";
+ export_after_collapse_time = (exported ? t.num_seconds() : -1.);
+ }
+
+ //===========================================================================
+ // Display info
+ //===========================================================================
+
+ std::cerr
+ << "\n================================================\n"
+ << "Number of vertices: " << tc.number_of_vertices() << "\n"
+ << "Computation times (seconds): \n"
+ << " * Tangential complex: " << init_time + computation_time << "\n"
+ << " - Init + kd-tree = " << init_time << "\n"
+ << " - TC computation = " << computation_time << "\n"
+ << " * Export to OFF (before perturb): " << export_before_time << "\n"
+ << " * Fix inconsistencies 1: " << perturb_time
+ << " (" << num_perturb_steps << " steps) ==> "
+ << (perturb_success ? "FIXED" : "NOT fixed") << "\n"
+ << " * Export to OFF (after perturb): " << export_after_perturb_time << "\n"
+ << " * Export to OFF (after collapse): "
+ << export_after_collapse_time << "\n"
+ << "================================================\n";
+
+ //===========================================================================
+ // Export info
+ //===========================================================================
+ GUDHI_TC_SET_PERFORMANCE_DATA("Init_time", init_time);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_successful",
+ (perturb_success ? 1 : 0));
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_time", perturb_time);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_steps", num_perturb_steps);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_pure_pseudomanifold",
+ (is_pure_pseudomanifold ? 1 : 0));
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_num_wrong_dim_simplices",
+ num_wrong_dim_simplices);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_num_wrong_number_of_cofaces",
+ num_wrong_number_of_cofaces);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Result_num_unconnected_stars",
+ num_unconnected_stars);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Info", "");
+}
+
+int main() {
+ CGAL::set_error_behaviour(CGAL::ABORT);
+
+#ifdef GUDHI_USE_TBB
+#ifdef _DEBUG
+ int num_threads = 1;
+#else
+ int num_threads = tbb::task_scheduler_init::default_num_threads() - 4;
+#endif
+#endif
+
+ std::ifstream script_file;
+ script_file.open(BENCHMARK_SCRIPT_FILENAME);
+ // Script?
+ // Script file format: each line gives
+ // - Filename (point set) or "generate_XXX" (point set generation)
+ // - Ambient dim
+ // - Intrinsic dim
+ // - Number of iterations with these parameters
+ if (script_file.is_open()) {
+ int i = 1;
+#ifdef GUDHI_USE_TBB
+#ifdef BENCHMARK_WITH_1_TO_MAX_THREADS
+ for (num_threads = 1;
+ num_threads <= tbb::task_scheduler_init::default_num_threads();
+ ++num_threads)
+#endif
+#endif
+ /*for (Concurrent_mesher_config::get().num_work_items_per_batch = 5 ;
+ Concurrent_mesher_config::get().num_work_items_per_batch < 100 ;
+ Concurrent_mesher_config::get().num_work_items_per_batch += 5)*/ {
+#ifdef GUDHI_USE_TBB
+ tbb::task_scheduler_init init(
+ num_threads > 0 ? num_threads : tbb::task_scheduler_init::automatic);
+#endif
+
+ std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' found.\n";
+ script_file.seekg(0);
+ while (script_file.good()) {
+ std::string line;
+ std::getline(script_file, line);
+ if (line.size() > 1 && line[0] != '#') {
+ boost::replace_all(line, "\t", " ");
+ boost::trim_all(line);
+ std::cerr << "\n\n";
+ std::cerr << "*****************************************\n";
+ std::cerr << "******* " << line << "\n";
+ std::cerr << "*****************************************\n";
+ std::stringstream sstr(line);
+
+ std::string input;
+ std::string param1;
+ std::string param2;
+ std::string param3;
+ std::size_t num_points;
+ int ambient_dim;
+ int intrinsic_dim;
+ double sparsity;
+ double max_perturb;
+ char perturb, add_high_dim_simpl, collapse;
+ double time_limit_for_perturb;
+ int num_iteration;
+ sstr >> input;
+ sstr >> param1;
+ sstr >> param2;
+ sstr >> param3;
+ sstr >> num_points;
+ sstr >> ambient_dim;
+ sstr >> intrinsic_dim;
+ sstr >> sparsity;
+ sstr >> max_perturb;
+ sstr >> perturb;
+ sstr >> add_high_dim_simpl;
+ sstr >> collapse;
+ sstr >> time_limit_for_perturb;
+ sstr >> num_iteration;
+
+ for (int j = 0; j < num_iteration; ++j) {
+ std::string input_stripped = input;
+ size_t slash_index = input_stripped.find_last_of('/');
+ if (slash_index == std::string::npos)
+ slash_index = input_stripped.find_last_of('\\');
+ if (slash_index == std::string::npos)
+ slash_index = 0;
+ else
+ ++slash_index;
+ input_stripped = input_stripped.substr(
+ slash_index, input_stripped.find_last_of('.') - slash_index);
+
+ GUDHI_TC_SET_PERFORMANCE_DATA("Input", input_stripped);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Param1", param1);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Param2", param2);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Param3", param3);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Ambient_dim", ambient_dim);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", intrinsic_dim);
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_technique", "Tangential_translation");
+ GUDHI_TC_SET_PERFORMANCE_DATA("Perturb_which_points", "Center_vertex");
+
+#ifdef GUDHI_USE_TBB
+ GUDHI_TC_SET_PERFORMANCE_DATA(
+ "Num_threads",
+ (num_threads == -1 ? tbb::task_scheduler_init::default_num_threads() : num_threads));
+#else
+ GUDHI_TC_SET_PERFORMANCE_DATA("Num_threads", "N/A");
+#endif
+
+ std::cerr << "\nTC #" << i << "...\n";
+
+#ifdef GUDHI_TC_PROFILING
+ Gudhi::Clock t_gen;
+#endif
+
+ std::vector<Point> points;
+ TC::TS_container tangent_spaces;
+
+ if (input == "generate_moment_curve") {
+ points = Gudhi::generate_points_on_moment_curve<Kernel>(
+ num_points, ambient_dim,
+ std::atof(param1.c_str()), std::atof(param2.c_str()));
+ } else if (input == "generate_plane") {
+ points = Gudhi::generate_points_on_plane<Kernel>(
+ num_points, intrinsic_dim, ambient_dim);
+ } else if (input == "generate_sphere_d") {
+ points = Gudhi::generate_points_on_sphere_d<Kernel>(
+ num_points, ambient_dim,
+ std::atof(param1.c_str()), // radius
+ std::atof(param2.c_str())); // radius_noise_percentage
+ } else if (input == "generate_two_spheres_d") {
+ points = Gudhi::generate_points_on_two_spheres_d<Kernel>(
+ num_points, ambient_dim,
+ std::atof(param1.c_str()),
+ std::atof(param2.c_str()),
+ std::atof(param3.c_str()));
+ } else if (input == "generate_3sphere_and_circle_d") {
+ GUDHI_CHECK(intrinsic_dim == 3,
+ std::logic_error("Intrinsic dim should be 3"));
+ GUDHI_CHECK(ambient_dim == 5,
+ std::logic_error("Ambient dim should be 5"));
+ points = Gudhi::generate_points_on_3sphere_and_circle<Kernel>(
+ num_points,
+ std::atof(param1.c_str()));
+ } else if (input == "generate_torus_3D") {
+ points = Gudhi::generate_points_on_torus_3D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()),
+ std::atof(param2.c_str()),
+ param3 == "Y");
+ } else if (input == "generate_torus_d") {
+ points = Gudhi::generate_points_on_torus_d<Kernel>(
+ num_points,
+ intrinsic_dim,
+ param1 == "Y", // uniform
+ std::atof(param2.c_str())); // radius_noise_percentage
+ } else if (input == "generate_klein_bottle_3D") {
+ points = Gudhi::generate_points_on_klein_bottle_3D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()), std::atof(param2.c_str()));
+ } else if (input == "generate_klein_bottle_4D") {
+ points = Gudhi::generate_points_on_klein_bottle_4D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()), std::atof(param2.c_str()),
+ std::atof(param3.c_str())); // noise
+ } else if (input == "generate_klein_bottle_variant_5D") {
+ points = Gudhi::generate_points_on_klein_bottle_variant_5D<Kernel>(
+ num_points,
+ std::atof(param1.c_str()), std::atof(param2.c_str()));
+ } else {
+ // Contains tangent space basis
+ if (input.substr(input.size() - 3) == "pwt") {
+ load_points_and_tangent_space_basis_from_file
+ <Kernel, typename TC::Tangent_space_basis > (
+ input, std::back_inserter(points),
+ std::back_inserter(tangent_spaces),
+ intrinsic_dim,
+ ONLY_LOAD_THE_FIRST_N_POINTS);
+ } else {
+ load_points_from_file<Kernel>(
+ input, std::back_inserter(points),
+ ONLY_LOAD_THE_FIRST_N_POINTS);
+ }
+ }
+
+#ifdef GUDHI_TC_PROFILING
+ t_gen.end();
+ std::cerr << "Point set generated/loaded in " << t_gen.num_seconds()
+ << " seconds.\n";
+#endif
+
+ if (!points.empty()) {
+#if defined(TC_INPUT_STRIDES) && TC_INPUT_STRIDES > 1
+ auto p = points | boost::adaptors::strided(TC_INPUT_STRIDES);
+ std::vector<Point> points(p.begin(), p.end());
+ std::cerr << "****************************************\n"
+ << "WARNING: taking 1 point every " << TC_INPUT_STRIDES
+ << " points.\n"
+ << "****************************************\n";
+#endif
+
+ make_tc(points, tangent_spaces, intrinsic_dim,
+ sparsity, max_perturb,
+ perturb == 'Y', add_high_dim_simpl == 'Y', collapse == 'Y',
+ time_limit_for_perturb, input.c_str());
+
+ std::cerr << "TC #" << i++ << " done.\n";
+ std::cerr << "\n---------------------------------\n";
+ } else {
+ std::cerr << "TC #" << i++ << ": no points loaded.\n";
+ }
+
+ XML_perf_data::commit();
+ }
+ }
+ }
+ script_file.seekg(0);
+ script_file.clear();
+ }
+
+ script_file.close();
+ } // Or not script?
+ else {
+ std::cerr << "Script file '" << BENCHMARK_SCRIPT_FILENAME << "' NOT found.\n";
+ }
+
+ // system("pause");
+ return 0;
+}