14 std::vector<std::vector<double>>
const &input,
15 std::vector<std::vector<double>>
const &latent) {
18 if(input.size() != latent.size()) {
19 printErr(
"Input and representation have different sizes");
22 if(input.size() == 0) {
23 printErr(
"Empty input / representation");
28 dimHigh_ = input[0].size();
29 dimLow_ = latent[0].size();
30 printMsg(
"#pts: " + std::to_string(n_) +
", highDim: "
31 + std::to_string(dimHigh_) +
", lowDim: " + std::to_string(dimLow_));
33 inputCompressedDistanceMatrix_.clear();
34 latentCompressedDistanceMatrix_.clear();
36 for(
unsigned i = 1; i < n_; ++i) {
37 for(
unsigned j = 0; j < i; ++j) {
38 double sHigh = 0., sLow = 0.;
39 for(
unsigned d = 0; d < dimHigh_; ++d)
40 sHigh += (input[i][d] - input[j][d]) * (input[i][d] - input[j][d]);
41 inputCompressedDistanceMatrix_.push_back(sqrt(sHigh));
42 for(
unsigned d = 0; d < dimLow_; ++d)
43 sLow += (latent[i][d] - latent[j][d]) * (latent[i][d] - latent[j][d]);
44 latentCompressedDistanceMatrix_.push_back(sqrt(sLow));
48 printMsg(
"Computing Wasserstein metrics", 0, tm.getElapsedTime());
49 computeTopologicalMetrics();
50 printMsg(
"Computing triplet accuracy", 0, tm.getElapsedTime());
51 computeTripletAccuracy();
52 printMsg(
"Computing distance-based measures", 0, tm.getElapsedTime());
53 computePairwiseDistanceBasedMetrics();
54 printMsg(
"Computing rank-based measures", 0, tm.getElapsedTime());
55 computeRankBasedMetrics();
56 printMsg(
"Complete", 1, tm.getElapsedTime());
59void ttk::DimensionReductionMetrics::computeTopologicalMetrics() {
63 {latentCompressedDistanceMatrix_}, latentPD,
rpd::inf, 1,
true);
64 inputPD[0].pop_back();
65 latentPD[0].pop_back();
68 auction0.setNewBidder(latentPD[0]);
69 auction0.setWasserstein(Wasserstein);
70 w0_ = auction0.runAuction();
73 auction1.setNewBidder(latentPD[1]);
74 auction1.setWasserstein(Wasserstein);
75 w1_ = auction1.runAuction();
78bool ttk::DimensionReductionMetrics::tripletOrderPreserved(
int i,
81 std::vector<std::pair<double, char>> inputTriangle
82 = {{inputDM(i, j), 0}, {inputDM(i, k), 1}, {inputDM(j, k), 2}};
83 std::vector<std::pair<double, char>> latentTriangle
84 = {{latentDM(i, j), 0}, {latentDM(i, k), 1}, {latentDM(j, k), 2}};
85 std::sort(inputTriangle.begin(), inputTriangle.end());
86 std::sort(latentTriangle.begin(), latentTriangle.end());
87 return inputTriangle[0].second == latentTriangle[0].second
88 && inputTriangle[1].second == latentTriangle[1].second
89 && inputTriangle[2].second == latentTriangle[2].second;
92void ttk::DimensionReductionMetrics::computeTripletAccuracy() {
93 unsigned stableTriplets = 0;
94 if(SampleSize <= -1) {
95 for(
unsigned i = 0; i < n_; ++i) {
96 for(
unsigned j = i + 1; j < n_; ++j) {
97 for(
unsigned k = j + 1; k < n_; ++k) {
98 if(tripletOrderPreserved(i, j, k))
103 ta_ = double(stableTriplets) * 6 / (n_ * (n_ - 1) * (n_ - 2));
105 std::random_device rd;
106 std::mt19937 gen(rd());
107 std::uniform_int_distribution<> uniform(0, n_ - 1);
108 for(
int s = 0; s < SampleSize; ++s) {
109 if(tripletOrderPreserved(uniform(gen), uniform(gen), uniform(gen)))
112 ta_ = double(stableTriplets) / SampleSize;
116void ttk::DimensionReductionMetrics::computePairwiseDistanceBasedMetrics() {
117 double sumX = 0., sumY = 0., sumXY = 0.;
118 double sqSumX = 0., sqSumY = 0.;
119 double sqSumDiff = 0.;
120 const unsigned Ndis = n_ * (n_ - 1) / 2;
121 for(
unsigned i = 0; i < Ndis; ++i) {
122 const double x = inputCompressedDistanceMatrix_[i];
123 const double y = latentCompressedDistanceMatrix_[i];
129 sqSumDiff += (x - y) * (x - y);
131 lc_ = (Ndis * sumXY - sumX * sumY)
132 / sqrt((Ndis * sqSumX - sumX * sumX) * (Ndis * sqSumY - sumY * sumY));
133 rmse_ = sqrt(sqSumDiff / Ndis);
136void ttk::DimensionReductionMetrics::computeRankBasedMetrics() {
137 NeighborhoodSize = std::min(NeighborhoodSize, n_ - 1);
139 int trustworthinessSum = 0;
140 int continuitySum = 0;
142 double inputMRRESum = 0;
143 double latentMRRESum = 0;
144 const int normalizingTC
145 = (NeighborhoodSize < n_ / 2)
146 ? n_ * NeighborhoodSize * (2 * n_ - 3 * NeighborhoodSize - 1)
147 : n_ * (n_ - NeighborhoodSize) * (n_ - NeighborhoodSize - 1);
148 double normalizingMRRE = 0.;
149 for(
unsigned k = 1; k < NeighborhoodSize; ++k)
150 normalizingMRRE += n_ * std::abs(
double(n_) - 2 * k + 1) / k;
152 for(
unsigned i = 0; i < n_; ++i) {
153 std::vector<std::pair<double, unsigned>> inputNeighborhood;
154 std::vector<std::pair<double, unsigned>> latentNeighborhood;
155 for(
unsigned j = 0; j < n_; ++j) {
156 inputNeighborhood.emplace_back(inputDM(i, j), j);
157 latentNeighborhood.emplace_back(latentDM(i, j), j);
159 std::sort(inputNeighborhood.begin(), inputNeighborhood.end());
160 std::sort(latentNeighborhood.begin(), latentNeighborhood.end());
162 std::vector<unsigned> inputRanks(n_);
163 std::vector<unsigned> latentRanks(n_);
164 for(
unsigned s = 0; s < n_; ++s) {
165 inputRanks[inputNeighborhood[s].second] = s;
166 latentRanks[latentNeighborhood[s].second] = s;
169 for(
unsigned j = 0; j < n_; ++j) {
170 if(latentRanks[j] <= NeighborhoodSize && inputRanks[j] > NeighborhoodSize)
171 trustworthinessSum += inputRanks[j] - NeighborhoodSize;
172 else if(inputRanks[j] <= NeighborhoodSize
173 && latentRanks[j] > NeighborhoodSize)
174 continuitySum += latentRanks[j] - NeighborhoodSize;
175 else if(inputRanks[j] <= NeighborhoodSize
176 && latentRanks[j] <= NeighborhoodSize && i != j)
180 for(
unsigned s = 1; s <= NeighborhoodSize; ++s) {
181 const unsigned inputNeighbor = inputNeighborhood[s].second;
182 inputMRRESum += double(std::abs(
int(s) -
int(latentRanks[inputNeighbor])))
183 / latentRanks[inputNeighbor];
184 const unsigned latentNeighbor = latentNeighborhood[s].second;
186 += double(std::abs(
int(s) -
int(inputRanks[latentNeighbor])))
187 / inputRanks[latentNeighbor];
191 trust_ = 1. - 2 * double(trustworthinessSum) / normalizingTC;
192 cont_ = 1. - 2 * double(continuitySum) / normalizingTC;
193 lcmc_ = (double(LCMCSum) / (n_ * NeighborhoodSize)
194 -
double(NeighborhoodSize) / (n_ - 1))
195 / (1 - double(NeighborhoodSize) / (n_ - 1));
196 mrreh_ = inputMRRESum / normalizingMRRE;
197 mrrel_ = latentMRRESum / normalizingMRRE;
void setDebugMsgPrefix(const std::string &prefix)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
void execute(std::vector< std::vector< double > > const &input, std::vector< std::vector< double > > const &latent)
Main entry point.
DimensionReductionMetrics()
TTK base class that computes the Wasserstein distance between two persistence diagrams.
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::vector< Diagram > MultidimensionalDiagram
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)