geneticevo 0.1.0a1__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.
Files changed (51) hide show
  1. geneticevo-0.1.0a1/LICENSE +21 -0
  2. geneticevo-0.1.0a1/MANIFEST.in +5 -0
  3. geneticevo-0.1.0a1/PKG-INFO +366 -0
  4. geneticevo-0.1.0a1/README.md +330 -0
  5. geneticevo-0.1.0a1/benchmarks/baselines.py +72 -0
  6. geneticevo-0.1.0a1/benchmarks/equal_work.py +93 -0
  7. geneticevo-0.1.0a1/benchmarks/ppo_updates.py +48 -0
  8. geneticevo-0.1.0a1/docs/architecture.md +129 -0
  9. geneticevo-0.1.0a1/docs/benchmark_snapshot.json +460 -0
  10. geneticevo-0.1.0a1/docs/release.md +92 -0
  11. geneticevo-0.1.0a1/docs/report.md +159 -0
  12. geneticevo-0.1.0a1/docs/validation.md +81 -0
  13. geneticevo-0.1.0a1/examples/custom_genome.py +66 -0
  14. geneticevo-0.1.0a1/examples/custom_learner.py +46 -0
  15. geneticevo-0.1.0a1/examples/generalization.py +37 -0
  16. geneticevo-0.1.0a1/examples/native_ppo.py +27 -0
  17. geneticevo-0.1.0a1/examples/neural.py +16 -0
  18. geneticevo-0.1.0a1/examples/sb3_learning.py +25 -0
  19. geneticevo-0.1.0a1/examples/shared_world.py +42 -0
  20. geneticevo-0.1.0a1/examples/vector.py +18 -0
  21. geneticevo-0.1.0a1/pyproject.toml +41 -0
  22. geneticevo-0.1.0a1/setup.cfg +4 -0
  23. geneticevo-0.1.0a1/src/geneticevo/__init__.py +9 -0
  24. geneticevo-0.1.0a1/src/geneticevo/agents.py +176 -0
  25. geneticevo-0.1.0a1/src/geneticevo/core.py +187 -0
  26. geneticevo-0.1.0a1/src/geneticevo/environments.py +35 -0
  27. geneticevo-0.1.0a1/src/geneticevo/evaluation.py +91 -0
  28. geneticevo-0.1.0a1/src/geneticevo/evolution.py +37 -0
  29. geneticevo-0.1.0a1/src/geneticevo/execution.py +22 -0
  30. geneticevo-0.1.0a1/src/geneticevo/integrations/__init__.py +1 -0
  31. geneticevo-0.1.0a1/src/geneticevo/integrations/pettingzoo.py +9 -0
  32. geneticevo-0.1.0a1/src/geneticevo/integrations/sb3.py +268 -0
  33. geneticevo-0.1.0a1/src/geneticevo/integrations_validation.py +10 -0
  34. geneticevo-0.1.0a1/src/geneticevo/learners.py +24 -0
  35. geneticevo-0.1.0a1/src/geneticevo/plotting.py +19 -0
  36. geneticevo-0.1.0a1/src/geneticevo/ppo.py +212 -0
  37. geneticevo-0.1.0a1/src/geneticevo/results.py +122 -0
  38. geneticevo-0.1.0a1/src/geneticevo/runner.py +379 -0
  39. geneticevo-0.1.0a1/src/geneticevo/shared.py +355 -0
  40. geneticevo-0.1.0a1/src/geneticevo/tensor.py +269 -0
  41. geneticevo-0.1.0a1/src/geneticevo.egg-info/PKG-INFO +366 -0
  42. geneticevo-0.1.0a1/src/geneticevo.egg-info/SOURCES.txt +49 -0
  43. geneticevo-0.1.0a1/src/geneticevo.egg-info/dependency_links.txt +1 -0
  44. geneticevo-0.1.0a1/src/geneticevo.egg-info/requires.txt +26 -0
  45. geneticevo-0.1.0a1/src/geneticevo.egg-info/top_level.txt +1 -0
  46. geneticevo-0.1.0a1/tests/test_core.py +179 -0
  47. geneticevo-0.1.0a1/tests/test_learning.py +173 -0
  48. geneticevo-0.1.0a1/tests/test_parallel.py +25 -0
  49. geneticevo-0.1.0a1/tests/test_pettingzoo.py +20 -0
  50. geneticevo-0.1.0a1/tests/test_shared.py +115 -0
  51. geneticevo-0.1.0a1/tests/test_tensor.py +238 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 geneticevo contributors
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,5 @@
1
+ include README.md pyproject.toml LICENSE
2
+ recursive-include docs *.md *.json
3
+ recursive-include examples *.py
4
+ recursive-include tests *.py
5
+ recursive-include benchmarks *.py
@@ -0,0 +1,366 @@
1
+ Metadata-Version: 2.4
2
+ Name: geneticevo
3
+ Version: 0.1.0a1
4
+ Summary: Reproducible evolutionary experiments with optional independent lifetime learning
5
+ License-Expression: MIT
6
+ Keywords: evolution,genetic-algorithms,reinforcement-learning,research
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy<3,>=1.26
17
+ Requires-Dist: gymnasium<1.3,>=1.2
18
+ Provides-Extra: torch
19
+ Requires-Dist: torch<2.13,>=2.12; extra == "torch"
20
+ Provides-Extra: sb3
21
+ Requires-Dist: stable-baselines3<2.10,>=2.9; extra == "sb3"
22
+ Requires-Dist: torch<2.13,>=2.12; extra == "sb3"
23
+ Provides-Extra: shared
24
+ Requires-Dist: pettingzoo<1.26,>=1.24; extra == "shared"
25
+ Provides-Extra: plot
26
+ Requires-Dist: matplotlib<3.11,>=3.10; extra == "plot"
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest<10,>=8; extra == "dev"
29
+ Requires-Dist: build<2,>=1; extra == "dev"
30
+ Provides-Extra: bench
31
+ Requires-Dist: psutil<8,>=7; extra == "bench"
32
+ Provides-Extra: release
33
+ Requires-Dist: build<2,>=1; extra == "release"
34
+ Requires-Dist: twine<7,>=6; extra == "release"
35
+ Dynamic: license-file
36
+
37
+ # geneticevo
38
+
39
+ **Alpha preview: 0.1.0a1.** APIs and checkpoint compatibility may change.
40
+
41
+ A Python library for reproducible evolutionary experiments, with optional
42
+ lifetime learning and population tensor execution. Supply a problem and an agent
43
+ factory; the runner handles selection, mutation, elites, lineage, evaluation,
44
+ metrics, archives, and checkpoints.
45
+
46
+ Pure evolution requires only NumPy and Gymnasium. PyTorch, Stable-Baselines3
47
+ (SB3), PettingZoo, and plotting are optional. The package and Python import name
48
+ are `geneticevo`. This project has not been published or deployed.
49
+
50
+ Evolution, learning, communication, and GPU execution do not guarantee better
51
+ results or general intelligence. These are research tools, not deployment safety
52
+ guarantees.
53
+
54
+ ## Installation
55
+
56
+ Python 3.10+ is declared; Python 3.11.9 was tested on Windows. From this directory:
57
+
58
+ ```powershell
59
+ python -m venv .venv
60
+ .\.venv\Scripts\Activate.ps1
61
+ python -m pip install -e .
62
+ # Choose the extras you need:
63
+ python -m pip install -e ".[sb3]" # PPO and DQN; includes PyTorch
64
+ python -m pip install -e ".[torch]" # Native population tensors and PPO
65
+ python -m pip install -e ".[shared]" # Official PettingZoo integration
66
+ python -m pip install -e ".[plot]" # Saved plots
67
+ python -m pip install -e ".[dev,release]" # Test/build/metadata validation tools
68
+ ```
69
+
70
+ On Linux/macOS, activate with `source .venv/bin/activate`. Source installation is
71
+ the verified installation path; the project has not been uploaded to PyPI.
72
+ To install the locally built alpha wheel, use:
73
+
74
+ ```powershell
75
+ python -m pip install "dist/geneticevo-0.1.0a1-py3-none-any.whl"
76
+ ```
77
+
78
+ Core evolution does not install PyTorch, SB3, PettingZoo, or Matplotlib. Optional
79
+ extras have their own upstream Python/platform requirements; for example, the
80
+ tested PettingZoo 1.25.0 declares Python <3.13. Only Python 3.11.9 on Windows has
81
+ been exercised here; the minimum declared Python version is not a tested matrix.
82
+
83
+ ## CPU and GPU requirements
84
+
85
+ - Ordinary CPU execution needs Python, NumPy, and Gymnasium. CUDA and a GPU are
86
+ unnecessary for vector optimization and NumPy neural evolution.
87
+ - Native tensor inference/PPO requires the `torch` extra and works on CPU.
88
+ SB3 learning requires the `sb3` extra and also works on CPU.
89
+ - CUDA execution is **experimental and hardware-unverified** in this release.
90
+ It requires an NVIDIA GPU, a compatible driver, and a compatible CUDA-enabled
91
+ PyTorch build. Install the appropriate PyTorch build before requesting CUDA.
92
+ The CUDA version string on an installed PyTorch build does not establish that
93
+ a usable GPU exists.
94
+ - Python environments keep running on the CPU. GPU policies with Python
95
+ environments are hybrid execution; native tensor simulation requires a
96
+ compatible tensor environment. There is no general GPU speedup claim.
97
+ - An explicitly requested unavailable device raises an actionable error.
98
+ Automatic CPU fallback is not used.
99
+
100
+ Declared ranges and tested versions:
101
+
102
+ | Dependency | Declared range | Tested |
103
+ |---|---|---|
104
+ | NumPy | >=1.26,<3 | 2.4.4 |
105
+ | Gymnasium | >=1.2,<1.3 | 1.2.3 |
106
+ | PyTorch (optional) | >=2.12,<2.13 | 2.12.1+cu126, CPU execution |
107
+ | SB3 (optional) | >=2.9,<2.10 | 2.9.0 |
108
+ | PettingZoo (optional) | >=1.24,<1.26 | 1.25.0 |
109
+ | Matplotlib (optional) | >=3.10,<3.11 | 3.10.6 |
110
+
111
+ Only the listed versions were exercised; the entire allowed ranges were not
112
+ tested. CUDA hardware was unavailable. See [validation](docs/validation.md).
113
+
114
+ ## Complete quickstart
115
+
116
+ This environment is included and uses Gymnasium's reset/step conventions:
117
+
118
+ ```python
119
+ from geneticevo import Evolution, EvolutionConfig, GaussianMutation
120
+ from geneticevo.agents import MLPAgentFactory
121
+ from geneticevo.environments import Reach1D
122
+
123
+ experiment = Evolution(
124
+ env_factory=Reach1D,
125
+ agent_factory=MLPAgentFactory(hidden_sizes=(16, 16)),
126
+ config=EvolutionConfig(
127
+ population_size=12,
128
+ generations=5,
129
+ elite_count=2,
130
+ selection="tournament",
131
+ evaluation_episodes=3,
132
+ seed=42,
133
+ output_dir="results/quickstart",
134
+ ),
135
+ mutation=GaussianMutation(parameter_probability=0.1, std=0.1),
136
+ learner=None,
137
+ backend="serial",
138
+ device="cpu",
139
+ )
140
+ result = experiment.run()
141
+ result.best_agent.save("results/quickstart/champion")
142
+ print(result.best_fitness)
143
+ ```
144
+
145
+ The NumPy MLP has separate actor and critic networks. Its inherited vector
146
+ contains all actor weights/biases, critic weights/biases, and, for continuous
147
+ actions, log standard deviations. Critic genes matter when lifetime learning is
148
+ enabled. Pure evolution does not use the critic for action selection.
149
+
150
+ ## Runnable examples
151
+
152
+ Run these from the repository after installation:
153
+
154
+ ```powershell
155
+ python examples/vector.py
156
+ python examples/neural.py
157
+ python examples/custom_genome.py
158
+ python examples/custom_learner.py
159
+ python examples/generalization.py
160
+ python examples/sb3_learning.py --algorithm PPO
161
+ python examples/sb3_learning.py --algorithm DQN --inheritance baldwinian
162
+ python examples/native_ppo.py --device cpu
163
+ python examples/native_ppo.py --continuous
164
+ python examples/shared_world.py
165
+ python examples/shared_world.py --rl
166
+ ```
167
+
168
+ For CUDA, use `python examples/native_ppo.py --device cuda`. This path is
169
+ implemented but hardware validation and performance are outstanding.
170
+
171
+ ## Configuration and lifecycle
172
+
173
+ `generations=5` evaluates populations **0 through 4**. There is no unused final
174
+ offspring population. A generation initializes/restores, optionally measures
175
+ pre-learning performance, learns, evaluates frozen policies, updates the
176
+ archive, records statistics, and checkpoints. Reproduction happens only if
177
+ another generation will be evaluated.
178
+
179
+ These settings have different meanings:
180
+
181
+ | Setting | Meaning |
182
+ |---|---|
183
+ | `population_size` | Number of independently inherited individuals |
184
+ | `generations` | Number of evaluated populations |
185
+ | `env_copies` | Environment copies **per individual**, used by learners and tensor evaluation |
186
+ | `learning_budget` | Requested training transitions **per individual per generation** |
187
+ | `evaluation_episodes` | Frozen selection episodes per individual; also sizes the archive reference suite |
188
+ | Shared world's `possible_agents` | Roles acting together in one world; independent of population size |
189
+
190
+ Serial evaluation visits episodes sequentially. CPU parallelism evaluates
191
+ individuals in spawned processes. It requires pickleable top-level factories
192
+ and an `if __name__ == "__main__":` entry point. Shared population evaluation is
193
+ currently serial. SB3 learning runs individuals sequentially, even when fitness
194
+ evaluation uses CPU workers.
195
+
196
+ Mutation probability applies **per scalar parameter**. `std` controls its
197
+ magnitude. Tournament and rank selection honor `maximize`; custom selection,
198
+ mutation, and optional crossover are supported. Crossover is disabled by default.
199
+ `immigrant_count` injects fresh agents. `diversity_pairs` enables sampled parameter
200
+ distances without an all-pairs calculation.
201
+
202
+ Target fitness and stagnation use fixed archive-reference fitness. Time and
203
+ interaction caps stop at **complete generation boundaries**, so they can
204
+ overshoot by a generation. The first population is always evaluated. Counts
205
+ include archive and optional pre-learning evaluation. Custom vector objectives
206
+ consume zero environment interactions.
207
+
208
+ ## Learning and inheritance
209
+
210
+ Use `learner=None` and `learning_budget=0` for evolution only.
211
+
212
+ - **Lamarckian:** learned parameters replace inherited genes before reproduction.
213
+ - **Baldwinian:** train a fresh copy; fitness and the deployed archive snapshot
214
+ use that copy, while reproduction uses the original genes.
215
+ - Unchanged elites continue optimizer/counter/replay state by default and learn
216
+ again (`elite_learning=True`). Set it false to skip further elite learning with
217
+ serial SB3/custom learners. Native batching requires it true.
218
+ - Mutated children and immigrants start fresh optimizer, replay/rollout,
219
+ exploration, counter, and random-action state. DQN targets are synchronized to
220
+ the child's mutated online network. Unchanged elites preserve DQN targets.
221
+ - Environments reset at generation boundaries. Mid-episode state is not resumed.
222
+
223
+ SB3's factory builds the algorithm's own compatible `MlpPolicy`; arbitrary NumPy
224
+ or PyTorch modules cannot attach to it unchanged. PPO evolves its full online
225
+ policy, including value and distribution parameters. DQN evolves its online Q
226
+ network; target networks are algorithm state. Normalization wrappers are rejected
227
+ until a frozen-statistics serialization adapter exists.
228
+
229
+ PPO rounds a budget up to `rollout_steps * env_copies` (SB3 uses `n_steps`).
230
+ Updates may occur within unfinished episodes. DQN's default step frequency is
231
+ one; custom frequencies may overshoot. Requested and actual counts are distinct.
232
+ With SB3, set the factory's and learner's `env_copies` to match the config.
233
+
234
+ Native PPO batches independent policies, losses, gradients, clipping, and Adam.
235
+ Adam has separate moments **and step counters** for each individual, so a fresh
236
+ child can learn alongside an older elite. Advantages normalize per individual
237
+ over a rollout. Discrete categorical and continuous tanh-squashed Gaussian
238
+ likelihoods are implemented. Continuous entropy regularization uses the base
239
+ normal's entropy; its default coefficient is zero.
240
+
241
+ ## Supported combinations
242
+
243
+ | Agents / learner | Serial CPU | CPU process evaluation | Batched policies, Python env | Tensor environment |
244
+ |---|---|---|---|---|
245
+ | Vector objective / none | Yes | Yes | No | No |
246
+ | NumPy MLP / none | Yes | Yes | Yes | Yes |
247
+ | SB3 PPO or DQN / SB3Learner | Yes | Yes; learning stays sequential | No | No |
248
+ | MLP / NativePPO | No | No | Yes | Yes |
249
+ | Evolved message head / none | Shared serial | No | No | No |
250
+ | SB3 task policy / fixed messages | Shared serial | No | No | No |
251
+
252
+ Neural observations must be flat `Box`; actions must be zero-start `Discrete` or
253
+ flat, finite, strictly bounded `Box`. DQN supports `Discrete` only. Shared worlds
254
+ use the PettingZoo Parallel protocol with flat `Box` observations. Other spaces
255
+ need explicit tested adapters.
256
+
257
+ `backend="batched"` uses fixed shared architectures. Tensor computation also runs
258
+ on CPU. Omitting `tensor_env_factory` uses `GymTensorBridge`: Python simulation
259
+ stays on CPU even if policies run on CUDA. This is labeled hybrid execution.
260
+ Setting a device never migrates arbitrary Python simulation code. Native tensor
261
+ environments require matching policy/environment devices. The included
262
+ `TensorReach1D` has a matching CPU reference. Archives always use the serial CPU
263
+ reference evaluator, including for tensor runs.
264
+
265
+ ## Shared worlds and communication
266
+
267
+ Communication is disabled by default. `MessageChannel` uses bounded fixed-size
268
+ messages and broadcasts to other active agents. Each sender owns an identified
269
+ inbox slot plus a presence bit. Messages sent with a task action become visible
270
+ in the **next** observation. Reset clears inboxes. Optional L1 message cost is
271
+ subtracted from sender reward. Recipient and transform hooks allow custom
272
+ routing/noise/dropout; queued delays need a custom channel implementation.
273
+
274
+ Policies receive only their permitted local observation and prior inbox. Pure
275
+ evolution can change both task and message heads. `SharedEvaluator` rotates focal
276
+ roles and current-population partners for selection; archive comparisons use a
277
+ fixed partner pool. Use another evaluator with unfamiliar partners for final
278
+ testing. `reward_mode` chooses focal-individual or mean-team reward. World steps
279
+ and all active-agent transitions are counted separately; inactive roles do not
280
+ act. Explicit focal-to-role mappings are retained in evaluation details.
281
+
282
+ The tested multi-agent learning integration is PPO/DQN on `SharedFocalEnv` against
283
+ frozen partners with **fixed message rules**. The learner trains task actions;
284
+ messages have no trainable distribution. End-to-end learned stochastic messages
285
+ and simultaneous RL of distinct communicating policies are unsupported.
286
+ Experience sharing, parameter averaging, imitation, and global memory are not
287
+ part of communication.
288
+
289
+ ## Results, checkpoints, and generalization
290
+
291
+ `output_dir` writes `metadata.json`, incremental `metrics.jsonl`, `lineage.json`,
292
+ and atomic `latest.checkpoint`. Metrics include fitness quantiles, task metrics,
293
+ episode lengths, training/evaluation costs, learner reports, population and
294
+ mutation settings, component timings, throughput, and cumulative wall time.
295
+ Final-info success/failure fields are retained when environments provide them.
296
+ Trajectories and every network are not saved by default.
297
+
298
+ The archive shortlists the best `archive_size` current candidates, then compares
299
+ them with old archive snapshots on common, fixed reference scenarios. It does
300
+ not compare incomparable rotating selection scores across generations.
301
+ Snapshots are independent copies with their evaluation context.
302
+
303
+ Resume at an evaluated generation boundary:
304
+
305
+ ```python
306
+ # Re-create experiment with the same components/configuration; generations may increase.
307
+ result = experiment.run(resume_from="results/quickstart/latest.checkpoint")
308
+ ```
309
+
310
+ Checkpoint schema 1 stores population/archive genes, resumable learning state,
311
+ RNG state, IDs, lineage, and counters. Scalar settings and component descriptions
312
+ are checked on restore. Custom components should expose configuration as public
313
+ fields on stable classes; arbitrary hidden global or closure state cannot be
314
+ verified. Load only trusted checkpoints: they use Python pickle. Agent folders
315
+ save inference genomes; continuing optimizer/replay state requires a checkpoint.
316
+ Bitwise reproducibility across devices, versions, and platforms is not promised.
317
+
318
+ Training uses a separate `training_env_factory` (defaults to `env_factory`).
319
+ Selection scenarios rotate by generation, with a common suite for each
320
+ population. Archive scenarios stay fixed. `validation_sampler` and
321
+ `archive_sampler` accept `(rng, count, generation)` and return `Scenario` objects.
322
+ `Scenario.options` reaches Gymnasium reset, enabling procedural distributions.
323
+
324
+ Final testing is explicit and never drives the runner:
325
+
326
+ ```python
327
+ from geneticevo.core import scenarios_for
328
+ from geneticevo.evaluation import GymEvaluator
329
+ test = result.evaluate(GymEvaluator(Reach1D), scenarios_for(2026, "test", 20))
330
+ ```
331
+
332
+ Use separate test scenarios and partners, including shifted distributions.
333
+ `adaptation_evaluation` gives every task a fresh training-state copy and records
334
+ pre/post performance and costs. It does not modify the champion. Repeated
335
+ training seeds and `uncertainty_summary` describe uncertainty across runs;
336
+ additional episodes do not replace independent training seeds. No mechanism
337
+ prevents memorization or invalid experimental design.
338
+
339
+ ## Development and evidence
340
+
341
+ ```powershell
342
+ python -m unittest discover -s tests -v
343
+ python -m pytest -q
344
+ python -m build --wheel --no-isolation
345
+ python -m twine check --strict dist/geneticevo-0.1.0a1*
346
+ python benchmarks/equal_work.py --repeats 3
347
+ python benchmarks/baselines.py --seeds 1 2 3
348
+ ```
349
+
350
+ Windows sandbox restrictions may prevent spawned worker pipes; use an ordinary
351
+ local terminal for process tests. [Architecture and extensions](docs/architecture.md)
352
+ explain custom genomes/environments/learners. [Validation](docs/validation.md)
353
+ documents correctness checks and benchmark methodology. [Delivery report](docs/report.md)
354
+ records measured results and remaining limitations.
355
+ The [alpha release checklist](docs/release.md) records packaging checks and the
356
+ boundary between CPU validation and unverified CUDA execution.
357
+
358
+ For a saved plot: `from geneticevo.plotting import plot_history`, then call
359
+ `plot_history("results/neural/metrics.jsonl", "results/neural/fitness.png")`.
360
+
361
+ ## License
362
+
363
+ geneticevo is licensed under the [MIT License](LICENSE). Copyright notices and
364
+ the license text ship with the source distribution and wheel. Dependencies
365
+ retain their own licenses.
366
+