fcmaes 2.0.2__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fcmaes-2.0.2 → fcmaes-2.0.3}/PKG-INFO +9 -4
- {fcmaes-2.0.2 → fcmaes-2.0.3}/README.adoc +27 -2
- fcmaes-2.0.3/README.md +13 -0
- fcmaes-2.0.3/ai-context.md +711 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/pyproject.toml +3 -1
- fcmaes-2.0.2/README.md +0 -10
- {fcmaes-2.0.2 → fcmaes-2.0.3}/.gitignore +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/CMakeLists.txt +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/LICENSE +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/CMakeLists.txt +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/acmaesoptimizer.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/acma_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/acma_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/bite_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/bite_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/common.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/crfmnes_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/crfmnes_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/da_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/da_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/de_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/de_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/gil_utils.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/gtop_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/gtop_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/mode_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/mode_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/module.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/ndarray_utils.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/pgpe_bindings.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/bindings/pgpe_bindings.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/biteoptimizer.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/crfmnes.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/daoptimizer.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/deoptimizer.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/gtop.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGS.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSB.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/BFGSMat.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/BKLDLT.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/Cauchy.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/LineSearchBacktracking.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/LineSearchBracketing.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/LineSearchMoreThuente.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/LineSearchNocedalWright.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/Param.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/LBFGSpp/SubspaceMin.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/acmaesoptimizer.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/biteaux.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/biteopt.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/biteopt_asktell.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/biteoptimizer.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/biteort.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/crfmnesoptimizer.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/daoptimizer.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/deopt.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/deoptimizer.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/evaluator.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/gtop.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/modeoptimizer.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/nmsopt.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/pcg_extras.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/pcg_random.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/pcg_uint128.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/pgpeoptimizer.hpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/smaesopt.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/include/spheropt.h +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/modeoptimizer.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/_fcmaescpp/pgpe.cpp +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/__init__.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/_fcmaes_ext.pyi +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/_native.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/advretry.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/astro.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/bitecpp.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/cmaes.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/cmaescpp.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/crfmnes.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/crfmnescpp.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/dacpp.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/de.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/decpp.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/diversifier.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/evaluator.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/journal.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/mapelites.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/mode.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/modecpp.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/moretry.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/multiretry.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/optimizer.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/pgpecpp.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/pygmoretry.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/retry.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/test_cma.py +0 -0
- {fcmaes-2.0.2 → fcmaes-2.0.3}/fcmaes/testfun.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: fcmaes
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: A Python 3 gradient-free optimization library.
|
|
5
5
|
Keywords: optimization,multi-objective,parallel
|
|
6
6
|
Author-Email: Dietmar Wolz <drdietmarwolz@yahoo.de>
|
|
@@ -24,6 +24,8 @@ Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
|
24
24
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
25
25
|
Project-URL: Homepage, https://github.com/dietmarwo/fast-cma-es
|
|
26
26
|
Project-URL: Repository, https://github.com/dietmarwo/fast-cma-es
|
|
27
|
+
Project-URL: Documentation, https://dietmarwo.github.io/fast-cma-es/
|
|
28
|
+
Project-URL: Tutorials, https://dietmarwo.github.io/fast-cma-es/tutorials/
|
|
27
29
|
Requires-Python: >=3.10
|
|
28
30
|
Requires-Dist: numpy
|
|
29
31
|
Requires-Dist: scipy
|
|
@@ -37,9 +39,12 @@ Description-Content-Type: text/markdown
|
|
|
37
39
|
# fcmaes
|
|
38
40
|
A Python 3 gradient-free optimization library.
|
|
39
41
|
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
42
|
-
|
|
42
|
+
- [Documentation book](https://dietmarwo.github.io/fast-cma-es/)
|
|
43
|
+
- [Full README](https://github.com/dietmarwo/fast-cma-es/blob/master/README.adoc)
|
|
44
|
+
- [Tutorials](https://dietmarwo.github.io/fast-cma-es/tutorials/)
|
|
45
|
+
- [Python API](https://dietmarwo.github.io/fast-cma-es/fcmaes_documentation.html)
|
|
46
|
+
- [C++ API](https://dietmarwo.github.io/fast-cma-es/cpp_documentation.html)
|
|
47
|
+
- [Examples API](https://dietmarwo.github.io/fast-cma-es/examples_documentation.html)
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
|
|
@@ -14,9 +14,9 @@ It supports multi-threaded use of several gradient-free
|
|
|
14
14
|
https://dietmarwo.github.io/fast-cma-es/fcmaes_documentation.html[algorithms] partly implemented in https://dietmarwo.github.io/fast-cma-es/cpp_documentation.html[{cpp}].
|
|
15
15
|
It is designed for real-world problems, including multi-objective and constrained optimization. The main algorithms are available in both Python and C++. They support parallel fitness evaluation as well as parallel retry strategies.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The https://dietmarwo.github.io/fast-cma-es/[documentation book] combines the API references with many practical https://dietmarwo.github.io/fast-cma-es/tutorials/[tutorials] and https://dietmarwo.github.io/fast-cma-es/examples_documentation.html[examples] that show how to use fcmaes in detail.
|
|
18
18
|
|
|
19
|
-
Detailed benchmark results are available in https://github.
|
|
19
|
+
Detailed benchmark results are available in the book's https://dietmarwo.github.io/fast-cma-es/tutorials/Performance.html[performance chapter].
|
|
20
20
|
|
|
21
21
|
=== Features
|
|
22
22
|
|
|
@@ -29,6 +29,9 @@ Detailed benchmark results are available in https://github.com/dietmarwo/fast-cm
|
|
|
29
29
|
- Offers a selection of efficient single-objective optimizers.
|
|
30
30
|
- Provides an ask-tell interface for CMA-ES, CR-FM-NES, DE, MODE, and PGPE.
|
|
31
31
|
|
|
32
|
+
=== Update: Native Rust implementation of fcmaes
|
|
33
|
+
See https://github.com/dietmarwo/fcmaes-rust[fcmaes-rust]. This repo is an alternative both for Rust and Python users as it provides a PyO3 API. See https://github.com/dietmarwo/fcmaes-rust/blob/main/examples/python/test_cma.py[python example].
|
|
34
|
+
|
|
32
35
|
=== Update (2.0.2): Ask Tell interface for BiteOpt
|
|
33
36
|
|
|
34
37
|
The native BiteOpt backend now also provides an ask/tell interface through `bitecpp.Bite_C`.
|
|
@@ -245,6 +248,28 @@ Example dependencies:
|
|
|
245
248
|
|
|
246
249
|
- pykep: https://esa.github.io/pykep/[pykep]. Install with 'pip install pykep'.
|
|
247
250
|
|
|
251
|
+
=== Documentation
|
|
252
|
+
|
|
253
|
+
The GitHub Pages workflow builds this README, all AsciiDoc tutorials, and the
|
|
254
|
+
three maintained HTML API references as one navigable site:
|
|
255
|
+
|
|
256
|
+
- https://dietmarwo.github.io/fast-cma-es/[Documentation home]
|
|
257
|
+
- https://dietmarwo.github.io/fast-cma-es/fcmaes_documentation.html[Python API]
|
|
258
|
+
- https://dietmarwo.github.io/fast-cma-es/cpp_documentation.html[{cpp} API]
|
|
259
|
+
- https://dietmarwo.github.io/fast-cma-es/examples_documentation.html[Examples API]
|
|
260
|
+
- https://dietmarwo.github.io/fast-cma-es/tutorials/[Tutorial index]
|
|
261
|
+
|
|
262
|
+
Build and validate the same site locally with Asciidoctor 2.0.23 or newer:
|
|
263
|
+
|
|
264
|
+
[source,bash]
|
|
265
|
+
----
|
|
266
|
+
gem install asciidoctor --version 2.0.23 --no-document
|
|
267
|
+
python scripts/build_docs.py
|
|
268
|
+
----
|
|
269
|
+
|
|
270
|
+
The generated site is written to `target/site`. AsciiDoc remains the canonical
|
|
271
|
+
source; no Markdown conversion is required.
|
|
272
|
+
|
|
248
273
|
=== Packaging and release
|
|
249
274
|
|
|
250
275
|
- Pull requests and branch pushes build wheels on Linux, Windows, and macOS.
|
fcmaes-2.0.3/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# fcmaes
|
|
2
|
+
A Python 3 gradient-free optimization library.
|
|
3
|
+
|
|
4
|
+
- [Documentation book](https://dietmarwo.github.io/fast-cma-es/)
|
|
5
|
+
- [Full README](https://github.com/dietmarwo/fast-cma-es/blob/master/README.adoc)
|
|
6
|
+
- [Tutorials](https://dietmarwo.github.io/fast-cma-es/tutorials/)
|
|
7
|
+
- [Python API](https://dietmarwo.github.io/fast-cma-es/fcmaes_documentation.html)
|
|
8
|
+
- [C++ API](https://dietmarwo.github.io/fast-cma-es/cpp_documentation.html)
|
|
9
|
+
- [Examples API](https://dietmarwo.github.io/fast-cma-es/examples_documentation.html)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
# AI context for solving user optimization problems with fcmaes
|
|
2
|
+
|
|
3
|
+
This file is operational context for an AI that must design and implement an
|
|
4
|
+
optimization solution with this repository. It is not a claim that one
|
|
5
|
+
optimizer is universally best. Use the problem structure, evaluation cost, and
|
|
6
|
+
the user's desired output to choose a small set of defensible candidates, then
|
|
7
|
+
compare them under the same evaluation and worker budget.
|
|
8
|
+
|
|
9
|
+
The repository provides the `fcmaes` Python package. It combines Python
|
|
10
|
+
optimizer and orchestration code with a C++17 backend exposed through nanobind.
|
|
11
|
+
The modules whose names end in `cpp` use that native backend; modules such as
|
|
12
|
+
`de.py`, `cmaes.py`, and `mode.py` contain Python implementations. All
|
|
13
|
+
optimizers minimize.
|
|
14
|
+
|
|
15
|
+
The public distribution and import name are the same:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
python -m pip install fcmaes
|
|
19
|
+
python -c "import fcmaes"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The published package requires Python 3.10 or newer. Release wheels target
|
|
23
|
+
CPython 3.10 through 3.13 on Linux x86-64, Windows AMD64, and current Intel and
|
|
24
|
+
Apple Silicon macOS runners. Installing a matching wheel needs no compiler.
|
|
25
|
+
A source build needs a C++17 compiler, CMake, nanobind, and Eigen 3.4.
|
|
26
|
+
Repository `examples`, `tutorials`, documentation sources, scripts, and tests
|
|
27
|
+
are intentionally excluded from the source distribution.
|
|
28
|
+
|
|
29
|
+
Use public Python wrappers such as `fcmaes.decpp.minimize` rather than calling
|
|
30
|
+
private extension symbols directly. Return values from scalar minimizers are
|
|
31
|
+
normally `scipy.optimize.OptimizeResult` objects with `x`, `fun`, `nfev`,
|
|
32
|
+
`nit`, `status`, and `success` fields. Multi-objective and quality-diversity
|
|
33
|
+
entry points return arrays or archives as documented by their modules.
|
|
34
|
+
|
|
35
|
+
## Required workflow for the AI
|
|
36
|
+
|
|
37
|
+
Before selecting an algorithm, create a problem card containing these facts.
|
|
38
|
+
Inspect the user's code and data where possible. Ask only for facts that cannot
|
|
39
|
+
be inferred and would materially change the solution.
|
|
40
|
+
|
|
41
|
+
| Question | Why it matters |
|
|
42
|
+
|---|---|
|
|
43
|
+
| What is the decision dimension? | Population size, covariance cost, and useful budgets depend strongly on dimension. |
|
|
44
|
+
| What is each variable's lower and upper bound? | Most global algorithms need a finite, meaningful search box. |
|
|
45
|
+
| Which variables are continuous, integer, ordinal, categorical, or structured? | DE and MODE have integer support, but categorical and structured variables still need decoding or repair. |
|
|
46
|
+
| Is there one objective, several objectives, or a quality-diversity archive? | This selects scalar optimization, MODE/weighted retry, or MAP-Elites. |
|
|
47
|
+
| Which directions are optimized? | Convert maximization to minimization by negating the value. |
|
|
48
|
+
| What are the constraints and feasibility convention? | MODE and `moretry` require constraints after objectives and treat `g(x) <= 0` as feasible. |
|
|
49
|
+
| Is a good initial point known? | CMA-ES, CR-FM-NES, PGPE, and local refinement benefit from it. |
|
|
50
|
+
| Is the objective smooth, discontinuous, noisy, stochastic, or multimodal? | Distribution search, restart strategy, and stopping tolerances differ. |
|
|
51
|
+
| For a stochastic objective, can simulations accept explicit seeds? | Common random numbers make comparisons fair; disjoint seeds are needed for validation. |
|
|
52
|
+
| How long does one evaluation take, and is it safe to run in another process? | This determines inner population evaluation versus outer retry parallelism. |
|
|
53
|
+
| What is the evaluation, wall-time, memory, and core budget? | Evaluation counts are the fairest first comparison unit. |
|
|
54
|
+
| Is a target value known? | Set `stop_fitness`; do not confuse it with the store filter `value_limit`. |
|
|
55
|
+
| Does the user need one solution, a Pareto front, or diverse behavior niches? | The requested output is part of the algorithm choice. |
|
|
56
|
+
|
|
57
|
+
Do not proceed with arbitrary placeholder bounds. If bounds are genuinely
|
|
58
|
+
unknown, derive physically meaningful limits or transform the variables. An
|
|
59
|
+
unnecessarily wide search box can cost orders of magnitude more evaluations.
|
|
60
|
+
|
|
61
|
+
For every completed solution, report the problem card, algorithm and rejected
|
|
62
|
+
alternatives, objective and constraint convention, every non-default
|
|
63
|
+
parameter, evaluation and process budgets, random seeds, validation method,
|
|
64
|
+
and quality statistics. Code without this configuration record is not a
|
|
65
|
+
reproducible optimization solution.
|
|
66
|
+
|
|
67
|
+
## First decide whether fcmaes is appropriate
|
|
68
|
+
|
|
69
|
+
Do not choose a gradient-free optimizer merely because the model is a
|
|
70
|
+
simulation. Prefer a gradient-based optimizer when all variables are
|
|
71
|
+
continuous, the complete objective is differentiable, reliable analytical,
|
|
72
|
+
automatic-differentiation, adjoint, or sensitivity gradients are available,
|
|
73
|
+
and the user needs one optimum or a smooth trade-off. Those gradients usually
|
|
74
|
+
carry much more information per evaluation.
|
|
75
|
+
|
|
76
|
+
fcmaes is a strong candidate when one or more of these conditions holds:
|
|
77
|
+
|
|
78
|
+
- gradients are unavailable, unreliable, or dominated by simulation noise;
|
|
79
|
+
- events, contact, clipping, repair, routing, integer choices, or categorical
|
|
80
|
+
decoding make the complete objective nonsmooth;
|
|
81
|
+
- the landscape is multimodal and needs global exploration or many restarts;
|
|
82
|
+
- objectives are cheap enough that optimizer overhead and parallel retries
|
|
83
|
+
matter;
|
|
84
|
+
- the result must cover behaviorally different niches instead of returning
|
|
85
|
+
only one optimum; or
|
|
86
|
+
- robust maxima, quantiles, failures, or other outer logic make an otherwise
|
|
87
|
+
smooth model nonsmooth.
|
|
88
|
+
|
|
89
|
+
Route evaluation-scarce problems to Bayesian or surrogate optimization when
|
|
90
|
+
only tens or hundreds of evaluations are affordable and a useful surrogate
|
|
91
|
+
can be fitted. Route exact linear, mixed-integer linear, routing, and
|
|
92
|
+
scheduling formulations to dedicated mathematical-programming solvers when
|
|
93
|
+
their structure can be expressed faithfully. Use fcmaes for structured
|
|
94
|
+
problems only when a defensible continuous encoding and deterministic repair
|
|
95
|
+
are part of the formulation.
|
|
96
|
+
|
|
97
|
+
## Fast algorithm-selection decision tree
|
|
98
|
+
|
|
99
|
+
1. If valid and economical gradients exist for the complete map from decisions
|
|
100
|
+
to objectives, start with a gradient-based method.
|
|
101
|
+
2. If the user wants the best solution in many behavior niches, use
|
|
102
|
+
`mapelites.optimize_map_elites`. Add `diversifier.minimize` when local
|
|
103
|
+
improvement emitters are useful.
|
|
104
|
+
3. If there are two or more competing objectives:
|
|
105
|
+
- Use `modecpp.minimize` for one coordinated Pareto population, especially
|
|
106
|
+
with explicit constraints or integer-decoded variables.
|
|
107
|
+
- Use `moretry.minimize` when many independent weighted scalar runs are
|
|
108
|
+
desirable or a DE/CMA/BiteOpt scalar pipeline is already effective.
|
|
109
|
+
4. For one scalar objective:
|
|
110
|
+
- Start with native BiteOpt for a difficult bounded, nonsmooth,
|
|
111
|
+
multimodal, or poorly characterized black box.
|
|
112
|
+
- Start with native DE for robust bounded exploration, integer-decoded
|
|
113
|
+
variables, and DE-to-CMA sequences.
|
|
114
|
+
- Use active CMA-ES when a useful guess exists, variables are continuous,
|
|
115
|
+
and correlations or ill-conditioning matter.
|
|
116
|
+
- Use CR-FM-NES for higher-dimensional continuous distribution search.
|
|
117
|
+
- Use PGPE for very high-dimensional mirrored sampling, noisy policy
|
|
118
|
+
search, or high-throughput batch objectives.
|
|
119
|
+
- Use Dual Annealing for low-to-moderate-dimensional global exploration,
|
|
120
|
+
optionally followed by its local search.
|
|
121
|
+
5. If local optima are likely, use independent `retry`. Compare
|
|
122
|
+
`advretry` only when retained elites, crossover boxes, and increasing
|
|
123
|
+
per-run budgets are plausible advantages.
|
|
124
|
+
6. Benchmark at least two plausible choices with identical bounds, objective,
|
|
125
|
+
total evaluations, random protocol, and worker resources. A useful general
|
|
126
|
+
comparison is BiteOpt retry versus DE followed by CMA-ES.
|
|
127
|
+
|
|
128
|
+
## Choose the integration surface
|
|
129
|
+
|
|
130
|
+
For normal Python use, prefer these native wrappers:
|
|
131
|
+
|
|
132
|
+
- `fcmaes.bitecpp.minimize`
|
|
133
|
+
- `fcmaes.decpp.minimize`
|
|
134
|
+
- `fcmaes.cmaescpp.minimize`
|
|
135
|
+
- `fcmaes.crfmnescpp.minimize`
|
|
136
|
+
- `fcmaes.pgpecpp.minimize`
|
|
137
|
+
- `fcmaes.dacpp.minimize`
|
|
138
|
+
- `fcmaes.modecpp.minimize`
|
|
139
|
+
|
|
140
|
+
The corresponding stateful `Bite_C`, `DE_C`, `ACMA_C`, `CRFMNES_C`,
|
|
141
|
+
`PGPE_C`, and `MODE_C` classes provide ask/tell integration. Use ask/tell when
|
|
142
|
+
the application owns batching, remote execution, accelerators, or a simulator
|
|
143
|
+
pool. Preserve candidate order between `ask()` and `tell()`.
|
|
144
|
+
|
|
145
|
+
The Python `de`, `cmaes`, `crfmnes`, and `mode` modules remain useful for
|
|
146
|
+
experimentation, inspection, custom modifiers, and comparisons. Do not mix
|
|
147
|
+
Python and C++ APIs just because class names look similar; verify the exact
|
|
148
|
+
signature in the current module or generated API documentation.
|
|
149
|
+
|
|
150
|
+
Use `fcmaes.optimizer` adapters with `retry` and `advretry`. `Sequence`
|
|
151
|
+
passes the best point from one optimizer to the next. `Choice` selects one
|
|
152
|
+
configured optimizer per run. Maintained constructors include `de_cma`,
|
|
153
|
+
`de_cma_py`, `da_cma`, `de_crfmnes`, `crfmnes_bite`, `bite_cma`, and
|
|
154
|
+
`cma_bite`.
|
|
155
|
+
|
|
156
|
+
The objective callback boundary is important:
|
|
157
|
+
|
|
158
|
+
- Cheap scalar Python callbacks do not become fast merely because the search
|
|
159
|
+
loop is C++; each callback still crosses into Python and needs the GIL.
|
|
160
|
+
- `retry`, `advretry`, `moretry`, and the evaluator helpers use Python
|
|
161
|
+
processes, bypassing the GIL but requiring serializable inputs and incurring
|
|
162
|
+
inter-process communication.
|
|
163
|
+
- NumPy, SciPy, native extensions, external programs, and simulations may
|
|
164
|
+
release the GIL or own their own thread pools. Measure the complete topology.
|
|
165
|
+
- Ask/tell is the safest integration for a user-owned vectorized, distributed,
|
|
166
|
+
or asynchronous evaluator.
|
|
167
|
+
|
|
168
|
+
## Algorithm comparison
|
|
169
|
+
|
|
170
|
+
| Algorithm | Best fit | Main limitation | Practical initial configuration |
|
|
171
|
+
|---|---|---|---|
|
|
172
|
+
| Native DE (`decpp`) | Bounded global search, discontinuities, integer decoding, restarts | Smooth local convergence can be slower than CMA-ES | Population 31, `F=0.5`, `CR=0.9`; compare a DE-to-CMA sequence |
|
|
173
|
+
| Active CMA-ES (`cmaescpp`) | Continuous correlated or ill-conditioned variables, refinement from a guess | Full covariance work becomes costly in high dimension | Population 31, normalized coordinates, sigma based on uncertainty |
|
|
174
|
+
| CR-FM-NES (`crfmnescpp`) | Medium/high-dimensional continuous search and complete batch evaluation | Needs a meaningful center and scalar sigma; not a discrete optimizer | Even population 32; parallelize expensive batches |
|
|
175
|
+
| PGPE (`pgpecpp`) | Very high-dimensional mirrored sampling, noisy objectives, policy search | Diagonal distribution does not learn a full covariance matrix | Even population 32; ranking enabled for one-shot `minimize` |
|
|
176
|
+
| Dual Annealing (`dacpp`) | Low/moderate-dimensional global exploration with optional refinement | No population ask/tell interface | Keep local search for deterministic smooth-enough objectives |
|
|
177
|
+
| BiteOpt (`bitecpp`) | Hard bounded black boxes, nonsmoothness, multimodality, little tuning | Constraints need penalties or repair; batched ask/tell changes feedback timing | Automatic population and `M=1` first |
|
|
178
|
+
| MODE (`modecpp`) | Constrained multi-objective Pareto search | Objective rows and constraint conventions must be exact | Population 64–256, NSGA-II update, evaluate complete populations |
|
|
179
|
+
| Weighted MO retry (`moretry`) | Independent scalarizations with any scalar optimizer | Sensitive to objective scaling and weight ranges | Tens or hundreds of retries; normalize objectives |
|
|
180
|
+
| CVT MAP-Elites (`mapelites`) | Quality-diversity over meaningful descriptors | Requires fixed descriptor bounds and enough evaluations for coverage | Pilot with hundreds of niches before increasing capacity |
|
|
181
|
+
| Diversifier (`diversifier`) | CMA-ME-style local improvement of an archive | More expensive and parameter-rich than basic MAP-Elites | Seed an archive first; use a small solver set |
|
|
182
|
+
|
|
183
|
+
These are starting hypotheses. The objective landscape dominates generic
|
|
184
|
+
rules.
|
|
185
|
+
|
|
186
|
+
## Scalar optimizer parameters
|
|
187
|
+
|
|
188
|
+
All scalar objectives are minimized. Return a finite `float`. The wrappers
|
|
189
|
+
generally replace exceptions and non-finite values with a very large finite
|
|
190
|
+
value, but explicit, scaled rejection values are easier to diagnose.
|
|
191
|
+
|
|
192
|
+
Use `numpy.random.Generator(PCG64DXSM(seed))` for controlled runs. Avoid the
|
|
193
|
+
module signatures' already-constructed default generators in reproducibility-
|
|
194
|
+
critical code; supply a fresh generator explicitly.
|
|
195
|
+
|
|
196
|
+
### Native Differential Evolution
|
|
197
|
+
|
|
198
|
+
`decpp.minimize` defaults:
|
|
199
|
+
|
|
200
|
+
| Parameter | Default | Guidance |
|
|
201
|
+
|---|---:|---|
|
|
202
|
+
| `popsize` | 31 | Increase for broad multimodal exploration only if many generations still fit. |
|
|
203
|
+
| `max_evaluations` | 100,000 | Set from the real budget. |
|
|
204
|
+
| `keep` | 200 | Usually leave unchanged; controls temporal/history behavior. |
|
|
205
|
+
| `stop_fitness` | negative infinity | Set only for a genuine known target. |
|
|
206
|
+
| `f` / `cr` | 0.5 / 0.9 | Tune after population and budget. |
|
|
207
|
+
| `min_mutate` / `max_mutate` | 0.1 / 0.5 | Additional mutation range for integer-marked coordinates. |
|
|
208
|
+
| `min_sigma` | 0 | Usually leave at zero. |
|
|
209
|
+
| `workers` | 1 | More workers call Python objectives concurrently from the native path; benchmark carefully. |
|
|
210
|
+
|
|
211
|
+
Pass a Boolean `ints` mask for integer coordinates, but still round, clamp,
|
|
212
|
+
lookup, and repair authoritatively in the objective. Integer mutation does not
|
|
213
|
+
turn unrelated categorical indices into a meaningful metric space.
|
|
214
|
+
|
|
215
|
+
Without `x0`, DE initializes from the bounds. With `x0`, provide a compatible
|
|
216
|
+
`input_sigma` if local initialization is intended. `DE_C` exposes
|
|
217
|
+
`ask()`, `tell(ys)`, `population()`, and `result()`.
|
|
218
|
+
|
|
219
|
+
### Native active CMA-ES
|
|
220
|
+
|
|
221
|
+
`cmaescpp.minimize` defaults to population 31, 100,000 evaluations,
|
|
222
|
+
`input_sigma=0.3`, normalized coordinates, delayed update enabled,
|
|
223
|
+
`accuracy=1`, no finite target, and automatic history/update settings.
|
|
224
|
+
|
|
225
|
+
With `normalize=True`, the search coordinates are scaled relative to the
|
|
226
|
+
bounds. Choose sigma in that normalized optimizer space. A sigma around
|
|
227
|
+
0.05–0.3 is a useful first range only when it matches the real uncertainty in
|
|
228
|
+
the guess. With normalization disabled, sigma is in physical units.
|
|
229
|
+
|
|
230
|
+
Use `workers > 1` only after measuring. With `delayed_update=False`, the wrapper
|
|
231
|
+
uses a multiprocessing batch evaluator; with delayed update enabled, native
|
|
232
|
+
parallel callback behavior applies. Do not combine a full process pool with a
|
|
233
|
+
simulator or BLAS library already using all cores.
|
|
234
|
+
|
|
235
|
+
### CR-FM-NES
|
|
236
|
+
|
|
237
|
+
`crfmnescpp.minimize` defaults to an even population of 32, 100,000
|
|
238
|
+
evaluations, `input_sigma=0.3`, no finite target, bound-violation handling
|
|
239
|
+
enabled, `penalty_coef=1e5`, and `normalize=False`.
|
|
240
|
+
|
|
241
|
+
The `use_constraint_violation` option concerns box-bound handling, not
|
|
242
|
+
arbitrary user constraints. General constraints still require a penalty,
|
|
243
|
+
repair, MODE, or another constrained formulation. Supply a guess and use a
|
|
244
|
+
batch objective for expensive populations. Compare against CMA-ES around
|
|
245
|
+
dimension 100 rather than treating a dimension threshold as absolute.
|
|
246
|
+
|
|
247
|
+
### PGPE
|
|
248
|
+
|
|
249
|
+
`pgpecpp.minimize` defaults:
|
|
250
|
+
|
|
251
|
+
| Parameter | Default |
|
|
252
|
+
|---|---:|
|
|
253
|
+
| `popsize` | 32, expected to be even |
|
|
254
|
+
| `input_sigma` | 0.1 |
|
|
255
|
+
| `max_evaluations` | 100,000 |
|
|
256
|
+
| `lr_decay_steps` | 1,000 |
|
|
257
|
+
| `use_ranking` | true |
|
|
258
|
+
| `center_learning_rate` | 0.15 |
|
|
259
|
+
| `stdev_learning_rate` | 0.1 |
|
|
260
|
+
| `stdev_max_change` | 0.2 |
|
|
261
|
+
| `b1` / `b2` / `eps` | 0.9 / 0.999 / 1e-8 |
|
|
262
|
+
| `decay_coef` | 1.0 |
|
|
263
|
+
| `normalize` | true |
|
|
264
|
+
|
|
265
|
+
Keep ranking enabled for a robust first experiment. Increase the even
|
|
266
|
+
population for noisy objectives or more parallel work. Change learning rates
|
|
267
|
+
one at a time and validate across multiple seeds. Note that the low-level
|
|
268
|
+
`PGPE_C` constructor defaults `use_ranking=False`; set it explicitly when
|
|
269
|
+
reproducing the one-shot wrapper's behavior.
|
|
270
|
+
|
|
271
|
+
### Dual Annealing
|
|
272
|
+
|
|
273
|
+
`dacpp.minimize` defaults to 100,000 evaluations and local search enabled.
|
|
274
|
+
Use finite bounds. Local finite-difference refinement is inappropriate for
|
|
275
|
+
very noisy or sharply discontinuous objectives; disable `use_local_search` in
|
|
276
|
+
that case.
|
|
277
|
+
|
|
278
|
+
### BiteOpt
|
|
279
|
+
|
|
280
|
+
`bitecpp.minimize` defaults to automatic population (`popsize=0`), 100,000
|
|
281
|
+
evaluations, `M=1`, automatic stall criterion, and no finite target.
|
|
282
|
+
|
|
283
|
+
Start with `M=1`. Test a small deeper value only when multimodality and budget
|
|
284
|
+
justify multiple internal populations. `Bite_C` provides batched ask/tell with
|
|
285
|
+
configurable `batch_size`; compare it against ordinary one-at-a-time BiteOpt
|
|
286
|
+
because delayed selector feedback can change convergence.
|
|
287
|
+
|
|
288
|
+
## Recommended scalar recipes
|
|
289
|
+
|
|
290
|
+
### Unknown bounded black box
|
|
291
|
+
|
|
292
|
+
Run two fair baselines:
|
|
293
|
+
|
|
294
|
+
1. `Bite_cpp` with automatic population and `M=1`.
|
|
295
|
+
2. A fixed-budget `Sequence([De_cpp(...), Cma_cpp(...)])`.
|
|
296
|
+
|
|
297
|
+
Set the DE and CMA evaluation allocations explicitly for a controlled
|
|
298
|
+
comparison. `optimizer.de_cma` randomly assigns between 10% and 50% of the
|
|
299
|
+
total budget to DE when explicit stage budgets are omitted, so it is
|
|
300
|
+
convenient for retry diversity but not a fixed-protocol benchmark.
|
|
301
|
+
|
|
302
|
+
### Known good continuous guess
|
|
303
|
+
|
|
304
|
+
Use normalized active CMA-ES first. Compare CR-FM-NES at larger dimensions and
|
|
305
|
+
PGPE when diagonal mirrored search matches the problem. Derive per-coordinate
|
|
306
|
+
uncertainty from the model rather than copying one sigma blindly.
|
|
307
|
+
|
|
308
|
+
### Expensive objective
|
|
309
|
+
|
|
310
|
+
Prefer one population with parallel or vectorized evaluation when every
|
|
311
|
+
generation is expensive and useful. Choose a population at least as large as
|
|
312
|
+
the worker count. If independent global restarts matter more, use outer retry
|
|
313
|
+
processes and keep inner workers at one.
|
|
314
|
+
|
|
315
|
+
If the simulator owns a process or thread pool, compare two explicit
|
|
316
|
+
topologies: many serial simulator evaluations under fcmaes versus fewer
|
|
317
|
+
fcmaes evaluations using the simulator's internal parallelism. Keep the total
|
|
318
|
+
core allowance equal.
|
|
319
|
+
|
|
320
|
+
### Noisy objective
|
|
321
|
+
|
|
322
|
+
Use PGPE ranking, larger populations, or repeated evaluations. Do not use a
|
|
323
|
+
tight `stop_fitness` based on one noisy observation. If each objective call
|
|
324
|
+
averages replications, report both optimizer calls and the true simulation
|
|
325
|
+
count.
|
|
326
|
+
|
|
327
|
+
Use the same fixed training seed set for every candidate. Re-evaluate
|
|
328
|
+
finalists, Pareto points, and archive elites on a disjoint holdout seed set.
|
|
329
|
+
For noisy QD, validate both quality and descriptor location because an elite
|
|
330
|
+
can move to another niche.
|
|
331
|
+
|
|
332
|
+
## Constraints and variable encoding
|
|
333
|
+
|
|
334
|
+
Use these conventions consistently:
|
|
335
|
+
|
|
336
|
+
- All objectives are minimized. Negate quantities that must be maximized.
|
|
337
|
+
- MODE and `moretry` rows are `[objective_0, ..., objective_m,
|
|
338
|
+
constraint_0, ..., constraint_k]`.
|
|
339
|
+
- A constraint is feasible when `constraint <= 0`.
|
|
340
|
+
- Convert `h(x) = 0` to `abs(h(x)) - tolerance <= 0` when a tolerance is
|
|
341
|
+
meaningful.
|
|
342
|
+
- For scalar optimizers, use decoding or repair for hard structure and a
|
|
343
|
+
scaled penalty for remaining violations. A useful starting form is
|
|
344
|
+
`objective + rho * sum(max(0, g_i(x))**2)` after normalizing terms.
|
|
345
|
+
- Return a large finite rejection value for invalid simulations.
|
|
346
|
+
- Encode a bounded integer as a real coordinate, round it, and clamp it in the
|
|
347
|
+
objective; optionally also set DE or MODE's integer mask.
|
|
348
|
+
- Encode a category as an index into a fixed list. Do not interpret distances
|
|
349
|
+
between unrelated categories physically.
|
|
350
|
+
- Decode random keys or repair permutations, schedules, subsets, and mutually
|
|
351
|
+
exclusive choices deterministically.
|
|
352
|
+
|
|
353
|
+
The `JobShop`, `Scheduling`, `Routing`, `Subset`, `UAV`, `FluidDynamics`, and
|
|
354
|
+
`MINLP` tutorials are repository-specific encoding references. Test every
|
|
355
|
+
decoder independently before optimization.
|
|
356
|
+
|
|
357
|
+
If a scalar penalty dominates everywhere, normalize the base objective and
|
|
358
|
+
constraint residuals before tuning `rho`. Too small lets infeasible points
|
|
359
|
+
win; too large creates a nearly flat rejection landscape.
|
|
360
|
+
|
|
361
|
+
## Multi-objective optimization
|
|
362
|
+
|
|
363
|
+
### MODE
|
|
364
|
+
|
|
365
|
+
Use `modecpp.minimize` for a coordinated Pareto population. The objective must
|
|
366
|
+
return exactly `nobj + ncon` finite values, with constraints trailing the
|
|
367
|
+
objectives. The defaults are population 64, `F=0.5`, `CR=0.9`, NSGA-II update,
|
|
368
|
+
`pro_c=0.5`, `dis_c=15`, `pro_m=0.9`, `dis_m=20`, and integer mutation range
|
|
369
|
+
0.1–0.5.
|
|
370
|
+
|
|
371
|
+
Guidance:
|
|
372
|
+
|
|
373
|
+
- Start with NSGA-II update.
|
|
374
|
+
- Use at least population 64; try 128–512 for difficult fronts, cheap
|
|
375
|
+
objectives, or more objectives while preserving many generations.
|
|
376
|
+
- Scale objective magnitudes before judging front quality.
|
|
377
|
+
- Use `workers > 1` for expensive objective populations, not for tiny Python
|
|
378
|
+
callbacks.
|
|
379
|
+
- Use `MODE_C.ask()` and `tell(ys)` when the application owns evaluation.
|
|
380
|
+
- Filter feasible rows before calculating or reporting a Pareto front.
|
|
381
|
+
- `modecpp.retry` runs independent MODE processes and can consume
|
|
382
|
+
approximately `num_retries * max_evaluations`; set both explicitly.
|
|
383
|
+
|
|
384
|
+
### Weighted multi-objective retry
|
|
385
|
+
|
|
386
|
+
`moretry.minimize` samples weights inside `weight_bounds`, scalarizes the
|
|
387
|
+
objective prefix, adds penalties for positive trailing constraints, runs a
|
|
388
|
+
scalar optimizer, and then re-evaluates retained points using the original
|
|
389
|
+
multi-objective function.
|
|
390
|
+
|
|
391
|
+
Use it when independent scalar runs are effective and easy to parallelize.
|
|
392
|
+
Set `ncon` exactly. Normalize or shift objective values to comparable,
|
|
393
|
+
preferably nonnegative scales before choosing weight bounds. With non-integer
|
|
394
|
+
`value_exp`, negative weighted values can be mathematically invalid. Report
|
|
395
|
+
the retained unscalarized objective vectors, not the scalar retry score.
|
|
396
|
+
|
|
397
|
+
## Quality diversity
|
|
398
|
+
|
|
399
|
+
Use MAP-Elites only when behavior descriptors express diversity the user
|
|
400
|
+
actually values. A descriptor is not another minimized objective.
|
|
401
|
+
|
|
402
|
+
The QD fitness contract is:
|
|
403
|
+
|
|
404
|
+
```python
|
|
405
|
+
fitness, descriptor = qd_fitness(x)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
The descriptor must match `qd_bounds`. A typical workflow is:
|
|
409
|
+
|
|
410
|
+
1. Define decision and descriptor bounds.
|
|
411
|
+
2. Create or let `optimize_map_elites` create an archive.
|
|
412
|
+
3. Seed the archive with evaluated candidates.
|
|
413
|
+
4. Run MAP-Elites variation and optional CMA emitters.
|
|
414
|
+
5. Optionally pass the archive to `diversifier.minimize`.
|
|
415
|
+
6. Report occupied niches, coverage, best fitness, descriptor ranges, and
|
|
416
|
+
representative elites.
|
|
417
|
+
|
|
418
|
+
`mapelites.optimize_map_elites` defaults to 4,000 niches, 20 CVT samples per
|
|
419
|
+
niche, all CPU processes, and 100 iterations. Those defaults can be expensive:
|
|
420
|
+
pilot with fewer niches and a measured evaluation budget. In two descriptor
|
|
421
|
+
dimensions, inspect whether grid indexing or CVT centers fit the intended
|
|
422
|
+
geometry. Capacity controls both resolution and memory.
|
|
423
|
+
|
|
424
|
+
`diversifier.minimize` accepts one solver configuration or a sequence through
|
|
425
|
+
`opt_params`. Supported maintained solver names include `CMA`, `CMA_CPP`,
|
|
426
|
+
`CRMFNES`, `CRMFNES_CPP`, `DE`, `DE_CPP`, `PGPE`, `BITE_CPP`, and `elites`.
|
|
427
|
+
Start with a small, explicit configuration rather than relying on a large
|
|
428
|
+
mixed default. Keep archive updates and stochastic validation reproducible.
|
|
429
|
+
|
|
430
|
+
## Retry selection and parameters
|
|
431
|
+
|
|
432
|
+
### Basic retry
|
|
433
|
+
|
|
434
|
+
`retry.minimize` defaults to 1,024 retries, one process per CPU, a retained
|
|
435
|
+
capacity of 500, 50,000 evaluations per run, no value filter, and no finite
|
|
436
|
+
stop target. Its default optimizer is a DE-to-CMA sequence.
|
|
437
|
+
|
|
438
|
+
Set these explicitly in production:
|
|
439
|
+
|
|
440
|
+
- `num_retries`: number of independent runs;
|
|
441
|
+
- `workers`: number of outer processes;
|
|
442
|
+
- the optimizer's per-run `max_evaluations`;
|
|
443
|
+
- `capacity`: number of retained distinct results;
|
|
444
|
+
- `value_limit`: strict upper filter for stored results;
|
|
445
|
+
- `stop_fitness`: target that stops new work;
|
|
446
|
+
- a reproducible random protocol; and
|
|
447
|
+
- `statistic_num` if improvement history is required.
|
|
448
|
+
|
|
449
|
+
Configured work is roughly `num_retries * evaluations_per_run`, reduced by
|
|
450
|
+
early termination. `popsize` and `max_evaluations` on `retry.minimize` are
|
|
451
|
+
ignored when a custom `optimizer` object supplies its own settings.
|
|
452
|
+
|
|
453
|
+
### Advanced retry
|
|
454
|
+
|
|
455
|
+
`advretry.minimize` coordinates restarts through a shared result store,
|
|
456
|
+
crossover boxes, and a budget that increases with retry progress. Defaults are
|
|
457
|
+
5,000 retries, 1,500 initial evaluations, check interval 100, retained
|
|
458
|
+
capacity 500, and an automatically capped final budget factor up to 50.
|
|
459
|
+
|
|
460
|
+
Use it only after a basic retry baseline. `value_limit` matters more here:
|
|
461
|
+
retaining many poor parents can make crossover regions unhelpful. Optimizer
|
|
462
|
+
adapters receive the store-derived local bounds, guess, standard deviations,
|
|
463
|
+
and evaluation budget through their normal `minimize` interface. A custom
|
|
464
|
+
adapter that ignores those values defeats advanced retry.
|
|
465
|
+
|
|
466
|
+
`datafile` can persist and reload advanced-retry state. Treat it as mutable
|
|
467
|
+
run state, not source data, and record the code version and problem definition
|
|
468
|
+
with it.
|
|
469
|
+
|
|
470
|
+
## Parallelism rules
|
|
471
|
+
|
|
472
|
+
There are three possible levels:
|
|
473
|
+
|
|
474
|
+
1. Outer process parallelism: `retry`, `advretry`, `moretry`,
|
|
475
|
+
`modecpp.retry`, MAP-Elites, and Diversifier.
|
|
476
|
+
2. Inner population evaluation: `workers` on supported scalar/MODE wrappers,
|
|
477
|
+
`evaluator.parallel`, `parallel_mo`, or application-owned ask/tell batches.
|
|
478
|
+
3. Parallelism inside NumPy, BLAS, a simulator, an external program, or a
|
|
479
|
+
machine-learning framework.
|
|
480
|
+
|
|
481
|
+
Do not enable every level at the full core count. For 16 cores, compare:
|
|
482
|
+
|
|
483
|
+
- 16 retry processes and one inner worker;
|
|
484
|
+
- one optimizer with a 16-worker expensive population;
|
|
485
|
+
- four retry processes with four inner workers only if both levels have
|
|
486
|
+
enough work; or
|
|
487
|
+
- one fcmaes worker when the simulator already owns 16 threads.
|
|
488
|
+
|
|
489
|
+
Process objectives and their captured data must be serializable under the
|
|
490
|
+
platform's multiprocessing start method. Put process-launching code behind
|
|
491
|
+
`if __name__ == "__main__":`, especially on Windows and macOS. Do not rely on
|
|
492
|
+
fork-only global state.
|
|
493
|
+
|
|
494
|
+
The evaluator uses persistent processes and must be stopped. Use `try/finally`
|
|
495
|
+
or a wrapper that stops it. fcmaes limits BLAS threads in several retry worker
|
|
496
|
+
paths, but the application is still responsible for avoiding nested pools in
|
|
497
|
+
other libraries.
|
|
498
|
+
|
|
499
|
+
Multi-process scheduling can change result arrival order. Treat stochastic
|
|
500
|
+
parallel retry as statistically reproducible unless the exact scheduling and
|
|
501
|
+
seed-to-run assignment are explicitly controlled. Ask/tell with ordered,
|
|
502
|
+
deterministic batch results is the strongest reproducibility path.
|
|
503
|
+
|
|
504
|
+
## Budget and parameter-setting procedure
|
|
505
|
+
|
|
506
|
+
Tune in this order:
|
|
507
|
+
|
|
508
|
+
1. Validate objective values, signs, constraints, decoding, and bounds.
|
|
509
|
+
2. Transform variables with extreme scale differences. Use log coordinates
|
|
510
|
+
for positive variables spanning orders of magnitude.
|
|
511
|
+
3. Choose the algorithm family from the requested result and problem
|
|
512
|
+
structure.
|
|
513
|
+
4. Set the total evaluation and worker budget.
|
|
514
|
+
5. Set population size so several generations fit and workers receive work.
|
|
515
|
+
6. Set initialization and sigma from real uncertainty.
|
|
516
|
+
7. Only then tune mutation, crossover, or learning rates.
|
|
517
|
+
|
|
518
|
+
Use a staged budget:
|
|
519
|
+
|
|
520
|
+
- Smoke test: a few populations to exercise decoding, invalid paths, and
|
|
521
|
+
reporting.
|
|
522
|
+
- Pilot: several seeds for two or three candidate algorithms.
|
|
523
|
+
- Production: use the measured wall-time/evaluation budget for the most robust
|
|
524
|
+
configuration and retain disjoint validation seeds.
|
|
525
|
+
|
|
526
|
+
Population algorithms may check limits at generation boundaries, so actual
|
|
527
|
+
evaluations can exceed the requested limit by part of a population. Compare
|
|
528
|
+
the returned `nfev`, not only configured limits.
|
|
529
|
+
|
|
530
|
+
## Minimal implementation patterns
|
|
531
|
+
|
|
532
|
+
### Bounded scalar native DE
|
|
533
|
+
|
|
534
|
+
```python
|
|
535
|
+
import numpy as np
|
|
536
|
+
from numpy.random import Generator, PCG64DXSM
|
|
537
|
+
from scipy.optimize import Bounds
|
|
538
|
+
from fcmaes import decpp
|
|
539
|
+
|
|
540
|
+
bounds = Bounds([-5.0] * 8, [5.0] * 8)
|
|
541
|
+
|
|
542
|
+
def objective(x):
|
|
543
|
+
return float(np.dot(x, x))
|
|
544
|
+
|
|
545
|
+
result = decpp.minimize(
|
|
546
|
+
objective,
|
|
547
|
+
bounds=bounds,
|
|
548
|
+
popsize=31,
|
|
549
|
+
max_evaluations=50_000,
|
|
550
|
+
rg=Generator(PCG64DXSM(1)),
|
|
551
|
+
)
|
|
552
|
+
assert result.success and np.isfinite(result.fun)
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Reproducible ask/tell population
|
|
556
|
+
|
|
557
|
+
```python
|
|
558
|
+
import numpy as np
|
|
559
|
+
from numpy.random import Generator, PCG64DXSM
|
|
560
|
+
from scipy.optimize import Bounds
|
|
561
|
+
from fcmaes.decpp import DE_C
|
|
562
|
+
|
|
563
|
+
bounds = Bounds([-5.0] * 4, [5.0] * 4)
|
|
564
|
+
solver = DE_C(
|
|
565
|
+
dim=4,
|
|
566
|
+
bounds=bounds,
|
|
567
|
+
popsize=32,
|
|
568
|
+
rg=Generator(PCG64DXSM(2)),
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
for _ in range(100):
|
|
572
|
+
xs = solver.ask()
|
|
573
|
+
ys = np.asarray([np.dot(x, x) for x in xs], dtype=np.float64)
|
|
574
|
+
if solver.tell(ys) != 0:
|
|
575
|
+
break
|
|
576
|
+
|
|
577
|
+
result = solver.result()
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Parallel retry
|
|
581
|
+
|
|
582
|
+
```python
|
|
583
|
+
import multiprocessing as mp
|
|
584
|
+
import numpy as np
|
|
585
|
+
from scipy.optimize import Bounds
|
|
586
|
+
from fcmaes import retry
|
|
587
|
+
from fcmaes.optimizer import Bite_cpp
|
|
588
|
+
|
|
589
|
+
def objective(x):
|
|
590
|
+
return float(np.dot(x, x))
|
|
591
|
+
|
|
592
|
+
if __name__ == "__main__":
|
|
593
|
+
result = retry.minimize(
|
|
594
|
+
objective,
|
|
595
|
+
Bounds([-5.0] * 6, [5.0] * 6),
|
|
596
|
+
optimizer=Bite_cpp(max_evaluations=20_000),
|
|
597
|
+
num_retries=32,
|
|
598
|
+
workers=min(8, mp.cpu_count()),
|
|
599
|
+
capacity=32,
|
|
600
|
+
)
|
|
601
|
+
print(result.fun, result.x, result.nfev)
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Constrained native MODE
|
|
605
|
+
|
|
606
|
+
```python
|
|
607
|
+
import numpy as np
|
|
608
|
+
from numpy.random import Generator, PCG64DXSM
|
|
609
|
+
from scipy.optimize import Bounds
|
|
610
|
+
from fcmaes import modecpp
|
|
611
|
+
|
|
612
|
+
def objectives_and_constraint(x):
|
|
613
|
+
return np.asarray([
|
|
614
|
+
np.dot(x, x),
|
|
615
|
+
np.dot(x - 1.0, x - 1.0),
|
|
616
|
+
x.sum() - 2.5, # feasible when <= 0
|
|
617
|
+
])
|
|
618
|
+
|
|
619
|
+
xs, ys = modecpp.minimize(
|
|
620
|
+
objectives_and_constraint,
|
|
621
|
+
nobj=2,
|
|
622
|
+
ncon=1,
|
|
623
|
+
bounds=Bounds([0.0] * 4, [1.0] * 4),
|
|
624
|
+
popsize=128,
|
|
625
|
+
max_evaluations=50_000,
|
|
626
|
+
workers=1,
|
|
627
|
+
rg=Generator(PCG64DXSM(3)),
|
|
628
|
+
)
|
|
629
|
+
feasible = ys[:, -1] <= 0
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
For optimizer sequences and advanced retry, copy the maintained adapters from
|
|
633
|
+
`fcmaes/optimizer.py` instead of recreating store and budget handling ad hoc.
|
|
634
|
+
|
|
635
|
+
## Validation and reporting checklist
|
|
636
|
+
|
|
637
|
+
Before declaring success:
|
|
638
|
+
|
|
639
|
+
- Unit-test decoding, objective signs, constraint signs, bounds, and known
|
|
640
|
+
reference points.
|
|
641
|
+
- Confirm every final point is decoded and re-evaluated independently.
|
|
642
|
+
- Run the deterministic wheel smoke suite with the selected interpreter:
|
|
643
|
+
`python -m pytest -q tests/test_wheel_smoke.py`.
|
|
644
|
+
- Run relevant module and example tests; the historical `fcmaes/test_cma.py`
|
|
645
|
+
suite is stochastic and comparatively expensive, so report retries or
|
|
646
|
+
failures honestly.
|
|
647
|
+
- Record algorithm, every non-default parameter, bounds, generator seed,
|
|
648
|
+
workers, configured budget, actual evaluations, and wall time.
|
|
649
|
+
- Compare algorithms using the same objective calls and core allowance.
|
|
650
|
+
- Use multiple seeds and report best, median or mean, dispersion, and
|
|
651
|
+
success/feasibility rate.
|
|
652
|
+
- For multi-objective runs, report feasible Pareto points and an appropriate
|
|
653
|
+
front-quality measure, not only one selected point.
|
|
654
|
+
- For QD runs, report capacity, occupied niches, coverage, best fitness,
|
|
655
|
+
descriptor ranges, and holdout niche migration for noisy problems.
|
|
656
|
+
- Test scaling with workers 1 and N before claiming parallel speedup.
|
|
657
|
+
- Preserve a small deterministic smoke configuration.
|
|
658
|
+
|
|
659
|
+
## Failure diagnosis
|
|
660
|
+
|
|
661
|
+
| Symptom | Likely cause | First action |
|
|
662
|
+
|---|---|---|
|
|
663
|
+
| No improvement from initialization | Wrong sign, invalid decoding, flat penalty, or bounds too broad | Print and test decoded points and every objective term. |
|
|
664
|
+
| All results are infeasible | Constraint sign error or badly scaled violation | Verify feasible means `<= 0` and test a known feasible point. |
|
|
665
|
+
| CMA-ES immediately hits bounds | Guess or sigma uses the wrong coordinate scale | Check `normalize` and rescale sigma. |
|
|
666
|
+
| DE explores but does not refine | Population is too large for the budget or local smooth convergence is needed | Reduce population or hand the best point to CMA-ES. |
|
|
667
|
+
| Parallel execution is slower | Objective is cheap, IPC dominates, or pools are nested | Use one worker level and benchmark a larger batch. |
|
|
668
|
+
| Multiprocessing hangs or recursively starts | Missing main guard or unpicklable objective state | Add `if __name__ == "__main__":` and isolate process-safe data. |
|
|
669
|
+
| Front covers one extreme | Poor objective scaling, population, or weight bounds | Normalize objectives and increase MODE population or scalarization diversity. |
|
|
670
|
+
| MAP-Elites coverage stays low | Wrong descriptor bounds, too many niches, or invalid descriptors | Inspect descriptor distributions and reduce pilot capacity. |
|
|
671
|
+
| Noisy runs stop inconsistently | Target or tolerance is tighter than the noise | Increase replication/population and validate on disjoint seeds. |
|
|
672
|
+
| Native wrapper returns `success=False` with a huge value | Input shape/type error or an exception hidden by the defensive wrapper | Reproduce with a tiny call, validate contiguous numeric arrays, and inspect the underlying exception path. |
|
|
673
|
+
|
|
674
|
+
## Repository references
|
|
675
|
+
|
|
676
|
+
- `README.adoc`: installation, algorithm overview, release behavior, and
|
|
677
|
+
documentation entry points.
|
|
678
|
+
- `fcmaes/optimizer.py`: retry adapters, sequences, choices, and maintained
|
|
679
|
+
scalar recipes.
|
|
680
|
+
- `fcmaes/retry.py`: independent parallel retry and result storage.
|
|
681
|
+
- `fcmaes/advretry.py`: coordinated retry, crossover, adaptive budgets, and
|
|
682
|
+
persisted state.
|
|
683
|
+
- `fcmaes/moretry.py`: weighted multi-objective retry and Pareto filtering.
|
|
684
|
+
- `fcmaes/modecpp.py`: native constrained MODE wrapper and ask/tell state.
|
|
685
|
+
- `fcmaes/mode.py`: Python MODE implementation, modifiers, feasibility, and
|
|
686
|
+
Pareto utilities.
|
|
687
|
+
- `fcmaes/mapelites.py`: CVT MAP-Elites archive and emitters.
|
|
688
|
+
- `fcmaes/diversifier.py`: archive improvement with scalar solvers.
|
|
689
|
+
- `fcmaes/evaluator.py`: persistent multiprocessing evaluators and callback
|
|
690
|
+
safety behavior.
|
|
691
|
+
- `fcmaes/_fcmaes_ext.pyi`: native extension signatures.
|
|
692
|
+
- `tests/test_wheel_smoke.py`: deterministic installed-wheel smoke coverage.
|
|
693
|
+
- `tutorials/README.adoc`: tutorial index and retry output explanation.
|
|
694
|
+
- `tutorials/Introduction.adoc`: practical optimizer selection and trajectory
|
|
695
|
+
examples.
|
|
696
|
+
- `tutorials/Performance.adoc`: performance comparisons.
|
|
697
|
+
- `tutorials/Constraints.adoc`, `tutorials/MODE.adoc`, and
|
|
698
|
+
`tutorials/MultiObjective.adoc`: constraint and Pareto formulations.
|
|
699
|
+
- `tutorials/MapElites.adoc` and `tutorials/Diversity.adoc`: quality-diversity
|
|
700
|
+
workflows.
|
|
701
|
+
- `tutorials/FluidDynamics.adoc`, `tutorials/MINLP.adoc`,
|
|
702
|
+
`tutorials/JobShop.adoc`, `tutorials/Scheduling.adoc`,
|
|
703
|
+
`tutorials/Routing.adoc`, `tutorials/Subset.adoc`, and
|
|
704
|
+
`tutorials/UAV.adoc`: mixed and structured encodings.
|
|
705
|
+
- Generated API documentation:
|
|
706
|
+
`https://dietmarwo.github.io/fast-cma-es/fcmaes_documentation.html`.
|
|
707
|
+
- Local documentation build: `python scripts/build_docs.py`.
|
|
708
|
+
|
|
709
|
+
When this guide and the implementation disagree, treat the current public
|
|
710
|
+
Python API, native type stub, and tests as authoritative. Update this file with
|
|
711
|
+
the implementation and record why the behavior changed.
|
|
@@ -7,7 +7,7 @@ build-backend = "scikit_build_core.build"
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "fcmaes"
|
|
10
|
-
version = "2.0.
|
|
10
|
+
version = "2.0.3"
|
|
11
11
|
description = "A Python 3 gradient-free optimization library."
|
|
12
12
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
13
13
|
requires-python = ">=3.10"
|
|
@@ -51,6 +51,8 @@ jit = [
|
|
|
51
51
|
[project.urls]
|
|
52
52
|
Homepage = "https://github.com/dietmarwo/fast-cma-es"
|
|
53
53
|
Repository = "https://github.com/dietmarwo/fast-cma-es"
|
|
54
|
+
Documentation = "https://dietmarwo.github.io/fast-cma-es/"
|
|
55
|
+
Tutorials = "https://dietmarwo.github.io/fast-cma-es/tutorials/"
|
|
54
56
|
|
|
55
57
|
[tool.scikit-build]
|
|
56
58
|
minimum-version = "build-system.requires"
|
fcmaes-2.0.2/README.md
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|