Skip to content

Commit a7e5b01

Browse files
Minor documentation updates.
1 parent c1e63c8 commit a7e5b01

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4141
- Includes test/visualization script for trained controllers
4242
- Full documentation in example README with usage tips
4343

44+
- **New Example**: Better Lunar Lander example (as in, it actually solves the environment)
45+
4446
### Changed
4547
- Dropped support for Python 3.6 and 3.7; neat-python now requires Python 3.8 or newer.
4648
- Modernized internal implementation in `neat/` and `examples/` to use Python 3 features

docs/config_essentials.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ Let's walk through the XOR example config with explanations:
194194
# Legacy values ``full`` and ``partial`` are accepted for backward compatibility but
195195
# are deprecated; prefer the explicit variants above.
196196
initial_connection = full_direct
197+
198+
# Note: The original NEAT paper emphasizes starting from minimal structure (no hidden nodes
199+
# and sparse connectivity) and then complexifying over time. NEAT-Python follows this
200+
# philosophy by treating ``unconnected`` as the canonical "no edges" option (see
201+
# :ref:`initial-connection-config-label` and :doc:`neat_overview`). In simple examples like XOR
202+
# we use ``full_direct`` for convenience so networks make progress quickly, while still
203+
# starting with zero hidden nodes. If you want the sparsest possible starting networks,
204+
# set ``initial_connection = unconnected`` instead.
197205
198206
# Activation function for neurons
199207
# sigmoid: outputs in range (0, 1) - good for most problems

docs/reproducibility.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ The ``seed`` parameter takes precedence over the config file setting:
6161
# Config file has seed=100, but this uses seed=42
6262
pop = neat.Population(config, seed=42)
6363
64+
Note that passing ``seed=None`` explicitly to :class:`~neat.population.Population` disables seeding from the
65+
configuration file even if ``[NEAT]`` contains a ``seed = ...`` entry; omitting the ``seed`` argument entirely
66+
causes :class:`~neat.population.Population` to use ``config.seed`` if present.
67+
6468
Random Behavior (Default)
6569
^^^^^^^^^^^^^^^^^^^^^^^^^^
6670

@@ -184,6 +188,36 @@ Checkpoints preserve:
184188

185189
This means checkpointing maintains reproducibility even without explicitly setting a seed when restoring.
186190

191+
.. note::
192+
193+
**Checkpoint vs. uninterrupted-run trajectories**
194+
195+
Restoring the *same* checkpoint multiple times produces a deterministic
196+
continuation of evolution: given a fixed checkpoint file and fitness
197+
function, repeated restores followed by additional generations will take
198+
the same evolutionary path.
199+
200+
However, there is one subtle limitation: the sequence of populations you
201+
get when running **without** checkpointing is not currently guaranteed to be
202+
*bit-for-bit identical* to the sequence you get when running **with**
203+
checkpointing and later restoring from a checkpoint at generation ``N``.
204+
205+
The reason is that some helper objects involved in evolution (such as the
206+
reproduction and stagnation helpers) are reconstructed when a checkpoint is
207+
restored rather than being pickled and resumed exactly as-is. Although
208+
their behavior is designed to be equivalent, and key invariants (population,
209+
species, random state, innovation tracking) are preserved, there are still
210+
rare edge cases where the evolutionary trajectory after generation ``N`` may
211+
differ slightly between an uninterrupted run and a resumed run.
212+
213+
In practice this means:
214+
215+
* Checkpoints are suitable for pausing/resuming long runs and for
216+
experiment management.
217+
* Checkpoints do **not** currently provide a strict guarantee that
218+
"run-with-checkpoint" and "run-without-checkpoint" will produce
219+
identical post-``N`` populations, even when using the same seed.
220+
187221
Limitations
188222
-----------
189223

docs/xor_example.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ then the fitness value of A should be greater than the value of B. The absolute
3333
are not important, only their relative values.
3434

3535
In this example, we create a :term:`feed-forward` neural network based on the genome, and then for each case in the
36-
table above, we provide that network with the inputs, and compute the network's output. The error for each genome
37-
is :math:`1 - \sum_i (e_i - a_i)^2` between the expected (:math:`e_i`) and actual (:math:`a_i`) outputs, so that if the
38-
network produces exactly the expected output, its fitness is 1, otherwise it is a value less than 1, with the fitness
39-
value decreasing the more incorrect the network responses are.
36+
table above, we provide that network with the inputs, and compute the network's output. The fitness for each genome
37+
is computed as :math:`4.0 - \\sum_i (e_i - a_i)^2`, where :math:`e_i` and :math:`a_i` are the expected and actual outputs
38+
for each of the four XOR test cases. If the network produces exactly the expected output on all cases, its fitness is
39+
4.0; otherwise it is a value less than 4.0, with the fitness value decreasing the more incorrect the network responses
40+
are.
4041

4142
This fitness computation is implemented in the ``eval_genomes`` function. This function takes two arguments: a list
4243
of genomes (the current population) and the active configuration. neat-python expects the fitness function to calculate

0 commit comments

Comments
 (0)