neat/evolve

The evolution chapter is where one NEAT generation actually turns into the next.

If the root Neat controller explains the public lifecycle, this module explains the orchestration core that makes that lifecycle real. The exported evolve() function is intentionally long in responsibility but short in local decision-making: it reads like a stage manager for one generation and delegates the detailed work to focused helpers under adaptive/, objectives/, population/, runtime/, speciation/, and telemetry/. That split matters because the controller has to coordinate many policies at once without collapsing them into one opaque algorithm blob.

Read this chapter when you want to answer questions such as:

The high-level flow is easier to retain if you treat it as five phases:

  1. make the current population comparable,
  2. update adaptive and objective policies,
  3. rank and summarize the current generation,
  4. construct the next population,
  5. finalize runtime state for the next loop.
flowchart TD
  Evaluate[Evaluate current population] --> Adapt[Apply adaptive controllers]
  Adapt --> Rank[Sort, rank, and speciate]
  Rank --> Snapshot[Snapshot best genome and telemetry evidence]
  Snapshot --> Rebuild[Build next population via elitism, provenance, and offspring]
  Rebuild --> Mutate[Apply pruning, mutation, and cache invalidation]
  Mutate --> Finalize[Advance generation and maintain runtime history]

Reading order:

neat/evolve/evolve.types.ts

Shared runtime contracts for the NEAT evolution orchestration chapter.

The exported evolve() function in evolve.ts reads like a stage manager. This file explains the cast it is allowed to move around: genomes carrying runtime metadata, species snapshots used during allocation, objective descriptors reused by multi-objective ranking, and the narrow controller host surface that the evolve helpers coordinate.

The contracts naturally group into four layers:

  1. evolving genome state: GenomeWithMetadata,
  2. species- and telemetry-facing summaries: SpeciesWithMetadata and SpeciesHistoryRecord,
  3. policy descriptors reused during the step: MutationMethod, ObjectiveDescriptor, and MultiObjectiveOptions,
  4. orchestration host state: NeatControllerForEvolution.

Read this chapter when the evolve root chapter tells you when something happens but you still need to know which state that step is allowed to read or mutate.

flowchart TD
  Controller[NeatControllerForEvolution host] --> Population[Population genomes]
  Population --> Genome[GenomeWithMetadata runtime state]
  Controller --> Species[SpeciesWithMetadata live registry]
  Species --> History[SpeciesHistoryRecord snapshots]
  Controller --> Objectives[Objective and multi-objective policy]
  Controller --> Hooks[Runtime hooks for evaluate sort mutate and telemetry]

GenomeWithMetadata

Runtime interface for a genome carrying evolution metadata.

This mirrors the dynamic properties attached at runtime during evolution, without pulling in the full Genome class to avoid circular dependencies. These fields are intentionally permissive because evolution attaches metadata such as ids, ancestry, crowding, and objective ranks dynamically while one generation is being processed.

Treat this as the per-genome working set for one generation. The structure fields (nodes, connections) describe the candidate itself. The underscored fields capture temporary or cached evidence produced while the controller is ranking, speciating, adapting, and tracking lineage.

The important boundary is that this interface is richer than the minimal shared genome contracts used by read-side chapters, because evolve helpers are the place where new runtime metadata is actually attached.

MultiObjectiveOptions

Multi-objective configuration block.

This is the policy bundle evolve helpers consult when deciding how dynamic objective scheduling, epsilon tuning, and inactive-objective pruning should behave during a run. It is broader than one descriptor but narrower than the full controller options object.

MutationMethod

Mutation method descriptor used by runtime mutation hooks.

The evolve chapter only needs the stable operator identity, not the richer mutation policy metadata defined in the mutation subtree. That is why this local descriptor stays intentionally tiny: evolve orchestration mainly uses it as a token when handing work off to mutation-oriented hooks.

NeatControllerForEvolution

NEAT controller subset used by evolve orchestrations.

This is a minimal, runtime-focused surface used by evolve utilities to avoid circular dependencies on the full controller class.

This host contract is the backbone of the evolve subtree. It bundles five kinds of state that the orchestration step must coordinate:

  1. population and generation state,
  2. policy options that shape selection, mutation, pruning, and multi-objective ranking,
  3. live caches and archives such as species history or Pareto snapshots,
  4. controller hooks that perform focused work like evaluation, mutation, or telemetry recording,
  5. adaptation and test seams that let utility chapters nudge policy without depending on the full Neat class implementation.

The interface is intentionally large because evolve orchestration really is the point where many chapter boundaries meet. Even so, it is still narrower than the full public controller API: only the state and callbacks needed for one generation step are surfaced here.

ObjectiveDescriptor

Objective descriptor for multi-objective evaluation.

This is the shared scoring token used when evolve orchestration hands the current population to objective-aware ranking logic. Each descriptor couples a stable key with the accessor that extracts that objective's numeric evidence from one genome.

SpeciesHistoryRecord

Species history snapshot record used for telemetry/exports.

Unlike SpeciesWithMetadata, which describes the current live registry, this contract is archival. It captures the summarized species view that can be retained across generations for telemetry, historical diagnostics, and later export.

SpeciesWithMetadata

Runtime interface for species metadata used in allocation and stats.

This is the live species record shape used during one evolve step. Helpers in speciation/, population/, and telemetry-oriented paths rely on it to ask practical generation-level questions: which genomes belong together now, how much shared fitness does the species have, and how many offspring should it receive next?

neat/evolve/evolve.ts

evolve

evolve(): Promise<default>

Run a single evolution step for this NEAT population.

This is the orchestration spine for one full generation update. The method does not try to implement every evolutionary policy inline; instead, it coordinates the major phases in a fixed order so the rest of the NEAT controller can remain modular and inspectable.

The lifecycle is easiest to read in seven stages:

  1. ensure the current population has fresh evaluation scores,
  2. run adaptive controllers that may change complexity or objective policy,
  3. rank the current generation through sorting, multi-objective processing, and speciation,
  4. capture the best-network snapshot plus telemetry evidence while the generation is still intact,
  5. build the next population through elitism, provenance, and offspring allocation,
  6. mutate and prune the newly built population,
  7. finalize runtime bookkeeping for the next call.

A subtle but important design choice is that the returned {@link Network} represents the best genome from the generation that was just analyzed, not from the population after mutation. That makes the return value a stable evaluation artifact: callers can inspect or replay the winning candidate without worrying that post-selection mutation has already changed it.

The method mutates controller-owned state such as this.population, this.generation, compatibility caches, telemetry buffers, objective snapshots, and species-history state. In other words, call this when you intend to advance the controller, not when you merely want a read-only score refresh.

Important side-effects:

Use the surrounding helper folders as the next reading map:

Example:

// assuming `neat` is an instance with configured population/options
const bestNetwork = await neat.evolve();
console.log('generation:', neat.generation);
console.log('output nodes:', bestNetwork.output);

Returns: a deep-cloned network snapshot representing the best genome from the previous generation, ready for inspection or external evaluation

EVOLVE_AUTO_COMPAT_ADJUST_RATE

Default rate used when nudging compatibility coefficients toward the desired species count.

EVOLVE_AUTO_COMPAT_MAX_COEFF

Maximum compatibility coefficient allowed during automatic tuning.

EVOLVE_AUTO_COMPAT_MIN_COEFF

Minimum compatibility coefficient allowed during automatic tuning.

EVOLVE_AUTO_COMPAT_RANDOM_SCALE

Random perturbation scale used when compatibility tuning has no directional error to follow.

EVOLVE_AUTO_COMPAT_TARGET_MIN

Minimum target species count used by automatic compatibility tuning.

The controller never tries to collapse diversity below this floor when adjusting coefficients.

EVOLVE_AUTO_ENTROPY_ADD_AT

Default generation at which automatic entropy objective scheduling becomes eligible.

EVOLVE_CROSS_SPECIES_GUARD_LIMIT

Retry limit for cross-species parent sampling before the controller falls back to a safer path.

EVOLVE_DEFAULT_EPSILON_ADJUST

Default adjustment step for dominance epsilon.

The value is intentionally small because epsilon changes should steer ranking gradually rather than jerk it.

EVOLVE_DEFAULT_EPSILON_COOLDOWN

Default cooldown in generations between epsilon adjustments.

This prevents the controller from reacting to every short-lived fluctuation in front width.

EVOLVE_DEFAULT_EPSILON_MAX

Maximum dominance epsilon ceiling used by adaptive Pareto tuning.

EVOLVE_DEFAULT_EPSILON_MIN

Minimum dominance epsilon floor used by adaptive Pareto tuning.

EVOLVE_GLOBAL_STAGNATION_REPLACE_FRACTION

Fraction of the population replaced with fresh genomes when global stagnation rescue triggers.

EVOLVE_MIN_OFFSPRING_DEFAULT

Minimum offspring allocation reserved for a surviving species during speciated reproduction.

EVOLVE_OLD_MULTIPLIER_DEFAULT

Fitness-sharing multiplier applied to older species so stale lineages lose selection privilege.

EVOLVE_OLD_THRESHOLD_DEFAULT

Generation threshold after which a species is treated as old for age-based fitness shaping.

EVOLVE_PARETO_ARCHIVE_MAX

Maximum number of Pareto archive snapshots to retain.

This keeps multi-objective history useful for inspection without letting archive state grow unbounded during long runs.

EVOLVE_PRUNE_RANGE_EPS_DEFAULT

Default numerical range epsilon for deciding whether an objective has effectively gone flat.

EVOLVE_PRUNE_WINDOW_DEFAULT

Default inactivity window used before adaptive objective pruning considers removal.

EVOLVE_REENABLE_DELTA_SCALE

Scale factor that converts re-enable success error into a probability update.

EVOLVE_REENABLE_MAX

Upper bound for adaptive connection re-enable probability.

EVOLVE_REENABLE_MIN

Lower bound for adaptive connection re-enable probability.

EVOLVE_REENABLE_MIN_SAMPLES

Minimum re-enable observations required before the controller trusts its adaptation signal.

EVOLVE_REENABLE_TARGET

Desired success ratio for connection re-enable attempts during adaptive mutation control.

EVOLVE_SPECIES_HISTORY_MAX

Maximum number of species-history snapshots to retain for telemetry and later export.

EVOLVE_SURVIVAL_THRESHOLD_DEFAULT

Survivor fraction used when choosing the parent pool inside each species.

EVOLVE_TARGET_FRONT_LOWER_RATIO

Lower ratio threshold for Pareto front size vs target.

When the first front shrinks below this band, the controller can relax epsilon to avoid over-pruning.

EVOLVE_TARGET_FRONT_MIN

Minimum target front size used for adaptive epsilon tuning.

Small Pareto fronts are easy to overfit, so the epsilon controller never aims below this floor.

EVOLVE_TARGET_FRONT_UPPER_RATIO

Upper ratio threshold for Pareto front size vs target.

When the first front grows beyond this band, the controller can tighten epsilon to recover pressure.

EVOLVE_YOUNG_MULTIPLIER_DEFAULT

Fitness-sharing multiplier applied to species that are still in their early growth window.

EVOLVE_YOUNG_THRESHOLD_DEFAULT

Generation threshold below which a species is still treated as young.

Generated from source JSDoc • GitHub