defoundry 0.1.0__py3-none-any.whl
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.
- defoundry-0.1.0.dist-info/METADATA +357 -0
- defoundry-0.1.0.dist-info/RECORD +24 -0
- defoundry-0.1.0.dist-info/WHEEL +5 -0
- defoundry-0.1.0.dist-info/licenses/LICENSE +21 -0
- defoundry-0.1.0.dist-info/top_level.txt +1 -0
- differential_evolution/__init__.py +134 -0
- differential_evolution/_numeric.py +73 -0
- differential_evolution/benchmarks.py +208 -0
- differential_evolution/boundaries.py +133 -0
- differential_evolution/compat.py +193 -0
- differential_evolution/crossover_rates.py +100 -0
- differential_evolution/crossovers.py +194 -0
- differential_evolution/diversity.py +347 -0
- differential_evolution/history.py +55 -0
- differential_evolution/initializers.py +678 -0
- differential_evolution/jde.py +61 -0
- differential_evolution/mutation.py +653 -0
- differential_evolution/optimizer.py +501 -0
- differential_evolution/population_schedules.py +104 -0
- differential_evolution/protocols.py +37 -0
- differential_evolution/py.typed +0 -0
- differential_evolution/result.py +48 -0
- differential_evolution/scales.py +143 -0
- differential_evolution/shade.py +350 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: defoundry
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Composable Differential Evolution optimizer
|
|
5
|
+
Author: Honza
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/vrbaj/differential_evolution
|
|
8
|
+
Project-URL: Issues, https://github.com/vrbaj/differential_evolution/issues
|
|
9
|
+
Keywords: optimization,differential-evolution,global-optimization
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Provides-Extra: test
|
|
23
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
24
|
+
Requires-Dist: mypy>=1.10; extra == "test"
|
|
25
|
+
Requires-Dist: ruff>=0.6; extra == "test"
|
|
26
|
+
Provides-Extra: release
|
|
27
|
+
Requires-Dist: build>=1.2; extra == "release"
|
|
28
|
+
Requires-Dist: twine>=6; extra == "release"
|
|
29
|
+
Provides-Extra: docs
|
|
30
|
+
Requires-Dist: Sphinx<9,>=8; extra == "docs"
|
|
31
|
+
Requires-Dist: sphinxcontrib-bibtex<3,>=2.6; extra == "docs"
|
|
32
|
+
Requires-Dist: sphinx-rtd-theme<4,>=3; extra == "docs"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# DEFoundry — Differential Evolution
|
|
36
|
+
|
|
37
|
+
This repository now provides a small, explicit Differential Evolution package with independently composable mutation strategies and crossover operators.
|
|
38
|
+
|
|
39
|
+
## What changed
|
|
40
|
+
|
|
41
|
+
- The optimizer is now a real Python package: `differential_evolution/`
|
|
42
|
+
- Mutation and crossover are separate components
|
|
43
|
+
- Randomness is explicit and reproducible
|
|
44
|
+
- A deterministic test suite verifies formulas and DE invariants
|
|
45
|
+
- The original `main.py`, `population_initialization.py`, and `testing_functions.py` remain as compatibility shims
|
|
46
|
+
- Full `SHADE` and `LSHADE` optimizers are available for success-history adaptive DE
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
DEFoundry requires Python 3.11 or later and has no mandatory runtime dependencies.
|
|
51
|
+
The distribution name is `defoundry`; the Python import is `differential_evolution`.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python3 -m pip install defoundry
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For development, install from a source checkout with `python3 -m pip install -e .`.
|
|
58
|
+
Maintainers can follow the [release guide](https://github.com/vrbaj/differential_evolution/blob/master/RELEASE.md)
|
|
59
|
+
to validate and publish distributions.
|
|
60
|
+
|
|
61
|
+
## Core concepts
|
|
62
|
+
|
|
63
|
+
- target vector: the current population member being evolved
|
|
64
|
+
- donor vector: the output of a mutation strategy
|
|
65
|
+
- trial vector: the result of applying a crossover operator to the target and donor
|
|
66
|
+
|
|
67
|
+
The optimizer orchestrates:
|
|
68
|
+
|
|
69
|
+
1. population initialization
|
|
70
|
+
2. donor-vector mutation
|
|
71
|
+
3. target/donor crossover
|
|
72
|
+
4. boundary handling
|
|
73
|
+
5. objective evaluation
|
|
74
|
+
6. greedy one-to-one selection
|
|
75
|
+
|
|
76
|
+
## Built-in mutation strategies
|
|
77
|
+
|
|
78
|
+
- `Rand1`
|
|
79
|
+
- `Rand2`
|
|
80
|
+
- `Best1`
|
|
81
|
+
- `Best2`
|
|
82
|
+
- `CurrentToBest1`
|
|
83
|
+
- `CurrentToBest2`
|
|
84
|
+
- `CurrentToRand1`
|
|
85
|
+
- `CurrentToRand2`
|
|
86
|
+
- `TrigonometricMutation`
|
|
87
|
+
- `DirectedMutation`
|
|
88
|
+
- `NeighborhoodSearchMutation`
|
|
89
|
+
|
|
90
|
+
## Built-in scale-factor controllers
|
|
91
|
+
|
|
92
|
+
- `ConstantScaleFactor`
|
|
93
|
+
- `RandomizedScaleFactor`
|
|
94
|
+
- `AdaptiveScaleFactor`
|
|
95
|
+
|
|
96
|
+
## Built-in crossover-rate controllers
|
|
97
|
+
|
|
98
|
+
- `ConstantCrossoverRate`
|
|
99
|
+
- `AdaptiveCrossoverRate`
|
|
100
|
+
|
|
101
|
+
These can be passed anywhere a mutation strategy expects `scale` or `difference_scale`.
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from differential_evolution import AdaptiveScaleFactor, Rand1
|
|
105
|
+
|
|
106
|
+
mutation = Rand1(scale=AdaptiveScaleFactor(initial=0.5, tau=0.1, lower=0.1, upper=0.9))
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
For the Brest et al. paper's full `jDE` control-parameter scheme, pair `AdaptiveScaleFactor` with `AdaptiveCrossoverRate`, or use the convenience helper:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from differential_evolution import DifferentialEvolution, jde_rand_1_bin, sphere_function
|
|
113
|
+
|
|
114
|
+
components = jde_rand_1_bin()
|
|
115
|
+
optimizer = DifferentialEvolution(
|
|
116
|
+
objective=sphere_function,
|
|
117
|
+
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
|
|
118
|
+
population_size=20,
|
|
119
|
+
mutation=components.mutation,
|
|
120
|
+
crossover=components.crossover,
|
|
121
|
+
max_generations=100,
|
|
122
|
+
seed=123,
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Built-in crossover operators
|
|
127
|
+
|
|
128
|
+
- `BinomialCrossover`
|
|
129
|
+
- `ExponentialCrossover`
|
|
130
|
+
- `IdentityCrossover`
|
|
131
|
+
|
|
132
|
+
`IdentityCrossover` is useful for canonical current-to-rand style runs where no extra crossover is desired.
|
|
133
|
+
|
|
134
|
+
## Built-in diversity measures
|
|
135
|
+
|
|
136
|
+
- `PopulationDiameter`
|
|
137
|
+
- `PopulationRadius`
|
|
138
|
+
- `AverageDistanceAroundPopulationCenter`
|
|
139
|
+
- `AverageDistanceAroundAllIndividuals`
|
|
140
|
+
- `PopulationCoherence`
|
|
141
|
+
- `DimensionalVariance`
|
|
142
|
+
- `AggregatedDistribution`
|
|
143
|
+
- `AveragePairwiseDistance`
|
|
144
|
+
|
|
145
|
+
You can disable diversity tracking by leaving `diversity_measures=None`, or track several measures at once:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from differential_evolution import (
|
|
149
|
+
AveragePairwiseDistance,
|
|
150
|
+
DifferentialEvolution,
|
|
151
|
+
PopulationDiameter,
|
|
152
|
+
Rand1,
|
|
153
|
+
BinomialCrossover,
|
|
154
|
+
sphere_function,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
optimizer = DifferentialEvolution(
|
|
158
|
+
objective=sphere_function,
|
|
159
|
+
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
|
|
160
|
+
population_size=20,
|
|
161
|
+
mutation=Rand1(scale=0.8),
|
|
162
|
+
crossover=BinomialCrossover(crossover_rate=0.9),
|
|
163
|
+
diversity_measures=[
|
|
164
|
+
PopulationDiameter(),
|
|
165
|
+
AveragePairwiseDistance(),
|
|
166
|
+
"population_coherence",
|
|
167
|
+
],
|
|
168
|
+
max_generations=50,
|
|
169
|
+
seed=123,
|
|
170
|
+
)
|
|
171
|
+
result = optimizer.run()
|
|
172
|
+
print(result.diversity_history["population_diameter"])
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`PopulationCoherence` compares the movement of the population center between consecutive generations with the average movement of individuals. Its first recorded value is `0.0` because there is no previous generation yet.
|
|
176
|
+
|
|
177
|
+
`AggregatedDistribution` is implemented here as a project-specific marginal dispersion statistic: each coordinate is normalized to `[0, 1]`, binned, and summarized by the variance-to-mean ratio of occupancy counts.
|
|
178
|
+
|
|
179
|
+
## Built-in initializers
|
|
180
|
+
|
|
181
|
+
- `RandomInitializer`
|
|
182
|
+
- `TentInitializer`
|
|
183
|
+
- `OppositionInitializer`
|
|
184
|
+
- `QuasiOppositionInitializer`
|
|
185
|
+
- `SobolInitializer`
|
|
186
|
+
|
|
187
|
+
`SobolInitializer` supports up to 40 dimensions and `2**30` sequence points.
|
|
188
|
+
It applies a seed-dependent digital shift by default; pass `scramble=False`
|
|
189
|
+
for the unshifted sequence. See the current
|
|
190
|
+
[algorithm reference](https://github.com/vrbaj/differential_evolution/blob/master/docs/algorithm_reference.rst#initialization).
|
|
191
|
+
|
|
192
|
+
## Population reduction
|
|
193
|
+
|
|
194
|
+
The optimizer can optionally reduce population size during the run:
|
|
195
|
+
|
|
196
|
+
- `LinearPopulationReduction`
|
|
197
|
+
- `HyperbolicTangentPopulationReduction`
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
from differential_evolution import (
|
|
201
|
+
BinomialCrossover,
|
|
202
|
+
DifferentialEvolution,
|
|
203
|
+
LinearPopulationReduction,
|
|
204
|
+
Rand1,
|
|
205
|
+
sphere_function,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
optimizer = DifferentialEvolution(
|
|
209
|
+
objective=sphere_function,
|
|
210
|
+
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
|
|
211
|
+
population_size=20,
|
|
212
|
+
mutation=Rand1(scale=0.8),
|
|
213
|
+
crossover=BinomialCrossover(crossover_rate=0.9),
|
|
214
|
+
population_schedule=LinearPopulationReduction(min_population_size=4),
|
|
215
|
+
max_evaluations=2000,
|
|
216
|
+
seed=123,
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`LinearPopulationReduction` follows the L-SHADE idea of shrinking linearly with used function-evaluation budget when `max_evaluations` is provided. If `max_evaluations` is omitted, it falls back to generation progress. `HyperbolicTangentPopulationReduction` is a project-specific smooth nonlinear schedule.
|
|
221
|
+
|
|
222
|
+
Supply at least one stopping limit. `max_generations` defaults to `None`, so an evaluation budget alone runs until that budget is exhausted. If both limits are supplied, the first one reached stops the run.
|
|
223
|
+
|
|
224
|
+
When the population is reduced, the worst individuals by current fitness are removed. Users must choose a minimum population size that remains compatible with the mutation strategy in use.
|
|
225
|
+
|
|
226
|
+
## SHADE and L-SHADE
|
|
227
|
+
|
|
228
|
+
The package also includes dedicated optimizers for the full success-history adaptive algorithms:
|
|
229
|
+
|
|
230
|
+
- `SHADE`
|
|
231
|
+
- `LSHADE`
|
|
232
|
+
|
|
233
|
+
`SHADE` includes:
|
|
234
|
+
|
|
235
|
+
- `current-to-pbest/1`
|
|
236
|
+
- external archive
|
|
237
|
+
- Cauchy sampling of `F`
|
|
238
|
+
- Gaussian sampling of `CR`
|
|
239
|
+
- success-history memories `M_F` and `M_CR`
|
|
240
|
+
|
|
241
|
+
`LSHADE` extends `SHADE` with linear population size reduction.
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
from differential_evolution import LSHADE, sphere_function
|
|
245
|
+
|
|
246
|
+
optimizer = LSHADE(
|
|
247
|
+
objective=sphere_function,
|
|
248
|
+
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
|
|
249
|
+
population_size=18,
|
|
250
|
+
min_population_size=4,
|
|
251
|
+
memory_size=6,
|
|
252
|
+
max_evaluations=2000,
|
|
253
|
+
seed=123,
|
|
254
|
+
)
|
|
255
|
+
result = optimizer.run()
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Saving runs
|
|
259
|
+
|
|
260
|
+
For post-run investigation, enable `record_snapshots=True` and save the result:
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
result = optimizer.run()
|
|
264
|
+
result.save_json("shade_run.json")
|
|
265
|
+
result.save_pickle("shade_run.pkl")
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Each snapshot stores the generation number, evaluation count, best solution, population size, optional population and fitness arrays, diversity values, and algorithm-specific extra state. For `SHADE` and `LSHADE`, the extra state includes the external archive and the parameter memories.
|
|
269
|
+
|
|
270
|
+
## Example
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
from differential_evolution import (
|
|
274
|
+
BinomialCrossover,
|
|
275
|
+
DifferentialEvolution,
|
|
276
|
+
ExponentialCrossover,
|
|
277
|
+
Rand1,
|
|
278
|
+
Best1,
|
|
279
|
+
sphere_function,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
optimizer = DifferentialEvolution(
|
|
283
|
+
objective=sphere_function,
|
|
284
|
+
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
|
|
285
|
+
population_size=20,
|
|
286
|
+
mutation=Rand1(scale=0.8),
|
|
287
|
+
crossover=BinomialCrossover(crossover_rate=0.9),
|
|
288
|
+
max_generations=50,
|
|
289
|
+
seed=123,
|
|
290
|
+
)
|
|
291
|
+
result = optimizer.run()
|
|
292
|
+
|
|
293
|
+
optimizer_alt = DifferentialEvolution(
|
|
294
|
+
objective=sphere_function,
|
|
295
|
+
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
|
|
296
|
+
population_size=20,
|
|
297
|
+
mutation=Best1(scale=0.5),
|
|
298
|
+
crossover=ExponentialCrossover(crossover_rate=0.8),
|
|
299
|
+
max_generations=50,
|
|
300
|
+
seed=123,
|
|
301
|
+
)
|
|
302
|
+
result_alt = optimizer_alt.run()
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Custom components
|
|
306
|
+
|
|
307
|
+
Any callable with the right signature can be injected.
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
class MyMutation:
|
|
311
|
+
def __call__(self, context):
|
|
312
|
+
target = context.population[context.target_index]
|
|
313
|
+
return [value * 0.5 for value in target]
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
class MyCrossover:
|
|
317
|
+
def __call__(self, target_vector, donor_vector, rng):
|
|
318
|
+
trial = list(target_vector)
|
|
319
|
+
trial[0] = donor_vector[0]
|
|
320
|
+
return trial
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Reproducibility
|
|
324
|
+
|
|
325
|
+
Use `seed=` or pass a custom RNG object. The optimizer does not use module-level global random state.
|
|
326
|
+
|
|
327
|
+
## Compatibility
|
|
328
|
+
|
|
329
|
+
The original constructor remains available from a source checkout only:
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
from main import DifferentialEvolution
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Installed users can use `from differential_evolution.compat import DifferentialEvolution`.
|
|
336
|
+
Both paths emit a deprecation warning and forward into the new implementation.
|
|
337
|
+
Details are in [MIGRATION.md](https://github.com/vrbaj/differential_evolution/blob/master/MIGRATION.md).
|
|
338
|
+
|
|
339
|
+
## Verification
|
|
340
|
+
|
|
341
|
+
- algorithm audit: [ALGORITHM_AUDIT.md](https://github.com/vrbaj/differential_evolution/blob/master/ALGORITHM_AUDIT.md)
|
|
342
|
+
- migration notes: [MIGRATION.md](https://github.com/vrbaj/differential_evolution/blob/master/MIGRATION.md)
|
|
343
|
+
- tests: `python3 -m unittest discover -s tests -v`
|
|
344
|
+
- examples: `python3 -m examples.basic_usage`, `python3 -m examples.custom_components`, `python3 -m examples.diversity_measures`, and `python3 -m examples.population_initialization`
|
|
345
|
+
|
|
346
|
+
### Review corrections and compatibility
|
|
347
|
+
|
|
348
|
+
See [review fixes](https://github.com/vrbaj/differential_evolution/blob/master/docs/review_fixes.md) for changes and the disposition of the
|
|
349
|
+
reported findings. Plain DE now clips to bounds by default; SHADE/L-SHADE use
|
|
350
|
+
parent-aware midpoint repair. Mutation and crossover components are copied per
|
|
351
|
+
optimizer; inspect adapted state on `optimizer.mutation` and `optimizer.crossover`.
|
|
352
|
+
`run()` is single-use. `result.success` means a usable objective value was found,
|
|
353
|
+
not numerical convergence; `result.message` reports the exhausted limit.
|
|
354
|
+
|
|
355
|
+
Sobol initialization uses a seeded digital shift by default. Use
|
|
356
|
+
`SobolInitializer(scramble=False)` for the original unshifted sequence. All
|
|
357
|
+
fixed-dimensional benchmarks, including Ackley, require exactly two coordinates.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
defoundry-0.1.0.dist-info/licenses/LICENSE,sha256=J51U_0iHTQ2nz798bkyc7rPSYITcGVsMNf2KlhZTBfA,1062
|
|
2
|
+
differential_evolution/__init__.py,sha256=E0DHLP7guIXv8ZmJtzimn9Og9eYvf2-ZJY_tFaMyhLA,3433
|
|
3
|
+
differential_evolution/_numeric.py,sha256=2AgpmOjZGXVKTAwkxkfQodL-c5vD4Iyg64Os93ccVWo,2595
|
|
4
|
+
differential_evolution/benchmarks.py,sha256=GfkBaliJjQmE8HVe-gVJbaWVpLKePIrZ5vNbbxjVfLA,7378
|
|
5
|
+
differential_evolution/boundaries.py,sha256=CnDToPfD9v2gz8IUS7D_zTMlo2126muR5gdcb1ZB_BQ,3951
|
|
6
|
+
differential_evolution/compat.py,sha256=Tvh1uY-VUIz2xZvDecvMpsrhZTocdpXD-S1xBzq24FA,6740
|
|
7
|
+
differential_evolution/crossover_rates.py,sha256=n2IqdiFZOns_DUdCc7VMqoqt8vsTSSNySJG7aDmEIn0,3644
|
|
8
|
+
differential_evolution/crossovers.py,sha256=MLJLVTP3VnDYsEi7bWOAOJE5kzmu69lfdfzuKZS_QGM,6391
|
|
9
|
+
differential_evolution/diversity.py,sha256=4zCpk_TVhzjlh7sqf7NCMwcebHUG0lLMxB-6mk3Gy_8,12769
|
|
10
|
+
differential_evolution/history.py,sha256=t6RI3qnn8hSFng0XFZrOqCUalhkCR4V9ZErNo14m-5U,1508
|
|
11
|
+
differential_evolution/initializers.py,sha256=Ni4mZ-NeU3tu4gjtu75iIu41R0UMTt62fd8u6RMo0VI,12846
|
|
12
|
+
differential_evolution/jde.py,sha256=S7Z6jqTxJDXgCfohyAbSbFv-nOMqWy-7A7ytKiq9QoM,1562
|
|
13
|
+
differential_evolution/mutation.py,sha256=JlM0kfCpx6SreEslV-M6s95gdWH5Lk9YHnGC1c4BhHM,22987
|
|
14
|
+
differential_evolution/optimizer.py,sha256=wLjY2xEIHrChteRrC3XFNHFbxX4Jp2VELQ4pK7REq4s,21588
|
|
15
|
+
differential_evolution/population_schedules.py,sha256=dHYxj8hzLwexe1Ehu7LxEqP5y0xRwrJRVi3MXg40swM,3817
|
|
16
|
+
differential_evolution/protocols.py,sha256=Z1ry7-PccxM7C2DqmpY4LR2bis5SgkaVdqGxNVK9vB0,1331
|
|
17
|
+
differential_evolution/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
differential_evolution/result.py,sha256=XtJrCtJMiHaqUxzyUIEE78KvhF3W_E9YtMBz0dyj5Cg,1337
|
|
19
|
+
differential_evolution/scales.py,sha256=11rUGaA45aJD8ahPzIesxghFG3Hu2-r9WyMPKkjQomQ,4898
|
|
20
|
+
differential_evolution/shade.py,sha256=QPCwpGxlCbbSwaXX3z66SrDhvXLjwB75Ck3WH9OcH9Y,14206
|
|
21
|
+
defoundry-0.1.0.dist-info/METADATA,sha256=bF00U2Ds0dnDWdFlOu7qSu_n7SIfWesVp5YB2d8nHOg,11771
|
|
22
|
+
defoundry-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
23
|
+
defoundry-0.1.0.dist-info/top_level.txt,sha256=_dSOtYkjdxsSYRfQxQONLBWvAIpRSGToBjmCJYO3f7k,23
|
|
24
|
+
defoundry-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Honza
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
differential_evolution
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Composable Differential Evolution optimizer."""
|
|
2
|
+
|
|
3
|
+
from .benchmarks import (
|
|
4
|
+
ackley_function,
|
|
5
|
+
beale_function,
|
|
6
|
+
booth_function,
|
|
7
|
+
bukin_function,
|
|
8
|
+
easom_function,
|
|
9
|
+
eggholder_function,
|
|
10
|
+
goldstein_price_function,
|
|
11
|
+
himmelblau_function,
|
|
12
|
+
levi_function,
|
|
13
|
+
mccormick_function,
|
|
14
|
+
matyas_function,
|
|
15
|
+
rastrigin_function,
|
|
16
|
+
schaffer_n2_function,
|
|
17
|
+
sphere_function,
|
|
18
|
+
three_hump_camel_function,
|
|
19
|
+
)
|
|
20
|
+
from .boundaries import (
|
|
21
|
+
ClipBoundaryHandler,
|
|
22
|
+
NoBoundaryHandler,
|
|
23
|
+
RandomResetBoundaryHandler,
|
|
24
|
+
MidpointBoundaryHandler,
|
|
25
|
+
ReflectionBoundaryHandler,
|
|
26
|
+
)
|
|
27
|
+
from .crossovers import BinomialCrossover, ExponentialCrossover, IdentityCrossover
|
|
28
|
+
from .crossover_rates import AdaptiveCrossoverRate, ConstantCrossoverRate
|
|
29
|
+
from .initializers import (
|
|
30
|
+
OppositionInitializer,
|
|
31
|
+
QuasiOppositionInitializer,
|
|
32
|
+
RandomInitializer,
|
|
33
|
+
SobolInitializer,
|
|
34
|
+
TentInitializer,
|
|
35
|
+
)
|
|
36
|
+
from .diversity import (
|
|
37
|
+
AggregatedDistribution,
|
|
38
|
+
AverageDistanceAroundAllIndividuals,
|
|
39
|
+
AverageDistanceAroundPopulationCenter,
|
|
40
|
+
AveragePairwiseDistance,
|
|
41
|
+
DimensionalVariance,
|
|
42
|
+
PopulationCoherence,
|
|
43
|
+
PopulationDiameter,
|
|
44
|
+
PopulationRadius,
|
|
45
|
+
)
|
|
46
|
+
from .jde import JDEComponents, jde_rand_1_bin
|
|
47
|
+
from .mutation import (
|
|
48
|
+
Best1,
|
|
49
|
+
Best2,
|
|
50
|
+
CurrentToBest1,
|
|
51
|
+
CurrentToBest2,
|
|
52
|
+
CurrentToRand1,
|
|
53
|
+
CurrentToRand2,
|
|
54
|
+
DirectedMutation,
|
|
55
|
+
MutationContext,
|
|
56
|
+
NeighborhoodSearchMutation,
|
|
57
|
+
Rand1,
|
|
58
|
+
Rand2,
|
|
59
|
+
TrigonometricMutation,
|
|
60
|
+
sample_distinct_indices,
|
|
61
|
+
)
|
|
62
|
+
from .optimizer import DifferentialEvolution
|
|
63
|
+
from .population_schedules import (
|
|
64
|
+
HyperbolicTangentPopulationReduction,
|
|
65
|
+
LinearPopulationReduction,
|
|
66
|
+
)
|
|
67
|
+
from .result import OptimizeResult
|
|
68
|
+
from .scales import AdaptiveScaleFactor, ConstantScaleFactor, RandomizedScaleFactor
|
|
69
|
+
from .shade import LSHADE, SHADE
|
|
70
|
+
|
|
71
|
+
__all__ = [
|
|
72
|
+
"LSHADE",
|
|
73
|
+
"SHADE",
|
|
74
|
+
"AdaptiveCrossoverRate",
|
|
75
|
+
"AdaptiveScaleFactor",
|
|
76
|
+
"AggregatedDistribution",
|
|
77
|
+
"AverageDistanceAroundAllIndividuals",
|
|
78
|
+
"AverageDistanceAroundPopulationCenter",
|
|
79
|
+
"AveragePairwiseDistance",
|
|
80
|
+
"Best1",
|
|
81
|
+
"Best2",
|
|
82
|
+
"BinomialCrossover",
|
|
83
|
+
"ClipBoundaryHandler",
|
|
84
|
+
"ConstantCrossoverRate",
|
|
85
|
+
"ConstantScaleFactor",
|
|
86
|
+
"CurrentToBest1",
|
|
87
|
+
"CurrentToBest2",
|
|
88
|
+
"CurrentToRand1",
|
|
89
|
+
"CurrentToRand2",
|
|
90
|
+
"DifferentialEvolution",
|
|
91
|
+
"DimensionalVariance",
|
|
92
|
+
"DirectedMutation",
|
|
93
|
+
"ExponentialCrossover",
|
|
94
|
+
"HyperbolicTangentPopulationReduction",
|
|
95
|
+
"IdentityCrossover",
|
|
96
|
+
"JDEComponents",
|
|
97
|
+
"LinearPopulationReduction",
|
|
98
|
+
"MidpointBoundaryHandler",
|
|
99
|
+
"MutationContext",
|
|
100
|
+
"NeighborhoodSearchMutation",
|
|
101
|
+
"NoBoundaryHandler",
|
|
102
|
+
"OppositionInitializer",
|
|
103
|
+
"OptimizeResult",
|
|
104
|
+
"PopulationCoherence",
|
|
105
|
+
"PopulationDiameter",
|
|
106
|
+
"PopulationRadius",
|
|
107
|
+
"QuasiOppositionInitializer",
|
|
108
|
+
"Rand1",
|
|
109
|
+
"Rand2",
|
|
110
|
+
"RandomInitializer",
|
|
111
|
+
"RandomResetBoundaryHandler",
|
|
112
|
+
"RandomizedScaleFactor",
|
|
113
|
+
"ReflectionBoundaryHandler",
|
|
114
|
+
"SobolInitializer",
|
|
115
|
+
"TentInitializer",
|
|
116
|
+
"TrigonometricMutation",
|
|
117
|
+
"ackley_function",
|
|
118
|
+
"beale_function",
|
|
119
|
+
"booth_function",
|
|
120
|
+
"bukin_function",
|
|
121
|
+
"easom_function",
|
|
122
|
+
"eggholder_function",
|
|
123
|
+
"goldstein_price_function",
|
|
124
|
+
"himmelblau_function",
|
|
125
|
+
"jde_rand_1_bin",
|
|
126
|
+
"levi_function",
|
|
127
|
+
"matyas_function",
|
|
128
|
+
"mccormick_function",
|
|
129
|
+
"rastrigin_function",
|
|
130
|
+
"sample_distinct_indices",
|
|
131
|
+
"schaffer_n2_function",
|
|
132
|
+
"sphere_function",
|
|
133
|
+
"three_hump_camel_function",
|
|
134
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Overflow-safe coordinate arithmetic for finite search bounds."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
from collections.abc import Sequence
|
|
5
|
+
from fractions import Fraction
|
|
6
|
+
|
|
7
|
+
from .protocols import RandomSource
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def require_integer(value: object, name: str) -> None:
|
|
11
|
+
"""Reject fractional counts and booleans before they reach loops or budgets."""
|
|
12
|
+
if isinstance(value, bool) or not isinstance(value, int):
|
|
13
|
+
raise TypeError(f"{name} must be an integer.")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def mean(values: Sequence[float], *, total: float | None = None) -> float:
|
|
17
|
+
"""Preserve ordinary arithmetic, avoiding overflow of a finite-value sum."""
|
|
18
|
+
if total is None:
|
|
19
|
+
total = sum(values)
|
|
20
|
+
if math.isfinite(total) or not all(math.isfinite(value) for value in values):
|
|
21
|
+
return total / len(values)
|
|
22
|
+
return float(sum(Fraction(value) for value in values) / len(values))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def sum_differences(base: float, *terms: tuple[float, float, float]) -> float:
|
|
26
|
+
"""Compute base + sum(scale * (left - right)), with an overflow fallback.
|
|
27
|
+
|
|
28
|
+
Ordinary coordinates retain their floating-point operation order. Exact
|
|
29
|
+
arithmetic recovers finite results lost to intermediate overflow. A result
|
|
30
|
+
outside float range becomes signed infinity for boundary repair.
|
|
31
|
+
"""
|
|
32
|
+
value = base
|
|
33
|
+
for scale, left, right in terms:
|
|
34
|
+
value += scale * (left - right)
|
|
35
|
+
if math.isfinite(value):
|
|
36
|
+
return value
|
|
37
|
+
if not math.isfinite(base) or not all(
|
|
38
|
+
math.isfinite(number) for term in terms for number in term
|
|
39
|
+
):
|
|
40
|
+
return value
|
|
41
|
+
exact = Fraction(base) + sum(
|
|
42
|
+
Fraction(scale) * (Fraction(left) - Fraction(right))
|
|
43
|
+
for scale, left, right in terms
|
|
44
|
+
)
|
|
45
|
+
try:
|
|
46
|
+
return float(exact)
|
|
47
|
+
except OverflowError:
|
|
48
|
+
return math.inf if exact > 0 else -math.inf
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def interpolate(lower: float, upper: float, fraction: float) -> float:
|
|
52
|
+
width = upper - lower
|
|
53
|
+
if math.isfinite(width):
|
|
54
|
+
value = lower + fraction * width
|
|
55
|
+
else:
|
|
56
|
+
value = (1.0 - fraction) * lower + fraction * upper
|
|
57
|
+
return min(max(lower, upper), max(min(lower, upper), value))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def uniform(lower: float, upper: float, rng: RandomSource) -> float:
|
|
61
|
+
if math.isfinite(upper - lower):
|
|
62
|
+
return rng.uniform(lower, upper)
|
|
63
|
+
return interpolate(lower, upper, rng.random())
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def midpoint(left: float, right: float) -> float:
|
|
67
|
+
total = left + right
|
|
68
|
+
return total / 2 if math.isfinite(total) else left / 2 + right / 2
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def opposite(value: float, lower: float, upper: float) -> float:
|
|
72
|
+
total = lower + upper
|
|
73
|
+
return total - value if math.isfinite(total) else lower + (upper - value)
|