11 : n_(distanceMatrix ? (1 + sqrt(1 + 8 * points[0].size())) / 2
13 parallelSort_(parallelSort), oracle_(oracle) {
18 compressedDM_ = points[0];
20 const unsigned dim = points[0].size();
21 for(
int i = 1; i < n_; ++i) {
22 for(
int j = 0; j < i; ++j) {
24 for(
unsigned d = 0; d < dim; ++d)
25 s += (points[i][d] - points[j][d]) * (points[i][d] - points[j][d]);
26 compressedDM_.push_back(sqrt(s));
38 : n_(n), parallelSort_(parallelSort), oracle_(oracle) {
42 for(
int i = 1; i < n_; ++i) {
43 for(
int j = 0; j < i; ++j) {
45 for(
int d = 0; d < dim; ++d)
46 s += (data[dim * i + d] - data[dim * j + d])
47 * (data[dim * i + d] - data[dim * j + d]);
48 compressedDM_.push_back(sqrt(s));
56 bool distanceMatrix) {
57 ripser::ripser(points, oracle, threshold, 1, distanceMatrix,
false,
false);
62 if(x.second.second == y.second.second) {
64 Simplex const &t1 = x.second.first;
65 Simplex const &t2 = y.second.first;
66 return !std::lexicographical_compare(
67 t1.rbegin(), t1.rend(), t2.rbegin(), t2.rend());
69 return x.second.second < y.second.second;
75 for(
auto const &[b, d] : oracle_[1]) {
77 bound_ = std::max(bound_, d.second);
79 printMsg(
"Upper bound from the PD oracle: " + std::to_string(bound_));
80 initializeWithBound();
81 printMsg(
"Initialized (#p=" + std::to_string(n_)
82 +
", #e=" + std::to_string(nEdges_) +
")",
83 0, tm.getElapsedTime());
84 pairCellsWithOracle();
85 printMsg(
"Complete", 1, tm.getElapsedTime());
88void ttk::rpd::PairCellsWithOracle::initializeWithBound() {
91 for(
id_t i = 0; i < n_; ++i) {
92 for(
id_t j = i + 1; j < n_; ++j) {
93 if(DM(i, j) <= bound_) {
94 edgeToIndex_[{i, j}] = edges_.size();
95 edges_.push_back({{i, j}, DM(i, j)});
101 nEdges_ = edges_.size();
104 edgesIndices_.resize(nEdges_);
105 edgesOrder_.resize(nEdges_);
106 edgesPartner_.resize(nEdges_, -1);
107 std::iota(edgesIndices_.begin(), edgesIndices_.end(), 0);
110 [&](
id_t i,
id_t j) { return edges_[i] < edges_[j]; })
112 std::sort(edgesIndices_.begin(), edgesIndices_.end(),
113 [&](
id_t i,
id_t j) { return edges_[i] < edges_[j]; });
114 for(
unsigned i = 0; i < edgesIndices_.size(); ++i)
115 edgesOrder_[edgesIndices_[i]] = i;
118void ttk::rpd::PairCellsWithOracle::pairCellsWithOracle() {
119 for(
const auto &[birth, death] : oracle_[1]) {
120 if(death.second <
inf) {
121 const id_t e_id = edgeToIndex_[{birth.first[0], birth.first[1]}];
122 const id_t t_id = triangles_.size();
123 triangles_.push_back(
124 {{death.first[0], death.first[1], death.first[2]}, death.second});
125 boundaries_.push_back({edgeToIndex_[{death.first[0], death.first[1]}],
126 edgeToIndex_[{death.first[1], death.first[2]}],
127 edgeToIndex_[{death.first[0], death.first[2]}]});
128 cascadeEdges_.emplace_back();
129 trianglesPartner_.push_back(e_id);
130 edgesPartner_[e_id] = t_id;
131 eliminateBoundaryWithOracle(t_id, e_id);
136void ttk::rpd::PairCellsWithOracle::eliminateBoundaryWithOracle(
id_t t_id,
139 id_t youngest_id = -1;
140 while(youngest_id != e_id) {
141 youngest_id = *std::max_element(
142 boundaries_[t_id].
begin(), boundaries_[t_id].
end(),
143 [&](
id_t i,
id_t j) {
return edgesOrder_[i] < edgesOrder_[j]; });
144 if(youngest_id == e_id)
146 cascadeEdges_[t_id].push_back(youngest_id);
147 if(edgesPartner_[youngest_id] != -1)
148 bc.exclusiveAddBoundary(boundaries_[edgesPartner_[youngest_id]]);
150 const auto &[i, j] = edges_[youngest_id].e;
151 const double d = edges_[youngest_id].d;
152 for(
id_t const &k : graph_[i]) {
153 if(DM(i, k) < d && DM(j, k) < d) {
154 bc.exclusiveAddBoundary({youngest_id, edgeToIndex_[std::minmax(i, k)],
155 edgeToIndex_[std::minmax(j, k)]});
164 std::vector<Generator1> &generators)
const {
165 for(
unsigned i = 0; i < triangles_.size(); ++i) {
167 for(
id_t const &e_id : boundaries_[i])
168 boundary.emplace_back(edges_[e_id].e);
169 generators.emplace_back(
171 std::make_pair(edges_[trianglesPartner_[i]].d, triangles_[i].d));
178 for(
auto const &c : cascadeEdges_) {
179 critical[
DEATH1].emplace_back(edges_[c[0]].e);
181 for(
id_t const &e_id : c)
182 cascade.emplace_back(edges_[e_id].e);
183 cascades.push_back(cascade);
189 std::set<id_t> cascadeSet;
190 for(
auto const &c : cascadeEdges_) {
191 critical[
DEATH1].emplace_back(edges_[c[0]].e);
192 for(
unsigned i = 1; i < c.size(); ++i)
193 cascadeSet.insert(c[i]);
195 for(
const id_t &e_id : cascadeSet)
196 critical[
CASC1].emplace_back(edges_[e_id].e);
#define TTK_PSORT(NTHREADS,...)
Parallel sort macro.
void setDebugMsgPrefix(const std::string &prefix)
void getGenerators(std::vector< Generator1 > &generators) const
PairCellsWithOracle(const PointCloud &points, MultidimensionalDiagram const &oracle, bool distanceMatrix=false, bool parallelSort=false)
void getCascades(std::vector< Cascade > &cascades, EdgeSets3 &critical) const
static void callOracle(const PointCloud &points, MultidimensionalDiagram &oracle, double threshold=inf, bool distanceMatrix=false)
void ripser(std::vector< std::vector< value_t > > points, PersistenceType &ph, value_t threshold, index_t dim_max, bool distanceMatrix, bool criticalEdgesOnly=true, bool infinitePairs=true, coefficient_t modulus=2)
std::array< EdgeSet, 4 > EdgeSets4
std::pair< FiltratedSimplex, FiltratedSimplex > PersistencePair
std::vector< std::vector< value_t > > PointCloud
std::vector< Edge > EdgeSet
std::vector< Diagram > MultidimensionalDiagram
std::array< EdgeSet, 3 > EdgeSets3
std::vector< id_t > Simplex
COMMON_EXPORTS int globalThreadNumber_
T end(std::pair< T, T > &p)
T begin(std::pair< T, T > &p)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)