TTK
Loading...
Searching...
No Matches
PDClustering.cpp
Go to the documentation of this file.
1
14
15#include <PDClustering.h>
16
17#include <algorithm>
18#include <cmath>
19#include <cstdlib> /* srand, rand */
20#include <iostream>
21#include <iterator>
22#include <random>
23
25 std::vector<DiagramType> &final_centroids,
26 std::vector<std::vector<std::vector<std::vector<MatchingType>>>>
27 &all_matchings_per_type_and_cluster) {
28
29 all_matchings_per_type_and_cluster.resize(k_);
30 for(int c = 0; c < k_; c++) {
31 all_matchings_per_type_and_cluster[c].resize(3);
32 for(int i = 0; i < 3; i++) {
33 all_matchings_per_type_and_cluster[c][i].resize(numberOfInputs_);
34 }
35 }
36 int matchings_only = false;
37 Timer const tm;
38 {
39 // PARTICULARITIES FOR THE CASE OF ONE UNIQUE CLUSTER
40 if(k_ <= 1) {
41 use_accelerated_ = false;
42 use_kmeanspp_ = false;
44 use_progressive_ = false;
45 deterministic_ = true;
46 matchings_only = true;
47 time_limit_ = 99999999999;
48 }
49 }
50
51 std::vector<bool *> current_prec;
52 current_prec.emplace_back(&precision_min_);
53 current_prec.emplace_back(&precision_sad_);
54 current_prec.emplace_back(&precision_max_);
55
56 std::vector<bool *> current_dos;
57 current_dos.emplace_back(&do_min_);
58 current_dos.emplace_back(&do_sad_);
59 current_dos.emplace_back(&do_max_);
60 bool converged = false;
61 std::vector<bool> diagrams_complete(3);
62 for(int c = 0; c < 3; c++) {
63 diagrams_complete[c] = (!use_progressive_) || (!original_dos[c]);
64 }
65 n_iterations_ = 0;
66 double total_time = 0;
67
68 // double cost = std::numeric_limits<double>::max();
70 cost_ = std::numeric_limits<double>::max();
71 double min_cost_min = std::numeric_limits<double>::max();
72 double min_cost_max = std::numeric_limits<double>::max();
73 double min_cost_sad = std::numeric_limits<double>::max();
74 // double last_min_cost_obtained = -1;
75 double last_min_cost_obtained_min = -1;
76 double last_min_cost_obtained_sad = -1;
77 double last_min_cost_obtained_max = -1;
78 std::vector<double> epsilon0(3);
79 std::vector<double> epsilon_candidate(3);
80 std::vector<double> rho(3);
81
82 // Getting current diagrams (with only at most min_points_to_add points)
83 std::vector<double> max_persistence(3);
84 std::vector<double> lowest_persistence(3);
85 std::vector<double> min_persistence(3);
86
87 const auto square = [](const double a) { return a * a; };
88
89 for(int i_crit = 0; i_crit < 3; i_crit++) {
90 max_persistence[i_crit] = 2 * getMostPersistent(i_crit);
91 lowest_persistence[i_crit] = getLessPersistent(i_crit);
92 min_persistence[i_crit] = 0;
93 epsilon_[i_crit] = square(0.5 * max_persistence[i_crit])
94 / 8.; // max_persistence actually holds 2 times the
95 // highest persistence
96 epsilon0[i_crit] = epsilon_[i_crit];
97 }
98
99 std::vector<int> min_points_to_add(3);
100 min_points_to_add[0] = 10;
101 min_points_to_add[1] = 10;
102 min_points_to_add[2] = 10;
103
104 if(use_progressive_) {
105 } else {
106 min_points_to_add[0] = std::numeric_limits<int>::max();
107 min_points_to_add[1] = std::numeric_limits<int>::max();
108 min_points_to_add[2] = std::numeric_limits<int>::max();
109 }
110 std::vector<std::vector<double>> min_diag_price(3);
111 std::vector<std::vector<double>> min_off_diag_price(3);
112 for(int c = 0; c < 3; ++c) {
113 for(int i = 0; i < numberOfInputs_; i++) {
114 min_diag_price[c].emplace_back(0);
115 min_off_diag_price[c].emplace_back(0);
116 }
117 }
118 min_persistence = enrichCurrentBidderDiagrams(
119 max_persistence, min_persistence, min_diag_price, min_off_diag_price,
120 min_points_to_add, false, true);
121
122 for(int c = 0; c < 3; c++) {
123 if(min_persistence[c] <= lowest_persistence[c]) {
124 diagrams_complete[c] = true;
125 } // max_persistence actually holds 2 times the highest persistence
126 }
127 bool all_diagrams_complete
128 = diagrams_complete[0] && diagrams_complete[1] && diagrams_complete[2];
129 if(all_diagrams_complete) {
130 use_progressive_ = false;
131 }
132
133 // Initializing centroids and clusters
134 if(use_kmeanspp_) {
136 } else {
138 }
140 if(use_accelerated_) {
144 } else {
147 }
148 if(debugLevel_ > 3 && k_ > 1) {
149 printMsg("Initial Clustering: ");
151 }
152 initializeBarycenterComputers(min_persistence);
153 while(!converged || (!all_diagrams_complete && use_progressive_)) {
154 Timer t_inside;
155 {
157
158 for(int i_crit = 0; i_crit < 3; i_crit++) {
159 if(*(current_dos[i_crit])) {
160 rho[i_crit] = min_persistence[i_crit] > 0
161 ? std::sqrt(8.0 * epsilon_[i_crit])
162 : -1;
163 }
164 }
165
167
168 do_min_ = do_min_ && (min_persistence[0] > rho[0]);
169 do_sad_ = do_sad_ && (min_persistence[1] > rho[1]);
170 do_max_ = do_max_ && (min_persistence[2] > rho[2]);
171
172 for(int i_crit = 0; i_crit < 3; i_crit++) {
173 if(*(current_dos[i_crit])) {
174 epsilon_candidate[i_crit] = square(min_persistence[i_crit]) / 8.;
175 if(epsilon_candidate[i_crit] > epsilon_[i_crit]) {
176 // Should always be the case except if min_persistence is
177 // equal to zero
178 epsilon_[i_crit] = epsilon_candidate[i_crit];
179 }
180 }
181 }
182
183 if(epsilon_[0] < 5e-5) {
184 // Add all remaining points for final convergence.
185 // rho[0] = 0;
186 min_persistence[0] = 0;
187 min_points_to_add[0] = std::numeric_limits<int>::max();
188 }
189 if(epsilon_[1] < 5e-5) {
190 // Add all remaining points for final convergence.
191 // rho[1] = 0;
192 min_persistence[1] = 0;
193 min_points_to_add[1] = std::numeric_limits<int>::max();
194 }
195 if(epsilon_[2] < 5e-5) {
196 // Add all remaining points for final convergence.
197 // rho[2] = 0;
198 min_persistence[2] = 0;
199 min_points_to_add[2] = std::numeric_limits<int>::max();
200 }
201
202 if(do_min_ || do_sad_ || do_max_) {
203 min_persistence = enrichCurrentBidderDiagrams(
204 min_persistence, rho, min_diag_price, min_off_diag_price,
205 min_points_to_add, true, false);
206 }
208
209 for(int i_crit = 0; i_crit < 3; i_crit++) {
210 if(*(current_dos[i_crit])) {
211 if(min_persistence[i_crit] <= lowest_persistence[i_crit]) {
212 diagrams_complete[i_crit] = true;
213 }
214 }
215 }
216
217 if(diagrams_complete[0] && diagrams_complete[1]
218 && diagrams_complete[2]) {
219 use_progressive_ = false;
220 all_diagrams_complete = true;
221 }
222
224 }
225 std::vector<double> max_shift_vec = updateCentroidsPosition(
226 &min_off_diag_price, &min_diag_price,
227 all_matchings_per_type_and_cluster, matchings_only);
228 if(do_min_ && !UseDeltaLim_) {
229 precision_min_ = (epsilon_[0] < epsilon0[0] / 500.);
230 }
231 if(do_sad_ && !UseDeltaLim_) {
232 precision_sad_ = (epsilon_[1] < epsilon0[1] / 500.);
233 }
234 if(do_max_ && !UseDeltaLim_) {
235 precision_max_ = (epsilon_[2] < epsilon0[2] / 500.);
236 }
237
238 for(int i_crit = 0; i_crit < 3; i_crit++) {
239 if(*(current_dos[i_crit]) /*&& (!*(current_prec[i_crit]) || !diagrams_complete[i_crit] ) */) {
240 epsilon_candidate[i_crit] = std::min(
241 std::max(max_shift_vec[i_crit] / 8., epsilon_[i_crit] / 5.),
242 epsilon0[i_crit] / square(n_iterations_));
243
244 if((epsilon_candidate[i_crit] < epsilon_[i_crit]
245 && !diagrams_complete[i_crit])
246 || diagrams_complete[i_crit]) {
247 epsilon_[i_crit] = epsilon_candidate[i_crit];
248 } else {
249 epsilon_[i_crit] *= 0.95;
250 }
251 }
252 }
253
254 if(epsilon_[0] < epsilon_min_ /*&& diagrams_complete[0]*/) {
255 this->printMsg("[min barycenter] epsilon under minimal value ",
257 do_min_ = false;
259 diagrams_complete[0] = true;
260 }
261 if(epsilon_[1] < epsilon_min_ /*&& diagrams_complete[1]*/) {
262 this->printMsg("[sad barycenter] epsilon under minimal value ",
264 do_sad_ = false;
266 diagrams_complete[1] = true;
267 }
268 if(epsilon_[2] < epsilon_min_ /*&& diagrams_complete[2]*/) {
269 this->printWrn("[max barycenter] epsilon under minimal value ");
270 do_max_ = false;
272 diagrams_complete[2] = true;
273 }
274
275 if(diagrams_complete[0] && diagrams_complete[1]
276 && diagrams_complete[2]) {
277 use_progressive_ = false;
278 all_diagrams_complete = true;
279 }
280 if(use_accelerated_) {
282 } else {
283 // updateClusters();
284 }
285
288 bool const precision_criterion_reached = precision_criterion_;
289
290 this->printMsg("Iteration " + std::to_string(n_iterations_)
291 + " epsilon " + std::to_string(epsilon_[0]) + " "
292 + std::to_string(epsilon_[1]) + " "
293 + std::to_string(epsilon_[2]),
295 this->printMsg(" complete " + std::to_string(diagrams_complete[0]) + " "
296 + std::to_string(diagrams_complete[1]) + " "
297 + std::to_string(diagrams_complete[2]),
299 this->printMsg(" precision " + std::to_string(precision_min_) + " "
300 + std::to_string(precision_sad_) + " "
301 + std::to_string(precision_max_),
303 this->printMsg(" cost " + std::to_string(cost_min_) + " "
304 + std::to_string(cost_sad_) + " "
305 + std::to_string(cost_max_),
307
309 && diagrams_complete[0] /*&& precision_min_*/) {
310 min_cost_min = cost_min_;
311 last_min_cost_obtained_min = 0;
312 } else if(n_iterations_ > 2 && precision_min_ && diagrams_complete[0]) {
313 last_min_cost_obtained_min += 1;
314 if(last_min_cost_obtained_min > 1) {
315 do_min_ = false;
316 }
317 }
318
320 && diagrams_complete[1] /*&& precision_sad_*/) {
321 min_cost_sad = cost_sad_;
322 last_min_cost_obtained_sad = 0;
323 } else if(n_iterations_ > 2 && precision_sad_ && diagrams_complete[1]) {
324 last_min_cost_obtained_sad += 1;
325 if(last_min_cost_obtained_sad > 1 && diagrams_complete[1]) {
326 do_sad_ = false;
327 }
328 }
329
331 && diagrams_complete[2] /*&& precision_max_*/) {
332 min_cost_max = cost_max_;
333 last_min_cost_obtained_max = 0;
334 } else if(n_iterations_ > 2 && precision_max_ && diagrams_complete[2]) {
335 last_min_cost_obtained_max += 1;
336 if(last_min_cost_obtained_max > 1 && diagrams_complete[2]) {
337 do_max_ = false;
338 }
339 }
340
341 if(debugLevel_ > 5) {
342 this->printMsg("Clustering result:", debug::Priority::DETAIL);
344 }
345 converged = converged
346 || (all_diagrams_complete && !do_min_ && !do_sad_
347 && !do_max_ && (precision_criterion_reached))
348 || (precision_criterion_reached && UseDeltaLim_
349 && numberOfInputs_ == 2);
350 }
351
352 total_time
353 += t_inside.getElapsedTime(); // - t_real_cost.getElapsedTime();
354
355 if(total_time + t_inside.getElapsedTime() > 0.9 * time_limit_) {
356 min_cost_min = cost_min_;
357 min_cost_sad = cost_sad_;
358 min_cost_max = cost_max_;
359 converged = true;
360 }
361 if(total_time > 0.1 * time_limit_) {
362 all_diagrams_complete = true;
363 diagrams_complete[0] = true;
364 diagrams_complete[1] = true;
365 diagrams_complete[2] = true;
366 use_progressive_ = false;
367 }
368 if(debugLevel_ > 4) {
369 std::cout << "== Iteration " << n_iterations_
370 << " == complete : " << all_diagrams_complete
371 << " , progressive : " << use_progressive_
372 << " , converged : " << converged << std::endl;
373 }
374 }
376
377 // display results
378 std::vector<std::vector<std::string>> const rows{
379 {" Min-saddle cost", std::to_string(cost_min_)},
380 {" Saddle-saddle cost", std::to_string(cost_sad_)},
381 {" Saddle-max cost", std::to_string(cost_max_)},
382 {matchings_only ? "Wasserstein Distance" : "Final Cost",
383 std::to_string(cost_min_ + cost_sad_ + cost_max_)},
384 };
385 this->printMsg(rows);
386
387 if(!use_progressive_ && k_ > 1) {
388 clustering_ = old_clustering_; // reverting to last clustering
389 }
390 invertClusters(); // this is to pass the old inverse clustering to the VTK
391 // wrapper
392 if(k_ > 1) {
393 this->printMsg("Clustering result:");
395 }
396 } // End of timer
397
398 // CORRECT MATCHINGS :
399 // correctMatchings(all_matchings);
400 if(matchings_only) {
401 computeBarycenterForTwoGlobal(all_matchings_per_type_and_cluster);
402 }
403 correctMatchings(all_matchings_per_type_and_cluster);
404 // Filling the final centroids for output
405
406 final_centroids.resize(k_);
407 centroids_sizes_.resize(k_);
408 for(int c = 0; c < k_; c++) {
409 centroids_sizes_[c].resize(3);
410 if(do_min_)
411 centroids_sizes_[c][0] = centroids_min_[c].size();
412 if(do_sad_)
413 centroids_sizes_[c][1] = centroids_saddle_[c].size();
414 if(do_max_)
415 centroids_sizes_[c][2] = centroids_max_[c].size();
416 }
417
418 for(int c = 0; c < k_; ++c) {
419 // if NumberOfClusters > 1, the global pair was duplicated
420 // and needs to be removed from the min-saddle problem
421 // It is the first pair.
422 int const removeFirstPairMin
423 = (k_ > 1 and original_dos[0] and original_dos[2]) ? 1 : 0;
424 int addedFirstPairMax = 0;
425 int addedFirstPairMin = removeFirstPairMin;
426
427 // min-max Pair
428 if(removeFirstPairMin or (!do_min_ and do_max_)) {
429 Good const &g = centroids_max_[c].at(0);
430 const auto &critCoords = g.GetCriticalCoordinates();
431 final_centroids[c].emplace_back(PersistencePair{
432 CriticalVertex{0, g.x_, {}, critCoords, CriticalType::Local_minimum},
433 CriticalVertex{0, g.y_, {}, critCoords, CriticalType::Local_maximum}, 0,
434 false});
435 addedFirstPairMax = 1;
436 } else if(do_min_) {
437 Good const &g = centroids_min_[c].at(0);
438 const auto &critCoords = g.GetCriticalCoordinates();
439 final_centroids[c].emplace_back(PersistencePair{
440 CriticalVertex{0, g.x_, {}, critCoords, CriticalType::Local_minimum},
441 CriticalVertex{0, g.y_, {}, critCoords, CriticalType::Local_maximum}, 0,
442 false});
443 addedFirstPairMin = 1;
444 }
445
446 if(do_min_) {
447 for(size_t i = addedFirstPairMin; i < centroids_min_[c].size(); ++i) {
448 Good const &g = centroids_min_[c].at(i);
449 const auto &critCoords = g.GetCriticalCoordinates();
450 final_centroids[c].emplace_back(PersistencePair{
451 CriticalVertex{0, g.x_, {}, critCoords, CriticalType::Local_minimum},
452 CriticalVertex{0, g.y_, {}, critCoords, CriticalType::Saddle1}, 0,
453 true});
454 if(g.getPersistence() > 1000) {
455 this->printMsg("Found a abnormally high persistence in min diagram",
457 }
458 }
459 }
460
461 if(do_sad_) {
462 for(size_t i = 0; i < centroids_saddle_[c].size(); ++i) {
463 Good const &g = centroids_saddle_[c].at(i);
464 const auto &critCoords = g.GetCriticalCoordinates();
465 final_centroids[c].emplace_back(PersistencePair{
466 CriticalVertex{0, g.x_, {}, critCoords, CriticalType::Saddle1},
467 CriticalVertex{0, g.y_, {}, critCoords, CriticalType::Saddle2}, 1,
468 true});
469 if(g.getPersistence() > 1000) {
470 this->printMsg("Found a abnormally high persistence in sad diagram",
472 }
473 }
474 }
475
476 if(do_max_) {
477 for(size_t i = addedFirstPairMax; i < centroids_max_[c].size(); ++i) {
478 Good const &g = centroids_max_[c].at(i);
479 const auto &critCoords = g.GetCriticalCoordinates();
480 ttk::CriticalType saddle_type;
481 if(do_sad_)
482 saddle_type = ttk::CriticalType::Saddle2;
483 else
484 saddle_type = ttk::CriticalType::Saddle1;
485
486 final_centroids[c].emplace_back(PersistencePair{
487 CriticalVertex{0, g.x_, {}, critCoords, saddle_type},
488 CriticalVertex{0, g.y_, {}, critCoords, CriticalType::Local_maximum},
489 2, true});
490
491 if(g.getPersistence() > 1000) {
492 this->printMsg("Found a abnormally high persistence in min diagram",
494 }
495 }
496 }
497 }
498
499 if(distanceWritingOptions_ == 1) {
501 } else if(distanceWritingOptions_ == 2) {
503 }
504
505 return inv_clustering_;
506}
507
509 std::vector<std::vector<std::vector<std::vector<MatchingType>>>>
510 &previous_matchings) {
511 for(int c = 0; c < k_; c++) {
512 for(size_t i = 0; i < clustering_[c].size(); i++) {
513 int const diagram_id = clustering_[c][i];
514 if(original_dos[0]) {
515 // 1. Invert the current_bidder_ids_ vector
516 std::vector<int> new_to_old_id(
517 current_bidder_diagrams_min_[diagram_id].size(), -1);
518 for(size_t j = 0; j < current_bidder_ids_min_[diagram_id].size(); j++) {
519 int const new_id = current_bidder_ids_min_[diagram_id][j];
520 if(new_id >= 0) {
521 new_to_old_id[new_id] = j;
522 }
523 }
524 // 2. Reconstruct the matchings
525 std::vector<MatchingType> matchings_diagram_i;
526 for(size_t j = 0; j < previous_matchings[c][0][i].size(); j++) {
527 MatchingType m = previous_matchings[c][0][i][j];
528 int const new_id = std::get<0>(m);
529 if(new_id >= 0 && std::get<1>(m) >= 0) {
530 std::get<0>(m) = new_to_old_id[new_id];
531 matchings_diagram_i.emplace_back(m);
532 } else if(std::get<1>(m)
533 >= 0) { // new_id < 0 corresponds to a diagonal matching
534 std::get<0>(m) = -1;
535 matchings_diagram_i.emplace_back(m);
536 }
537 }
538 previous_matchings[c][0][i].resize(matchings_diagram_i.size());
539 previous_matchings[c][0][i] = matchings_diagram_i;
540 }
541 if(original_dos[1]) {
542 // 1. Invert the current_bidder_ids_ vector
543 std::vector<int> new_to_old_id(
544 current_bidder_diagrams_saddle_[diagram_id].size());
545 for(size_t j = 0; j < current_bidder_ids_sad_[diagram_id].size(); j++) {
546 int const new_id = current_bidder_ids_sad_[diagram_id][j];
547 if(new_id >= 0) {
548 new_to_old_id[new_id] = j;
549 }
550 }
551 // 2. Reconstruct the matchings
552 int zero_done = 0;
553 std::vector<MatchingType> matchings_diagram_i;
554 for(size_t j = 0; j < previous_matchings[c][1][i].size(); j++) {
555 MatchingType m = previous_matchings[c][1][i][j];
556 int const new_id = std::get<0>(m);
557 if(new_id >= 0 && std::get<1>(m) >= 0) {
558 int const old_id = new_to_old_id[new_id];
559 if(old_id > 0) {
560 std::get<0>(m) = old_id;
561 matchings_diagram_i.emplace_back(m);
562 } else {
563 if(!zero_done) {
564 zero_done = 1;
565 std::get<0>(m) = old_id;
566 matchings_diagram_i.emplace_back(m);
567 }
568 }
569 } else if(std::get<1>(m)
570 >= 0) { // new_id < 0 corresponds to a diagonal matching
571 std::get<0>(m) = -1;
572 matchings_diagram_i.emplace_back(m);
573 }
574 }
575 previous_matchings[c][1][i].resize(matchings_diagram_i.size());
576 previous_matchings[c][1][i] = matchings_diagram_i;
577 }
578 if(original_dos[2]) {
579 // 1. Invert the current_bidder_ids_ vector
580 std::vector<int> new_to_old_id(
581 current_bidder_diagrams_max_[diagram_id].size());
582 for(size_t j = 0; j < current_bidder_ids_max_[diagram_id].size(); j++) {
583 int const new_id = current_bidder_ids_max_[diagram_id][j];
584 if(new_id >= 0) {
585 new_to_old_id[new_id] = j;
586 }
587 }
588 // 2. Reconstruct the matchings
589 int zero_done = 0;
590 std::vector<MatchingType> matchings_diagram_i;
591 for(size_t j = 0; j < previous_matchings[c][2][i].size(); j++) {
592 MatchingType m = previous_matchings[c][2][i][j];
593 int const new_id = std::get<0>(m);
594 if(new_id >= 0 && std::get<1>(m) >= 0) {
595 int const old_id = new_to_old_id[new_id];
596 if(old_id > 0) {
597 std::get<0>(m) = old_id;
598 matchings_diagram_i.emplace_back(m);
599 } else {
600 if(!zero_done) {
601 zero_done = 1;
602 std::get<0>(m) = old_id;
603 matchings_diagram_i.emplace_back(m);
604 }
605 }
606 } else if(std::get<1>(m)
607 >= 0) { // new_id < 0 corresponds to a diagonal matching
608 std::get<0>(m) = -1;
609 matchings_diagram_i.emplace_back(m);
610 }
611 }
612 previous_matchings[c][2][i].resize(matchings_diagram_i.size());
613 previous_matchings[c][2][i] = matchings_diagram_i;
614 }
615 }
616 }
617}
618
620 std::vector<std::vector<std::vector<MatchingType>>> matchings) {
621 std::cout << "\n MATCHINGS : " << std::endl;
622 for(int d = 0; d < 3; d++) {
623 if(original_dos[d]) {
624 std::cout << "\n Diagram type : " << d << std::endl;
625 for(size_t i = 0; i < matchings[d].size(); i++) {
626 std::cout << " diagram " << i << " : ";
627 for(size_t j = 0; j < matchings[d][i].size(); j++) {
628 std::cout << std::get<0>(matchings[d][i][j]) << " ";
629 std::cout << std::get<1>(matchings[d][i][j]) << " ";
630 std::cout << std::get<2>(matchings[d][i][j]) << " | ";
631 }
632 std::cout << "\n";
633 }
634 }
635 }
636}
637
638std::vector<std::vector<int>> ttk::PDClustering::get_centroids_sizes() {
639 return centroids_sizes_;
640}
641
643 double max_persistence = 0;
644
645 if(do_min_ && (type == -1 || type == 0)) {
646 for(size_t i = 0; i < bidder_diagrams_min_.size(); ++i) {
647 for(size_t j = 0; j < bidder_diagrams_min_[i].size(); ++j) {
648 Bidder const b = bidder_diagrams_min_[i].at(j);
649 double const persistence = b.getPersistence();
650 if(persistence > max_persistence) {
651 max_persistence = persistence;
652 }
653 }
654 }
655 }
656
657 if(do_sad_ && (type == -1 || type == 1)) {
658 for(size_t i = 0; i < bidder_diagrams_saddle_.size(); ++i) {
659 for(size_t j = 0; j < bidder_diagrams_saddle_[i].size(); ++j) {
660 Bidder const b = bidder_diagrams_saddle_[i].at(j);
661 double const persistence = b.getPersistence();
662 if(persistence > max_persistence) {
663 max_persistence = persistence;
664 }
665 }
666 }
667 }
668
669 if(do_max_ && (type == -1 || type == 2)) {
670 for(size_t i = 0; i < bidder_diagrams_max_.size(); ++i) {
671 for(size_t j = 0; j < bidder_diagrams_max_[i].size(); ++j) {
672 Bidder const b = bidder_diagrams_max_[i].at(j);
673 double const persistence = b.getPersistence();
674 if(persistence > max_persistence) {
675 max_persistence = persistence;
676 }
677 }
678 }
679 }
680 return max_persistence;
681}
682
684 // type == -1 : query the min of all the types of diagrams.
685 // type = 0 : min, 1 : sad, 2 : max
686
687 double min_persistence = std::numeric_limits<double>::max();
688 if(do_min_ && (type == -1 || type == 0)) {
689 for(size_t i = 0; i < bidder_diagrams_min_.size(); ++i) {
690 for(size_t j = 0; j < bidder_diagrams_min_[i].size(); ++j) {
691 Bidder const b = bidder_diagrams_min_[i].at(j);
692 double const persistence = b.getPersistence();
693 if(persistence < min_persistence) {
694 min_persistence = persistence;
695 }
696 }
697 }
698 }
699
700 if(do_sad_ && (type == -1 || type == 1)) {
701 for(size_t i = 0; i < bidder_diagrams_saddle_.size(); ++i) {
702 for(size_t j = 0; j < bidder_diagrams_saddle_[i].size(); ++j) {
703 Bidder const b = bidder_diagrams_saddle_[i].at(j);
704 double const persistence = b.getPersistence();
705 if(persistence < min_persistence) {
706 min_persistence = persistence;
707 }
708 }
709 }
710 }
711
712 if(do_max_ && (type == -1 || type == 2)) {
713 for(size_t i = 0; i < bidder_diagrams_max_.size(); ++i) {
714 for(size_t j = 0; j < bidder_diagrams_max_[i].size(); ++j) {
715 Bidder const b = bidder_diagrams_max_[i].at(j);
716 double const persistence = b.getPersistence();
717 if(persistence < min_persistence) {
718 min_persistence = persistence;
719 }
720 }
721 }
722 }
723 return min_persistence;
724}
725
726std::vector<std::vector<double>> ttk::PDClustering::getMinPrices() {
727 std::vector<std::vector<double>> min_prices(3);
728
729 if(original_dos[0]) {
730 for(int i = 0; i < numberOfInputs_; ++i) {
731 min_prices[0].emplace_back(std::numeric_limits<double>::max());
732 for(size_t j = 0; j < centroids_with_price_min_[i].size(); ++j) {
733 Good const g = centroids_with_price_min_[i].at(j);
734 double const price = g.getPrice();
735 if(price < min_prices[0][i]) {
736 min_prices[0][i] = price;
737 }
738 }
739 }
740 }
741
742 if(original_dos[1]) {
743 for(int i = 0; i < numberOfInputs_; ++i) {
744 min_prices[1].emplace_back(std::numeric_limits<double>::max());
745 for(size_t j = 0; j < centroids_with_price_saddle_[i].size(); ++j) {
746 Good const g = centroids_with_price_saddle_[i].at(j);
747 double const price = g.getPrice();
748 if(price < min_prices[1][i]) {
749 min_prices[1][i] = price;
750 }
751 }
752 }
753 }
754
755 if(original_dos[2]) {
756 for(int i = 0; i < numberOfInputs_; ++i) {
757 min_prices[2].emplace_back(std::numeric_limits<double>::max());
758 for(size_t j = 0; j < centroids_with_price_max_[i].size(); ++j) {
759 Good const g = centroids_with_price_max_[i].at(j);
760 double const price = g.getPrice();
761 if(price < min_prices[2][i]) {
762 min_prices[2][i] = price;
763 }
764 }
765 }
766 }
767
768 return min_prices;
769}
770
771std::vector<std::vector<double>> ttk::PDClustering::getMinDiagonalPrices() {
772 std::vector<std::vector<double>> min_prices(3);
773 if(original_dos[0]) {
774 for(int i = 0; i < numberOfInputs_; ++i) {
775 min_prices[0].emplace_back(std::numeric_limits<double>::max());
776 for(size_t j = 0; j < current_bidder_diagrams_min_[i].size(); ++j) {
777 Bidder const b = current_bidder_diagrams_min_[i].at(j);
778 double const price = b.diagonal_price_;
779 if(price < min_prices[0][i]) {
780 min_prices[0][i] = price;
781 }
782 }
783 if(min_prices[0][i] >= std::numeric_limits<double>::max() / 2.) {
784 min_prices[0][i] = 0;
785 }
786 }
787 }
788
789 if(original_dos[1]) {
790 for(int i = 0; i < numberOfInputs_; ++i) {
791 min_prices[1].emplace_back(std::numeric_limits<double>::max());
792 for(size_t j = 0; j < current_bidder_diagrams_saddle_[i].size(); ++j) {
793 Bidder const b = current_bidder_diagrams_saddle_[i].at(j);
794 double const price = b.diagonal_price_;
795 if(price < min_prices[1][i]) {
796 min_prices[1][i] = price;
797 }
798 }
799 if(min_prices[1][i] >= std::numeric_limits<double>::max() / 2.) {
800 min_prices[1][i] = 0;
801 }
802 }
803 }
804
805 if(original_dos[2]) {
806 for(int i = 0; i < numberOfInputs_; ++i) {
807 min_prices[2].emplace_back(std::numeric_limits<double>::max());
808 for(size_t j = 0; j < current_bidder_diagrams_max_[i].size(); ++j) {
809 Bidder const b = current_bidder_diagrams_max_[i].at(j);
810 double const price = b.diagonal_price_;
811 if(price < min_prices[2][i]) {
812 min_prices[2][i] = price;
813 }
814 }
815 if(min_prices[2][i] >= std::numeric_limits<double>::max() / 2.) {
816 min_prices[2][i] = 0;
817 }
818 }
819 }
820 return min_prices;
821}
822
824 const BidderDiagram &D2,
825 const double delta_lim) {
826 GoodDiagram const D2_bis = diagramToCentroid(D2);
827 return computeDistance(D1, D2_bis, delta_lim);
828}
829
831 const GoodDiagram &D2,
832 const double delta_lim) {
833 std::vector<MatchingType> matchings;
834 const auto D2_bis = centroidWithZeroPrices(D2);
836 delta_lim, use_kdtree_, nonMatchingWeight_);
837 auction.BuildAuctionDiagrams(D1, D2_bis);
838 double const cost = auction.run(matchings);
839 return cost;
840}
841
843 const GoodDiagram *const D2,
844 const double delta_lim) {
845 std::vector<MatchingType> matchings;
847 delta_lim, use_kdtree_, nonMatchingWeight_);
848 int const size1 = D1->size();
849 auction.BuildAuctionDiagrams(*D1, *D2);
850 double const cost = auction.run(matchings);
851 // Diagonal Points were added in the original diagram. The following line
852 // removes them.
853 D1->resize(size1);
854 return cost;
855}
856
858 const GoodDiagram &D2,
859 const double delta_lim) {
860 BidderDiagram const D1_bis = centroidToDiagram(D1);
861 return computeDistance(D1_bis, D2, delta_lim);
862}
863
867 for(size_t i = 0; i < centroid.size(); i++) {
868 Good g = centroid.at(i);
869 g.setPrice(0);
870 GD.emplace_back(g);
871 }
872 return GD;
873}
874
878 for(size_t i = 0; i < diagram.size(); i++) {
879 Bidder b = diagram.at(i);
880 b.setDiagonalPrice(0);
881 BD.emplace_back(b);
882 }
883 return BD;
884}
885
889 for(size_t i = 0; i < centroid.size(); i++) {
890 Good g = centroid.at(i);
891
892 Bidder b = Bidder(g.x_, g.y_, g.isDiagonal(), BD.size());
893 b.SetCriticalCoordinates(g.coords_[0], g.coords_[1], g.coords_[2]);
894 b.setPositionInAuction(BD.size());
895 BD.emplace_back(b);
896 }
897 return BD;
898}
899
903 for(size_t i = 0; i < diagram.size(); i++) {
904 Bidder b = diagram.at(i);
905
906 Good g = Good(b.x_, b.y_, b.isDiagonal(), GD.size());
907 g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
908 GD.emplace_back(g);
909 }
910 return GD;
911}
912
914 clustering_ = std::vector<std::vector<int>>(k_);
915}
916
918 std::vector<int> idx(numberOfInputs_);
919 // To perform a random draw with replacement, the vector {1, 2, ...,
920 // numberOfInputs_} is shuffled, and we consider its k_ first elements to be
921 // the initial centroids.
922 for(int i = 0; i < numberOfInputs_; i++) {
923 idx[i] = i;
924 }
925 if(!deterministic_)
926 std::shuffle(idx.begin(), idx.end(), std::random_device());
927
928 for(int c = 0; c < k_; c++) {
929 if(do_min_) {
930 GoodDiagram const centroid_min
932 centroids_min_.emplace_back(centroid_min);
933 }
934 if(do_sad_) {
935 GoodDiagram const centroid_sad
937 centroids_saddle_.emplace_back(centroid_sad);
938 }
939 if(do_max_) {
940 GoodDiagram const centroid_max
942 centroids_max_.emplace_back(centroid_max);
943 }
944 }
945}
946
948 std::vector<int> indexes_clusters;
949 int const random_idx = deterministic_ ? 0 : rand() % numberOfInputs_;
950 indexes_clusters.emplace_back(random_idx);
951
952 if(do_min_) {
953 GoodDiagram const centroid_min
955 centroids_min_.emplace_back(centroid_min);
956 }
957 if(do_sad_) {
958 GoodDiagram const centroid_sad
960 centroids_saddle_.emplace_back(centroid_sad);
961 }
962 if(do_max_) {
963 GoodDiagram const centroid_max
965 centroids_max_.emplace_back(centroid_max);
966 }
967
968 const auto square = [](const double a) { return a * a; };
969
970 while((int)indexes_clusters.size() < k_) {
971 std::vector<double> min_distance_to_centroid(numberOfInputs_);
972 std::vector<double> probabilities(numberOfInputs_);
973
974 // Uncomment for a deterministic algorithm
975 double maximal_distance = 0;
976 int candidate_centroid = 0;
977
978 for(int i = 0; i < numberOfInputs_; i++) {
979
980 min_distance_to_centroid[i] = std::numeric_limits<double>::max();
981 if(std::find(indexes_clusters.begin(), indexes_clusters.end(), i)
982 != indexes_clusters.end()) {
983
984 min_distance_to_centroid[i] = 0;
985 } else {
986
987 for(size_t j = 0; j < indexes_clusters.size(); ++j) {
988
989 double distance = 0;
990 if(do_min_) {
991 GoodDiagram const centroid_min
993 distance += computeDistance(
994 current_bidder_diagrams_min_[i], centroid_min, 0.01);
995 }
996 if(do_sad_) {
997 GoodDiagram const centroid_saddle
999 distance += computeDistance(
1000 current_bidder_diagrams_saddle_[i], centroid_saddle, 0.01);
1001 }
1002 if(do_max_) {
1003 GoodDiagram const centroid_max
1005 distance += computeDistance(
1006 current_bidder_diagrams_max_[i], centroid_max, 0.01);
1007 }
1008 if(distance < min_distance_to_centroid[i]) {
1009 min_distance_to_centroid[i] = distance;
1010 }
1011 }
1012 }
1013 probabilities[i] = square(min_distance_to_centroid[i]);
1014
1015 // The following block is useful in case of need for a deterministic
1016 // algorithm
1017 if(deterministic_ && min_distance_to_centroid[i] > maximal_distance) {
1018 maximal_distance = min_distance_to_centroid[i];
1019 candidate_centroid = i;
1020 }
1021 }
1022 // Comment the following four lines to make it deterministic
1023 std::random_device rd;
1024 std::mt19937 gen(rd());
1025 std::discrete_distribution<int> distribution(
1026 probabilities.begin(), probabilities.end());
1027
1028 if(!deterministic_) {
1029 candidate_centroid = distribution(gen);
1030 }
1031
1032 indexes_clusters.emplace_back(candidate_centroid);
1033 if(do_min_) {
1034 GoodDiagram const centroid_min
1035 = diagramToCentroid(current_bidder_diagrams_min_[candidate_centroid]);
1036 centroids_min_.emplace_back(centroid_min);
1037 }
1038 if(do_sad_) {
1039 GoodDiagram const centroid_sad = diagramToCentroid(
1040 current_bidder_diagrams_saddle_[candidate_centroid]);
1041 centroids_saddle_.emplace_back(centroid_sad);
1042 }
1043 if(do_max_) {
1044 GoodDiagram const centroid_max
1045 = diagramToCentroid(current_bidder_diagrams_max_[candidate_centroid]);
1046 centroids_max_.emplace_back(centroid_max);
1047 }
1048 }
1049}
1050
1052 // r_ is a vector stating for each diagram if its distance to its centroid is
1053 // up to date (false) or needs to be recomputed (true)
1054 r_ = std::vector<bool>(numberOfInputs_);
1055 // u_ is a vector of upper bounds of the distance of each diagram to its
1056 // closest centroid
1057 u_ = std::vector<double>(numberOfInputs_);
1058 inv_clustering_ = std::vector<int>(numberOfInputs_);
1059 for(int i = 0; i < numberOfInputs_; i++) {
1060 r_[i] = true;
1061 u_[i] = std::numeric_limits<double>::max();
1062 inv_clustering_[i] = -1;
1063 }
1064 // l_ is the matrix of lower bounds for the distance from each diagram
1065 // to each centroid
1066 l_ = std::vector<std::vector<double>>(numberOfInputs_);
1067 for(int i = 0; i < numberOfInputs_; ++i) {
1068 l_[i] = std::vector<double>(k_);
1069 for(int c = 0; c < k_; ++c) {
1070 l_[i][c] = 0;
1071 }
1072 }
1073
1074 // And d_ is a (K x K) matrix storing the distances between each pair of
1075 // centroids
1077 for(int i = 0; i < k_; ++i) {
1078 centroidsDistanceMatrix_[i].resize(k_, 0.0);
1079 }
1080}
1081
1082std::vector<std::vector<double>> ttk::PDClustering::getDistanceMatrix() {
1083 std::vector<std::vector<double>> D(numberOfInputs_);
1084
1085 for(int i = 0; i < numberOfInputs_; ++i) {
1086 BidderDiagram D1_min, D1_sad, D1_max;
1087 if(do_min_) {
1089 }
1090 if(do_sad_) {
1092 }
1093 if(do_max_) {
1095 }
1096 for(int c = 0; c < k_; ++c) {
1097 GoodDiagram D2_min, D2_sad, D2_max;
1098 double distance = 0;
1099 if(do_min_) {
1100 D2_min = centroids_min_[c];
1101 distance += computeDistance(D1_min, D2_min, 0.01);
1102 }
1103 if(do_sad_) {
1104 D2_sad = centroids_saddle_[c];
1105 distance += computeDistance(D1_sad, D2_sad, 0.01);
1106 }
1107 if(do_max_) {
1108 D2_max = centroids_max_[c];
1109 distance += computeDistance(D1_max, D2_max, 0.01);
1110 }
1111 D[i].emplace_back(distance);
1112 }
1113 }
1114 return D;
1115}
1116
1118 for(int i = 0; i < k_; ++i) {
1119 GoodDiagram D1_min, D1_sad, D1_max;
1120 if(do_min_) {
1122 }
1123 if(do_sad_) {
1125 }
1126 if(do_max_) {
1128 }
1129 for(int j = i + 1; j < k_; ++j) {
1130 double distance{};
1131 GoodDiagram D2_min, D2_sad, D2_max;
1132 if(do_min_) {
1134 distance += computeDistance(D1_min, D2_min, 0.01);
1135 }
1136 if(do_sad_) {
1138 distance += computeDistance(D1_sad, D2_sad, 0.01);
1139 }
1140 if(do_max_) {
1142 distance += computeDistance(D1_max, D2_max, 0.01);
1143 }
1144
1145 centroidsDistanceMatrix_[i][j] = distance;
1146 centroidsDistanceMatrix_[j][i] = distance;
1147 }
1148 }
1149}
1150
1153
1154 for(int i = 0; i < numberOfInputs_; ++i) {
1155 double const delta_lim{0.01};
1156 double distance{};
1157 auto c = inv_clustering_[i];
1158 if(original_dos[0]) {
1159 GoodDiagram const centroid_min
1161 BidderDiagram const bidder_diag
1163 distance += computeDistance(bidder_diag, centroid_min, delta_lim);
1164 }
1165 if(original_dos[1]) {
1166 GoodDiagram const centroid_saddle
1168 BidderDiagram const bidder_diag
1170 distance += computeDistance(bidder_diag, centroid_saddle, delta_lim);
1171 }
1172 if(original_dos[2]) {
1173 GoodDiagram const centroid_max
1175 BidderDiagram const bidder_diag
1177 distance += computeDistance(bidder_diag, centroid_max, delta_lim);
1178 }
1179 distanceToCentroid_[i] = distance;
1180 }
1181}
1182
1184 if(k_ > 1) {
1185 std::vector<std::vector<double>> distance_matrix = getDistanceMatrix();
1189
1190 for(int i = 0; i < numberOfInputs_; ++i) {
1191 double min_distance_to_centroid = std::numeric_limits<double>::max();
1192 int cluster = -1;
1193 for(int c = 0; c < k_; ++c) {
1194 if(distance_matrix[i][c] < min_distance_to_centroid) {
1195 min_distance_to_centroid = distance_matrix[i][c];
1196 cluster = c;
1197 }
1198 }
1199
1200 clustering_[cluster].emplace_back(i);
1201 if(cluster != inv_clustering_[i]) {
1202 // New centroid attributed to this diagram
1205 if(do_min_) {
1208 }
1209 if(do_sad_) {
1212 }
1213 if(do_max_) {
1216 }
1217 inv_clustering_[i] = cluster;
1218 }
1219 }
1220
1221 } else {
1225
1226 for(int i = 0; i < numberOfInputs_; i++) {
1227 clustering_[0].emplace_back(i);
1228 if(n_iterations_ < 1) {
1229 if(do_min_) {
1232 }
1233 if(do_sad_) {
1236 }
1237 if(do_max_) {
1240 }
1241 }
1242 inv_clustering_[i] = 0;
1243 }
1244 }
1245}
1246
1251
1252 // Initializes clusters with -1
1253 inv_clustering_ = std::vector<int>(numberOfInputs_, -1);
1254
1255 // Fill in the clusters
1256 for(int c = 0; c < k_; ++c) {
1257 for(size_t j = 0; j < clustering_[c].size(); ++j) {
1258 int const idx = clustering_[c][j];
1259 inv_clustering_[idx] = c;
1260 }
1261 }
1262}
1263
1265 clustering_ = std::vector<std::vector<int>>(k_);
1266 for(int i = 0; i < numberOfInputs_; ++i) {
1267 clustering_[inv_clustering_[i]].emplace_back(i);
1268 }
1269
1270 // Check if a cluster was left without diagram
1271 for(int c = 0; c < k_; ++c) {
1272 if(clustering_[c].empty()) {
1273 std::cout << "Problem in invertInverseClusters()... \nCluster " << c
1274 << " was left with no diagram attached to it... " << std::endl;
1275 }
1276 }
1277}
1278
1280 // Step 1
1283 // self.old_clusters = copy.copy(self.clusters)
1286 bool const do_min = original_dos[0];
1287 bool const do_sad = original_dos[1];
1288 bool const do_max = original_dos[2];
1289
1290 for(int i = 0; i < numberOfInputs_; ++i) {
1291 // Step 3 find potential changes of clusters
1292 BidderDiagram D1_min, D1_sad, D1_max;
1293 if(do_min) {
1295 }
1296 if(do_sad) {
1298 }
1299 if(do_max) {
1301 }
1302
1303 for(int c = 0; c < k_; ++c) {
1304 if(inv_clustering_[i] == -1) {
1305 // If not yet assigned, assign it first to a random cluster
1306
1307 if(deterministic_) {
1308 inv_clustering_[i] = i % k_;
1309 } else {
1310 std::cout << " - ASSIGNED TO A RANDOM CLUSTER " << '\n';
1311 inv_clustering_[i] = rand() % (k_);
1312 }
1313
1314 r_[i] = true;
1315 if(do_min) {
1318 }
1319 if(do_sad) {
1322 }
1323 if(do_max) {
1326 }
1327 }
1328
1329 if(c != inv_clustering_[i] && u_[i] > l_[i][c]
1330 && u_[i] > 0.5 * centroidsDistanceMatrix_[inv_clustering_[i]][c]) {
1331 // Step 3a, If necessary, recompute the distance to centroid
1332 if(r_[i]) {
1333 double distance = 0;
1334 GoodDiagram centroid_min, centroid_sad, centroid_max;
1335 if(do_min) {
1336 centroid_min
1338 distance += computeDistance(D1_min, centroid_min, 0.01);
1339 }
1340 if(do_sad) {
1341 centroid_sad
1343 distance += computeDistance(D1_sad, centroid_sad, 0.01);
1344 }
1345 if(do_max) {
1346 centroid_max
1348 distance += computeDistance(D1_max, centroid_max, 0.01);
1349 }
1350 r_[i] = false;
1351 u_[i] = distance;
1352 l_[i][inv_clustering_[i]] = distance;
1353 }
1354 // Step 3b, check if still potential change of clusters
1355 if((n_iterations_ > 2 || n_iterations_ < 1)
1356 && (u_[i] > l_[i][c]
1357 || u_[i]
1358 > 0.5 * centroidsDistanceMatrix_[inv_clustering_[i]][c])) {
1359 BidderDiagram diagram_min, diagram_sad, diagram_max;
1360 GoodDiagram centroid_min, centroid_sad, centroid_max;
1361 double distance = 0;
1362
1363 if(do_min) {
1364 centroid_min = centroidWithZeroPrices(centroids_min_[c]);
1365 diagram_min
1367 distance += computeDistance(diagram_min, centroid_min, 0.01);
1368 }
1369 if(do_sad) {
1370 centroid_sad = centroidWithZeroPrices(centroids_saddle_[c]);
1371 diagram_sad
1373 distance += computeDistance(diagram_sad, centroid_sad, 0.01);
1374 }
1375 if(do_max) {
1376 centroid_max = centroidWithZeroPrices(centroids_max_[c]);
1377 diagram_max
1379 distance += computeDistance(diagram_max, centroid_max, 0.01);
1380 }
1381 l_[i][c] = distance;
1382 // TODO Prices are lost here... If distance<self.u[i], we should keep
1383 // the prices
1384 if(distance < u_[i]) {
1385 // Changing cluster
1388 u_[i] = distance;
1389 inv_clustering_[i] = c;
1390
1391 if(do_min) {
1394 }
1395 if(do_sad) {
1398 }
1399 if(do_max) {
1402 }
1403 }
1404 }
1405 }
1406 }
1407 }
1409 for(int c = 0; c < k_; ++c) {
1410 if(clustering_[c].empty()) {
1411 std::cout << "Adding artificial centroid because a cluster was empty"
1412 << std::endl;
1413 bool idx_acceptable = false;
1414 int idx = 0;
1415
1416 std::vector<double> copy_of_u(u_.size());
1417 copy_of_u = u_;
1418 while(!idx_acceptable) {
1419 auto argMax = std::max_element(copy_of_u.begin(), copy_of_u.end());
1420 idx = std::distance(copy_of_u.begin(), argMax);
1421 if(inv_clustering_[idx] < k_ && inv_clustering_[idx] >= 0
1422 && clustering_[inv_clustering_[idx]].size() > 1) {
1423 idx_acceptable = true;
1424 int const cluster_removal = inv_clustering_[idx];
1425 // Removing the index to remove
1426 clustering_[cluster_removal].erase(
1427 std::remove(clustering_[cluster_removal].begin(),
1428 clustering_[cluster_removal].end(), idx),
1429 clustering_[cluster_removal].end());
1430 } else {
1431 if(copy_of_u.size() > (size_t)idx) {
1432 copy_of_u.erase(argMax);
1433 } else {
1434 idx_acceptable = true;
1435 int cluster_max = 0;
1436 if(!clustering_[cluster_max].empty()) {
1437 idx = clustering_[cluster_max][0];
1438 }
1439 for(int i_test = 1; i_test < k_; i_test++) {
1440 if(clustering_[i_test].size() > clustering_[cluster_max].size()) {
1441 cluster_max = i_test;
1442 idx = clustering_[cluster_max][0];
1443 }
1444 }
1445 int const cluster_removal = inv_clustering_[idx];
1446 clustering_[cluster_removal].erase(
1447 std::remove(clustering_[cluster_removal].begin(),
1448 clustering_[cluster_removal].end(), idx),
1449 clustering_[cluster_removal].end());
1450 }
1451 }
1452 }
1453
1454 clustering_[c].emplace_back(idx);
1455 inv_clustering_[idx] = c;
1456
1457 if(do_min) {
1462 }
1463 if(do_sad) {
1468 }
1469 if(do_max) {
1474 }
1477 }
1478 }
1479}
1480
1482 std::vector<std::vector<double>> *min_price,
1483 std::vector<std::vector<double>> *min_diag_price,
1484 std::vector<std::vector<std::vector<std::vector<MatchingType>>>>
1485 &all_matchings_per_type_and_cluster,
1486 int only_matchings) {
1488 std::vector<double> max_shift_vector(3);
1489 max_shift_vector[0] = 0;
1490 max_shift_vector[1] = 0;
1491 max_shift_vector[2] = 0;
1492 double max_shift_c_min = 0;
1493 double max_shift_c_sad = 0;
1494 double max_shift_c_max = 0;
1495 double max_wasserstein_shift = 0;
1496 bool precision_min = true;
1497 bool precision_sad = true;
1498 bool precision_max = true;
1499 cost_ = 0;
1500 double const sq_dist_min = cost_min_;
1501 double const sq_dist_sad = cost_sad_;
1502 double const sq_dist_max = cost_max_;
1503 if(do_min_) {
1504 cost_min_ = 0;
1505 }
1506 if(do_sad_) {
1507 cost_sad_ = 0;
1508 }
1509 if(do_max_) {
1510 cost_max_ = 0;
1511 }
1512
1513 for(int c = 0; c < k_; ++c) {
1514 if(!clustering_[c].empty()) {
1515 std::vector<GoodDiagram> centroids_with_price_min,
1516 centroids_with_price_sad, centroids_with_price_max;
1517 int count = 0;
1518 for(int const idx : clustering_[c]) {
1519 // Timer time_first_thing;
1520 // Find the position of diagrams[idx] in old cluster c
1521 std::vector<int>::iterator const i = std::find(
1522 old_clustering_[c].begin(), old_clustering_[c].end(), idx);
1523 int const pos = (i == old_clustering_[c].end())
1524 ? -1
1525 : std::distance(old_clustering_[c].begin(), i);
1526 if(pos >= 0) {
1527 // Diagram was already linked to this centroid before
1528 if(do_min_) {
1529 centroids_with_price_min.emplace_back(
1531 }
1532 if(do_sad_) {
1533 centroids_with_price_sad.emplace_back(
1535 }
1536 if(do_max_) {
1537 centroids_with_price_max.emplace_back(
1539 }
1540 } else {
1541 int number_of_points_min = 0;
1542 int number_of_points_max = 0;
1543 int number_of_points_sad = 0;
1544
1545 // Otherwise, centroid is given 0 prices and the diagram is given 0
1546 // diagonal-prices
1547 if(do_min_) {
1548 centroids_with_price_min.emplace_back(
1552 number_of_points_min += centroids_with_price_min_[idx].size()
1553 + current_bidder_diagrams_min_[idx].size();
1554 }
1555 if(do_sad_) {
1556 centroids_with_price_sad.emplace_back(
1560 number_of_points_sad
1561 += centroids_with_price_saddle_[idx].size()
1562 + current_bidder_diagrams_saddle_[idx].size();
1563 }
1564 if(do_max_) {
1565 centroids_with_price_max.emplace_back(
1569 number_of_points_max += centroids_with_price_max_[idx].size()
1570 + current_bidder_diagrams_max_[idx].size();
1571 }
1572
1573 if(n_iterations_ > 1) {
1574 // If diagram new to cluster and we're not at first iteration,
1575 // precompute prices for the objects via compute_distance()
1576 // number_of_points /= (int)do_min_ + (int)do_sad_ + (int)do_max_;
1577 // double d_estimated = pow(cost_ / numberOfInputs_, 1. /
1578 // wasserstein_) + 1e-7; We use pointer in the auction in order to
1579 // keep the prices at the end
1580
1581 if(do_min_) {
1582 // double estimated_delta_lim = number_of_points_min *
1583 // epsilon_[0] / (2*sq_dist_min) ;
1584 double estimated_delta_lim
1585 = 1.
1586 / sqrt(1 - number_of_points_min * epsilon_[0] / sq_dist_min)
1587 - 1;
1588 if(estimated_delta_lim > 1) {
1589 estimated_delta_lim = 1;
1590 }
1592 &(centroids_with_price_min[count]),
1593 estimated_delta_lim);
1594 }
1595 if(do_sad_) {
1596 // double estimated_delta_lim = number_of_points_sad *
1597 // epsilon_[1] / (2*sq_dist_sad);
1598 double estimated_delta_lim
1599 = 1.
1600 / sqrt(1 - number_of_points_sad * epsilon_[1] / sq_dist_sad)
1601 - 1;
1602 if(estimated_delta_lim > 1) {
1603 estimated_delta_lim = 1;
1604 }
1606 &(centroids_with_price_sad[count]),
1607 estimated_delta_lim);
1608 }
1609 if(do_max_) {
1610 // double estimated_delta_lim = number_of_points_max *
1611 // epsilon_[2] / (2*sq_dist_max);
1612 double estimated_delta_lim
1613 = 1.
1614 / sqrt(1 - number_of_points_max * epsilon_[2] / sq_dist_max)
1615 - 1;
1616 if(estimated_delta_lim > 1) {
1617 estimated_delta_lim = 1;
1618 }
1620 &(centroids_with_price_max[count]),
1621 estimated_delta_lim);
1622 }
1623 }
1624 }
1625 count++;
1626 }
1627 double total_cost = 0;
1628 double wasserstein_shift = 0;
1629
1630 using KDTreePair = PDBarycenter::KDTreePair;
1631
1632 if(do_min_) {
1633 std::vector<std::vector<MatchingType>> all_matchings;
1634 std::vector<int> sizes;
1635 Timer const time_preprocess_bary;
1636 std::vector<BidderDiagram> diagrams_c_min;
1638 for(int const idx : clustering_[c]) {
1639 diagrams_c_min.emplace_back(current_bidder_diagrams_min_[idx]);
1640 }
1641 sizes.resize(diagrams_c_min.size());
1642 for(size_t i = 0; i < diagrams_c_min.size(); i++) {
1643 sizes[i] = diagrams_c_min[i].size();
1644 }
1645 barycenter_computer_min_[c].setNumberOfInputs(diagrams_c_min.size());
1646 barycenter_computer_min_[c].setCurrentBidders(diagrams_c_min);
1647
1648 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
1649 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
1650 i_diagram++) {
1651 barycenter_goods[i_diagram]
1652 = centroids_with_price_min_[clustering_[c][i_diagram]];
1653 }
1654 barycenter_computer_min_[c].setCurrentBarycenter(barycenter_goods);
1655 all_matchings.resize(diagrams_c_min.size());
1656 } else {
1657 sizes.resize(barycenter_computer_min_[c].getCurrentBidders().size());
1658 for(size_t i = 0;
1659 i < barycenter_computer_min_[c].getCurrentBidders().size(); i++) {
1660 sizes[i]
1661 = barycenter_computer_min_[c].getCurrentBidders().at(i).size();
1662 }
1663 diagrams_c_min.resize(
1664 barycenter_computer_min_[c].getCurrentBidders().size());
1665 all_matchings.resize(
1666 barycenter_computer_min_[c].getCurrentBidders().size());
1667 }
1668
1669 KDTreePair pair;
1670 bool use_kdt = false;
1671 if(!barycenter_computer_min_[c].getCurrentBarycenter()[0].empty()) {
1672 pair = barycenter_computer_min_[c].getKDTree();
1673 use_kdt = true;
1674 }
1675
1676 barycenter_computer_min_[c].runMatching(
1677 &total_cost, epsilon_[0], sizes, *pair.first, pair.second,
1678 &(min_diag_price->at(0)), &(min_price->at(0)), &(all_matchings),
1679 use_kdt, only_matchings);
1680 for(size_t ii = 0; ii < all_matchings.size(); ii++) {
1681 all_matchings_per_type_and_cluster[c][0][ii].resize(
1682 all_matchings[ii].size());
1683 all_matchings_per_type_and_cluster[c][0][ii] = all_matchings[ii];
1684 }
1685 for(int ii = all_matchings.size(); ii < numberOfInputs_; ii++) {
1686 all_matchings_per_type_and_cluster[c][0][ii].resize(0);
1687 }
1688
1689 precision_min
1690 = barycenter_computer_min_[c].isPrecisionObjectiveMet(deltaLim_, 0);
1691 cost_min_ += total_cost;
1692 Timer const time_update;
1693 if(!only_matchings) {
1694 max_shift_c_min
1695 = barycenter_computer_min_[c].updateBarycenter(all_matchings);
1696 }
1697
1698 if(max_shift_c_min > max_shift_vector[0]) {
1699 max_shift_vector[0] = max_shift_c_min;
1700 }
1701
1702 // Now that barycenters and diagrams are updated in
1703 // PDBarycenter class, we import the results here.
1704 diagrams_c_min = barycenter_computer_min_[c].getCurrentBidders();
1705 centroids_with_price_min
1706 = barycenter_computer_min_[c].getCurrentBarycenter();
1707 int i = 0;
1708 for(int const idx : clustering_[c]) {
1709 current_bidder_diagrams_min_[idx] = diagrams_c_min[i];
1710 centroids_with_price_min_[idx] = centroids_with_price_min[i];
1711 i++;
1712 }
1713
1714 GoodDiagram const old_centroid = centroids_min_[c];
1717
1718 if(use_accelerated_) {
1719 wasserstein_shift
1720 += computeDistance(old_centroid, centroids_min_[c], 0.01);
1721 }
1722 }
1723
1724 if(do_sad_) {
1725 std::vector<std::vector<MatchingType>> all_matchings;
1726 total_cost = 0;
1727 std::vector<int> sizes;
1728
1729 std::vector<BidderDiagram> diagrams_c_min;
1731 for(int const idx : clustering_[c]) {
1732 diagrams_c_min.emplace_back(current_bidder_diagrams_saddle_[idx]);
1733 }
1734 sizes.resize(diagrams_c_min.size());
1735 for(size_t i = 0; i < diagrams_c_min.size(); i++) {
1736 sizes[i] = diagrams_c_min[i].size();
1737 }
1738 barycenter_computer_sad_[c].setNumberOfInputs(diagrams_c_min.size());
1739 barycenter_computer_sad_[c].setCurrentBidders(diagrams_c_min);
1740 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
1741 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
1742 i_diagram++) {
1743 barycenter_goods[i_diagram]
1745 }
1746 barycenter_computer_sad_[c].setCurrentBarycenter(barycenter_goods);
1747 all_matchings.resize(diagrams_c_min.size());
1748 } else {
1749 sizes.resize(barycenter_computer_sad_[c].getCurrentBidders().size());
1750 for(size_t i = 0;
1751 i < barycenter_computer_sad_[c].getCurrentBidders().size(); i++) {
1752 sizes[i]
1753 = barycenter_computer_sad_[c].getCurrentBidders().at(i).size();
1754 }
1755 all_matchings.resize(
1756 barycenter_computer_sad_[c].getCurrentBidders().size());
1757 diagrams_c_min.resize(
1758 barycenter_computer_sad_[c].getCurrentBidders().size());
1759 }
1760
1761 KDTreePair pair;
1762 bool use_kdt = false;
1763 if(!barycenter_computer_sad_[c].getCurrentBarycenter()[0].empty()) {
1764 pair = barycenter_computer_sad_[c].getKDTree();
1765 use_kdt = true;
1766 }
1767
1768 barycenter_computer_sad_[c].runMatching(
1769 &total_cost, epsilon_[1], sizes, *pair.first, pair.second,
1770 &(min_diag_price->at(1)), &(min_price->at(1)), &(all_matchings),
1771 use_kdt, only_matchings);
1772 for(size_t ii = 0; ii < all_matchings.size(); ii++) {
1773 all_matchings_per_type_and_cluster[c][1][ii].resize(
1774 all_matchings[ii].size());
1775 all_matchings_per_type_and_cluster[c][1][ii] = all_matchings[ii];
1776 }
1777 for(int ii = all_matchings.size(); ii < numberOfInputs_; ii++) {
1778 all_matchings_per_type_and_cluster[c][1][ii].resize(0);
1779 }
1780
1781 precision_sad
1782 = barycenter_computer_sad_[c].isPrecisionObjectiveMet(deltaLim_, 0);
1783 if(!only_matchings) {
1784 max_shift_c_sad
1785 = barycenter_computer_sad_[c].updateBarycenter(all_matchings);
1786 }
1787
1788 cost_sad_ += total_cost;
1789
1790 if(max_shift_c_sad > max_shift_vector[1]) {
1791 max_shift_vector[1] = max_shift_c_sad;
1792 }
1793
1794 // Now that barycenters and diagrams are updated in PDBarycenter class,
1795 // we import the results here.
1796 diagrams_c_min = barycenter_computer_sad_[c].getCurrentBidders();
1797 centroids_with_price_sad
1798 = barycenter_computer_sad_[c].getCurrentBarycenter();
1799 int i = 0;
1800 for(int const idx : clustering_[c]) {
1801 current_bidder_diagrams_saddle_[idx] = diagrams_c_min[i];
1802 centroids_with_price_saddle_[idx] = centroids_with_price_sad[i];
1803 i++;
1804 }
1805 GoodDiagram const old_centroid = centroids_saddle_[c];
1809 wasserstein_shift
1810 += computeDistance(old_centroid, centroids_saddle_[c], 0.01);
1811 }
1812
1813 if(do_max_) {
1814 std::vector<std::vector<MatchingType>> all_matchings;
1815 Timer const time_preprocess_bary;
1816 total_cost = 0;
1817 std::vector<int> sizes;
1818 std::vector<BidderDiagram> diagrams_c_min;
1820 for(int const idx : clustering_[c]) {
1821 diagrams_c_min.emplace_back(current_bidder_diagrams_max_[idx]);
1822 }
1823 sizes.resize(diagrams_c_min.size());
1824 for(size_t i = 0; i < diagrams_c_min.size(); i++) {
1825 sizes[i] = diagrams_c_min[i].size();
1826 }
1827 barycenter_computer_max_[c].setNumberOfInputs(diagrams_c_min.size());
1828 barycenter_computer_max_[c].setCurrentBidders(diagrams_c_min);
1829 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
1830 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
1831 i_diagram++) {
1832 barycenter_goods[i_diagram]
1833 = centroids_with_price_max_[clustering_[c][i_diagram]];
1834 }
1835 barycenter_computer_max_[c].setCurrentBarycenter(barycenter_goods);
1836 all_matchings.resize(diagrams_c_min.size());
1837 } else {
1838 sizes.resize(barycenter_computer_max_[c].getCurrentBidders().size());
1839 for(size_t i = 0;
1840 i < barycenter_computer_max_[c].getCurrentBidders().size(); i++) {
1841 sizes[i]
1842 = barycenter_computer_max_[c].getCurrentBidders().at(i).size();
1843 }
1844
1845 diagrams_c_min.resize(
1846 barycenter_computer_max_[c].getCurrentBidders().size());
1847 all_matchings.resize(
1848 barycenter_computer_max_[c].getCurrentBidders().size());
1849 }
1850
1851 KDTreePair pair;
1852 bool use_kdt = false;
1853 if(!barycenter_computer_max_[c].getCurrentBarycenter()[0].empty()) {
1854 pair = barycenter_computer_max_[c].getKDTree();
1855 use_kdt = true;
1856 }
1857
1858 barycenter_computer_max_[c].runMatching(
1859 &total_cost, epsilon_[2], sizes, *pair.first, pair.second,
1860 &(min_diag_price->at(2)), &(min_price->at(2)), &(all_matchings),
1861 use_kdt, only_matchings);
1862 for(size_t ii = 0; ii < all_matchings.size(); ii++) {
1863 all_matchings_per_type_and_cluster[c][2][ii].resize(
1864 all_matchings[ii].size());
1865 all_matchings_per_type_and_cluster[c][2][ii] = all_matchings[ii];
1866 }
1867 for(int ii = all_matchings.size(); ii < numberOfInputs_; ii++) {
1868 all_matchings_per_type_and_cluster[c][2][ii].resize(0);
1869 }
1870 precision_max
1871 = barycenter_computer_max_[c].isPrecisionObjectiveMet(deltaLim_, 0);
1872
1873 cost_max_ += total_cost;
1874 Timer const time_update;
1875 if(!only_matchings) {
1876 max_shift_c_max
1877 = barycenter_computer_max_[c].updateBarycenter(all_matchings);
1878 }
1879 if(max_shift_c_max > max_shift_vector[2]) {
1880 max_shift_vector[2] = max_shift_c_max;
1881 }
1882
1883 // Now that barycenters and diagrams are updated in PDBarycenter class,
1884 // we import the results here.
1885 diagrams_c_min = barycenter_computer_max_[c].getCurrentBidders();
1886 centroids_with_price_max
1887 = barycenter_computer_max_[c].getCurrentBarycenter();
1888 int i = 0;
1889 for(int const idx : clustering_[c]) {
1890 current_bidder_diagrams_max_[idx] = diagrams_c_min[i];
1891 centroids_with_price_max_[idx] = centroids_with_price_max[i];
1892 i++;
1893 }
1894 GoodDiagram const old_centroid = centroids_max_[c];
1897 if(use_accelerated_) {
1898 wasserstein_shift
1899 += computeDistance(old_centroid, centroids_max_[c], 0.01);
1900 }
1901 }
1902
1904 if(wasserstein_shift > max_wasserstein_shift) {
1905 max_wasserstein_shift = wasserstein_shift;
1906 }
1907 if(use_accelerated_) {
1908 for(int i = 0; i < numberOfInputs_; ++i) {
1909 // Step 5 of Accelerated KMeans: Update the lower bound on distance
1910 // thanks to the triangular inequality
1911 l_[i][c] = Geometry::pow(
1912 Geometry::pow(l_[i][c], 1. / wasserstein_)
1913 - Geometry::pow(wasserstein_shift, 1. / wasserstein_),
1914 wasserstein_);
1915 if(l_[i][c] < 0) {
1916 l_[i][c] = 0;
1917 }
1918 }
1919 for(int const idx : clustering_[c]) {
1920 // Step 6, update the upper bound on the distance to the centroid
1921 // thanks to the triangle inequality
1922 u_[idx] = Geometry::pow(
1923 Geometry::pow(u_[idx], 1. / wasserstein_)
1924 + Geometry::pow(wasserstein_shift, 1. / wasserstein_),
1925 wasserstein_);
1926 r_[idx] = true;
1927 }
1928 }
1929 }
1930 }
1931 // Normally return max_shift, but it seems there is a bug
1932 // yielding max_shift > 100 * max_wasserstein_shift
1933 // which should logically not really happen...
1934 // This is supposed to be only a temporary patch...
1935 precision_min_ = precision_min;
1936 precision_sad_ = precision_sad;
1937 precision_max_ = precision_max;
1938 precision_criterion_ = precision_min && precision_sad && precision_max;
1940 return max_shift_vector; // std::min(max_shift, max_wasserstein_shift);
1941}
1942
1944 for(int i = 0; i < numberOfInputs_; i++) {
1945 if(do_min_) {
1946 DiagramType *CTDiagram = &((*inputDiagramsMin_)[i]);
1947 BidderDiagram bidders;
1948 for(size_t j = 0; j < CTDiagram->size(); j++) {
1949 // Add bidder to bidders
1950 Bidder b((*CTDiagram)[j], j, lambda_);
1951
1952 b.setPositionInAuction(bidders.size());
1953 bidders.emplace_back(b);
1954 if(b.isDiagonal() || b.x_ == b.y_) {
1955 this->printMsg("Diagonal point in diagram", debug::Priority::DETAIL);
1956 }
1957 }
1958 bidder_diagrams_min_.emplace_back(bidders);
1959 current_bidder_diagrams_min_.emplace_back();
1960 centroids_with_price_min_.emplace_back();
1961 std::vector<int> ids(bidders.size(), -1);
1962 current_bidder_ids_min_.emplace_back(ids);
1963 }
1964
1965 if(do_sad_) {
1966 DiagramType *CTDiagram = &((*inputDiagramsSaddle_)[i]);
1967
1968 BidderDiagram bidders;
1969 for(size_t j = 0; j < CTDiagram->size(); j++) {
1970 // Add bidder to bidders
1971 Bidder b((*CTDiagram)[j], j, lambda_);
1972
1973 b.setPositionInAuction(bidders.size());
1974 bidders.emplace_back(b);
1975 if(b.isDiagonal() || b.x_ == b.y_) {
1976 this->printMsg("Diagonal point in diagram", debug::Priority::DETAIL);
1977 }
1978 }
1979 bidder_diagrams_saddle_.emplace_back(bidders);
1980 current_bidder_diagrams_saddle_.emplace_back();
1981 centroids_with_price_saddle_.emplace_back();
1982 std::vector<int> ids(bidders.size(), -1);
1983 current_bidder_ids_sad_.emplace_back(ids);
1984 }
1985
1986 if(do_max_) {
1987 DiagramType *CTDiagram = &((*inputDiagramsMax_)[i]);
1988
1989 BidderDiagram bidders;
1990 for(size_t j = 0; j < CTDiagram->size(); j++) {
1991 // Add bidder to bidders
1992 Bidder b((*CTDiagram)[j], j, lambda_);
1993
1994 b.setPositionInAuction(bidders.size());
1995 bidders.emplace_back(b);
1996 if(b.isDiagonal() || b.x_ == b.y_) {
1997 this->printMsg("Diagonal point in diagram", debug::Priority::DETAIL);
1998 }
1999 }
2000 bidder_diagrams_max_.emplace_back(bidders);
2001 current_bidder_diagrams_max_.emplace_back();
2002 centroids_with_price_max_.emplace_back();
2003 std::vector<int> ids(bidders.size(), -1);
2004 current_bidder_ids_max_.emplace_back(ids);
2005 }
2006 }
2007}
2008
2010 std::vector<double> &previous_min_persistence,
2011 std::vector<double> &min_persistence,
2012 std::vector<std::vector<double>> &initial_diagonal_prices,
2013 std::vector<std::vector<double>> &initial_off_diagonal_prices,
2014 std::vector<int> &min_points_to_add,
2015 bool add_points_to_barycenter,
2016 bool first_enrichment) {
2017
2018 std::vector<double> new_min_persistence = min_persistence;
2019
2020 if(!do_min_) {
2021 new_min_persistence[0] = previous_min_persistence[0];
2022 }
2023 if(!do_sad_) {
2024 new_min_persistence[1] = previous_min_persistence[1];
2025 }
2026 if(!do_max_) {
2027 new_min_persistence[2] = previous_min_persistence[2];
2028 }
2029
2030 // 1. Get size of the largest current diagram, deduce the maximal number of
2031 // points to append
2032 size_t max_diagram_size_min{};
2033 size_t max_diagram_size_sad{};
2034 size_t max_diagram_size_max{};
2035 if(do_min_) {
2036 for(int i = 0; i < numberOfInputs_; i++) {
2037 if(current_bidder_diagrams_min_[i].size() > max_diagram_size_min) {
2038 max_diagram_size_min = current_bidder_diagrams_min_[i].size();
2039 }
2040 }
2041 }
2042 if(do_sad_) {
2043 for(int i = 0; i < numberOfInputs_; i++) {
2044 if(current_bidder_diagrams_saddle_[i].size() > max_diagram_size_sad) {
2045 max_diagram_size_sad = current_bidder_diagrams_saddle_[i].size();
2046 }
2047 }
2048 }
2049 if(do_max_) {
2050 for(int i = 0; i < numberOfInputs_; i++) {
2051 if(current_bidder_diagrams_max_[i].size() > max_diagram_size_max) {
2052 max_diagram_size_max = current_bidder_diagrams_max_[i].size();
2053 }
2054 }
2055 }
2056 int const max_points_to_add_min
2057 = std::max(min_points_to_add[0],
2058 min_points_to_add[0] + (int)(max_diagram_size_min / 10));
2059 int const max_points_to_add_sad
2060 = std::max(min_points_to_add[1],
2061 min_points_to_add[1] + (int)(max_diagram_size_sad / 10));
2062 int const max_points_to_add_max
2063 = std::max(min_points_to_add[2],
2064 min_points_to_add[2] + (int)(max_diagram_size_max / 10));
2065
2066 // 2. Get which points can be added, deduce the new minimal persistence
2067 std::vector<std::vector<int>> candidates_to_be_added_min(numberOfInputs_);
2068 std::vector<std::vector<int>> candidates_to_be_added_sad(numberOfInputs_);
2069 std::vector<std::vector<int>> candidates_to_be_added_max(numberOfInputs_);
2070 std::vector<std::vector<int>> idx_min(numberOfInputs_);
2071 std::vector<std::vector<int>> idx_sad(numberOfInputs_);
2072 std::vector<std::vector<int>> idx_max(numberOfInputs_);
2073
2074 if(do_min_) {
2075 for(int i = 0; i < numberOfInputs_; i++) {
2076 std::vector<double> persistences;
2077 for(size_t j = 0; j < bidder_diagrams_min_[i].size(); j++) {
2078 Bidder const b = bidder_diagrams_min_[i].at(j);
2079 double const persistence = b.getPersistence();
2080 if(persistence >= min_persistence[0]
2081 && persistence <= previous_min_persistence[0]) {
2082 candidates_to_be_added_min[i].emplace_back(j);
2083 idx_min[i].emplace_back(idx_min[i].size());
2084 persistences.emplace_back(persistence);
2085 }
2086 }
2087 sort(
2088 idx_min[i].begin(), idx_min[i].end(), [&persistences](int &a, int &b) {
2089 return ((persistences[a] > persistences[b])
2090 || ((persistences[a] == persistences[b]) && (a > b)));
2091 });
2092 int const size = candidates_to_be_added_min[i].size();
2093 if(size >= max_points_to_add_min) {
2094 double const last_persistence_added_min
2095 = persistences[idx_min[i][max_points_to_add_min - 1]];
2096 if(first_enrichment) { // a minima min_point_to_add (=max_point_to_add)
2097 // added per diagram
2098 if(i == 0) {
2099 new_min_persistence[0] = last_persistence_added_min;
2100 } else {
2101 if(last_persistence_added_min < new_min_persistence[0])
2102 new_min_persistence[0] = last_persistence_added_min;
2103 }
2104 } else { // a maxima max_point_to_add added per diagram
2105 if(last_persistence_added_min > new_min_persistence[0]) {
2106 new_min_persistence[0] = last_persistence_added_min;
2107 }
2108 }
2109 }
2110 }
2111 }
2112
2113 if(do_sad_) {
2114 for(int i = 0; i < numberOfInputs_; i++) {
2115 std::vector<double> persistences;
2116 for(size_t j = 0; j < bidder_diagrams_saddle_[i].size(); j++) {
2117 Bidder const b = bidder_diagrams_saddle_[i].at(j);
2118 double const persistence = b.getPersistence();
2119 if(persistence >= min_persistence[1]
2120 && persistence <= previous_min_persistence[1]) {
2121 candidates_to_be_added_sad[i].emplace_back(j);
2122 idx_sad[i].emplace_back(idx_sad[i].size());
2123 persistences.emplace_back(persistence);
2124 }
2125 }
2126 sort(
2127 idx_sad[i].begin(), idx_sad[i].end(), [&persistences](int &a, int &b) {
2128 return ((persistences[a] > persistences[b])
2129 || ((persistences[a] == persistences[b]) && (a > b)));
2130 });
2131 int const size = candidates_to_be_added_sad[i].size();
2132 if(size >= max_points_to_add_sad) {
2133 double const last_persistence_added_sad
2134 = persistences[idx_sad[i][max_points_to_add_sad - 1]];
2135 if(first_enrichment) { // a minima min_point_to_add (=max_point_to_add)
2136 // added per diagram
2137 if(i == 0) {
2138 new_min_persistence[1] = last_persistence_added_sad;
2139 } else {
2140 if(last_persistence_added_sad < new_min_persistence[1])
2141 new_min_persistence[1] = last_persistence_added_sad;
2142 }
2143 } else { // a maxima max_point_to_add added per diagram
2144 if(last_persistence_added_sad > new_min_persistence[1]) {
2145 new_min_persistence[1] = last_persistence_added_sad;
2146 }
2147 }
2148 }
2149 }
2150 }
2151 if(do_max_) {
2152 for(int i = 0; i < numberOfInputs_; i++) {
2153 std::vector<double> persistences;
2154 for(size_t j = 0; j < bidder_diagrams_max_[i].size(); j++) {
2155 Bidder const b = bidder_diagrams_max_[i].at(j);
2156 double const persistence = b.getPersistence();
2157 if(persistence >= min_persistence[2]
2158 && persistence <= previous_min_persistence[2]) {
2159 candidates_to_be_added_max[i].emplace_back(j);
2160 idx_max[i].emplace_back(idx_max[i].size());
2161 persistences.emplace_back(persistence);
2162 }
2163 }
2164 sort(
2165 idx_max[i].begin(), idx_max[i].end(), [&persistences](int &a, int &b) {
2166 return ((persistences[a] > persistences[b])
2167 || ((persistences[a] == persistences[b]) && (a > b)));
2168 });
2169 int const size = candidates_to_be_added_max[i].size();
2170 if(size >= max_points_to_add_max) {
2171 double const last_persistence_added_max
2172 = persistences[idx_max[i][max_points_to_add_max - 1]];
2173 if(first_enrichment) { // a minima min_point_to_add (=max_point_to_add)
2174 // added per diagram
2175 if(i == 0) {
2176 new_min_persistence[2] = last_persistence_added_max;
2177 } else {
2178 if(last_persistence_added_max < new_min_persistence[2])
2179 new_min_persistence[2] = last_persistence_added_max;
2180 }
2181 } else { // a maxima max_point_to_add added per diagram
2182 if(last_persistence_added_max > new_min_persistence[2]) {
2183 new_min_persistence[2] = last_persistence_added_max;
2184 }
2185 }
2186 }
2187 }
2188 }
2189
2190 // 3. Add the points to the current diagrams
2191 if(do_min_) {
2192 int counter_for_adding_points = 0;
2193 for(int i = 0; i < numberOfInputs_; i++) {
2194 int const size = candidates_to_be_added_min[i].size();
2195 for(int j = 0; j < std::min(max_points_to_add_min, size); j++) {
2196 Bidder b = bidder_diagrams_min_[i].at(
2197 candidates_to_be_added_min[i][idx_min[i][j]]);
2198 double const persistence = b.getPersistence();
2199 if(persistence >= new_min_persistence[0]) {
2200 b.id_ = current_bidder_diagrams_min_[i].size();
2202 b.setDiagonalPrice(initial_diagonal_prices[0][i]);
2203 current_bidder_diagrams_min_[i].emplace_back(b);
2205 [candidates_to_be_added_min[i][idx_min[i][j]]]
2206 = current_bidder_diagrams_min_[i].size() - 1;
2207
2208 if(use_accelerated_ && n_iterations_ > 0) {
2209 for(int c = 0; c < k_; ++c) {
2210 // Step 5 of Accelerated KMeans: Update the lower bound on
2211 // distance thanks to the triangular inequality
2212 l_[i][c]
2214 - persistence / sqrt(2),
2215 wasserstein_);
2216 if(l_[i][c] < 0) {
2217 l_[i][c] = 0;
2218 }
2219 }
2220 // Step 6, update the upper bound on the distance to the centroid
2221 // thanks to the triangle inequality
2222 u_[i] = Geometry::pow(
2223 Geometry::pow(u_[i], 1. / wasserstein_) + persistence / sqrt(2),
2224 wasserstein_);
2225 r_[i] = true;
2226 }
2227 int const to_be_added_to_barycenter
2228 = deterministic_ ? counter_for_adding_points % numberOfInputs_
2229 : rand() % numberOfInputs_;
2230 if(to_be_added_to_barycenter == 0 && add_points_to_barycenter) {
2231 for(int k = 0; k < numberOfInputs_; k++) {
2232 if(inv_clustering_[i] == inv_clustering_[k]) {
2233 Good g = Good(
2234 b.x_, b.y_, false, centroids_with_price_min_[k].size());
2235 g.setPrice(initial_off_diagonal_prices[0][k]);
2237 b.coords_[0], b.coords_[1], b.coords_[2]);
2238 centroids_with_price_min_[k].emplace_back(g);
2239 }
2240 }
2241 Good g = Good(
2242 b.x_, b.y_, false, centroids_min_[inv_clustering_[i]].size());
2243 g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
2244 centroids_min_[inv_clustering_[i]].emplace_back(g);
2245 }
2246 }
2247 counter_for_adding_points++;
2248 }
2249 }
2250 }
2251 if(do_sad_) {
2252 int counter_for_adding_points = 0;
2253 for(int i = 0; i < numberOfInputs_; i++) {
2254 int const size = candidates_to_be_added_sad[i].size();
2255 for(int j = 0; j < std::min(max_points_to_add_sad, size); j++) {
2257 candidates_to_be_added_sad[i][idx_sad[i][j]]);
2258 double const persistence = b.getPersistence();
2259 if(persistence >= new_min_persistence[1]) {
2262 b.setDiagonalPrice(initial_diagonal_prices[1][i]);
2263 current_bidder_diagrams_saddle_[i].emplace_back(b);
2265 [candidates_to_be_added_sad[i][idx_sad[i][j]]]
2266 = current_bidder_diagrams_saddle_[i].size() - 1;
2267
2268 if(use_accelerated_ && n_iterations_ > 0) {
2269 for(int c = 0; c < k_; ++c) {
2270 // Step 5 of Accelerated KMeans: Update the lower bound on
2271 // distance thanks to the triangular inequality
2272 l_[i][c]
2274 - persistence / sqrt(2),
2275 wasserstein_);
2276 if(l_[i][c] < 0) {
2277 l_[i][c] = 0;
2278 }
2279 }
2280 // Step 6, update the upper bound on the distance to the centroid
2281 // thanks to the triangle inequality
2282 u_[i] = Geometry::pow(
2283 Geometry::pow(u_[i], 1. / wasserstein_) + persistence / sqrt(2),
2284 wasserstein_);
2285 r_[i] = true;
2286 }
2287 int const to_be_added_to_barycenter
2288 = deterministic_ ? counter_for_adding_points % numberOfInputs_
2289 : rand() % numberOfInputs_;
2290 if(to_be_added_to_barycenter == 0 && add_points_to_barycenter) {
2291 for(int k = 0; k < numberOfInputs_; k++) {
2292 if(inv_clustering_[i] == inv_clustering_[k]) {
2293 Good g = Good(
2294 b.x_, b.y_, false, centroids_with_price_saddle_[k].size());
2295 g.setPrice(initial_off_diagonal_prices[1][k]);
2297 b.coords_[0], b.coords_[1], b.coords_[2]);
2298 centroids_with_price_saddle_[k].emplace_back(g);
2299 }
2300 }
2301 }
2302 }
2303 counter_for_adding_points++;
2304 }
2305 }
2306 }
2307 if(do_max_) {
2308 int counter_for_adding_points = 0;
2309 for(int i = 0; i < numberOfInputs_; i++) {
2310 int const size = candidates_to_be_added_max[i].size();
2311 for(int j = 0; j < std::min(max_points_to_add_max, size); j++) {
2312 Bidder b = bidder_diagrams_max_[i].at(
2313 candidates_to_be_added_max[i][idx_max[i][j]]);
2314 double const persistence = b.getPersistence();
2315 if(persistence >= new_min_persistence[2]) {
2316 b.id_ = current_bidder_diagrams_max_[i].size();
2318 b.setDiagonalPrice(initial_diagonal_prices[2][i]);
2319 current_bidder_diagrams_max_[i].emplace_back(b);
2321 [candidates_to_be_added_max[i][idx_max[i][j]]]
2322 = current_bidder_diagrams_max_[i].size() - 1;
2323
2324 if(use_accelerated_ && n_iterations_ > 0) {
2325 for(int c = 0; c < k_; ++c) {
2326 // Step 5 of Accelerated KMeans: Update the lower bound on
2327 // distance thanks to the triangular inequality
2328 l_[i][c]
2330 - persistence / sqrt(2),
2331 wasserstein_);
2332 if(l_[i][c] < 0) {
2333 l_[i][c] = 0;
2334 }
2335 }
2336 // Step 6, update the upper bound on the distance to the centroid
2337 // thanks to the triangle inequality
2338 u_[i] = Geometry::pow(
2339 Geometry::pow(u_[i], 1. / wasserstein_) + persistence / sqrt(2),
2340 wasserstein_);
2341 r_[i] = true;
2342 }
2343 int const to_be_added_to_barycenter
2344 = deterministic_ ? counter_for_adding_points % numberOfInputs_
2345 : rand() % numberOfInputs_;
2346 if(to_be_added_to_barycenter == 0 && add_points_to_barycenter) {
2347 for(int k = 0; k < numberOfInputs_; k++) {
2348 if(inv_clustering_[i] == inv_clustering_[k]) {
2349 Good g = Good(
2350 b.x_, b.y_, false, centroids_with_price_max_[k].size());
2351 g.setPrice(initial_off_diagonal_prices[2][k]);
2353 b.coords_[0], b.coords_[1], b.coords_[2]);
2354 centroids_with_price_max_[k].emplace_back(g);
2355 }
2356 }
2357 Good g = Good(
2358 b.x_, b.y_, false, centroids_max_[inv_clustering_[i]].size());
2359 g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
2360 centroids_max_[inv_clustering_[i]].emplace_back(g);
2361 }
2362 }
2363 counter_for_adding_points++;
2364 }
2365 }
2366 }
2367
2368 return new_min_persistence;
2369}
2370
2372 std::vector<double> & /*min_persistence*/) {
2373
2374 if(do_min_) {
2376 for(int c = 0; c < k_; c++) {
2377 std::vector<BidderDiagram> diagrams_c;
2378 for(int const idx : clustering_[c]) {
2379 diagrams_c.emplace_back(current_bidder_diagrams_min_[idx]);
2380 }
2382 barycenter_computer_min_[c].setThreadNumber(threadNumber_);
2383 barycenter_computer_min_[c].setWasserstein(wasserstein_);
2384 barycenter_computer_min_[c].setDiagramType(0);
2385 barycenter_computer_min_[c].setUseProgressive(false);
2386 barycenter_computer_min_[c].setDeterministic(true);
2387 barycenter_computer_min_[c].setGeometricalFactor(geometrical_factor_);
2388 barycenter_computer_min_[c].setDebugLevel(debugLevel_);
2389 barycenter_computer_min_[c].setNumberOfInputs(diagrams_c.size());
2390 barycenter_computer_min_[c].setCurrentBidders(diagrams_c);
2391 barycenter_computer_min_[c].setNonMatchingWeight(nonMatchingWeight_);
2392 }
2393 }
2394 if(do_sad_) {
2396 for(int c = 0; c < k_; c++) {
2397 std::vector<BidderDiagram> diagrams_c;
2398 for(int const idx : clustering_[c]) {
2399 diagrams_c.emplace_back(current_bidder_diagrams_saddle_[idx]);
2400 }
2402 barycenter_computer_sad_[c].setThreadNumber(threadNumber_);
2403 barycenter_computer_sad_[c].setWasserstein(wasserstein_);
2404 barycenter_computer_sad_[c].setDiagramType(1);
2405 barycenter_computer_sad_[c].setUseProgressive(false);
2406 barycenter_computer_sad_[c].setDeterministic(true);
2407 barycenter_computer_sad_[c].setGeometricalFactor(geometrical_factor_);
2408 barycenter_computer_sad_[c].setDebugLevel(debugLevel_);
2409 barycenter_computer_sad_[c].setNumberOfInputs(diagrams_c.size());
2410 barycenter_computer_sad_[c].setCurrentBidders(diagrams_c);
2411 barycenter_computer_sad_[c].setNonMatchingWeight(nonMatchingWeight_);
2412
2413 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
2414 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
2415 i_diagram++) {
2416 barycenter_goods[i_diagram]
2418 }
2419 barycenter_computer_sad_[c].setCurrentBarycenter(barycenter_goods);
2420 }
2421 }
2422 if(do_max_) {
2424 for(int c = 0; c < k_; c++) {
2425 std::vector<BidderDiagram> diagrams_c;
2426 for(int const idx : clustering_[c]) {
2427 diagrams_c.emplace_back(current_bidder_diagrams_max_[idx]);
2428 }
2431 barycenter_computer_max_[c].setThreadNumber(threadNumber_);
2432 barycenter_computer_max_[c].setWasserstein(wasserstein_);
2433 barycenter_computer_max_[c].setDiagramType(2);
2434 barycenter_computer_max_[c].setUseProgressive(false);
2435 barycenter_computer_max_[c].setDeterministic(true);
2436 barycenter_computer_max_[c].setGeometricalFactor(geometrical_factor_);
2437 barycenter_computer_max_[c].setDebugLevel(debugLevel_);
2438 barycenter_computer_max_[c].setNumberOfInputs(diagrams_c.size());
2439 barycenter_computer_max_[c].setCurrentBidders(diagrams_c);
2440 barycenter_computer_max_[c].setNonMatchingWeight(nonMatchingWeight_);
2441
2442 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
2443 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
2444 i_diagram++) {
2445 barycenter_goods[i_diagram]
2446 = centroids_with_price_max_[clustering_[c][i_diagram]];
2447 }
2448 barycenter_computer_max_[c].setCurrentBarycenter(barycenter_goods);
2449 }
2450 }
2451}
2452
2454 std::ofstream ufile("u_vec.txt");
2455 std::ofstream lfile("l_mat.txt");
2456 std::ofstream approx_file("a_mat.txt");
2457 if(ufile.is_open() && lfile.is_open()) {
2458 for(int i = 0; i < numberOfInputs_; i++) {
2459 ufile << u_[i] << " ";
2460 for(int j = 0; j < k_; j++) {
2461 lfile << l_[i][j] << " ";
2462 }
2463 lfile << "\n";
2464 }
2465 }
2466
2467 for(int c = 0; c < k_; c++) {
2468 for(int const i : clustering_[c]) {
2469 approx_file << (u_[i] + l_[i][c]) / 2 << " ";
2470 }
2471 approx_file << "\n";
2472 }
2473 lfile.close();
2474 ufile.close();
2475 approx_file.close();
2476}
2477
2479 std::cout << "Computing real distances to every clusters" << std::endl;
2480 std::ofstream file("a_real_mat.txt");
2481 if(file.is_open()) {
2482 for(int c = 0; c < k_; c++) {
2483 for(int const i : clustering_[c]) {
2484 file << distanceToCentroid_[i] << " ";
2485 }
2486 file << "\n";
2487 }
2488 file.close();
2489 } else {
2490 std::cout << "file not open" << std::endl;
2491 }
2492}
2493
2495 std::ofstream file(
2496 "prices_evolution.txt", std::ofstream::out | std::ofstream::app);
2497 if(file.is_open()) {
2498 file << "\nITERATION " << iteration << "\n" << std::endl;
2499 for(int i = 0; i < k_; i++) {
2500 file << "\ncentroid " << i << std::endl;
2501
2502 for(size_t j = 0; j < centroids_with_price_max_[i].size(); j++) {
2503 Good const g = centroids_with_price_max_[i].at(j);
2504 file << g.getPrice() << " ";
2505 }
2506 }
2507 }
2508 file.close();
2509}
2510
2512 double total_real_cost_min = 0;
2513 double total_real_cost_max = 0;
2514 double total_real_cost_sad = 0;
2515 double sq_distance;
2516 if(original_dos[0]) {
2517 for(int c = 0; c < k_; c++) {
2518 double real_cost_cluster = 0;
2519 for(int i = 0; i < numberOfInputs_; i++) {
2520 GoodDiagram const current_barycenter
2522 sq_distance
2523 = computeDistance(bidder_diagrams_min_[i], current_barycenter, 0.01);
2524 real_cost_cluster += sq_distance;
2525 }
2526 total_real_cost_min += real_cost_cluster;
2527 }
2528 }
2529 if(original_dos[1]) {
2530 for(int c = 0; c < k_; c++) {
2531 double real_cost_cluster = 0;
2532 for(int i = 0; i < numberOfInputs_; i++) {
2533 GoodDiagram const current_barycenter
2535 sq_distance = computeDistance(
2536 bidder_diagrams_saddle_[i], current_barycenter, 0.01);
2537 real_cost_cluster += sq_distance;
2538 }
2539 total_real_cost_sad += real_cost_cluster;
2540 }
2541 }
2542 if(original_dos[2]) {
2543 for(int c = 0; c < k_; c++) {
2544 double real_cost_cluster = 0;
2545 for(int i = 0; i < numberOfInputs_; i++) {
2546 GoodDiagram const current_barycenter
2548 sq_distance
2549 = computeDistance(bidder_diagrams_max_[i], current_barycenter, 0.01);
2550 real_cost_cluster += sq_distance;
2551 }
2552 total_real_cost_max += real_cost_cluster;
2553 }
2554 }
2555 return total_real_cost_min + total_real_cost_sad + total_real_cost_max;
2556}
2557
2559 std::vector<std::vector<std::vector<std::vector<MatchingType>>>>
2560 &all_matchings_per_type_and_cluster) {
2561
2562 if(do_min_) {
2564 all_matchings_per_type_and_cluster[0][0], current_bidder_ids_min_,
2566 }
2567 if(do_sad_) {
2568 computeBarycenterForTwo(all_matchings_per_type_and_cluster[0][1],
2572 }
2573 if(do_max_) {
2575 all_matchings_per_type_and_cluster[0][2], current_bidder_ids_max_,
2577 }
2578}
2579
2581 std::vector<std::vector<MatchingType>> &matchings,
2582 std::vector<std::vector<int>> &bidders_ids,
2583 std::vector<BidderDiagram> &current_bidder_diagrams,
2584 std::vector<BidderDiagram> &bidder_diagrams,
2585 GoodDiagram &barycenter) {
2586
2587 auto &matchings0 = matchings[0];
2588 auto &diagram0 = bidder_diagrams[0];
2589 auto &current_diagram0 = current_bidder_diagrams[0];
2590 auto &ids0 = bidders_ids[0];
2591
2592 auto &matchings1 = matchings[1];
2593 auto &diagram1 = bidder_diagrams[1];
2594 auto &current_diagram1 = current_bidder_diagrams[1];
2595 auto &ids1 = bidders_ids[1];
2596
2597 std::vector<int> new_to_old_id(current_diagram1.size());
2598 // 1. Invert the current_bidder_ids_ vector
2599 for(size_t j = 0; j < ids1.size(); j++) {
2600 int const new_id = ids1[j];
2601 if(new_id >= 0) {
2602 new_to_old_id[new_id] = j;
2603 }
2604 }
2605
2606 std::vector<MatchingType> matching_to_add(0);
2607 std::vector<MatchingType> matching_to_add2(0);
2608
2609 for(size_t i = 0; i < matchings1.size(); i++) {
2610 MatchingType &t = matchings1[i];
2611 int const bidderId = std::get<0>(t);
2612 int const goodId = std::get<1>(t);
2613
2614 if(bidderId >= 0) {
2615 Bidder const b = diagram1.at(new_to_old_id[bidderId]);
2616 double const bx = b.x_;
2617 double const by = b.y_;
2618 if(goodId >= 0) {
2619 Good const g = barycenter.at(goodId);
2620 double const gx = g.x_;
2621 double const gy = g.y_;
2622 barycenter.at(goodId).x_ = (bx + gx) / 2;
2623 barycenter.at(goodId).y_ = (by + gy) / 2;
2624 // divide by 4 in order to display the cost of the half matching
2625 // i.e. the cost of matching to the barycenter
2626 std::get<2>(t) /= 4;
2627
2628 } else {
2629 double gx = (bx + by) / 2;
2630 double gy = (bx + by) / 2;
2631 gx = (gx + bx) / 2;
2632 gy = (gy + by) / 2;
2633 double const cost = nonMatchingWeight_
2634 * (Geometry::pow((gx - bx), wasserstein_)
2635 + Geometry::pow((gy - by), wasserstein_));
2636 MatchingType const t2
2637 = std::make_tuple(bidderId, barycenter.size(), cost);
2638 MatchingType const t3 = std::make_tuple(-1, barycenter.size(), cost);
2639 Good const g = Good(gx, gy, false, barycenter.size());
2640 // g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
2641 barycenter.emplace_back(g);
2642 matching_to_add.emplace_back(t2);
2643 matching_to_add2.emplace_back(t3);
2644 }
2645 } else {
2646 if(goodId >= 0) {
2647 Good const g = barycenter.at(goodId);
2648 double const gx = (g.x_ + g.y_) / 2;
2649 double const gy = (g.x_ + g.y_) / 2;
2650 barycenter.at(goodId).x_ = (gx + g.x_) / 2;
2651 barycenter.at(goodId).y_ = (gy + g.y_) / 2;
2652 std::get<2>(t) /= 4;
2653 }
2654 }
2655 }
2656 for(size_t j = 0; j < matching_to_add.size(); j++) {
2657 matchings1.emplace_back(matching_to_add[j]);
2658 }
2659 for(size_t j = 0; j < matching_to_add2.size(); j++) {
2660 matchings0.emplace_back(matching_to_add2[j]);
2661 }
2662
2663 // correct the costs of matchings in diagram 0
2664 // costs are initially allzeros because the barycenter is identical
2665 // to diagram 0
2666 std::vector<int> new_to_old_id2(current_diagram0.size());
2667 // 1. Invert the current_bidder_ids_ vector
2668 for(size_t j = 0; j < ids0.size(); j++) {
2669 int const new_id = ids0[j];
2670 if(new_id >= 0) {
2671 new_to_old_id2[new_id] = j;
2672 }
2673 }
2674
2675 for(size_t i = 0; i < matchings0.size(); i++) {
2676 MatchingType &t = matchings0[i];
2677 int const bidderId = std::get<0>(t);
2678 int const goodId = std::get<1>(t);
2679
2680 if(bidderId >= 0 and goodId >= 0) {
2681 Bidder const b = diagram0.at(new_to_old_id2[bidderId]);
2682 double const bx = b.x_;
2683 double const by = b.y_;
2684 Good const g = barycenter.at(goodId);
2685 double const gx = g.x_;
2686 double const gy = g.y_;
2687 double const cost = Geometry::pow((gx - bx), wasserstein_)
2688 + Geometry::pow((gy - by), wasserstein_);
2689 std::get<2>(t) = cost;
2690 }
2691 }
2692}
void setDiagonalPrice(const double price)
void setPositionInAuction(const int pos)
int debugLevel_
Definition Debug.h:379
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
void setPrice(const double price)
std::pair< typename KDT::KDTreeRoot, typename KDT::KDTreeMap > KDTreePair
std::vector< std::vector< int > > old_clustering_
void initializeAcceleratedKMeans()
std::vector< double > enrichCurrentBidderDiagrams(std::vector< double > &previous_min_persistence, std::vector< double > &min_persistence, std::vector< std::vector< double > > &initial_diagonal_prices, std::vector< std::vector< double > > &initial_off_diagonal_prices, std::vector< int > &min_points_to_add, bool add_points_to_barycenter, bool first_enrichment)
std::vector< int > inv_clustering_
std::vector< double > u_
std::vector< bool > r_
double getLessPersistent(int type=-1)
std::vector< DiagramType > * inputDiagramsMax_
void computeBarycenterForTwo(std::vector< std::vector< MatchingType > > &matchings, std::vector< std::vector< int > > &bidders_ids, std::vector< BidderDiagram > &current_bidder_diagrams, std::vector< BidderDiagram > &bidder_diagrams, GoodDiagram &barycenter)
std::vector< std::vector< double > > centroidsDistanceMatrix_
std::vector< std::vector< double > > l_
std::vector< BidderDiagram > current_bidder_diagrams_saddle_
std::vector< PDBarycenter > barycenter_computer_min_
BidderDiagram centroidToDiagram(const GoodDiagram &centroid)
void initializeCentroidsKMeanspp()
double computeDistance(const BidderDiagram &D1, const BidderDiagram &D2, const double delta_lim)
std::vector< BidderDiagram > current_bidder_diagrams_min_
std::vector< BidderDiagram > bidder_diagrams_saddle_
std::vector< BidderDiagram > current_bidder_diagrams_max_
std::vector< PDBarycenter > barycenter_computer_max_
bool barycenter_inputs_reset_flag
std::vector< double > updateCentroidsPosition(std::vector< std::vector< double > > *min_price, std::vector< std::vector< double > > *min_diag_price, std::vector< std::vector< std::vector< std::vector< MatchingType > > > > &all_matchings, int only_matchings)
std::vector< GoodDiagram > centroids_with_price_min_
void printPricesToFile(int)
BidderDiagram diagramWithZeroPrices(const BidderDiagram &diagram)
double getMostPersistent(int type=-1)
std::vector< std::vector< int > > clustering_
std::vector< GoodDiagram > centroids_min_
GoodDiagram diagramToCentroid(const BidderDiagram &diagram)
std::vector< double > distanceToCentroid_
std::vector< PDBarycenter > barycenter_computer_sad_
std::vector< std::vector< int > > current_bidder_ids_sad_
std::array< double, 3 > epsilon_
std::vector< BidderDiagram > bidder_diagrams_min_
std::vector< BidderDiagram > bidder_diagrams_max_
std::vector< GoodDiagram > centroids_saddle_
std::vector< std::vector< double > > getMinDiagonalPrices()
void computeBarycenterForTwoGlobal(std::vector< std::vector< std::vector< std::vector< MatchingType > > > > &)
std::vector< std::vector< int > > centroids_sizes_
std::vector< std::vector< double > > getMinPrices()
void printMatchings(std::vector< std::vector< std::vector< MatchingType > > >)
std::vector< std::vector< double > > getDistanceMatrix()
void initializeBarycenterComputers(std::vector< double > &min_persistence)
std::vector< std::vector< int > > current_bidder_ids_min_
GoodDiagram centroidWithZeroPrices(const GoodDiagram &centroid)
std::vector< GoodDiagram > centroids_with_price_max_
std::vector< std::vector< int > > current_bidder_ids_max_
void resetDosToOriginalValues()
std::vector< GoodDiagram > centroids_max_
std::vector< int > execute(std::vector< DiagramType > &final_centroids, std::vector< std::vector< std::vector< std::vector< MatchingType > > > > &all_matchings)
std::array< bool, 3 > original_dos
std::vector< std::vector< int > > get_centroids_sizes()
void correctMatchings(std::vector< std::vector< std::vector< std::vector< MatchingType > > > > &previous_matchings)
std::vector< GoodDiagram > centroids_with_price_saddle_
void SetCriticalCoordinates(const float coords_x, const float coords_y, const float coords_z)
std::array< float, 3 > GetCriticalCoordinates() const
double run(std::vector< MatchingType > &matchings, const int kdt_index=0)
void BuildAuctionDiagrams(const BidderDiagram &BD, const GoodDiagram &GD)
double getElapsedTime()
Definition Timer.h:15
T1 pow(const T1 val, const T2 n)
Definition Geometry.h:456
CriticalType
default value for critical index
Definition DataTypes.h:88
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
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)