-typedef struct particle particle;
+#include "rand.h"
-typedef struct {
- double min;
- double max;
-} range;
+typedef struct particle particle;
typedef struct {
double *x;
typedef struct {
int dim;
int particlec;
+ range *rrange;
double (*f)(double*); // fitness function
double eps; // convergence tolerance
double w; // inertia
} swarm_parameters;
typedef struct {
- swarm_parameters params;
particle *particles;
particle *global_best;
} swarm;
double *velocity;
};
-void pick(const int dim, const range *rrange, double *v);
-void swarm_populate(swarm *sw, const range *rrange);
-void swarm_velocity_update(swarm *sw);
-void swarm_optimize(swarm *sw);
+void swarm_alloc(swarm_parameters *par, swarm *sw);
+void swarm_free(swarm_parameters *par, swarm *sw);
+void swarm_populate(swarm_parameters *par, swarm *sw, const range *rrange);
+void swarm_velocity_update(swarm_parameters *par, swarm *sw);
+
+void swarm_optimize(swarm_parameters *par, particle_state *res);
}
int main(int argc, char *argv[]) {
- swarm sw = {
+ range rrange[2] = {
+ (range) { -100.0, 100.0 },
+ (range) { -100.0, 100.0 }
+ };
+ swarm_parameters par = {
2,
100,
+ rrange,
f,
pow(2, 40),
0.8,
2.05,
2.05
};
- range rrange[2] = {
- (range) { -100.0, 100.0 },
- (range) { -100.0, 100.0 }
- };
- swarm_populate(&sw, rrange);
- swarm_optimize(&sw);
+ particle_state best = { vec_alloc(par.dim), 0.0 };
+ swarm_optimize(&par, &best);
printf("apso: converged in x=");
- vec_print(sw.params.dim, sw.global_best->current.x);
- printf(" with fitness f(x)=%f\n", sw.global_best->current.fitness);
+ vec_print(par.dim, best.x);
+ printf(" with fitness f(x)=%f\n", best.fitness);
// GtkApplication *app = gui_init();
// return g_application_run(G_APPLICATION(app), argc, argv);
return 0;
#include <math.h>
-#include <stdlib.h>
#include <omp.h>
+#include <stdlib.h>
#include "swarm.h"
#include "vector.h"
-double rands() {
- return (double) rand() / RAND_MAX;
-}
-
-double randrange(double min, double max) {
- return rands() * (max - min) + min;
+void swarm_alloc(swarm_parameters *par, swarm *sw) {
+ sw->particles = malloc(sizeof(particle) * par->particlec);
+ #pragma omp parallel for
+ for (int p = 0; p < par->particlec; p++) {
+ sw->particles[p].current.x = vec_alloc(par->dim);
+ sw->particles[p].best.x = vec_alloc(par->dim);
+ sw->particles[p].velocity = vec_alloc(par->dim);
+ }
}
-void pick(const int dim, const range *rrange, double *v) {
- for (int d = 0; d < dim; d++) v[d] = randrange(rrange[d].min, rrange[d].max);
+void swarm_free(swarm_parameters *par, swarm *sw) {
+ #pragma omp parallel for
+ for (int p = 0; p < par->particlec; p++) {
+ free(sw->particles[p].current.x);
+ free(sw->particles[p].best.x);
+ free(sw->particles[p].velocity);
+ }
+ free(sw->particles);
}
-void swarm_populate(swarm *sw, const range *rrange) {
- sw->particles = malloc(sizeof(particle) * sw->params.particlec);
+void swarm_populate(swarm_parameters *par, swarm *sw, const range *rrange) {
sw->global_best = &sw->particles[0];
#pragma omp parallel for
- for (int p = 0; p < sw->params.particlec; p++) {
+ for (int p = 0; p < par->particlec; p++) {
particle *pt = &sw->particles[p];
- pt->current.x = vec_alloc(sw->params.dim);
- pt->best.x = vec_alloc(sw->params.dim);
- pt->velocity = vec_alloc(sw->params.dim);
- for (int d = 0; d < sw->params.dim; d++) {
- pick(sw->params.dim, rrange, pt->current.x);
- vec_copy(sw->params.dim, pt->current.x, pt->best.x);
+ for (int d = 0; d < par->dim; d++) {
+ vec_pick(par->dim, rrange, pt->current.x);
+ vec_copy(par->dim, pt->current.x, pt->best.x);
}
- pt->current.fitness = sw->params.f(pt->current.x);
+ pt->current.fitness = par->f(pt->current.x);
pt->best.fitness = pt->current.fitness;
#pragma omp critical
{
}
}
-void swarm_velocity_update(swarm *sw) {
+void swarm_velocity_update(swarm_parameters *par, swarm *sw) {
#pragma omp parallel for
- for (int p = 0; p < sw->params.particlec; p++) {
+ for (int p = 0; p < par->particlec; p++) {
particle *pt = &sw->particles[p];
- for (int d = 0; d < sw->params.dim; d++)
- pt->velocity[d] = sw->params.w * pt->velocity[d] + sw->params.c * rands() * (pt->best.x[d] - pt->current.x[d]) + sw->params.s * rands() * (sw->global_best->current.x[d] - pt->current.x[d]);
+ for (int d = 0; d < par->dim; d++)
+ pt->velocity[d] = par->w * pt->velocity[d] + par->c * rands() * (pt->best.x[d] - pt->current.x[d]) + par->s * rands() * (sw->global_best->current.x[d] - pt->current.x[d]);
}
#pragma omp parallel for
- for (int p = 0; p < sw->params.particlec; p++) {
+ for (int p = 0; p < par->particlec; p++) {
particle *pt = &sw->particles[p];
- vec_add(sw->params.dim, pt->velocity, pt->current.x);
- pt->current.fitness = sw->params.f(pt->current.x);
- if (pt->current.fitness < pt->best.fitness) pt->best = pt->current;
+ vec_add(par->dim, pt->velocity, pt->current.x);
+ pt->current.fitness = par->f(pt->current.x);
+ if (pt->current.fitness < pt->best.fitness) {
+ vec_copy(par->dim, pt->current.x, pt->best.x);
+ pt->best.fitness = pt->current.fitness;
+ }
#pragma omp critical
{
if (pt->current.fitness < sw->global_best->current.fitness)
}
}
-void swarm_optimize(swarm *sw) {
+void swarm_optimize(swarm_parameters *par, particle_state *res) {
+ swarm sw;
+ swarm_alloc(par, &sw);
+ swarm_populate(par, &sw, par->rrange);
int conv = 0;
double best = INFINITY;
while (conv < 1000) {
- swarm_velocity_update(sw);
- if (fabs(sw->global_best->current.fitness - best) < sw->params.eps)
+ swarm_velocity_update(par, &sw);
+ if (fabs(sw.global_best->current.fitness - best) < par->eps)
conv++;
else {
- best = sw->global_best->current.fitness;
+ best = sw.global_best->current.fitness;
conv = 0;
}
}
+ vec_copy(par->dim, sw.global_best->best.x, res->x);
+ res->fitness = sw.global_best->best.fitness;
+ swarm_free(par, &sw);
}