chore: add comments to swarm.hpp

This commit is contained in:
dvdrw 2024-11-25 14:44:01 +01:00
parent 2b20e90a08
commit fe62617beb
Signed by: dvdrw
GPG Key ID: 3ED4E5A371C20DD7
2 changed files with 38 additions and 1 deletions

View File

@ -8,13 +8,37 @@
#include <vec.hpp> #include <vec.hpp>
#include <vector> #include <vector>
/**
* An Agent in a Particle Swarm Optimisation simulation.
* #T is the type of the position vector the Agent uses.
*/
template<typename T> template<typename T>
struct Agent { struct Agent {
/**
* Type of the fitness function.
*/
using F = std::function<float(T)>; using F = std::function<float(T)>;
/**
* Moves the Agent along its velocity by a factor of #dt.
*
* The parameter #dt is useful when drawing the Agent moving faster than it
* #tick()s.
*
* @see: step()
*/
virtual void move(float dt) = 0; virtual void move(float dt) = 0;
/**
* Steps the algorithm values one tick forward.
* Warning: Does not move the Agent. Use #move() for this
* @see: move()
*/
virtual void step() = 0; virtual void step() = 0;
/**
* The best position this Agent has seen during its lifetime.
*/
virtual std::pair<float, T> best() const = 0; virtual std::pair<float, T> best() const = 0;
Agent(F f) : f(f) {} Agent(F f) : f(f) {}
@ -24,6 +48,8 @@ protected:
template <typename A> template <typename A>
concept ParameterChangeAlgorithm = requires(A alg, float f, unsigned int i) { concept ParameterChangeAlgorithm = requires(A alg, float f, unsigned int i) {
// initial viscosity, initial nostalgia, initial peer pressure, current
// iteration, max iteration
{ alg(f, f, f, i, i) } -> std::same_as<vec<3>>; { alg(f, f, f, i, i) } -> std::same_as<vec<3>>;
}; };
@ -62,13 +88,14 @@ namespace ParamChange {
}; };
}; };
template<std::size_t N, ParameterChangeAlgorithm A = ParamChange::MTanhAlg<>> template<std::size_t N, ParameterChangeAlgorithm A = ParamChange::MLinAlg>
struct Particle : public Agent<vec<N>> { struct Particle : public Agent<vec<N>> {
std::pair<float, vec<N>> best() const override { return {pb, pb_pos}; }; std::pair<float, vec<N>> best() const override { return {pb, pb_pos}; };
void move(float dt=1) override { position = position + velocity * dt; } void move(float dt=1) override { position = position + velocity * dt; }
void step() override { void step() override {
// Get the new parameter values
vec<3> params = alg(kviscosity, knostalgia, kpeer_pressure, vec<3> params = alg(kviscosity, knostalgia, kpeer_pressure,
curr_iter, max_iter); curr_iter, max_iter);

View File

@ -65,12 +65,21 @@ main(int argc, char **argv) {
scr.draw(); scr.draw();
}; };
// We draw to the screen at a rate of `kFPS', but step()ing the swarm at
// this rate would be far too fast to be interesting to look at. On the
// other hand, step()ing once a second is too slow.
//
// So, we step() every quarter second. To line up the move() so that a unit
// move() happens preceding each step(), we also need to move as fast as
// we've shortened our step() interval.
for(int i = 0; i < iter_count * kFPS/4;) { for(int i = 0; i < iter_count * kFPS/4;) {
if(!pause) { if(!pause) {
scr.clear(); scr.clear();
update_and_draw(); update_and_draw();
// Since we step() 4x a second, we need to move() 4x as fast as moving by dt
// each frame.
swarm.move(kDT * 4); swarm.move(kDT * 4);
if(i % (kFPS/4) == (kFPS/4)-1) if(i % (kFPS/4) == (kFPS/4)-1)
swarm.step(); swarm.step();
@ -152,6 +161,7 @@ main(int argc, char **argv) {
break; break;
} }
// Wait for kDT (time between two frames)
usleep(1000 * 1000 / kFPS); usleep(1000 * 1000 / kFPS);
} }