diff --git a/include/swarm.hpp b/include/swarm.hpp index 5e2ba00..002ee55 100644 --- a/include/swarm.hpp +++ b/include/swarm.hpp @@ -12,7 +12,7 @@ struct Agent { using F = std::function; virtual void move(float dt) = 0; - virtual void step(float dt) = 0; + virtual void step() = 0; virtual std::pair best() const = 0; @@ -21,44 +21,87 @@ protected: F f; }; -template +template +concept ParameterChangeAlgorithm = requires(A alg, float f, unsigned int i) { + { alg(f, f, f, i, i) } -> std::same_as>; +}; + +namespace ParamChange { + struct Const { + vec<3> operator()( + float visc, float nostal, float peerp, int _1, int _2) { + return {visc, nostal, peerp}; + } + }; + + struct MLinAlg { + vec<3> operator()( + float visc, float nostal, float peerp, int curr, int max) { + float pct_done = (float)curr / (float)max; + return { + visc - (0.9f - 0.4f) * pct_done, + nostal - (2.5f - 0.5f) * pct_done, + peerp + (2.5f - 0.5f) * pct_done, + }; + } + }; +}; + +template struct Particle : public Agent> { std::pair> best() const override { return {pb, pb_pos}; }; void move(float dt=1) override { position = position + velocity * dt; } - void step(float dt=1) override { - velocity = kviscosity * velocity - + knostalgia * (pb_pos - position) - + kpeer_pressure * (peer.best().second - position); + void step() override { + 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; } + + vec<3> params = alg(kviscosity, knostalgia, kpeer_pressure, + curr_iter, max_iter); + + viscosity = params.x; + nostalgia = params.y; + peer_pressure = params.z; + + curr_iter++; }; - float kviscosity = 0.9f; - float knostalgia = 2.5f; - float kpeer_pressure = 0.5f; + const float kviscosity = 0.9f; + const float knostalgia = 2.5f; + const float kpeer_pressure = 0.5f; + + float viscosity = kviscosity; + float nostalgia = knostalgia; + float peer_pressure = kpeer_pressure; Particle(Agent>::F f, const Agent>& peer, - vec position, vec velocity) + vec position, vec velocity, unsigned max_iter) : Agent>(f), position(position), velocity(velocity), - pb_pos(position), peer(peer) { + pb_pos(position), max_iter(max_iter), peer(peer) { pb = f(position); } const vec &get_position() const { return position; }; private: + A alg; vec position; vec velocity; vec pb_pos; float pb; + unsigned curr_iter = 0; + unsigned max_iter; + const Agent>& peer; }; @@ -71,7 +114,7 @@ struct Swarm : public Agent> { p.move(dt); } - void step(float dt=1) override { + void step() override { if(particles.empty()) return; // find best before step() on each particle @@ -85,26 +128,28 @@ struct Swarm : public Agent> { best_pos = b->best().second; for(auto &p : particles) - p.step(dt); + p.step(); } void add_particle(std::size_t n=1) { for(std::size_t i=0; i <= n; ++i) particles.push_back( - Particle(this->_f, *this, vec(0), vec(10)) + Particle(this->_f, *this, vec(0), vec(10), max_iter) ); } void add_particle(const vec &pos, const vec &vel) { particles.push_back( - Particle(this->f, *this, pos, vel) + Particle(this->f, *this, pos, vel, max_iter) ); } const std::vector>& get_particles() { return particles; }; - Swarm(Agent>::F f) : Agent>(f) {} + Swarm(Agent>::F f, unsigned max_iter = 150) + : Agent>(f), max_iter(max_iter) {} private: + unsigned max_iter; vec best_pos; float best_val; std::vector> particles; diff --git a/src/main.cpp b/src/main.cpp index 82d6678..56d3a74 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,8 +8,8 @@ static constexpr int kFPS = 60; static constexpr float kDT = 1.0 / kFPS; float f(vec<2> x) { - return 50 * (std::pow(std::sin((x.x - 10)/2),2) + std::pow(std::sin(x.y/2),2)) - + std::pow(std::abs(x.x - 10), 1.2) + std::pow(std::abs(x.y), 1.2); + return 50 * (std::pow(std::sin((x.x - 10)/2),2) + std::pow(std::sin(x.y/2),2)) + + std::pow(std::abs(x.x - 3.141592653589), 1.2) + std::pow(std::abs(x.y), 1.2); } int @@ -18,7 +18,7 @@ main(int argc, char **argv) { if(argc < 2) iter_count = 100; else sscanf(argv[1], "%d", &iter_count); - Swarm<2> swarm(f); + Swarm<2> swarm(f, iter_count); Screen scr(80, 24); TanhColorizer tanh_col; @@ -148,7 +148,7 @@ main(int argc, char **argv) { case 'p': auto [y, x] = swarm.best(); - printf("Current best: f(%.3f, %.3f) = %.3f", x.x, x.y, y); + printf("Current best: f(%.10f, %.10f) = %.10f", x.x, x.y, y); break; }