74 std::vector<MatchingType> &matchings,
bool get_diagonal_matches) {
75 double wassersteinDistance = 0;
76 for(
size_t i = 0; i < bidders_.size(); i++) {
77 Bidder const &b = bidders_[i];
86 MatchingType const t = std::make_tuple(i, good_id, cost);
87 matchings.emplace_back(t);
90 this->printWrn(
"both the bidder and the good are diagonal points");
93 if(get_diagonal_matches) {
94 MatchingType const t = std::make_tuple(i, good_id, cost);
95 matchings.emplace_back(t);
98 wassersteinDistance += cost;
104 if(get_diagonal_matches) {
106 matchings.emplace_back(t);
108 wassersteinDistance += cost;
111 return wassersteinDistance;
116 for(
unsigned int i = 0; i < bidders_.size(); ++i) {
117 if(bidders_[i].isDiagonal())
121 double bestCost = std::numeric_limits<double>::max();
122 std::vector<KDT *> neighbours;
123 std::vector<double> costs;
125 std::array<double, 5> coordinates;
126 bidders_[i].GetKDTCoordinates(geometricalFactor_, coordinates);
127 kdt_.getKClosest(1, coordinates, neighbours, costs, kdt_index);
128 int const bestIndex = neighbours[0]->id_;
129 bestCost = bidders_[i].cost(goods_[bestIndex], wasserstein_,
130 geometricalFactor_, nonMatchingWeight_);
132 for(
unsigned int j = 0; j < goods_.size(); ++j) {
133 double const cost = bidders_[i].cost(
134 goods_[j], wasserstein_, geometricalFactor_, nonMatchingWeight_);
141 Good g{bidders_[i].
x_, bidders_[i].y_,
true, -bidders_[i].id_ - 1};
142 g.SetCriticalCoordinates(bidders_[i].GetCriticalCoordinates());
143 g.projectOnDiagonal();
144 double const cost = bidders_[i].cost(
145 g, wasserstein_, geometricalFactor_, nonMatchingWeight_);
150 lowerBoundCost_ += bestCost;
152 return lowerBoundCost_;
156 const int kdt_index) {
157 initLowerBoundCostWeight(delta_lim_);
158 initLowerBoundCost(kdt_index);
162 while(delta > delta_lim_) {
164 this->buildUnassignedBidders();
165 this->reinitializeGoods();
166 this->runAuctionRound(n_biddings, kdt_index);
167 delta = this->getRelativePrecision();
169 double const wassersteinDistance
170 = this->getMatchingsAndDistance(matchings,
true);
171 return wassersteinDistance;
213 double geometricalFactor,
214 double nonMatchingWeight) {
215 double best_val = std::numeric_limits<double>::lowest();
216 double second_val = std::numeric_limits<double>::lowest();
218 for(
size_t i = 0; i < goods->size(); i++) {
219 Good &g = (*goods)[i];
221 = -this->cost(g, wasserstein, geometricalFactor, nonMatchingWeight);
224 second_val = best_val;
227 }
else if(val > second_val) {
234 = -this->cost(g, wasserstein, geometricalFactor, nonMatchingWeight);
237 second_val = best_val;
240 }
else if(val > second_val) {
244 if(second_val == std::numeric_limits<double>::lowest()) {
246 second_val = best_val;
248 if(best_good ==
nullptr) {
251 double const old_price = best_good->
getPrice();
252 double new_price = old_price + best_val - second_val + epsilon;
253 if(new_price > std::numeric_limits<double>::max() / 2) {
254 new_price = old_price + epsilon;
257 this->setProperty(*best_good);
258 this->setPricePaid(new_price);
262 int const idx_reassigned = best_good->getOwner();
263 best_good->assign(this->position_in_auction_, new_price);
264 return idx_reassigned;
272 double geometricalFactor,
273 double nonMatchingWeight,
274 std::priority_queue<std::pair<int, double>,
275 std::vector<std::pair<int, double>>,
283 bool updated_top_pair
286 bool const non_empty_goods = goods->size() > 0;
287 std::pair<int, double> best_pair;
288 if(non_empty_goods) {
289 while(!updated_top_pair) {
290 std::pair<int, double> top_pair = diagonal_queue.top();
291 diagonal_queue.pop();
293 double const queue_weight = top_pair.second;
294 const auto &good = (*goods)[top_pair.first];
295 if(good.getPrice() > queue_weight) {
297 std::get<1>(top_pair) = good.getPrice();
298 diagonal_queue.push(top_pair);
300 updated_top_pair =
true;
301 best_pair = top_pair;
306 std::pair<int, double> second_pair;
307 if(non_empty_goods && diagonal_queue.size() > 0) {
308 bool updated_second_pair =
false;
309 while(!updated_second_pair) {
310 second_pair = diagonal_queue.top();
311 double const queue_weight = second_pair.second;
312 const auto &good = (*goods)[second_pair.first];
313 if(good.getPrice() != queue_weight) {
315 diagonal_queue.pop();
316 std::get<1>(second_pair) = good.getPrice();
317 diagonal_queue.push(second_pair);
319 updated_second_pair =
true;
326 double second_val = 0;
327 if(non_empty_goods) {
328 best_val = -best_pair.second;
329 second_val = diagonal_queue.size() > 0 ? -second_pair.second : best_val;
330 best_good = &(*goods)[best_pair.first];
334 bool is_twin =
false;
337 = -this->cost(g, wasserstein, geometricalFactor, nonMatchingWeight);
339 if(non_empty_goods) {
341 second_val = best_val;
345 }
else if(val > second_val || diagonal_queue.empty()) {
352 second_val = best_val;
355 if(second_val == std::numeric_limits<double>::lowest()) {
357 second_val = best_val;
359 double const old_price = best_good->
getPrice();
360 double new_price = old_price + best_val - second_val + epsilon;
361 if(new_price > std::numeric_limits<double>::max() / 2) {
362 new_price = old_price + epsilon;
366 this->setProperty(*best_good);
367 this->setPricePaid(new_price);
371 int const idx_reassigned = best_good->getOwner();
372 best_good->assign(this->position_in_auction_, new_price);
374 std::get<1>(best_pair) = new_price;
376 if(non_empty_goods) {
377 diagonal_queue.push(best_pair);
379 return idx_reassigned;
387 double geometricalFactor,
388 double nonMatchingWeight,
389 std::vector<KDT *> &correspondence_kdt_map,
390 std::priority_queue<std::pair<int, double>,
391 std::vector<std::pair<int, double>>,
393 const int kdt_index) {
401 bool updated_top_pair
404 bool const non_empty_goods = goods->size() > 0;
405 std::pair<int, double> best_pair;
406 if(non_empty_goods) {
407 while(!updated_top_pair) {
408 std::pair<int, double> top_pair = diagonal_queue.top();
409 double const queue_weight = top_pair.second;
410 const auto &good = (*goods)[top_pair.first];
412 diagonal_queue.pop();
413 if(good.getPrice() > queue_weight) {
415 std::get<1>(top_pair) = good.getPrice();
416 diagonal_queue.push(top_pair);
418 updated_top_pair =
true;
419 best_pair = top_pair;
423 std::pair<int, double> second_pair;
424 if(non_empty_goods && diagonal_queue.size() > 0) {
425 bool updated_second_pair =
false;
426 while(!updated_second_pair) {
427 second_pair = diagonal_queue.top();
428 double const queue_weight = second_pair.second;
429 const auto &good = (*goods)[second_pair.first];
430 if(good.getPrice() > queue_weight) {
432 diagonal_queue.pop();
433 std::get<1>(second_pair) = good.getPrice();
434 diagonal_queue.push(second_pair);
436 updated_second_pair =
true;
443 double second_val = 0;
444 if(non_empty_goods) {
445 best_val = -best_pair.second;
446 second_val = diagonal_queue.size() > 0 ? -second_pair.second : best_val;
447 best_good = &(*goods)[best_pair.first];
451 bool is_twin =
false;
454 = -this->cost(g, wasserstein, geometricalFactor, nonMatchingWeight);
456 if(non_empty_goods) {
458 second_val = best_val;
462 }
else if(val > second_val || diagonal_queue.empty()) {
469 second_val = best_val;
472 if(second_val == std::numeric_limits<double>::lowest()) {
474 second_val = best_val;
476 double const old_price = best_good->
getPrice();
477 double new_price = old_price + best_val - second_val + epsilon;
478 if(new_price > std::numeric_limits<double>::max() / 2) {
479 new_price = old_price + epsilon;
483 this->setProperty(*best_good);
484 this->setPricePaid(new_price);
488 int const idx_reassigned = best_good->getOwner();
489 best_good->assign(this->position_in_auction_, new_price);
492 correspondence_kdt_map[best_good->id_]->updateWeight(new_price, kdt_index);
493 if(non_empty_goods) {
494 diagonal_queue.push(best_pair);
497 if(non_empty_goods) {
498 std::get<1>(best_pair) = new_price;
499 diagonal_queue.push(best_pair);
502 return idx_reassigned;
509 double geometricalFactor,
510 double nonMatchingWeight,
512 const int kdt_index) {
515 std::vector<KDT *> neighbours;
516 std::vector<double> costs;
518 std::array<double, 5> coordinates;
519 GetKDTCoordinates(geometricalFactor, coordinates);
521 kdt->
getKClosest(2, coordinates, neighbours, costs, kdt_index);
522 double best_val, second_val;
525 if(costs.size() == 2) {
526 std::array<int, 2> idx{0, 1};
527 std::sort(idx.begin(), idx.end(),
528 [&costs](
int &a,
int &b) { return costs[a] < costs[b]; });
530 closest_kdt = neighbours[idx[0]];
531 best_good = &(*goods)[closest_kdt->
id_];
534 best_val = -costs[idx[0]];
535 second_val = -costs[idx[1]];
538 closest_kdt = neighbours[0];
539 best_good = &(*goods)[closest_kdt->
id_];
540 best_val = -costs[0];
541 second_val = best_val;
544 bool twin_chosen =
false;
547 = -this->cost(g, wasserstein, geometricalFactor, nonMatchingWeight);
550 second_val = best_val;
554 }
else if(val > second_val) {
558 if(second_val == std::numeric_limits<double>::lowest()) {
560 second_val = best_val;
562 double const old_price = best_good->
getPrice();
563 double new_price = old_price + best_val - second_val + epsilon;
564 if(new_price > std::numeric_limits<double>::max() / 2) {
565 new_price = old_price + epsilon;
568 this->setProperty(*best_good);
569 this->setPricePaid(new_price);
572 int const idx_reassigned = best_good->getOwner();
574 best_good->assign(this->position_in_auction_, new_price);
579 return idx_reassigned;
int runDiagonalBidding(GoodDiagram *goods, Good &twinGood, int wasserstein, double epsilon, double geometricalFactor, double nonMatchingWeight, std::priority_queue< std::pair< int, double >, std::vector< std::pair< int, double > >, Compare > &diagonal_queue)
int runKDTBidding(GoodDiagram *goods, Good &diagonalGood, int wasserstein, double epsilon, double geometricalFactor, double nonMatchingWeight, KDT *kdt, const int kdt_index=0)
int runDiagonalKDTBidding(GoodDiagram *goods, Good &diagonalGood, int wasserstein, double epsilon, double geometricalFactor, double nonMatchingWeight, std::vector< KDT * > &correspondence_kdt_map, std::priority_queue< std::pair< int, double >, std::vector< std::pair< int, double > >, Compare > &diagonal_queue, const int kdt_index=0)