TTK
Loading...
Searching...
No Matches
PersistenceDiagramDictionary.cpp
Go to the documentation of this file.
2#include <algorithm>
3#include <cmath>
4
6
7using namespace ttk;
8
10 std::vector<ttk::DiagramType> &intermediateDiagrams,
11 const std::vector<ttk::DiagramType> &intermediateAtoms,
12 std::vector<ttk::DiagramType> &dictDiagrams,
13 std::vector<std::vector<double>> &vectorWeights,
14 const int seed,
15 const int numAtom,
16 std::vector<double> &lossTab,
17 std::vector<std::vector<double>> &allLosses,
18 double percent) {
19
20 if(!ProgApproach_) {
21 // Regular approach
22
23 bool doCompression = false;
25 doCompression = true;
26 }
27
28 std::vector<BidderDiagram> trueBidderDiagramMin(
29 intermediateDiagrams.size());
30 std::vector<BidderDiagram> trueBidderDiagramSad(
31 intermediateDiagrams.size());
32 std::vector<BidderDiagram> trueBidderDiagramMax(
33 intermediateDiagrams.size());
34
35 std::vector<std::vector<double>> histoVectorWeights(
36 intermediateDiagrams.size());
37 std::vector<ttk::DiagramType> histoDictDiagrams(numAtom);
38 this->MaxLag2_ = 5;
39
40 Timer tm_init{};
41 bool preWeightOpt = false;
42 this->printMsg("Regular approach:");
43 initDictionary(dictDiagrams, intermediateDiagrams, intermediateAtoms,
44 numAtom, this->do_min_, this->do_sad_, this->do_max_, seed,
45 percent);
46 this->printMsg("Initialization computed ", 1, tm_init.getElapsedTime(),
48
49 controlAtomsSize(intermediateDiagrams, dictDiagrams);
50
51 method(intermediateDiagrams, dictDiagrams, vectorWeights, numAtom, lossTab,
52 allLosses, histoVectorWeights, histoDictDiagrams, preWeightOpt,
53 percent, doCompression);
54 } else {
55 // Multi scale approach
56 bool doCompression = false;
57 for(size_t i = 0; i < intermediateDiagrams.size(); ++i) {
58 auto &diag = intermediateDiagrams[i];
59 std::sort(diag.begin(), diag.end(),
60 [](const PersistencePair &t1, const PersistencePair &t2) {
61 return (t1.death.sfValue - t1.birth.sfValue)
62 > (t2.death.sfValue - t2.birth.sfValue);
63 });
64 }
65
66 int start = 20;
67 double stop = percent;
68 std::vector<double> percentages;
69 for(int value = start; value > stop; value -= 5) {
70 percentages.push_back(static_cast<double>(value) / 100.);
71 }
72 percentages.push_back(static_cast<double>(percent) / 100.);
73 std::vector<std::vector<double>> histoVectorWeights(
74 intermediateDiagrams.size());
75 std::vector<ttk::DiagramType> histoDictDiagrams(numAtom);
76 std::vector<ttk::DiagramType> dataTemp(intermediateDiagrams.size());
77 bool preWeightOpt = true;
78 Timer tm_method{};
79 for(size_t j = 0; j < 1; ++j) {
80 double percentage = percentages[j];
81 this->MaxLag2_ = 0;
82 this->printMsg("First step multi-scale approach:");
83 for(size_t i = 0; i < intermediateDiagrams.size(); ++i) {
84 auto &diag = intermediateDiagrams[i];
85 auto &t = diag[0];
86 double maxPers = getMaxPers(diag);
87 dataTemp[i].push_back(t);
88 for(size_t p = 1; p < diag.size(); ++p) {
89 auto &t2 = diag[p];
90 if(percentage * maxPers <= (t2.death.sfValue - t2.birth.sfValue)) {
91 dataTemp[i].push_back(t2);
92 } else {
93 continue;
94 }
95 }
96 }
97
98 Timer tm_init{};
99 initDictionary(dictDiagrams, dataTemp, intermediateAtoms, numAtom,
100 this->do_min_, this->do_sad_, this->do_max_, seed,
101 percent);
102 this->printMsg("Initialization computed ", 1, tm_init.getElapsedTime(),
104
105 method(dataTemp, dictDiagrams, vectorWeights, numAtom, lossTab, allLosses,
106 histoVectorWeights, histoDictDiagrams, preWeightOpt, percent,
107 doCompression);
108 }
109
110 int counter = 0;
111 for(size_t j = 1; j < percentages.size(); ++j) {
112 if(j == percentages.size() - static_cast<size_t>(1) && CompressionMode_) {
113 doCompression = true;
114 }
115 double percentage = percentages[j];
116 double previousPerc = percentages[j - 1];
117 if(j < percentages.size() - 1) {
118 this->MaxLag2_ = 0;
119 } else {
120 this->MaxLag2_ = 5;
121 }
122 if(j < percentages.size() - 1) {
123 this->printMsg("New step multi-scale approach:");
124 } else {
125 this->printMsg("Final step multi-scale approach:");
126 }
127
128 for(size_t i = 0; i < intermediateDiagrams.size(); ++i) {
129 auto &diag = intermediateDiagrams[i];
130 double maxPers = getMaxPers(diag);
131 for(size_t p = 0; p < diag.size(); ++p) {
132 auto &t2 = diag[p];
133 if(percentage * maxPers <= (t2.death.sfValue - t2.birth.sfValue)
134 && (t2.death.sfValue - t2.birth.sfValue)
135 < previousPerc * maxPers) {
136 dataTemp[i].push_back(t2);
137 counter += 1;
138 }
139 }
140 }
141 if(counter == 0) {
142 continue;
143 }
144 method(dataTemp, dictDiagrams, vectorWeights, numAtom, lossTab, allLosses,
145 histoVectorWeights, histoDictDiagrams, preWeightOpt, percent,
146 doCompression);
147 }
148
149 this->printMsg(
150 "Total time", 1.0, tm_method.getElapsedTime(), threadNumber_);
151 }
152}
153
155 const std::vector<ttk::DiagramType> &intermediateDiagrams,
156 std::vector<ttk::DiagramType> &dictDiagrams,
157 std::vector<std::vector<double>> &vectorWeights,
158 const int numAtom,
159 std::vector<double> &lossTab,
160 std::vector<std::vector<double>> &allLosses,
161 std::vector<std::vector<double>> &histoVectorWeights,
162 std::vector<ttk::DiagramType> &histoDictDiagrams,
163 bool preWeightOpt,
164 double percent,
165 bool doCompression) {
166
167 Timer tm{};
168
169 bool doOptimizeAtoms = false;
170 bool doOptimizeWeights = false;
171
172 if(OptimizeWeights_) {
173 printMsg("Weight Optimization activated");
174 doOptimizeWeights = true;
175 } else {
176 printWrn("Weight Optimization desactivated");
177 }
178 if(OptimizeAtoms_) {
179 doOptimizeAtoms = true;
180 printMsg("Atom Optimization activated");
181 } else {
182 printWrn("Atom Optimization desactivated");
183 }
184
185 const auto nDiags = intermediateDiagrams.size();
186
187 // tracking the original indices
188 std::vector<ttk::DiagramType> inputDiagramsMin(nDiags);
189 std::vector<ttk::DiagramType> inputDiagramsSad(nDiags);
190 std::vector<ttk::DiagramType> inputDiagramsMax(nDiags);
191
192 std::vector<BidderDiagram> bidderDiagramsMin{};
193 std::vector<BidderDiagram> bidderDiagramsSad{};
194 std::vector<BidderDiagram> bidderDiagramsMax{};
195
196 std::vector<std::vector<size_t>> originIndexDatasMin(nDiags);
197 std::vector<std::vector<size_t>> originIndexDatasSad(nDiags);
198 std::vector<std::vector<size_t>> originIndexDatasMax(nDiags);
199
201 intermediateDiagrams, inputDiagramsMin, inputDiagramsSad, inputDiagramsMax,
202 bidderDiagramsMin, bidderDiagramsSad, bidderDiagramsMax,
203 originIndexDatasMin, originIndexDatasSad, originIndexDatasMax, true);
204
205 std::vector<ttk::DiagramType> barycentersList(nDiags);
206 std::vector<std::vector<std::vector<ttk::MatchingType>>> allMatchingsAtoms(
207 nDiags);
208 std::vector<std::vector<ttk::MatchingType>> matchingsDatasMin(nDiags);
209 std::vector<std::vector<ttk::MatchingType>> matchingsDatasSad(nDiags);
210 std::vector<std::vector<ttk::MatchingType>> matchingsDatasMax(nDiags);
212 double loss;
213 int lag = 0;
214 int lag2 = 0;
215 int lag3 = 0;
216 int lagLimit = 10;
217 int minEpoch = 20;
218 int maxEpoch = MaxEpoch_;
219 bool cond = true;
220 int epoch = 0;
221 int nbEpochPrevious = lossTab.size();
222 std::vector<size_t> initSizes(dictDiagrams.size());
223 for(size_t j = 0; j < dictDiagrams.size(); ++j) {
224 initSizes[j] = dictDiagrams[j].size();
225 }
226
227 double factEquiv = static_cast<double>(numAtom);
228 double step = 1. / (2. * 2. * factEquiv);
229 gradActor.setStep(factEquiv);
230
231 // BUFFERS
232 std::vector<std::vector<int>> bufferHistoAllEpochLife(dictDiagrams.size());
233 std::vector<std::vector<bool>> bufferHistoAllBoolLife(dictDiagrams.size());
234 std::vector<std::vector<bool>> bufferCheckUnderDiag(dictDiagrams.size());
235 std::vector<std::vector<bool>> bufferCheckDiag(dictDiagrams.size());
236 std::vector<std::vector<bool>> bufferCheckAboveGlobal(dictDiagrams.size());
237
238 std::vector<std::vector<int>> histoAllEpochLife(dictDiagrams.size());
239 std::vector<std::vector<bool>> histoAllBoolLife(dictDiagrams.size());
240 std::vector<std::vector<bool>> checkUnderDiag(dictDiagrams.size());
241 std::vector<std::vector<bool>> checkDiag(dictDiagrams.size());
242 std::vector<std::vector<bool>> checkAboveGlobal(dictDiagrams.size());
243
244 std::vector<double> allLossesAtEpoch(nDiags, 0.);
245 std::vector<double> trueAllLossesAtEpoch(nDiags, 0.);
246
247 while(epoch < maxEpoch && cond) {
248 loss = 0.;
249 Timer tm_it{};
250#ifdef TTK_ENABLE_OPENMP
251#pragma omp parallel for num_threads(threadNumber_)
252#endif // TTK_ENABLE_OPENMP
254 for(size_t i = 0; i < nDiags; ++i) {
255 auto &barycenter = barycentersList[i];
256 std::vector<double> &weight = vectorWeights[i];
257 std::vector<std::vector<ttk::MatchingType>> &matchings
258 = allMatchingsAtoms[i];
260 dictDiagrams, weight, barycenter, matchings, *this, ProgBarycenter_);
261 }
262 this->printMsg(
263 "Computed 1st Barycenters for epoch " + std::to_string(epoch),
264 epoch / static_cast<double>(maxEpoch), tm_it.getElapsedTime(),
266
267 // "====================BARYCENTER FINISHED======================");
268
269 // tracking the original indices
270 std::vector<ttk::DiagramType> barycentersListMin(nDiags);
271 std::vector<ttk::DiagramType> barycentersListSad(nDiags);
272 std::vector<ttk::DiagramType> barycentersListMax(nDiags);
273
274 std::vector<BidderDiagram> bidderBarycentersListMin{};
275 std::vector<BidderDiagram> bidderBarycentersListSad{};
276 std::vector<BidderDiagram> bidderBarycentersListMax{};
277
278 std::vector<std::vector<size_t>> originIndexBarysMin(nDiags);
279 std::vector<std::vector<size_t>> originIndexBarysSad(nDiags);
280 std::vector<std::vector<size_t>> originIndexBarysMax(nDiags);
281
283 barycentersList, nDiags, barycentersListMin, barycentersListSad,
284 barycentersListMax, bidderBarycentersListMin, bidderBarycentersListSad,
285 bidderBarycentersListMax, originIndexBarysMin, originIndexBarysSad,
286 originIndexBarysMax, bidderDiagramsMin, bidderDiagramsMax,
287 bidderDiagramsSad, matchingsDatasMin, matchingsDatasMax,
288 matchingsDatasSad, allLossesAtEpoch, true);
289
290 for(size_t p = 0; p < nDiags; ++p) {
291 loss += allLossesAtEpoch[p];
292 }
293
294 for(size_t p = 0; p < nDiags; ++p) {
295 if(!ProgApproach_) {
296 allLosses[p].push_back(allLossesAtEpoch[p]);
297 } else {
298 allLosses[p].push_back(trueAllLossesAtEpoch[p]);
299 }
300 }
301
302 lossTab.push_back(loss);
303
304 printMsg(
305 " Epoch " + std::to_string(epoch) + ", loss = " + std::to_string(loss), 1,
306 tm_it.getElapsedTime(), threadNumber_, ttk::debug::LineMode::REPLACE);
307
308 if(preWeightOpt && OptimizeAtoms_) {
309 if(epoch < 10) {
310 // Pre optimization of barycentric weights
311 doOptimizeAtoms = false;
312 } else {
313 doOptimizeAtoms = true;
314 }
315 }
316
317 if(loss < 1e-7) {
318 cond = false;
319 doOptimizeWeights = false;
320 doOptimizeAtoms = false;
321 }
322
323 double mini
324 = *std::min_element(lossTab.begin() + nbEpochPrevious, lossTab.end() - 1);
325 if(loss <= mini) {
326 for(size_t p = 0; p < dictDiagrams.size(); ++p) {
327 const auto &atom = dictDiagrams[p];
328 histoDictDiagrams[p] = atom;
329
330 const auto &histoEpochAtom = histoAllEpochLife[p];
331 const auto &histoBoolAtom = histoAllBoolLife[p];
332 const auto &boolUnderDiag = checkUnderDiag[p];
333 const auto &boolDiag = checkDiag[p];
334 const auto &boolAboveGlobal = checkAboveGlobal[p];
335
336 bufferHistoAllEpochLife[p] = histoEpochAtom;
337 bufferHistoAllBoolLife[p] = histoBoolAtom;
338 bufferCheckUnderDiag[p] = boolUnderDiag;
339 bufferCheckDiag[p] = boolDiag;
340 bufferCheckAboveGlobal[p] = boolAboveGlobal;
341 }
342 for(size_t p = 0; p < nDiags; ++p) {
343 const auto &weights = vectorWeights[p];
344 histoVectorWeights[p] = weights;
345 }
346 lag = 0;
347 lag3 = 0;
348 } else {
349 if(epoch > minEpoch) {
350 lag += 1;
351 } else {
352 lag = 0;
353 }
354 }
355
356 if((epoch > minEpoch)
357 && (lossTab[epoch + nbEpochPrevious]
358 / lossTab[epoch + nbEpochPrevious - 1]
359 > 0.99)) {
360 if(lossTab[epoch + nbEpochPrevious]
361 < lossTab[epoch + nbEpochPrevious - 1]) {
362 if(lag2 == this->MaxLag2_) {
363 this->printMsg("Loss not decreasing enough");
364 if(StopCondition_) {
365 for(size_t p = 0; p < dictDiagrams.size(); ++p) {
366 const auto &atom = histoDictDiagrams[p];
367 dictDiagrams[p] = atom;
368 }
369 for(size_t p = 0; p < nDiags; ++p) {
370 const auto &weights = histoVectorWeights[p];
371 vectorWeights[p] = weights;
372 }
373 doOptimizeWeights = false;
374 doOptimizeAtoms = false;
375 cond = false;
376 }
377 } else {
378 lag2 += 1;
379 }
380 }
381 } else {
382 lag2 = 0;
383 }
384
385 if(epoch > minEpoch && lag > lagLimit) {
386
387 if(StopCondition_) {
388 for(size_t p = 0; p < dictDiagrams.size(); ++p) {
389 const auto &atom = histoDictDiagrams[p];
390 dictDiagrams[p] = atom;
391 }
392 for(size_t p = 0; p < nDiags; ++p) {
393 const auto &weights = histoVectorWeights[p];
394 vectorWeights[p] = weights;
395 }
396 this->printMsg("Minimum not passed");
397 doOptimizeWeights = false;
398 doOptimizeAtoms = false;
399
400 cond = false;
401 }
402 }
403
404 if(cond && (epoch > 0) && (lossTab[epoch + nbEpochPrevious] > 2. * mini)) {
405 lag3 += 1;
406 lag2 = 0;
407
408 if(lag3 > 2) {
409 this->printMsg("Loss increasing too much, reducing step and recompute "
410 "Barycenters and matchings");
411 for(size_t p = 0; p < dictDiagrams.size(); ++p) {
412 const auto &atom = histoDictDiagrams[p];
413 dictDiagrams[p] = atom;
414
415 const auto &bufferHistoEpochAtom = bufferHistoAllEpochLife[p];
416 const auto &bufferHistoBoolAtom = bufferHistoAllBoolLife[p];
417 const auto &bufferBoolUnderDiag = bufferCheckUnderDiag[p];
418 const auto &bufferBoolDiag = bufferCheckDiag[p];
419 const auto &bufferBoolAboveGlobal = bufferCheckAboveGlobal[p];
420
421 histoAllEpochLife[p] = bufferHistoEpochAtom;
422 histoAllBoolLife[p] = bufferHistoBoolAtom;
423 checkUnderDiag[p] = bufferBoolUnderDiag;
424 checkDiag[p] = bufferBoolDiag;
425 checkAboveGlobal[p] = bufferBoolAboveGlobal;
426 }
427
428 for(size_t p = 0; p < nDiags; ++p) {
429 const auto &weights = histoVectorWeights[p];
430 vectorWeights[p] = weights;
431 }
432 gradActor.reduceStep();
433 step = step / 2.;
434 lag3 = 0;
435
436 barycentersList.clear();
437 barycentersList.resize(nDiags);
438 allMatchingsAtoms.clear();
439 allMatchingsAtoms.resize(nDiags);
440
441 barycentersListMin.clear();
442 barycentersListSad.clear();
443 barycentersListMax.clear();
444
445 barycentersListMin.resize(nDiags);
446 barycentersListSad.resize(nDiags);
447 barycentersListMax.resize(nDiags);
448
449 bidderBarycentersListMin.clear();
450 bidderBarycentersListSad.clear();
451 bidderBarycentersListMax.clear();
452
453 originIndexBarysMin.clear();
454 originIndexBarysSad.clear();
455 originIndexBarysMax.clear();
456
457 originIndexBarysMin.resize(nDiags);
458 originIndexBarysSad.resize(nDiags);
459 originIndexBarysMax.resize(nDiags);
460
461 matchingsDatasMin.clear();
462 matchingsDatasSad.clear();
463 matchingsDatasMax.clear();
464
465 matchingsDatasMin.resize(nDiags);
466 matchingsDatasSad.resize(nDiags);
467 matchingsDatasMax.resize(nDiags);
468
469#ifdef TTK_ENABLE_OPENMP
470#pragma omp parallel for num_threads(threadNumber_)
471#endif // TTK_ENABLE_OPENMP
473 for(size_t i = 0; i < nDiags; ++i) {
474 auto &barycenter = barycentersList[i];
475 std::vector<double> &weight = vectorWeights[i];
476 std::vector<std::vector<ttk::MatchingType>> &matchings
477 = allMatchingsAtoms[i];
478 computeWeightedBarycenter(dictDiagrams, weight, barycenter, matchings,
479 *this, ProgBarycenter_);
480 }
481
483 barycentersList, nDiags, barycentersListMin, barycentersListSad,
484 barycentersListMax, bidderBarycentersListMin,
485 bidderBarycentersListSad, bidderBarycentersListMax,
486 originIndexBarysMin, originIndexBarysSad, originIndexBarysMax,
487 bidderDiagramsMin, bidderDiagramsMax, bidderDiagramsSad,
488 matchingsDatasMin, matchingsDatasMax, matchingsDatasSad,
489 allLossesAtEpoch, false);
490 }
491 }
492
493 std::vector<std::vector<Matrix>> allHessianLists(nDiags);
494 std::vector<std::vector<double>> gradWeightsList(nDiags);
495 Timer tm_opt1{};
496
497 // WEIGHT OPTIMIZATION
498 if(doOptimizeWeights) {
499#ifdef TTK_ENABLE_OPENMP
500#pragma omp parallel for num_threads(threadNumber_)
501#endif // TTK_ENABLE_OPENMP
502 for(size_t i = 0; i < nDiags; ++i) {
503 auto &gradWeights = gradWeightsList[i];
504 const auto &matchingsAtoms = allMatchingsAtoms[i];
505 const auto &Barycenter = barycentersList[i];
506 const auto &Data = intermediateDiagrams[i];
507 std::vector<Matrix> &hessianList = allHessianLists[i];
508 const std::vector<ttk::MatchingType> &matchingsMin
509 = matchingsDatasMin[i];
510 const std::vector<ttk::MatchingType> &matchingsMax
511 = matchingsDatasMax[i];
512 const std::vector<ttk::MatchingType> &matchingsSad
513 = matchingsDatasSad[i];
514 const std::vector<size_t> &indexBaryMin = originIndexBarysMin[i];
515 const std::vector<size_t> &indexBarySad = originIndexBarysSad[i];
516 const std::vector<size_t> &indexBaryMax = originIndexBarysMax[i];
517 const std::vector<size_t> &indexDataMin = originIndexDatasMin[i];
518 const std::vector<size_t> &indexDataSad = originIndexDatasSad[i];
519 const std::vector<size_t> &indexDataMax = originIndexDatasMax[i];
520 std::vector<double> &weights = vectorWeights[i];
521 computeGradientWeights(gradWeights, hessianList, dictDiagrams,
522 matchingsAtoms, Barycenter, Data, matchingsMin,
523 matchingsMax, matchingsSad, indexBaryMin,
524 indexBaryMax, indexBarySad, indexDataMin,
525 indexDataMax, indexDataSad, doOptimizeAtoms);
526 gradActor.executeWeightsProjected(
527 hessianList, weights, gradWeights, MaxEigenValue_);
528 }
529
530 this->printMsg("Computed 1st opt for epoch " + std::to_string(epoch),
531 epoch / static_cast<double>(maxEpoch),
532 tm_opt1.getElapsedTime(), threadNumber_,
534 }
535
536 for(size_t p = 0; p < nDiags; ++p) {
537 allLossesAtEpoch[p] = 0.;
538 trueAllLossesAtEpoch[p] = 0.;
539 }
540 barycentersList.clear();
541 barycentersList.resize(nDiags);
542 allMatchingsAtoms.clear();
543 allMatchingsAtoms.resize(nDiags);
545 if(doOptimizeAtoms) {
546 Timer tm_it2{};
547#ifdef TTK_ENABLE_OPENMP
548#pragma omp parallel for num_threads(threadNumber_)
549#endif // TTK_ENABLE_OPENMP
550 for(size_t i = 0; i < nDiags; ++i) {
551 auto &barycenter = barycentersList[i];
552 std::vector<double> &weight = vectorWeights[i];
553 std::vector<std::vector<ttk::MatchingType>> &matchings
554 = allMatchingsAtoms[i];
556 dictDiagrams, weight, barycenter, matchings, *this, ProgBarycenter_);
557 }
558 this->printMsg(
559 "Computed 2nd Barycenters for epoch " + std::to_string(epoch),
560 epoch / static_cast<double>(maxEpoch), tm_it2.getElapsedTime(),
562
563 barycentersListMin.clear();
564 barycentersListSad.clear();
565 barycentersListMax.clear();
566
567 barycentersListMin.resize(nDiags);
568 barycentersListSad.resize(nDiags);
569 barycentersListMax.resize(nDiags);
570
571 bidderBarycentersListMin.clear();
572 bidderBarycentersListSad.clear();
573 bidderBarycentersListMax.clear();
574
575 originIndexBarysMin.clear();
576 originIndexBarysSad.clear();
577 originIndexBarysMax.clear();
578
579 originIndexBarysMin.resize(nDiags);
580 originIndexBarysSad.resize(nDiags);
581 originIndexBarysMax.resize(nDiags);
582
583 matchingsDatasMin.clear();
584 matchingsDatasSad.clear();
585 matchingsDatasMax.clear();
586
587 matchingsDatasMin.resize(nDiags);
588 matchingsDatasSad.resize(nDiags);
589 matchingsDatasMax.resize(nDiags);
590
591 computeAllDistances(
592 barycentersList, nDiags, barycentersListMin, barycentersListSad,
593 barycentersListMax, bidderBarycentersListMin, bidderBarycentersListSad,
594 bidderBarycentersListMax, originIndexBarysMin, originIndexBarysSad,
595 originIndexBarysMax, bidderDiagramsMin, bidderDiagramsMax,
596 bidderDiagramsSad, matchingsDatasMin, matchingsDatasMax,
597 matchingsDatasSad, allLossesAtEpoch, false);
598
599 std::vector<std::vector<std::vector<std::array<double, 2>>>>
600 allPairToAddToGradList(nDiags);
601 std::vector<ttk::DiagramType> allInfoToAdd(nDiags);
602 std::vector<std::vector<Matrix>> gradsAtomsList(nDiags);
603 std::vector<std::vector<int>> checkerAtomsList(nDiags);
604
605 bool doDimReduct = false;
606 if(DimReductMode_ && numAtom <= 3) {
607 doDimReduct = true;
608 } else {
609 doDimReduct = false;
610 }
611
612 Timer tm_opt2{};
613#ifdef TTK_ENABLE_OPENMP
614#pragma omp parallel for num_threads(threadNumber_)
615#endif // TTK_ENABLE_OPENMP
616 for(size_t i = 0; i < nDiags; ++i) {
617 auto &pairToAddGradList = allPairToAddToGradList[i];
618 auto &infoToAdd = allInfoToAdd[i];
619 auto &gradsAtoms = gradsAtomsList[i];
620 auto &checkerAtoms = checkerAtomsList[i];
621 const auto &Barycenter = barycentersList[i];
622 const auto &Data = intermediateDiagrams[i];
623 const std::vector<ttk::MatchingType> &matchingsMin
624 = matchingsDatasMin[i];
625 const std::vector<ttk::MatchingType> &matchingsMax
626 = matchingsDatasMax[i];
627 const std::vector<ttk::MatchingType> &matchingsSad
628 = matchingsDatasSad[i];
629 const std::vector<size_t> &indexBaryMin = originIndexBarysMin[i];
630 const std::vector<size_t> &indexBarySad = originIndexBarysSad[i];
631 const std::vector<size_t> &indexBaryMax = originIndexBarysMax[i];
632 const std::vector<size_t> &indexDataMin = originIndexDatasMin[i];
633 const std::vector<size_t> &indexDataSad = originIndexDatasSad[i];
634 const std::vector<size_t> &indexDataMax = originIndexDatasMax[i];
635 const std::vector<double> &weights = vectorWeights[i];
636 computeGradientAtoms(
637 gradsAtoms, weights, Barycenter, Data, matchingsMin, matchingsMax,
638 matchingsSad, indexBaryMin, indexBaryMax, indexBarySad, indexDataMin,
639 indexDataMax, indexDataSad, checkerAtoms, pairToAddGradList,
640 infoToAdd, doDimReduct);
641 }
642
643 std::vector<double> maxiDeath(numAtom);
644 std::vector<double> minBirth(numAtom);
645 for(int j = 0; j < numAtom; ++j) {
646 auto &atom = dictDiagrams[j];
647 auto &temp = atom[0];
648 maxiDeath[j] = temp.death.sfValue;
649 minBirth[j] = temp.birth.sfValue;
650 }
651
652 std::vector<std::vector<std::vector<int>>> allProjectionsList(nDiags);
653 std::vector<ttk::DiagramType> allFeaturesToAdd(nDiags);
654 std::vector<std::vector<std::array<double, 2>>> allProjLocations(nDiags);
655 std::vector<std::vector<std::vector<double>>>
656 allVectorForProjContributions(nDiags);
657 std::vector<ttk::DiagramType> allTrueFeaturesToAdd(numAtom);
658 std::vector<std::vector<std::vector<int>>> allTrueProj(numAtom);
659 std::vector<std::vector<std::array<double, 2>>> allTrueProjLoc(numAtom);
660
661 for(size_t i = 0; i < nDiags; ++i) {
662 auto &pairToAddGradList = allPairToAddToGradList[i];
663 auto &infoToAdd = allInfoToAdd[i];
664 auto &projForDiag = allProjectionsList[i];
665 auto &vectorForProjContrib = allVectorForProjContributions[i];
666 auto &featuresToAdd = allFeaturesToAdd[i];
667 auto &projLocations = allProjLocations[i];
668 auto &gradsAtoms = gradsAtomsList[i];
669 const auto &matchingsAtoms = allMatchingsAtoms[i];
670 const auto &Barycenter = barycentersList[i];
671 const auto &checkerAtoms = checkerAtomsList[i];
672 gradActor.executeAtoms(
673 dictDiagrams, matchingsAtoms, Barycenter, gradsAtoms, checkerAtoms,
674 projForDiag, featuresToAdd, projLocations, vectorForProjContrib,
675 pairToAddGradList, infoToAdd);
676 }
677
678 if(CreationFeatures_) {
679 for(size_t i = 0; i < nDiags; ++i) {
680 auto &projForDiag = allProjectionsList[i];
681 auto &featuresToAdd = allFeaturesToAdd[i];
682 auto &projLocations = allProjLocations[i];
683 auto &vectorForProjContrib = allVectorForProjContributions[i];
684 for(size_t j = 0; j < projForDiag.size(); ++j) {
685 auto &t = featuresToAdd[j];
686 std::array<double, 2> &pair = projLocations[j];
687 std::vector<double> &vectorContrib = vectorForProjContrib[j];
688 std::vector<int> &projAndIndex = projForDiag[j];
689 std::vector<int> proj(numAtom);
690 for(int m = 0; m < numAtom; ++m) {
691 proj[m] = projAndIndex[m];
692 }
693 int atomIndex = static_cast<int>(projAndIndex[numAtom]);
694 bool lenNull = allTrueProj[atomIndex].size() == 0;
695 if(lenNull) {
696 const CriticalType c1 = t.birth.type;
697 const CriticalType c2 = t.death.type;
698 const SimplexId idTemp = t.dim;
699 pair[0] = pair[0] - step * vectorContrib[0];
700 pair[1] = pair[1] - step * vectorContrib[1];
701 if(pair[0] > pair[1]) {
702 pair[1] = pair[0];
703 }
704 if(pair[0] < minBirth[atomIndex]) {
705 continue;
706 }
707 if(pair[1] - pair[0] < 1e-7) {
708 continue;
709 }
710
711 PersistencePair newPair{CriticalVertex{0, pair[0], 0, {}, c1},
712 CriticalVertex{0, pair[1], 0, {}, c2},
713 idTemp, true};
714 allTrueProj[atomIndex].push_back(proj);
715 allTrueFeaturesToAdd[atomIndex].push_back(newPair);
716 allTrueProjLoc[atomIndex].push_back(pair);
717 } else {
718 bool ralph = true;
719 size_t index = 0;
720 if(ralph) {
721 const CriticalType c1 = t.birth.type;
722 const CriticalType c2 = t.death.type;
723 const SimplexId idTemp = t.dim;
724 pair[0] = pair[0] - step * vectorContrib[0];
725 pair[1] = pair[1] - step * vectorContrib[1];
726 if(pair[0] > pair[1]) {
727 pair[1] = pair[0];
728 }
729 if(pair[0] < minBirth[atomIndex]) {
730 continue;
731 }
732 if(pair[1] - pair[0] < 1e-7) {
733 continue;
734 }
735
736 PersistencePair newPair{CriticalVertex{0, pair[0], 0, {}, c1},
737 CriticalVertex{0, pair[0], 0, {}, c2},
738 idTemp, true};
739 allTrueProj[atomIndex].push_back(proj);
740 allTrueFeaturesToAdd[atomIndex].push_back(newPair);
741 allTrueProjLoc[atomIndex].push_back(pair);
742
743 } else {
744 auto &tReal = allTrueFeaturesToAdd[atomIndex][index];
745 tReal.birth.sfValue
746 = tReal.birth.sfValue - step * vectorContrib[0];
747 tReal.death.sfValue
748 = tReal.death.sfValue - step * vectorContrib[1];
749 if(tReal.birth.sfValue > tReal.death.sfValue) {
750 tReal.death.sfValue = tReal.birth.sfValue;
751 }
752 }
753 }
754 }
755 }
756
757 if(!doCompression) {
758 for(int i = 0; i < numAtom; ++i) {
759 auto &atom = dictDiagrams[i];
760 auto &histoEpochAtom = histoAllEpochLife[i];
761 auto &histoBoolAtom = histoAllBoolLife[i];
762 auto &boolUnderDiag = checkUnderDiag[i];
763 auto &boolDiag = checkDiag[i];
764 auto initSize = initSizes[i];
765 auto &boolAboveGlobal = checkAboveGlobal[i];
766 if(histoEpochAtom.size() > 0) {
767 for(size_t j = 0; j < histoEpochAtom.size(); ++j) {
768 auto &t = atom[initSize + j];
769 histoEpochAtom[j] += 1;
770 histoBoolAtom[j] = t.death.sfValue - t.birth.sfValue
771 < 0.1 * (percent / 100.) * maxiDeath[i];
772 boolDiag[j] = t.death.sfValue - t.birth.sfValue < 1e-6;
773 boolUnderDiag[j] = t.death.sfValue < t.birth.sfValue;
774 boolAboveGlobal[j] = t.birth.sfValue > maxiDeath[i];
775 }
776 }
777 }
778
779 for(int i = 0; i < numAtom; ++i) {
780 auto &atom = dictDiagrams[i];
781 auto &histoEpochAtom = histoAllEpochLife[i];
782 auto &histoBoolAtom = histoAllBoolLife[i];
783 auto &boolUnderDiag = checkUnderDiag[i];
784 auto &boolDiag = checkDiag[i];
785 auto &trueFeaturesToAdd = allTrueFeaturesToAdd[i];
786 auto &boolAboveGlobal = checkAboveGlobal[i];
787 for(size_t j = 0; j < trueFeaturesToAdd.size(); ++j) {
788 auto &t = trueFeaturesToAdd[j];
789 atom.push_back(t);
790 histoEpochAtom.push_back(0);
791 histoBoolAtom.push_back(t.death.sfValue - t.birth.sfValue
792 < 0.1 * (percent / 100.) * maxiDeath[i]);
793 boolDiag.push_back(t.death.sfValue - t.birth.sfValue < 1e-6);
794 boolUnderDiag.push_back(t.death.sfValue < t.birth.sfValue);
795 boolAboveGlobal.push_back(t.birth.sfValue > maxiDeath[i]);
796 }
797 }
798
799 std::vector<std::vector<size_t>> allIndicesToDelete(numAtom);
800 for(int i = 0; i < numAtom; ++i) {
801 auto &indicesAtomToDelete = allIndicesToDelete[i];
802 auto &histoEpochAtom = histoAllEpochLife[i];
803 auto &histoBoolAtom = histoAllBoolLife[i];
804 auto &boolUnderDiag = checkUnderDiag[i];
805 auto &boolDiag = checkDiag[i];
806 auto &boolAboveGlobal = checkAboveGlobal[i];
807 for(size_t j = 0; j < histoEpochAtom.size(); ++j) {
808 if(boolUnderDiag[j] || boolDiag[j] || boolAboveGlobal[j]
809 || (histoEpochAtom[j] > 5 && histoBoolAtom[j])) {
810 indicesAtomToDelete.push_back(j);
811 }
812 }
813 }
814
815 for(int i = 0; i < numAtom; ++i) {
816 auto &atom = dictDiagrams[i];
817 auto &histoEpochAtom = histoAllEpochLife[i];
818 auto &histoBoolAtom = histoAllBoolLife[i];
819 auto &indicesAtomToDelete = allIndicesToDelete[i];
820 auto &boolUnderDiag = checkUnderDiag[i];
821 auto &boolDiag = checkDiag[i];
822 auto &boolAboveGlobal = checkAboveGlobal[i];
823 auto initSize = initSizes[i];
824 if(static_cast<int>(indicesAtomToDelete.size()) > 0) {
825 for(int j = static_cast<int>(indicesAtomToDelete.size()) - 1;
826 j >= 0; j--) {
827 atom.erase(atom.begin() + initSize + indicesAtomToDelete[j]);
828 histoEpochAtom.erase(histoEpochAtom.begin()
829 + indicesAtomToDelete[j]);
830 histoBoolAtom.erase(histoBoolAtom.begin()
831 + indicesAtomToDelete[j]);
832 boolUnderDiag.erase(boolUnderDiag.begin()
833 + indicesAtomToDelete[j]);
834 boolDiag.erase(boolDiag.begin() + indicesAtomToDelete[j]);
835 boolAboveGlobal.erase(boolAboveGlobal.begin()
836 + indicesAtomToDelete[j]);
837 }
838 } else {
839 continue;
840 }
841 }
842 } else {
843 for(int i = 0; i < numAtom; ++i) {
844 auto &atom = dictDiagrams[i];
845 auto &trueFeaturesToAdd = allTrueFeaturesToAdd[i];
846 for(size_t j = 0; j < trueFeaturesToAdd.size(); ++j) {
847 auto &t = trueFeaturesToAdd[j];
848 atom.push_back(t);
849 }
850 }
851 controlAtomsSize(intermediateDiagrams, dictDiagrams);
852 }
853 } else {
854 if(doCompression) {
855 if(epoch > -1) {
856 controlAtomsSize(intermediateDiagrams, dictDiagrams);
857 }
858 }
859 }
860 // Ensuring to stay in the space of persistence diagrams:
861 for(int i = 0; i < numAtom; ++i) {
862 auto &atom = dictDiagrams[i];
863 auto &globalPair = atom[0];
864 for(size_t j = 0; j < atom.size(); ++j) {
865 auto &t = atom[j];
866
867 if(t.death.sfValue > globalPair.death.sfValue) {
868 t.death.sfValue = globalPair.death.sfValue;
869 }
870
871 if(t.birth.sfValue > t.death.sfValue) {
872 t.death.sfValue = t.birth.sfValue;
873 }
874
875 if(t.birth.sfValue < globalPair.birth.sfValue) {
876 t.birth.sfValue = globalPair.birth.sfValue;
877 }
878 }
879 }
880 this->printMsg("Computed 2nd opt for epoch " + std::to_string(epoch),
881 epoch / static_cast<double>(maxEpoch),
882 tm_opt2.getElapsedTime(), threadNumber_,
884
885 // ATOM OPTIMIZATION
886 }
887 epoch += 1;
888 barycentersList.clear();
889 barycentersList.resize(nDiags);
890 allMatchingsAtoms.clear();
891 allMatchingsAtoms.resize(nDiags);
892 }
893 printMsg(
894 " Epoch " + std::to_string(epoch) + ", loss = " + std::to_string(loss), 1.0,
895 tm.getElapsedTime(), threadNumber_);
896
897 printMsg(
898 "Loss returned "
899 + std::to_string(
900 *std::min_element(lossTab.begin() + nbEpochPrevious, lossTab.end()))
901 + " at Epoch "
902 + std::to_string(
903 std::min_element(lossTab.begin() + nbEpochPrevious, lossTab.end())
904 - lossTab.begin()),
905 1.0, tm.getElapsedTime(), threadNumber_);
906
907 for(size_t p = 0; p < dictDiagrams.size(); ++p) {
908 const auto &atom = histoDictDiagrams[p];
909 dictDiagrams[p] = atom;
910 }
911 for(size_t p = 0; p < nDiags; ++p) {
912 const auto &weights = histoVectorWeights[p];
913 vectorWeights[p] = weights;
914 }
915
916 this->printMsg("Complete", 1.0, tm.getElapsedTime(), this->threadNumber_);
917}
918
920 const std::vector<double> &vec1, const std::vector<double> &vec2) const {
921
922 double dist = 0.;
923 for(size_t i = 0; i < vec1.size(); ++i) {
924 dist = dist + (vec1[i] - vec2[i]) * (vec1[i] - vec2[i]);
925 }
926 return std::sqrt(dist);
927}
928
930 const std::vector<BidderDiagram> &bidder_diags) const {
931
932 double max_persistence = 0;
933
934 for(unsigned int i = 0; i < bidder_diags.size(); ++i) {
935 for(size_t j = 0; j < bidder_diags[i].size(); ++j) {
936 const double persistence = bidder_diags[i].at(j).getPersistence();
937 if(persistence > max_persistence) {
938 max_persistence = persistence;
939 }
940 }
941 }
942
943 return max_persistence;
944}
945
947 const BidderDiagram &D1,
948 const BidderDiagram &D2,
949 std::vector<ttk::MatchingType> &matching) const {
950
951 GoodDiagram D2_bis{};
952 for(size_t i = 0; i < D2.size(); i++) {
953 const Bidder &b = D2.at(i);
954 Good g(b.x_, b.y_, b.isDiagonal(), D2_bis.size());
956 g.setPrice(0);
957 D2_bis.emplace_back(g);
958 }
959
960 PersistenceDiagramAuction auction(this->Wasserstein, 1.0, 1.0, 0.01, true);
961 auction.BuildAuctionDiagrams(D1, D2_bis);
962 double loss = auction.run(matching);
963 return loss;
964}
965
967 std::vector<double> &gradWeights,
968 std::vector<Matrix> &hessianList,
969 const std::vector<ttk::DiagramType> &dictDiagrams,
970 const std::vector<std::vector<ttk::MatchingType>> &matchingsAtoms,
971 const ttk::DiagramType &Barycenter,
972 const ttk::DiagramType &newData,
973 const std::vector<ttk::MatchingType> &matchingsMin,
974 const std::vector<ttk::MatchingType> &matchingsMax,
975 const std::vector<ttk::MatchingType> &matchingsSad,
976 const std::vector<size_t> &indexBaryMin,
977 const std::vector<size_t> &indexBaryMax,
978 const std::vector<size_t> &indexBarySad,
979 const std::vector<size_t> &indexDataMin,
980 const std::vector<size_t> &indexDataMax,
981 const std::vector<size_t> &indexDataSad,
982 const bool doOptimizeAtoms) const {
983
984 // initialization
985 std::vector<std::vector<std::array<double, 2>>> gradBuffersList(
986 Barycenter.size());
987 std::vector<std::vector<std::array<double, 2>>> pairToAddGradList;
988 for(size_t i = 0; i < gradBuffersList.size(); ++i) {
989 gradBuffersList[i].resize(matchingsAtoms.size());
990 }
991 std::vector<std::array<double, 2>> directions(Barycenter.size());
992 std::vector<std::array<double, 2>> dataAssigned(Barycenter.size());
993 gradWeights.resize(dictDiagrams.size());
994 for(size_t i = 0; i < dictDiagrams.size(); ++i) {
995 gradWeights[i] = 0.;
996 }
997
998 std::vector<std::vector<int>> checker(Barycenter.size());
999 for(size_t j = 0; j < Barycenter.size(); ++j) {
1000 checker[j].resize(matchingsAtoms.size());
1001 }
1002 std::vector<int> tracker(Barycenter.size(), 0);
1003 std::vector<int> tracker2(Barycenter.size(), 0);
1004
1005 // computing gradients
1006 for(size_t i = 0; i < matchingsAtoms.size(); ++i) {
1007 for(size_t j = 0; j < matchingsAtoms[i].size(); ++j) {
1008 const ttk::MatchingType &t = matchingsAtoms[i][j];
1009 // Id in atom
1010 const SimplexId Id1 = std::get<0>(t);
1011 // Id in barycenter
1012 const SimplexId Id2 = std::get<1>(t);
1013 if(Id2 < 0 || static_cast<int>(gradBuffersList.size()) <= Id2
1014 || static_cast<int>(dictDiagrams[i].size()) <= Id1) {
1015 continue;
1016 } else if(Id1 < 0) {
1017 const PersistencePair &t3 = Barycenter[Id2];
1018 auto &point = gradBuffersList[Id2][i];
1019 const double birthBarycenter = t3.birth.sfValue;
1020 const double deathBarycenter = t3.death.sfValue;
1021 const double birth_death_atom
1022 = birthBarycenter + (deathBarycenter - birthBarycenter) / 2.;
1023 point[0] = birth_death_atom;
1024 point[1] = birth_death_atom;
1025 checker[Id2][i] = i;
1026 tracker[Id2] = 1;
1027 } else {
1028 const PersistencePair &t2 = dictDiagrams[i][Id1];
1029 auto &point = gradBuffersList[Id2][i];
1030 const double birth_atom = t2.birth.sfValue;
1031 const double death_atom = t2.death.sfValue;
1032 point[0] = birth_atom;
1033 point[1] = death_atom;
1034 checker[Id2][i] = i;
1035 tracker[Id2] = 1;
1036 }
1037 }
1038 }
1039
1040 // Compute directions for min diagram
1041 computeDirectionsGradWeight(matchingsAtoms, Barycenter, newData, matchingsMin,
1042 indexBaryMin, indexDataMin, pairToAddGradList,
1043 directions, dataAssigned, tracker2,
1044 doOptimizeAtoms);
1045
1046 // Compute directions for max diagram
1047 computeDirectionsGradWeight(matchingsAtoms, Barycenter, newData, matchingsMax,
1048 indexBaryMax, indexDataMax, pairToAddGradList,
1049 directions, dataAssigned, tracker2,
1050 doOptimizeAtoms);
1051
1052 // Compute directions for saddle diagram
1053 computeDirectionsGradWeight(matchingsAtoms, Barycenter, newData, matchingsSad,
1054 indexBarySad, indexDataSad, pairToAddGradList,
1055 directions, dataAssigned, tracker2,
1056 doOptimizeAtoms);
1057
1058 std::vector<int> temp(pairToAddGradList.size(), 1);
1059 gradBuffersList.insert(
1060 gradBuffersList.end(), pairToAddGradList.begin(), pairToAddGradList.end());
1061 tracker2.insert(tracker2.end(), temp.begin(), temp.end());
1062 tracker.insert(tracker.end(), temp.begin(), temp.end());
1063 std::vector<int> temp2(matchingsAtoms.size());
1064 for(size_t j = 0; j < matchingsAtoms.size(); ++j) {
1065 temp2.push_back(static_cast<int>(j));
1066 }
1067 for(size_t j = 0; j < pairToAddGradList.size(); ++j) {
1068 checker.push_back(temp2);
1069 }
1070
1071 for(size_t i = 0; i < gradBuffersList.size(); ++i) {
1072 const auto &data_point = dataAssigned[i];
1073 for(size_t j = 0; j < checker[i].size(); ++j) {
1074 auto &point = gradBuffersList[i][checker[i][j]];
1075 point[0] -= data_point[0];
1076 point[1] -= data_point[1];
1077 }
1078 }
1079
1080 for(size_t i = 0; i < gradBuffersList.size(); ++i) {
1081 if(tracker[i] == 0 || tracker2[i] == 0) {
1082 continue;
1083 } else {
1084 for(size_t j = 0; j < checker[i].size(); ++j) {
1085 const auto &point = gradBuffersList[i][checker[i][j]];
1086 const auto &direction = directions[i];
1087 gradWeights[checker[i][j]]
1088 += -2 * (point[0] * direction[0] + point[1] * direction[1]);
1089 }
1090 }
1091 }
1092 hessianList.resize(gradBuffersList.size());
1093 for(size_t i = 0; i < gradBuffersList.size(); ++i) {
1094 Matrix &hessian = hessianList[i];
1095 hessian.resize(checker[i].size());
1096 for(size_t j = 0; j < checker[i].size(); ++j) {
1097 auto &line = hessian[j];
1098 line.resize(checker[i].size());
1099 const auto &point = gradBuffersList[i][checker[i][j]];
1100 for(size_t q = 0; q < checker[i].size(); ++q) {
1101 const auto &point_temp = gradBuffersList[i][checker[i][q]];
1102 line[q] = point[0] * point_temp[0] + point[1] * point_temp[1];
1103 }
1104 }
1105 }
1106}
1107
1109 std::vector<Matrix> &gradsAtoms,
1110 const std::vector<double> &weights,
1111 const ttk::DiagramType &Barycenter,
1112 const ttk::DiagramType &newData,
1113 const std::vector<ttk::MatchingType> &matchingsMin,
1114 const std::vector<ttk::MatchingType> &matchingsMax,
1115 const std::vector<ttk::MatchingType> &matchingsSad,
1116 const std::vector<size_t> &indexBaryMin,
1117 const std::vector<size_t> &indexBaryMax,
1118 const std::vector<size_t> &indexBarySad,
1119 const std::vector<size_t> &indexDataMin,
1120 const std::vector<size_t> &indexDataMax,
1121 const std::vector<size_t> &indexDataSad,
1122 std::vector<int> &checker,
1123 std::vector<std::vector<std::array<double, 2>>> &pairToAddGradList,
1124 std::vector<PersistencePair> &infoToAdd,
1125 bool doDimReduct) const {
1126
1127 gradsAtoms.resize(Barycenter.size());
1128 for(size_t i = 0; i < Barycenter.size(); ++i) {
1129 gradsAtoms[i].resize(weights.size());
1130 }
1131
1132 checker.resize(Barycenter.size());
1133 for(size_t i = 0; i < Barycenter.size(); ++i) {
1134 checker[i] = 0;
1135 }
1136 std::vector<std::vector<double>> directions(Barycenter.size());
1137
1138 // Compute directions for min diagram
1139 computeDirectionsGradAtoms(gradsAtoms, Barycenter, weights, newData,
1140 matchingsMin, indexBaryMin, indexDataMin,
1141 pairToAddGradList, directions, checker, infoToAdd,
1142 doDimReduct);
1143
1144 // Compute directions for max diagram
1145 computeDirectionsGradAtoms(gradsAtoms, Barycenter, weights, newData,
1146 matchingsMax, indexBaryMax, indexDataMax,
1147 pairToAddGradList, directions, checker, infoToAdd,
1148 doDimReduct);
1149
1150 // Compute directions for saddle diagram
1151 computeDirectionsGradAtoms(gradsAtoms, Barycenter, weights, newData,
1152 matchingsSad, indexBarySad, indexDataSad,
1153 pairToAddGradList, directions, checker, infoToAdd,
1154 doDimReduct);
1155
1156 for(size_t i = 0; i < Barycenter.size(); ++i) {
1157 if(checker[i] == 0) {
1158 continue;
1159 } else {
1160 for(size_t j = 0; j < weights.size(); ++j) {
1161 std::vector<double> temp(2);
1162 const std::vector<double> &direction = directions[i];
1163 temp[0] = -2 * weights[j] * direction[0];
1164 temp[1] = -2 * weights[j] * direction[1];
1165 gradsAtoms[i][j] = temp;
1166 }
1167 }
1168 }
1169}
1170
1172 const size_t nInputs,
1173 std::vector<ttk::DiagramType> &inputDiagrams,
1174 std::vector<BidderDiagram> &bidder_diags) const {
1175
1176 bidder_diags.resize(nInputs);
1177
1178#ifdef TTK_ENABLE_OPENMP
1179#pragma omp parallel for num_threads(threadNumber_)
1180#endif // TTK_ENABLE_OPENMP
1181 for(size_t i = 0; i < nInputs; i++) {
1182 auto &diag = inputDiagrams[i];
1183 auto &bidders = bidder_diags[i];
1184
1185 for(size_t j = 0; j < diag.size(); j++) {
1186 // Add bidder to bidders
1187 Bidder b(diag[j], j, 1.0);
1188 b.setPositionInAuction(bidders.size());
1189 bidders.emplace_back(b);
1190 if(b.isDiagonal() || b.x_ == b.y_) {
1191 this->printMsg("Diagonal point in diagram " + std::to_string(i) + "!",
1193 }
1194 }
1195 }
1196}
1197
1199 std::vector<ttk::DiagramType> &dictDiagrams,
1200 const std::vector<ttk::DiagramType> &datas,
1201 const std::vector<ttk::DiagramType> &inputAtoms,
1202 const int &nbAtom,
1203 bool &do_min,
1204 bool &do_sad,
1205 bool &do_max,
1206 int seed,
1207 double &percent) {
1208 switch(this->BackEnd) {
1209 case BACKEND::INPUT_ATOMS: {
1210 if(static_cast<int>(inputAtoms.size()) != nbAtom) {
1211 printErr("number of atoms don't match, going with "
1212 + std::to_string(inputAtoms.size()) + " atoms");
1213 }
1214 for(size_t i = 0; i < inputAtoms.size(); i++) {
1215 const auto &t = inputAtoms[i];
1216 double maxPers = getMaxPers(t);
1217
1218 dictDiagrams.push_back(t);
1219 dictDiagrams[i].erase(
1220 std::remove_if(dictDiagrams[i].begin(), dictDiagrams[i].end(),
1221 [maxPers](ttk::PersistencePair &p) {
1222 return (p.death.sfValue - p.birth.sfValue)
1223 < 0. * maxPers;
1224 }),
1225 dictDiagrams[i].end());
1226 }
1227 break;
1228 }
1229
1230 case BACKEND::BORDER_INIT: {
1232 initializer.setThreadNumber(this->threadNumber_);
1233 initializer.execute(dictDiagrams, datas, nbAtom, do_min, do_sad, do_max);
1234 break;
1235 }
1236
1238 ttk::InitRandomDict{}.execute(dictDiagrams, datas, nbAtom, seed); // TODO
1239 break;
1240
1241 case BACKEND::FIRST_DIAGS: {
1242 for(int i = 0; i < nbAtom; ++i) {
1243 const auto &t = datas[i];
1244 dictDiagrams.push_back(t);
1245 }
1246 break;
1247 }
1248 case BACKEND::GREEDY_INIT: {
1249 dictDiagrams.resize(datas.size());
1250 for(size_t i = 0; i < datas.size(); ++i) {
1251 dictDiagrams[i] = datas[i];
1252 }
1253 while(static_cast<int>(dictDiagrams.size()) != nbAtom) {
1254 std::vector<double> allEnergy(dictDiagrams.size());
1255
1256#ifdef TTK_ENABLE_OPENMP
1257#pragma omp parallel for num_threads(threadNumber_)
1258#endif // TTK_ENABLE_OPENMP
1259 for(size_t j = 0; j < dictDiagrams.size(); ++j) {
1260 std::vector<ttk::DiagramType> dictTemp;
1261 std::vector<ttk::DiagramType> dataAlone;
1262 std::vector<double> lossTabTemp;
1263 std::vector<std::vector<double>> allLossesTemp(1);
1264
1265 for(size_t p = 0; p < dictDiagrams.size(); ++p) {
1266 if(p != j) {
1267 dictTemp.push_back(dictDiagrams[p]);
1268 } else {
1269 dataAlone.push_back(dictDiagrams[p]);
1270 }
1271 }
1272 std::vector<std::vector<double>> weightsTemp(1);
1273 std::vector<double> weights(
1274 dictTemp.size(), 1. / (static_cast<int>(dictTemp.size()) * 1.));
1275 weightsTemp[0] = weights;
1276 std::vector<std::vector<double>> histoVectorWeights(1);
1277 std::vector<ttk::DiagramType> histoDictDiagrams(dictTemp.size());
1278 bool doCompression = false;
1279 this->method(dataAlone, dictTemp, weightsTemp,
1280 static_cast<int>(dictTemp.size()), lossTabTemp,
1281 allLossesTemp, histoVectorWeights, histoDictDiagrams,
1282 false, percent, doCompression);
1283 double min_loss
1284 = *std::min_element(lossTabTemp.begin(), lossTabTemp.end());
1285 allEnergy[j] = min_loss;
1286 }
1287 int index = std::min_element(allEnergy.begin(), allEnergy.end())
1288 - allEnergy.begin();
1289 dictDiagrams.erase(dictDiagrams.begin() + index);
1290 }
1291 break;
1292 }
1293 default:
1294 break;
1295 }
1296
1297 return 0;
1298}
1299
1301 const std::vector<ttk::DiagramType> &intermediateDiagrams,
1302 std::vector<ttk::DiagramType> &inputDiagramsMin,
1303 std::vector<ttk::DiagramType> &inputDiagramsSad,
1304 std::vector<ttk::DiagramType> &inputDiagramsMax,
1305 std::vector<BidderDiagram> &bidderDiagramsMin,
1306 std::vector<BidderDiagram> &bidderDiagramsSad,
1307 std::vector<BidderDiagram> &bidderDiagramsMax,
1308 std::vector<std::vector<size_t>> &originIndexMin,
1309 std::vector<std::vector<size_t>> &originIndexSad,
1310 std::vector<std::vector<size_t>> &originIndexMax,
1311 bool insertOriginIndexMode) const {
1312
1313 size_t nDiags = intermediateDiagrams.size();
1314
1315 // Create diagrams for min, saddle and max persistence pairs
1316#ifdef TTK_ENABLE_OPENMP
1317#pragma omp parallel for num_threads(threadNumber_)
1318#endif // TTK_ENABLE_OPENMP
1319 for(size_t i = 0; i < nDiags; i++) {
1320 const auto &CTDiagram = intermediateDiagrams[i];
1321
1322 for(size_t j = 0; j < CTDiagram.size(); ++j) {
1323 const PersistencePair &t = CTDiagram[j];
1324 const ttk::CriticalType nt1 = t.birth.type;
1325 const ttk::CriticalType nt2 = t.death.type;
1326 const double pers = t.persistence();
1327 if(pers > 0) {
1329 && nt2 == CriticalType::Local_maximum) {
1330 inputDiagramsMin[i].emplace_back(t);
1331 if(insertOriginIndexMode) {
1332 originIndexMin[i].push_back(j);
1333 }
1334 } else {
1336 || nt2 == CriticalType::Local_maximum) {
1337 inputDiagramsMax[i].emplace_back(t);
1338 if(insertOriginIndexMode) {
1339 originIndexMax[i].push_back(j);
1340 }
1341 }
1343 || nt2 == CriticalType::Local_minimum) {
1344 inputDiagramsMin[i].emplace_back(t);
1345 if(insertOriginIndexMode) {
1346 originIndexMin[i].push_back(j);
1347 }
1348 }
1349 if((nt1 == CriticalType::Saddle1 && nt2 == CriticalType::Saddle2)
1350 || (nt1 == CriticalType::Saddle2
1351 && nt2 == CriticalType::Saddle1)) {
1352 inputDiagramsSad[i].emplace_back(t);
1353 if(insertOriginIndexMode) {
1354 originIndexSad[i].push_back(j);
1355 }
1356 }
1357 }
1358 }
1359 }
1360 }
1361
1362 if(this->do_min_) {
1363 setBidderDiagrams(nDiags, inputDiagramsMin, bidderDiagramsMin);
1364 }
1365 if(this->do_sad_) {
1366 setBidderDiagrams(nDiags, inputDiagramsSad, bidderDiagramsSad);
1367 }
1368 if(this->do_max_) {
1369 setBidderDiagrams(nDiags, inputDiagramsMax, bidderDiagramsMax);
1370 }
1371}
1372
1374 double maxPers = 0.;
1375
1376 for(size_t j = 0; j < data.size(); ++j) {
1377 auto &t = data[j];
1378 double pers = t.death.sfValue - t.birth.sfValue;
1379 if(pers > maxPers) {
1380 maxPers = pers;
1381 }
1382 }
1383
1384 return maxPers;
1385}
1386
1388 const std::vector<ttk::DiagramType> &intermediateDiagrams,
1389 std::vector<ttk::DiagramType> &dictDiagrams) const {
1390
1391 size_t m = dictDiagrams.size();
1392 int globalSize = 0;
1393
1394 for(size_t j = 0; j < intermediateDiagrams.size(); ++j) {
1395 auto &data = intermediateDiagrams[j];
1396 globalSize += static_cast<int>(data.size());
1397 }
1398
1399 int dictSize = 0;
1400
1401 for(size_t j = 0; j < m; ++j) {
1402 auto &atom = dictDiagrams[j];
1403 dictSize += static_cast<int>(atom.size());
1404 }
1405
1406 if(static_cast<double>(dictSize)
1407 > (1. / this->CompressionFactor_) * static_cast<double>(globalSize)) {
1408 double factor
1409 = (1. / this->CompressionFactor_)
1410 * (static_cast<double>(globalSize) / static_cast<double>(dictSize));
1411 std::vector<std::vector<double>> tempDictPersistencePairs(m);
1412
1413 for(size_t j = 0; j < m; ++j) {
1414 auto &temp = tempDictPersistencePairs[j];
1415 auto &atom = dictDiagrams[j];
1416 temp.resize(atom.size());
1417 for(size_t p = 0; p < atom.size(); ++p) {
1418 auto &t = atom[p];
1419 temp[p] = t.persistence();
1420 }
1421 }
1422
1423 for(size_t j = 0; j < m; ++j) {
1424 auto &temp = tempDictPersistencePairs[j];
1425 std::sort(temp.begin(), temp.end(), std::greater<double>());
1426 }
1427
1428 std::vector<double> persThresholds(m);
1429 for(size_t j = 0; j < m; ++j) {
1430 auto &temp = tempDictPersistencePairs[j];
1431 int index
1432 = static_cast<int>(floor(factor * static_cast<double>(temp.size())));
1433 persThresholds[j] = temp[index];
1434 }
1435
1436 for(size_t j = 0; j < m; ++j) {
1437 double persThreshold = persThresholds[j];
1438 auto &atom = dictDiagrams[j];
1439 atom.erase(std::remove_if(atom.begin(), atom.end(),
1440 [persThreshold](ttk::PersistencePair &t) {
1441 return (t.death.sfValue - t.birth.sfValue)
1442 < persThreshold;
1443 }),
1444 atom.end());
1445 }
1446 }
1447}
1448
1450 const std::vector<std::vector<ttk::MatchingType>> &matchingsAtoms,
1451 const ttk::DiagramType &Barycenter,
1452 const ttk::DiagramType &newData,
1453 const std::vector<ttk::MatchingType> &matchingsCritType,
1454 const std::vector<size_t> &indexBaryCritType,
1455 const std::vector<size_t> &indexDataCritType,
1456 std::vector<std::vector<std::array<double, 2>>> &pairToAddGradList,
1457 std::vector<std::array<double, 2>> &directions,
1458 std::vector<std::array<double, 2>> &dataAssigned,
1459 std::vector<int> &tracker2,
1460 const bool doOptimizeAtoms) const {
1461
1462 size_t m = matchingsCritType.size();
1463 // int k = 0;
1464 for(size_t i = 0; i < m; ++i) {
1465 const ttk::MatchingType &t = matchingsCritType[i];
1466 // Id in newData
1467 const SimplexId Id1 = std::get<0>(t);
1468 // Id in barycenter
1469 const SimplexId Id2 = std::get<1>(t);
1470 if(Id2 < 0) {
1471 if(Id1 < 0) {
1472 continue;
1473 } else {
1474 if(doOptimizeAtoms && CreationFeatures_ && ProgApproach_) {
1475 const PersistencePair &t2 = newData[indexDataCritType[Id1]];
1476 const double birthData = t2.birth.sfValue;
1477 const double deathData = t2.death.sfValue;
1478 const double birthDeathBarycenter
1479 = birthData + (deathData - birthData) / 2.;
1480 std::array<double, 2> direction;
1481 direction[0] = birthData - birthDeathBarycenter;
1482 direction[1] = deathData - birthDeathBarycenter;
1483
1484 std::vector<std::array<double, 2>> newPairs(matchingsAtoms.size());
1485 for(size_t j = 0; j < matchingsAtoms.size(); ++j) {
1486 std::array<double, 2> pair{
1487 birthDeathBarycenter, birthDeathBarycenter};
1488 newPairs[j] = pair;
1489 }
1490 // pair to add later from the diagonal
1491 pairToAddGradList.push_back(newPairs);
1492 dataAssigned.push_back({birthData, deathData});
1493 directions.push_back(direction);
1494 } else {
1495 continue;
1496 }
1497 }
1498 } else {
1499 const PersistencePair &t3 = Barycenter[indexBaryCritType[Id2]];
1500 const double birthBarycenter = t3.birth.sfValue;
1501 const double deathBarycenter = t3.death.sfValue;
1502 auto &direction = directions[indexBaryCritType[Id2]];
1503 if(Id1 < 0) {
1504 // If matching on the diagonal
1505 const double birthDeathData
1506 = birthBarycenter + (deathBarycenter - birthBarycenter) / 2.;
1507 direction[0] = birthDeathData - birthBarycenter;
1508 direction[1] = birthDeathData - deathBarycenter;
1509 dataAssigned[indexBaryCritType[Id2]] = {birthDeathData, birthDeathData};
1510 } else {
1511 const PersistencePair &t2 = newData[indexDataCritType[Id1]];
1512 const double birthData = t2.birth.sfValue;
1513 const double deathData = t2.death.sfValue;
1514 direction[0] = birthData - birthBarycenter;
1515 direction[1] = deathData - deathBarycenter;
1516 dataAssigned[indexBaryCritType[Id2]] = {birthData, deathData};
1517 }
1518 tracker2[indexBaryCritType[Id2]] = 1;
1519 }
1520 }
1521}
1522
1524 std::vector<Matrix> &gradsAtoms,
1525 const ttk::DiagramType &Barycenter,
1526 const std::vector<double> &weights,
1527 const ttk::DiagramType &newData,
1528 const std::vector<ttk::MatchingType> &matchingsCritType,
1529 const std::vector<size_t> &indexBaryCritType,
1530 const std::vector<size_t> &indexDataCritType,
1531 std::vector<std::vector<std::array<double, 2>>> &pairToAddGradList,
1532 std::vector<std::vector<double>> &directions,
1533 std::vector<int> &checker,
1534 std::vector<PersistencePair> &infoToAdd,
1535 const bool doDimReduct) const {
1536
1537 for(size_t i = 0; i < matchingsCritType.size(); ++i) {
1538 const ttk::MatchingType &t = matchingsCritType[i];
1539 // Id in newData
1540 const SimplexId Id1 = std::get<0>(t);
1541 // Id in barycenter
1542 const SimplexId Id2 = std::get<1>(t);
1543 int maxWeights
1544 = std::max_element(weights.begin(), weights.end()) - weights.begin();
1545 if(Id2 < 0) {
1546 if(Id1 < 0) {
1547 continue;
1548 } else {
1549 if(CreationFeatures_) {
1550 const PersistencePair &t2 = newData[indexDataCritType[Id1]];
1551 const double birthData = t2.birth.sfValue;
1552 const double deathData = t2.death.sfValue;
1553 const double birthDeathBarycenter
1554 = birthData + (deathData - birthData) / 2.;
1555 std::vector<double> direction(2);
1556 direction[0] = birthData - birthDeathBarycenter;
1557 direction[1] = deathData - birthDeathBarycenter;
1558 std::vector<std::vector<double>> temp3(weights.size());
1559 std::vector<double> temp2(2);
1560 if(CompressionMode_ && !doDimReduct) {
1561 for(size_t j = 0; j < weights.size(); ++j) {
1562 if(j == static_cast<size_t>(maxWeights)) {
1563 temp2[0] = -2 * weights[j] * direction[0];
1564 temp2[1] = -2 * weights[j] * direction[1];
1565 } else {
1566 temp2[0] = 0.;
1567 temp2[1] = 0.;
1568 }
1569 temp3[j] = temp2;
1570 }
1571 } else {
1572 for(size_t j = 0; j < weights.size(); ++j) {
1573 temp2[0] = -2 * weights[j] * direction[0];
1574 temp2[1] = -2 * weights[j] * direction[1];
1575 temp3[j] = temp2;
1576 }
1577 }
1578 gradsAtoms.push_back(temp3);
1579 checker.push_back(1);
1580 std::vector<std::array<double, 2>> newPairs(weights.size());
1581 for(size_t j = 0; j < weights.size(); ++j) {
1582 std::array<double, 2> pair{
1583 birthDeathBarycenter, birthDeathBarycenter};
1584 newPairs[j] = pair;
1585 }
1586 // pair to add later from the diagonal
1587 pairToAddGradList.push_back(newPairs);
1588 infoToAdd.push_back(t2);
1589
1590 } else {
1591 continue;
1592 }
1593 }
1594 } else {
1595 const PersistencePair &t3 = Barycenter[indexBaryCritType[Id2]];
1596 const double birthBarycenter = t3.birth.sfValue;
1597 const double deathBarycenter = t3.death.sfValue;
1598 std::vector<double> direction(2);
1599 if(Id1 < 0) {
1600 const double birthDeathData
1601 = birthBarycenter + (deathBarycenter - birthBarycenter) / 2.;
1602 direction[0] = birthDeathData - birthBarycenter;
1603 direction[1] = birthDeathData - deathBarycenter;
1604 } else {
1605 const PersistencePair &t2 = newData[indexDataCritType[Id1]];
1606 const double birthData = t2.birth.sfValue;
1607 const double deathData = t2.death.sfValue;
1608 direction[0] = birthData - birthBarycenter;
1609 direction[1] = deathData - deathBarycenter;
1610 }
1611 directions[indexBaryCritType[Id2]] = std::move(direction);
1612 checker[indexBaryCritType[Id2]] = 1;
1613 }
1614 }
1615}
1616
1618 std::vector<ttk::DiagramType> &barycentersList,
1619 const size_t nDiags,
1620 std::vector<ttk::DiagramType> &barycentersListMin,
1621 std::vector<ttk::DiagramType> &barycentersListSad,
1622 std::vector<ttk::DiagramType> &barycentersListMax,
1623 std::vector<BidderDiagram> &bidderBarycentersListMin,
1624 std::vector<BidderDiagram> &bidderBarycentersListSad,
1625 std::vector<BidderDiagram> &bidderBarycentersListMax,
1626 std::vector<std::vector<size_t>> &originIndexBarysMin,
1627 std::vector<std::vector<size_t>> &originIndexBarysSad,
1628 std::vector<std::vector<size_t>> &originIndexBarysMax,
1629 std::vector<BidderDiagram> &bidderDiagramsMin,
1630 std::vector<BidderDiagram> &bidderDiagramsMax,
1631 std::vector<BidderDiagram> &bidderDiagramsSad,
1632 std::vector<std::vector<ttk::MatchingType>> &matchingsDatasMin,
1633 std::vector<std::vector<ttk::MatchingType>> &matchingsDatasMax,
1634 std::vector<std::vector<ttk::MatchingType>> &matchingsDatasSad,
1635 std::vector<double> &allLossesAtEpoch,
1636 bool firstDistComputation) const {
1637
1638 gettingBidderDiagrams(barycentersList, barycentersListMin, barycentersListSad,
1639 barycentersListMax, bidderBarycentersListMin,
1640 bidderBarycentersListSad, bidderBarycentersListMax,
1641 originIndexBarysMin, originIndexBarysSad,
1642 originIndexBarysMax, true);
1643
1644 // Compute distance and matchings
1645#ifdef TTK_ENABLE_OPENMP
1646#pragma omp parallel for num_threads(threadNumber_)
1647#endif // TTK_ENABLE_OPENMP
1648 for(size_t i = 0; i < nDiags; ++i) {
1649 std::vector<ttk::MatchingType> matchingMin;
1650 std::vector<ttk::MatchingType> matchingSad;
1651 std::vector<ttk::MatchingType> matchingMax;
1652
1653 if(this->do_min_) {
1654 auto &barycentermin = bidderBarycentersListMin[i];
1655 auto &datamin = bidderDiagramsMin[i];
1656 if(firstDistComputation) {
1657 allLossesAtEpoch[i]
1658 += computeDistance(datamin, barycentermin, matchingMin);
1659
1660 } else {
1661 computeDistance(datamin, barycentermin, matchingMin);
1662 }
1663 }
1664 if(this->do_max_) {
1665 auto &barycentermax = bidderBarycentersListMax[i];
1666 auto &datamax = bidderDiagramsMax[i];
1667 if(firstDistComputation) {
1668 allLossesAtEpoch[i]
1669 += computeDistance(datamax, barycentermax, matchingMax);
1670 } else {
1671 computeDistance(datamax, barycentermax, matchingMax);
1672 }
1673 }
1674 if(this->do_sad_) {
1675 auto &barycentersListad = bidderBarycentersListSad[i];
1676 auto &datasad = bidderDiagramsSad[i];
1677 if(firstDistComputation) {
1678 allLossesAtEpoch[i]
1679 += computeDistance(datasad, barycentersListad, matchingSad);
1680 } else {
1681 computeDistance(datasad, barycentersListad, matchingSad);
1682 }
1683 }
1684 matchingsDatasMin[i] = std::move(matchingMin);
1685 matchingsDatasSad[i] = std::move(matchingSad);
1686 matchingsDatasMax[i] = std::move(matchingMax);
1687 }
1688}
virtual int setThreadNumber(const int threadNumber)
Definition BaseClass.h:80
void setPositionInAuction(const int pos)
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
void setPrice(const double price)
void execute(std::vector< ttk::DiagramType > &DictDiagrams, const std::vector< ttk::DiagramType > &datas, const int nbAtoms, const int seed)
void SetCriticalCoordinates(const float coords_x, const float coords_y, const float coords_z)
double run(std::vector< MatchingType > &matchings, const int kdt_index=0)
void BuildAuctionDiagrams(const BidderDiagram &BD, const GoodDiagram &GD)
void execute(std::vector< ttk::DiagramType > &DictDiagrams, const std::vector< ttk::DiagramType > &datas, const int &nbAtoms, bool do_min_, bool do_sad_, bool do_max_)
void execute(std::vector< ttk::DiagramType > &intermediateDiagrams, const std::vector< ttk::DiagramType > &intermediateAtoms, std::vector< ttk::DiagramType > &dictDiagrams, std::vector< std::vector< double > > &vectorWeights, const int seed, const int numAtom, std::vector< double > &lossTab, std::vector< std::vector< double > > &allLosses, double percent)
void method(const std::vector< ttk::DiagramType > &intermediateDiagrams, std::vector< ttk::DiagramType > &dictDiagrams, std::vector< std::vector< double > > &vectorWeights, const int numAtom, std::vector< double > &lossTab, std::vector< std::vector< double > > &allLosses, std::vector< std::vector< double > > &histoVectorWeights, std::vector< ttk::DiagramType > &histoDictDiagrams, bool preWeightOpt, double percent, bool doCompression)
void computeDirectionsGradAtoms(std::vector< Matrix > &gradsAtoms, const ttk::DiagramType &Barycenter, const std::vector< double > &weights, const ttk::DiagramType &newData, const std::vector< ttk::MatchingType > &matchingsCritType, const std::vector< size_t > &indexBaryCritType, const std::vector< size_t > &indexDataCritType, std::vector< std::vector< std::array< double, 2 > > > &pairToAddGradList, std::vector< std::vector< double > > &directions, std::vector< int > &checker, std::vector< PersistencePair > &infoToAdd, const bool doOptimizeAtoms) const
void computeGradientAtoms(std::vector< Matrix > &gradsAtoms, const std::vector< double > &weights, const ttk::DiagramType &Barycenter, const ttk::DiagramType &newData, const std::vector< ttk::MatchingType > &matchingsMin, const std::vector< ttk::MatchingType > &matchingsMax, const std::vector< ttk::MatchingType > &matchingsSad, const std::vector< size_t > &indexBaryMin, const std::vector< size_t > &indexBaryMax, const std::vector< size_t > &indexBarySad, const std::vector< size_t > &indexDataMin, const std::vector< size_t > &indexDataMax, const std::vector< size_t > &indexDataSad, std::vector< int > &checker, std::vector< std::vector< std::array< double, 2 > > > &pairToAddGradList, ttk::DiagramType &infoToAdd, bool doDimReduct) const
int initDictionary(std::vector< ttk::DiagramType > &dictDiagrams, const std::vector< ttk::DiagramType > &datas, const std::vector< ttk::DiagramType > &inputAtoms, const int &nbAtom, bool &do_min_, bool &do_sad_, bool &do_max_, int seed, double &percent)
void computeDirectionsGradWeight(const std::vector< std::vector< ttk::MatchingType > > &matchingsAtoms, const ttk::DiagramType &Barycenter, const ttk::DiagramType &newData, const std::vector< ttk::MatchingType > &matchingsCritType, const std::vector< size_t > &indexBaryCritType, const std::vector< size_t > &indexDataCritType, std::vector< std::vector< std::array< double, 2 > > > &pairToAddGradList, std::vector< std::array< double, 2 > > &directions, std::vector< std::array< double, 2 > > &data_assigned, std::vector< int > &tracker2, const bool doOptimizeAtoms) const
double distVect(const std::vector< double > &vec1, const std::vector< double > &vec2) const
void controlAtomsSize(const std::vector< ttk::DiagramType > &intermediateDiagrams, std::vector< ttk::DiagramType > &dictDiagrams) const
double getMostPersistent(const std::vector< BidderDiagram > &bidder_diags) const
void computeAllDistances(std::vector< ttk::DiagramType > &barycentersList, const size_t nDiag, std::vector< ttk::DiagramType > &barycentersListMin, std::vector< ttk::DiagramType > &barycentersListSad, std::vector< ttk::DiagramType > &barycentersListMax, std::vector< BidderDiagram > &bidderBarycentersListMin, std::vector< BidderDiagram > &bidderBarycentersListSad, std::vector< BidderDiagram > &bidderBarycentersListMax, std::vector< std::vector< size_t > > &originIndexBarysMin, std::vector< std::vector< size_t > > &originIndexBarysSad, std::vector< std::vector< size_t > > &originIndexBarysMax, std::vector< BidderDiagram > &bidderDiagramsMin, std::vector< BidderDiagram > &bidderDiagramsMax, std::vector< BidderDiagram > &bidderDiagramsSad, std::vector< std::vector< ttk::MatchingType > > &matchingsDatasMin, std::vector< std::vector< ttk::MatchingType > > &matchingsDatasMax, std::vector< std::vector< ttk::MatchingType > > &matchingsDatasSad, std::vector< double > &allLossesAtEpoch, bool firstDistComputation) const
double getMaxPers(const ttk::DiagramType &data)
void setBidderDiagrams(const size_t nInputs, std::vector< ttk::DiagramType > &inputDiagrams, std::vector< BidderDiagram > &bidder_diags) const
double computeDistance(const BidderDiagram &D1, const BidderDiagram &D2, std::vector< ttk::MatchingType > &matching) const
void computeGradientWeights(std::vector< double > &gradWeights, std::vector< Matrix > &hessianList, const std::vector< ttk::DiagramType > &dictDiagrams, const std::vector< std::vector< ttk::MatchingType > > &matchingsAtoms, const ttk::DiagramType &Barycenter, const ttk::DiagramType &newData, const std::vector< ttk::MatchingType > &matchingsMin, const std::vector< ttk::MatchingType > &matchingsMax, const std::vector< ttk::MatchingType > &matchingsSad, const std::vector< size_t > &indexBaryMin, const std::vector< size_t > &indexBaryMax, const std::vector< size_t > &indexBarySad, const std::vector< size_t > &indexDataMin, const std::vector< size_t > &indexDataMax, const std::vector< size_t > &indexDataSad, const bool doOptimizeAtoms) const
void gettingBidderDiagrams(const std::vector< ttk::DiagramType > &intermediateDiagrams, std::vector< ttk::DiagramType > &inputDiagramsMin, std::vector< ttk::DiagramType > &inputDiagramsSad, std::vector< ttk::DiagramType > &inputDiagramsMax, std::vector< BidderDiagram > &bidderDiagramsMin, std::vector< BidderDiagram > &bidderDiagramsSad, std::vector< BidderDiagram > &bidderDiagramsMax, std::vector< std::vector< size_t > > &originIndexMin, std::vector< std::vector< size_t > > &originIndexSad, std::vector< std::vector< size_t > > &originIndexMax, bool insertOriginIndexMode) const
TTK base package defining the standard types.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
std::vector< std::vector< double > > Matrix
CriticalType
default value for critical index
Definition DataTypes.h:88
void computeWeightedBarycenter(std::vector< DiagramType > &intermediateDiagrams, std::vector< double > &weights, DiagramType &barycenter, std::vector< std::vector< MatchingType > > &matchings, const ttk::Debug &dbg, const bool ProgBarycenter)
std::tuple< int, int, double > MatchingType
Matching between two Persistence Diagram pairs.
std::vector< Good > GoodDiagram
std::vector< Bidder > BidderDiagram
std::vector< PersistencePair > DiagramType
Persistence Diagram type as a vector of Persistence pairs.
T end(std::pair< T, T > &p)
Definition ripser.cpp:503
T begin(std::pair< T, T > &p)
Definition ripser.cpp:499
double persistence() const
Return the topological persistence of the pair.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)