From 656909e3ef718f34fbcd7af01d6f3e4df0dea6b2 Mon Sep 17 00:00:00 2001 From: ametama Date: Wed, 17 Dec 2025 22:50:37 +0100 Subject: [PATCH] refactor: split gui/optimization --- include/gui.h | 3 + include/{particle_swarm.h => swarm.h} | 15 +++- src/gui.c | 15 ++++ src/main.c | 47 +++++++++++ src/particle_swarm.c | 114 -------------------------- src/swarm.c | 67 +++++++++++++++ 6 files changed, 145 insertions(+), 116 deletions(-) create mode 100644 include/gui.h rename include/{particle_swarm.h => swarm.h} (59%) create mode 100644 src/gui.c create mode 100644 src/main.c delete mode 100644 src/particle_swarm.c create mode 100644 src/swarm.c diff --git a/include/gui.h b/include/gui.h new file mode 100644 index 0000000..2ea4b73 --- /dev/null +++ b/include/gui.h @@ -0,0 +1,3 @@ +#include + +GtkApplication *gui_init(); diff --git a/include/particle_swarm.h b/include/swarm.h similarity index 59% rename from include/particle_swarm.h rename to include/swarm.h index a9fdedb..25cbe0b 100644 --- a/include/particle_swarm.h +++ b/include/swarm.h @@ -11,7 +11,17 @@ typedef struct { } particle_state; typedef struct { + int dim; + double (*f)(double*); int particlec; + double eps; + double w; + double c; + double s; +} swarm_parameters; + +typedef struct { + swarm_parameters params; particle *particles; particle *global_best; } swarm; @@ -23,5 +33,6 @@ struct particle { }; void pick(const int dim, const range *vrange, double *v); -void swarm_init(swarm *sw, const int dim, const range *vrange); -void swarm_velocity_update(swarm *sw, const int dim); +void swarm_populate(swarm *sw, const range *rrange); +void swarm_velocity_update(swarm *sw); +void swarm_optimize(swarm *sw); diff --git a/src/gui.c b/src/gui.c new file mode 100644 index 0000000..532f9af --- /dev/null +++ b/src/gui.c @@ -0,0 +1,15 @@ +#include "gui.h" + +static void on_activate(GtkApplication *app) { + GtkWidget *window = gtk_application_window_new(app); + GtkWidget *button = gtk_button_new_with_label("Hello, World!"); + g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_window_close), window); + gtk_window_set_child(GTK_WINDOW(window), button); + gtk_window_present(GTK_WINDOW(window)); +} + +GtkApplication *gui_init() { + GtkApplication *app = gtk_application_new("org.wafflesoft.NCPSO", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL); + return app; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..3ba6629 --- /dev/null +++ b/src/main.c @@ -0,0 +1,47 @@ +#include "vector.h" +#include "swarm.h" +#include "gui.h" + +double b0(double *x) { + return -x[0]; +} + +double b1(double *x) { + return -x[1]; +} + +double b2(double *x) { + return x[0] - 10; +} + +double b3(double *x) { + return x[1] - 15; +} + +double f(double *x) { + return exp(b0(x)) + exp(b1(x)) + exp(b2(x)) + exp(b3(x)) + x[0] - x[1]; +} + +int main(int argc, char *argv[]) { + swarm sw = { + 2, + f, + 100, + 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); + 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); + // GtkApplication *app = gui_init(); + // return g_application_run(G_APPLICATION(app), argc, argv); + return 0; +} diff --git a/src/particle_swarm.c b/src/particle_swarm.c deleted file mode 100644 index 1d574c1..0000000 --- a/src/particle_swarm.c +++ /dev/null @@ -1,114 +0,0 @@ -#include -#include -#include -#include "particle_swarm.h" -#include "vector.h" -#include - -double c = 2.05; -double s = 2.05; -double w = 0.8; - -double rands() { - return (double) rand() / RAND_MAX; -} - -double randrange(double min, double max) { - return rands() * (max - min) + min; -} - -void pick(const int dim, const range *vrange, double *v) { - for (int d = 0; d < dim; d++) v[d] = randrange(vrange[d].min, vrange[d].max); -} - -double b0(double *x) { - return -x[0]; -} - -double b1(double *x) { - return -x[1]; -} - -double b2(double *x) { - return x[0] - 10; -} - -double b3(double *x) { - return x[1] - 15; -} - -double f(double *x) { - return exp(b0(x)) + exp(b1(x)) + exp(b2(x)) + exp(b3(x)) + x[0] - x[1]; -} - -void swarm_init(swarm *sw, const int dim, const range *vrange) { - sw->particles = malloc(sizeof(particle) * sw->particlec); - sw->global_best = &sw->particles[0]; - for (int p = 0; p < sw->particlec; p++) { - particle *pt = &sw->particles[p]; - pt->current.x = vec_alloc(dim); - pt->best.x = vec_alloc(dim); - pt->velocity = vec_alloc(dim); - for (int d = 0; d < dim; d++) { - pick(dim, vrange, pt->current.x); - vec_copy(dim, pt->current.x, pt->best.x); - } - pt->current.fitness = f(pt->current.x); - pt->best.fitness = pt->current.fitness; - if (pt->current.fitness < sw->global_best->current.fitness) sw->global_best = pt; - } -} - -void swarm_velocity_update(swarm *sw, const int dim) { - for (int p = 0; p < sw->particlec; p++) { - particle *pt = &sw->particles[p]; - for (int d = 0; d < dim; d++) - pt->velocity[d] = w * pt->velocity[d] + c * rands() * (pt->best.x[d] - pt->current.x[d]) + s * rands() * (sw->global_best->current.x[d] - pt->current.x[d]); - } - for (int p = 0; p < sw->particlec; p++) { - particle *pt = &sw->particles[p]; - vec_add(dim, pt->velocity, pt->current.x); - pt->current.fitness = f(pt->current.x); - if (pt->current.fitness < pt->best.fitness) pt->best = pt->current; - if (pt->current.fitness < sw->global_best->current.fitness) sw->global_best = &sw->particles[p]; - } -} - -static void on_activate(GtkApplication *app) { - GtkWidget *window = gtk_application_window_new(app); - GtkWidget *button = gtk_button_new_with_label("Hello, World!"); - g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_window_close), window); - gtk_window_set_child(GTK_WINDOW(window), button); - gtk_window_present(GTK_WINDOW(window)); -} - -int main(int argc, char *argv[]) { - double eps = pow(2, 40); - int dim = 2; - int particlec = 100; - range vrange[2] = { - (range) { -100.0, 100.0 }, - (range) { -100.0, 100.0 } - }; - swarm sw; - sw.particlec = particlec; - swarm_init(&sw, dim, vrange); - int conv = 0; - double best = 0.0; - while (conv < 10000) { - swarm_velocity_update(&sw, dim); - if (fabs(sw.global_best->current.fitness - best) < eps) - conv++; - else { - best = sw.global_best->current.fitness; - conv = 0; - } - } - printf("PSO: converged in x="); - vec_print(dim, sw.global_best->current.x); - printf(" with fitness f(x)=%f\n", sw.global_best->current.fitness); - - GtkApplication *app = gtk_application_new("org.wafflesoft.NCPSO", G_APPLICATION_DEFAULT_FLAGS); - g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/src/swarm.c b/src/swarm.c new file mode 100644 index 0000000..3fe83ff --- /dev/null +++ b/src/swarm.c @@ -0,0 +1,67 @@ +#include +#include +#include "swarm.h" +#include "vector.h" + +double c = 2.05; +double s = 2.05; +double w = 0.8; + +double rands() { + return (double) rand() / RAND_MAX; +} + +double randrange(double min, double max) { + return rands() * (max - min) + min; +} + +void pick(const int dim, const range *vrange, double *v) { + for (int d = 0; d < dim; d++) v[d] = randrange(vrange[d].min, vrange[d].max); +} + +void swarm_populate(swarm *sw, const range *rrange) { + sw->particles = malloc(sizeof(particle) * sw->params.particlec); + sw->global_best = &sw->particles[0]; + for (int p = 0; p < sw->params.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); + } + pt->current.fitness = sw->params.f(pt->current.x); + pt->best.fitness = pt->current.fitness; + if (pt->current.fitness < sw->global_best->current.fitness) sw->global_best = pt; + } +} + +void swarm_velocity_update(swarm *sw) { + for (int p = 0; p < sw->params.particlec; p++) { + particle *pt = &sw->particles[p]; + for (int d = 0; d < sw->params.dim; d++) + pt->velocity[d] = w * pt->velocity[d] + c * rands() * (pt->best.x[d] - pt->current.x[d]) + s * rands() * (sw->global_best->current.x[d] - pt->current.x[d]); + } + for (int p = 0; p < sw->params.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; + if (pt->current.fitness < sw->global_best->current.fitness) sw->global_best = &sw->particles[p]; + } +} + +void swarm_optimize(swarm *sw) { + int conv = 0; + double best = INFINITY; + while (conv < 10000) { + swarm_velocity_update(sw); + if (fabs(sw->global_best->current.fitness - best) < sw->params.eps) + conv++; + else { + best = sw->global_best->current.fitness; + conv = 0; + } + } +} -- 2.34.1