13#if !defined(ULTRA_ORACLE_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(ULTRA_ORACLE_TCC)
18#define ULTRA_ORACLE_TCC
24template<Indiv
idual P,
bool S>
25const std::string basic_reg_oracle<P, S>::SERIALIZE_ID(
26 gp::Team<P> ?
"TEAM_REG_ORACLE" :
"REG_ORACLE");
31template<Indiv
idual P,
bool S>
32basic_reg_oracle<P, S>::basic_reg_oracle(
const P &prg)
33 :
internal::reg_oracle_storage<P, S>(prg)
35 Expects(!prg.empty());
44template<Indiv
idual P,
bool S>
45basic_reg_oracle<P, S>::basic_reg_oracle(std::istream &in,
47 :
internal::reg_oracle_storage<P, S>(in, ss)
49 static_assert(S,
"reg_oracle requires storage for de-serialization");
58template<Indiv
idual P,
bool S>
59value_t basic_reg_oracle<P, S>::operator()(
const std::vector<value_t> &e)
const
61 if constexpr (!gp::Team<P>)
65 D_DOUBLE sum(0), count(0);
67 for (
const auto &core : this->team_)
69 const auto res(core.run(e));
73 sum += std::get<D_DOUBLE>(res);
91template<Indiv
idual P,
bool S>
92classification_result basic_reg_oracle<P, S>::tag(
93 const std::vector<value_t> &)
const
95 throw std::logic_error(
"tag() called on regression oracle");
102template<Indiv
idual P,
bool S>
103std::string basic_reg_oracle<P, S>::name(
const value_t &a)
const
105 return lexical_cast<std::string>(a);
111template<Indiv
idual P,
bool S>
112bool basic_reg_oracle<P, S>::is_valid()
const
114 return internal::reg_oracle_storage<P, S>::is_valid();
123template<Indiv
idual P,
bool S>
124bool basic_reg_oracle<P, S>::save(std::ostream &
out)
const
126 return internal::reg_oracle_storage<P, S>::save(
out);
136template<RegressionPredictor O>
137reg_oracle_adaptor<O>::reg_oracle_adaptor(O oracle)
138 : oracle_(
std::move(oracle))
150template<RegressionPredictor O>
151value_t reg_oracle_adaptor<O>::operator()(
const std::vector<value_t> &x)
const
162template<RegressionPredictor O>
163std::string reg_oracle_adaptor<O>::name(
const value_t &v)
const
165 return lexical_cast<std::string>(v);
173template<RegressionPredictor O>
174classification_result reg_oracle_adaptor<O>::tag(
175 const std::vector<value_t> &)
const
177 throw std::logic_error(
"tag() called on regression oracle");
187template<RegressionPredictor O>
188std::string reg_oracle_adaptor<O>::serialize_id()
const
190 return "REG_ORACLE_ADAPTOR";
198template<RegressionPredictor O>
199bool reg_oracle_adaptor<O>::save(std::ostream &)
const
201 throw std::logic_error(
"reg_oracle_adaptor is not serializable");
208template<
class I,
bool S>
209const std::string basic_gaussian_oracle<I, S>::SERIALIZE_ID(
217template<
class I,
bool S>
218basic_gaussian_oracle<I, S>::basic_gaussian_oracle(
219 const I &ind,
const dataframe &d, std::vector<std::string> names)
220 : basic_class_oracle(
std::move(names)), oracle_(ind), gauss_dist_(d.classes())
222 static_assert(Individual<I>);
223 Expects(!ind.empty());
224 Expects(d.classes() > 1);
237template<
class I,
bool S>
238basic_gaussian_oracle<I, S>::basic_gaussian_oracle(std::istream &in,
239 const symbol_set &ss)
240 : basic_class_oracle(), oracle_(in, ss)
243 S,
"gaussian_oracle requires storage space for de-serialization");
247 throw exception::data_format(
"Cannot read gaussian_oracle size component");
249 for (std::size_t i(0); i < n; ++i)
251 distribution<double> d;
253 throw exception::data_format(
254 "Cannot read gaussian_oracle distribution component");
256 gauss_dist_.push_back(d);
260 throw exception::data_format(
261 "Cannot read gaussian_oracle class_names component");
304template<
class I,
bool S>
305void basic_gaussian_oracle<I, S>::fill_vector(
const dataframe &d)
307 Expects(d.classes() > 1);
309 std::vector<unsigned> unknown_in_class(d.classes(), 0);
311 constexpr double cut(100000000.0);
313 for (
const auto &ex : d)
315 const auto cl(
label(ex));
317 if (
const auto res(oracle_(ex.input));
has_value(res))
319 auto val(std::get<D_DOUBLE>(res));
320 val = std::clamp(val, -cut, cut);
322 gauss_dist_[cl].add(val);
325 ++unknown_in_class[cl];
328 constexpr double min_variance(1e-6);
329 constexpr unsigned missing_per_inflation(2);
331 for (std::size_t cl(0); cl < d.classes(); ++cl)
333 auto &g(gauss_dist_[cl]);
335 if (
const unsigned k(unknown_in_class[cl] / missing_per_inflation);
338 const double mean(g.mean());
339 const double var(std::max(g.variance(), min_variance));
340 const double delta(2.0 * std::sqrt(var));
342 for (std::size_t i(0); i < k; ++i)
350 for (std::size_t i(0); i < std::max(1u, k); ++i)
357 Ensures(g.size() > 0);
358 Ensures(std::isfinite(g.mean()));
359 Ensures(g.variance() >= 0.0);
360 Ensures(std::isfinite(g.variance()));
436template<
class I,
bool S>
437classification_result basic_gaussian_oracle<I, S>::tag(
438 const std::vector<value_t> &ex)
const
440 const std::size_t classes(gauss_dist_.size());
445 const auto res(oracle_(ex));
451 double best_count(0.0), total(0.0);
453 for (std::size_t i(0); i < classes; ++i)
456 const auto n(
static_cast<double>(gauss_dist_[i].size()));
466 const double confidence(total > 0.0 ? best_count / total : 0.0);
467 return {best, confidence};
471 const auto x(std::get<D_DOUBLE>(res));
473 double best_p(0.0), sum_p(0.0);
474 src::class_t probable_class(0);
476 for (std::size_t i(0); i < classes; ++i)
478 const auto mean(gauss_dist_[i].mean());
479 const auto variance(gauss_dist_[i].variance());
480 const auto distance(std::fabs(x - mean));
483 if (issmall(variance))
507 const double confidence(sum_p > 0.0 ? best_p / sum_p : 0.0);
509 return {probable_class, confidence};
518template<
class I,
bool S>
519bool basic_gaussian_oracle<I, S>::save(std::ostream &
out)
const
521 if (!oracle_.save(
out))
524 if (!(
out << gauss_dist_.size() <<
'\n'))
527 for (
const auto &g : gauss_dist_)
531 return save_names(
out);
537template<
class I,
bool S>
538bool basic_gaussian_oracle<I, S>::is_valid()
const
540 return oracle_.is_valid() && !gauss_dist_.empty();
547template<
class I,
bool S>
548const std::string basic_binary_oracle<I, S>::SERIALIZE_ID(
556template<
class I,
bool S>
557basic_binary_oracle<I, S>::basic_binary_oracle(
558 const I &ind, [[maybe_unused]]
const dataframe &d,
559 std::vector<std::string> names)
560 : basic_class_oracle(
std::move(names)), oracle_(ind)
562 static_assert(Individual<I>);
563 Expects(!ind.empty());
564 Expects(d.classes() == 2);
575template<
class I,
bool S>
576basic_binary_oracle<I, S>::basic_binary_oracle(std::istream &in,
577 const symbol_set &ss)
578 : basic_class_oracle(), oracle_(in, ss)
581 S,
"binary_oracle requires storage space for de-serialization");
584 throw exception::data_format(
585 "Cannot read binary_oracle class_names component");
595template<
class I,
bool S>
596classification_result basic_binary_oracle<I, S>::tag(
597 const std::vector<value_t> &ex)
const
599 const auto res(oracle_(ex));
600 const double val(
has_value(res) ? std::get<D_DOUBLE>(res) : 0.0);
602 return {val > 0.0 ? 1u : 0u,
603 std::fabs(2.0 * std::numbers::inv_pi * std::atan(val))};
609template<
class I,
bool S>
610bool basic_binary_oracle<I, S>::is_valid()
const
612 return oracle_.is_valid();
621template<
class I,
bool S>
622bool basic_binary_oracle<I, S>::save(std::ostream &
out)
const
624 if (!oracle_.save(
out))
627 return save_names(
out);
638template<ClassificationPredictor O>
639class_oracle_adaptor<O>::class_oracle_adaptor(O oracle,
640 std::vector<std::string> names)
641 : basic_class_oracle(
std::move(names)), oracle_(
std::move(oracle))
653template<ClassificationPredictor O>
654classification_result class_oracle_adaptor<O>::tag(
655 const std::vector<value_t> &x)
const
657 return oracle_.tag(x);
667template<ClassificationPredictor O>
668std::string class_oracle_adaptor<O>::serialize_id()
const
670 return "CLASS_ORACLE_ADAPTOR";
678template<ClassificationPredictor O>
679bool class_oracle_adaptor<O>::save(std::ostream &)
const
681 throw std::logic_error(
"class_oracle_adaptor is not serializable");
688template<ClassificationPredictor O, team_composition C>
689const std::string team_class_oracle<O, C>::SERIALIZE_ID(
690 "TEAM_" + O::SERIALIZE_ID);
697template<ClassificationPredictor O, team_composition C>
698template<Indiv
idual I>
703 team_.reserve(t.
size());
704 for (
const auto &ind : t)
705 team_.emplace_back(ind, d);
714template<ClassificationPredictor O, team_composition C>
719 if (!(in >> classes_))
727 for (std::size_t i(0); i < s; ++i)
728 team_.emplace_back(in, ss);
750template<ClassificationPredictor O, team_composition C>
752 const std::vector<value_t> &instance)
const
754 Expects(team_.size());
756 if constexpr (C == team_composition::wta)
758 const auto size(team_.size());
759 auto best(team_[0].tag(instance));
761 for (std::size_t i(1); i < size; ++i)
763 const auto res(team_[i].tag(instance));
765 if (res.sureness > best.sureness)
771 else if constexpr (C == team_composition::mv)
773 std::vector<unsigned> votes(classes_);
775 for (
const auto &oracle : team_)
776 ++votes[oracle.tag(instance).label];
779 for (
auto i(max + 1); i < classes_; ++i)
780 if (votes[i] > votes[max])
783 return {max,
static_cast<double>(votes[max])
784 /
static_cast<double>(team_.size())};
794template<ClassificationPredictor O, team_composition C>
795bool team_class_oracle<O, C>::save(std::ostream &out)
const
797 if (!(out << classes_ <<
'\n'))
800 if (!(out << team_.size() <<
'\n'))
803 for (
const auto &i : team_)
807 return save_names(out);
813template<ClassificationPredictor O, team_composition C>
814std::string team_class_oracle<O, C>::serialize_id() const noexcept
822template<ClassificationPredictor O, team_composition C>
828namespace serialize::oracle
833using build_func = std::unique_ptr<basic_oracle> (*)(std::istream &,
837std::unique_ptr<basic_oracle> build(std::istream &in,
const symbol_set &ss)
839 return std::make_unique<U>(in, ss);
842extern std::map<std::string, build_func> factory_;
851 Expects(!
id.empty());
852 return internal::factory_.insert({id, internal::build<U>}).second;
855template<Indiv
idual T>
856std::unique_ptr<basic_oracle>
load(std::istream &in,
const symbol_set &ss)
858 if (internal::factory_.find(reg_oracle<T>::SERIALIZE_ID)
859 == internal::factory_.end())
861 insert<reg_oracle<T>>(reg_oracle<T>::SERIALIZE_ID);
863 insert<gaussian_oracle<T>>(gaussian_oracle<T>::SERIALIZE_ID);
864 insert<binary_oracle<T>>(binary_oracle<T>::SERIALIZE_ID);
871 const auto iter(internal::factory_.find(
id));
872 if (iter != internal::factory_.end())
873 return iter->second(in, ss);
std::size_t size() const noexcept
Definition team.h:246
basic_class_oracle(std::vector< std::string >={})
Definition oracle.cc:23
bool load_names(std::istream &)
Loads the class names, accepting a zero count for omitted names.
Definition oracle.cc:57
Definition dataframe.h:76
team_class_oracle(const gp::team< I > &, const dataframe &, std::vector< std::string >={})
Definition oracle.h:700
bool is_valid() const final
Definition oracle.h:824
classification_result tag(const std::vector< value_t > &) const final
Definition oracle.h:752
Definition symbol_set.h:115
class_t label(const example &e)
Definition dataframe.cc:87
double distance(F f1, F f2)
Definition fitness.tcc:117
bool load(std::istream &in, F *f)
Definition fitness.tcc:190
value_t run(const gp::individual &ind)
Definition interpreter.cc:239
bool has_value(const value_t &v) noexcept
Definition value.cc:31
std::variant< D_VOID, D_INT, D_DOUBLE, D_STRING, const D_NULLARY *, D_ADDRESS, const D_VARIABLE *, D_IVECTOR > value_t
Definition value.h:54
bool insert(const std::string &id)
Definition oracle.tcc:849