diff --git a/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt new file mode 100644 index 00000000000..7155f246c2b --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/CMakeLists.txt @@ -0,0 +1,77 @@ +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + + +project( Tangential_complex_benchmark ) + +cmake_minimum_required(VERSION 2.6.2) +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) + cmake_policy(VERSION 2.8.4) + else() + cmake_policy(VERSION 2.6) + endif() +endif() + +# Creates a new CMake option, turned ON by default +option(ACTIVATE_MSVC_PRECOMPILED_HEADERS + "Activate precompiled headers in MSVC" + OFF) + +# Macro to add precompiled headers for MSVC +# This function does two things: +# 1. Enable precompiled headers on each file which is listed in "SourcesVar". +# 2. Add the content of "PrecompiledSource" (e.g. "StdAfx.cpp") to "SourcesVar". +MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar) + IF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS) + GET_FILENAME_COMPONENT(PrecompiledBasename ${PrecompiledHeader} NAME_WE) + SET(Sources ${${SourcesVar}}) + + SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource} + PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\"") + SET_SOURCE_FILES_PROPERTIES(${Sources} + PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledHeaders}\" /FI\"${PrecompiledHeader}\"") + # Add precompiled header to SourcesVar + LIST(APPEND ${SourcesVar} ${PrecompiledSource}) + ENDIF(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS) +ENDMACRO(ADD_MSVC_PRECOMPILED_HEADER) + +# The compiler might need more memory because of precompiled headers +if(MSVC AND ACTIVATE_MSVC_PRECOMPILED_HEADERS AND NOT(MSVC_VERSION LESS 1310)) + set(CGAL_C_FLAGS "${CGAL_C_FLAGS} /Zm1000") + set(CGAL_CXX_FLAGS "${CGAL_CXX_FLAGS} /Zm1000") +endif() + +find_package(CGAL QUIET COMPONENTS Core ) + +if ( CGAL_FOUND ) + include( ${CGAL_USE_FILE} ) + + find_package( TBB QUIET ) + + if( TBB_FOUND ) + include(${TBB_USE_FILE}) + list(APPEND CGAL_3RD_PARTY_LIBRARIES ${TBB_LIBRARIES}) + endif() + + + include( CGAL_CreateSingleSourceCGALProgram ) + + find_package(Eigen3 3.1.0) + if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + include_directories (BEFORE "../../include") + include_directories (BEFORE "include") + + set (SOURCE_FILES "benchmark_tc.cpp") + ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" SOURCE_FILES) + create_single_source_cgal_program( ${SOURCE_FILES} ) + + else() + message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") + endif() + +else() + message(STATUS "This program requires the CGAL library, and will not be compiled.") +endif() + diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp b/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp new file mode 100644 index 00000000000..15668dcadef --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.cpp @@ -0,0 +1,2 @@ +// Build the precompiled headers. +#include "StdAfx.h" \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/StdAfx.h b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h new file mode 100644 index 00000000000..df71d9a8260 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/StdAfx.h @@ -0,0 +1,14 @@ +#ifndef STDAFX_H +#define STDAFX_H + +// CGAL +#include +#include +//#include +//#include +//#include +//#include +//#include +#include + +#endif //STDAFX_H \ No newline at end of file diff --git a/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h b/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h new file mode 100644 index 00000000000..158d3d648d4 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/XML_exporter.h @@ -0,0 +1,236 @@ +// Copyright (c) 2012 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// +// Author(s) : Clement Jamin +// + +#include +#include +#include +#include +#include + +template +class Simple_XML_exporter +{ +public: + typedef value_type Value_type; + typedef std::vector Element; + typedef std::map Element_with_map; + typedef std::vector List_of_elements; + + Simple_XML_exporter( + const std::string &list_name, + const std::string &element_name, + const std::vector &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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::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 << "" << 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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + + if (m_add_timestamp) + xmlfile << " " << time(NULL) << " " << std::endl; + + for (int i = 0 ; + it_subelement_name != it_subelement_name_end ; + ++it_subelement_name, ++i) + { + xmlfile + << " <" << *it_subelement_name << "> " + << (*it_element)[i] + << " " << std::endl; + } + xmlfile << " " << std::endl; + } + + xmlfile << "" << std::endl; + xmlfile.close(); + return 0; + + } + +protected: + std::string m_list_name; + std::string m_element_name; + std::vector m_subelement_names; + List_of_elements m_list_of_elements; + bool m_add_timestamp; +}; + + + + + +template +class Streaming_XML_exporter +{ +public: + typedef value_type Value_type; + typedef std::vector Element; + typedef std::map Element_with_map; + typedef std::vector List_of_elements; + + Streaming_XML_exporter( + const std::string &filename, + const std::string &list_name, + const std::string &element_name, + const std::vector &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 << "" << 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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::const_iterator + it_subelement_name_end = m_subelement_names.end(); + + if (m_add_timestamp) + { + m_xml_fstream << " " << time(NULL) << " " << 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] + << " " << std::endl; + } + m_xml_fstream << " " << 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 << "" << 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::const_iterator + it_subelement_name = m_subelement_names.begin(); + std::vector::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 m_subelement_names; + bool m_add_timestamp; +}; diff --git a/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp new file mode 100644 index 00000000000..391d5162155 --- /dev/null +++ b/Tangential_complex/benchmark/Tangential_complex/benchmark_tc.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include + +#include "../../test/Tangential_complex/test_utilities.h" + + +#include +#include + +#ifdef CGAL_LINKED_WITH_TBB +# include +#endif +#include "XML_exporter.h" +#define CGAL_TC_EXPORT_PERFORMANCE_DATA +#define CGAL_TC_SET_PERFORMANCE_DATA(value_name, value) \ + XML_perf_data::set(value_name, value); + +class XML_perf_data +{ +public: + typedef Streaming_XML_exporter 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 + 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 << "Performance_log_" << time(0) << ".xml"; + return sstr.str(); + } + + static std::vector construct_subelements_names() + { + std::vector subelements; + subelements.push_back("Name"); + subelements.push_back("Intrinsic_dim"); + subelements.push_back("Ambient_dim"); + subelements.push_back("Num_points"); + subelements.push_back("Noise"); + subelements.push_back("Init_time"); + subelements.push_back("Comput_time"); + subelements.push_back("Fix_time"); + + return subelements; + } + + void set_data(const std::string &name, const std::string &value) + { + m_current_element[name] = value; + } + + template + 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; +}; + +#ifdef _DEBUG + const int NUM_POINTS = 50; +#else + const int NUM_POINTS = 30000; +#endif + +int main() +{ +#ifdef CGAL_LINKED_WITH_TBB +# ifdef _DEBUG + tbb::task_scheduler_init init(1); +# else + tbb::task_scheduler_init init(10); +# endif +#endif + + const int INTRINSIC_DIMENSION = 2; + const int AMBIENT_DIMENSION = 4; + + typedef CGAL::Epick_d > Kernel; + typedef Kernel::FT FT; + typedef Kernel::Point_d Point; + + int i = 0; + bool stop = false; + //for ( ; !stop ; ++i) + { + Kernel k; + Wall_clock_timer t; + CGAL::default_random = CGAL::Random(i); + std::cerr << "Random seed = " << i << std::endl; + +#ifdef CGAL_TC_PROFILING + Wall_clock_timer t_gen; +#endif + //std::vector points; + //load_points_from_file( + // "data/points_10_10k.cin", std::back_inserter(points)/*, 600*/); + + std::vector points = + //generate_points_on_circle_2(NUM_POINTS, 3.); + //generate_points_on_moment_curve(NUM_POINTS, AMBIENT_DIMENSION, 0., 1.); + //generate_points_on_plane(NUM_POINTS); + //generate_points_on_sphere_3(NUM_POINTS, 3.0); + //generate_points_on_sphere_d(NUM_POINTS, AMBIENT_DIMENSION, 3.0); + //generate_points_on_klein_bottle_3D(NUM_POINTS, 4., 3.); + generate_points_on_klein_bottle_4D(NUM_POINTS, 4., 3.); + //generate_points_on_klein_bottle_variant_5D(NUM_POINTS, 4., 3.); + + + CGAL_TC_SET_PERFORMANCE_DATA("Name", "Klein bottle 4D"); + CGAL_TC_SET_PERFORMANCE_DATA("Intrinsic_dim", INTRINSIC_DIMENSION); + CGAL_TC_SET_PERFORMANCE_DATA("Ambient_dim", AMBIENT_DIMENSION); + CGAL_TC_SET_PERFORMANCE_DATA("Noise", 0.01); + +#ifdef CGAL_TC_PROFILING + std::cerr << "Point set generated in " << t_gen.elapsed() + << " seconds." << std::endl; +#endif + + std::cerr << "Number of points before sparsification: " + << points.size() << std::endl; + //points = sparsify_point_set( + // k, points, FT(INPUT_SPARSITY)*FT(INPUT_SPARSITY)); + std::cerr << "Number of points after sparsification: " + << points.size() << std::endl; + + CGAL::Tangential_complex< + Kernel, + INTRINSIC_DIMENSION, + CGAL::Parallel_tag> tc(points.begin(), points.end(), k); + double init_time = t.elapsed(); t.reset(); + + //tc.estimate_intrinsic_dimension(); + tc.compute_tangential_complex(); + double computation_time = t.elapsed(); t.reset(); + + std::set > incorrect_simplices; + //stop = !tc.check_if_all_simplices_are_in_the_ambient_delaunay(&incorrect_simplices); + + t.reset(); + tc.fix_inconsistencies(); + double fix_time = t.elapsed(); t.reset(); + + double export_time = -1.; + if (INTRINSIC_DIMENSION <= 3) + { + t.reset(); + std::stringstream output_filename; + output_filename << "data/test_tc_" << INTRINSIC_DIMENSION + << "_in_R" << AMBIENT_DIMENSION << ".off"; + std::ofstream off_stream(output_filename.str().c_str()); + tc.export_to_off(off_stream, true, &incorrect_simplices, true); + double export_time = t.elapsed(); t.reset(); + } + /*else + tc.number_of_inconsistent_simplices();*/ + + + std::cerr << std::endl + << "================================================" << std::endl + << "Number of vertices: " << tc.number_of_vertices() << std::endl + << "Computation times (seconds): " << std::endl + << " * Tangential complex: " << init_time + computation_time + << std::endl + << " - Init + kd-tree = " << init_time << std::endl + << " - TC computation = " << computation_time << std::endl + << " * Fix inconsistencies: " << fix_time << std::endl + << " * Export to OFF: " << export_time << std::endl + << "================================================" << std::endl + << std::endl; + + CGAL_TC_SET_PERFORMANCE_DATA("Num_points", tc.number_of_vertices()); + CGAL_TC_SET_PERFORMANCE_DATA("Init_time", init_time); + CGAL_TC_SET_PERFORMANCE_DATA("Comput_time", computation_time); + CGAL_TC_SET_PERFORMANCE_DATA("Fix_time", fix_time); + } + + return 0; +}