00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef RANDOM_TERM_GENERATOR_HH
00018 # define RANDOM_TERM_GENERATOR_HH
00019
00020 # include "../utils/call_with.hh"
00021 # include <tuple>
00022 # include <functional>
00023 # include <vector>
00024 # include <cassert>
00025 # include <random>
00026 # include <type_traits>
00027 # include "../type_traits/try_first.hh"
00028 # include "../wrappers/function_wrappers.hh"
00029 # include "position.hh"
00030 # include "dataset.hh"
00031
00032 namespace catsfoot {
00033 namespace details {
00034 template <typename T, typename... Functions>
00035 struct number_function_returns;
00036
00038 template <typename T>
00039 struct number_function_returns<T> {
00040 static const size_t value = 0u;
00041 };
00042
00044 template <typename T, typename... Args, typename... Functions>
00045 struct number_function_returns<T, std::function<T(Args...)>,
00046 Functions...> {
00047 static const size_t value =
00048 number_function_returns<T, Functions...>::value + 1;
00049 };
00050
00052 template <typename T, typename... Args, typename... Functions>
00053 struct number_function_returns<T, std::function<const T&(Args...)>,
00054 Functions...> {
00055 static const size_t value =
00056 number_function_returns<T, Functions...>::value + 1;
00057 };
00058
00060 template <typename T, typename... Args, typename... Functions>
00061 struct number_function_returns<T, std::function<T&(Args...)>,
00062 Functions...> {
00063 static const size_t value =
00064 number_function_returns<T, Functions...>::value + 1;
00065 };
00066
00068 template <typename T, typename... Args, typename... Functions>
00069 struct number_function_returns<T, std::function<T&&(Args...)>,
00070 Functions...> {
00071 static const size_t value =
00072 number_function_returns<T, Functions...>::value + 1;
00073 };
00074
00076 template <typename T, typename Ret, typename... Args,
00077 typename... Functions>
00078 struct number_function_returns<T, std::function<Ret(Args...)>,
00079 Functions...> {
00080 static const size_t value =
00081 number_function_returns<T, Functions...>::value;
00082 };
00083
00084 template <typename T, typename... Functions>
00085 struct number_ground_terms;
00086
00088 template <typename T>
00089 struct number_ground_terms<T> {
00090 static const size_t value = 0u;
00091 };
00092
00094 template <typename T, typename... Functions>
00095 struct number_ground_terms<T, std::function<T()>,
00096 Functions...> {
00097 static const size_t value =
00098 number_ground_terms<T, Functions...>::value + 1;
00099 };
00100
00102 template <typename T, typename... Functions>
00103 struct number_ground_terms<T, std::function<const T&()>,
00104 Functions...> {
00105 static const size_t value =
00106 number_ground_terms<T, Functions...>::value + 1;
00107 };
00108
00110 template <typename T, typename... Functions>
00111 struct number_ground_terms<T, std::function<T&()>,
00112 Functions...> {
00113 static const size_t value =
00114 number_ground_terms<T, Functions...>::value + 1;
00115 };
00116
00118 template <typename T, typename... Functions>
00119 struct number_ground_terms<T, std::function<T&&()>,
00120 Functions...> {
00121 static const size_t value =
00122 number_ground_terms<T, Functions...>::value + 1;
00123 };
00124
00126 template <typename T, typename Ret, typename... Args,
00127 typename... Functions>
00128 struct number_ground_terms<T, std::function<Ret(Args...)>,
00129 Functions...> {
00130 static const size_t value =
00131 number_ground_terms<T, Functions...>::value;
00132 };
00133 }
00134
00138 template <typename... Types>
00139 struct term_generator_builder {
00140 private:
00141 size_t size;
00142 public:
00143 term_generator_builder(size_t size = 200u): size(size) {}
00144
00145 template <typename Generator, typename... Functions>
00146 struct generator {
00147 private:
00148 size_t size;
00149 Generator& g;
00150 std::tuple<Functions...> functions;
00151 std::tuple<std::vector<Types>...> terms;
00152
00153 public:
00154 template <typename... F>
00155 generator(size_t size, Generator& g, F&&... functions):
00156 size(size), g(g), functions(std::forward<F>(functions)...) {
00157 }
00158
00159 private:
00160 template <typename Return>
00161 Return call_this_one(std::function<Return()>& f) {
00162 return f();
00163 }
00164
00165 template <typename Return>
00166 Return&& call_this_one(std::function<Return&&()>& f) {
00167 return std::move(f());
00168 }
00169
00170 template <typename Return>
00171 Return& call_this_one(std::function<Return&()>& f) {
00172 return f();
00173 }
00174
00175 template <typename Return>
00176 const Return&& call_this_one(std::function<const Return&()>& f) {
00177 return f();
00178 }
00179
00180 template <typename Return, typename... Args,
00181 typename... Bound, typename = typename
00182 std::enable_if<sizeof...(Bound) < sizeof...(Args)>::type>
00183 Return call_this_one(std::function<Return(Args...)>& f,
00184 Bound&... bound...) {
00185 typedef typename
00186 std::decay<
00187 typename std::tuple_element<sizeof...(Bound),
00188 std::tuple<Args...> >::type
00189 >::type
00190 that_arg;
00191 std::vector<that_arg>&
00192 l = std::get<details::position<that_arg, Types...>::value>(terms);
00193
00194 if (l.size() == 0) {
00195 return call_this_one(f, bound..., generate<that_arg>(-1));
00196 }
00197 if (std::is_same<that_arg, Return>::value) {
00198
00199 return call_this_one(f, bound...,
00200 l[std::uniform_int_distribution<size_t>
00201 (0, l.size()-1)(g)]);
00202 }
00203 return call_this_one(f, bound..., generate<that_arg>());
00204 }
00205
00206 template <typename Return, typename... Args,
00207 typename... Bound, typename = typename
00208 std::enable_if<sizeof...(Bound) < sizeof...(Args)>::type>
00209 Return&& call_this_one(std::function<Return&&(Args...)>& f,
00210 Bound&... bound...) {
00211 typedef typename
00212 std::decay<
00213 typename std::tuple_element<sizeof...(Bound),
00214 std::tuple<Args...> >::type
00215 >::type
00216 that_arg;
00217 std::vector<that_arg>&
00218 l = std::get<details::position<that_arg, Types...>::value>(terms);
00219
00220 if (l.size() == 0) {
00221 return call_this_one(f, bound..., generate<that_arg>(-1));
00222 }
00223 if (std::is_same<that_arg, Return>::value) {
00224
00225 return call_this_one(f, bound...,
00226 l[std::uniform_int_distribution<size_t>
00227 (0, l.size()-1)(g)]);
00228 }
00229 return call_this_one(f, bound..., generate<that_arg>());
00230 }
00231
00232 template <typename Return, typename... Args,
00233 typename... Bound, typename = typename
00234 std::enable_if<sizeof...(Bound) < sizeof...(Args)>::type>
00235 const Return& call_this_one(std::function<const Return&(Args...)>& f,
00236 Bound&... bound...) {
00237 typedef typename
00238 std::decay<
00239 typename std::tuple_element<sizeof...(Bound),
00240 std::tuple<Args...> >::type
00241 >::type
00242 that_arg;
00243 std::vector<that_arg>&
00244 l = std::get<details::position<that_arg, Types...>::value>(terms);
00245
00246 if (l.size() == 0) {
00247 return std::move(call_this_one(f, bound..., generate<that_arg>(-1)));
00248 }
00249 if (std::is_same<that_arg, Return>::value) {
00250
00251 return call_this_one(f, bound...,
00252 l[std::uniform_int_distribution<size_t>
00253 (0, l.size()-1)(g)]);
00254 }
00255 return call_this_one(f, bound..., generate<that_arg>());
00256 }
00257
00258 template <typename Return, typename... Args,
00259 typename... Bound, typename = typename
00260 std::enable_if<sizeof...(Bound) < sizeof...(Args)>::type>
00261 Return& call_this_one(std::function<Return&(Args...)>& f,
00262 Bound&... bound...) {
00263 typedef typename
00264 std::decay<
00265 typename std::tuple_element<sizeof...(Bound),
00266 std::tuple<Args...> >::type
00267 >::type
00268 that_arg;
00269 std::vector<that_arg>&
00270 l = std::get<details::position<that_arg, Types...>::value>(terms);
00271
00272 if (l.size() == 0) {
00273 return call_this_one(f, bound..., generate<that_arg>(-1));
00274 }
00275 if (std::is_same<that_arg, Return>::value) {
00276
00277 return call_this_one(f, bound...,
00278 l[std::uniform_int_distribution<size_t>
00279 (0, l.size()-1)(g)]);
00280 }
00281
00282
00283 return call_this_one(f, bound..., generate<that_arg>(0));
00284 }
00285
00286 template <typename Return, typename... Args, typename ...Bound,
00287 typename = typename
00288 std::enable_if<sizeof...(Bound) == sizeof...(Args)>::type>
00289 Return call_this_one(std::function<Return(Args...)>& f,
00290 Bound&... bound) {
00291 return f(bound...);
00292 }
00293
00294 template <typename Return>
00295 Return call(selector<Return>, size_t) {
00296 assert(false);
00297 }
00298
00299 template <typename Return, typename... FS,
00300 typename... Args>
00301 Return call(selector<Return>, size_t fun_to_call,
00302 std::function<Return(Args...)>& f,
00303 FS... fs) {
00304 if (fun_to_call == 0) {
00305 return call_this_one(f);
00306 } else {
00307 return call
00308 (selector<Return>(),
00309 fun_to_call-1, fs...);
00310 }
00311 }
00312
00313 template <typename Return, typename... FS,
00314 typename... Args>
00315 Return call(selector<Return>, size_t fun_to_call,
00316 std::function<Return&(Args...)>& f,
00317 FS... fs) {
00318 if (fun_to_call == 0) {
00319 return call_this_one(f);
00320 } else {
00321 return call
00322 (selector<Return>(),
00323 fun_to_call-1, fs...);
00324 }
00325 }
00326
00327 template <typename Return, typename... FS,
00328 typename... Args>
00329 Return call(selector<Return>, size_t fun_to_call,
00330 std::function<const Return&(Args...)>& f,
00331 FS... fs) {
00332 if (fun_to_call == 0) {
00333 return call_this_one(f);
00334 } else {
00335 return call
00336 (selector<Return>(),
00337 fun_to_call-1, fs...);
00338 }
00339 }
00340
00341 template <typename Return, typename... FS,
00342 typename... Args>
00343 Return call(selector<Return>, size_t fun_to_call,
00344 std::function<Return&&(Args...)>& f,
00345 FS... fs) {
00346 if (fun_to_call == 0) {
00347 return std::move(call_this_one(f));
00348 } else {
00349 return std::move(call
00350 (selector<Return>(),
00351 fun_to_call-1, fs...));
00352 }
00353 }
00354
00355 template <typename Return,
00356 typename OtherReturn, typename... FS,
00357 typename... Args>
00358 Return call(selector<Return>, size_t fun_to_call,
00359 std::function<OtherReturn(Args...)>&,
00360 FS... fs) {
00361 return call
00362 (selector<Return>(),
00363 fun_to_call, fs...);
00364 }
00365
00366 public:
00367 template <typename Return,
00368 bool moveable = is_constructible<Return(const Return&)>::value ||
00369 is_constructible<Return(Return&&)>::value>
00370 struct random_container {
00371 private:
00372 generator<Generator, Functions...>* upper;
00373 public:
00374 random_container(generator<Generator, Functions...>& upper)
00375 : upper(&upper) {}
00376 struct iterator {
00377 private:
00378 generator<Generator, Functions...>* upper;
00379 size_t pos;
00380
00381 public:
00382 iterator(generator<Generator, Functions...>& upper,
00383 size_t pos = 0u):
00384 upper(&upper),
00385 pos(pos) {
00386 if (pos == this->upper->size)
00387 return ;
00388 std::vector<Return>& l =
00389 std::get<details::position<Return, Types...>::value>
00390 (this->upper->terms);
00391 while (l.size() <= pos)
00392 this->upper->template generate<Return>();
00393 }
00394 iterator(const iterator& other):
00395 upper(other.upper),
00396 pos(other.pos) {}
00397 Return& operator*() const {
00398 std::vector<Return>& l =
00399 std::get<details::position<Return, Types...>::value>
00400 (upper->terms);
00401 return l[pos];
00402 }
00403 iterator& operator++() {
00404 ++pos;
00405 std::vector<Return>& l =
00406 std::get<details::position<Return, Types...>::value>
00407 (upper->terms);
00408 while (l.size() <= pos)
00409 upper->template generate<Return>();
00410 return *this;
00411 }
00412 iterator& operator++(int) {
00413 iterator ret(*this);
00414 ++*this;
00415 return *this;
00416 }
00417 bool operator==(const iterator& other) const {
00418 return pos == other.pos;
00419 }
00420 bool operator!=(const iterator& other) const {
00421 return pos != other.pos;
00422 }
00423
00424 iterator& operator=(iterator&& other) {
00425 std::swap(upper, other.upper);
00426 std::swap(pos, other.pos);
00427 return *this;
00428 }
00429
00430 iterator& operator=(const iterator& other) {
00431 return *this = iterator(other);
00432 }
00433 };
00434 iterator begin() {
00435 return iterator(*upper, 0);
00436 }
00437 iterator end() {
00438 return iterator(*upper, upper->size);
00439 }
00440 };
00441
00442 template <typename Return>
00443 struct random_container<Return, false> {
00444 private:
00445 generator<Generator, Functions...>* upper;
00446 public:
00447 random_container(generator<Generator, Functions...>& upper)
00448 : upper(&upper) {}
00449 struct iterator {
00450 private:
00451 generator<Generator, Functions...>* upper;
00452 size_t pos;
00453
00454 public:
00455 iterator(generator<Generator, Functions...>& upper,
00456 size_t pos = 0u):
00457 upper(&upper),
00458 pos(pos) {
00459 }
00460 iterator(const iterator& other):
00461 upper(other.upper),
00462 pos(other.pos) {}
00463 Return& operator*() const {
00464 return const_cast<iterator*>(this)->upper->template generate<Return>();
00465 }
00466 iterator& operator++() {
00467 ++pos;
00468 return *this;
00469 }
00470 iterator& operator++(int) {
00471 iterator ret(*this);
00472 ++*this;
00473 return *this;
00474 }
00475 bool operator==(const iterator& other) const {
00476 return pos == other.pos;
00477 }
00478 bool operator!=(const iterator& other) const {
00479 return pos != other.pos;
00480 }
00481
00482 iterator& operator=(iterator&& other) {
00483 std::swap(upper, other.upper);
00484 std::swap(pos, other.pos);
00485 return *this;
00486 }
00487
00488 iterator& operator=(const iterator& other) {
00489 return *this = iterator(other);
00490 }
00491 };
00492 iterator begin() {
00493 return iterator(*upper, 0);
00494 }
00495 iterator end() {
00496 return iterator(*upper, upper->size);
00497 }
00498 };
00499
00500 template <typename Return,
00501 typename NonRefReturn = typename std::decay<Return>
00502 ::type,
00503 typename = typename details::position<NonRefReturn, Types...>::type
00504 >
00505 random_container<NonRefReturn> get(selector<Return>) {
00506 return random_container<NonRefReturn>(*this);
00507 }
00508
00509 template <typename Return,
00510 typename = typename
00511 std::enable_if<is_constructible<Return(const Return&)>::value ||
00512 is_constructible<Return(Return&&)>::value>::type>
00513 Return& generate(int prob = 1) {
00514 static_assert(details::number_function_returns
00515 <Return, Functions...>::value > 0,
00516 "No function with such return");
00517
00518
00519 std::vector<Return>& l =
00520 std::get<details::position<Return, Types...>::value>(terms);
00521 if (!l.empty()) {
00522 if (prob < 0) {
00523 return l[std::uniform_int_distribution<size_t>
00524 (0, l.size()-1)(g)];
00525 }
00526 if (prob > 0)
00527 if (std::uniform_int_distribution<int>(0,prob)(g)) {
00528 return l[std::uniform_int_distribution<size_t>
00529 (0, l.size()-1)(g)];
00530 }
00531 }
00532
00533 size_t fun_to_call =
00534 std::uniform_int_distribution<size_t>
00535 (0, details::number_function_returns<Return,
00536 Functions...>::value-1)(g);
00537 Return ret = call_with([this, fun_to_call] (Functions&...
00538 funs) {
00539 return this->call
00540 (selector<Return>(),
00541 fun_to_call,
00542 funs...);
00543 }, functions);
00544
00545 l.push_back(std::move(ret));
00546 return l.back();
00547 }
00548
00549 template <typename Return,
00550 typename = typename
00551 std::enable_if<!(is_constructible<Return(const Return&)>::value ||
00552 is_constructible<Return(Return&&)>::value)>::type,
00553 typename = void>
00554 Return& generate(int = 1) {
00555 static_assert(details::number_function_returns
00556 <Return, Functions...>::value > 0,
00557 "No function with such return");
00558 size_t fun_to_call =
00559 std::uniform_int_distribution<size_t>
00560 (0, details::number_function_returns<Return&,
00561 Functions...>::value-1)(g);
00562
00563 return call_with([this, fun_to_call] (Functions&...
00564 funs) -> Return& {
00565 return this->call
00566 (selector<Return&>(),
00567 fun_to_call,
00568 funs...);
00569 }, functions);
00570 }
00571
00572 };
00573
00578 template <typename Generator, typename... Functions>
00579 generator<Generator, typename wrapped<Functions>::type...>
00580 operator()(Generator& g, Functions&&... functions) const {
00581 return generator<Generator, typename std::decay<typename wrapped<Functions>::type>::type...>
00582 (size, g, wrap(std::forward<Functions>(functions))...);
00583 }
00584 };
00585
00586 }
00587
00588 #endif