13#if !defined(ULTRA_SEARCH_STATS_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(ULTRA_SEARCH_STATS_TCC)
18#define ULTRA_SEARCH_STATS_TCC
39template<Indiv
idual I, Fitness F>
40void search_stats<I, F>::update(
const I &lr_best_prg,
41 const model_measurements<F> &lr_measurements,
42 std::chrono::milliseconds lr_elapsed)
44 Expects(lr_measurements.fitness.has_value());
45 Expects(!std::isnan(*lr_measurements.fitness));
47 const std::size_t initial_run_id(runs());
52 auto it(std::ranges::upper_bound(
53 stats_, lr_measurements,
54 [](
const auto &lhs,
const auto &rhs)
56 if (*lhs.fitness > *rhs.fitness)
59 if (*rhs.fitness > *lhs.fitness)
62 return lhs.accuracy > rhs.accuracy;
64 &run_summary::best_measurements));
66 run_summary new_run{initial_run_id, lr_best_prg, lr_measurements};
67 stats_.insert(it, std::move(new_run));
70 if (
const auto fit(lr_measurements.fitness); fit && isfinite(*fit))
71 fitness_distribution.add(*fit);
73 elapsed += lr_elapsed;
88template<Indiv
idual I, Fitness F>
89std::set<std::size_t> search_stats<I, F>::good_runs(
90 const model_measurements<F> &threshold)
const
92 std::set<std::size_t> ret;
94 if (threshold.empty())
97 for (
const auto &s : stats_)
98 if (s.best_measurements >= threshold)
103 Ensures(ret.empty() || threshold.accuracy.has_value()
104 || ret.contains(best_run()));
116template<Indiv
idual I, Fitness F>
117std::size_t search_stats<I, F>::best_run() const noexcept
120 return stats_.front().run;
128template<Indiv
idual I, Fitness F>
129const I &search_stats<I, F>::best_individual() const noexcept
132 return stats_.front().best_individual;
140template<Indiv
idual I, Fitness F>
141const model_measurements<F> &
142search_stats<I, F>::best_measurements() const noexcept
145 return stats_.front().best_measurements;
151template<Indiv
idual I, Fitness F>
152std::size_t search_stats<I, F>::runs() const noexcept
154 return stats_.size();
168template<Indiv
idual I, Fitness F>
169double search_stats<I, F>::success_rate(
170 const model_measurements<F> &threshold)
const noexcept
172 const auto solutions(
static_cast<double>(good_runs(threshold).size()));
174 return runs() ? solutions /
static_cast<double>(runs()) : 0;
196template<Indiv
idual I, Fitness F>
197std::span<const typename search_stats<I, F>::run_summary>
198search_stats<I, F>::elite_runs(
double perc)
const noexcept
200 Expects(in_0_1(perc));
202 const std::size_t total(stats_.size());
203 if (total == 0 || issmall(perc))
206 const auto n(
static_cast<std::size_t
>(
207 std::ceil(
static_cast<double>(total) * perc)));
209 return {stats_.data(), n};