diff --git a/include/swarm.hpp b/include/swarm.hpp index 445e66e..23a8e8a 100644 --- a/include/swarm.hpp +++ b/include/swarm.hpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include #include @@ -94,6 +96,14 @@ struct Particle : public Agent> { void move(float dt=1) override { position = position + velocity * dt; } + void observe() { + float y = this->f(position); + if(y < pb) { + pb = y; + pb_pos = position; + } + } + void step() override { // Get the new parameter values vec<3> params = alg(kviscosity, knostalgia, kpeer_pressure, @@ -105,15 +115,9 @@ struct Particle : public Agent> { curr_iter++; - velocity = viscosity * velocity - + nostalgia * (pb_pos - position) - + peer_pressure * (peer.best().second - position); - - float y = f(position); - if(y < pb) { - pb = y; - pb_pos = position; - } + velocity = viscosity * velocity + + nostalgia * (random_coefficients() * (pb_pos - position)) + + peer_pressure * (random_coefficients() * (peer.best().second - position)); }; const float kviscosity = 0.9f; @@ -135,6 +139,17 @@ struct Particle : public Agent> { const vec &get_velocity() const { return velocity; }; private: + static vec random_coefficients() { + static thread_local std::mt19937 generator(std::random_device{}()); + static thread_local std::uniform_real_distribution distribution(0.0f, 1.0f); + + vec coefficients; + for(std::size_t i = 0; i < N; ++i) + coefficients.c[i] = distribution(generator); + + return coefficients; + } + A alg; vec position; vec velocity; @@ -160,8 +175,10 @@ struct Swarm : public Agent> { void step() override { if(particles.empty()) return; - // find best before step() on each particle - // otherwise, if this were in best(), each p.step() would update it + for(auto &p : particles) { + p.observe(); + } + const Particle *b = &particles[0]; for(const auto &p : particles) { if(b->best().first > p.best().first) b = &p; @@ -185,6 +202,12 @@ struct Swarm : public Agent> { particles.push_back( Particle(this->f, *this, pos, vel, max_iter) ); + + const auto [particle_best_val, particle_best_pos] = particles.back().best(); + if(particle_best_val < best_val) { + best_val = particle_best_val; + best_pos = particle_best_pos; + } } const std::vector>& get_particles() { return particles; }; @@ -194,6 +217,6 @@ struct Swarm : public Agent> { private: unsigned max_iter; vec best_pos; - float best_val; + float best_val = std::numeric_limits::infinity(); std::vector> particles; };