Skip to content

Repository files navigation

ARRDE

ARRDE (Adaptive Restart-Refine Differential Evolution) is a standalone C++17 library implementing a self-adaptive differential evolution optimizer for bound-constrained, derivative-free minimization.

ARRDE runs a current-to-pbest/1 bin DE variant with external archive, Cauchy/normal parameter adaptation, population-size reduction, and an adaptive restart–refine cycle: it restarts with fresh samples when progress stagnates and switches to a refinement phase that exploits accumulated population and archive records as the evaluation budget nears exhaustion.

Origin

ARRDE was originally developed by Khoirul Faiq Muzakka as part of the Minion optimization framework.

This repository is not the original implementation. It is a standalone extraction and simplification of the ARRDE code from Minion, reduced to a single optimizer while preserving its numerical behavior exactly. The extraction history and validation methodology are documented in docs/EXTRACTION.md.

Features

  • Single, dependency-free C++17 optimizer (class ARRDE)
  • Deterministic, seedable RNG stream per run
  • Batch (population) objective interface — evaluate many candidates per call
  • Six bound-enforcement strategies
  • Latin-hypercube or uniform population initialization
  • Optional callback for progress reporting and early stopping

Public API

All names live in namespace arrde (header: algorithms/arrde.h).

Types

Type Description
Result Optimization outcome: x, fun, nit, nfev, status, message
TerminationStatus Running, MaxEvaluationsReached, CallbackStopped, RuntimeError
ObjectiveFunction std::function<std::vector<double>(const std::vector<std::vector<double>>&, void*)> — receives a batch of candidate points, returns one fitness value per point
ConfigValue std::variant<bool, int, double, std::string> option value
Options Typed map wrapper; get<T>(key, default)

Optimizer

class ARRDE {
public:
    ARRDE(ObjectiveFunction func,
          const std::vector<std::pair<double,double>>& bounds,
          const std::vector<std::vector<double>>& x0 = {},
          void* data = nullptr,
          std::function<bool(Result*)> callback = nullptr,
          size_t maxevals = 100000,
          int seed = -1,
          std::map<std::string, ConfigValue> options = {});

    Result optimize();
};
  • bounds — one {lower, upper} pair per dimension.
  • x0 — optional initial guesses (each dimension of bounds); used to seed the initial population.
  • data — opaque pointer passed through to the objective.
  • callback — invoked with intermediate results; return true to stop.
  • seed — seeds the global RNG; -1 leaves the RNG unseeded (randomly initialized).
  • Throws std::invalid_argument on invalid bounds or mismatched x0.

Utility functions

The header also exposes the supporting utilities used by ARRDE: set_global_seed, get_rng, rand_gen, rand_int, rand_norm, rand_cauchy, random_choice, argsort, findMin, findArgMin, findArgMax, clamp, latin_hypercube_sampling, random_sampling, calcMean, calcStdDev, enforce_bounds.

Options

Key Type Default Meaning
population_size int 0 Initial population size; 0 selects a size automatically from budget and dimensionality
bound_strategy string "reflect-random" Out-of-bounds handling: clip, reflect, reflect-random, periodic, random, none

Usage example

#include "algorithms/arrde.h"

std::vector<double> sphere(const std::vector<std::vector<double>>& X, void*) {
    std::vector<double> f;
    f.reserve(X.size());
    for (const auto& x : X) {
        double s = 0.0;
        for (double v : x) s += v * v;
        f.push_back(s);
    }
    return f;
}

int main() {
    std::vector<std::pair<double, double>> bounds(10, {-100.0, 100.0});

    arrde::ARRDE opt(sphere, bounds, {}, nullptr, nullptr,
                     100000 /*maxevals*/, 42 /*seed*/);

    arrde::Result res = opt.optimize();
    // res.fun  - best objective value found
    // res.x    - minimizer
    // res.nfev - number of objective evaluations used
}

A complete runnable example against the CEC-2017 benchmark suite is in test_arrde_f24.cpp.

Building

Prerequisites: a C++17 compiler and CMake ≥ 3.14. The bundled CEC-2017 benchmark needs its input data:

bash get_cec2017.sh   # downloads cec_input_data/
bash build.sh         # configures and builds into build/
bash run.sh           # runs the F24 regression example

Or manually:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
./build/test_arrde_f24            # F24, D=30, 300000 evals, seed 42
./build/test_arrde_f24 24 20 300000 20260817 10000

Repository layout

algorithms/arrde.h           public API: types + ARRDE class + utility templates
algorithms/arrde.cpp         optimizer implementation
algorithms/arrde_utils.cpp   RNG state, sampling, statistics helpers
algorithms/default_options.h default option values
cec/                         CEC-2017 benchmark wrapper (test-only)
test_arrde_f24.cpp           example driver / regression entry point
docs/EXTRACTION.md           extraction and validation history
docs/extraction/             archived prompts and per-pass analysis reports
build.sh, run.sh             convenience scripts
get_cec2017.sh               benchmark data downloader

Development

This standalone library was produced through a sequence of small, behavior-preserving refactoring passes, each followed by a deterministic regression test comparing the complete optimizer output byte-for-byte against recorded baselines. Every cleanup stage is therefore verified to leave the algorithm's numerical behavior unchanged.

The refactoring was assisted by AI tools (ChatGPT, OpenCode, Ollama, and local Qwen models); the ARRDE algorithm itself remains the work of its original author.

License

See LICENSE.

About

ARRDE and CEC-2017 (~3.4 KLOC) extracted from Minion (~27 KLOC).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages