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
308 if(cost_min_ < min_cost_min && n_iterations_ > 2
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
319 if(cost_sad_ < min_cost_sad && n_iterations_ > 2
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
330 if(cost_max_ < min_cost_max && n_iterations_ > 2
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{
433 CriticalVertex{0, CriticalType::Local_maximum, g.y_, critCoords}, 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{
441 CriticalVertex{0, CriticalType::Local_maximum, g.y_, critCoords}, 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{
452 CriticalVertex{0, CriticalType::Saddle1, g.y_, critCoords}, 0, true});
453 if(g.getPersistence() > 1000) {
454 this->printMsg("Found a abnormally high persistence in min diagram",
456 }
457 }
458 }
459
460 if(do_sad_) {
461 for(size_t i = 0; i < centroids_saddle_[c].size(); ++i) {
462 Good const &g = centroids_saddle_[c].at(i);
463 const auto &critCoords = g.GetCriticalCoordinates();
464 final_centroids[c].emplace_back(PersistencePair{
465 CriticalVertex{0, CriticalType::Saddle1, g.x_, critCoords},
466 CriticalVertex{0, CriticalType::Saddle2, g.y_, critCoords}, 1, true});
467 if(g.getPersistence() > 1000) {
468 this->printMsg("Found a abnormally high persistence in sad diagram",
470 }
471 }
472 }
473
474 if(do_max_) {
475 for(size_t i = addedFirstPairMax; i < centroids_max_[c].size(); ++i) {
476 Good const &g = centroids_max_[c].at(i);
477 const auto &critCoords = g.GetCriticalCoordinates();
478 ttk::CriticalType saddle_type;
479 if(do_sad_)
480 saddle_type = ttk::CriticalType::Saddle2;
481 else
482 saddle_type = ttk::CriticalType::Saddle1;
483
484 final_centroids[c].emplace_back(PersistencePair{
485 CriticalVertex{0, saddle_type, g.x_, critCoords},
486 CriticalVertex{0, CriticalType::Local_maximum, g.y_, critCoords}, 2,
487 true});
488
489 if(g.getPersistence() > 1000) {
490 this->printMsg("Found a abnormally high persistence in min diagram",
492 }
493 }
494 }
495 }
496
497 if(distanceWritingOptions_ == 1) {
499 } else if(distanceWritingOptions_ == 2) {
501 }
502
503 return inv_clustering_;
504}
505
507 std::vector<std::vector<std::vector<std::vector<MatchingType>>>>
508 &previous_matchings) {
509 for(int c = 0; c < k_; c++) {
510 for(size_t i = 0; i < clustering_[c].size(); i++) {
511 int const diagram_id = clustering_[c][i];
512 if(original_dos[0]) {
513 // 1. Invert the current_bidder_ids_ vector
514 std::vector<int> new_to_old_id(
515 current_bidder_diagrams_min_[diagram_id].size(), -1);
516 for(size_t j = 0; j < current_bidder_ids_min_[diagram_id].size(); j++) {
517 int const new_id = current_bidder_ids_min_[diagram_id][j];
518 if(new_id >= 0) {
519 new_to_old_id[new_id] = j;
520 }
521 }
522 // 2. Reconstruct the matchings
523 std::vector<MatchingType> matchings_diagram_i;
524 for(size_t j = 0; j < previous_matchings[c][0][i].size(); j++) {
525 MatchingType m = previous_matchings[c][0][i][j];
526 int const new_id = std::get<0>(m);
527 if(new_id >= 0 && std::get<1>(m) >= 0) {
528 std::get<0>(m) = new_to_old_id[new_id];
529 matchings_diagram_i.emplace_back(m);
530 } else if(std::get<1>(m)
531 >= 0) { // new_id < 0 corresponds to a diagonal matching
532 std::get<0>(m) = -1;
533 matchings_diagram_i.emplace_back(m);
534 }
535 }
536 previous_matchings[c][0][i].resize(matchings_diagram_i.size());
537 previous_matchings[c][0][i] = matchings_diagram_i;
538 }
539 if(original_dos[1]) {
540 // 1. Invert the current_bidder_ids_ vector
541 std::vector<int> new_to_old_id(
542 current_bidder_diagrams_saddle_[diagram_id].size());
543 for(size_t j = 0; j < current_bidder_ids_sad_[diagram_id].size(); j++) {
544 int const new_id = current_bidder_ids_sad_[diagram_id][j];
545 if(new_id >= 0) {
546 new_to_old_id[new_id] = j;
547 }
548 }
549 // 2. Reconstruct the matchings
550 int zero_done = 0;
551 std::vector<MatchingType> matchings_diagram_i;
552 for(size_t j = 0; j < previous_matchings[c][1][i].size(); j++) {
553 MatchingType m = previous_matchings[c][1][i][j];
554 int const new_id = std::get<0>(m);
555 if(new_id >= 0 && std::get<1>(m) >= 0) {
556 int const old_id = new_to_old_id[new_id];
557 if(old_id > 0) {
558 std::get<0>(m) = old_id;
559 matchings_diagram_i.emplace_back(m);
560 } else {
561 if(!zero_done) {
562 zero_done = 1;
563 std::get<0>(m) = old_id;
564 matchings_diagram_i.emplace_back(m);
565 }
566 }
567 } else if(std::get<1>(m)
568 >= 0) { // new_id < 0 corresponds to a diagonal matching
569 std::get<0>(m) = -1;
570 matchings_diagram_i.emplace_back(m);
571 }
572 }
573 previous_matchings[c][1][i].resize(matchings_diagram_i.size());
574 previous_matchings[c][1][i] = matchings_diagram_i;
575 }
576 if(original_dos[2]) {
577 // 1. Invert the current_bidder_ids_ vector
578 std::vector<int> new_to_old_id(
579 current_bidder_diagrams_max_[diagram_id].size());
580 for(size_t j = 0; j < current_bidder_ids_max_[diagram_id].size(); j++) {
581 int const new_id = current_bidder_ids_max_[diagram_id][j];
582 if(new_id >= 0) {
583 new_to_old_id[new_id] = j;
584 }
585 }
586 // 2. Reconstruct the matchings
587 int zero_done = 0;
588 std::vector<MatchingType> matchings_diagram_i;
589 for(size_t j = 0; j < previous_matchings[c][2][i].size(); j++) {
590 MatchingType m = previous_matchings[c][2][i][j];
591 int const new_id = std::get<0>(m);
592 if(new_id >= 0 && std::get<1>(m) >= 0) {
593 int const old_id = new_to_old_id[new_id];
594 if(old_id > 0) {
595 std::get<0>(m) = old_id;
596 matchings_diagram_i.emplace_back(m);
597 } else {
598 if(!zero_done) {
599 zero_done = 1;
600 std::get<0>(m) = old_id;
601 matchings_diagram_i.emplace_back(m);
602 }
603 }
604 } else if(std::get<1>(m)
605 >= 0) { // new_id < 0 corresponds to a diagonal matching
606 std::get<0>(m) = -1;
607 matchings_diagram_i.emplace_back(m);
608 }
609 }
610 previous_matchings[c][2][i].resize(matchings_diagram_i.size());
611 previous_matchings[c][2][i] = matchings_diagram_i;
612 }
613 }
614 }
615}
616
618 std::vector<std::vector<std::vector<MatchingType>>> matchings) {
619 std::cout << "\n MATCHINGS : " << std::endl;
620 for(int d = 0; d < 3; d++) {
621 if(original_dos[d]) {
622 std::cout << "\n Diagram type : " << d << std::endl;
623 for(size_t i = 0; i < matchings[d].size(); i++) {
624 std::cout << " diagram " << i << " : ";
625 for(size_t j = 0; j < matchings[d][i].size(); j++) {
626 std::cout << std::get<0>(matchings[d][i][j]) << " ";
627 std::cout << std::get<1>(matchings[d][i][j]) << " ";
628 std::cout << std::get<2>(matchings[d][i][j]) << " | ";
629 }
630 std::cout << "\n";
631 }
632 }
633 }
634}
635
636std::vector<std::vector<int>> ttk::PDClustering::get_centroids_sizes() {
637 return centroids_sizes_;
638}
639
641 double max_persistence = 0;
642
643 if(do_min_ && (type == -1 || type == 0)) {
644 for(size_t i = 0; i < bidder_diagrams_min_.size(); ++i) {
645 for(size_t j = 0; j < bidder_diagrams_min_[i].size(); ++j) {
646 Bidder const b = bidder_diagrams_min_[i].at(j);
647 double const persistence = b.getPersistence();
648 if(persistence > max_persistence) {
649 max_persistence = persistence;
650 }
651 }
652 }
653 }
654
655 if(do_sad_ && (type == -1 || type == 1)) {
656 for(size_t i = 0; i < bidder_diagrams_saddle_.size(); ++i) {
657 for(size_t j = 0; j < bidder_diagrams_saddle_[i].size(); ++j) {
658 Bidder const b = bidder_diagrams_saddle_[i].at(j);
659 double const persistence = b.getPersistence();
660 if(persistence > max_persistence) {
661 max_persistence = persistence;
662 }
663 }
664 }
665 }
666
667 if(do_max_ && (type == -1 || type == 2)) {
668 for(size_t i = 0; i < bidder_diagrams_max_.size(); ++i) {
669 for(size_t j = 0; j < bidder_diagrams_max_[i].size(); ++j) {
670 Bidder const b = bidder_diagrams_max_[i].at(j);
671 double const persistence = b.getPersistence();
672 if(persistence > max_persistence) {
673 max_persistence = persistence;
674 }
675 }
676 }
677 }
678 return max_persistence;
679}
680
682 // type == -1 : query the min of all the types of diagrams.
683 // type = 0 : min, 1 : sad, 2 : max
684
685 double min_persistence = std::numeric_limits<double>::max();
686 if(do_min_ && (type == -1 || type == 0)) {
687 for(size_t i = 0; i < bidder_diagrams_min_.size(); ++i) {
688 for(size_t j = 0; j < bidder_diagrams_min_[i].size(); ++j) {
689 Bidder const b = bidder_diagrams_min_[i].at(j);
690 double const persistence = b.getPersistence();
691 if(persistence < min_persistence) {
692 min_persistence = persistence;
693 }
694 }
695 }
696 }
697
698 if(do_sad_ && (type == -1 || type == 1)) {
699 for(size_t i = 0; i < bidder_diagrams_saddle_.size(); ++i) {
700 for(size_t j = 0; j < bidder_diagrams_saddle_[i].size(); ++j) {
701 Bidder const b = bidder_diagrams_saddle_[i].at(j);
702 double const persistence = b.getPersistence();
703 if(persistence < min_persistence) {
704 min_persistence = persistence;
705 }
706 }
707 }
708 }
709
710 if(do_max_ && (type == -1 || type == 2)) {
711 for(size_t i = 0; i < bidder_diagrams_max_.size(); ++i) {
712 for(size_t j = 0; j < bidder_diagrams_max_[i].size(); ++j) {
713 Bidder const b = bidder_diagrams_max_[i].at(j);
714 double const persistence = b.getPersistence();
715 if(persistence < min_persistence) {
716 min_persistence = persistence;
717 }
718 }
719 }
720 }
721 return min_persistence;
722}
723
724std::vector<std::vector<double>> ttk::PDClustering::getMinPrices() {
725 std::vector<std::vector<double>> min_prices(3);
726
727 if(original_dos[0]) {
728 for(int i = 0; i < numberOfInputs_; ++i) {
729 min_prices[0].emplace_back(std::numeric_limits<double>::max());
730 for(size_t j = 0; j < centroids_with_price_min_[i].size(); ++j) {
731 Good const g = centroids_with_price_min_[i].at(j);
732 double const price = g.getPrice();
733 if(price < min_prices[0][i]) {
734 min_prices[0][i] = price;
735 }
736 }
737 }
738 }
739
740 if(original_dos[1]) {
741 for(int i = 0; i < numberOfInputs_; ++i) {
742 min_prices[1].emplace_back(std::numeric_limits<double>::max());
743 for(size_t j = 0; j < centroids_with_price_saddle_[i].size(); ++j) {
744 Good const g = centroids_with_price_saddle_[i].at(j);
745 double const price = g.getPrice();
746 if(price < min_prices[1][i]) {
747 min_prices[1][i] = price;
748 }
749 }
750 }
751 }
752
753 if(original_dos[2]) {
754 for(int i = 0; i < numberOfInputs_; ++i) {
755 min_prices[2].emplace_back(std::numeric_limits<double>::max());
756 for(size_t j = 0; j < centroids_with_price_max_[i].size(); ++j) {
757 Good const g = centroids_with_price_max_[i].at(j);
758 double const price = g.getPrice();
759 if(price < min_prices[2][i]) {
760 min_prices[2][i] = price;
761 }
762 }
763 }
764 }
765
766 return min_prices;
767}
768
769std::vector<std::vector<double>> ttk::PDClustering::getMinDiagonalPrices() {
770 std::vector<std::vector<double>> min_prices(3);
771 if(original_dos[0]) {
772 for(int i = 0; i < numberOfInputs_; ++i) {
773 min_prices[0].emplace_back(std::numeric_limits<double>::max());
774 for(size_t j = 0; j < current_bidder_diagrams_min_[i].size(); ++j) {
775 Bidder const b = current_bidder_diagrams_min_[i].at(j);
776 double const price = b.diagonal_price_;
777 if(price < min_prices[0][i]) {
778 min_prices[0][i] = price;
779 }
780 }
781 if(min_prices[0][i] >= std::numeric_limits<double>::max() / 2.) {
782 min_prices[0][i] = 0;
783 }
784 }
785 }
786
787 if(original_dos[1]) {
788 for(int i = 0; i < numberOfInputs_; ++i) {
789 min_prices[1].emplace_back(std::numeric_limits<double>::max());
790 for(size_t j = 0; j < current_bidder_diagrams_saddle_[i].size(); ++j) {
791 Bidder const b = current_bidder_diagrams_saddle_[i].at(j);
792 double const price = b.diagonal_price_;
793 if(price < min_prices[1][i]) {
794 min_prices[1][i] = price;
795 }
796 }
797 if(min_prices[1][i] >= std::numeric_limits<double>::max() / 2.) {
798 min_prices[1][i] = 0;
799 }
800 }
801 }
802
803 if(original_dos[2]) {
804 for(int i = 0; i < numberOfInputs_; ++i) {
805 min_prices[2].emplace_back(std::numeric_limits<double>::max());
806 for(size_t j = 0; j < current_bidder_diagrams_max_[i].size(); ++j) {
807 Bidder const b = current_bidder_diagrams_max_[i].at(j);
808 double const price = b.diagonal_price_;
809 if(price < min_prices[2][i]) {
810 min_prices[2][i] = price;
811 }
812 }
813 if(min_prices[2][i] >= std::numeric_limits<double>::max() / 2.) {
814 min_prices[2][i] = 0;
815 }
816 }
817 }
818 return min_prices;
819}
820
822 const BidderDiagram &D2,
823 const double delta_lim) {
824 GoodDiagram const D2_bis = diagramToCentroid(D2);
825 return computeDistance(D1, D2_bis, delta_lim);
826}
827
829 const GoodDiagram &D2,
830 const double delta_lim) {
831 std::vector<MatchingType> matchings;
832 const auto D2_bis = centroidWithZeroPrices(D2);
833 PersistenceDiagramAuction auction(wasserstein_, geometrical_factor_, lambda_,
834 delta_lim, use_kdtree_, nonMatchingWeight_);
835 auction.BuildAuctionDiagrams(D1, D2_bis);
836 double const cost = auction.run(matchings);
837 return cost;
838}
839
841 const GoodDiagram *const D2,
842 const double delta_lim) {
843 std::vector<MatchingType> matchings;
844 PersistenceDiagramAuction auction(wasserstein_, geometrical_factor_, lambda_,
845 delta_lim, use_kdtree_, nonMatchingWeight_);
846 int const size1 = D1->size();
847 auction.BuildAuctionDiagrams(*D1, *D2);
848 double const cost = auction.run(matchings);
849 // Diagonal Points were added in the original diagram. The following line
850 // removes them.
851 D1->resize(size1);
852 return cost;
853}
854
856 const GoodDiagram &D2,
857 const double delta_lim) {
858 BidderDiagram const D1_bis = centroidToDiagram(D1);
859 return computeDistance(D1_bis, D2, delta_lim);
860}
861
865 for(size_t i = 0; i < centroid.size(); i++) {
866 Good g = centroid.at(i);
867 g.setPrice(0);
868 GD.emplace_back(g);
869 }
870 return GD;
871}
872
876 for(size_t i = 0; i < diagram.size(); i++) {
877 Bidder b = diagram.at(i);
878 b.setDiagonalPrice(0);
879 BD.emplace_back(b);
880 }
881 return BD;
882}
883
887 for(size_t i = 0; i < centroid.size(); i++) {
888 Good g = centroid.at(i);
889
890 Bidder b = Bidder(g.x_, g.y_, g.isDiagonal(), BD.size());
891 b.SetCriticalCoordinates(g.coords_[0], g.coords_[1], g.coords_[2]);
892 b.setPositionInAuction(BD.size());
893 BD.emplace_back(b);
894 }
895 return BD;
896}
897
901 for(size_t i = 0; i < diagram.size(); i++) {
902 Bidder b = diagram.at(i);
903
904 Good g = Good(b.x_, b.y_, b.isDiagonal(), GD.size());
905 g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
906 GD.emplace_back(g);
907 }
908 return GD;
909}
910
912 clustering_ = std::vector<std::vector<int>>(k_);
913}
914
916 std::vector<int> idx(numberOfInputs_);
917 // To perform a random draw with replacement, the vector {1, 2, ...,
918 // numberOfInputs_} is shuffled, and we consider its k_ first elements to be
919 // the initial centroids.
920 for(int i = 0; i < numberOfInputs_; i++) {
921 idx[i] = i;
922 }
923 if(!deterministic_)
924 std::shuffle(idx.begin(), idx.end(), std::random_device());
925
926 for(int c = 0; c < k_; c++) {
927 if(do_min_) {
928 GoodDiagram const centroid_min
929 = diagramToCentroid(current_bidder_diagrams_min_[idx[c]]);
930 centroids_min_.emplace_back(centroid_min);
931 }
932 if(do_sad_) {
933 GoodDiagram const centroid_sad
934 = diagramToCentroid(current_bidder_diagrams_saddle_[idx[c]]);
935 centroids_saddle_.emplace_back(centroid_sad);
936 }
937 if(do_max_) {
938 GoodDiagram const centroid_max
939 = diagramToCentroid(current_bidder_diagrams_max_[idx[c]]);
940 centroids_max_.emplace_back(centroid_max);
941 }
942 }
943}
944
946 std::vector<int> indexes_clusters;
947 int const random_idx = deterministic_ ? 0 : rand() % numberOfInputs_;
948 indexes_clusters.emplace_back(random_idx);
949
950 if(do_min_) {
951 GoodDiagram const centroid_min
952 = diagramToCentroid(current_bidder_diagrams_min_[random_idx]);
953 centroids_min_.emplace_back(centroid_min);
954 }
955 if(do_sad_) {
956 GoodDiagram const centroid_sad
957 = diagramToCentroid(current_bidder_diagrams_saddle_[random_idx]);
958 centroids_saddle_.emplace_back(centroid_sad);
959 }
960 if(do_max_) {
961 GoodDiagram const centroid_max
962 = diagramToCentroid(current_bidder_diagrams_max_[random_idx]);
963 centroids_max_.emplace_back(centroid_max);
964 }
965
966 const auto square = [](const double a) { return a * a; };
967
968 while((int)indexes_clusters.size() < k_) {
969 std::vector<double> min_distance_to_centroid(numberOfInputs_);
970 std::vector<double> probabilities(numberOfInputs_);
971
972 // Uncomment for a deterministic algorithm
973 double maximal_distance = 0;
974 int candidate_centroid = 0;
975
976 for(int i = 0; i < numberOfInputs_; i++) {
977
978 min_distance_to_centroid[i] = std::numeric_limits<double>::max();
979 if(std::find(indexes_clusters.begin(), indexes_clusters.end(), i)
980 != indexes_clusters.end()) {
981
982 min_distance_to_centroid[i] = 0;
983 } else {
984
985 for(size_t j = 0; j < indexes_clusters.size(); ++j) {
986
987 double distance = 0;
988 if(do_min_) {
989 GoodDiagram const centroid_min
990 = centroidWithZeroPrices(centroids_min_[j]);
991 distance += computeDistance(
992 current_bidder_diagrams_min_[i], centroid_min, 0.01);
993 }
994 if(do_sad_) {
995 GoodDiagram const centroid_saddle
996 = centroidWithZeroPrices(centroids_saddle_[j]);
997 distance += computeDistance(
998 current_bidder_diagrams_saddle_[i], centroid_saddle, 0.01);
999 }
1000 if(do_max_) {
1001 GoodDiagram const centroid_max
1002 = centroidWithZeroPrices(centroids_max_[j]);
1003 distance += computeDistance(
1004 current_bidder_diagrams_max_[i], centroid_max, 0.01);
1005 }
1006 if(distance < min_distance_to_centroid[i]) {
1007 min_distance_to_centroid[i] = distance;
1008 }
1009 }
1010 }
1011 probabilities[i] = square(min_distance_to_centroid[i]);
1012
1013 // The following block is useful in case of need for a deterministic
1014 // algorithm
1015 if(deterministic_ && min_distance_to_centroid[i] > maximal_distance) {
1016 maximal_distance = min_distance_to_centroid[i];
1017 candidate_centroid = i;
1018 }
1019 }
1020 // Comment the following four lines to make it deterministic
1021 std::random_device rd;
1022 std::mt19937 gen(rd());
1023 std::discrete_distribution<int> distribution(
1024 probabilities.begin(), probabilities.end());
1025
1026 if(!deterministic_) {
1027 candidate_centroid = distribution(gen);
1028 }
1029
1030 indexes_clusters.emplace_back(candidate_centroid);
1031 if(do_min_) {
1032 GoodDiagram const centroid_min
1033 = diagramToCentroid(current_bidder_diagrams_min_[candidate_centroid]);
1034 centroids_min_.emplace_back(centroid_min);
1035 }
1036 if(do_sad_) {
1037 GoodDiagram const centroid_sad = diagramToCentroid(
1038 current_bidder_diagrams_saddle_[candidate_centroid]);
1039 centroids_saddle_.emplace_back(centroid_sad);
1040 }
1041 if(do_max_) {
1042 GoodDiagram const centroid_max
1043 = diagramToCentroid(current_bidder_diagrams_max_[candidate_centroid]);
1044 centroids_max_.emplace_back(centroid_max);
1045 }
1046 }
1047}
1048
1050 // r_ is a vector stating for each diagram if its distance to its centroid is
1051 // up to date (false) or needs to be recomputed (true)
1052 r_ = std::vector<bool>(numberOfInputs_);
1053 // u_ is a vector of upper bounds of the distance of each diagram to its
1054 // closest centroid
1055 u_ = std::vector<double>(numberOfInputs_);
1056 inv_clustering_ = std::vector<int>(numberOfInputs_);
1057 for(int i = 0; i < numberOfInputs_; i++) {
1058 r_[i] = true;
1059 u_[i] = std::numeric_limits<double>::max();
1060 inv_clustering_[i] = -1;
1061 }
1062 // l_ is the matrix of lower bounds for the distance from each diagram
1063 // to each centroid
1064 l_ = std::vector<std::vector<double>>(numberOfInputs_);
1065 for(int i = 0; i < numberOfInputs_; ++i) {
1066 l_[i] = std::vector<double>(k_);
1067 for(int c = 0; c < k_; ++c) {
1068 l_[i][c] = 0;
1069 }
1070 }
1071
1072 // And d_ is a (K x K) matrix storing the distances between each pair of
1073 // centroids
1074 centroidsDistanceMatrix_.resize(k_);
1075 for(int i = 0; i < k_; ++i) {
1076 centroidsDistanceMatrix_[i].resize(k_, 0.0);
1077 }
1078}
1079
1080std::vector<std::vector<double>> ttk::PDClustering::getDistanceMatrix() {
1081 std::vector<std::vector<double>> D(numberOfInputs_);
1082
1083 for(int i = 0; i < numberOfInputs_; ++i) {
1084 BidderDiagram D1_min, D1_sad, D1_max;
1085 if(do_min_) {
1086 D1_min = diagramWithZeroPrices(current_bidder_diagrams_min_[i]);
1087 }
1088 if(do_sad_) {
1089 D1_sad = diagramWithZeroPrices(current_bidder_diagrams_saddle_[i]);
1090 }
1091 if(do_max_) {
1092 D1_max = diagramWithZeroPrices(current_bidder_diagrams_max_[i]);
1093 }
1094 for(int c = 0; c < k_; ++c) {
1095 GoodDiagram D2_min, D2_sad, D2_max;
1096 double distance = 0;
1097 if(do_min_) {
1098 D2_min = centroids_min_[c];
1099 distance += computeDistance(D1_min, D2_min, 0.01);
1100 }
1101 if(do_sad_) {
1102 D2_sad = centroids_saddle_[c];
1103 distance += computeDistance(D1_sad, D2_sad, 0.01);
1104 }
1105 if(do_max_) {
1106 D2_max = centroids_max_[c];
1107 distance += computeDistance(D1_max, D2_max, 0.01);
1108 }
1109 D[i].emplace_back(distance);
1110 }
1111 }
1112 return D;
1113}
1114
1116 for(int i = 0; i < k_; ++i) {
1117 GoodDiagram D1_min, D1_sad, D1_max;
1118 if(do_min_) {
1119 D1_min = centroidWithZeroPrices(centroids_min_[i]);
1120 }
1121 if(do_sad_) {
1122 D1_sad = centroidWithZeroPrices(centroids_saddle_[i]);
1123 }
1124 if(do_max_) {
1125 D1_max = centroidWithZeroPrices(centroids_max_[i]);
1126 }
1127 for(int j = i + 1; j < k_; ++j) {
1128 double distance{};
1129 GoodDiagram D2_min, D2_sad, D2_max;
1130 if(do_min_) {
1131 D2_min = centroidWithZeroPrices(centroids_min_[j]);
1132 distance += computeDistance(D1_min, D2_min, 0.01);
1133 }
1134 if(do_sad_) {
1135 D2_sad = centroidWithZeroPrices(centroids_saddle_[j]);
1136 distance += computeDistance(D1_sad, D2_sad, 0.01);
1137 }
1138 if(do_max_) {
1139 D2_max = centroidWithZeroPrices(centroids_max_[j]);
1140 distance += computeDistance(D1_max, D2_max, 0.01);
1141 }
1142
1143 centroidsDistanceMatrix_[i][j] = distance;
1144 centroidsDistanceMatrix_[j][i] = distance;
1145 }
1146 }
1147}
1148
1150 distanceToCentroid_.resize(numberOfInputs_);
1151
1152 for(int i = 0; i < numberOfInputs_; ++i) {
1153 double const delta_lim{0.01};
1154 double distance{};
1155 auto c = inv_clustering_[i];
1156 if(original_dos[0]) {
1157 GoodDiagram const centroid_min
1158 = centroidWithZeroPrices(centroids_min_[c]);
1159 BidderDiagram const bidder_diag
1160 = diagramWithZeroPrices(current_bidder_diagrams_min_[i]);
1161 distance += computeDistance(bidder_diag, centroid_min, delta_lim);
1162 }
1163 if(original_dos[1]) {
1164 GoodDiagram const centroid_saddle
1165 = centroidWithZeroPrices(centroids_saddle_[c]);
1166 BidderDiagram const bidder_diag
1167 = diagramWithZeroPrices(current_bidder_diagrams_saddle_[i]);
1168 distance += computeDistance(bidder_diag, centroid_saddle, delta_lim);
1169 }
1170 if(original_dos[2]) {
1171 GoodDiagram const centroid_max
1172 = centroidWithZeroPrices(centroids_max_[c]);
1173 BidderDiagram const bidder_diag
1174 = diagramWithZeroPrices(current_bidder_diagrams_max_[i]);
1175 distance += computeDistance(bidder_diag, centroid_max, delta_lim);
1176 }
1177 distanceToCentroid_[i] = distance;
1178 }
1179}
1180
1182 if(k_ > 1) {
1183 std::vector<std::vector<double>> distance_matrix = getDistanceMatrix();
1184 old_clustering_ = clustering_;
1185 invertClusters();
1186 initializeEmptyClusters();
1187
1188 for(int i = 0; i < numberOfInputs_; ++i) {
1189 double min_distance_to_centroid = std::numeric_limits<double>::max();
1190 int cluster = -1;
1191 for(int c = 0; c < k_; ++c) {
1192 if(distance_matrix[i][c] < min_distance_to_centroid) {
1193 min_distance_to_centroid = distance_matrix[i][c];
1194 cluster = c;
1195 }
1196 }
1197
1198 clustering_[cluster].emplace_back(i);
1199 if(cluster != inv_clustering_[i]) {
1200 // New centroid attributed to this diagram
1201 resetDosToOriginalValues();
1202 barycenter_inputs_reset_flag = true;
1203 if(do_min_) {
1204 centroids_with_price_min_[i]
1205 = centroidWithZeroPrices(centroids_min_[cluster]);
1206 }
1207 if(do_sad_) {
1208 centroids_with_price_saddle_[i]
1209 = centroidWithZeroPrices(centroids_saddle_[cluster]);
1210 }
1211 if(do_max_) {
1212 centroids_with_price_max_[i]
1213 = centroidWithZeroPrices(centroids_max_[cluster]);
1214 }
1215 inv_clustering_[i] = cluster;
1216 }
1217 }
1218
1219 } else {
1220 old_clustering_ = clustering_;
1221 invertClusters();
1222 initializeEmptyClusters();
1223
1224 for(int i = 0; i < numberOfInputs_; i++) {
1225 clustering_[0].emplace_back(i);
1226 if(n_iterations_ < 1) {
1227 if(do_min_) {
1228 centroids_with_price_min_[i]
1229 = centroidWithZeroPrices(centroids_min_[0]);
1230 }
1231 if(do_sad_) {
1232 centroids_with_price_saddle_[i]
1233 = centroidWithZeroPrices(centroids_saddle_[0]);
1234 }
1235 if(do_max_) {
1236 centroids_with_price_max_[i]
1237 = centroidWithZeroPrices(centroids_max_[0]);
1238 }
1239 }
1240 inv_clustering_[i] = 0;
1241 }
1242 }
1243}
1244
1249
1250 // Initializes clusters with -1
1251 inv_clustering_ = std::vector<int>(numberOfInputs_, -1);
1252
1253 // Fill in the clusters
1254 for(int c = 0; c < k_; ++c) {
1255 for(size_t j = 0; j < clustering_[c].size(); ++j) {
1256 int const idx = clustering_[c][j];
1257 inv_clustering_[idx] = c;
1258 }
1259 }
1260}
1261
1263 clustering_ = std::vector<std::vector<int>>(k_);
1264 for(int i = 0; i < numberOfInputs_; ++i) {
1265 clustering_[inv_clustering_[i]].emplace_back(i);
1266 }
1267
1268 // Check if a cluster was left without diagram
1269 for(int c = 0; c < k_; ++c) {
1270 if(clustering_[c].empty()) {
1271 std::cout << "Problem in invertInverseClusters()... \nCluster " << c
1272 << " was left with no diagram attached to it... " << std::endl;
1273 }
1274 }
1275}
1276
1278 // Step 1
1279 getCentroidDistanceMatrix();
1280 old_clustering_ = clustering_;
1281 // self.old_clusters = copy.copy(self.clusters)
1282 invertClusters();
1283 initializeEmptyClusters();
1284 bool const do_min = original_dos[0];
1285 bool const do_sad = original_dos[1];
1286 bool const do_max = original_dos[2];
1287
1288 for(int i = 0; i < numberOfInputs_; ++i) {
1289 // Step 3 find potential changes of clusters
1290 BidderDiagram D1_min, D1_sad, D1_max;
1291 if(do_min) {
1292 D1_min = diagramWithZeroPrices(current_bidder_diagrams_min_[i]);
1293 }
1294 if(do_sad) {
1295 D1_sad = diagramWithZeroPrices(current_bidder_diagrams_saddle_[i]);
1296 }
1297 if(do_max) {
1298 D1_max = diagramWithZeroPrices(current_bidder_diagrams_max_[i]);
1299 }
1300
1301 for(int c = 0; c < k_; ++c) {
1302 if(inv_clustering_[i] == -1) {
1303 // If not yet assigned, assign it first to a random cluster
1304
1305 if(deterministic_) {
1306 inv_clustering_[i] = i % k_;
1307 } else {
1308 std::cout << " - ASSIGNED TO A RANDOM CLUSTER " << '\n';
1309 inv_clustering_[i] = rand() % (k_);
1310 }
1311
1312 r_[i] = true;
1313 if(do_min) {
1314 centroids_with_price_min_[i]
1315 = centroidWithZeroPrices(centroids_min_[inv_clustering_[i]]);
1316 }
1317 if(do_sad) {
1318 centroids_with_price_saddle_[i]
1319 = centroidWithZeroPrices(centroids_saddle_[inv_clustering_[i]]);
1320 }
1321 if(do_max) {
1322 centroids_with_price_max_[i]
1323 = centroidWithZeroPrices(centroids_max_[inv_clustering_[i]]);
1324 }
1325 }
1326
1327 if(c != inv_clustering_[i] && u_[i] > l_[i][c]
1328 && u_[i] > 0.5 * centroidsDistanceMatrix_[inv_clustering_[i]][c]) {
1329 // Step 3a, If necessary, recompute the distance to centroid
1330 if(r_[i]) {
1331 double distance = 0;
1332 GoodDiagram centroid_min, centroid_sad, centroid_max;
1333 if(do_min) {
1334 centroid_min
1335 = centroidWithZeroPrices(centroids_min_[inv_clustering_[i]]);
1336 distance += computeDistance(D1_min, centroid_min, 0.01);
1337 }
1338 if(do_sad) {
1339 centroid_sad
1340 = centroidWithZeroPrices(centroids_saddle_[inv_clustering_[i]]);
1341 distance += computeDistance(D1_sad, centroid_sad, 0.01);
1342 }
1343 if(do_max) {
1344 centroid_max
1345 = centroidWithZeroPrices(centroids_max_[inv_clustering_[i]]);
1346 distance += computeDistance(D1_max, centroid_max, 0.01);
1347 }
1348 r_[i] = false;
1349 u_[i] = distance;
1350 l_[i][inv_clustering_[i]] = distance;
1351 }
1352 // Step 3b, check if still potential change of clusters
1353 if((n_iterations_ > 2 || n_iterations_ < 1)
1354 && (u_[i] > l_[i][c]
1355 || u_[i]
1356 > 0.5 * centroidsDistanceMatrix_[inv_clustering_[i]][c])) {
1357 BidderDiagram diagram_min, diagram_sad, diagram_max;
1358 GoodDiagram centroid_min, centroid_sad, centroid_max;
1359 double distance = 0;
1360
1361 if(do_min) {
1362 centroid_min = centroidWithZeroPrices(centroids_min_[c]);
1363 diagram_min
1364 = diagramWithZeroPrices(current_bidder_diagrams_min_[i]);
1365 distance += computeDistance(diagram_min, centroid_min, 0.01);
1366 }
1367 if(do_sad) {
1368 centroid_sad = centroidWithZeroPrices(centroids_saddle_[c]);
1369 diagram_sad
1370 = diagramWithZeroPrices(current_bidder_diagrams_saddle_[i]);
1371 distance += computeDistance(diagram_sad, centroid_sad, 0.01);
1372 }
1373 if(do_max) {
1374 centroid_max = centroidWithZeroPrices(centroids_max_[c]);
1375 diagram_max
1376 = diagramWithZeroPrices(current_bidder_diagrams_max_[i]);
1377 distance += computeDistance(diagram_max, centroid_max, 0.01);
1378 }
1379 l_[i][c] = distance;
1380 // TODO Prices are lost here... If distance<self.u[i], we should keep
1381 // the prices
1382 if(distance < u_[i]) {
1383 // Changing cluster
1384 resetDosToOriginalValues();
1385 barycenter_inputs_reset_flag = true;
1386 u_[i] = distance;
1387 inv_clustering_[i] = c;
1388
1389 if(do_min) {
1390 centroids_with_price_min_[i]
1391 = centroidWithZeroPrices(centroids_min_[c]);
1392 }
1393 if(do_sad) {
1394 centroids_with_price_saddle_[i]
1395 = centroidWithZeroPrices(centroids_saddle_[c]);
1396 }
1397 if(do_max) {
1398 centroids_with_price_max_[i]
1399 = centroidWithZeroPrices(centroids_max_[c]);
1400 }
1401 }
1402 }
1403 }
1404 }
1405 }
1406 invertInverseClusters();
1407 for(int c = 0; c < k_; ++c) {
1408 if(clustering_[c].empty()) {
1409 std::cout << "Adding artificial centroid because a cluster was empty"
1410 << std::endl;
1411 bool idx_acceptable = false;
1412 int idx = 0;
1413
1414 std::vector<double> copy_of_u(u_.size());
1415 copy_of_u = u_;
1416 while(!idx_acceptable) {
1417 auto argMax = std::max_element(copy_of_u.begin(), copy_of_u.end());
1418 idx = std::distance(copy_of_u.begin(), argMax);
1419 if(inv_clustering_[idx] < k_ && inv_clustering_[idx] >= 0
1420 && clustering_[inv_clustering_[idx]].size() > 1) {
1421 idx_acceptable = true;
1422 int const cluster_removal = inv_clustering_[idx];
1423 // Removing the index to remove
1424 clustering_[cluster_removal].erase(
1425 std::remove(clustering_[cluster_removal].begin(),
1426 clustering_[cluster_removal].end(), idx),
1427 clustering_[cluster_removal].end());
1428 } else {
1429 if(copy_of_u.size() > (size_t)idx) {
1430 copy_of_u.erase(argMax);
1431 } else {
1432 idx_acceptable = true;
1433 int cluster_max = 0;
1434 if(!clustering_[cluster_max].empty()) {
1435 idx = clustering_[cluster_max][0];
1436 }
1437 for(int i_test = 1; i_test < k_; i_test++) {
1438 if(clustering_[i_test].size() > clustering_[cluster_max].size()) {
1439 cluster_max = i_test;
1440 idx = clustering_[cluster_max][0];
1441 }
1442 }
1443 int const cluster_removal = inv_clustering_[idx];
1444 clustering_[cluster_removal].erase(
1445 std::remove(clustering_[cluster_removal].begin(),
1446 clustering_[cluster_removal].end(), idx),
1447 clustering_[cluster_removal].end());
1448 }
1449 }
1450 }
1451
1452 clustering_[c].emplace_back(idx);
1453 inv_clustering_[idx] = c;
1454
1455 if(do_min) {
1456 centroids_min_[c]
1457 = diagramToCentroid(current_bidder_diagrams_min_[idx]);
1458 centroids_with_price_min_[idx]
1459 = centroidWithZeroPrices(centroids_min_[c]);
1460 }
1461 if(do_sad) {
1462 centroids_saddle_[c]
1463 = diagramToCentroid(current_bidder_diagrams_saddle_[idx]);
1464 centroids_with_price_saddle_[idx]
1465 = centroidWithZeroPrices(centroids_saddle_[c]);
1466 }
1467 if(do_max) {
1468 centroids_max_[c]
1469 = diagramToCentroid(current_bidder_diagrams_max_[idx]);
1470 centroids_with_price_max_[idx]
1471 = centroidWithZeroPrices(centroids_max_[c]);
1472 }
1473 resetDosToOriginalValues();
1474 barycenter_inputs_reset_flag = true;
1475 }
1476 }
1477}
1478
1480 std::vector<std::vector<double>> *min_price,
1481 std::vector<std::vector<double>> *min_diag_price,
1482 std::vector<std::vector<std::vector<std::vector<MatchingType>>>>
1483 &all_matchings_per_type_and_cluster,
1484 int only_matchings) {
1485 barycenter_inputs_reset_flag = true;
1486 std::vector<double> max_shift_vector(3);
1487 max_shift_vector[0] = 0;
1488 max_shift_vector[1] = 0;
1489 max_shift_vector[2] = 0;
1490 double max_shift_c_min = 0;
1491 double max_shift_c_sad = 0;
1492 double max_shift_c_max = 0;
1493 double max_wasserstein_shift = 0;
1494 bool precision_min = true;
1495 bool precision_sad = true;
1496 bool precision_max = true;
1497 cost_ = 0;
1498 double const sq_dist_min = cost_min_;
1499 double const sq_dist_sad = cost_sad_;
1500 double const sq_dist_max = cost_max_;
1501 if(do_min_) {
1502 cost_min_ = 0;
1503 }
1504 if(do_sad_) {
1505 cost_sad_ = 0;
1506 }
1507 if(do_max_) {
1508 cost_max_ = 0;
1509 }
1510
1511 for(int c = 0; c < k_; ++c) {
1512 if(!clustering_[c].empty()) {
1513 std::vector<GoodDiagram> centroids_with_price_min,
1514 centroids_with_price_sad, centroids_with_price_max;
1515 int count = 0;
1516 for(int const idx : clustering_[c]) {
1517 // Timer time_first_thing;
1518 // Find the position of diagrams[idx] in old cluster c
1519 std::vector<int>::iterator const i = std::find(
1520 old_clustering_[c].begin(), old_clustering_[c].end(), idx);
1521 int const pos = (i == old_clustering_[c].end())
1522 ? -1
1523 : std::distance(old_clustering_[c].begin(), i);
1524 if(pos >= 0) {
1525 // Diagram was already linked to this centroid before
1526 if(do_min_) {
1527 centroids_with_price_min.emplace_back(
1528 centroids_with_price_min_[idx]);
1529 }
1530 if(do_sad_) {
1531 centroids_with_price_sad.emplace_back(
1532 centroids_with_price_saddle_[idx]);
1533 }
1534 if(do_max_) {
1535 centroids_with_price_max.emplace_back(
1536 centroids_with_price_max_[idx]);
1537 }
1538 } else {
1539 int number_of_points_min = 0;
1540 int number_of_points_max = 0;
1541 int number_of_points_sad = 0;
1542
1543 // Otherwise, centroid is given 0 prices and the diagram is given 0
1544 // diagonal-prices
1545 if(do_min_) {
1546 centroids_with_price_min.emplace_back(
1547 centroidWithZeroPrices(centroids_min_[c]));
1548 current_bidder_diagrams_min_[idx]
1549 = diagramWithZeroPrices(current_bidder_diagrams_min_[idx]);
1550 number_of_points_min += centroids_with_price_min_[idx].size()
1551 + current_bidder_diagrams_min_[idx].size();
1552 }
1553 if(do_sad_) {
1554 centroids_with_price_sad.emplace_back(
1555 centroidWithZeroPrices(centroids_saddle_[c]));
1556 current_bidder_diagrams_saddle_[idx]
1557 = diagramWithZeroPrices(current_bidder_diagrams_saddle_[idx]);
1558 number_of_points_sad
1559 += centroids_with_price_saddle_[idx].size()
1560 + current_bidder_diagrams_saddle_[idx].size();
1561 }
1562 if(do_max_) {
1563 centroids_with_price_max.emplace_back(
1564 centroidWithZeroPrices(centroids_max_[c]));
1565 current_bidder_diagrams_max_[idx]
1566 = diagramWithZeroPrices(current_bidder_diagrams_max_[idx]);
1567 number_of_points_max += centroids_with_price_max_[idx].size()
1568 + current_bidder_diagrams_max_[idx].size();
1569 }
1570
1571 if(n_iterations_ > 1) {
1572 // If diagram new to cluster and we're not at first iteration,
1573 // precompute prices for the objects via compute_distance()
1574 // number_of_points /= (int)do_min_ + (int)do_sad_ + (int)do_max_;
1575 // double d_estimated = pow(cost_ / numberOfInputs_, 1. /
1576 // wasserstein_) + 1e-7; We use pointer in the auction in order to
1577 // keep the prices at the end
1578
1579 if(do_min_) {
1580 // double estimated_delta_lim = number_of_points_min *
1581 // epsilon_[0] / (2*sq_dist_min) ;
1582 double estimated_delta_lim
1583 = 1.
1584 / sqrt(1 - number_of_points_min * epsilon_[0] / sq_dist_min)
1585 - 1;
1586 if(estimated_delta_lim > 1) {
1587 estimated_delta_lim = 1;
1588 }
1589 computeDistance(&(current_bidder_diagrams_min_[idx]),
1590 &(centroids_with_price_min[count]),
1591 estimated_delta_lim);
1592 }
1593 if(do_sad_) {
1594 // double estimated_delta_lim = number_of_points_sad *
1595 // epsilon_[1] / (2*sq_dist_sad);
1596 double estimated_delta_lim
1597 = 1.
1598 / sqrt(1 - number_of_points_sad * epsilon_[1] / sq_dist_sad)
1599 - 1;
1600 if(estimated_delta_lim > 1) {
1601 estimated_delta_lim = 1;
1602 }
1603 computeDistance(&(current_bidder_diagrams_saddle_[idx]),
1604 &(centroids_with_price_sad[count]),
1605 estimated_delta_lim);
1606 }
1607 if(do_max_) {
1608 // double estimated_delta_lim = number_of_points_max *
1609 // epsilon_[2] / (2*sq_dist_max);
1610 double estimated_delta_lim
1611 = 1.
1612 / sqrt(1 - number_of_points_max * epsilon_[2] / sq_dist_max)
1613 - 1;
1614 if(estimated_delta_lim > 1) {
1615 estimated_delta_lim = 1;
1616 }
1617 computeDistance(&(current_bidder_diagrams_max_[idx]),
1618 &(centroids_with_price_max[count]),
1619 estimated_delta_lim);
1620 }
1621 }
1622 }
1623 count++;
1624 }
1625 double total_cost = 0;
1626 double wasserstein_shift = 0;
1627
1628 using KDTreePair = PDBarycenter::KDTreePair;
1629
1630 if(do_min_) {
1631 std::vector<std::vector<MatchingType>> all_matchings;
1632 std::vector<int> sizes;
1633 Timer const time_preprocess_bary;
1634 std::vector<BidderDiagram> diagrams_c_min;
1635 if(barycenter_inputs_reset_flag) {
1636 for(int const idx : clustering_[c]) {
1637 diagrams_c_min.emplace_back(current_bidder_diagrams_min_[idx]);
1638 }
1639 sizes.resize(diagrams_c_min.size());
1640 for(size_t i = 0; i < diagrams_c_min.size(); i++) {
1641 sizes[i] = diagrams_c_min[i].size();
1642 }
1643 barycenter_computer_min_[c].setNumberOfInputs(diagrams_c_min.size());
1644 barycenter_computer_min_[c].setCurrentBidders(diagrams_c_min);
1645
1646 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
1647 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
1648 i_diagram++) {
1649 barycenter_goods[i_diagram]
1650 = centroids_with_price_min_[clustering_[c][i_diagram]];
1651 }
1652 barycenter_computer_min_[c].setCurrentBarycenter(barycenter_goods);
1653 all_matchings.resize(diagrams_c_min.size());
1654 } else {
1655 sizes.resize(barycenter_computer_min_[c].getCurrentBidders().size());
1656 for(size_t i = 0;
1657 i < barycenter_computer_min_[c].getCurrentBidders().size(); i++) {
1658 sizes[i]
1659 = barycenter_computer_min_[c].getCurrentBidders().at(i).size();
1660 }
1661 diagrams_c_min.resize(
1662 barycenter_computer_min_[c].getCurrentBidders().size());
1663 all_matchings.resize(
1664 barycenter_computer_min_[c].getCurrentBidders().size());
1665 }
1666
1667 KDTreePair pair;
1668 bool use_kdt = false;
1669 if(!barycenter_computer_min_[c].getCurrentBarycenter()[0].empty()) {
1670 pair = barycenter_computer_min_[c].getKDTree();
1671 use_kdt = true;
1672 }
1673
1674 barycenter_computer_min_[c].runMatching(
1675 &total_cost, epsilon_[0], sizes, *pair.first, pair.second,
1676 &(min_diag_price->at(0)), &(min_price->at(0)), &(all_matchings),
1677 use_kdt, only_matchings);
1678 for(size_t ii = 0; ii < all_matchings.size(); ii++) {
1679 all_matchings_per_type_and_cluster[c][0][ii].resize(
1680 all_matchings[ii].size());
1681 all_matchings_per_type_and_cluster[c][0][ii] = all_matchings[ii];
1682 }
1683 for(int ii = all_matchings.size(); ii < numberOfInputs_; ii++) {
1684 all_matchings_per_type_and_cluster[c][0][ii].resize(0);
1685 }
1686
1687 precision_min
1688 = barycenter_computer_min_[c].isPrecisionObjectiveMet(deltaLim_, 0);
1689 cost_min_ += total_cost;
1690 Timer const time_update;
1691 if(!only_matchings) {
1692 max_shift_c_min
1693 = barycenter_computer_min_[c].updateBarycenter(all_matchings);
1694 }
1695
1696 if(max_shift_c_min > max_shift_vector[0]) {
1697 max_shift_vector[0] = max_shift_c_min;
1698 }
1699
1700 // Now that barycenters and diagrams are updated in
1701 // PDBarycenter class, we import the results here.
1702 diagrams_c_min = barycenter_computer_min_[c].getCurrentBidders();
1703 centroids_with_price_min
1704 = barycenter_computer_min_[c].getCurrentBarycenter();
1705 int i = 0;
1706 for(int const idx : clustering_[c]) {
1707 current_bidder_diagrams_min_[idx] = diagrams_c_min[i];
1708 centroids_with_price_min_[idx] = centroids_with_price_min[i];
1709 i++;
1710 }
1711
1712 GoodDiagram const old_centroid = centroids_min_[c];
1713 centroids_min_[c] = centroidWithZeroPrices(
1714 centroids_with_price_min_[clustering_[c][0]]);
1715
1716 if(use_accelerated_) {
1717 wasserstein_shift
1718 += computeDistance(old_centroid, centroids_min_[c], 0.01);
1719 }
1720 }
1721
1722 if(do_sad_) {
1723 std::vector<std::vector<MatchingType>> all_matchings;
1724 total_cost = 0;
1725 std::vector<int> sizes;
1726
1727 std::vector<BidderDiagram> diagrams_c_min;
1728 if(barycenter_inputs_reset_flag) {
1729 for(int const idx : clustering_[c]) {
1730 diagrams_c_min.emplace_back(current_bidder_diagrams_saddle_[idx]);
1731 }
1732 sizes.resize(diagrams_c_min.size());
1733 for(size_t i = 0; i < diagrams_c_min.size(); i++) {
1734 sizes[i] = diagrams_c_min[i].size();
1735 }
1736 barycenter_computer_sad_[c].setNumberOfInputs(diagrams_c_min.size());
1737 barycenter_computer_sad_[c].setCurrentBidders(diagrams_c_min);
1738 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
1739 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
1740 i_diagram++) {
1741 barycenter_goods[i_diagram]
1742 = centroids_with_price_saddle_[clustering_[c][i_diagram]];
1743 }
1744 barycenter_computer_sad_[c].setCurrentBarycenter(barycenter_goods);
1745 all_matchings.resize(diagrams_c_min.size());
1746 } else {
1747 sizes.resize(barycenter_computer_sad_[c].getCurrentBidders().size());
1748 for(size_t i = 0;
1749 i < barycenter_computer_sad_[c].getCurrentBidders().size(); i++) {
1750 sizes[i]
1751 = barycenter_computer_sad_[c].getCurrentBidders().at(i).size();
1752 }
1753 all_matchings.resize(
1754 barycenter_computer_sad_[c].getCurrentBidders().size());
1755 diagrams_c_min.resize(
1756 barycenter_computer_sad_[c].getCurrentBidders().size());
1757 }
1758
1759 KDTreePair pair;
1760 bool use_kdt = false;
1761 if(!barycenter_computer_sad_[c].getCurrentBarycenter()[0].empty()) {
1762 pair = barycenter_computer_sad_[c].getKDTree();
1763 use_kdt = true;
1764 }
1765
1766 barycenter_computer_sad_[c].runMatching(
1767 &total_cost, epsilon_[1], sizes, *pair.first, pair.second,
1768 &(min_diag_price->at(1)), &(min_price->at(1)), &(all_matchings),
1769 use_kdt, only_matchings);
1770 for(size_t ii = 0; ii < all_matchings.size(); ii++) {
1771 all_matchings_per_type_and_cluster[c][1][ii].resize(
1772 all_matchings[ii].size());
1773 all_matchings_per_type_and_cluster[c][1][ii] = all_matchings[ii];
1774 }
1775 for(int ii = all_matchings.size(); ii < numberOfInputs_; ii++) {
1776 all_matchings_per_type_and_cluster[c][1][ii].resize(0);
1777 }
1778
1779 precision_sad
1780 = barycenter_computer_sad_[c].isPrecisionObjectiveMet(deltaLim_, 0);
1781 if(!only_matchings) {
1782 max_shift_c_sad
1783 = barycenter_computer_sad_[c].updateBarycenter(all_matchings);
1784 }
1785
1786 cost_sad_ += total_cost;
1787
1788 if(max_shift_c_sad > max_shift_vector[1]) {
1789 max_shift_vector[1] = max_shift_c_sad;
1790 }
1791
1792 // Now that barycenters and diagrams are updated in PDBarycenter class,
1793 // we import the results here.
1794 diagrams_c_min = barycenter_computer_sad_[c].getCurrentBidders();
1795 centroids_with_price_sad
1796 = barycenter_computer_sad_[c].getCurrentBarycenter();
1797 int i = 0;
1798 for(int const idx : clustering_[c]) {
1799 current_bidder_diagrams_saddle_[idx] = diagrams_c_min[i];
1800 centroids_with_price_saddle_[idx] = centroids_with_price_sad[i];
1801 i++;
1802 }
1803 GoodDiagram const old_centroid = centroids_saddle_[c];
1804 centroids_saddle_[c] = centroidWithZeroPrices(
1805 centroids_with_price_saddle_[clustering_[c][0]]);
1806 if(use_accelerated_)
1807 wasserstein_shift
1808 += computeDistance(old_centroid, centroids_saddle_[c], 0.01);
1809 }
1810
1811 if(do_max_) {
1812 std::vector<std::vector<MatchingType>> all_matchings;
1813 Timer const time_preprocess_bary;
1814 total_cost = 0;
1815 std::vector<int> sizes;
1816 std::vector<BidderDiagram> diagrams_c_min;
1817 if(barycenter_inputs_reset_flag) {
1818 for(int const idx : clustering_[c]) {
1819 diagrams_c_min.emplace_back(current_bidder_diagrams_max_[idx]);
1820 }
1821 sizes.resize(diagrams_c_min.size());
1822 for(size_t i = 0; i < diagrams_c_min.size(); i++) {
1823 sizes[i] = diagrams_c_min[i].size();
1824 }
1825 barycenter_computer_max_[c].setNumberOfInputs(diagrams_c_min.size());
1826 barycenter_computer_max_[c].setCurrentBidders(diagrams_c_min);
1827 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
1828 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
1829 i_diagram++) {
1830 barycenter_goods[i_diagram]
1831 = centroids_with_price_max_[clustering_[c][i_diagram]];
1832 }
1833 barycenter_computer_max_[c].setCurrentBarycenter(barycenter_goods);
1834 all_matchings.resize(diagrams_c_min.size());
1835 } else {
1836 sizes.resize(barycenter_computer_max_[c].getCurrentBidders().size());
1837 for(size_t i = 0;
1838 i < barycenter_computer_max_[c].getCurrentBidders().size(); i++) {
1839 sizes[i]
1840 = barycenter_computer_max_[c].getCurrentBidders().at(i).size();
1841 }
1842
1843 diagrams_c_min.resize(
1844 barycenter_computer_max_[c].getCurrentBidders().size());
1845 all_matchings.resize(
1846 barycenter_computer_max_[c].getCurrentBidders().size());
1847 }
1848
1849 KDTreePair pair;
1850 bool use_kdt = false;
1851 if(!barycenter_computer_max_[c].getCurrentBarycenter()[0].empty()) {
1852 pair = barycenter_computer_max_[c].getKDTree();
1853 use_kdt = true;
1854 }
1855
1856 barycenter_computer_max_[c].runMatching(
1857 &total_cost, epsilon_[2], sizes, *pair.first, pair.second,
1858 &(min_diag_price->at(2)), &(min_price->at(2)), &(all_matchings),
1859 use_kdt, only_matchings);
1860 for(size_t ii = 0; ii < all_matchings.size(); ii++) {
1861 all_matchings_per_type_and_cluster[c][2][ii].resize(
1862 all_matchings[ii].size());
1863 all_matchings_per_type_and_cluster[c][2][ii] = all_matchings[ii];
1864 }
1865 for(int ii = all_matchings.size(); ii < numberOfInputs_; ii++) {
1866 all_matchings_per_type_and_cluster[c][2][ii].resize(0);
1867 }
1868 precision_max
1869 = barycenter_computer_max_[c].isPrecisionObjectiveMet(deltaLim_, 0);
1870
1871 cost_max_ += total_cost;
1872 Timer const time_update;
1873 if(!only_matchings) {
1874 max_shift_c_max
1875 = barycenter_computer_max_[c].updateBarycenter(all_matchings);
1876 }
1877 if(max_shift_c_max > max_shift_vector[2]) {
1878 max_shift_vector[2] = max_shift_c_max;
1879 }
1880
1881 // Now that barycenters and diagrams are updated in PDBarycenter class,
1882 // we import the results here.
1883 diagrams_c_min = barycenter_computer_max_[c].getCurrentBidders();
1884 centroids_with_price_max
1885 = barycenter_computer_max_[c].getCurrentBarycenter();
1886 int i = 0;
1887 for(int const idx : clustering_[c]) {
1888 current_bidder_diagrams_max_[idx] = diagrams_c_min[i];
1889 centroids_with_price_max_[idx] = centroids_with_price_max[i];
1890 i++;
1891 }
1892 GoodDiagram const old_centroid = centroids_max_[c];
1893 centroids_max_[c] = centroidWithZeroPrices(
1894 centroids_with_price_max_[clustering_[c][0]]);
1895 if(use_accelerated_) {
1896 wasserstein_shift
1897 += computeDistance(old_centroid, centroids_max_[c], 0.01);
1898 }
1899 }
1900
1901 cost_ = cost_min_ + cost_sad_ + cost_max_;
1902 if(wasserstein_shift > max_wasserstein_shift) {
1903 max_wasserstein_shift = wasserstein_shift;
1904 }
1905 if(use_accelerated_) {
1906 for(int i = 0; i < numberOfInputs_; ++i) {
1907 // Step 5 of Accelerated KMeans: Update the lower bound on distance
1908 // thanks to the triangular inequality
1909 l_[i][c] = Geometry::pow(
1910 Geometry::pow(l_[i][c], 1. / wasserstein_)
1911 - Geometry::pow(wasserstein_shift, 1. / wasserstein_),
1912 wasserstein_);
1913 if(l_[i][c] < 0) {
1914 l_[i][c] = 0;
1915 }
1916 }
1917 for(int const idx : clustering_[c]) {
1918 // Step 6, update the upper bound on the distance to the centroid
1919 // thanks to the triangle inequality
1920 u_[idx] = Geometry::pow(
1921 Geometry::pow(u_[idx], 1. / wasserstein_)
1922 + Geometry::pow(wasserstein_shift, 1. / wasserstein_),
1923 wasserstein_);
1924 r_[idx] = true;
1925 }
1926 }
1927 }
1928 }
1929 // Normally return max_shift, but it seems there is a bug
1930 // yielding max_shift > 100 * max_wasserstein_shift
1931 // which should logically not really happen...
1932 // This is supposed to be only a temporary patch...
1933 precision_min_ = precision_min;
1934 precision_sad_ = precision_sad;
1935 precision_max_ = precision_max;
1936 precision_criterion_ = precision_min && precision_sad && precision_max;
1937 barycenter_inputs_reset_flag = false;
1938 return max_shift_vector; // std::min(max_shift, max_wasserstein_shift);
1939}
1940
1942 for(int i = 0; i < numberOfInputs_; i++) {
1943 if(do_min_) {
1944 DiagramType *CTDiagram = &((*inputDiagramsMin_)[i]);
1945 BidderDiagram bidders;
1946 for(size_t j = 0; j < CTDiagram->size(); j++) {
1947 // Add bidder to bidders
1948 Bidder b((*CTDiagram)[j], j, lambda_);
1949
1950 b.setPositionInAuction(bidders.size());
1951 bidders.emplace_back(b);
1952 if(b.isDiagonal() || b.x_ == b.y_) {
1953 this->printMsg("Diagonal point in diagram", debug::Priority::DETAIL);
1954 }
1955 }
1956 bidder_diagrams_min_.emplace_back(bidders);
1957 current_bidder_diagrams_min_.emplace_back();
1958 centroids_with_price_min_.emplace_back();
1959 std::vector<int> ids(bidders.size(), -1);
1960 current_bidder_ids_min_.emplace_back(ids);
1961 }
1962
1963 if(do_sad_) {
1964 DiagramType *CTDiagram = &((*inputDiagramsSaddle_)[i]);
1965
1966 BidderDiagram bidders;
1967 for(size_t j = 0; j < CTDiagram->size(); j++) {
1968 // Add bidder to bidders
1969 Bidder b((*CTDiagram)[j], j, lambda_);
1970
1971 b.setPositionInAuction(bidders.size());
1972 bidders.emplace_back(b);
1973 if(b.isDiagonal() || b.x_ == b.y_) {
1974 this->printMsg("Diagonal point in diagram", debug::Priority::DETAIL);
1975 }
1976 }
1977 bidder_diagrams_saddle_.emplace_back(bidders);
1978 current_bidder_diagrams_saddle_.emplace_back();
1979 centroids_with_price_saddle_.emplace_back();
1980 std::vector<int> ids(bidders.size(), -1);
1981 current_bidder_ids_sad_.emplace_back(ids);
1982 }
1983
1984 if(do_max_) {
1985 DiagramType *CTDiagram = &((*inputDiagramsMax_)[i]);
1986
1987 BidderDiagram bidders;
1988 for(size_t j = 0; j < CTDiagram->size(); j++) {
1989 // Add bidder to bidders
1990 Bidder b((*CTDiagram)[j], j, lambda_);
1991
1992 b.setPositionInAuction(bidders.size());
1993 bidders.emplace_back(b);
1994 if(b.isDiagonal() || b.x_ == b.y_) {
1995 this->printMsg("Diagonal point in diagram", debug::Priority::DETAIL);
1996 }
1997 }
1998 bidder_diagrams_max_.emplace_back(bidders);
1999 current_bidder_diagrams_max_.emplace_back();
2000 centroids_with_price_max_.emplace_back();
2001 std::vector<int> ids(bidders.size(), -1);
2002 current_bidder_ids_max_.emplace_back(ids);
2003 }
2004 }
2005}
2006
2008 std::vector<double> &previous_min_persistence,
2009 std::vector<double> &min_persistence,
2010 std::vector<std::vector<double>> &initial_diagonal_prices,
2011 std::vector<std::vector<double>> &initial_off_diagonal_prices,
2012 std::vector<int> &min_points_to_add,
2013 bool add_points_to_barycenter,
2014 bool first_enrichment) {
2015
2016 std::vector<double> new_min_persistence = min_persistence;
2017
2018 if(!do_min_) {
2019 new_min_persistence[0] = previous_min_persistence[0];
2020 }
2021 if(!do_sad_) {
2022 new_min_persistence[1] = previous_min_persistence[1];
2023 }
2024 if(!do_max_) {
2025 new_min_persistence[2] = previous_min_persistence[2];
2026 }
2027
2028 // 1. Get size of the largest current diagram, deduce the maximal number of
2029 // points to append
2030 size_t max_diagram_size_min{};
2031 size_t max_diagram_size_sad{};
2032 size_t max_diagram_size_max{};
2033 if(do_min_) {
2034 for(int i = 0; i < numberOfInputs_; i++) {
2035 if(current_bidder_diagrams_min_[i].size() > max_diagram_size_min) {
2036 max_diagram_size_min = current_bidder_diagrams_min_[i].size();
2037 }
2038 }
2039 }
2040 if(do_sad_) {
2041 for(int i = 0; i < numberOfInputs_; i++) {
2042 if(current_bidder_diagrams_saddle_[i].size() > max_diagram_size_sad) {
2043 max_diagram_size_sad = current_bidder_diagrams_saddle_[i].size();
2044 }
2045 }
2046 }
2047 if(do_max_) {
2048 for(int i = 0; i < numberOfInputs_; i++) {
2049 if(current_bidder_diagrams_max_[i].size() > max_diagram_size_max) {
2050 max_diagram_size_max = current_bidder_diagrams_max_[i].size();
2051 }
2052 }
2053 }
2054 int const max_points_to_add_min
2055 = std::max(min_points_to_add[0],
2056 min_points_to_add[0] + (int)(max_diagram_size_min / 10));
2057 int const max_points_to_add_sad
2058 = std::max(min_points_to_add[1],
2059 min_points_to_add[1] + (int)(max_diagram_size_sad / 10));
2060 int const max_points_to_add_max
2061 = std::max(min_points_to_add[2],
2062 min_points_to_add[2] + (int)(max_diagram_size_max / 10));
2063
2064 // 2. Get which points can be added, deduce the new minimal persistence
2065 std::vector<std::vector<int>> candidates_to_be_added_min(numberOfInputs_);
2066 std::vector<std::vector<int>> candidates_to_be_added_sad(numberOfInputs_);
2067 std::vector<std::vector<int>> candidates_to_be_added_max(numberOfInputs_);
2068 std::vector<std::vector<int>> idx_min(numberOfInputs_);
2069 std::vector<std::vector<int>> idx_sad(numberOfInputs_);
2070 std::vector<std::vector<int>> idx_max(numberOfInputs_);
2071
2072 if(do_min_) {
2073 for(int i = 0; i < numberOfInputs_; i++) {
2074 std::vector<double> persistences;
2075 for(size_t j = 0; j < bidder_diagrams_min_[i].size(); j++) {
2076 Bidder const b = bidder_diagrams_min_[i].at(j);
2077 double const persistence = b.getPersistence();
2078 if(persistence >= min_persistence[0]
2079 && persistence <= previous_min_persistence[0]) {
2080 candidates_to_be_added_min[i].emplace_back(j);
2081 idx_min[i].emplace_back(idx_min[i].size());
2082 persistences.emplace_back(persistence);
2083 }
2084 }
2085 sort(
2086 idx_min[i].begin(), idx_min[i].end(), [&persistences](int &a, int &b) {
2087 return ((persistences[a] > persistences[b])
2088 || ((persistences[a] == persistences[b]) && (a > b)));
2089 });
2090 int const size = candidates_to_be_added_min[i].size();
2091 if(size >= max_points_to_add_min) {
2092 double const last_persistence_added_min
2093 = persistences[idx_min[i][max_points_to_add_min - 1]];
2094 if(first_enrichment) { // a minima min_point_to_add (=max_point_to_add)
2095 // added per diagram
2096 if(i == 0) {
2097 new_min_persistence[0] = last_persistence_added_min;
2098 } else {
2099 if(last_persistence_added_min < new_min_persistence[0])
2100 new_min_persistence[0] = last_persistence_added_min;
2101 }
2102 } else { // a maxima max_point_to_add added per diagram
2103 if(last_persistence_added_min > new_min_persistence[0]) {
2104 new_min_persistence[0] = last_persistence_added_min;
2105 }
2106 }
2107 }
2108 }
2109 }
2110
2111 if(do_sad_) {
2112 for(int i = 0; i < numberOfInputs_; i++) {
2113 std::vector<double> persistences;
2114 for(size_t j = 0; j < bidder_diagrams_saddle_[i].size(); j++) {
2115 Bidder const b = bidder_diagrams_saddle_[i].at(j);
2116 double const persistence = b.getPersistence();
2117 if(persistence >= min_persistence[1]
2118 && persistence <= previous_min_persistence[1]) {
2119 candidates_to_be_added_sad[i].emplace_back(j);
2120 idx_sad[i].emplace_back(idx_sad[i].size());
2121 persistences.emplace_back(persistence);
2122 }
2123 }
2124 sort(
2125 idx_sad[i].begin(), idx_sad[i].end(), [&persistences](int &a, int &b) {
2126 return ((persistences[a] > persistences[b])
2127 || ((persistences[a] == persistences[b]) && (a > b)));
2128 });
2129 int const size = candidates_to_be_added_sad[i].size();
2130 if(size >= max_points_to_add_sad) {
2131 double const last_persistence_added_sad
2132 = persistences[idx_sad[i][max_points_to_add_sad - 1]];
2133 if(first_enrichment) { // a minima min_point_to_add (=max_point_to_add)
2134 // added per diagram
2135 if(i == 0) {
2136 new_min_persistence[1] = last_persistence_added_sad;
2137 } else {
2138 if(last_persistence_added_sad < new_min_persistence[1])
2139 new_min_persistence[1] = last_persistence_added_sad;
2140 }
2141 } else { // a maxima max_point_to_add added per diagram
2142 if(last_persistence_added_sad > new_min_persistence[1]) {
2143 new_min_persistence[1] = last_persistence_added_sad;
2144 }
2145 }
2146 }
2147 }
2148 }
2149 if(do_max_) {
2150 for(int i = 0; i < numberOfInputs_; i++) {
2151 std::vector<double> persistences;
2152 for(size_t j = 0; j < bidder_diagrams_max_[i].size(); j++) {
2153 Bidder const b = bidder_diagrams_max_[i].at(j);
2154 double const persistence = b.getPersistence();
2155 if(persistence >= min_persistence[2]
2156 && persistence <= previous_min_persistence[2]) {
2157 candidates_to_be_added_max[i].emplace_back(j);
2158 idx_max[i].emplace_back(idx_max[i].size());
2159 persistences.emplace_back(persistence);
2160 }
2161 }
2162 sort(
2163 idx_max[i].begin(), idx_max[i].end(), [&persistences](int &a, int &b) {
2164 return ((persistences[a] > persistences[b])
2165 || ((persistences[a] == persistences[b]) && (a > b)));
2166 });
2167 int const size = candidates_to_be_added_max[i].size();
2168 if(size >= max_points_to_add_max) {
2169 double const last_persistence_added_max
2170 = persistences[idx_max[i][max_points_to_add_max - 1]];
2171 if(first_enrichment) { // a minima min_point_to_add (=max_point_to_add)
2172 // added per diagram
2173 if(i == 0) {
2174 new_min_persistence[2] = last_persistence_added_max;
2175 } else {
2176 if(last_persistence_added_max < new_min_persistence[2])
2177 new_min_persistence[2] = last_persistence_added_max;
2178 }
2179 } else { // a maxima max_point_to_add added per diagram
2180 if(last_persistence_added_max > new_min_persistence[2]) {
2181 new_min_persistence[2] = last_persistence_added_max;
2182 }
2183 }
2184 }
2185 }
2186 }
2187
2188 // 3. Add the points to the current diagrams
2189 if(do_min_) {
2190 int counter_for_adding_points = 0;
2191 for(int i = 0; i < numberOfInputs_; i++) {
2192 int const size = candidates_to_be_added_min[i].size();
2193 for(int j = 0; j < std::min(max_points_to_add_min, size); j++) {
2194 Bidder b = bidder_diagrams_min_[i].at(
2195 candidates_to_be_added_min[i][idx_min[i][j]]);
2196 double const persistence = b.getPersistence();
2197 if(persistence >= new_min_persistence[0]) {
2198 b.id_ = current_bidder_diagrams_min_[i].size();
2199 b.setPositionInAuction(current_bidder_diagrams_min_[i].size());
2200 b.setDiagonalPrice(initial_diagonal_prices[0][i]);
2201 current_bidder_diagrams_min_[i].emplace_back(b);
2202 current_bidder_ids_min_[i]
2203 [candidates_to_be_added_min[i][idx_min[i][j]]]
2204 = current_bidder_diagrams_min_[i].size() - 1;
2205
2206 if(use_accelerated_ && n_iterations_ > 0) {
2207 for(int c = 0; c < k_; ++c) {
2208 // Step 5 of Accelerated KMeans: Update the lower bound on
2209 // distance thanks to the triangular inequality
2210 l_[i][c]
2211 = Geometry::pow(Geometry::pow(l_[i][c], 1. / wasserstein_)
2212 - persistence / sqrt(2),
2213 wasserstein_);
2214 if(l_[i][c] < 0) {
2215 l_[i][c] = 0;
2216 }
2217 }
2218 // Step 6, update the upper bound on the distance to the centroid
2219 // thanks to the triangle inequality
2220 u_[i] = Geometry::pow(
2221 Geometry::pow(u_[i], 1. / wasserstein_) + persistence / sqrt(2),
2222 wasserstein_);
2223 r_[i] = true;
2224 }
2225 int const to_be_added_to_barycenter
2226 = deterministic_ ? counter_for_adding_points % numberOfInputs_
2227 : rand() % numberOfInputs_;
2228 if(to_be_added_to_barycenter == 0 && add_points_to_barycenter) {
2229 for(int k = 0; k < numberOfInputs_; k++) {
2230 if(inv_clustering_[i] == inv_clustering_[k]) {
2231 Good g = Good(
2232 b.x_, b.y_, false, centroids_with_price_min_[k].size());
2233 g.setPrice(initial_off_diagonal_prices[0][k]);
2235 b.coords_[0], b.coords_[1], b.coords_[2]);
2236 centroids_with_price_min_[k].emplace_back(g);
2237 }
2238 }
2239 Good g = Good(
2240 b.x_, b.y_, false, centroids_min_[inv_clustering_[i]].size());
2241 g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
2242 centroids_min_[inv_clustering_[i]].emplace_back(g);
2243 }
2244 }
2245 counter_for_adding_points++;
2246 }
2247 }
2248 }
2249 if(do_sad_) {
2250 int counter_for_adding_points = 0;
2251 for(int i = 0; i < numberOfInputs_; i++) {
2252 int const size = candidates_to_be_added_sad[i].size();
2253 for(int j = 0; j < std::min(max_points_to_add_sad, size); j++) {
2254 Bidder b = bidder_diagrams_saddle_[i].at(
2255 candidates_to_be_added_sad[i][idx_sad[i][j]]);
2256 double const persistence = b.getPersistence();
2257 if(persistence >= new_min_persistence[1]) {
2258 b.id_ = current_bidder_diagrams_saddle_[i].size();
2259 b.setPositionInAuction(current_bidder_diagrams_saddle_[i].size());
2260 b.setDiagonalPrice(initial_diagonal_prices[1][i]);
2261 current_bidder_diagrams_saddle_[i].emplace_back(b);
2262 current_bidder_ids_sad_[i]
2263 [candidates_to_be_added_sad[i][idx_sad[i][j]]]
2264 = current_bidder_diagrams_saddle_[i].size() - 1;
2265
2266 if(use_accelerated_ && n_iterations_ > 0) {
2267 for(int c = 0; c < k_; ++c) {
2268 // Step 5 of Accelerated KMeans: Update the lower bound on
2269 // distance thanks to the triangular inequality
2270 l_[i][c]
2271 = Geometry::pow(Geometry::pow(l_[i][c], 1. / wasserstein_)
2272 - persistence / sqrt(2),
2273 wasserstein_);
2274 if(l_[i][c] < 0) {
2275 l_[i][c] = 0;
2276 }
2277 }
2278 // Step 6, update the upper bound on the distance to the centroid
2279 // thanks to the triangle inequality
2280 u_[i] = Geometry::pow(
2281 Geometry::pow(u_[i], 1. / wasserstein_) + persistence / sqrt(2),
2282 wasserstein_);
2283 r_[i] = true;
2284 }
2285 int const to_be_added_to_barycenter
2286 = deterministic_ ? counter_for_adding_points % numberOfInputs_
2287 : rand() % numberOfInputs_;
2288 if(to_be_added_to_barycenter == 0 && add_points_to_barycenter) {
2289 for(int k = 0; k < numberOfInputs_; k++) {
2290 if(inv_clustering_[i] == inv_clustering_[k]) {
2291 Good g = Good(
2292 b.x_, b.y_, false, centroids_with_price_saddle_[k].size());
2293 g.setPrice(initial_off_diagonal_prices[1][k]);
2295 b.coords_[0], b.coords_[1], b.coords_[2]);
2296 centroids_with_price_saddle_[k].emplace_back(g);
2297 }
2298 }
2299 }
2300 }
2301 counter_for_adding_points++;
2302 }
2303 }
2304 }
2305 if(do_max_) {
2306 int counter_for_adding_points = 0;
2307 for(int i = 0; i < numberOfInputs_; i++) {
2308 int const size = candidates_to_be_added_max[i].size();
2309 for(int j = 0; j < std::min(max_points_to_add_max, size); j++) {
2310 Bidder b = bidder_diagrams_max_[i].at(
2311 candidates_to_be_added_max[i][idx_max[i][j]]);
2312 double const persistence = b.getPersistence();
2313 if(persistence >= new_min_persistence[2]) {
2314 b.id_ = current_bidder_diagrams_max_[i].size();
2315 b.setPositionInAuction(current_bidder_diagrams_max_[i].size());
2316 b.setDiagonalPrice(initial_diagonal_prices[2][i]);
2317 current_bidder_diagrams_max_[i].emplace_back(b);
2318 current_bidder_ids_max_[i]
2319 [candidates_to_be_added_max[i][idx_max[i][j]]]
2320 = current_bidder_diagrams_max_[i].size() - 1;
2321
2322 if(use_accelerated_ && n_iterations_ > 0) {
2323 for(int c = 0; c < k_; ++c) {
2324 // Step 5 of Accelerated KMeans: Update the lower bound on
2325 // distance thanks to the triangular inequality
2326 l_[i][c]
2327 = Geometry::pow(Geometry::pow(l_[i][c], 1. / wasserstein_)
2328 - persistence / sqrt(2),
2329 wasserstein_);
2330 if(l_[i][c] < 0) {
2331 l_[i][c] = 0;
2332 }
2333 }
2334 // Step 6, update the upper bound on the distance to the centroid
2335 // thanks to the triangle inequality
2336 u_[i] = Geometry::pow(
2337 Geometry::pow(u_[i], 1. / wasserstein_) + persistence / sqrt(2),
2338 wasserstein_);
2339 r_[i] = true;
2340 }
2341 int const to_be_added_to_barycenter
2342 = deterministic_ ? counter_for_adding_points % numberOfInputs_
2343 : rand() % numberOfInputs_;
2344 if(to_be_added_to_barycenter == 0 && add_points_to_barycenter) {
2345 for(int k = 0; k < numberOfInputs_; k++) {
2346 if(inv_clustering_[i] == inv_clustering_[k]) {
2347 Good g = Good(
2348 b.x_, b.y_, false, centroids_with_price_max_[k].size());
2349 g.setPrice(initial_off_diagonal_prices[2][k]);
2351 b.coords_[0], b.coords_[1], b.coords_[2]);
2352 centroids_with_price_max_[k].emplace_back(g);
2353 }
2354 }
2355 Good g = Good(
2356 b.x_, b.y_, false, centroids_max_[inv_clustering_[i]].size());
2357 g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
2358 centroids_max_[inv_clustering_[i]].emplace_back(g);
2359 }
2360 }
2361 counter_for_adding_points++;
2362 }
2363 }
2364 }
2365
2366 return new_min_persistence;
2367}
2368
2370 std::vector<double> & /*min_persistence*/) {
2371
2372 if(do_min_) {
2373 barycenter_computer_min_.resize(k_);
2374 for(int c = 0; c < k_; c++) {
2375 std::vector<BidderDiagram> diagrams_c;
2376 for(int const idx : clustering_[c]) {
2377 diagrams_c.emplace_back(current_bidder_diagrams_min_[idx]);
2378 }
2379 barycenter_computer_min_[c] = {};
2380 barycenter_computer_min_[c].setThreadNumber(threadNumber_);
2381 barycenter_computer_min_[c].setWasserstein(wasserstein_);
2382 barycenter_computer_min_[c].setDiagramType(0);
2383 barycenter_computer_min_[c].setUseProgressive(false);
2384 barycenter_computer_min_[c].setDeterministic(true);
2385 barycenter_computer_min_[c].setGeometricalFactor(geometrical_factor_);
2386 barycenter_computer_min_[c].setDebugLevel(debugLevel_);
2387 barycenter_computer_min_[c].setNumberOfInputs(diagrams_c.size());
2388 barycenter_computer_min_[c].setCurrentBidders(diagrams_c);
2389 barycenter_computer_min_[c].setNonMatchingWeight(nonMatchingWeight_);
2390 }
2391 }
2392 if(do_sad_) {
2393 barycenter_computer_sad_.resize(k_);
2394 for(int c = 0; c < k_; c++) {
2395 std::vector<BidderDiagram> diagrams_c;
2396 for(int const idx : clustering_[c]) {
2397 diagrams_c.emplace_back(current_bidder_diagrams_saddle_[idx]);
2398 }
2399 barycenter_computer_sad_[c] = {};
2400 barycenter_computer_sad_[c].setThreadNumber(threadNumber_);
2401 barycenter_computer_sad_[c].setWasserstein(wasserstein_);
2402 barycenter_computer_sad_[c].setDiagramType(1);
2403 barycenter_computer_sad_[c].setUseProgressive(false);
2404 barycenter_computer_sad_[c].setDeterministic(true);
2405 barycenter_computer_sad_[c].setGeometricalFactor(geometrical_factor_);
2406 barycenter_computer_sad_[c].setDebugLevel(debugLevel_);
2407 barycenter_computer_sad_[c].setNumberOfInputs(diagrams_c.size());
2408 barycenter_computer_sad_[c].setCurrentBidders(diagrams_c);
2409 barycenter_computer_sad_[c].setNonMatchingWeight(nonMatchingWeight_);
2410
2411 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
2412 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
2413 i_diagram++) {
2414 barycenter_goods[i_diagram]
2415 = centroids_with_price_saddle_[clustering_[c][i_diagram]];
2416 }
2417 barycenter_computer_sad_[c].setCurrentBarycenter(barycenter_goods);
2418 }
2419 }
2420 if(do_max_) {
2421 barycenter_computer_max_.resize(k_);
2422 for(int c = 0; c < k_; c++) {
2423 std::vector<BidderDiagram> diagrams_c;
2424 for(int const idx : clustering_[c]) {
2425 diagrams_c.emplace_back(current_bidder_diagrams_max_[idx]);
2426 }
2427 barycenter_computer_max_[c] = {};
2428 barycenter_computer_max_[c].setDiagrams(inputDiagramsMax_);
2429 barycenter_computer_max_[c].setThreadNumber(threadNumber_);
2430 barycenter_computer_max_[c].setWasserstein(wasserstein_);
2431 barycenter_computer_max_[c].setDiagramType(2);
2432 barycenter_computer_max_[c].setUseProgressive(false);
2433 barycenter_computer_max_[c].setDeterministic(true);
2434 barycenter_computer_max_[c].setGeometricalFactor(geometrical_factor_);
2435 barycenter_computer_max_[c].setDebugLevel(debugLevel_);
2436 barycenter_computer_max_[c].setNumberOfInputs(diagrams_c.size());
2437 barycenter_computer_max_[c].setCurrentBidders(diagrams_c);
2438 barycenter_computer_max_[c].setNonMatchingWeight(nonMatchingWeight_);
2439
2440 std::vector<GoodDiagram> barycenter_goods(clustering_[c].size());
2441 for(size_t i_diagram = 0; i_diagram < clustering_[c].size();
2442 i_diagram++) {
2443 barycenter_goods[i_diagram]
2444 = centroids_with_price_max_[clustering_[c][i_diagram]];
2445 }
2446 barycenter_computer_max_[c].setCurrentBarycenter(barycenter_goods);
2447 }
2448 }
2449}
2450
2452 std::ofstream ufile("u_vec.txt");
2453 std::ofstream lfile("l_mat.txt");
2454 std::ofstream approx_file("a_mat.txt");
2455 if(ufile.is_open() && lfile.is_open()) {
2456 for(int i = 0; i < numberOfInputs_; i++) {
2457 ufile << u_[i] << " ";
2458 for(int j = 0; j < k_; j++) {
2459 lfile << l_[i][j] << " ";
2460 }
2461 lfile << "\n";
2462 }
2463 }
2464
2465 for(int c = 0; c < k_; c++) {
2466 for(int const i : clustering_[c]) {
2467 approx_file << (u_[i] + l_[i][c]) / 2 << " ";
2468 }
2469 approx_file << "\n";
2470 }
2471 lfile.close();
2472 ufile.close();
2473 approx_file.close();
2474}
2475
2477 std::cout << "Computing real distances to every clusters" << std::endl;
2478 std::ofstream file("a_real_mat.txt");
2479 if(file.is_open()) {
2480 for(int c = 0; c < k_; c++) {
2481 for(int const i : clustering_[c]) {
2482 file << distanceToCentroid_[i] << " ";
2483 }
2484 file << "\n";
2485 }
2486 file.close();
2487 } else {
2488 std::cout << "file not open" << std::endl;
2489 }
2490}
2491
2493 std::ofstream file(
2494 "prices_evolution.txt", std::ofstream::out | std::ofstream::app);
2495 if(file.is_open()) {
2496 file << "\nITERATION " << iteration << "\n" << std::endl;
2497 for(int i = 0; i < k_; i++) {
2498 file << "\ncentroid " << i << std::endl;
2499
2500 for(size_t j = 0; j < centroids_with_price_max_[i].size(); j++) {
2501 Good const g = centroids_with_price_max_[i].at(j);
2502 file << g.getPrice() << " ";
2503 }
2504 }
2505 }
2506 file.close();
2507}
2508
2510 double total_real_cost_min = 0;
2511 double total_real_cost_max = 0;
2512 double total_real_cost_sad = 0;
2513 double sq_distance;
2514 if(original_dos[0]) {
2515 for(int c = 0; c < k_; c++) {
2516 double real_cost_cluster = 0;
2517 for(int i = 0; i < numberOfInputs_; i++) {
2518 GoodDiagram const current_barycenter
2519 = centroidWithZeroPrices(centroids_min_[c]);
2520 sq_distance
2521 = computeDistance(bidder_diagrams_min_[i], current_barycenter, 0.01);
2522 real_cost_cluster += sq_distance;
2523 }
2524 total_real_cost_min += real_cost_cluster;
2525 }
2526 }
2527 if(original_dos[1]) {
2528 for(int c = 0; c < k_; c++) {
2529 double real_cost_cluster = 0;
2530 for(int i = 0; i < numberOfInputs_; i++) {
2531 GoodDiagram const current_barycenter
2532 = centroidWithZeroPrices(centroids_saddle_[c]);
2533 sq_distance = computeDistance(
2534 bidder_diagrams_saddle_[i], current_barycenter, 0.01);
2535 real_cost_cluster += sq_distance;
2536 }
2537 total_real_cost_sad += real_cost_cluster;
2538 }
2539 }
2540 if(original_dos[2]) {
2541 for(int c = 0; c < k_; c++) {
2542 double real_cost_cluster = 0;
2543 for(int i = 0; i < numberOfInputs_; i++) {
2544 GoodDiagram const current_barycenter
2545 = centroidWithZeroPrices(centroids_max_[c]);
2546 sq_distance
2547 = computeDistance(bidder_diagrams_max_[i], current_barycenter, 0.01);
2548 real_cost_cluster += sq_distance;
2549 }
2550 total_real_cost_max += real_cost_cluster;
2551 }
2552 }
2553 return total_real_cost_min + total_real_cost_sad + total_real_cost_max;
2554}
2555
2557 std::vector<std::vector<std::vector<std::vector<MatchingType>>>>
2558 &all_matchings_per_type_and_cluster) {
2559
2560 if(do_min_) {
2561 computeBarycenterForTwo(
2562 all_matchings_per_type_and_cluster[0][0], current_bidder_ids_min_,
2563 current_bidder_diagrams_min_, bidder_diagrams_min_, centroids_min_[0]);
2564 }
2565 if(do_sad_) {
2566 computeBarycenterForTwo(all_matchings_per_type_and_cluster[0][1],
2567 current_bidder_ids_sad_,
2568 current_bidder_diagrams_saddle_,
2569 bidder_diagrams_saddle_, centroids_saddle_[0]);
2570 }
2571 if(do_max_) {
2572 computeBarycenterForTwo(
2573 all_matchings_per_type_and_cluster[0][2], current_bidder_ids_max_,
2574 current_bidder_diagrams_max_, bidder_diagrams_max_, centroids_max_[0]);
2575 }
2576}
2577
2579 std::vector<std::vector<MatchingType>> &matchings,
2580 std::vector<std::vector<int>> &bidders_ids,
2581 std::vector<BidderDiagram> &current_bidder_diagrams,
2582 std::vector<BidderDiagram> &bidder_diagrams,
2583 GoodDiagram &barycenter) {
2584
2585 auto &matchings0 = matchings[0];
2586 auto &diagram0 = bidder_diagrams[0];
2587 auto &current_diagram0 = current_bidder_diagrams[0];
2588 auto &ids0 = bidders_ids[0];
2589
2590 auto &matchings1 = matchings[1];
2591 auto &diagram1 = bidder_diagrams[1];
2592 auto &current_diagram1 = current_bidder_diagrams[1];
2593 auto &ids1 = bidders_ids[1];
2594
2595 std::vector<int> new_to_old_id(current_diagram1.size());
2596 // 1. Invert the current_bidder_ids_ vector
2597 for(size_t j = 0; j < ids1.size(); j++) {
2598 int const new_id = ids1[j];
2599 if(new_id >= 0) {
2600 new_to_old_id[new_id] = j;
2601 }
2602 }
2603
2604 std::vector<MatchingType> matching_to_add(0);
2605 std::vector<MatchingType> matching_to_add2(0);
2606
2607 for(size_t i = 0; i < matchings1.size(); i++) {
2608 MatchingType &t = matchings1[i];
2609 int const bidderId = std::get<0>(t);
2610 int const goodId = std::get<1>(t);
2611
2612 if(bidderId >= 0) {
2613 Bidder const b = diagram1.at(new_to_old_id[bidderId]);
2614 double const bx = b.x_;
2615 double const by = b.y_;
2616 if(goodId >= 0) {
2617 Good const g = barycenter.at(goodId);
2618 double const gx = g.x_;
2619 double const gy = g.y_;
2620 barycenter.at(goodId).x_ = (bx + gx) / 2;
2621 barycenter.at(goodId).y_ = (by + gy) / 2;
2622 // divide by 4 in order to display the cost of the half matching
2623 // i.e. the cost of matching to the barycenter
2624 std::get<2>(t) /= 4;
2625
2626 } else {
2627 double gx = (bx + by) / 2;
2628 double gy = (bx + by) / 2;
2629 gx = (gx + bx) / 2;
2630 gy = (gy + by) / 2;
2631 double const cost = nonMatchingWeight_
2632 * (Geometry::pow((gx - bx), wasserstein_)
2633 + Geometry::pow((gy - by), wasserstein_));
2634 MatchingType const t2
2635 = std::make_tuple(bidderId, barycenter.size(), cost);
2636 MatchingType const t3 = std::make_tuple(-1, barycenter.size(), cost);
2637 Good const g = Good(gx, gy, false, barycenter.size());
2638 // g.SetCriticalCoordinates(b.coords_[0], b.coords_[1], b.coords_[2]);
2639 barycenter.emplace_back(g);
2640 matching_to_add.emplace_back(t2);
2641 matching_to_add2.emplace_back(t3);
2642 }
2643 } else {
2644 if(goodId >= 0) {
2645 Good const g = barycenter.at(goodId);
2646 double const gx = (g.x_ + g.y_) / 2;
2647 double const gy = (g.x_ + g.y_) / 2;
2648 barycenter.at(goodId).x_ = (gx + g.x_) / 2;
2649 barycenter.at(goodId).y_ = (gy + g.y_) / 2;
2650 std::get<2>(t) /= 4;
2651 }
2652 }
2653 }
2654 for(size_t j = 0; j < matching_to_add.size(); j++) {
2655 matchings1.emplace_back(matching_to_add[j]);
2656 }
2657 for(size_t j = 0; j < matching_to_add2.size(); j++) {
2658 matchings0.emplace_back(matching_to_add2[j]);
2659 }
2660
2661 // correct the costs of matchings in diagram 0
2662 // costs are initially allzeros because the barycenter is identical
2663 // to diagram 0
2664 std::vector<int> new_to_old_id2(current_diagram0.size());
2665 // 1. Invert the current_bidder_ids_ vector
2666 for(size_t j = 0; j < ids0.size(); j++) {
2667 int const new_id = ids0[j];
2668 if(new_id >= 0) {
2669 new_to_old_id2[new_id] = j;
2670 }
2671 }
2672
2673 for(size_t i = 0; i < matchings0.size(); i++) {
2674 MatchingType &t = matchings0[i];
2675 int const bidderId = std::get<0>(t);
2676 int const goodId = std::get<1>(t);
2677
2678 if(bidderId >= 0 and goodId >= 0) {
2679 Bidder const b = diagram0.at(new_to_old_id2[bidderId]);
2680 double const bx = b.x_;
2681 double const by = b.y_;
2682 Good const g = barycenter.at(goodId);
2683 double const gx = g.x_;
2684 double const gy = g.y_;
2685 double const cost = Geometry::pow((gx - bx), wasserstein_)
2686 + Geometry::pow((gy - by), wasserstein_);
2687 std::get<2>(t) = cost;
2688 }
2689 }
2690}
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_
double getLessPersistent(int type=-1)
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)
BidderDiagram centroidToDiagram(const GoodDiagram &centroid)
void initializeCentroidsKMeanspp()
double computeDistance(const BidderDiagram &D1, const BidderDiagram &D2, const double delta_lim)
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)
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::array< double, 3 > epsilon_
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)
GoodDiagram centroidWithZeroPrices(const GoodDiagram &centroid)
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)
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
std::vector< Bidder > BidderDiagram
CriticalType
default value for critical index
Definition DataTypes.h:80
std::vector< PersistencePair > DiagramType
Persistence Diagram type as a vector of Persistence pairs.
std::tuple< int, int, double > MatchingType
Matching between two Persistence Diagram pairs.
std::vector< Good > GoodDiagram
T end(std::pair< T, T > &p)
Definition ripserpy.cpp:483
T begin(std::pair< T, T > &p)
Definition ripserpy.cpp:479
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)