Skip to content

Commit 6b20571

Browse files
committed
Fix wrong scoring tendancy
CURA-12324 When processing the last criterion pass, we used to keep all the best candidates in regard to the scoring threshold, then the first one of them would be returned, which is not always the one with the actual best score. Now we just early-out with the best candidate in case of the last pass. This is also more efficient.
1 parent ffe59a8 commit 6b20571

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

include/utils/scoring/BestElementFinder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class ScoringCriterion;
1515

1616
/*!
1717
* This class implements an algorithm to find an element amongst a list, regarding one or multiple scoring criteria. The
18-
* criteria are implemented by subclassing the CriterionScoring class. It is also possible to setup multiple passes of
18+
* criteria are implemented by subclassing the CriterionScoring class. It is also possible to set up multiple passes of
1919
* criteria. Thus, if the first pass gives a few best candidates that are too close to each other, we keep only the best
2020
* candidates and process a second pass with different criteria, and so on until we have a single outsider, or no more
2121
* criteria.
@@ -60,6 +60,7 @@ class BestElementFinder
6060
* Once we have calculated the global scores of each element for this pass, we calculate the score difference
6161
* between the best candidate and the following ones. If the following ones have a score close enough to the
6262
* best, within this threshold, they will also be considered outsiders and will be run for the next pass.
63+
* This value will be ignored for the last pass.
6364
*/
6465
double outsider_delta_threshold{ 0.0 };
6566
};

src/utils/scoring/BestElementFinder.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include <limits>
77

8+
#include <range/v3/view/enumerate.hpp>
9+
810
#include "utils/scoring/ScoringCriterion.h"
911

1012
namespace cura
@@ -33,11 +35,11 @@ std::optional<size_t> cura::BestElementFinder::findBestElement(const size_t cand
3335
const auto begin = best_candidates.begin();
3436
auto end = best_candidates.end();
3537

36-
// Now run the criteria passes until we have a single outsider or no more cirteria
37-
for (const CriteriaPass& criteria_pass : criteria_)
38+
// Now run the criteria passes until we have a single outsider or no more criteria
39+
for (const auto& [pass_index, criteria_pass] : criteria_ | ranges::views::enumerate)
3840
{
3941
// For each element, reset score, process each criterion and apply weights to get the global score
40-
double best_score = 0.0;
42+
auto best_candidate_iterator = end;
4143
for (auto iterator = begin; iterator != end; ++iterator)
4244
{
4345
iterator->score = 0.0;
@@ -47,17 +49,32 @@ std::optional<size_t> cura::BestElementFinder::findBestElement(const size_t cand
4749
iterator->score += weighed_criterion.criterion->computeScore(iterator->candidate_index) * weighed_criterion.weight;
4850
}
4951

50-
best_score = std::max(best_score, iterator->score);
52+
if (best_candidate_iterator == end || iterator->score > best_candidate_iterator->score)
53+
{
54+
best_candidate_iterator = iterator;
55+
}
56+
}
57+
58+
if (best_candidate_iterator == end)
59+
{
60+
// Something got wrong, we have not best candidate
61+
return std::nullopt;
62+
}
63+
64+
// Early out for last pass, just keep the best candidate
65+
if (pass_index == criteria_.size() - 1)
66+
{
67+
return best_candidate_iterator->candidate_index;
5168
}
5269

5370
// Skip candidates that have a score too far from the actual best one
5471
const double delta_threshold = criteria_pass.outsider_delta_threshold + std::numeric_limits<double>::epsilon();
5572
end = std::remove_if(
5673
begin,
5774
end,
58-
[&best_score, &delta_threshold](const Candidate& candidate)
75+
[&best_candidate_iterator, &delta_threshold](const Candidate& candidate)
5976
{
60-
return best_score - candidate.score > delta_threshold;
77+
return best_candidate_iterator->score - candidate.score > delta_threshold;
6178
});
6279

6380
if (std::distance(begin, end) == 1)

0 commit comments

Comments
 (0)