3 * \remark This file is part of VITA.
5 * \copyright Copyright (C) 2013-2022 EOS di Manlio Morini.
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
10 * You can obtain one at http://mozilla.org/MPL/2.0/
13#if !defined(VITA_ANALYZER_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(VITA_ANALYZER_TCC)
18#define VITA_ANALYZER_TCC
21/// New empty analyzer.
24analyzer<T>::analyzer()
30/// Resets gathered statics.
33void analyzer<T>::clear()
39 functions_ = sym_counter();
40 terminals_ = sym_counter();
47/// \return a constant reference to the first statistical symbol we have
51typename analyzer<T>::const_iterator analyzer<T>::begin() const
53 return sym_counter_.begin();
57/// \return a constant reference (sentry) used for loops
60typename analyzer<T>::const_iterator analyzer<T>::end() const
62 return sym_counter_.end();
66/// \param[in] eff effective / noneffective functions
67/// \return number of functions in the population
70std::uintmax_t analyzer<T>::functions(bool eff) const
72 return functions_.counter[eff];
76/// \param[in] eff effective / noneffective terminals
77/// \return number of terminals in the population
80std::uintmax_t analyzer<T>::terminals(bool eff) const
82 return terminals_.counter[eff];
86/// \return statistics about the age distribution of the individuals
89const distribution<double> &analyzer<T>::age_dist() const
95/// \param[in] g a group
96/// \return statistics about the age distribution of individuals in group
100const distribution<double> &analyzer<T>::age_dist(unsigned g) const
102 const auto gi(group_stat_.find(g));
103 assert(gi != group_stat_.end());
105 return gi->second.age;
109/// \return statistics about the fitness distribution of the individuals
112const distribution<fitness_t> &analyzer<T>::fit_dist() const
118/// \param[in] g a group
119/// \return statistics about the fitness distribution of individuals in
123const distribution<fitness_t> &analyzer<T>::fit_dist(unsigned g) const
125 const auto gi(group_stat_.find(g));
126 assert(gi != group_stat_.end());
128 return gi->second.fitness;
132/// \return statistic about the length distribution of the individuals
135const distribution<double> &analyzer<T>::length_dist() const
141/// \param[in] sym symbol we are gathering statistics about
142/// \param[in] active is this an active gene?
144/// Used by `count(const T &)`.
147void analyzer<T>::count(const symbol *sym, bool active)
151 ++sym_counter_[sym].counter[active];
154 ++terminals_.counter[active];
156 ++functions_.counter[active];
160/// \return `true` if the object passes the internal consistency check
163bool analyzer<T>::is_valid() const
165 return std::all_of(sym_counter_.begin(), sym_counter_.end(),
168 return e.second.counter[true] <= e.second.counter[false];
173/// Adds a new individual to the pool used to calculate statistics.
175/// \param[in] ind new individual
176/// \param[in] f fitness of the new individual
177/// \param[in] g a group of the population
179/// The optional `g` parameter can be used to group information (e.g. for the
180/// ALPS algorithm it's used for layer specific statistics).
183void analyzer<T>::add(const T &ind, const fitness_t &f, unsigned g)
186 group_stat_[g].age.add(ind.age());
188 length_.add(count(ind));
193 group_stat_[g].fitness.add(f);
198/// \tparam T type of individual
200/// \param[in] ind individual to be analyzed
201/// \return effective length of individual we gathered statistics about
204std::size_t analyzer<T>::count(const T &ind)
206 return count_team(ind, is_team<T>());
210/// Specialization of `count_team(T)` for non-team.
214std::size_t analyzer<T>::count_team(const U &ind, std::false_type)
216 return count_introns(ind, has_introns<T>());
220/// Specialization of `count_team(T)` for teams.
223std::size_t analyzer<T>::count_team(const T &t, std::true_type)
225 return std::accumulate(t.begin(), t.end(), std::size_t{0},
226 [=](auto s, const auto &ind)
228 return s + count_team(ind, std::false_type());
233/// Specialization of `count_introns(U)` for individuals with introns.
237std::size_t analyzer<T>::count_introns(const U &ind, std::true_type)
239 for (index_t i(0); i < ind.size(); ++i)
240 for (category_t c(0); c < ind.categories(); ++c)
241 count(ind[{i, c}].sym, false);
243 return count_introns(ind, std::false_type());
247/// Specialization of `count_introns(U)` for individuals without introns.
251std::size_t analyzer<T>::count_introns(const U &ind, std::false_type)
253 std::size_t length(0);
254 for (const auto &g : ind)
264/// \param[in] ind individual to be analyzed
265/// \return effective length of individual we gathered statistics about
268inline std::size_t analyzer<i_de>::count(const i_de &ind)
270 return ind.parameters();
274/// \param[in] ind individual to be analyzed
275/// \return effective length of individual we gathered statistics about
278inline std::size_t analyzer<i_ga>::count(const i_ga &ind)
280 return ind.parameters();
283#endif // include guard