CEC and BBOB2009 Benchmarks
This page describes how to minimize CEC benchmark functions and the BBOB2009 benchmark suite with both the C++ and Python Minion APIs.
General Pattern
Using a CEC benchmark follows the same overall workflow as any other objective:
Construct a benchmark evaluator such as
CEC2017Functions.Provide search
boundsseparately toMinimizer.Run
optimize().
CEC benchmark evaluators are already batch evaluators:
In C++, benchmark classes derive from
minion::CECBaseand evaluate batches throughoperator()(const std::vector<std::vector<double>>& X).In Python, benchmark wrappers are already vectorized and can be passed directly as
func=...tominionpy.Minimizer.
The same pattern also applies to BBOB2009Problem:
In C++, the BBOB wrapper exposes
evaluateBatchandoperator().In Python,
BBOB2009Problemis callable and can be passed directly tominionpy.Minimizer.
Constructor Pattern
The benchmark suites use these constructor forms:
minion::CEC2014Functions(function_number, dimension)
minion::CEC2017Functions(function_number, dimension)
minion::CEC2019Functions(function_number, dimension)
minion::CEC2020Functions(function_number, dimension)
minion::CEC2022Functions(function_number, dimension)
minion::CEC2011Functions(function_number, dimension)
minion::BBOB2009Problem(function_number, dimension)
mpy.CEC2014Functions(function_number, dimension)
mpy.CEC2017Functions(function_number, dimension)
mpy.CEC2019Functions(function_number, dimension)
mpy.CEC2020Functions(function_number, dimension)
mpy.CEC2022Functions(function_number, dimension)
mpy.CEC2011Functions(function_number, dimension)
mpy.BBOB2009Problem(function_number, dimension)
Valid Dimensions
Valid dimensions by suite:
CEC2011: fixed, problem-specific dimensions depending on the selected functionCEC2014:2, 10, 20, 30, 50, 100CEC2017:2, 10, 20, 30, 50, 100CEC2019:9for F1,16for F2,18for F3, and10for F4-F10CEC2020: C++ implementation accepts2, 5, 10, 15, 20, 30, 50, 100Python wrapper currently accepts2, 5, 10, 15, 20CEC2022: C++ implementation accepts2, 10, 20Python wrapper currently accepts2, 10, 20BBOB2009:2, 5, 10, 20, 40
Some suites also have function-specific restrictions at certain dimensions.
C++ Usage
The usual C++ pattern is to adapt the CEC evaluator to MinionFunction:
#include <minion.h>
#include <minion_cec.h>
std::vector<double> cec2017_batch(const std::vector<std::vector<double>>& X, void* data) {
auto* cec = static_cast<minion::CECBase*>(data);
return (*cec)(X);
}
int main() {
const int function_number = 1;
const int dimension = 30;
const size_t maxevals = 30000;
const int seed = 20250306;
minion::CEC2017Functions cec_f1(function_number, dimension);
std::vector<std::pair<double, double>> bounds(dimension, {-100.0, 100.0});
std::vector<std::vector<double>> x0 = {};
auto options = minion::DefaultSettings().getDefaultSettings("ARRDE");
minion::Minimizer optimizer(
cec2017_batch, bounds, x0, &cec_f1, nullptr, "ARRDE", maxevals, seed, options
);
minion::MinionResult result = optimizer.optimize();
}
For BBOB2009, the same pattern works with BBOB2009Problem:
#include <minion.h>
#include <bbob2009.h>
int main() {
const int function_number = 1;
const int dimension = 10;
const size_t maxevals = 30000;
const int seed = 20250306;
minion::BBOB2009Problem bbob(function_number, dimension);
std::vector<std::vector<double>> x0 = {bbob.initialSolution()};
auto bounds = bbob.bounds();
minion::Minimizer optimizer(
bbob, bounds, x0, nullptr, nullptr, "ARRDE", maxevals, seed
);
minion::MinionResult result = optimizer.optimize();
}
Python Usage
In Python, no adapter is needed because the benchmark wrapper is already vectorized:
import minionpy as mpy
function_number = 1
dimension = 30
maxevals = 30000
seed = 20250306
cec_f1 = mpy.CEC2017Functions(function_number=function_number, dimension=dimension)
bounds = [(-100.0, 100.0)] * dimension
optimizer = mpy.Minimizer(
func=cec_f1,
x0=None,
bounds=bounds,
algo="ARRDE",
maxevals=maxevals,
callback=None,
seed=seed,
options=None,
)
result = optimizer.optimize()
print("best f =", result.fun)
print("f_opt =", cec_f1.f_opt)
For BBOB2009, the same direct usage works with BBOB2009Problem:
import minionpy as mpy
function_number = 1
dimension = 10
maxevals = 30000
seed = 20250306
bbob = mpy.BBOB2009Problem(function_number=function_number, dimension=dimension)
bounds = bbob.bounds
optimizer = mpy.Minimizer(
func=bbob,
x0=[bbob.initial_solution],
bounds=bounds,
algo="ARRDE",
maxevals=maxevals,
callback=None,
seed=seed,
options=None,
)
result = optimizer.optimize()
print("best f =", result.fun)
print("f_opt =", bbob.f_opt)
Benchmark Driver
For repeated benchmark runs, use examples/main_run_benchmark.cpp.
It is built as the run_benchmark example target when MINION_BUILD_EXAMPLES=ON and MINION_BUILD_BENCHMARK=ON.
Build it:
cmake --build build --target run_benchmark --config Release
Run it:
./build/bin/run_benchmark cec 1 10 ARRDE 0 2017 30000 1 8
./build/bin/run_benchmark bbob 1 10 ARRDE 0 2009 30000 1 8
The command-line layout is:
cec|bbob Nruns dim algo popsize year maxevals nthreads acc
If you omit the leading cec or bbob, the driver defaults to cec.
Python Benchmark API
The Python binding exposes the benchmark runner through:
minionpy.run_benchmark(mode="cec" | "bbob", ...)minionpy.Benchmarkminionpy.BenchmarkConfigminionpy.BenchmarkModefor lower-level use
Example:
import minionpy as mpy
result = mpy.run_benchmark(
mode="bbob",#cec
num_runs=51,
dimension=10,
algo="ARRDE",
popsize=0,
year=2009,
max_evals=30000,
nthreads=32,
acc=8,
dump_results=False,
results_folder=".",
log_min_ev=False,
)
print(result.results)
print(result.results_file)
If you prefer an object-oriented wrapper, mpy.Benchmark(config).run() is also available, and BenchmarkConfig.mode accepts the enum value mpy.BenchmarkMode.Bbob.
About Bounds
The benchmark object evaluates the objective, but it does not supply bounds to Minimizer automatically. You should still pass bounds explicitly.
Typical examples:
CEC2014/CEC2017/CEC2020/CEC2022: the project benchmark drivers typically use[-100, 100]^Din C++, or[(-100, 100)] * dimensionin PythonCEC2019: use the suite-specific ranges - F1:[-8192, 8192]^9- F2:[-16384, 16384]^16- F3:[-4, 4]^18- F4-F10:[-100, 100]^10CEC2011: use the problem-specific bounds from the original suiteBBOB2009: use the suite-provided bounds fromBBOB2009Problem.bounds
For CEC2011, MinionPy exposes the suite-defined bounds directly.
The benchmark object also exposes f_opt when the suite defines a known global optimum:
cec2011 = mpy.CEC2011Functions(function_number=1, dimension=6)
bounds = cec2011.get_bounds()
f_opt = cec2011.f_opt
For BBOB2009, the problem object exposes the same information:
bbob = mpy.BBOB2009Problem(function_number=1, dimension=10)
bounds = bbob.bounds
f_opt = bbob.f_opt
For a full C++ per-problem bound setup, see the benchmark implementation in minion/benchmark/benchmark.cpp and the integration test in tests/test_minion.cpp.
CEC Benchmark Function Details
The tables below summarize the basic benchmark families used by each numbered function in the current CEC2014 and CEC2017 implementations. In the published suite design, CEC2020 and CEC2022 are best understood as selected subsets of the CEC2017-style benchmark family. The implementation does not simply reuse the CEC2017 public function numbers one-for-one; instead, it dispatches through the shared benchmark families. The tables below therefore map each public suite function to the shared family used by the implementation.
CEC2014
Function number |
Basic functions used |
|---|---|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
CEC2017
Function number |
Basic functions used |
|---|---|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
CEC2020
Public function number |
Shared CEC2017-style family used |
|---|---|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
CEC2022
Function number |
Shared CEC2017-style family used |
|---|---|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
Further Examples
For broader benchmark coverage, see:
tests/test_minion.cpptests/test_minionpy.py