Skip to content

Latest commit

 

History

History
75 lines (54 loc) · 2.61 KB

README.md

File metadata and controls

75 lines (54 loc) · 2.61 KB

de

Single file Apache 2.0 licensed implementation of the Adaptive Differential Evolution optimiser.

Adaptive DE with radius limiting is among the state of the art in gradient-free optimisers. Gradient-free optimisers are theoretically very portable (since they require no information from the problem other than fitness scores). However, I was not happy with the portability of existing DE implementations.

Since this implementation is a single C99 header, it can be easily integrated with any existing build system which supports compiling C code, and the API itself couldn't be simpler.

Usage

Below is a quick tour of every interface in de.h. For a more complete example with error handling and a real world optimisation problem, see example.c.

To use de.h include it where it is needed, and in one file define DIFFERENTIAL_EVOLUTION_IMPL before including the header.

#define DIFFERENTIAL_EVOLUTION_IMPL
#include "de.h"

To initialise the library, fill out a de_settings struct with your problem dimensions, then call de_init. If a memory allocation fails, it will return a null pointer.

de_optimiser *opt = de_init(&(de_settings){
    .dimension_count = 50,      // Number of dimensions in the optimisation problem
    .population_count = 100,    // Number of agents in the population
    .lower_bound = -2.0f,       // Lower bound of the search space (same in all dimensions)
    .upper_bound = 2.0f,        // Upper bound of the search space (same in all dimensions)
    .random_seed = 42,          // Seed for the optimiser's RNG
});

Then (likely in a loop), call de_ask to retrieve an optimisation candidate. The library will also return an id which you must hold onto.

float candidate[50]; // For larger problems, we'll need to heap allocate this
int id = de_ask(opt, candidate);

Compute this candidate's fitness, then report it back to the optimiser with a call to de_tell.

float fitness = my_fitness(candidate); // We want to minimise this
de_tell(opt, id, candidate, fitness);

At any point, you can query the optimiser for the best candidate solution and its corresponding fitness value.

float best_candidate[50];
float best_fitness = de_best(opt, best_candidate);

Finally, when you are finished using the optimiser, remember to free its memory with de_deinit.

de_deinit(opt);

That's it! That's the entire library. See example.c for a complete example optimising the rosenbrock function.

Custom Allocators

To use your own custom allocators, define DE_ALLOC(dz) and DE_FREE(p) before including the header. These default to using malloc and free.