neat/evolve/adaptive

The evolve-time adaptive bridge coordinates optional controllers and post-mutation maintenance inside one finished generation step.

The root adaptive/ chapter explains the full catalog of adaptive policies: complexity budgeting, phased growth, acceptance pressure, lineage feedback, mutation tuning, and operator-stat decay. This file owns the narrower evolve question: when one generation is already in flight, which of those policies should be invoked now, which ones must remain best-effort, and which cleanup steps need to happen after mutation so the next generation starts from a coherent runtime state?

Read this chapter when you want to understand:

The helper flow is easiest to retain as four responsibilities:

  1. invoke optional controller-level adaptation without breaking narrower runtimes,
  2. retune compatibility pressure when species counts drift,
  3. run pruning and mutation as one mutation-phase maintenance block,
  4. repair mutation-side runtime state such as compatibility caches and re-enable probabilities before the next generation is evaluated.
flowchart TD
  Ranked[Ranked current generation] --> Controllers[Run optional adaptive controllers]
  Controllers --> Compat[Retune compatibility coefficients when enabled]
  Compat --> Mutate[Apply pruning and mutation]
  Mutate --> Repair[Adapt re-enable probability and clear compat caches]
  Repair --> Ready[Next generation runtime state ready]

neat/evolve/adaptive/evolve.adaptive.utils.ts

adaptReenableProbability

adaptReenableProbability(
  internal: NeatControllerForEvolution,
  config: { minSamples: number; target: number; min: number; max: number; deltaScale: number; },
): void

Adapt the re-enable probability based on recent success ratios.

Re-enable adaptation turns the last generation's connection-revival outcomes into one controller-level probability update for the next generation. It aggregates success and attempt counters across the whole population, resets those per-genome counters once consumed, and only adjusts the shared probability when the sample size is large enough to be meaningful.

Parameters:

Returns: Nothing.

applyAdaptiveComplexityControllers

applyAdaptiveComplexityControllers(
  internal: NeatControllerForEvolution,
): Promise<void>

Apply adaptive complexity controllers if available.

This helper is the evolve bridge into the root adaptive complexity policies. It keeps both optional calls together because they rewrite controller-level structure policy rather than one single genome: budget scheduling can change allowed network size, and phased complexity can flip the controller between growth and simplification modes.

Parameters:

Returns: A promise that resolves after optional complexity controllers have run.

applyAncestorUniqAdaptiveSafe

applyAncestorUniqAdaptiveSafe(
  internal: NeatControllerForEvolution,
): Promise<void>

Apply ancestor uniqueness adaptation if available.

This helper is the evolve-side bridge from freshly recorded telemetry lineage evidence back into future controller policy. The underlying adaptive rule may change dominance epsilon or lineage-pressure settings, but the bridge itself stays narrow: it only attempts the optional handoff and tolerates runtimes where lineage adaptation is absent.

Parameters:

Returns: A promise that resolves after the optional lineage controller runs.

applyAutoCompatibilityTuning

applyAutoCompatibilityTuning(
  internal: NeatControllerForEvolution,
  config: { targetMin: number; adjustRate: number; minCoeff: number; maxCoeff: number; randomScale: number; },
): void

Apply auto-compatibility tuning if enabled.

This helper keeps one small adaptive loop close to evolve because it depends directly on the just-observed species count from the ranked generation. When the observed registry drifts from the target, the helper nudges excess and disjoint coefficients together so the next speciation pass can tighten or loosen the compatibility boundary.

The fallback behavior when error === 0 is also deliberate: instead of doing nothing forever at equilibrium, the helper allows a bounded random nudge so the controller can keep exploring nearby coefficient space.

Parameters:

Returns: Nothing.

applyMinimalCriterionAdaptiveSafe

applyMinimalCriterionAdaptiveSafe(
  internal: NeatControllerForEvolution,
): Promise<void>

Apply minimal criterion adaptive controller if available.

Minimal criterion adaptation is one of the few adaptive policies that can rewrite the current generation's score landscape immediately. Keeping it in a safe wrapper lets evolve apply that pressure when configured without forcing every runtime surface to include the full adaptive subtree.

Parameters:

Returns: A promise that resolves after the optional acceptance controller runs.

applyOperatorAdaptationSafe

applyOperatorAdaptationSafe(
  internal: NeatControllerForEvolution,
): Promise<void>

Apply operator adaptation if available.

Operator adaptation is another best-effort policy-maintenance bridge. It decays long-running operator statistics so later mutation choices weight more recent evidence without forcing evolve to know the details of the adaptive operator-selection subsystem.

Parameters:

Returns: A promise that resolves after optional operator-stat decay runs.

applyPruningAndMutation

applyPruningAndMutation(
  internal: NeatControllerForEvolution,
): Promise<void>

Apply pruning and mutation phases.

Mutation-time maintenance is grouped here because evolve needs one compact place where structural removal, adaptive pruning, baseline mutation, and optional adaptive mutation all happen in the intended order. The helper does not decide whether the population should be rebuilt; it assumes the next generation already exists and now needs its structural edits.

Example:

await applyPruningAndMutation(internal);
invalidateCompatibilityCaches(internal);

Parameters:

Returns: A promise that resolves after mutation-phase maintenance finishes.

invalidateCompatibilityCaches

invalidateCompatibilityCaches(
  internal: NeatControllerForEvolution,
): void

Invalidate compatibility caches after mutations.

Structural mutation can make cached compatibility comparisons stale. Clearing those caches here ensures later speciation and distance reads are recomputed from the post-mutation topology instead of reusing scores from the previous generation.

Parameters:

Returns: Nothing.

Generated from source JSDoc • GitHub