Ultra 0.9.4
Loading...
Searching...
No Matches
oracle_internal.tcc
Go to the documentation of this file.
1
12
13#if !defined(ULTRA_ORACLE_H)
14# error "Don't include this file directly, include the specific .h instead"
15#endif
16
17#if !defined(ULTRA_ORACLE_INTERNAL_TCC)
18#define ULTRA_ORACLE_INTERNAL_TCC
19
20namespace internal
21{
22
23// ***********************************************************************
24// * reg_oracle_storage *
25// ***********************************************************************
26
27// The general template.
28template<class P, bool S> class reg_oracle_storage;
29
30// ********* First specialization (individual stored inside) *********
47template<>
48class reg_oracle_storage<gp::individual, true>
49{
50public:
57 explicit reg_oracle_storage(const gp::individual &ind) : ind_(ind)
58 {
59 Ensures(is_valid());
60 }
61
71 reg_oracle_storage(std::istream &in, const symbol_set &ss)
72 {
73 if (!ind_.load(in, ss))
74 throw exception::data_format("Cannot load individual");
75
76 int_.reset();
77
78 Ensures(is_valid());
79 }
80
99 template<class ...Args> [[nodiscard]] value_t run(Args && ...args) const
100 {
101 if (int_) [[likely]]
102 int_->rebind(ind_);
103 else
104 int_.emplace(ind_);
105
106 return int_->run(std::forward<Args>(args)...);
107 }
108
112 [[nodiscard]] bool is_valid() const
113 {
114 return ind_.is_valid();
115 }
116
123 bool save(std::ostream &out) const { return ind_.save(out); }
124
125private:
126 gp::individual ind_;
127
128 // Lazily initialised interpreter cache.
129 //
130 // This member is mutable to allow lazy construction and rebinding in
131 // `run()`, even though execution does not conceptually modify the logical
132 // state of the object.
133 //
134 // The interpreter is never accessed outside `run()`.
135 mutable std::optional<src::interpreter> int_ {};
136};
137
138// ********* Second specialization (individual not stored) *********
139template<>
140class reg_oracle_storage<gp::individual, false>
141{
142public:
143 explicit reg_oracle_storage(const gp::individual &ind) : int_(ind)
144 { Ensures(is_valid()); }
145
146 template<class ...Args> [[nodiscard]] value_t run(Args && ...args) const
147 {
148 return int_.run(std::forward<Args>(args)...);
149 }
150
151 [[nodiscard]] bool is_valid() const { return true; }
152
153 // Serialization
154 bool save(std::ostream &out) const
155 {
156 return int_.program().save(out);
157 }
158
159private:
160 mutable src::interpreter int_;
161};
162
163// ********* Third specialization (teams) *********
164template<gp::Team T, bool S>
165class reg_oracle_storage<T, S>
166{
167public:
168 explicit reg_oracle_storage(const T &t)
169 {
170 team_.reserve(t.size());
171 for (const auto &ind : t)
172 team_.emplace_back(ind);
173
174 Ensures(is_valid());
175 }
176
177 reg_oracle_storage(std::istream &in, const symbol_set &ss)
178 {
179 std::size_t n;
180 if (!(in >> n) || !n)
181 throw exception::data_format("Unknown/wrong number of programs");
182
183 team_.reserve(n);
184 for (std::size_t j(0); j < n; ++j)
185 team_.emplace_back(in, ss);
186
187 Ensures(is_valid());
188 }
189
190 [[nodiscard]] bool is_valid() const
191 {
192 return true;
193 }
194
195 // Serialization.
196 bool save(std::ostream &o) const
197 {
198 return (o << team_.size() << '\n')
199 && std::ranges::all_of(
200 team_,
201 [&o](const auto &ind) { return ind.save(o); });
202 }
203
204public:
205 std::vector<reg_oracle_storage<typename T::value_type, S>> team_ {};
206};
207
208} // namespace internal
209
210#endif // include guard
bool save(std::ostream &out, F f)
Definition fitness.tcc:150
value_t run(const gp::individual &ind)
Definition interpreter.cc:239
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
std::ranges::range_value_t< P > individual(const P &p)
Definition population.h:107