From f931b7ef3f20486f50f4894a6933277efecef0ea Mon Sep 17 00:00:00 2001 From: ametama Date: Thu, 15 Jan 2026 03:50:32 +0100 Subject: [PATCH] feat: differential evolution optimizer --- include/de.h | 12 ++++++++++++ src/de.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/main.c | 22 +++++++++++++++++----- 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 include/de.h create mode 100644 src/de.c diff --git a/include/de.h b/include/de.h new file mode 100644 index 0000000..cb95e53 --- /dev/null +++ b/include/de.h @@ -0,0 +1,12 @@ +#include "swarm.h" + +typedef struct { + int dim; + int particlec; + range *rrange; + double (*f)(double*); // fitness function + double cr; // crossover probability = .9 + double dw; // differential weight = .8 +} de_parameters; + +void de_optimize(de_parameters *par, double *res); diff --git a/src/de.c b/src/de.c new file mode 100644 index 0000000..8377787 --- /dev/null +++ b/src/de.c @@ -0,0 +1,43 @@ +#include +#include "vector.h" +#include "de.h" + +void de_optimize(de_parameters *par, double *res) { + int l = par->particlec * par->dim; + double *mem = malloc(sizeof(double) * l * 2); + int conv = 0; + double *xs = mem; + double *ys = mem + l; + for (double *x = xs; x < ys; x += par->dim) + vec_pick(par->dim, par->rrange, x); + while (conv < 1000) { + for (double *x = xs; x < ys; x += par->dim) { + double *y = x + l; + double *picks[4] = { x }; // agents { x, a, b, c } + for (int i = 1; i < 4; i++) { + double *pick = xs + (rand() % (par->particlec - i)); + picks[i] = pick; + for (int k = 0; k < i; k++) + if (pick >= picks[k]) picks[i]++; + } + int r = rand() % par->dim; + for (int i = 0; i < par->dim; i++) { + if (i == r || rands() < par->cr) y[i] = picks[1][i] + par->dw * (picks[2][i] - picks[3][i]); + else y[i] = x[i]; + } + if (par->f(y) <= par->f(x)) vec_copy(par->dim, y, x); + else conv++; + } + } + double *best = xs; + double bestf = par->f(best); + for (double *x = xs; x < ys; x += par->dim) { + double cur = par->f(x); + if (cur < bestf) { + best = x; + bestf = cur; + } + } + vec_copy(par->dim, best, res); + free(mem); +} diff --git a/src/main.c b/src/main.c index 430874c..c56f590 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ #include #include #include "vector.h" -#include "swarm.h" +#include "de.h" double b0(double *x) { return -x[0]; @@ -28,6 +28,7 @@ int main(int argc, char *argv[]) { (range) { -100.0, 100.0 }, (range) { -100.0, 100.0 } }; + /* swarm_parameters par = { 2, 100, @@ -38,11 +39,22 @@ int main(int argc, char *argv[]) { 2.05, 2.05 }; - particle_state best = { vec_alloc(par.dim), 0.0 }; - swarm_optimize(&par, &best); + */ + de_parameters par = { + 2, + 100, + rrange, + f, + 0.9, + 0.8 + }; + // particle_state best = { vec_alloc(par.dim), 0.0 }; + double res[2]; + //swarm_optimize(&par, &best); + de_optimize(&par, res); printf("apso: converged in x="); - vec_print(par.dim, best.x); - printf(" with fitness f(x)=%f\n", best.fitness); + vec_print(par.dim, res); + printf(" with fitness f(x)=%f\n", f(res)); // GtkApplication *app = gui_init(); // return g_application_run(G_APPLICATION(app), argc, argv); return 0; -- 2.34.1