-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsimplextree.h
262 lines (215 loc) · 9.36 KB
/
simplextree.h
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
// simplextree.h
// Author: Matt Piekenbrock
// License: MIT
// This package provides a simple implementation of the Simplex tree data structure using Rcpp + STL
// The simplex tree was originally introduced in the following paper:
// Boissonnat, Jean-Daniel, and Clement Maria. "The simplex tree: An efficient data structure for general simplicial complexes." Algorithmica 70.3 (2014): 406-427.
#ifndef SIMPLEXTREE_H_
#define SIMPLEXTREE_H_
#include <unordered_map>
#include <queue>
#include <vector>
#include <deque>
#include <memory>
#include <tuple>
#include <array>
#include <set>
#include <map>
#include <string>
#include "UnionFind.h"
#include "utility/discrete.h"
#include "utility/combinations.h"
#include "utility/delegate.hpp"
#include "utility/set_utilities.h"
// #include <iostream>
// Type for simplex labels
typedef std::size_t idx_t;
// Maximum expected size of simplices
static constexpr size_t array_threshold = 9;
// Buffer type
using splex_t = std::vector< idx_t, short_alloc< idx_t, 16, alignof(idx_t)> >;
using splex_alloc_t = typename splex_t::allocator_type::arena_type;
// Aliases
using std::array;
using std::tuple;
using std::vector;
using std::map;
using std::size_t;
using std::begin;
using std::end;
using std::set;
using std::find;
using std::get;
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args){
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// Simplex tree data structure.
// The Simplex Tree is a normal trie structure, with additional restrictions on the storage order,
// and a auxiliary map that is used to map 'cousin' simplexes at varying depths.
struct SimplexTree {
struct node;
using node_ptr = node*;
using node_uptr = std::unique_ptr< node >;
struct less_np_label {
bool operator()(const node_ptr& lhs, const node_uptr& rhs) {
return lhs->label < rhs->label;
}
bool operator()(const node_uptr& lhs, const node_ptr& rhs) {
return lhs->label < rhs->label;
}
};
struct less_ptr {
bool operator() (const node_uptr& lhs, const node_uptr& rhs) const { return (*lhs) < (*rhs); }
};
using node_set_t = set< node_uptr, less_ptr >;
using simplex_t = vector< idx_t >;
using cousin_map_t = std::map< idx_t, vector< node_ptr > >;
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
using value_type = node_ptr;
// Fields
node_uptr root; // empty face; initialized to id = 0, parent = nullptr
vector< cousin_map_t > level_map; // adjacency map between cousins
std::array< size_t, 32 > n_simplexes = { { 0 } };
// vector< size_t > n_simplexes; // tracks the number of simplices if each order
size_t tree_max_depth; // maximum tree depth; largest path from any given leaf to the root. The depth of the root is 0.
size_t max_id; // maximum vertex id used so far. Only needed by the id generator.
size_t id_policy; // policy type to generate new ids
// Node structure stored by the simplex tree. Contains the following fields:
// label := integer index type representing the id of simplex it represents
// parent := (shared) node pointer to its parent in the trie
// children := connected simplexes whose labels > the current simplex's label
struct node {
idx_t label;
node* parent;
node_set_t children;
node(idx_t id, node_ptr c_parent) : label(id), parent(c_parent){ }
node(const node& other) = delete;
bool operator== (const node& rhs) const noexcept { // equivalence by pointer address
return (this == &rhs);
}
bool operator< (const node& rhs) const { return (label < rhs.label); } // order by label
// struct iterator {
// using difference_type = std::ptrdiff_t;
// using value_type = node_ptr;
// using pointer = node_ptr*;
// using reference = node_ptr&;
// using iterator_category = std::forward_iterator_tag;
// std::reference_wrapper< node_ptr > cn;
// iterator(node_ptr current) : cn(std::ref(current)) { };
// bool operator==(const iterator& t) const { return cn == t.cn; }
// bool operator!=(const iterator& t) const { return cn != t.cn; }
// auto operator*() { return cn.get(); };
// auto operator++() {
// cn = std::ref(cn.get()->parent);
// return(*this);
// };
// };
// auto begin() { return iterator(this); };
// auto end() { return iterator(nullptr); };
};
SimplexTree(const SimplexTree&);
SimplexTree& operator=(const SimplexTree&);
// Adds node ptr to cousin map
void add_cousin(node_ptr cn, const idx_t depth){
if (depth_index(depth) >= level_map.size()){
level_map.resize(depth_index(depth) + 1);
}
auto& label_map = level_map[depth_index(depth)][cn->label];
auto it = std::find(begin(label_map), end(label_map), cn);
if (it == end(label_map)){ label_map.push_back(cn); } // insert
}
// Removes node ptr from cousin map
void remove_cousin(node_ptr cn, const idx_t depth){
if (depth_index(depth) >= level_map.size()){ return; }
auto& depth_map = level_map[depth_index(depth)];
auto cousin_it = depth_map.find(cn->label);
if (cousin_it != end(depth_map)){
auto& v = cousin_it->second;
v.erase(std::remove(v.begin(), v.end(), cn), v.end());
}
}
template < typename Iter >
auto append_node(Iter pos, node_ptr cn, idx_t label, size_t depth) -> node_set_t::iterator;
// Checks if cousins exist
bool cousins_exist(const idx_t label, const idx_t depth) const noexcept {
if (depth_index(depth) >= level_map.size()){ return false; }
return level_map[depth_index(depth)].find(label) != end(level_map[depth_index(depth)]);
}
const cousin_map_t::mapped_type& cousins(const idx_t label, const idx_t depth) const {
return level_map[depth_index(depth)].at(label);
}
template < typename Lambda >
void traverse_cousins(const idx_t label, const idx_t depth, Lambda f) const {
if (depth_index(depth) >= level_map.size()){ return; }
if (cousins_exist(label, depth)){
const auto& c_cousins = level_map[depth_index(depth)].at(label);
std::for_each(begin(c_cousins), end(c_cousins), f);
}
};
// Constructor
SimplexTree() : root(new node(-1, nullptr)), tree_max_depth(0), max_id(0), id_policy(0) { };
// Generates a new set of vertex ids, according to the given rule.
auto generate_ids(size_t) -> vector< size_t >;
auto degree(idx_t) const -> size_t;
auto adjacent_vertices(const idx_t) const -> simplex_t;
auto record_new_simplexes(const idx_t k, const int n) -> void;// record keeping
auto dimension() const -> idx_t { return tree_max_depth == 0 ? 0 : tree_max_depth - 1; }
template< typename Iterable >
auto insert(Iterable v) -> void;
template< bool use_lex = false, typename Iter >
auto insert_it(Iter, Iter, node_ptr, const idx_t) -> void;
template< typename Iterable >
auto find(Iterable v) const -> node_ptr;
template< typename Iter >
auto find_it(Iter, Iter, node_ptr cn) const -> node_ptr;
auto find_by_id(const node_set_t&, idx_t) const -> node_ptr;
auto remove(node_ptr cn) -> void;
auto remove_leaf(node_ptr, idx_t) -> void;
auto remove_subtree(node_ptr parent) -> void;
template < typename Lambda >
void traverse_facets(node_ptr, Lambda) const;
// Utility
auto is_face(simplex_t, simplex_t) const -> bool;
auto depth(node_ptr cn) const -> size_t;
auto max_depth(node_ptr cn) const -> size_t;
auto connected_components() const -> vector< idx_t >;
auto reindex(vector< idx_t >) -> void;
auto is_tree() const -> bool;
auto get_vertices() const -> vector< idx_t >;
auto clear() -> void;
// Modifying the complex w/ higher order operations
auto collapse(node_ptr, node_ptr) -> bool;
auto vertex_collapse(idx_t, idx_t, idx_t) -> bool;
auto vertex_collapse(node_ptr, node_ptr, node_ptr) -> bool;
auto contract(simplex_t) -> void;
auto expansion(const idx_t k) -> void;
template < typename Lambda >
auto expansion_f(const idx_t, Lambda&&) -> void;
template < typename Lambda >
auto expand_f(node_set_t&, const idx_t, size_t, Lambda&&) -> void;
template < typename Lambda >
void traverse_up(node_ptr, const size_t, Lambda&&) const noexcept;
template< typename OutputIt >
void full_simplex_out(node_ptr, const idx_t, OutputIt) const noexcept;
auto full_simplex(node_ptr cn, const idx_t depth = 0) const noexcept -> simplex_t;
template < typename T > // Assumes T is pointer type
static constexpr auto node_label(T& cn) -> idx_t { return cn->label; }
template < typename T > // Assumes T is pointer type
static constexpr auto node_children(T& cn) -> node_set_t& { return cn->children; }
static constexpr auto depth_index(const idx_t depth) noexcept -> idx_t { return(depth - 2); }
// Printing
template < typename OutputStream > void print_tree(OutputStream&) const;
template < typename OutputStream > void print_cousins(OutputStream&) const;
template < typename OutputStream > void print_level(OutputStream&, node_ptr, idx_t) const;
template < typename OutputStream > void print_subtree(OutputStream&, node_ptr) const;
template < typename OutputStream > void print_simplex(OutputStream&, node_ptr, bool newline = true) const;
// Policy for generating ids
std::string get_id_policy() const;
void set_id_policy(std::string);
};
#include "simplextree/st_iterators.hpp"
#include "simplextree/st_filtration.hpp"
#include "simplextree/st.hpp"
#endif