summaryrefslogtreecommitdiff
path: root/src/Coxeter_triangulation/include/gudhi/Coxeter_triangulation/Cell_complex/Cell_complex.h
blob: de342eccea9c78c2aa18575fbf12d765384b4c8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/*    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):       Siargey Kachanovich
 *
 *    Copyright (C) 2019 Inria
 *
 *    Modification(s):
 *      - YYYY/MM Author: Description of the modification
 */

#ifndef CELL_COMPLEX_H_
#define CELL_COMPLEX_H_

#include <Eigen/Dense>

#include <vector>
#include <map>
#include <utility>  // for std::make_pair

#include <gudhi/IO/output_debug_traces_to_html.h>  // for DEBUG_TRACES
#include <gudhi/Permutahedral_representation/Simplex_comparator.h>
#include <gudhi/Coxeter_triangulation/Cell_complex/Hasse_diagram_cell.h>  // for Hasse_cell

namespace Gudhi {

namespace coxeter_triangulation {

/** \class Cell_complex
 *  \brief A class that constructs the cell complex from the output provided by the class
 *   \ref Gudhi::coxeter_triangulation::Manifold_tracing.
 * 
 *  The use and interfaces of this cell complex is limited to the \ref coxeter_triangulation implementation.
 *
 *  \tparam Out_simplex_map_ The type of a map from a simplex type that is a
 *   model of SimplexInCoxeterTriangulation to Eigen::VectorXd.
 */
template <class Out_simplex_map_>
class Cell_complex {
 public:
  /** \brief Type of a simplex in the ambient triangulation.
   *  Is a model of the concept SimplexInCoxeterTriangulation.
   */
  using Simplex_handle = typename Out_simplex_map_::key_type;
  /** \brief Type of a cell in the cell complex.
   *  Always is Gudhi::Hasse_cell from the Hasse diagram module.
   *  The additional information is the boolean that is true if and only if the cell lies
   *  on the boundary.
   */
  using Hasse_cell = Gudhi::Hasse_diagram::Hasse_diagram_cell<int, double, bool>;
  /** \brief Type of a map from permutahedral representations of simplices in the
   *  ambient triangulation to the corresponding cells in the cell complex of some
   *  specific dimension.
   */
  using Simplex_cell_map = std::map<Simplex_handle, Hasse_cell*, Simplex_comparator<Simplex_handle> >;
  /** \brief Type of a vector of maps from permutahedral representations of simplices in the
   *  ambient triangulation to the corresponding cells in the cell complex of various dimensions.
   */
  using Simplex_cell_maps = std::vector<Simplex_cell_map>;

  /** \brief Type of a map from cells in the cell complex to the permutahedral representations
   *  of the corresponding simplices in the ambient triangulation.
   */
  using Cell_simplex_map = std::map<Hasse_cell*, Simplex_handle>;

  /** \brief Type of a map from vertex cells in the cell complex to the permutahedral representations
   *  of their Cartesian coordinates.
   */
  using Cell_point_map = std::map<Hasse_cell*, Eigen::VectorXd>;

 private:
  Hasse_cell* insert_cell(const Simplex_handle& simplex, std::size_t cell_d, bool is_boundary) {
    Simplex_cell_maps& simplex_cell_maps = (is_boundary ? boundary_simplex_cell_maps_ : interior_simplex_cell_maps_);
#ifdef DEBUG_TRACES
    CC_detail_list& cc_detail_list =
        (is_boundary ? cc_boundary_detail_lists[cell_d] : cc_interior_detail_lists[cell_d]);
    cc_detail_list.emplace_back(simplex);
#endif
    Simplex_cell_map& simplex_cell_map = simplex_cell_maps[cell_d];
    auto map_it = simplex_cell_map.find(simplex);
    if (map_it == simplex_cell_map.end()) {
      hasse_cells_.push_back(new Hasse_cell(is_boundary, cell_d));
      Hasse_cell* new_cell = hasse_cells_.back();
      simplex_cell_map.emplace(simplex, new_cell);
      cell_simplex_map_.emplace(new_cell, simplex);
#ifdef DEBUG_TRACES
      cc_detail_list.back().status_ = CC_detail_info::Result_type::inserted;
#endif
      return new_cell;
    }
#ifdef DEBUG_TRACES
    CC_detail_info& cc_info = cc_detail_list.back();
    cc_info.trigger_ = to_string(map_it->first);
    cc_info.status_ = CC_detail_info::Result_type::self;
#endif
    return map_it->second;
  }

  void expand_level(std::size_t cell_d) {
    bool is_manifold_with_boundary = boundary_simplex_cell_maps_.size() > 0;
    for (auto& sc_pair : interior_simplex_cell_maps_[cell_d - 1]) {
      const Simplex_handle& simplex = sc_pair.first;
      Hasse_cell* cell = sc_pair.second;
      for (Simplex_handle coface : simplex.coface_range(cod_d_ + cell_d)) {
        Hasse_cell* new_cell = insert_cell(coface, cell_d, false);
        new_cell->get_boundary().emplace_back(cell, 1);
      }
    }

    if (is_manifold_with_boundary) {
      for (auto& sc_pair : boundary_simplex_cell_maps_[cell_d - 1]) {
        const Simplex_handle& simplex = sc_pair.first;
        Hasse_cell* cell = sc_pair.second;
        if (cell_d != intr_d_)
          for (Simplex_handle coface : simplex.coface_range(cod_d_ + cell_d + 1)) {
            Hasse_cell* new_cell = insert_cell(coface, cell_d, true);
            new_cell->get_boundary().emplace_back(cell, 1);
          }
        auto map_it = interior_simplex_cell_maps_[cell_d].find(simplex);
        if (map_it == interior_simplex_cell_maps_[cell_d].end())
          std::cerr << "Cell_complex::expand_level error: A boundary cell does not have an interior counterpart.\n";
        else {
          Hasse_cell* i_cell = map_it->second;
          i_cell->get_boundary().emplace_back(cell, 1);
        }
      }
    }
  }

  void construct_complex_(const Out_simplex_map_& out_simplex_map) {
#ifdef DEBUG_TRACES
    cc_interior_summary_lists.resize(interior_simplex_cell_maps_.size());
    cc_interior_prejoin_lists.resize(interior_simplex_cell_maps_.size());
    cc_interior_detail_lists.resize(interior_simplex_cell_maps_.size());
#endif
    for (auto& os_pair : out_simplex_map) {
      const Simplex_handle& simplex = os_pair.first;
      const Eigen::VectorXd& point = os_pair.second;
      Hasse_cell* new_cell = insert_cell(simplex, 0, false);
      cell_point_map_.emplace(new_cell, point);
    }
    for (std::size_t cell_d = 1;
         cell_d < interior_simplex_cell_maps_.size() && !interior_simplex_cell_maps_[cell_d - 1].empty(); ++cell_d) {
      expand_level(cell_d);
    }
  }

  void construct_complex_(const Out_simplex_map_& interior_simplex_map, const Out_simplex_map_& boundary_simplex_map) {
#ifdef DEBUG_TRACES
    cc_interior_summary_lists.resize(interior_simplex_cell_maps_.size());
    cc_interior_prejoin_lists.resize(interior_simplex_cell_maps_.size());
    cc_interior_detail_lists.resize(interior_simplex_cell_maps_.size());
    cc_boundary_summary_lists.resize(boundary_simplex_cell_maps_.size());
    cc_boundary_prejoin_lists.resize(boundary_simplex_cell_maps_.size());
    cc_boundary_detail_lists.resize(boundary_simplex_cell_maps_.size());
#endif
    for (auto& os_pair : boundary_simplex_map) {
      const Simplex_handle& simplex = os_pair.first;
      const Eigen::VectorXd& point = os_pair.second;
      Hasse_cell* new_cell = insert_cell(simplex, 0, true);
      cell_point_map_.emplace(new_cell, point);
    }
    for (auto& os_pair : interior_simplex_map) {
      const Simplex_handle& simplex = os_pair.first;
      const Eigen::VectorXd& point = os_pair.second;
      Hasse_cell* new_cell = insert_cell(simplex, 0, false);
      cell_point_map_.emplace(new_cell, point);
    }
#ifdef DEBUG_TRACES
    for (const auto& sc_pair : interior_simplex_cell_maps_[0])
      cc_interior_summary_lists[0].push_back(CC_summary_info(sc_pair));
    for (const auto& sc_pair : boundary_simplex_cell_maps_[0])
      cc_boundary_summary_lists[0].push_back(CC_summary_info(sc_pair));
#endif

    for (std::size_t cell_d = 1;
         cell_d < interior_simplex_cell_maps_.size() && !interior_simplex_cell_maps_[cell_d - 1].empty(); ++cell_d) {
      expand_level(cell_d);

#ifdef DEBUG_TRACES
      for (const auto& sc_pair : interior_simplex_cell_maps_[cell_d])
        cc_interior_summary_lists[cell_d].push_back(CC_summary_info(sc_pair));
      if (cell_d < boundary_simplex_cell_maps_.size())
        for (const auto& sc_pair : boundary_simplex_cell_maps_[cell_d])
          cc_boundary_summary_lists[cell_d].push_back(CC_summary_info(sc_pair));
#endif
    }
  }

 public:
  /**
   * \brief Constructs the the cell complex that approximates an \f$m\f$-dimensional manifold
   *  without boundary embedded in the \f$ d \f$-dimensional Euclidean space
   *  from the output of the class Gudhi::Manifold_tracing.
   *
   * \param[in] out_simplex_map A map from simplices of dimension \f$(d-m)\f$
   * in the ambient triangulation that intersect the relative interior of the manifold
   * to the intersection points.
   */
  void construct_complex(const Out_simplex_map_& out_simplex_map) {
    interior_simplex_cell_maps_.resize(intr_d_ + 1);
    if (!out_simplex_map.empty()) cod_d_ = out_simplex_map.begin()->first.dimension();
    construct_complex_(out_simplex_map);
  }

  /**
   * \brief Constructs the skeleton of the cell complex that approximates
   *  an \f$m\f$-dimensional manifold without boundary embedded
   *  in the \f$d\f$-dimensional Euclidean space
   *  up to a limit dimension from the output of the class Gudhi::Manifold_tracing.
   *
   * \param[in] out_simplex_map A map from simplices of dimension \f$(d-m)\f$
   * in the ambient triangulation that intersect the relative interior of the manifold
   * to the intersection points.
   * \param[in] limit_dimension The dimension of the constructed skeleton.
   */
  void construct_complex(const Out_simplex_map_& out_simplex_map, std::size_t limit_dimension) {
    interior_simplex_cell_maps_.resize(limit_dimension + 1);
    if (!out_simplex_map.empty()) cod_d_ = out_simplex_map.begin()->first.dimension();
    construct_complex_(out_simplex_map);
  }

  /**
   * \brief Constructs the the cell complex that approximates an \f$m\f$-dimensional manifold
   *  with boundary embedded in the \f$ d \f$-dimensional Euclidean space
   *  from the output of the class Gudhi::Manifold_tracing.
   *
   * \param[in] interior_simplex_map A map from simplices of dimension \f$(d-m)\f$
   * in the ambient triangulation that intersect the relative interior of the manifold
   * to the intersection points.
   * \param[in] boundary_simplex_map A map from simplices of dimension \f$(d-m+1)\f$
   * in the ambient triangulation that intersect the boundary of the manifold
   * to the intersection points.
   */
  void construct_complex(const Out_simplex_map_& interior_simplex_map, const Out_simplex_map_& boundary_simplex_map) {
    interior_simplex_cell_maps_.resize(intr_d_ + 1);
    boundary_simplex_cell_maps_.resize(intr_d_);
    if (!interior_simplex_map.empty()) cod_d_ = interior_simplex_map.begin()->first.dimension();
    construct_complex_(interior_simplex_map, boundary_simplex_map);
  }

  /**
   * \brief Constructs the skeleton of the cell complex that approximates
   *  an \f$m\f$-dimensional manifold with boundary embedded
   *  in the \f$d\f$-dimensional Euclidean space
   *  up to a limit dimension from the output of the class Gudhi::Manifold_tracing.
   *
   * \param[in] interior_simplex_map A map from simplices of dimension \f$(d-m)\f$
   * in the ambient triangulation that intersect the relative interior of the manifold
   * to the intersection points.
   * \param[in] boundary_simplex_map A map from simplices of dimension \f$(d-m+1)\f$
   * in the ambient triangulation that intersect the boundary of the manifold
   * to the intersection points.
   * \param[in] limit_dimension The dimension of the constructed skeleton.
   */
  void construct_complex(const Out_simplex_map_& interior_simplex_map, const Out_simplex_map_& boundary_simplex_map,
                         std::size_t limit_dimension) {
    interior_simplex_cell_maps_.resize(limit_dimension + 1);
    boundary_simplex_cell_maps_.resize(limit_dimension);
    if (!interior_simplex_map.empty()) cod_d_ = interior_simplex_map.begin()->first.dimension();
    construct_complex_(interior_simplex_map, boundary_simplex_map);
  }

  /**
   * \brief Returns the dimension of the cell complex.
   */
  std::size_t intrinsic_dimension() const { return intr_d_; }

  /**
   * \brief Returns a vector of maps from the cells of various dimensions in the interior
   *  of the cell complex of type Gudhi::Hasse_cell to the permutahedral representations
   *  of the corresponding simplices in the ambient triangulation.
   */
  const Simplex_cell_maps& interior_simplex_cell_maps() const { return interior_simplex_cell_maps_; }

  /**
   * \brief Returns a vector of maps from the cells of various dimensions on the boundary
   *  of the cell complex of type Gudhi::Hasse_cell to the permutahedral representations
   *  of the corresponding simplices in the ambient triangulation.
   */
  const Simplex_cell_maps& boundary_simplex_cell_maps() const { return boundary_simplex_cell_maps_; }

  /**
   * \brief Returns a map from the cells of a given dimension in the interior
   *  of the cell complex of type Gudhi::Hasse_cell to the permutahedral representations
   *  of the corresponding simplices in the ambient triangulation.
   *
   * \param[in] cell_d The dimension of the cells.
   */
  const Simplex_cell_map& interior_simplex_cell_map(std::size_t cell_d) const {
    return interior_simplex_cell_maps_[cell_d];
  }

  /**
   * \brief Returns a map from the cells of a given dimension on the boundary
   *  of the cell complex of type Gudhi::Hasse_cell to the permutahedral representations
   *  of the corresponding simplices in the ambient triangulation.
   *
   * \param[in] cell_d The dimension of the cells.
   */
  const Simplex_cell_map& boundary_simplex_cell_map(std::size_t cell_d) const {
    return boundary_simplex_cell_maps_[cell_d];
  }

  /**
   * \brief Returns a map from the cells in the cell complex of type Gudhi::Hasse_cell
   *  to the permutahedral representations of the corresponding simplices in the
   *  ambient triangulation.
   */
  const Cell_simplex_map& cell_simplex_map() const { return cell_simplex_map_; }

  /**
   * \brief Returns a map from the vertex cells in the cell complex of type Gudhi::Hasse_cell
   *  to their Cartesian coordinates.
   */
  const Cell_point_map& cell_point_map() const { return cell_point_map_; }

  /**
   * \brief Constructor for the class Cell_complex.
   *
   * \param[in] intrinsic_dimension The dimension of the cell complex.
   */
  Cell_complex(std::size_t intrinsic_dimension) : intr_d_(intrinsic_dimension) {}

  ~Cell_complex() {
    for (Hasse_cell* hs_ptr : hasse_cells_) delete hs_ptr;
  }

 private:
  std::size_t intr_d_, cod_d_;
  Simplex_cell_maps interior_simplex_cell_maps_, boundary_simplex_cell_maps_;
  Cell_simplex_map cell_simplex_map_;
  Cell_point_map cell_point_map_;
  std::vector<Hasse_cell*> hasse_cells_;
};

}  // namespace coxeter_triangulation

}  // namespace Gudhi

#endif