@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.
Files changed (223) hide show
  1. package/.github/agents/boundary-mapper.agent.md +29 -0
  2. package/.github/agents/docs-scout.agent.md +29 -0
  3. package/.github/agents/plan-scout.agent.md +29 -0
  4. package/.github/agents/solid-split.agent.md +138 -0
  5. package/.github/copilot-instructions.md +103 -0
  6. package/package.json +6 -3
  7. package/plans/ES2023 migration +13 -8
  8. package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
  9. package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
  10. package/plans/Memory_Optimization.md +3 -3
  11. package/plans/README.md +63 -0
  12. package/plans/Roadmap.md +15 -3
  13. package/plans/asciiMaze_SOLID_split.done.md +130 -0
  14. package/plans/flappy_bird_SOLID_split.done.md +67 -0
  15. package/scripts/assets/theme.css +221 -34
  16. package/scripts/copy-examples.mjs +9 -5
  17. package/scripts/export-onnx.mjs +3 -3
  18. package/scripts/generate-bench-tables.mjs +10 -10
  19. package/scripts/generate-bench-tables.ts +10 -10
  20. package/scripts/generate-docs.ts +1415 -449
  21. package/scripts/render-docs-html.ts +15 -8
  22. package/src/README.md +101 -223
  23. package/src/architecture/README.md +57 -185
  24. package/src/architecture/layer/README.md +38 -38
  25. package/src/architecture/network/README.md +33 -31
  26. package/src/architecture/network/activate/README.md +77 -77
  27. package/src/architecture/network/connect/README.md +15 -13
  28. package/src/architecture/network/deterministic/README.md +7 -7
  29. package/src/architecture/network/evolve/README.md +44 -44
  30. package/src/architecture/network/gating/README.md +20 -20
  31. package/src/architecture/network/genetic/README.md +51 -51
  32. package/src/architecture/network/mutate/README.md +97 -97
  33. package/src/architecture/network/onnx/README.md +264 -264
  34. package/src/architecture/network/prune/README.md +39 -39
  35. package/src/architecture/network/remove/README.md +26 -26
  36. package/src/architecture/network/serialize/README.md +56 -56
  37. package/src/architecture/network/slab/README.md +61 -61
  38. package/src/architecture/network/standalone/README.md +24 -24
  39. package/src/architecture/network/stats/README.md +9 -9
  40. package/src/architecture/network/topology/README.md +46 -46
  41. package/src/architecture/network/training/README.md +21 -21
  42. package/src/methods/README.md +9 -87
  43. package/src/multithreading/README.md +8 -77
  44. package/src/multithreading/workers/README.md +2 -2
  45. package/src/multithreading/workers/browser/README.md +0 -6
  46. package/src/multithreading/workers/node/README.md +0 -3
  47. package/src/neat/README.md +562 -568
  48. package/src/utils/README.md +18 -18
  49. package/test/examples/asciiMaze/README.md +59 -59
  50. package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
  51. package/test/examples/asciiMaze/browser-entry/README.md +196 -0
  52. package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
  53. package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
  54. package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
  55. package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
  56. package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
  57. package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
  58. package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
  59. package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
  60. package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
  61. package/test/examples/asciiMaze/browser-entry.ts +10 -576
  62. package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
  63. package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
  64. package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
  65. package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
  66. package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
  67. package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
  68. package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
  69. package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
  70. package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
  71. package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
  72. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
  73. package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
  74. package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
  75. package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
  76. package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
  77. package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
  78. package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
  79. package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
  80. package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
  81. package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
  82. package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
  83. package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
  84. package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
  85. package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
  86. package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
  87. package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
  88. package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
  89. package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
  90. package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
  91. package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
  92. package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
  93. package/test/examples/asciiMaze/fitness.ts +2 -2
  94. package/test/examples/asciiMaze/fitness.types.ts +65 -0
  95. package/test/examples/asciiMaze/interfaces.ts +64 -1352
  96. package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
  97. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
  98. package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
  99. package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
  100. package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
  101. package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
  102. package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
  103. package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
  104. package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
  105. package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
  106. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
  107. package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
  108. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
  109. package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
  110. package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
  111. package/test/examples/flappy_bird/Trace-20260309T191949.json +24124 -0
  112. package/test/examples/flappy_bird/browser-entry/README.md +1129 -0
  113. package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
  114. package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +6 -399
  115. package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +1 -717
  116. package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
  117. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +15 -893
  118. package/test/examples/flappy_bird/browser-entry/host/README.md +307 -0
  119. package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
  120. package/test/examples/flappy_bird/browser-entry/host/host.ts +562 -6
  121. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +274 -0
  122. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +31 -0
  123. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +360 -0
  124. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +117 -0
  125. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +63 -0
  126. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +250 -0
  127. package/test/examples/flappy_bird/browser-entry/network-view/README.md +399 -0
  128. package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +255 -0
  129. package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +802 -7
  130. package/test/examples/flappy_bird/browser-entry/playback/README.md +684 -0
  131. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +277 -0
  132. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +770 -0
  133. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +178 -0
  134. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +107 -0
  135. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +518 -0
  136. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +117 -0
  137. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +233 -0
  138. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +211 -0
  139. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
  140. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +212 -0
  141. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +81 -0
  142. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
  143. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +62 -0
  144. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +244 -0
  145. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
  146. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +68 -0
  147. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
  148. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +310 -0
  149. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +92 -0
  150. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +272 -0
  151. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +39 -0
  152. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +493 -0
  153. package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
  154. package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +4 -0
  155. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +44 -0
  156. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +39 -122
  157. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +272 -0
  158. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +62 -0
  159. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
  160. package/test/examples/flappy_bird/browser-entry/playback/playback.ts +409 -8
  161. package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +4 -12
  162. package/test/examples/flappy_bird/browser-entry/runtime/README.md +235 -0
  163. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +45 -0
  164. package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +81 -0
  165. package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +74 -0
  166. package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
  167. package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +36 -0
  168. package/test/examples/flappy_bird/browser-entry/visualization/README.md +557 -0
  169. package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
  170. package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +957 -19
  171. package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +138 -3
  172. package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +3 -27
  173. package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +1 -23
  174. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +156 -0
  175. package/test/examples/flappy_bird/constants/README.md +1179 -0
  176. package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
  177. package/test/examples/flappy_bird/constants/constants.palette.ts +7 -0
  178. package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
  179. package/test/examples/flappy_bird/environment/README.md +143 -0
  180. package/test/examples/flappy_bird/environment/environment.observation.utils.ts +1 -19
  181. package/test/examples/flappy_bird/environment/environment.step.service.ts +3 -66
  182. package/test/examples/flappy_bird/evaluation/README.md +130 -0
  183. package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +1 -1
  184. package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +5 -375
  185. package/test/examples/flappy_bird/evaluation/rollout/README.md +291 -0
  186. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +30 -0
  187. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +58 -0
  188. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +310 -0
  189. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +56 -0
  190. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +368 -0
  191. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +618 -0
  192. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +7 -7
  193. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +364 -0
  194. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +14 -0
  195. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +4 -201
  196. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +184 -345
  197. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +291 -0
  198. package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +5 -0
  199. package/test/examples/flappy_bird/simulation-shared/README.md +417 -0
  200. package/test/examples/flappy_bird/simulation-shared/observation/README.md +183 -0
  201. package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +301 -0
  202. package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +9 -0
  203. package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +59 -0
  204. package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +5 -403
  205. package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +20 -6
  206. package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +23 -8
  207. package/test/examples/flappy_bird/trainer/README.md +563 -0
  208. package/test/examples/flappy_bird/trainer/evaluation/README.md +199 -0
  209. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +9 -0
  210. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +73 -0
  211. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +165 -0
  212. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +25 -0
  213. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +161 -0
  214. package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
  215. package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
  216. package/test/examples/flappy_bird/trainer/trainer.report.service.ts +126 -0
  217. package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
  218. package/test/examples/flappy_bird/trainer/trainer.ts +11 -553
  219. package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
  220. package/test/examples/flappy_bird/environment/environment.ts +0 -7
  221. package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
  222. package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
  223. package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
@@ -0,0 +1,181 @@
1
+ import {
2
+ evaluateFlappyFitnessAcrossSeeds,
3
+ rolloutEpisode,
4
+ type FlappyRolloutOptions,
5
+ type FlappySeedBatchEvaluation,
6
+ } from '../flappyEvaluation';
7
+ import {
8
+ FLAPPY_TRAINER_DUMMY_FLAP_OUTPUT,
9
+ FLAPPY_TRAINER_DUMMY_NETWORK_ID,
10
+ FLAPPY_TRAINER_DUMMY_NO_FLAP_OUTPUT,
11
+ } from './trainer.constants';
12
+ import type { FlappyTrainerNetwork } from './trainer.types';
13
+
14
+ /**
15
+ * Aggregate and representative rollout resolved for the best genome.
16
+ *
17
+ * Keeping these values together lets the report facade stay focused on
18
+ * orchestration while this helper module owns cache fallback behavior.
19
+ */
20
+ export interface ResolvedBestGenerationDetails {
21
+ bestAggregate: FlappySeedBatchEvaluation;
22
+ bestEpisode: ReturnType<typeof rolloutEpisode>;
23
+ }
24
+
25
+ /**
26
+ * Collects only finite scores from the current population.
27
+ *
28
+ * Unevaluated or invalid scores are intentionally skipped so percentile and
29
+ * standard deviation calculations operate on stable numeric inputs only.
30
+ *
31
+ * @param population - Current population.
32
+ * @returns Finite scores in population order.
33
+ * @example
34
+ * ```ts
35
+ * const scores = collectFiniteGenomeScores(population);
36
+ * ```
37
+ */
38
+ export function collectFiniteGenomeScores(
39
+ population: readonly FlappyTrainerNetwork[],
40
+ ): number[] {
41
+ const finiteScores: number[] = [];
42
+
43
+ for (const genome of population) {
44
+ const genomeScore = genome.score ?? Number.NEGATIVE_INFINITY;
45
+ if (Number.isFinite(genomeScore)) {
46
+ finiteScores.push(genomeScore);
47
+ }
48
+ }
49
+
50
+ return finiteScores;
51
+ }
52
+
53
+ /**
54
+ * Resolves cached or fallback best-of-generation details for reporting.
55
+ *
56
+ * The report layer needs both aggregate seed statistics and one representative
57
+ * episode. This helper centralizes the fallback rules so the service facade can
58
+ * remain a thin orchestration layer.
59
+ *
60
+ * @param population - Current population.
61
+ * @param bestGenome - Genome selected as generation best.
62
+ * @param aggregateByGenome - Cached aggregate evaluations keyed by genome.
63
+ * @param fallbackSeeds - Seeds used when the aggregate must be recomputed.
64
+ * @param fallbackRolloutOptions - Rollout options for fallback evaluation.
65
+ * @returns Aggregate metrics and a representative best-genome episode.
66
+ * @example
67
+ * ```ts
68
+ * const { bestAggregate, bestEpisode } = resolveBestGenerationDetails(
69
+ * population,
70
+ * bestGenome,
71
+ * aggregateByGenome,
72
+ * reevaluationSeeds,
73
+ * reevaluationRolloutOptions,
74
+ * );
75
+ * ```
76
+ */
77
+ export function resolveBestGenerationDetails(
78
+ population: readonly FlappyTrainerNetwork[],
79
+ bestGenome: FlappyTrainerNetwork | undefined,
80
+ aggregateByGenome: ReadonlyMap<
81
+ FlappyTrainerNetwork,
82
+ FlappySeedBatchEvaluation
83
+ >,
84
+ fallbackSeeds: readonly number[],
85
+ fallbackRolloutOptions: FlappyRolloutOptions,
86
+ ): ResolvedBestGenerationDetails {
87
+ return {
88
+ bestAggregate: resolveBestAggregate(
89
+ population,
90
+ bestGenome,
91
+ aggregateByGenome,
92
+ fallbackSeeds,
93
+ fallbackRolloutOptions,
94
+ ),
95
+ bestEpisode: resolveBestEpisode(
96
+ population,
97
+ bestGenome,
98
+ fallbackSeeds,
99
+ fallbackRolloutOptions,
100
+ ),
101
+ };
102
+ }
103
+
104
+ function resolveBestAggregate(
105
+ population: readonly FlappyTrainerNetwork[],
106
+ bestGenome: FlappyTrainerNetwork | undefined,
107
+ aggregateByGenome: ReadonlyMap<
108
+ FlappyTrainerNetwork,
109
+ FlappySeedBatchEvaluation
110
+ >,
111
+ fallbackSeeds: readonly number[],
112
+ fallbackRolloutOptions: FlappyRolloutOptions,
113
+ ): FlappySeedBatchEvaluation {
114
+ const fallbackGenome = resolveFallbackGenome(population, bestGenome);
115
+ if (!fallbackGenome) {
116
+ return buildEmptySeedBatchEvaluation();
117
+ }
118
+
119
+ const cachedAggregate = aggregateByGenome.get(fallbackGenome);
120
+ if (cachedAggregate) {
121
+ return cachedAggregate;
122
+ }
123
+
124
+ return evaluateFlappyFitnessAcrossSeeds(
125
+ fallbackGenome,
126
+ fallbackSeeds,
127
+ fallbackRolloutOptions,
128
+ );
129
+ }
130
+
131
+ function resolveBestEpisode(
132
+ population: readonly FlappyTrainerNetwork[],
133
+ bestGenome: FlappyTrainerNetwork | undefined,
134
+ fallbackSeeds: readonly number[],
135
+ fallbackRolloutOptions: FlappyRolloutOptions,
136
+ ): ReturnType<typeof rolloutEpisode> {
137
+ const fallbackGenome = resolveFallbackGenome(population, bestGenome);
138
+ if (!fallbackGenome) {
139
+ return rolloutEpisode(resolveDummyNetwork(), fallbackRolloutOptions);
140
+ }
141
+
142
+ const episodeSeed = fallbackSeeds[0];
143
+ return rolloutEpisode(fallbackGenome, {
144
+ ...fallbackRolloutOptions,
145
+ seed: episodeSeed,
146
+ });
147
+ }
148
+
149
+ function resolveFallbackGenome(
150
+ population: readonly FlappyTrainerNetwork[],
151
+ bestGenome: FlappyTrainerNetwork | undefined,
152
+ ): FlappyTrainerNetwork | undefined {
153
+ return bestGenome ?? population[0];
154
+ }
155
+
156
+ function buildEmptySeedBatchEvaluation(): FlappySeedBatchEvaluation {
157
+ return {
158
+ seedCount: 0,
159
+ meanFitness: 0,
160
+ medianFitness: 0,
161
+ p90Fitness: 0,
162
+ fitnessStdDev: 0,
163
+ robustFitness: 0,
164
+ meanPipesPassed: 0,
165
+ meanFramesSurvived: 0,
166
+ };
167
+ }
168
+
169
+ function resolveDummyNetwork(): FlappyTrainerNetwork {
170
+ return {
171
+ activate: activateWithoutFlap,
172
+ _id: FLAPPY_TRAINER_DUMMY_NETWORK_ID,
173
+ };
174
+ }
175
+
176
+ function activateWithoutFlap(): number[] {
177
+ return [
178
+ FLAPPY_TRAINER_DUMMY_NO_FLAP_OUTPUT,
179
+ FLAPPY_TRAINER_DUMMY_FLAP_OUTPUT,
180
+ ];
181
+ }
@@ -0,0 +1,126 @@
1
+ import {
2
+ rolloutEpisode,
3
+ type FlappySeedBatchEvaluation,
4
+ } from '../flappyEvaluation';
5
+ import {
6
+ FLAPPY_TRAINER_LOG_PARTS_DELIMITER,
7
+ FLAPPY_TRAINER_SCORE_MEDIAN_PERCENTILE,
8
+ FLAPPY_TRAINER_SCORE_P90_PERCENTILE,
9
+ } from './trainer.constants';
10
+ import type { FlappyMutationSchedule } from './trainer.evaluation-plan.utils';
11
+ import {
12
+ collectFiniteGenomeScores,
13
+ resolveBestGenerationDetails,
14
+ } from './trainer.report.service.services';
15
+ import { buildGenerationLogParts } from './trainer.reporting.utils';
16
+ import { resolveBestGenomeByScore } from './trainer.selection.utils';
17
+ import {
18
+ computeMean,
19
+ computePercentile,
20
+ computePopulationStandardDeviation,
21
+ } from '../flappy.simulation.shared.utils';
22
+ import type {
23
+ FlappyGenerationEvaluationPlan,
24
+ FlappyGenerationReport,
25
+ FlappyTrainerNetwork,
26
+ } from './trainer.types';
27
+
28
+ /**
29
+ * Builds a compact report for the current generation.
30
+ *
31
+ * @param population - Current population.
32
+ * @param aggregateByGenome - Aggregate evaluation results keyed by genome.
33
+ * @param generationEvaluationPlan - Per-generation staged evaluation plan.
34
+ * @returns Aggregated generation report.
35
+ */
36
+ export function buildGenerationReport(
37
+ population: readonly FlappyTrainerNetwork[],
38
+ aggregateByGenome: ReadonlyMap<
39
+ FlappyTrainerNetwork,
40
+ FlappySeedBatchEvaluation
41
+ >,
42
+ generationEvaluationPlan: FlappyGenerationEvaluationPlan,
43
+ ): FlappyGenerationReport {
44
+ // Step 1: Collect stable numeric inputs for distribution statistics.
45
+ const finalScores = collectFiniteGenomeScores(population);
46
+ const scoreMean = computeMean(finalScores);
47
+ const scoreStdDev = computePopulationStandardDeviation(
48
+ finalScores,
49
+ scoreMean,
50
+ );
51
+
52
+ // Step 2: Resolve best-genome derived metrics through the report helper boundary.
53
+ const bestGenome = resolveBestGenomeByScore(population);
54
+ const { bestAggregate, bestEpisode } = resolveBestGenerationDetails(
55
+ population,
56
+ bestGenome,
57
+ aggregateByGenome,
58
+ generationEvaluationPlan.reevaluationSeeds,
59
+ generationEvaluationPlan.reevaluationRolloutOptions,
60
+ );
61
+
62
+ // Step 3: Fold the resolved metrics into the compact generation report.
63
+ return {
64
+ generationIndex: generationEvaluationPlan.generationIndex,
65
+ difficultyScale: generationEvaluationPlan.difficultyScale,
66
+ mutationRate: generationEvaluationPlan.mutationRate,
67
+ mutationAmount: generationEvaluationPlan.mutationAmount,
68
+ quickSeedCount: generationEvaluationPlan.quickSeeds.length,
69
+ fullSeedCount: generationEvaluationPlan.fullSeeds.length,
70
+ reevaluationSeedCount: generationEvaluationPlan.reevaluationSeeds.length,
71
+ evaluatedPopulationSize: population.length,
72
+ scoreMean,
73
+ scoreMedian: computePercentile(
74
+ finalScores,
75
+ FLAPPY_TRAINER_SCORE_MEDIAN_PERCENTILE,
76
+ ),
77
+ scoreP90: computePercentile(
78
+ finalScores,
79
+ FLAPPY_TRAINER_SCORE_P90_PERCENTILE,
80
+ ),
81
+ scoreStdDev,
82
+ bestRobustFitness: bestGenome?.score ?? Number.NaN,
83
+ bestMeanFitness: bestAggregate.meanFitness,
84
+ bestPipesPassed: bestEpisode.pipesPassed,
85
+ bestFramesSurvived: bestEpisode.framesSurvived,
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Emits one compact generation log line.
91
+ *
92
+ * @param generationLabel - Current generation label.
93
+ * @param mutationSchedule - Active mutation schedule.
94
+ * @param report - Optional aggregated generation report.
95
+ * @param fittestGenome - Fittest genome returned by the NEAT controller.
96
+ * @param fallbackEpisode - Fallback representative rollout episode.
97
+ * @returns Nothing.
98
+ */
99
+ export function logGenerationSummary(
100
+ generationLabel: number,
101
+ mutationSchedule: FlappyMutationSchedule,
102
+ report: FlappyGenerationReport | undefined,
103
+ fittestGenome: FlappyTrainerNetwork,
104
+ fallbackEpisode: ReturnType<typeof rolloutEpisode>,
105
+ ): void {
106
+ const bestFitness =
107
+ report?.bestRobustFitness ??
108
+ (fittestGenome.score as number) ??
109
+ fallbackEpisode.fitness;
110
+ const bestPipesPassed =
111
+ report?.bestPipesPassed ?? fallbackEpisode.pipesPassed;
112
+ const bestFramesSurvived =
113
+ report?.bestFramesSurvived ?? fallbackEpisode.framesSurvived;
114
+
115
+ const logParts = buildGenerationLogParts(
116
+ generationLabel,
117
+ bestFitness,
118
+ bestPipesPassed,
119
+ bestFramesSurvived,
120
+ report,
121
+ mutationSchedule,
122
+ );
123
+
124
+ // eslint-disable-next-line no-console
125
+ console.log(logParts.join(FLAPPY_TRAINER_LOG_PARTS_DELIMITER));
126
+ }
@@ -0,0 +1,89 @@
1
+ import type { FlappyTrainerNetwork, ScoredGenomeEntry } from './trainer.types';
2
+
3
+ /**
4
+ * Returns top genomes ordered by current provisional score.
5
+ *
6
+ * @param population - Current trainer population.
7
+ * @param provisionalScoresByGenome - Optional map of staged provisional scores.
8
+ * @param targetCount - Maximum number of genomes to return.
9
+ * @returns Highest-scoring genomes in descending score order.
10
+ */
11
+ export function selectTopGenomesByScore(
12
+ population: readonly FlappyTrainerNetwork[],
13
+ provisionalScoresByGenome: ReadonlyMap<FlappyTrainerNetwork, number>,
14
+ targetCount: number,
15
+ ): FlappyTrainerNetwork[] {
16
+ const scoredEntries = buildScoredGenomeEntries(
17
+ population,
18
+ provisionalScoresByGenome,
19
+ );
20
+
21
+ scoredEntries.sort(compareScoredGenomeEntriesDescending);
22
+
23
+ const selectedGenomes: FlappyTrainerNetwork[] = [];
24
+ const maximumSelectionCount = Math.max(
25
+ 0,
26
+ Math.min(targetCount, scoredEntries.length),
27
+ );
28
+
29
+ let selectedIndex = 0;
30
+ while (selectedIndex < maximumSelectionCount) {
31
+ const scoredEntry = scoredEntries[selectedIndex];
32
+ if (scoredEntry) {
33
+ selectedGenomes.push(scoredEntry.genome);
34
+ }
35
+ selectedIndex += 1;
36
+ }
37
+
38
+ return selectedGenomes;
39
+ }
40
+
41
+ /**
42
+ * Resolves the best genome by current score.
43
+ *
44
+ * @param population - Current trainer population.
45
+ * @returns Highest-scoring genome or `undefined` when population is empty.
46
+ */
47
+ export function resolveBestGenomeByScore(
48
+ population: readonly FlappyTrainerNetwork[],
49
+ ): FlappyTrainerNetwork | undefined {
50
+ const scoredGenomes = buildScoredGenomeEntries(population, undefined);
51
+ scoredGenomes.sort(compareScoredGenomeEntriesDescending);
52
+ return scoredGenomes[0]?.genome;
53
+ }
54
+
55
+ function buildScoredGenomeEntries(
56
+ population: readonly FlappyTrainerNetwork[],
57
+ provisionalScoresByGenome:
58
+ | ReadonlyMap<FlappyTrainerNetwork, number>
59
+ | undefined,
60
+ ): ScoredGenomeEntry[] {
61
+ const scoredEntries: ScoredGenomeEntry[] = [];
62
+
63
+ for (const genome of population) {
64
+ const score = resolveGenomeScore(genome, provisionalScoresByGenome);
65
+ scoredEntries.push({ genome, score });
66
+ }
67
+
68
+ return scoredEntries;
69
+ }
70
+
71
+ function resolveGenomeScore(
72
+ genome: FlappyTrainerNetwork,
73
+ provisionalScoresByGenome:
74
+ | ReadonlyMap<FlappyTrainerNetwork, number>
75
+ | undefined,
76
+ ): number {
77
+ if (provisionalScoresByGenome) {
78
+ return provisionalScoresByGenome.get(genome) ?? Number.NEGATIVE_INFINITY;
79
+ }
80
+
81
+ return genome.score ?? Number.NEGATIVE_INFINITY;
82
+ }
83
+
84
+ function compareScoredGenomeEntriesDescending(
85
+ leftEntry: ScoredGenomeEntry,
86
+ rightEntry: ScoredGenomeEntry,
87
+ ): number {
88
+ return rightEntry.score - leftEntry.score;
89
+ }