3 * \remark This file is part of VITA.
5 * \copyright Copyright (C) 2013-2023 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_TEAM_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(VITA_TEAM_TCC)
21team<T>::team() : individuals_(), signature_()
26team<T>::team(unsigned n) : individuals_(n), signature_()
31/// Creates a team of individuals that will cooperate to solve a task.
33/// \param[in] p current problem
36team<T>::team(const problem &p) : signature_()
38 Expects(p.env.team.individuals);
40 auto n(p.env.team.individuals);
41 individuals_.reserve(n);
43 for (decltype(n) i(0); i < n; ++i)
44 individuals_.emplace_back(p);
50/// Builds a team containing the individuals of a given vector.
52/// \param[in] v a vector of individuals
55team<T>::team(std::vector<T> v) : individuals_(std::move(v)), signature_()
61/// Mutates the individuals in `this` team and returns the number of mutations
64/// \param[in] pgm probability of gene mutation
65/// \param[in] prb current problem
66/// \return number of mutations performed
69unsigned team<T>::mutation(double pgm, const problem &prb)
75 const auto nm(random::element(individuals_).mutation(pgm, prb));
83 for (auto &i : individuals_)
84 nm += i.mutation(pgm, prb);
93/// \param[in] lhs first parent
94/// \param[in] rhs second parent
95/// \return the result of the crossover (we only generate a single
98/// \see individual::crossover for further details.
101team<T> crossover(const team<T> &lhs, const team<T> &rhs)
103 Expects(lhs.individuals() == rhs.individuals());
106 const auto j(random::sup(lhs.individuals()));
109 ret.individuals_[j] = crossover(lhs[j], rhs[j])
110 ret.signature_.clear();
113 const auto sup(lhs.individuals());
116 for (unsigned i(0); i < sup; ++i)
117 ret.individuals_[i] = crossover(lhs[i], rhs[i]);
119 // Clearing signature isn't required.
121 Ensures(ret.is_valid());
126/// \return an iterator pointing to the first individual of the team
129typename team<T>::const_iterator team<T>::begin() const
131 return individuals_.begin();
135/// \return an iterator pointing to a end-of-team sentry
138typename team<T>::const_iterator team<T>::end() const
140 return individuals_.end();
144/// \param[in] i index of a member of the team
145/// \return the `i`-th member of the team
148const T &team<T>::operator[](unsigned i) const
150 Expects(i < individuals());
151 return individuals_[i];
155/// \return `true` if the team is empty, `false` otherwise
158bool team<T>::empty() const
160 return individuals_.empty();
164/// \return number of individuals of the team.
167unsigned team<T>::individuals() const
169 return static_cast<unsigned>(individuals_.size());
173/// \return the number of active symbols in the team
177unsigned team<T>::active_symbols() const
179 return std::accumulate(begin(), end(), 0,
180 [](unsigned n, const T &ind)
182 return n + ind.active_symbols();
187/// Signature maps syntactically distinct (but logically equivalent)
188/// teams to the same value.
190/// \return the signature of `this` team
192/// In other words identical teams, at genotypic level, have the same
193/// signature; different teams at the genotipic level may be mapped
194/// to the same signature since the value of terminals is considered and not
197/// This is a very interesting property, useful for comparison, information
198/// retrieval, entropy calculation...
201hash_t team<T>::signature() const
203 if (signature_.empty())
210/// \return the signature of `this` team
214hash_t team<T>::hash() const
218 for_each(begin(), end(),
219 [&ret](const T &i) { ret.combine(i.signature()); });
225/// \param[in] lhs first term of comparison
226/// \param[in] rhs second term of comparision
227/// \return `true` if the two teams are equal (individual by individual)
229/// \note Age is not checked.
234bool operator==(const team<T> &lhs, const team<T> &rhs)
236 const auto sup(lhs.individuals());
237 if (sup != rhs.individuals())
240 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
244/// \param[in] lhs first term of comparison
245/// \param[in] rhs second term of comparision
246/// \return `true` if the two teams aren't equal
251bool operator!=(const team<T> &lhs, const team<T> &rhs)
253 return !(lhs == rhs);
257/// \param[in] lhs first term of comparison
258/// \param[in] rhs second term of comparision
259/// \return a numeric measurement of the difference between `x` and
260/// `this` (the number of different genes between teams)
265unsigned distance(const team<T> &lhs, const team<T> &rhs)
267 Expects(lhs.individuals() == rhs.individuals());
269 const auto sup(lhs.individuals());
271 for (auto i(decltype(sup){0}); i < sup; ++i)
272 d += distance(lhs[i], rhs[i]);
278/// \return the age of the team (average age of the team members)
281unsigned team<T>::age() const
283 const unsigned age_sum(std::accumulate(begin(), end(), 0,
284 [](unsigned sum, const T &i)
286 return sum + i.age();
289 return age_sum / individuals();
293/// Increments the age of every element of the team
296void team<T>::inc_age()
298 for (auto &i : individuals_)
303/// \return `true` if the team passes the internal consistency check
306bool team<T>::is_valid() const
308 return signature_.empty() || signature_ == hash();
312/// \param[in] ss active symbol set
313/// \param[in] in input stream
314/// \return `true` if team was loaded correctly
317/// If the load operation isn't successful the current team isn't modified.
320bool team<T>::load(std::istream &in, const symbol_set &ss)
323 if (!(in >> n) || !n)
326 decltype(individuals_) v;
329 for (unsigned j(0); j < n; ++j)
339 // We don't save/load signature: it can be easily calculated on the fly.
346/// \param[out] out output stream
347/// \return `true` if team was saved correctly
350bool team<T>::save(std::ostream &out) const
352 out << individuals() << '\n';
356 if (std::any_of(begin(), end(),
357 [&](const T &i) { return !i.save(out); }))
364/// \param[out] s output stream
365/// \param[in] t team to print
366/// \return output stream including `t`
371std::ostream &operator<<(std::ostream &s, const team<T> &t)
373 const auto format(out::print_format_flag(s));
375 for (const auto &i : t)
377 if (format == out::in_line_f)
382 if (format == out::in_line_f)
391#endif // include guard