@reicek/neataptic-ts 0.1.21 → 0.1.22
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.
- package/.github/agents/boundary-mapper.agent.md +29 -0
- package/.github/agents/docs-scout.agent.md +29 -0
- package/.github/agents/plan-scout.agent.md +29 -0
- package/.github/agents/solid-split.agent.md +138 -0
- package/.github/copilot-instructions.md +103 -0
- package/package.json +6 -3
- package/plans/ES2023 migration +13 -8
- package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
- package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
- package/plans/Memory_Optimization.md +3 -3
- package/plans/README.md +63 -0
- package/plans/Roadmap.md +15 -3
- package/plans/asciiMaze_SOLID_split.done.md +130 -0
- package/plans/flappy_bird_SOLID_split.done.md +67 -0
- package/scripts/assets/theme.css +221 -34
- package/scripts/copy-examples.mjs +9 -5
- package/scripts/export-onnx.mjs +3 -3
- package/scripts/generate-bench-tables.mjs +10 -10
- package/scripts/generate-bench-tables.ts +10 -10
- package/scripts/generate-docs.ts +1415 -449
- package/scripts/render-docs-html.ts +15 -8
- package/src/README.md +101 -223
- package/src/architecture/README.md +57 -185
- package/src/architecture/layer/README.md +38 -38
- package/src/architecture/network/README.md +33 -31
- package/src/architecture/network/activate/README.md +77 -77
- package/src/architecture/network/connect/README.md +15 -13
- package/src/architecture/network/deterministic/README.md +7 -7
- package/src/architecture/network/evolve/README.md +44 -44
- package/src/architecture/network/gating/README.md +20 -20
- package/src/architecture/network/genetic/README.md +51 -51
- package/src/architecture/network/mutate/README.md +97 -97
- package/src/architecture/network/onnx/README.md +264 -264
- package/src/architecture/network/prune/README.md +39 -39
- package/src/architecture/network/remove/README.md +26 -26
- package/src/architecture/network/serialize/README.md +56 -56
- package/src/architecture/network/slab/README.md +61 -61
- package/src/architecture/network/standalone/README.md +24 -24
- package/src/architecture/network/stats/README.md +9 -9
- package/src/architecture/network/topology/README.md +46 -46
- package/src/architecture/network/training/README.md +21 -21
- package/src/methods/README.md +9 -87
- package/src/multithreading/README.md +8 -77
- package/src/multithreading/workers/README.md +2 -2
- package/src/multithreading/workers/browser/README.md +0 -6
- package/src/multithreading/workers/node/README.md +0 -3
- package/src/neat/README.md +562 -568
- package/src/utils/README.md +18 -18
- package/test/examples/asciiMaze/README.md +59 -59
- package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
- package/test/examples/asciiMaze/browser-entry/README.md +196 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
- package/test/examples/asciiMaze/browser-entry.ts +10 -576
- package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
- package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
- package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
- package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
- package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
- package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
- package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
- package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
- package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
- package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
- package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
- package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
- package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
- package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
- package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
- package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
- package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
- package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
- package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
- package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
- package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
- package/test/examples/asciiMaze/fitness.ts +2 -2
- package/test/examples/asciiMaze/fitness.types.ts +65 -0
- package/test/examples/asciiMaze/interfaces.ts +64 -1352
- package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
- package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
- package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
- package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
- package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
- package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
- package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
- package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
- package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
- package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
- package/test/examples/flappy_bird/Trace-20260309T191949.json +24124 -0
- package/test/examples/flappy_bird/browser-entry/README.md +1129 -0
- package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
- package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +6 -399
- package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +1 -717
- package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
- package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +15 -893
- package/test/examples/flappy_bird/browser-entry/host/README.md +307 -0
- package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
- package/test/examples/flappy_bird/browser-entry/host/host.ts +562 -6
- package/test/examples/flappy_bird/browser-entry/host/resize/README.md +274 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +31 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +360 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +117 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +63 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +250 -0
- package/test/examples/flappy_bird/browser-entry/network-view/README.md +399 -0
- package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +255 -0
- package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +802 -7
- package/test/examples/flappy_bird/browser-entry/playback/README.md +684 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/README.md +277 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +770 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +178 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +107 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +518 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +117 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +233 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +211 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +212 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +81 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +62 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +244 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +68 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +310 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +92 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +272 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +39 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +493 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
- package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +4 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +44 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +39 -122
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +272 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +62 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
- package/test/examples/flappy_bird/browser-entry/playback/playback.ts +409 -8
- package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +4 -12
- package/test/examples/flappy_bird/browser-entry/runtime/README.md +235 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +45 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +81 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +74 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +36 -0
- package/test/examples/flappy_bird/browser-entry/visualization/README.md +557 -0
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +957 -19
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +138 -3
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +3 -27
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +1 -23
- package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +156 -0
- package/test/examples/flappy_bird/constants/README.md +1179 -0
- package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
- package/test/examples/flappy_bird/constants/constants.palette.ts +7 -0
- package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
- package/test/examples/flappy_bird/environment/README.md +143 -0
- package/test/examples/flappy_bird/environment/environment.observation.utils.ts +1 -19
- package/test/examples/flappy_bird/environment/environment.step.service.ts +3 -66
- package/test/examples/flappy_bird/evaluation/README.md +130 -0
- package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +1 -1
- package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +5 -375
- package/test/examples/flappy_bird/evaluation/rollout/README.md +291 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +30 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +58 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +310 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +56 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +368 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/README.md +618 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +7 -7
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +364 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +14 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +4 -201
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +184 -345
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +291 -0
- package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +5 -0
- package/test/examples/flappy_bird/simulation-shared/README.md +417 -0
- package/test/examples/flappy_bird/simulation-shared/observation/README.md +183 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +301 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +9 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +59 -0
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +5 -403
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +20 -6
- package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +23 -8
- package/test/examples/flappy_bird/trainer/README.md +563 -0
- package/test/examples/flappy_bird/trainer/evaluation/README.md +199 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +9 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +73 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +165 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +25 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +161 -0
- package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
- package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
- package/test/examples/flappy_bird/trainer/trainer.report.service.ts +126 -0
- package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
- package/test/examples/flappy_bird/trainer/trainer.ts +11 -553
- package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
- package/test/examples/flappy_bird/environment/environment.ts +0 -7
- package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
- package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import type Network from '../../../../src/architecture/network';
|
|
2
|
+
import type { FitnessEvaluatorFn } from '../fitness.types';
|
|
3
|
+
import type {
|
|
4
|
+
IDashboardManager,
|
|
5
|
+
IMazeRunResult,
|
|
6
|
+
INetwork,
|
|
7
|
+
} from '../interfaces';
|
|
8
|
+
|
|
9
|
+
/** Maze configuration used by the ASCII Maze evolution helpers. */
|
|
10
|
+
export interface IMazeConfig {
|
|
11
|
+
/** The maze layout, each element is a row string. Rows should be equal length. */
|
|
12
|
+
maze: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Agent simulation configuration. */
|
|
16
|
+
export interface IAgentSimulationConfig {
|
|
17
|
+
/** Maximum number of steps the agent can take in a single episode. */
|
|
18
|
+
maxSteps: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Configuration options for the evolutionary algorithm used in the ASCII Maze demos. */
|
|
22
|
+
export interface IEvolutionAlgorithmConfig {
|
|
23
|
+
allowRecurrent?: boolean;
|
|
24
|
+
popSize?: number;
|
|
25
|
+
maxStagnantGenerations?: number;
|
|
26
|
+
minProgressToPass?: number;
|
|
27
|
+
maxGenerations?: number;
|
|
28
|
+
stopOnlyOnSolve?: boolean;
|
|
29
|
+
autoPauseOnSolve?: boolean;
|
|
30
|
+
randomSeed?: number;
|
|
31
|
+
initialPopulation?: INetwork[];
|
|
32
|
+
initialBestNetwork?: INetwork | Network;
|
|
33
|
+
lamarckianIterations?: number;
|
|
34
|
+
lamarckianSampleSize?: number;
|
|
35
|
+
plateauGenerations?: number;
|
|
36
|
+
plateauImprovementThreshold?: number;
|
|
37
|
+
simplifyDuration?: number;
|
|
38
|
+
simplifyPruneFraction?: number;
|
|
39
|
+
simplifyStrategy?: 'weakWeight' | 'weakRecurrentPreferred';
|
|
40
|
+
persistEvery?: number;
|
|
41
|
+
persistDir?: string;
|
|
42
|
+
persistTopK?: number;
|
|
43
|
+
dynamicPopEnabled?: boolean;
|
|
44
|
+
dynamicPopMax?: number;
|
|
45
|
+
dynamicPopExpandInterval?: number;
|
|
46
|
+
dynamicPopExpandFactor?: number;
|
|
47
|
+
dynamicPopPlateauSlack?: number;
|
|
48
|
+
deterministic?: boolean;
|
|
49
|
+
memoryCompactionInterval?: number;
|
|
50
|
+
telemetryReduceStats?: boolean;
|
|
51
|
+
telemetryMinimal?: boolean;
|
|
52
|
+
disableBaldwinianRefinement?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Canonical stop reasons reported by the engine to host adapters. */
|
|
56
|
+
export type EvolutionStopReason =
|
|
57
|
+
| 'solved'
|
|
58
|
+
| 'stagnation'
|
|
59
|
+
| 'maxGenerations'
|
|
60
|
+
| 'cancelled'
|
|
61
|
+
| 'aborted';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Host-facing stop event emitted by the engine when a run finishes for a concrete reason.
|
|
65
|
+
*
|
|
66
|
+
* @remarks
|
|
67
|
+
* The engine uses this narrow payload so browser or terminal hosts can react to
|
|
68
|
+
* solve, stop, and pause-adjacent lifecycle events without the engine depending
|
|
69
|
+
* on browser globals or DOM APIs.
|
|
70
|
+
*/
|
|
71
|
+
export interface EvolutionHostStopEvent {
|
|
72
|
+
/** Canonical reason that caused the run to stop. */
|
|
73
|
+
reason: EvolutionStopReason;
|
|
74
|
+
/** Maze layout associated with the stopping run. */
|
|
75
|
+
maze: string[];
|
|
76
|
+
/** Number of generations completed before the stop reason fired. */
|
|
77
|
+
completedGenerations: number;
|
|
78
|
+
/** Latest best result available at stop time, when one exists. */
|
|
79
|
+
result?: IMazeRunResult;
|
|
80
|
+
/** Convenience progress mirror from the latest result. */
|
|
81
|
+
progress?: number;
|
|
82
|
+
/** Whether the host should cooperatively enter a paused state. */
|
|
83
|
+
requestHostPause?: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Narrow host adapter used by the engine for pause polling and stop notifications.
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
* Browser-entry and other host boundaries should implement this contract when
|
|
91
|
+
* they need host-specific pause control or solve/stop side effects.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const hostAdapter: EvolutionHostAdapter = {
|
|
96
|
+
* isPauseRequested: () => window.asciiMazePaused === true,
|
|
97
|
+
* handleStop: ({ reason }) => console.log('maze run stopped because', reason),
|
|
98
|
+
* };
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export interface EvolutionHostAdapter {
|
|
102
|
+
/** Return true while the host wants cooperative frame flushing to stay paused. */
|
|
103
|
+
isPauseRequested?: () => boolean;
|
|
104
|
+
/** React to a solved, aborted, or otherwise stopped run. */
|
|
105
|
+
handleStop?: (event: EvolutionHostStopEvent) => void | Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Reporting configuration used to control logging, dashboard updates and UI pacing. */
|
|
109
|
+
export interface IReportingConfig {
|
|
110
|
+
/** How frequently, in generations, to emit logs or telemetry updates. */
|
|
111
|
+
logEvery?: number;
|
|
112
|
+
/** Dashboard manager instance responsible for receiving per-generation updates. */
|
|
113
|
+
dashboardManager: IDashboardManager;
|
|
114
|
+
/** Optional human-readable label identifying this run. */
|
|
115
|
+
label?: string;
|
|
116
|
+
/** When true, yield to the host after each generation. */
|
|
117
|
+
paceEveryGeneration?: boolean;
|
|
118
|
+
/** Optional host adapter that owns pause polling and stop side effects. */
|
|
119
|
+
hostAdapter?: EvolutionHostAdapter;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Main options for running a single maze-evolution experiment. */
|
|
123
|
+
export interface IRunMazeEvolutionOptions {
|
|
124
|
+
mazeConfig: IMazeConfig;
|
|
125
|
+
agentSimConfig: IAgentSimulationConfig;
|
|
126
|
+
evolutionAlgorithmConfig: IEvolutionAlgorithmConfig;
|
|
127
|
+
reportingConfig: IReportingConfig;
|
|
128
|
+
fitnessEvaluator?: FitnessEvaluatorFn;
|
|
129
|
+
cancellation?: { isCancelled: () => boolean };
|
|
130
|
+
signal?: AbortSignal;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Stable result returned by `EvolutionEngine.runMazeEvolution()`.
|
|
135
|
+
*
|
|
136
|
+
* @remarks
|
|
137
|
+
* Browser curriculum code, terminal demos, and tooling should depend on this
|
|
138
|
+
* shared engine-owned contract instead of recreating local runtime result
|
|
139
|
+
* adapters just to read winner carry-over or solve progress.
|
|
140
|
+
*/
|
|
141
|
+
export interface MazeEvolutionRunResult {
|
|
142
|
+
/** Highest-scoring evolved network available at the end of the run. */
|
|
143
|
+
bestNetwork: NetworkInstance | null;
|
|
144
|
+
/** Best simulation result captured during the run, when one exists. */
|
|
145
|
+
bestResult: IMazeRunResult | undefined;
|
|
146
|
+
/** Final NEAT instance after all completed generations. */
|
|
147
|
+
neat: NeatInstance;
|
|
148
|
+
/** Canonical or compatibility exit reason describing why the run ended. */
|
|
149
|
+
exitReason: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Shared curriculum-facing summary derived from one completed evolution phase.
|
|
154
|
+
*
|
|
155
|
+
* @remarks
|
|
156
|
+
* Browser curriculum code and curriculum-style tests should depend on this
|
|
157
|
+
* engine-owned contract so host boundaries do not recreate local refinement or
|
|
158
|
+
* result-interpretation shims when carrying winners across phases.
|
|
159
|
+
*/
|
|
160
|
+
export interface MazeEvolutionCurriculumPhaseOutcome {
|
|
161
|
+
/** Original engine result for callers that still need the underlying run details. */
|
|
162
|
+
result: MazeEvolutionRunResult;
|
|
163
|
+
/** Convenience mirror of the best-run progress percentage for logging or gating. */
|
|
164
|
+
progress: number | undefined;
|
|
165
|
+
/** Whether the phase met the caller's curriculum advancement threshold. */
|
|
166
|
+
solved: boolean;
|
|
167
|
+
/** Refined winner to seed into the next curriculum phase, when one is available. */
|
|
168
|
+
nextBestNetwork: INetwork | undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Type for Neat class instance from the neataptic library. */
|
|
172
|
+
export type NeatInstance = import('../../../../src/neat').default;
|
|
173
|
+
|
|
174
|
+
/** Type for Network class instance from the neataptic library. */
|
|
175
|
+
export type NetworkInstance =
|
|
176
|
+
import('../../../../src/architecture/network').default;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Network instance annotated with telemetry fields during a generation.
|
|
180
|
+
*
|
|
181
|
+
* @remarks
|
|
182
|
+
* This keeps telemetry post-processing and dashboard reporting aligned on one
|
|
183
|
+
* engine-owned contract instead of file-local runtime casts.
|
|
184
|
+
*/
|
|
185
|
+
export interface TrackedNetworkInstance extends NetworkInstance {
|
|
186
|
+
_lastStepOutputs?: Float32Array[];
|
|
187
|
+
_saturationFraction?: number;
|
|
188
|
+
_actionEntropy?: number;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Loose genome shape shared by engine telemetry and population-dynamics helpers.
|
|
193
|
+
*
|
|
194
|
+
* @remarks
|
|
195
|
+
* The NEAT runtime exposes additional mutable fields during evolution, so the
|
|
196
|
+
* engine centralizes those optional members here rather than duplicating local
|
|
197
|
+
* runtime helper interfaces across multiple files.
|
|
198
|
+
*/
|
|
199
|
+
export interface EvolutionGenomeLike {
|
|
200
|
+
nodes?: NetworkNode[];
|
|
201
|
+
connections?: NetworkConnection[];
|
|
202
|
+
score?: number;
|
|
203
|
+
species?: number | null;
|
|
204
|
+
clone?: () => EvolutionGenomeLike;
|
|
205
|
+
mutate?: (method: unknown) => void;
|
|
206
|
+
_lastStepOutputs?: unknown[];
|
|
207
|
+
_id?: number;
|
|
208
|
+
_parentId?: number;
|
|
209
|
+
[key: string]: unknown;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** NEAT runtime shape needed by telemetry helpers that inspect the population. */
|
|
213
|
+
export interface TelemetryNeatLike {
|
|
214
|
+
population?: EvolutionGenomeLike[];
|
|
215
|
+
getTelemetry?: () => unknown;
|
|
216
|
+
[key: string]: unknown;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Mutation-operation surface read from the NEAT driver at runtime. */
|
|
220
|
+
export interface MutationOperationLike {
|
|
221
|
+
length?: number;
|
|
222
|
+
[key: string]: unknown;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Static host used to read optional species-history state from the engine facade. */
|
|
226
|
+
export interface SpeciesHistoryHost {
|
|
227
|
+
_speciesHistory?: unknown[];
|
|
228
|
+
[key: string]: unknown;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Encoded maze representation with cell values. */
|
|
232
|
+
export interface EncodedMaze {
|
|
233
|
+
width: number;
|
|
234
|
+
height: number;
|
|
235
|
+
cells: number[];
|
|
236
|
+
maze: string[];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** 2D position in maze coordinates. */
|
|
240
|
+
export interface Position {
|
|
241
|
+
x: number;
|
|
242
|
+
y: number;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Distance map for maze navigation. */
|
|
246
|
+
export interface DistanceMap {
|
|
247
|
+
width: number;
|
|
248
|
+
height: number;
|
|
249
|
+
distances: number[];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Options object passed to evolution functions. */
|
|
253
|
+
export interface EvolutionOptions {
|
|
254
|
+
cancellation?: {
|
|
255
|
+
isCancelled?: () => boolean;
|
|
256
|
+
isCancellationRequested?: () => boolean;
|
|
257
|
+
reason?: string;
|
|
258
|
+
};
|
|
259
|
+
signal?: AbortSignal;
|
|
260
|
+
maxGenerations?: number;
|
|
261
|
+
maxStagnantGenerations?: number;
|
|
262
|
+
minProgressToPass?: number;
|
|
263
|
+
logEvery?: number;
|
|
264
|
+
enableProfiling?: boolean;
|
|
265
|
+
persistDir?: string;
|
|
266
|
+
persistTopK?: number;
|
|
267
|
+
persistEvery?: number;
|
|
268
|
+
flushToFrame?: () => Promise<void>;
|
|
269
|
+
reportingConfig?: {
|
|
270
|
+
dashboardManager?: IDashboardManager;
|
|
271
|
+
logEvery?: number;
|
|
272
|
+
paceEveryGeneration?: boolean;
|
|
273
|
+
hostAdapter?: EvolutionHostAdapter;
|
|
274
|
+
[key: string]: unknown;
|
|
275
|
+
};
|
|
276
|
+
mazeConfig: {
|
|
277
|
+
maze: string[];
|
|
278
|
+
[key: string]: unknown;
|
|
279
|
+
};
|
|
280
|
+
agentSimConfig?: {
|
|
281
|
+
maxSteps: number;
|
|
282
|
+
[key: string]: unknown;
|
|
283
|
+
};
|
|
284
|
+
lamarckianIterations?: number;
|
|
285
|
+
lamarckianSampleSize?: number;
|
|
286
|
+
dynamicPopEnabled?: boolean;
|
|
287
|
+
dynamicPopMax?: number;
|
|
288
|
+
plateauGenerations?: number;
|
|
289
|
+
dynamicPopExpandInterval?: number;
|
|
290
|
+
dynamicPopExpandFactor?: number;
|
|
291
|
+
dynamicPopPlateauSlack?: number;
|
|
292
|
+
plateauImprovementThreshold?: number;
|
|
293
|
+
simplifyDuration?: number;
|
|
294
|
+
simplifyStrategy?: 'weakWeight' | 'weakRecurrentPreferred';
|
|
295
|
+
simplifyPruneFraction?: number;
|
|
296
|
+
memoryCompactionInterval?: number;
|
|
297
|
+
autoPauseOnSolve?: boolean;
|
|
298
|
+
stopOnlyOnSolve?: boolean;
|
|
299
|
+
initialBestNetwork?: unknown;
|
|
300
|
+
[key: string]: unknown;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Helper functions object passed to evolution loop orchestration. */
|
|
304
|
+
export interface EvolutionHelpers {
|
|
305
|
+
write: (msg: string) => void;
|
|
306
|
+
isProfilingDetailsEnabled: (state: unknown) => boolean;
|
|
307
|
+
getProfilingAccumulators: (state: unknown) => ProfilingAccumulators;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Profiling accumulator structure. */
|
|
311
|
+
export interface ProfilingAccumulators {
|
|
312
|
+
totalEvolveMs?: number;
|
|
313
|
+
totalLamarckMs?: number;
|
|
314
|
+
totalSimMs?: number;
|
|
315
|
+
mutate?: number;
|
|
316
|
+
crossover?: number;
|
|
317
|
+
select?: number;
|
|
318
|
+
snapshot?: number;
|
|
319
|
+
telemetry?: number;
|
|
320
|
+
simplify?: number;
|
|
321
|
+
prune?: number;
|
|
322
|
+
[key: string]: number | undefined;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** Node.js fs module type for file operations. */
|
|
326
|
+
export interface FileSystem {
|
|
327
|
+
writeFileSync: (path: string, data: string) => void;
|
|
328
|
+
readFileSync: (path: string, encoding: string) => string;
|
|
329
|
+
existsSync: (path: string) => boolean;
|
|
330
|
+
mkdirSync: (path: string, options?: { recursive?: boolean }) => void;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Node.js path module type. */
|
|
334
|
+
export interface PathModule {
|
|
335
|
+
join: (...paths: string[]) => string;
|
|
336
|
+
resolve: (...paths: string[]) => string;
|
|
337
|
+
dirname: (path: string) => string;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** Loop helpers returned by prepareLoopHelpers. */
|
|
341
|
+
export interface LoopHelpers {
|
|
342
|
+
flushToFrame: () => Promise<void>;
|
|
343
|
+
fs: unknown;
|
|
344
|
+
path: unknown;
|
|
345
|
+
safeWrite: (msg: string) => void;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** Scratch bundle containing reusable buffers. */
|
|
349
|
+
export interface ScratchBundle {
|
|
350
|
+
samplePool?: unknown[];
|
|
351
|
+
profilingScratch?: Float64Array;
|
|
352
|
+
exps?: Float64Array;
|
|
353
|
+
[key: string]: unknown;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** Snapshot entry for persistence. */
|
|
357
|
+
export interface SnapshotEntry {
|
|
358
|
+
idx?: number;
|
|
359
|
+
json?: string;
|
|
360
|
+
score?: number;
|
|
361
|
+
nodes?: number;
|
|
362
|
+
connections?: number;
|
|
363
|
+
[key: string]: unknown;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** Training constants used by Lamarckian warm-start and refinement helpers. */
|
|
367
|
+
export interface TrainingConstants {
|
|
368
|
+
DEFAULT_TRAIN_ERROR: number;
|
|
369
|
+
DEFAULT_TRAIN_RATE: number;
|
|
370
|
+
DEFAULT_TRAIN_MOMENTUM: number;
|
|
371
|
+
DEFAULT_TRAIN_BATCH_SMALL: number;
|
|
372
|
+
DEFAULT_STD_SMALL: number;
|
|
373
|
+
DEFAULT_STD_ADJUST_MULT: number;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/** Helper functions for evolution. */
|
|
377
|
+
export interface EvolutionLoopHelpers {
|
|
378
|
+
getNodeIndicesByType: (nodes: NetworkNode[], type: string) => number;
|
|
379
|
+
collectHiddenToOutputConns: (
|
|
380
|
+
hiddenNode: NetworkNode,
|
|
381
|
+
nodes: NetworkNode[],
|
|
382
|
+
outputCount: number,
|
|
383
|
+
) => NetworkConnection[];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** Network node representation used by engine-side runtime adaptation helpers. */
|
|
387
|
+
export interface NetworkNode {
|
|
388
|
+
type?: string;
|
|
389
|
+
bias?: number;
|
|
390
|
+
squash?:
|
|
391
|
+
| string
|
|
392
|
+
| { name?: string }
|
|
393
|
+
| ((x: number, derivate?: boolean) => number);
|
|
394
|
+
connections?: {
|
|
395
|
+
in?: NetworkConnection[];
|
|
396
|
+
out?: NetworkConnection[];
|
|
397
|
+
};
|
|
398
|
+
[key: string]: unknown;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** Network connection representation used by engine-side runtime adaptation helpers. */
|
|
402
|
+
export interface NetworkConnection {
|
|
403
|
+
from?: NetworkNode;
|
|
404
|
+
to?: NetworkNode;
|
|
405
|
+
weight?: number;
|
|
406
|
+
gain?: number;
|
|
407
|
+
enabled?: boolean;
|
|
408
|
+
[key: string]: unknown;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** Encoded maze for simulation. */
|
|
412
|
+
export interface EncodedMazeData {
|
|
413
|
+
width: number;
|
|
414
|
+
height: number;
|
|
415
|
+
cells: number[];
|
|
416
|
+
maze?: string[];
|
|
417
|
+
[key: string]: unknown;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/** Position in maze. */
|
|
421
|
+
export interface MazePosition {
|
|
422
|
+
x: number;
|
|
423
|
+
y: number;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/** Distance map for pathfinding. */
|
|
427
|
+
export interface MazeDistanceMap {
|
|
428
|
+
width: number;
|
|
429
|
+
height: number;
|
|
430
|
+
distances: number[];
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/** Ring state for logits tracking. */
|
|
434
|
+
export interface LogitsRingState {
|
|
435
|
+
logitsRingCap: number;
|
|
436
|
+
logitsRingShared: boolean;
|
|
437
|
+
scratchLogitsRingW: number;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/** Simulation result returned by generation evaluation helpers. */
|
|
441
|
+
export interface SimulationResult {
|
|
442
|
+
generationResult: IMazeRunResult;
|
|
443
|
+
simTime: number;
|
|
444
|
+
updatedRingState: LogitsRingState;
|
|
445
|
+
}
|
|
@@ -22,11 +22,6 @@
|
|
|
22
22
|
* @module evolutionEngine/evolutionLoop
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
/** Extended Window interface for maze-specific global state */
|
|
26
|
-
interface MazeWindow extends Window {
|
|
27
|
-
asciiMazePaused?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
25
|
/** Mutable result object with exitReason field */
|
|
31
26
|
interface MutableMazeResult extends IMazeRunResult {
|
|
32
27
|
exitReason?: string;
|
|
@@ -66,13 +61,6 @@ interface EvolutionLoopResult {
|
|
|
66
61
|
};
|
|
67
62
|
}
|
|
68
63
|
|
|
69
|
-
/** Network with dynamic runtime properties */
|
|
70
|
-
interface RuntimeNetworkInstance extends NetworkInstance {
|
|
71
|
-
_lastStepOutputs?: Float32Array[];
|
|
72
|
-
_saturationFraction?: number;
|
|
73
|
-
_actionEntropy?: number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
64
|
/** Simulation result with step outputs */
|
|
77
65
|
interface SimResultWithOutputs extends IMazeRunResult {
|
|
78
66
|
stepOutputs?: number[][];
|
|
@@ -113,20 +101,25 @@ import {
|
|
|
113
101
|
} from './rngAndTiming';
|
|
114
102
|
import type { EngineState } from './engineState';
|
|
115
103
|
import type {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
104
|
+
EvolutionHostAdapter,
|
|
105
|
+
EvolutionStopReason,
|
|
106
|
+
LoopHelpers,
|
|
107
|
+
NetworkConnection,
|
|
119
108
|
NetworkInstance,
|
|
109
|
+
NetworkNode,
|
|
120
110
|
NeatInstance,
|
|
121
|
-
|
|
122
|
-
LoopHelpers,
|
|
111
|
+
ProfilingAccumulators,
|
|
123
112
|
ScratchBundle,
|
|
113
|
+
SimulationResult,
|
|
124
114
|
SnapshotEntry,
|
|
125
|
-
|
|
115
|
+
TrackedNetworkInstance,
|
|
126
116
|
TrainingConstants,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
117
|
+
EvolutionOptions,
|
|
118
|
+
} from './evolutionEngine.types';
|
|
119
|
+
import type {
|
|
120
|
+
IDashboardManager,
|
|
121
|
+
IMazeRunResult,
|
|
122
|
+
INetwork,
|
|
130
123
|
} from '../interfaces';
|
|
131
124
|
|
|
132
125
|
/**
|
|
@@ -235,7 +228,7 @@ export const prepareLoopHelpers = (
|
|
|
235
228
|
scratchBundle: ScratchBundle,
|
|
236
229
|
): LoopHelpers => {
|
|
237
230
|
// Step 1: Create the lightweight host-yield helper first.
|
|
238
|
-
const flushToFrame = makeFlushToFrame();
|
|
231
|
+
const flushToFrame = makeFlushToFrame(opts?.reportingConfig?.hostAdapter);
|
|
239
232
|
|
|
240
233
|
// Step 2: Initialise persistence handles (best-effort; may be null in browsers).
|
|
241
234
|
const { fs, path } = initPersistence(opts?.persistDir);
|
|
@@ -284,8 +277,7 @@ export const prepareLoopHelpers = (
|
|
|
284
277
|
* Side Effects (Best-Effort):
|
|
285
278
|
* - Updates dashboard manager when stopping
|
|
286
279
|
* - Awaits flushToFrame to yield to host
|
|
287
|
-
* -
|
|
288
|
-
* - Dispatches 'asciiMazeSolved' CustomEvent on solve
|
|
280
|
+
* - Reports stop events through the optional host adapter
|
|
289
281
|
* - Annotates `bestResult.exitReason` with canonical reason string
|
|
290
282
|
*
|
|
291
283
|
* Parameters:
|
|
@@ -296,8 +288,9 @@ export const prepareLoopHelpers = (
|
|
|
296
288
|
* @param neat - NEAT driver instance (passed to dashboard update)
|
|
297
289
|
* @param dashboardManager - Optional manager exposing `update(maze, result, network, gen, neat)`
|
|
298
290
|
* @param flushToFrame - Async function to yield to host renderer (e.g. requestAnimationFrame)
|
|
291
|
+
* @param hostAdapter - Optional host adapter that owns host-side stop behavior
|
|
299
292
|
* @param minProgressToPass - Numeric threshold to consider a run 'solved'
|
|
300
|
-
* @param autoPauseOnSolve - When truthy
|
|
293
|
+
* @param autoPauseOnSolve - When truthy request host-side pause handling on solve
|
|
301
294
|
* @param stopOnlyOnSolve - When true ignore stagnation/maxGenerations as stop reasons
|
|
302
295
|
* @param stagnantGenerations - Current count of stagnant generations observed
|
|
303
296
|
* @param maxStagnantGenerations - Max allowed stagnant generations before stopping
|
|
@@ -324,6 +317,7 @@ export const checkStopConditions = async (
|
|
|
324
317
|
neat: NeatInstance,
|
|
325
318
|
dashboardManager: IDashboardManager | undefined,
|
|
326
319
|
flushToFrame: () => Promise<void>,
|
|
320
|
+
hostAdapter: EvolutionHostAdapter | undefined,
|
|
327
321
|
minProgressToPass: number,
|
|
328
322
|
autoPauseOnSolve: boolean,
|
|
329
323
|
stopOnlyOnSolve: boolean,
|
|
@@ -356,29 +350,14 @@ export const checkStopConditions = async (
|
|
|
356
350
|
// Swallow frame flush errors
|
|
357
351
|
}
|
|
358
352
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
detail: {
|
|
368
|
-
maze,
|
|
369
|
-
generations: completedGenerations,
|
|
370
|
-
progress: bestResult?.progress,
|
|
371
|
-
},
|
|
372
|
-
}),
|
|
373
|
-
);
|
|
374
|
-
} catch {
|
|
375
|
-
// Swallow event dispatch errors
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
} catch {
|
|
379
|
-
// Swallow window access errors
|
|
380
|
-
}
|
|
381
|
-
}
|
|
353
|
+
await notifyHostAboutStop(hostAdapter, {
|
|
354
|
+
reason: 'solved',
|
|
355
|
+
maze,
|
|
356
|
+
completedGenerations,
|
|
357
|
+
result: bestResult,
|
|
358
|
+
progress: bestResult?.progress,
|
|
359
|
+
requestHostPause: autoPauseOnSolve,
|
|
360
|
+
});
|
|
382
361
|
|
|
383
362
|
if (hasBest) (bestResult as MutableMazeResult).exitReason = 'solved';
|
|
384
363
|
return 'solved';
|
|
@@ -406,6 +385,14 @@ export const checkStopConditions = async (
|
|
|
406
385
|
} catch {
|
|
407
386
|
// Swallow frame flush errors
|
|
408
387
|
}
|
|
388
|
+
await notifyHostAboutStop(hostAdapter, {
|
|
389
|
+
reason: 'stagnation',
|
|
390
|
+
maze,
|
|
391
|
+
completedGenerations,
|
|
392
|
+
result: bestResult,
|
|
393
|
+
progress: bestResult?.progress,
|
|
394
|
+
requestHostPause: false,
|
|
395
|
+
});
|
|
409
396
|
if (hasBest) (bestResult as MutableMazeResult).exitReason = 'stagnation';
|
|
410
397
|
return 'stagnation';
|
|
411
398
|
}
|
|
@@ -416,6 +403,14 @@ export const checkStopConditions = async (
|
|
|
416
403
|
isFinite(maxGenerations) &&
|
|
417
404
|
completedGenerations >= maxGenerations
|
|
418
405
|
) {
|
|
406
|
+
await notifyHostAboutStop(hostAdapter, {
|
|
407
|
+
reason: 'maxGenerations',
|
|
408
|
+
maze,
|
|
409
|
+
completedGenerations,
|
|
410
|
+
result: bestResult,
|
|
411
|
+
progress: bestResult?.progress,
|
|
412
|
+
requestHostPause: false,
|
|
413
|
+
});
|
|
419
414
|
if (hasBest)
|
|
420
415
|
(bestResult as MutableMazeResult).exitReason = 'maxGenerations';
|
|
421
416
|
return 'maxGenerations';
|
|
@@ -425,6 +420,31 @@ export const checkStopConditions = async (
|
|
|
425
420
|
return undefined;
|
|
426
421
|
};
|
|
427
422
|
|
|
423
|
+
/**
|
|
424
|
+
* Report a concrete stop event through the optional host adapter.
|
|
425
|
+
*
|
|
426
|
+
* @param hostAdapter - Optional host adapter supplied by the embedding host.
|
|
427
|
+
* @param event - Canonical stop event payload.
|
|
428
|
+
* @returns Nothing.
|
|
429
|
+
*/
|
|
430
|
+
const notifyHostAboutStop = async (
|
|
431
|
+
hostAdapter: EvolutionHostAdapter | undefined,
|
|
432
|
+
event: {
|
|
433
|
+
reason: EvolutionStopReason;
|
|
434
|
+
maze: string[];
|
|
435
|
+
completedGenerations: number;
|
|
436
|
+
result?: IMazeRunResult;
|
|
437
|
+
progress?: number;
|
|
438
|
+
requestHostPause?: boolean;
|
|
439
|
+
},
|
|
440
|
+
): Promise<void> => {
|
|
441
|
+
try {
|
|
442
|
+
await hostAdapter?.handleStop?.(event);
|
|
443
|
+
} catch {
|
|
444
|
+
// Host-side effects must never break the engine loop.
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
|
|
428
448
|
/**
|
|
429
449
|
* Persist a population snapshot to disk at the configured interval.
|
|
430
450
|
*
|
|
@@ -1196,7 +1216,7 @@ export const simulateAndPostprocess = (
|
|
|
1196
1216
|
);
|
|
1197
1217
|
|
|
1198
1218
|
// Best-effort: attach legacy buffer refs and compact telemetry onto the genome.
|
|
1199
|
-
const runtimeFittest = fittest as
|
|
1219
|
+
const runtimeFittest = fittest as TrackedNetworkInstance;
|
|
1200
1220
|
try {
|
|
1201
1221
|
if (!runtimeFittest._lastStepOutputs) {
|
|
1202
1222
|
runtimeFittest._lastStepOutputs = scratchLogitsRing;
|
|
@@ -1475,7 +1495,17 @@ export const runEvolutionLoop = async (
|
|
|
1475
1495
|
while (true) {
|
|
1476
1496
|
// Step 1: cooperative cancellation check (non-allocating, safe)
|
|
1477
1497
|
const cancelReason = checkCancellation(opts, bestRunResult);
|
|
1478
|
-
if (cancelReason)
|
|
1498
|
+
if (cancelReason) {
|
|
1499
|
+
await notifyHostAboutStop(opts.reportingConfig?.hostAdapter, {
|
|
1500
|
+
reason: cancelReason as EvolutionStopReason,
|
|
1501
|
+
maze: opts.mazeConfig.maze,
|
|
1502
|
+
completedGenerations,
|
|
1503
|
+
result: bestRunResult,
|
|
1504
|
+
progress: bestRunResult?.progress,
|
|
1505
|
+
requestHostPause: false,
|
|
1506
|
+
});
|
|
1507
|
+
break;
|
|
1508
|
+
}
|
|
1479
1509
|
|
|
1480
1510
|
// Step 2: perform one generation and collect per-stage timings when enabled
|
|
1481
1511
|
const generationOutcome = await runGeneration(
|
|
@@ -1678,6 +1708,7 @@ export const runEvolutionLoop = async (
|
|
|
1678
1708
|
neat,
|
|
1679
1709
|
opts.reportingConfig?.dashboardManager,
|
|
1680
1710
|
flushToFrame,
|
|
1711
|
+
opts.reportingConfig?.hostAdapter,
|
|
1681
1712
|
opts.minProgressToPass ?? 0,
|
|
1682
1713
|
opts.autoPauseOnSolve ?? false,
|
|
1683
1714
|
opts.stopOnlyOnSolve ?? false,
|
|
@@ -24,10 +24,8 @@
|
|
|
24
24
|
import { Network } from '../../../../src/neataptic';
|
|
25
25
|
import { MazeUtils } from '../mazeUtils';
|
|
26
26
|
import { FitnessEvaluator } from '../fitness';
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
IRunMazeEvolutionOptions,
|
|
30
|
-
} from '../interfaces';
|
|
27
|
+
import type { IFitnessEvaluationContext } from '../fitness.types';
|
|
28
|
+
import type { IRunMazeEvolutionOptions } from './evolutionEngine.types';
|
|
31
29
|
import { createNeat, seedInitialPopulation } from './neatConfiguration';
|
|
32
30
|
|
|
33
31
|
/**
|