summaryrefslogtreecommitdiff
path: root/src/Witness_complex/example/protected_sets/protected_sets_paper2.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Witness_complex/example/protected_sets/protected_sets_paper2.h')
-rw-r--r--src/Witness_complex/example/protected_sets/protected_sets_paper2.h1384
1 files changed, 1384 insertions, 0 deletions
diff --git a/src/Witness_complex/example/protected_sets/protected_sets_paper2.h b/src/Witness_complex/example/protected_sets/protected_sets_paper2.h
new file mode 100644
index 00000000..04b5e3bc
--- /dev/null
+++ b/src/Witness_complex/example/protected_sets/protected_sets_paper2.h
@@ -0,0 +1,1384 @@
+#ifndef PROTECTED_SETS_H
+#define PROTECTED_SETS_H
+
+#include <algorithm>
+#include <CGAL/Cartesian_d.h>
+#include <CGAL/Epick_d.h>
+#include <CGAL/Euclidean_distance.h>
+#include <CGAL/Kernel_d/Sphere_d.h>
+#include <CGAL/Kernel_d/Hyperplane_d.h>
+#include <CGAL/Kernel_d/Vector_d.h>
+
+#include <CGAL/Orthogonal_k_neighbor_search.h>
+#include <CGAL/Kd_tree.h>
+#include <CGAL/Fuzzy_sphere.h>
+
+#include <boost/heap/fibonacci_heap.hpp>
+#include <boost/heap/policies.hpp>
+
+#include "output_tikz.h"
+#include "../output.h"
+#include "../generators.h"
+
+#include <CGAL/point_generators_d.h>
+
+
+typedef CGAL::Epick_d<CGAL::Dynamic_dimension_tag> K;
+typedef K::Point_d Point_d;
+typedef K::Line_d Line_d;
+typedef K::Vector_d Vector_d;
+typedef K::Oriented_side_d Oriented_side_d;
+typedef K::Has_on_positive_side_d Has_on_positive_side_d;
+typedef K::Sphere_d Sphere_d;
+typedef K::Hyperplane_d Hyperplane_d;
+
+typedef CGAL::Delaunay_triangulation<K> Delaunay_triangulation;
+typedef Delaunay_triangulation::Facet Facet;
+typedef Delaunay_triangulation::Vertex_handle Delaunay_vertex;
+typedef Delaunay_triangulation::Full_cell_handle Full_cell_handle;
+
+typedef std::vector<Point_d> Point_Vector;
+typedef CGAL::Euclidean_distance<Traits_base> Euclidean_distance;
+
+typedef CGAL::Search_traits_adapter<
+ std::ptrdiff_t, Point_d*, Traits_base> STraits;
+//typedef K TreeTraits;
+//typedef CGAL::Distance_adapter<std::ptrdiff_t,Point_d*,Euclidean_distance > Euclidean_adapter;
+//typedef CGAL::Kd_tree<STraits> Kd_tree;
+typedef CGAL::Orthogonal_k_neighbor_search<STraits, CGAL::Distance_adapter<std::ptrdiff_t,Point_d*,Euclidean_distance>> K_neighbor_search;
+typedef K_neighbor_search::Tree Tree;
+typedef K_neighbor_search::Distance Distance;
+typedef K_neighbor_search::iterator KNS_iterator;
+typedef K_neighbor_search::iterator KNS_range;
+typedef CGAL::Fuzzy_sphere<STraits> Fuzzy_sphere;
+
+typedef CGAL::Random_points_in_ball_d<Point_d> Random_point_iterator;
+
+
+FT _sfty = pow(10,-14);
+
+bool experiment1, experiment2, experiment3, experiment5 = false;
+
+/* Experiment 1: epsilon as function on time **********************/
+std::vector<FT> eps_vector;
+
+/* Experiment 2: R/epsilon on alpha *******************************/
+std::vector<FT> epsratio_vector;
+std::vector<FT> epsslope_vector;
+
+/* Experiment 3: theta on delta ***********************************/
+std::vector<FT> thetamin_vector; FT curr_theta;
+std::vector<FT> gammamin_vector;
+
+/* Statistical data ***********************************************/
+int refused_case1, refused_case2, refused_bad, refused_centers1, refused_centers2;
+
+void initialize_statistics()
+{
+ refused_case1 = 0;
+ refused_case2 = 0;
+ refused_bad = 0;
+ refused_centers1 = 0;
+ refused_centers2 = 0;
+}
+
+void print_statistics()
+{
+ std::cout << " * Old simplex not protected: " << refused_case1 << "\n";
+ std::cout << " * New simplex not protected: " << refused_case2 << "\n";
+ std::cout << " * New simplex not good: " << refused_bad << "\n";
+ std::cout << " * New-old centers too close: " << refused_centers1 << "\n";
+ std::cout << " * New-new centers too close: " << refused_centers2 << "\n";
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+// AUXILLARY FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/** Insert a point in Delaunay triangulation. If you are working in a flat torus, the procedure adds all the 3^d copies in adjacent cubes as well
+ *
+ * W is the initial point vector
+ * chosen_landmark is the index of the chosen point in W
+ * landmarks_ind is the vector of indices of already chosen points in W
+ * delaunay is the Delaunay triangulation
+ * landmark_count is the current number of chosen vertices
+ * torus is true iff you are working on a flat torus [-1,1]^d
+ * OUT: Vertex handle to the newly inserted point
+ */
+Delaunay_vertex insert_delaunay_landmark_with_copies(Point_Vector& W, int chosen_landmark, std::vector<int>& landmarks_ind, Delaunay_triangulation& delaunay, int& landmark_count, bool torus)
+{
+ if (!torus)
+ {
+ Delaunay_vertex v =delaunay.insert(W[chosen_landmark]);
+ landmarks_ind.push_back(chosen_landmark);
+ landmark_count++;
+ return v;
+ }
+ else
+ {
+ int D = W[0].size();
+ int nb_cells = pow(3, D);
+ Delaunay_vertex v;
+ for (int i = 0; i < nb_cells; ++i)
+ {
+ std::vector<FT> point;
+ int cell_i = i;
+ for (int l = 0; l < D; ++l)
+ {
+ point.push_back(W[chosen_landmark][l] + 2.0*(cell_i%3-1));
+ cell_i /= 3;
+ }
+ if (i == nb_cells/2)
+ v = delaunay.insert(point); //v = center point
+ else
+ delaunay.insert(point);
+ }
+ landmarks_ind.push_back(chosen_landmark);
+ landmark_count++;
+ return v;
+ }
+}
+
+/** Small check if the vertex v is in the full cell fc
+ */
+
+bool vertex_is_in_full_cell(Delaunay_triangulation::Vertex_handle v, Full_cell_handle fc)
+{
+ for (auto v_it = fc->vertices_begin(); v_it != fc->vertices_end(); ++v_it)
+ if (*v_it == v)
+ return true;
+ return false;
+}
+
+/** Fill chosen point vector from indices with copies if you are working on a flat torus
+ *
+ * IN: W is the point vector
+ * OUT: landmarks is the output vector
+ * IN: landmarks_ind is the vector of indices
+ * IN: torus is true iff you are working on a flat torus [-1,1]^d
+ */
+
+void fill_landmarks(Point_Vector& W, Point_Vector& landmarks, std::vector<int>& landmarks_ind, bool torus)
+{
+ if (!torus)
+ for (unsigned j = 0; j < landmarks_ind.size(); ++j)
+ landmarks.push_back(W[landmarks_ind[j]]);
+ else
+ {
+ int D = W[0].size();
+ int nb_cells = pow(3, D);
+ int nbL = landmarks_ind.size();
+ // Fill landmarks
+ for (int i = 0; i < nb_cells-1; ++i)
+ for (int j = 0; j < nbL; ++j)
+ {
+ int cell_i = i;
+ Point_d point;
+ for (int l = 0; l < D; ++l)
+ {
+ point.push_back(W[landmarks_ind[j]][l] + 2.0*(cell_i-1));
+ cell_i /= 3;
+ }
+ landmarks.push_back(point);
+ }
+ }
+}
+
+/** Fill a vector of all simplices in the Delaunay triangulation giving integer indices to vertices
+ *
+ * IN: t is the Delaunay triangulation
+ * OUT: full_cells is the output vector
+ */
+
+void fill_full_cell_vector(Delaunay_triangulation& t, std::vector<std::vector<int>>& full_cells)
+{
+ // Store vertex indices in a map
+ int ind = 0; //index of a vertex
+ std::map<Delaunay_triangulation::Vertex_handle, int> index_of_vertex;
+ for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it)
+ if (t.is_infinite(v_it))
+ continue;
+ else
+ index_of_vertex[v_it] = ind++;
+ // Write full cells as vectors in full_cells
+ for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it)
+ {
+ if (t.is_infinite(fc_it))
+ continue;
+ Point_Vector vertices;
+ for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it)
+ vertices.push_back((*fc_v_it)->point());
+ Sphere_d cs( vertices.begin(), vertices.end());
+ Point_d csc = cs.center();
+ bool in_cube = true;
+ for (auto xi = csc.cartesian_begin(); xi != csc.cartesian_end(); ++xi)
+ if (*xi > 1.0 || *xi < -1.0)
+ {
+ in_cube = false; break;
+ }
+ if (!in_cube)
+ continue;
+ std::vector<int> cell;
+ for (auto v_it = fc_it->vertices_begin(); v_it != fc_it->vertices_end(); ++v_it)
+ cell.push_back(index_of_vertex[*v_it]);
+ full_cells.push_back(cell);
+ }
+}
+
+bool sphere_intersects_cube(Point_d& c, FT r)
+{
+ bool in_cube = true;
+ // int i = 0, D = p.size();
+ for (auto xi = c.cartesian_begin(); xi != c.cartesian_end(); ++xi)
+ // if ((*xi < 1.0 || *xi > -1.0) &&
+ // (*xi-r < 1.0 || *xi-r > -1.0) &&
+ // (*xi+r < 1.0 || *xi+r > -1.0))
+
+ if ((*xi-r < -1.0 && *xi+r < -1.0) ||
+ (*xi-r > 1.0 && *xi+r > 1.0 ))
+ {
+ in_cube = false; break;
+ }
+ return in_cube;
+}
+
+/** Recursive function for checking if the simplex is good,
+ * meaning it does not contain a k-face, which is not theta0^(k-1) thick
+ */
+
+bool is_theta0_good(std::vector<Point_d>& vertices, FT theta0)
+{
+ if (theta0 > 1)
+ {
+ std::cout << "Warning! theta0 is set > 1\n";
+ return false;
+ }
+ int D = vertices.size()-1;
+ if (D <= 1)
+ return true; // Edges are always good
+ //******** Circumscribed sphere
+ Euclidean_distance ed;
+ Sphere_d cs(vertices.begin(), vertices.end());
+ FT r = sqrt(cs.squared_radius());
+ for (std::vector<Point_d>::iterator v_it = vertices.begin(); v_it != vertices.end(); ++v_it)
+ {
+ std::vector<Point_d> facet;
+ for (std::vector<Point_d>::iterator f_it = vertices.begin(); f_it != vertices.end(); ++f_it)
+ if (f_it != v_it)
+ facet.push_back(*f_it);
+ // Compute the altitude
+
+ if (vertices[0].size() == 3 && D == 2)
+ {
+ //Vector_d l = facet[0] - facet[1];
+ FT orth_length2 = ed.transformed_distance(facet[0],facet[1]);
+ K::Cartesian_const_iterator_d l_it, p_it, s_it, c_it;
+ FT h = 0;
+ // Scalar product = <sp,l>
+ FT scalar = 0;
+ for (p_it = v_it->cartesian_begin(),
+ s_it = facet[0].cartesian_begin(),
+ l_it = facet[1].cartesian_begin();
+ p_it != v_it->cartesian_end();
+ ++l_it, ++p_it, ++s_it)
+ scalar += (*l_it - *s_it)*(*p_it - *s_it);
+ // Gram-Schmidt for one vector
+ for (p_it = v_it->cartesian_begin(),
+ s_it = facet[0].cartesian_begin(),
+ l_it = facet[1].cartesian_begin();
+ p_it != v_it->cartesian_end();
+ ++l_it, ++p_it, ++s_it)
+ {
+ FT hx = (*p_it - *s_it) - scalar*(*l_it - *s_it)/orth_length2;
+ h += hx*hx;
+ }
+ h = sqrt(h);
+
+ if (h/(2*r) < pow(theta0, D-1))
+ return false;
+ if (!is_theta0_good(facet, theta0))
+ return false;
+ }
+ else
+ {
+ Hyperplane_d tau_h(facet.begin(), facet.end(), *v_it);
+ Vector_d orth_tau = tau_h.orthogonal_vector();
+ FT orth_length = sqrt(orth_tau.squared_length());
+ K::Cartesian_const_iterator_d o_it, p_it, s_it, c_it;
+ FT h = 0;
+ for (o_it = orth_tau.cartesian_begin(),
+ p_it = v_it->cartesian_begin(),
+ s_it = (facet.begin())->cartesian_begin();
+ o_it != orth_tau.cartesian_end();
+ ++o_it, ++p_it, ++s_it)
+ h += (*o_it)*(*p_it - *s_it)/orth_length;
+ h = fabs(h);
+ if (experiment3 && thetamin_vector[thetamin_vector.size()-1] > pow(h/(2*r), 1.0/(D-1)))
+ {
+ thetamin_vector[thetamin_vector.size()-1] = pow(h/(2*r), 1.0/(D-1));
+ //std::cout << "theta=" << h/(2*r) << ", ";
+ }
+ if (h/(2*r) < pow(theta0, D-1))
+ return false;
+ if (!is_theta0_good(facet, theta0))
+ return false;
+ }
+ }
+ return true;
+}
+
+/** Recursive function for checking the goodness of a simplex,
+ * meaning it does not contain a k-face, which is not theta0^(k-1) thick
+ */
+
+FT theta(std::vector<Point_d>& vertices)
+{
+ FT curr_value = 1.0;
+ int D = vertices.size()-1;
+ if (D <= 1)
+ return 1; // Edges are always good
+ //******** Circumscribed sphere
+ Euclidean_distance ed;
+ Sphere_d cs(vertices.begin(), vertices.end());
+ FT r = sqrt(cs.squared_radius());
+ for (std::vector<Point_d>::iterator v_it = vertices.begin(); v_it != vertices.end(); ++v_it)
+ {
+ std::vector<Point_d> facet;
+ for (std::vector<Point_d>::iterator f_it = vertices.begin(); f_it != vertices.end(); ++f_it)
+ if (f_it != v_it)
+ facet.push_back(*f_it);
+ // Compute the altitude
+ curr_value = std::min(curr_value, theta(facet)); // Check the corresponding facet
+ if (vertices[0].size() == 3 && D == 2)
+ {
+ //Vector_d l = facet[0] - facet[1];
+ FT orth_length2 = ed.transformed_distance(facet[0],facet[1]);
+ K::Cartesian_const_iterator_d l_it, p_it, s_it, c_it;
+ FT h = 0;
+ // Scalar product = <sp,l>
+ FT scalar = 0;
+ for (p_it = v_it->cartesian_begin(),
+ s_it = facet[0].cartesian_begin(),
+ l_it = facet[1].cartesian_begin();
+ p_it != v_it->cartesian_end();
+ ++l_it, ++p_it, ++s_it)
+ scalar += (*l_it - *s_it)*(*p_it - *s_it);
+ // Gram-Schmidt for one vector
+ for (p_it = v_it->cartesian_begin(),
+ s_it = facet[0].cartesian_begin(),
+ l_it = facet[1].cartesian_begin();
+ p_it != v_it->cartesian_end();
+ ++l_it, ++p_it, ++s_it)
+ {
+ FT hx = (*p_it - *s_it) - scalar*(*l_it - *s_it)/orth_length2;
+ h += hx*hx;
+ }
+ h = sqrt(h);
+ curr_value = std::min(curr_value, std::pow(h/(2*r), 1.0/(D-1)));
+ }
+ else
+ {
+ Hyperplane_d tau_h(facet.begin(), facet.end(), *v_it);
+ Vector_d orth_tau = tau_h.orthogonal_vector();
+ FT orth_length = sqrt(orth_tau.squared_length());
+ K::Cartesian_const_iterator_d o_it, p_it, s_it, c_it;
+ FT h = 0;
+ for (o_it = orth_tau.cartesian_begin(),
+ p_it = v_it->cartesian_begin(),
+ s_it = (facet.begin())->cartesian_begin();
+ o_it != orth_tau.cartesian_end();
+ ++o_it, ++p_it, ++s_it)
+ h += (*o_it)*(*p_it - *s_it)/orth_length;
+ h = fabs(h);
+ curr_value = std::min(curr_value, pow(h/(2*r), 1.0/(D-1)));
+ }
+ }
+ return curr_value;
+}
+
+// Doubling in a way 1->2->5->10
+void double_round(int& i)
+{
+ FT order10 = pow(10,std::floor(std::log10(i)));
+ int digit = std::floor( i / order10);
+ std::cout << digit;
+ if (digit == 1)
+ i *= 2;
+ else if (digit == 2)
+ i = 5*i/2;
+ else if (digit == 5)
+ i *= 2;
+ else
+ std::cout << "digit not correct. digit = " << digit << std::endl;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// IS VIOLATED TEST
+////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/** Check if a newly created cell is protected from old vertices
+ *
+ * t is the Delaunay triangulation
+ * vertices is the vector containing the point to insert and a facet f in t
+ * v1 is the vertex of t, such that f and v1 form a simplex
+ * v2 is the vertex of t, such that f and v2 form another simplex
+ * delta is the protection constant
+ * power_protection is true iff the delta-power protection is used
+ */
+
+bool new_cell_is_violated(Delaunay_triangulation& t, std::vector<Point_d>& vertices, const Delaunay_vertex& v1, const Delaunay_vertex v2, FT delta0, bool power_protection, FT theta0, FT gamma0)
+{
+ assert(vertices.size() == vertices[0].size() ||
+ vertices.size() == vertices[0].size() + 1); //simplex size = d | d+1
+ assert(v1 != v2);
+ if (vertices.size() == vertices[0].size() + 1)
+ // FINITE CASE
+ {
+ Sphere_d cs(vertices.begin(), vertices.end());
+ Point_d center_cs = cs.center();
+ FT r = sqrt(Euclidean_distance().transformed_distance(center_cs, vertices[0]));
+ /*
+ for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it)
+ if (!t.is_infinite(v_it))
+ {
+ //CGAL::Oriented_side side = Oriented_side_d()(cs, (v_it)->point());
+ if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end())
+ {
+ FT dist2 = Euclidean_distance().transformed_distance(center_cs, (v_it)->point());
+ if (!power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= (r+delta)*(r+delta))
+ return true;
+ if (power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= r*r+delta*delta)
+ return true;
+ }
+ }
+ */
+ // Is the center inside the box? (only Euclidean case)
+ // if (!torus)
+ // {
+ // bool inside_the_box = true;
+ // for (c_it = center_cs.cartesian_begin(); c_it != center_cs.cartesian_end(); ++c_it)
+ // if (*c_it > 1.0 || *c_it < -1.0)
+ // {
+ // inside_the_box = false; break;
+ // }
+ // if (inside_the_box && h/r < theta0)
+ // return true;
+ // }
+ // Check the two vertices (if not infinite)
+ if (!t.is_infinite(v1))
+ {
+ FT dist2 = Euclidean_distance().transformed_distance(center_cs, v1->point());
+ if (!power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= (r+r*delta0)*(r+r*delta0))
+ { refused_case2++; return true;}
+ if (power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= r*r+r*r*delta0*delta0)
+ { refused_case2++; return true;}
+ // Check if the centers are not too close
+ std::vector<Point_d> sigma(vertices);
+ sigma[0] = v1->point();
+ Sphere_d cs_sigma(sigma.begin(), sigma.end());
+ Point_d csc_sigma = cs_sigma.center();
+ FT r_sigma = sqrt(cs_sigma.squared_radius());
+ FT dcc = sqrt(Euclidean_distance().transformed_distance(center_cs, csc_sigma));
+ if (experiment3 && dcc/r < gammamin_vector[gammamin_vector.size()-1])
+ gammamin_vector[gammamin_vector.size()-1] = dcc/r;
+ if (experiment3 && dcc/r_sigma < gammamin_vector[gammamin_vector.size()-1])
+ gammamin_vector[gammamin_vector.size()-1] = dcc/r_sigma;
+ if (dcc < r*gamma0 || dcc < r_sigma*gamma0)
+ { refused_centers1++; return true; }
+ }
+ if (!t.is_infinite(v2))
+ {
+ FT dist2 = Euclidean_distance().transformed_distance(center_cs, v2->point());
+ if (!power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= (r+r*delta0)*(r+r*delta0))
+ { refused_case2++; return true;}
+ if (power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= r*r+r*r*delta0*delta0)
+ { refused_case2++; return true;}
+ // Check if the centers are not too close
+ std::vector<Point_d> sigma(vertices);
+ sigma[0] = v2->point();
+ Sphere_d cs_sigma(sigma.begin(), sigma.end());
+ Point_d csc_sigma = cs_sigma.center();
+ FT r_sigma = sqrt(cs_sigma.squared_radius());
+ FT dcc = sqrt(Euclidean_distance().transformed_distance(center_cs, csc_sigma));
+ if (experiment3 && dcc/r < gammamin_vector[gammamin_vector.size()-1])
+ gammamin_vector[gammamin_vector.size()-1] = dcc/r;
+ if (experiment3 && dcc/r_sigma < gammamin_vector[gammamin_vector.size()-1])
+ gammamin_vector[gammamin_vector.size()-1] = dcc/r_sigma;
+ if (dcc < r*gamma0 || dcc < r_sigma*gamma0)
+ { refused_centers1++; return true; }
+ }
+ // Check if the simplex is theta0-good
+ if (!is_theta0_good(vertices, theta0))
+ { refused_bad++; return true;}
+
+ }
+ else
+ // INFINITE CASE
+ {
+ Delaunay_triangulation::Vertex_iterator v = t.vertices_begin();
+ while (t.is_infinite(v) || std::find(vertices.begin(), vertices.end(), v->point()) == vertices.end())
+ v++;
+ Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v->point(), CGAL::ON_POSITIVE_SIDE);
+ Vector_d orth_v = facet_plane.orthogonal_vector();
+ /*
+ for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it)
+ if (!t.is_infinite(v_it))
+ if (std::find(vertices.begin(), vertices.end(), v_it->point()) == vertices.end())
+ {
+ std::vector<FT> coords;
+ Point_d p = v_it->point();
+ auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
+ for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
+ coords.push_back((*p_i) - (*orth_i) * delta / sqrt(orth_v.squared_length()));
+ Point_d p_delta = Point_d(coords);
+ bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p);
+ bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
+ if (!p_is_inside && p_delta_is_inside)
+ return true;
+ }
+ */
+ if (!t.is_infinite(v1))
+ {
+ std::vector<FT> coords;
+ Point_d p = v1->point();
+ auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
+ for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
+ coords.push_back((*p_i) - (*orth_i) * delta0 / sqrt(orth_v.squared_length()));
+ Point_d p_delta = Point_d(coords);
+ bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p);
+ bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
+ if (!power_protection && !p_is_inside && p_delta_is_inside)
+ return true;
+ }
+ if (!t.is_infinite(v2))
+ {
+ std::vector<FT> coords;
+ Point_d p = v2->point();
+ auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
+ for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
+ coords.push_back((*p_i) - (*orth_i) * delta0 / sqrt(orth_v.squared_length()));
+ Point_d p_delta = Point_d(coords);
+ bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p);
+ bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
+ if (!power_protection && !p_is_inside && p_delta_is_inside)
+ return true;
+ }
+ }
+ return false;
+}
+
+/** Auxillary recursive function to check if the point p violates the protection of the cell c and
+ * if there is a violation of an eventual new cell
+ *
+ * p is the point to insert
+ * t is the current triangulation
+ * c is the current cell (simplex)
+ * parent_cell is the parent cell (simplex)
+ * index is the index of the facet between c and parent_cell from parent_cell's point of view
+ * D is the dimension of the triangulation
+ * delta is the protection constant
+ * marked_cells is the vector of all visited cells containing p in their circumscribed ball
+ * power_protection is true iff you are working with delta-power protection
+ *
+ * OUT: true iff inserting p hasn't produced any violation so far
+ */
+
+bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, Full_cell_handle c, Full_cell_handle parent_cell, int index, int D, FT delta0, std::vector<Full_cell_handle>& marked_cells, bool power_protection, FT theta0, FT gamma0)
+{
+ Euclidean_distance ed;
+ std::vector<Point_d> vertices;
+ if (!t.is_infinite(c))
+ {
+ // if the cell is finite, we look if the protection is violated
+ for (auto v_it = c->vertices_begin(); v_it != c->vertices_end(); ++v_it)
+ vertices.push_back((*v_it)->point());
+ Sphere_d cs( vertices.begin(), vertices.end());
+ Point_d center_cs = cs.center();
+ FT r = sqrt(ed.transformed_distance(center_cs, vertices[0]));
+ FT dist2 = ed.transformed_distance(center_cs, p);
+ // if the new point is inside the protection ball of a non conflicting simplex
+ if (!power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= (r+r*delta0)*(r+r*delta0))
+ { refused_case1++; return true;}
+ if (power_protection)
+ if (dist2 >= r*r-_sfty && dist2 <= r*r+delta0*delta0*r*r)
+ { refused_case1++; return true;}
+ // if the new point is inside the circumscribing ball : continue violation searching on neighbours
+ //if (dist2 < r*r)
+ //if (dist2 < (5*r+delta)*(5*r+delta))
+ if (dist2 < r*r)
+ {
+ c->tds_data().mark_visited();
+ marked_cells.push_back(c);
+ for (int i = 0; i < D+1; ++i)
+ {
+ Full_cell_handle next_c = c->neighbor(i);
+ if (next_c->tds_data().is_clear() &&
+ is_violating_protection(p, t, next_c, c, i, D, delta0, marked_cells, power_protection, theta0, gamma0))
+ return true;
+ }
+ }
+ // if the new point is outside the protection sphere
+ else
+ {
+ // facet f is on the border of the conflict zone : check protection of simplex {p,f}
+ // the new simplex is guaranteed to be finite
+ vertices.clear(); vertices.push_back(p);
+ for (int i = 0; i < D+1; ++i)
+ if (i != index)
+ vertices.push_back(parent_cell->vertex(i)->point());
+ Delaunay_vertex vertex_to_check = t.infinite_vertex();
+ for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it)
+ if (!vertex_is_in_full_cell(*vh_it, parent_cell))
+ {
+ vertex_to_check = *vh_it; break;
+ }
+ if (new_cell_is_violated(t, vertices, vertex_to_check, parent_cell->vertex(index), delta0, power_protection, theta0, gamma0))
+ //if (new_cell_is_violated(t, vertices, vertex_to_check->point(), delta))
+ return true;
+ }
+ }
+ else
+ {
+ // Inside of the convex hull is + side. Outside is - side.
+ for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it)
+ if (!t.is_infinite(*vh_it))
+ vertices.push_back((*vh_it)->point());
+ Delaunay_triangulation::Vertex_iterator v_it = t.vertices_begin();
+ while (t.is_infinite(v_it) || vertex_is_in_full_cell(v_it, c))
+ v_it++;
+ Hyperplane_d facet_plane(vertices.begin(), vertices.end(), v_it->point(), CGAL::ON_POSITIVE_SIDE);
+ //CGAL::Oriented_side outside = Oriented_side_d()(facet_plane, v_it->point());
+ Vector_d orth_v = facet_plane.orthogonal_vector();
+ std::vector<FT> coords;
+ auto orth_i = orth_v.cartesian_begin(), p_i = p.cartesian_begin();
+ for (; orth_i != orth_v.cartesian_end(); ++orth_i, ++p_i)
+ coords.push_back((*p_i) - (*orth_i) * delta0 / sqrt(orth_v.squared_length()));
+ Point_d p_delta = Point_d(coords);
+ bool p_is_inside = !Has_on_positive_side_d()(facet_plane, p) && (Oriented_side_d()(facet_plane, p) != CGAL::ZERO);
+ bool p_delta_is_inside = !Has_on_positive_side_d()(facet_plane, p_delta);
+
+ // If we work with power protection, we just ignore any conflicts
+ if (!power_protection && !p_is_inside && p_delta_is_inside)
+ return true;
+ //if the cell is infinite we look at the neighbours regardless
+ if (p_is_inside)
+ {
+ c->tds_data().mark_visited();
+ marked_cells.push_back(c);
+ for (int i = 0; i < D+1; ++i)
+ {
+ Full_cell_handle next_c = c->neighbor(i);
+ if (next_c->tds_data().is_clear() &&
+ is_violating_protection(p, t, next_c, c, i, D, delta0, marked_cells, power_protection, theta0, gamma0))
+ return true;
+ }
+ }
+ else
+ {
+ // facet f is on the border of the conflict zone : check protection of simplex {p,f}
+ // the new simplex is finite if the parent cell is finite
+ vertices.clear(); vertices.push_back(p);
+ for (int i = 0; i < D+1; ++i)
+ if (i != index)
+ if (!t.is_infinite(parent_cell->vertex(i)))
+ vertices.push_back(parent_cell->vertex(i)->point());
+ Delaunay_vertex vertex_to_check = t.infinite_vertex();
+ for (auto vh_it = c->vertices_begin(); vh_it != c->vertices_end(); ++vh_it)
+ if (!vertex_is_in_full_cell(*vh_it, parent_cell))
+ {
+ vertex_to_check = *vh_it; break;
+ }
+ if (new_cell_is_violated(t, vertices, vertex_to_check, parent_cell->vertex(index), delta0, power_protection, theta0, gamma0))
+ //if (new_cell_is_violated(t, vertices, vertex_to_check->point(), delta))
+ return true;
+ }
+ }
+ //c->tds_data().clear_visited();
+ //marked_cells.pop_back();
+ return false;
+}
+
+/** Checks if inserting the point p in t will make conflicts
+ *
+ * p is the point to insert
+ * t is the current triangulation
+ * D is the dimension of triangulation
+ * delta is the protection constant
+ * power_protection is true iff you are working with delta-power protection
+ * OUT: true iff inserting p produces a violation of delta-protection.
+ */
+
+bool is_violating_protection(Point_d& p, Delaunay_triangulation& t, int D, FT delta0, bool power_protection, FT theta0, FT gamma0)
+{
+ Euclidean_distance ed;
+ Delaunay_triangulation::Vertex_handle v;
+ Delaunay_triangulation::Face f(t.current_dimension());
+ Delaunay_triangulation::Facet ft;
+ Delaunay_triangulation::Full_cell_handle c;
+ Delaunay_triangulation::Locate_type lt;
+ std::vector<Full_cell_handle> marked_cells;
+ //c = t.locate(p, lt, f, ft, v);
+ c = t.locate(p);
+ bool violation_existing_cells = is_violating_protection(p, t, c, c, 0, D, delta0, marked_cells, power_protection, theta0, gamma0);
+ for (Full_cell_handle fc : marked_cells)
+ fc->tds_data().clear();
+ return violation_existing_cells;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// INITIALIZATION
+////////////////////////////////////////////////////////////////////////
+
+// Query for a sphere near a cite in all copies of a torus
+// OUT points_inside
+void torus_search(Tree& treeW, int D, Point_d cite, FT r, std::vector<int>& points_inside)
+{
+ int nb_cells = pow(3, D);
+ Delaunay_vertex v;
+ for (int i = 0; i < nb_cells; ++i)
+ {
+ std::vector<FT> cite_copy;
+ int cell_i = i;
+ for (int l = 0; l < D; ++l)
+ {
+ cite_copy.push_back(cite[l] + 2.0*(cell_i%3-1));
+ cell_i /= 3;
+ }
+ Fuzzy_sphere fs(cite_copy, r, 0, treeW.traits());
+ treeW.search(std::insert_iterator<std::vector<int>>(points_inside, points_inside.end()), fs);
+ }
+}
+
+
+void initialize_torus(Point_Vector& W, Tree& treeW, Delaunay_triangulation& t, FT epsilon, std::vector<int>& landmarks_ind, int& landmark_count, std::vector<bool>& point_taken)
+{
+ initialize_statistics();
+ int D = W[0].size();
+ if (D == 2)
+ {
+ int xw = 6, yw = 4;
+ // Triangular lattice close to regular triangles h=0.866a ~ 0.875a : 48p
+ for (int i = 0; i < xw; ++i)
+ for (int j = 0; j < yw; ++j)
+ {
+ Point_d cite1(std::vector<FT>{2.0/xw*i, 2.0/yw*j});
+ std::vector<int> points_inside;
+ torus_search(treeW, D, cite1, epsilon, points_inside);
+ //std::cout << "i=" << i << ", j=" << j << " "; print_vector(points_inside); std::cout << "\n";
+ std::vector<int>::iterator p_it = points_inside.begin();
+ while (p_it != points_inside.end() && point_taken[*p_it])
+ ++p_it;
+ assert(p_it != points_inside.end());
+ //W[*p_it] = cite1; // debug purpose
+ insert_delaunay_landmark_with_copies(W, *p_it,
+ landmarks_ind, t, landmark_count, true);
+ point_taken[*p_it] = true;
+
+ Point_d cite2(std::vector<FT>{2.0/xw*(i+0.5), 2.0/yw*(j+0.5)});
+ points_inside.clear();
+ torus_search(treeW, D, cite2, epsilon, points_inside);
+ //std::cout << "i=" << i << ", j=" << j << " "; print_vector(points_inside); std::cout << "\n";
+ p_it = points_inside.begin();
+ while (p_it != points_inside.end() && point_taken[*p_it])
+ ++p_it;
+ assert(p_it != points_inside.end());
+ //W[*p_it] = cite2; // debug purpose
+ insert_delaunay_landmark_with_copies(W, *p_it,
+ landmarks_ind, t, landmark_count, true);
+ point_taken[*p_it] = true;
+ }
+ }
+ else if (D == 3)
+ {
+ int wd = 3;
+ // Body-centered cubic lattice : 54p
+ for (int i = 0; i < wd; ++i)
+ for (int j = 0; j < wd; ++j)
+ for (int k = 0; k < wd; ++k)
+ {
+ Point_d cite1(std::vector<FT>{2.0/wd*i, 2.0/wd*j, 2.0/wd*k});
+ std::vector<int> points_inside;
+ torus_search(treeW, D, cite1, epsilon, points_inside);
+ std::vector<int>::iterator p_it = points_inside.begin();
+ while (p_it != points_inside.end() && point_taken[*p_it])
+ ++p_it;
+ assert(p_it != points_inside.end());
+ insert_delaunay_landmark_with_copies(W, *(points_inside.begin()),
+ landmarks_ind, t, landmark_count, true);
+ point_taken[*p_it] = true;
+
+ Point_d cite2(std::vector<FT>{2.0/wd*(i+0.5), 2.0/wd*(j+0.5), 2.0/wd*(k+0.5)});
+ points_inside.clear();
+ torus_search(treeW, D, cite2, epsilon, points_inside);
+ p_it = points_inside.begin();
+ while (p_it != points_inside.end() && point_taken[*p_it])
+ ++p_it;
+ assert(p_it != points_inside.end());
+ insert_delaunay_landmark_with_copies(W, *(points_inside.begin()),
+ landmarks_ind, t, landmark_count, true);
+ point_taken[*p_it] = true;
+ }
+ }
+ //write_mesh
+}
+
+///////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+//!!!!!!!!!!!!! THE INTERFACE FOR LANDMARK CHOICE IS BELOW !!!!!!!!!!//
+///////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+
+// Struct for R_max_heap elements
+
+struct R_max_handle
+{
+ FT value;
+ Point_d center;
+
+ R_max_handle(FT value_, Point_d c): value(value_), center(c)
+ {}
+};
+
+struct R_max_compare
+{
+ bool operator()(const R_max_handle& rmh1, const R_max_handle& rmh2) const
+ {
+ return rmh1.value < rmh2.value;
+ }
+};
+
+// typedef boost::heap::fibonacci_heap<R_max_handle, boost::heap::compare<R_max_compare>> Heap;
+
+// void make_heap(Delaunay_triangulation& t, Heap& R_max_heap)
+// {
+// R_max_heap.clear();
+// for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it)
+// {
+// if (t.is_infinite(fc_it))
+// continue;
+// Point_Vector vertices;
+// for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it)
+// vertices.push_back((*fc_v_it)->point());
+// Sphere_d cs( vertices.begin(), vertices.end());
+// Point_d csc = cs.center();
+// FT r = sqrt(cs.squared_radius());
+// // A ball is in the heap, if it intersects the cube
+// bool accepted = sphere_intersects_cube(csc, sqrt(r));
+// if (!accepted)
+// continue;
+// R_max_heap.push(R_max_handle(r, fc_it, csc));
+// }
+// }
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SAMPLING RADIUS
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+R_max_handle sampling_radius(Delaunay_triangulation& t)
+{
+ FT epsilon2 = 0;
+ Point_d final_center;
+ Point_d control_point;
+ for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it)
+ {
+ if (t.is_infinite(fc_it))
+ continue;
+ Point_Vector vertices;
+ for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it)
+ vertices.push_back((*fc_v_it)->point());
+ Sphere_d cs( vertices.begin(), vertices.end());
+ Point_d csc = cs.center();
+ bool in_cube = true;
+ for (auto xi = csc.cartesian_begin(); xi != csc.cartesian_end(); ++xi)
+ if (*xi > 1.0 || *xi < -1.0)
+ {
+ in_cube = false; break;
+ }
+ if (!in_cube)
+ continue;
+ FT r2 = Euclidean_distance().transformed_distance(cs.center(), *(vertices.begin()));
+ if (epsilon2 < r2)
+ {
+ epsilon2 = r2;
+ final_center = csc;
+ control_point = (*vertices.begin());
+ }
+ }
+ return R_max_handle(sqrt(epsilon2), final_center);
+}
+
+FT sampling_fatness(Delaunay_triangulation& t)
+{
+ FT curr_theta = 1.0;
+ for (auto fc_it = t.full_cells_begin(); fc_it != t.full_cells_end(); ++fc_it)
+ {
+ if (t.is_infinite(fc_it))
+ continue;
+ Point_Vector vertices;
+ for (auto fc_v_it = fc_it->vertices_begin(); fc_v_it != fc_it->vertices_end(); ++fc_v_it)
+ vertices.push_back((*fc_v_it)->point());
+ Sphere_d cs( vertices.begin(), vertices.end());
+ Point_d csc = cs.center();
+ bool in_cube = true;
+ for (auto xi = csc.cartesian_begin(); xi != csc.cartesian_end(); ++xi)
+ if (*xi > 1.0 || *xi < -1.0)
+ {
+ in_cube = false; break;
+ }
+ if (!in_cube)
+ continue;
+ FT theta_f = theta(vertices);
+ curr_theta = std::min(curr_theta, theta_f);
+ //std::cout << "theta(sigma) = " << theta_f << "\n";
+ }
+ return curr_theta;
+}
+
+// Generate an epsilon sample for a given epsilon
+void generate_epsilon_sample_torus(Point_Vector& W, FT epsilon, int dim, Delaunay_triangulation& t)
+{
+ W.clear();
+ t.clear();
+ int point_count = 0;
+ std::vector<int> point_ind;
+ // std::vector<FT> coords;
+ FT curr_eps = 2*dim;
+ // Initialize
+ // for (int i = 0; i < dim; ++i)
+ // coords.push_back(-1);
+ // R_max_handle rmh(2*sqrt(dim), Point_d(coords));
+ // int N = dim; std::floor(std::pow(1/epsilon,dim));
+ // std::cout << N << "\n";
+ typedef CGAL::Random_points_in_cube_d<Point_d> Random_cube_iterator;
+ Random_cube_iterator rp(dim, 1.0);
+ W.push_back(*rp++);
+ insert_delaunay_landmark_with_copies(W, W.size()-1, point_ind, t, point_count, true);
+ curr_eps = sampling_radius(t).value;
+ while (curr_eps > epsilon)
+ {
+
+ W.push_back(*rp++);
+ insert_delaunay_landmark_with_copies(W, W.size()-1, point_ind, t, point_count, true);
+
+ Point_d c = sampling_radius(t).center;
+ W.push_back(c);
+ insert_delaunay_landmark_with_copies(W, W.size()-1, point_ind, t, point_count, true);
+ curr_eps = sampling_radius(t).value;
+
+ std::cout << "curr_eps = " << curr_eps << "\n";
+ }
+ // Iterate and insert in a torus
+ // while (rmh.value > epsilon)
+ // {
+ // W.push_back(rmh.center);
+ // insert_delaunay_landmark_with_copies(W, W.size()-1, point_ind, t, point_count, true);
+ // rmh = sampling_radius(t);
+ // //std::cout << rmh.value;
+ // }
+}
+
+///////////////////////////////////////////////////////////////////////
+// LANDMARK CHOICE PROCEDURE
+///////////////////////////////////////////////////////////////////////
+
+/** Procedure to compute a maximal protected subset from a point cloud. All OUTs should be empty at call.
+ *
+ * IN: W is the initial point cloud having type Epick_d<Dynamic_dimension_tag>::Point_d
+ * IN: nbP is the size of W
+ * OUT: landmarks is the output vector for the points
+ * OUT: landmarks_ind is the output vector for the indices of the selected points in W
+ * IN: delta is the constant of protection
+ * OUT: full_cells is the output vector of the simplices in the final Delaunay triangulation
+ * IN: torus is true iff you are working on a flat torus [-1,1]^d
+ */
+
+void protected_delaunay(Point_Vector& W,
+ //Point_Vector& landmarks,
+ std::vector<int>& landmarks_ind,
+ FT alpha,
+ FT epsilon,
+ FT delta0,
+ FT theta0,
+ FT gamma0,
+ //std::vector<std::vector<int>>& full_cells,
+ bool torus,
+ bool power_protection
+ )
+{
+ //bool return_ = true;
+ unsigned D = W[0].size();
+ int nbP = W.size();
+ //FT beta = 1/(1-alpha);
+ //FT Ad = pow((4*alpha + 8*beta)/alpha, D);
+ //FT theta0 = 1/Ad;
+ //FT delta0 = pow(1/Ad,D);
+ Torus_distance td;
+ Euclidean_distance ed;
+ Delaunay_triangulation t(D);
+ std::vector<bool> point_taken(nbP,false);
+ CGAL::Random rand;
+ int landmark_count = 0;
+ std::list<int> index_list;
+ //****************** Kd Tree W
+ STraits traits(&(W[0]));
+ Tree treeW(boost::counting_iterator<std::ptrdiff_t>(0),
+ boost::counting_iterator<std::ptrdiff_t>(nbP),
+ typename Tree::Splitter(),
+ traits);
+ // shuffle the list of indexes (via a vector)
+ {
+ std::vector<int> temp_vector;
+ for (int i = 0; i < nbP; ++i)
+ temp_vector.push_back(i);
+ unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
+ std::shuffle(temp_vector.begin(), temp_vector.end(), std::default_random_engine(seed));
+ //CGAL::spatial_sort(temp_vector.begin(), temp_vector.end());
+ for (std::vector<int>::iterator it = temp_vector.begin(); it != temp_vector.end(); ++it)
+ index_list.push_front(*it);
+ }
+ //******************** Initialize point set
+ if (!torus)
+ for (unsigned pos1 = 0; pos1 < D+1; ++pos1)
+ {
+ std::vector<FT> point;
+ for (unsigned i = 0; i < pos1; ++i)
+ point.push_back(-1);
+ if (pos1 != D)
+ point.push_back(1);
+ for (unsigned i = pos1+1; i < D; ++i)
+ point.push_back(0);
+ assert(point.size() == D);
+ W[index_list.front()] = Point_d(point);
+ insert_delaunay_landmark_with_copies(W, index_list.front(), landmarks_ind, t, landmark_count, torus);
+ index_list.pop_front();
+ }
+ else
+ initialize_torus(W, treeW, t, epsilon, landmarks_ind, landmark_count, point_taken);
+ //std::cout << "Size of treeW: " << treeW.size() << "\n";
+ //std::cout << "Size of t: " << t.number_of_vertices() << "\n";
+ //******************* Initialize heap for R_max
+ //Heap R_max_heap;
+ //make_heap(t, R_max_heap);
+
+
+ R_max_handle rh = sampling_radius(t);
+ FT epsilon0 = rh.value;
+ if (experiment1) eps_vector.push_back(pow(1/rh.value,D));
+ //******************** Iterative algorithm
+ std::vector<int> candidate_points;
+ torus_search(treeW, D,
+ rh.center,
+ alpha*rh.value,
+ candidate_points);
+ std::list<int>::iterator list_it;
+ std::vector<int>::iterator cp_it = candidate_points.begin();
+ while (cp_it != candidate_points.end())
+ {
+ if (!point_taken[*cp_it] && !is_violating_protection(W[*cp_it], t, D, delta0, power_protection, theta0, gamma0))
+ {
+ Delaunay_vertex v = insert_delaunay_landmark_with_copies(W, *cp_it, landmarks_ind, t, landmark_count, torus);
+ {
+ // Simple check if the new cells don't have centers too close one to another
+ std::vector<Full_cell_handle> inc_cells;
+ std::back_insert_iterator<std::vector<Full_cell_handle>> out(inc_cells);
+ t.tds().incident_full_cells(v, out);
+
+ std::vector<Sphere_d> spheres;
+ for (auto i_it = inc_cells.begin(); i_it != inc_cells.end(); ++i_it)
+ {
+ std::vector<Point_d> vertices;
+ for (auto v_it = (*i_it)->vertices_begin(); v_it != (*i_it)->vertices_end(); ++v_it)
+ vertices.push_back((*v_it)->point());
+ spheres.push_back(Sphere_d(vertices.begin(), vertices.end()));
+ }
+ for (auto s_it = spheres.begin(); s_it != spheres.end(); ++s_it)
+ for (auto t_it = s_it+1; t_it != spheres.end(); ++t_it)
+ {
+ FT ddc2 = ed.transformed_distance(s_it->center(),t_it->center());
+ if (ddc2 < gamma0*gamma0*s_it->squared_radius() ||
+ ddc2 < gamma0*gamma0*t_it->squared_radius())
+ { refused_centers2++; }
+ }
+ }
+
+ //std::cout << *cp_it << ",\n";
+ //make_heap(t, R_max_heap);
+ point_taken[*cp_it] = true;
+ rh = sampling_radius(t);
+ if (experiment1) eps_vector.push_back(pow(1/rh.value,D));
+ //std::cout << "rhvalue = " << rh.value << "\n";
+ //std::cout << "D = " <<
+ candidate_points.clear();
+ torus_search(treeW, D,
+ rh.center,
+ alpha*rh.value,
+ candidate_points);
+ cp_it = candidate_points.begin();
+ /*
+ // PIECE OF CODE FOR DEBUGGING PURPOSES
+
+ Delaunay_vertex inserted_v = insert_delaunay_landmark_with_copies(W, *list_it, landmarks_ind, t, landmark_count);
+ if (triangulation_is_protected(t, delta))
+ {
+ index_list.erase(list_it);
+ list_it = index_list.begin();
+ }
+ else
+ { //THAT'S WHERE SOMETHING'S WRONG
+ t.remove(inserted_v);
+ landmarks_ind.pop_back();
+ landmark_count--;
+ write_delaunay_mesh(t, W[*list_it], is2d);
+ is_violating_protection(W[*list_it], t_old, D, delta); //Called for encore
+ }
+ */
+ //std::cout << "index_list_size() = " << index_list.size() << "\n";
+ }
+ else
+ {
+ cp_it++;
+ //std::cout << "!!!!!WARNING!!!!! A POINT HAS BEEN OMITTED!!!\n";
+ }
+ //if (list_it != index_list.end())
+ // write_delaunay_mesh(t, W[*list_it], is2d);
+ }
+
+ if (experiment2) epsratio_vector.push_back(rh.value/epsilon0);
+ if (experiment2) epsslope_vector.push_back( (pow(1/rh.value,D)-pow(1/epsilon0,D))/(landmarks_ind.size() - 48) );
+ std::cout << "The iteration ended when cp_count = " << candidate_points.size() << "\n";
+ std::cout << "alphaRmax = " << alpha*rh.value << "\n";
+ std::cout << "epsilon' = " << rh.value << "\n";
+ std::cout << "nbL = " << landmarks_ind.size() << "\n";
+ print_statistics();
+ //print_vector(landmarks_ind); std::cout << std::endl;
+ //std::sort(landmarks_ind.begin(), landmarks_ind.end());
+ print_vector(landmarks_ind); std::cout << std::endl;
+ if (experiment3) thetamin_vector[thetamin_vector.size()-1] = sampling_fatness(t);
+ std::cout << "theta = " << sampling_fatness(t) << "\n";
+ //fill_landmarks(W, landmarks, landmarks_ind, torus);
+ //fill_full_cell_vector(t, full_cells);
+ /*
+ if (triangulation_is_protected(t, delta))
+ std::cout << "Triangulation is ok\n";
+ else
+ {
+ std::cout << "Triangulation is BAD!! T_T しくしく!\n";
+ }
+ */
+ write_delaunay_mesh(t, W[0], true);
+ //std::cout << t << std::endl;
+}
+
+void run_experiment5(Point_Vector& W,
+ int D,
+ FT alpha,
+ FT epsilon,
+ FT delta0,
+ FT theta0,
+ FT gamma0,
+ //std::vector<std::vector<int>>& full_cells,
+ bool torus,
+ bool power_protection
+ )
+{
+ // INITIALIZATION
+ Delaunay_triangulation t(D);
+ std::vector<int> landmarks_ind;
+ int landmark_count = 0;
+ initialize_statistics();
+ if (D == 2)
+ {
+ int xw = 6, yw = 4;
+ // Triangular lattice close to regular triangles h=0.866a ~ 0.875a : 48p
+ for (int i = 0; i < xw; ++i)
+ for (int j = 0; j < yw; ++j)
+ {
+ Point_d cite1(std::vector<FT>{2.0/xw*i, 2.0/yw*j});
+ W.push_back(cite1); // debug purpose
+ insert_delaunay_landmark_with_copies(W, W.size()-1,
+ landmarks_ind, t, landmark_count, true);
+
+ Point_d cite2(std::vector<FT>{2.0/xw*(i+0.5), 2.0/yw*(j+0.5)});
+ W.push_back(cite2); // debug purpose
+ insert_delaunay_landmark_with_copies(W, W.size()-1,
+ landmarks_ind, t, landmark_count, true);
+ }
+ }
+ else if (D == 3)
+ {
+ int wd = 3;
+ // Body-centered cubic lattice : 54p
+ for (int i = 0; i < wd; ++i)
+ for (int j = 0; j < wd; ++j)
+ for (int k = 0; k < wd; ++k)
+ {
+ Point_d cite1(std::vector<FT>{2.0/wd*i, 2.0/wd*j, 2.0/wd*k});
+ W.push_back(cite1); // debug purpose
+ insert_delaunay_landmark_with_copies(W, W.size()-1,
+ landmarks_ind, t, landmark_count, true);
+
+ Point_d cite2(std::vector<FT>{2.0/wd*(i+0.5), 2.0/wd*(j+0.5), 2.0/wd*(k+0.5)});
+ W.push_back(cite2); // debug purpose
+ insert_delaunay_landmark_with_copies(W, W.size()-1,
+ landmarks_ind, t, landmark_count, true);
+ }
+ }
+
+ // ITERATIONS
+ R_max_handle rh = sampling_radius(t);
+ Point_d rp = *(Random_point_iterator(D, alpha*rh.value));
+ int death_count = 0;
+ std::cout << "death count " << death_count << " rp = " << rp << "\n";
+ while (death_count < 100)
+ {
+ std::vector<FT> coords;
+ for (auto c_it = rh.center.cartesian_begin(),
+ r_it = rp.cartesian_begin();
+ c_it != rh.center.cartesian_end();
+ ++c_it, ++r_it)
+ coords.push_back(*c_it + *r_it);
+ Point_d new_p(coords);
+ if (!is_violating_protection(new_p, t, D, delta0, power_protection, theta0, gamma0))
+ {
+ W.push_back(new_p);
+ insert_delaunay_landmark_with_copies(W, W.size()-1, landmarks_ind, t, landmark_count, torus);
+ rh = sampling_radius(t);
+ rp = *(Random_point_iterator(D, alpha*rh.value));
+ death_count = 0;
+ std::cout << "death count " << death_count << " rp = " << rp << "\n";
+ }
+ else
+ {
+ rp = *(Random_point_iterator(D, alpha*rh.value));
+ death_count++;
+ std::cout << "death count " << death_count << " rp = " << rp << "\n";
+ }
+ //Point_d new_p = (*rp++) + Vector_d;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Series of experiments
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void start_experiments(Point_Vector& W, FT alpha, std::vector<int>& landmarks_ind, FT epsilon)
+{
+ int experiment_no = 1;
+ FT delta0 = 0.1;
+ FT theta0 = 0.1;
+ FT gamma0 = 0.01;
+ std::string suffix;
+ //std::cout << "ようこそジプシー我が神秘の部屋へ:\n";
+ while (experiment_no != 0)
+ {
+ std::cout << "Enter experiment no (0 to exit): ";
+ std::cin >> experiment_no;
+ switch (experiment_no)
+ {
+ case 1:
+ // Experiment 1
+ experiment1 = true;
+ eps_vector = {};
+ std::cout << "Enter delta0: "; std::cin >> delta0;
+ std::cout << "Enter theta0: "; std::cin >> theta0;
+ std::cout << "Enter gamma0: "; std::cin >> gamma0;
+ protected_delaunay(W, landmarks_ind, alpha, epsilon, delta0, theta0, gamma0, true, true);
+ write_tikz_plot(eps_vector,"epstime.tikz");
+ experiment1 = false;
+ break;
+
+ case 2:
+ // Experiment 2
+ suffix = "";
+ experiment2 = true;
+ epsratio_vector = {0};
+ epsslope_vector = {0};
+ std::cout << "File name suffix: ";
+ std::cin >> suffix;
+ for (FT alpha = 0.01; alpha < 0.999; alpha += 0.01)
+ {
+ landmarks_ind.clear();
+ std::cout << "Test for alpha = " << alpha << "\n";
+ protected_delaunay(W, landmarks_ind, alpha, epsilon, delta0, theta0, gamma0, true, true);
+ }
+ write_tikz_plot(epsratio_vector,"epsratio_alpha." + suffix + ".tex");
+ write_tikz_plot(epsslope_vector,"epsslope_alpha." + suffix + ".tex");
+ experiment2 = false;
+ break;
+
+ case 3:
+ // Experiment 3
+ experiment3 = true;
+ thetamin_vector = {};
+ gammamin_vector = {};
+ theta0 = 0;
+ gamma0 = 0;
+ for (FT delta0 = 0; delta0 < 0.999; delta0 += 0.05)
+ {
+ landmarks_ind.clear();
+ thetamin_vector.push_back(1.0); //0.7489 fatness of the initialization
+ gammamin_vector.push_back(10);
+ std::cout << "Test for delta0 = " << delta0 << "\n";
+ protected_delaunay(W, landmarks_ind, alpha, epsilon, delta0, theta0, gamma0, true, true);
+ }
+ write_tikz_plot(thetamin_vector,"thetamin_delta.tex");
+ write_tikz_plot(gammamin_vector,"gammamin_delta.tex");
+ experiment3 = false;
+ break;
+
+ // case 4:
+ // // Experiment 4
+ // {
+ // int dim;
+ // std::cout << "Enter dimension: ";
+ // std::cin >> dim;
+ // Delaunay_triangulation t(dim);
+ // // for (FT eps = 0.7; eps < 1.1; eps += 0.1)
+ // // {
+ // // generate_epsilon_sample_torus(W, eps, dim, t);
+ // // for (auto v_it = t.vertices_begin(); v_it != t.vertices_end(); ++v_it)
+ // // {
+ // // if (t.is_infinite(v_it))
+ // // continue;
+ // // bool in_cube = true;
+ // // for (auto xi = v_it->cartesian_begin(); xi != v_it->cartesian_end(); ++xi)
+ // // if (*xi > 1.0 || *xi < -1.0)
+ // // {
+ // // in_cube = false; break;
+ // // }
+ // // if (!in_cube)
+ // // continue;
+ // // for (auto t.tds().incident_full_cells())
+ // // }
+ // // std::cout << "eps = " << eps << ", real epsilon = " << sampling_radius(t).value << "\n";
+ // // }
+ // // }
+ // break;
+
+
+ case 5:
+ // Experiment 5
+ experiment5 = true;
+ // std::cout << "Enter dimension: ";
+ // std::cin >> dim;
+
+ landmarks_ind.clear();
+ W.clear();
+ run_experiment5(W, alpha, epsilon, delta0, theta0, gamma0, true, true);
+ experiment5 = false;
+ break;
+ }
+
+ }
+
+}
+
+#endif