#include #include #include #include #include #include #include template struct trained { unsigned int id; T decider; double monies; unsigned stock; double wealth; void recalculate(double price) { wealth = monies + stock*price; } double score; }; template class trainer { std::vector>> trainees; std::function factory; unsigned int id; std::default_random_engine random_engine; std::size_t n; public: double money; unsigned stock; std::function> x)> q; trainer(double money, unsigned stock, std::size_t n, std::function factory) : factory(factory), id(0), money(money), stock(stock), n(n), q([](std::shared_ptr> x){ return x->wealth; }), random_engine(std::time(0)) { add(n); } void add(std::size_t n, std::function factory) { for(std::size_t i = 0; i < n; i++) { add(factory()); } } void add(std::size_t n) { add(n, factory); } void add(const T& decider) { auto trainee = std::make_shared>(); trainee->id = ++id; trainee->decider = decider; trainees.push_back(trainee); } int train(std::shared_ptr> trainee, double price) { auto decision = trainee->decider.decide(price, trainee->monies, trainee->stock); auto current = price*trainee->stock + trainee->monies; auto max_credit = std::max(current * 0.05, -1e4); /* std::cout << "D: " << decision << " C: " << current << " P: " << price << " MC: " << max_credit << std::endl; */ if (decision > 0 && trainee->monies - decision*price < -max_credit) { decision = floor((trainee->monies + max_credit) / price); } if (decision < 0 && -decision > trainee->stock) { decision = -trainee->stock; } trainee->stock += decision; trainee->monies -= price*decision; trainee->recalculate(price); return decision; } void test(std::istream& input) { for (auto trainee : trainees) { trainee->monies = money; trainee->stock = stock; trainee->decider.start_money = money; trainee->decider.start_stock = stock; trainee->decider.reset(); } double price, start; input >> price; start = price*stock + money; do { for (auto trainee : trainees) { train(trainee, price); } } while (input >> price); auto hodl = price * stock + money; std::cout << "Zakonczono testy " << trainees.size() << " przypadkow." << std::endl; std::cout << "HODL: " << hodl << " START: " << start << std::endl; std::cout << "-----------------------" << std::endl; normalize(); for (auto trainee : trainees) { std::cout << "#" << trainee->id << ": " << trainee->wealth << " [" << trainee->wealth - hodl << "] (" << trainee->score << ") " << trainee->stock << " akcji, " << trainee->monies << " gelda w banku. " << std::endl; } filter(); breed(); } void normalize() { std::sort(trainees.begin(), trainees.end(), [=](std::shared_ptr> a, std::shared_ptr> b){ return q(a) > q(b); }); auto high = q(*trainees.begin()); auto low = q(*(trainees.end() - 1)); // best = 1, worst = 0 for (auto t : trainees) { t->score = (q(t) - low) / (high - low); }; } void filter() { /* static std::exponential_distribution distribution(0.50); */ /* auto random = [=](){ return 1. - std::clamp(0., distribution(random_engine), 2.)/2.1; }; */ /* auto iterator = std::remove_if(trainees.begin(), trainees.end(), [=](std::shared_ptr> t) { */ /* return random() > t->score; */ /* }); */ trainees.erase(trainees.begin() + 49, trainees.end()); std::cout << "Przy życiu pozostają: "; for (auto trainee : trainees) { std::cout << "#" << trainee->id << " "; } std::cout << std::endl; } void breed() { std::size_t diff = n - trainees.size(); std::cout << "---------------------------------------" << std::endl; std::cout << "W populacji brakuje " << diff << " sieci, aktualnie " << trainees.size() << "." << std::endl; std::vector probability; for (auto t : trainees) { probability.push_back(t->score); } std::discrete_distribution distribution(probability.begin(), probability.end()); std::exponential_distribution exponential(1.5); auto combiner = [=](const double& a, const double& b){ auto mutation = (rand() % 2 ? -1 : 1) * exponential(random_engine); if (exponential(random_engine) < 1) { return .6 * a + .4 * b + mutation; } return (rand() % 2 ? a : b) + mutation; }; unsigned first, second; for (int i = 0; i < diff; i++) { first = distribution(random_engine); do { second = distribution(random_engine); } while (first == second); auto combined = trainees[first]->decider.combine(trainees[second]->decider, combiner); std::cout << "Łączenie #" << trainees[first]->id << " z #" << trainees[second]->id << " dało #" << (id+1) << std::endl; add(combined); } } void see_best(std::istream& stream) { std::shared_ptr> trainee = this->trainees[0]; std::cout << "price,decision" << std::endl; double price; trainee->monies = money; trainee->stock = stock; trainee->decider.reset(); while (stream >> price) { int decision = train(trainee, price); std::cout << price << "," << decision << std::endl; } } };