@reicek/neataptic-ts 0.1.24 → 0.1.26

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 (215) hide show
  1. package/.github/copilot-instructions.md +11 -0
  2. package/.github/skills/trace-analyzer-extension/SKILL.md +3 -3
  3. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
  4. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
  5. package/.github/skills/trace-audit-reporting/SKILL.md +3 -3
  6. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
  7. package/.github/workflows/ci.yml +3 -3
  8. package/.github/workflows/deploy-pages.yml +6 -6
  9. package/.github/workflows/manual_release_pipeline.yml +3 -3
  10. package/.github/workflows/publish.yml +18 -19
  11. package/.github/workflows/release_dispatch.yml +3 -3
  12. package/package.json +26 -20
  13. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +4 -4
  14. package/plans/README.md +24 -0
  15. package/plans/Roadmap.md +62 -40
  16. package/plans/analyze-trace-solid-split.plans.md +66 -0
  17. package/plans/architecture-solid-split.plans.md +9 -15
  18. package/plans/asciiMaze-typescript-repair.plans.md +1 -1
  19. package/plans/generate-docs-solid-split.plans.md +87 -0
  20. package/plans/methods-docs.plans.md +25 -1
  21. package/plans/methods-solid-split.plans.md +14 -14
  22. package/plans/neat-docs.plans.md +9 -1
  23. package/plans/neat-test-surface-repair.plans.md +1 -1
  24. package/plans/render-docs-html-solid-split.plans.md +68 -0
  25. package/plans/src-no-explicit-any-cleanup.plans.md +1 -1
  26. package/plans/utils-docs.plans.md +6 -1
  27. package/scripts/analyze-trace/analyze-trace.analysis.ts +479 -0
  28. package/scripts/analyze-trace/analyze-trace.constants.ts +35 -0
  29. package/scripts/analyze-trace/analyze-trace.io.ts +69 -0
  30. package/scripts/analyze-trace/analyze-trace.report.ts +100 -0
  31. package/scripts/analyze-trace/analyze-trace.shared.ts +116 -0
  32. package/scripts/analyze-trace/analyze-trace.ts +45 -0
  33. package/scripts/analyze-trace/analyze-trace.types.ts +72 -0
  34. package/scripts/assets/theme.css +80 -23
  35. package/scripts/copy-examples.ts +239 -0
  36. package/scripts/export-onnx.ts +223 -0
  37. package/scripts/generate-bench-tables.ts +378 -37
  38. package/scripts/generate-docs/generate-docs.constants.ts +107 -0
  39. package/scripts/generate-docs/generate-docs.order.ts +355 -0
  40. package/scripts/generate-docs/generate-docs.state.ts +31 -0
  41. package/scripts/generate-docs/generate-docs.targets.ts +165 -0
  42. package/scripts/generate-docs/generate-docs.ts +63 -0
  43. package/scripts/generate-docs/generate-docs.types.ts +112 -0
  44. package/scripts/generate-docs/output/generate-docs.output.folder-index.utils.ts +167 -0
  45. package/scripts/generate-docs/output/generate-docs.output.ordering.utils.ts +353 -0
  46. package/scripts/generate-docs/output/generate-docs.output.readme.utils.ts +420 -0
  47. package/scripts/generate-docs/output/generate-docs.output.ts +123 -0
  48. package/scripts/generate-docs/output/generate-docs.output.warnings.utils.ts +219 -0
  49. package/scripts/generate-docs/symbols/generate-docs.symbols.collection.utils.ts +365 -0
  50. package/scripts/generate-docs/symbols/generate-docs.symbols.jsdoc.utils.ts +373 -0
  51. package/scripts/generate-docs/symbols/generate-docs.symbols.normalize.utils.ts +155 -0
  52. package/scripts/generate-docs/symbols/generate-docs.symbols.render.utils.ts +149 -0
  53. package/scripts/generate-docs/symbols/generate-docs.symbols.signature.utils.ts +289 -0
  54. package/scripts/generate-docs/symbols/generate-docs.symbols.ts +11 -0
  55. package/scripts/mermaid-cli.mjs +102 -22
  56. package/scripts/mermaid-cli.ts +736 -0
  57. package/scripts/render-docs-html/render-docs-html.assets.ts +54 -0
  58. package/scripts/render-docs-html/render-docs-html.mermaid.ts +245 -0
  59. package/scripts/{render-docs-html.sidebar.ts → render-docs-html/render-docs-html.navigation.ts} +141 -144
  60. package/scripts/render-docs-html/render-docs-html.pages.ts +333 -0
  61. package/scripts/render-docs-html/render-docs-html.shared.ts +333 -0
  62. package/scripts/render-docs-html/render-docs-html.types.ts +42 -0
  63. package/scripts/render-docs-html.ts +23 -587
  64. package/scripts/run-docs.ts +238 -0
  65. package/scripts/write-dist-docs-pkg.ts +40 -0
  66. package/src/README.md +75 -75
  67. package/src/architecture/connection/README.md +5 -5
  68. package/src/architecture/layer/README.md +508 -508
  69. package/src/architecture/network/README.md +1458 -1458
  70. package/src/architecture/network/activate/README.md +694 -694
  71. package/src/architecture/network/bootstrap/README.md +77 -77
  72. package/src/architecture/network/connect/README.md +74 -74
  73. package/src/architecture/network/deterministic/README.md +135 -135
  74. package/src/architecture/network/evolve/README.md +364 -364
  75. package/src/architecture/network/gating/README.md +130 -130
  76. package/src/architecture/network/genetic/README.md +399 -399
  77. package/src/architecture/network/mutate/README.md +897 -897
  78. package/src/architecture/network/onnx/README.md +720 -720
  79. package/src/architecture/network/onnx/export/README.md +728 -728
  80. package/src/architecture/network/onnx/export/layers/README.md +450 -450
  81. package/src/architecture/network/onnx/import/README.md +618 -618
  82. package/src/architecture/network/onnx/schema/README.md +32 -32
  83. package/src/architecture/network/prune/README.md +245 -245
  84. package/src/architecture/network/remove/README.md +135 -135
  85. package/src/architecture/network/runtime/README.md +106 -106
  86. package/src/architecture/network/serialize/README.md +542 -542
  87. package/src/architecture/network/slab/README.md +608 -608
  88. package/src/architecture/network/standalone/README.md +212 -212
  89. package/src/architecture/network/stats/README.md +84 -84
  90. package/src/architecture/network/topology/README.md +465 -465
  91. package/src/architecture/network/training/README.md +200 -200
  92. package/src/architecture/node/README.md +5 -5
  93. package/src/architecture/nodePool/README.md +14 -14
  94. package/src/methods/README.md +99 -99
  95. package/src/methods/activation/README.md +189 -189
  96. package/src/methods/cost/README.md +131 -131
  97. package/src/methods/rate/README.md +86 -86
  98. package/src/multithreading/README.md +77 -77
  99. package/src/multithreading/workers/browser/README.md +8 -8
  100. package/src/multithreading/workers/node/README.md +8 -8
  101. package/src/neat/README.md +148 -148
  102. package/src/neat/adaptive/README.md +120 -120
  103. package/src/neat/adaptive/acceptance/README.md +40 -40
  104. package/src/neat/adaptive/complexity/README.md +137 -137
  105. package/src/neat/adaptive/core/README.md +197 -197
  106. package/src/neat/adaptive/lineage/README.md +90 -90
  107. package/src/neat/adaptive/mutation/README.md +284 -284
  108. package/src/neat/compat/README.md +43 -43
  109. package/src/neat/compat/core/README.md +90 -90
  110. package/src/neat/diversity/README.md +35 -35
  111. package/src/neat/diversity/core/README.md +88 -88
  112. package/src/neat/evaluate/README.md +85 -85
  113. package/src/neat/evaluate/auto-distance/README.md +75 -75
  114. package/src/neat/evaluate/entropy-compat/README.md +37 -37
  115. package/src/neat/evaluate/entropy-sharing/README.md +43 -43
  116. package/src/neat/evaluate/fitness/README.md +23 -23
  117. package/src/neat/evaluate/novelty/README.md +120 -120
  118. package/src/neat/evaluate/objectives/README.md +17 -17
  119. package/src/neat/evaluate/shared/README.md +94 -94
  120. package/src/neat/evolve/README.md +96 -96
  121. package/src/neat/evolve/adaptive/README.md +60 -60
  122. package/src/neat/evolve/objectives/README.md +63 -63
  123. package/src/neat/evolve/offspring/README.md +56 -56
  124. package/src/neat/evolve/population/README.md +171 -171
  125. package/src/neat/evolve/runtime/README.md +79 -79
  126. package/src/neat/evolve/speciation/README.md +74 -74
  127. package/src/neat/evolve/warnings/README.md +10 -10
  128. package/src/neat/export/README.md +114 -114
  129. package/src/neat/helpers/README.md +50 -50
  130. package/src/neat/init/README.md +9 -9
  131. package/src/neat/lineage/core/README.md +101 -101
  132. package/src/neat/multiobjective/category/README.md +74 -74
  133. package/src/neat/multiobjective/crowding/README.md +272 -272
  134. package/src/neat/multiobjective/dominance/README.md +171 -171
  135. package/src/neat/multiobjective/fronts/README.md +68 -68
  136. package/src/neat/multiobjective/metrics/README.md +43 -43
  137. package/src/neat/multiobjective/objectives/README.md +31 -31
  138. package/src/neat/multiobjective/shared/README.md +27 -27
  139. package/src/neat/mutation/README.md +97 -97
  140. package/src/neat/mutation/add-conn/README.md +115 -115
  141. package/src/neat/mutation/add-node/README.md +126 -126
  142. package/src/neat/mutation/flow/README.md +149 -149
  143. package/src/neat/mutation/repair/README.md +185 -185
  144. package/src/neat/mutation/select/README.md +117 -117
  145. package/src/neat/mutation/shared/README.md +32 -32
  146. package/src/neat/objectives/README.md +25 -25
  147. package/src/neat/objectives/core/README.md +67 -67
  148. package/src/neat/pruning/README.md +40 -40
  149. package/src/neat/pruning/core/README.md +171 -171
  150. package/src/neat/pruning/facade/README.md +32 -32
  151. package/src/neat/rng/README.md +104 -104
  152. package/src/neat/rng/core/README.md +137 -137
  153. package/src/neat/rng/facade/README.md +50 -50
  154. package/src/neat/selection/README.md +111 -111
  155. package/src/neat/selection/core/README.md +227 -227
  156. package/src/neat/selection/facade/README.md +61 -61
  157. package/src/neat/shared/README.md +163 -163
  158. package/src/neat/speciation/README.md +31 -31
  159. package/src/neat/speciation/threshold/README.md +35 -35
  160. package/src/neat/species/README.md +25 -25
  161. package/src/neat/species/core/README.md +20 -20
  162. package/src/neat/species/core/shared/README.md +18 -18
  163. package/src/neat/species/history/context/README.md +22 -22
  164. package/src/neat/telemetry/accessors/README.md +58 -58
  165. package/src/neat/telemetry/exports/README.md +233 -233
  166. package/src/neat/telemetry/facade/README.md +252 -252
  167. package/src/neat/telemetry/facade/archive/README.md +57 -57
  168. package/src/neat/telemetry/facade/buffer/README.md +43 -43
  169. package/src/neat/telemetry/facade/lineage/README.md +12 -12
  170. package/src/neat/telemetry/facade/objectives/README.md +44 -44
  171. package/src/neat/telemetry/facade/runtime/README.md +26 -26
  172. package/src/neat/telemetry/facade/species/README.md +27 -27
  173. package/src/neat/telemetry/metrics/README.md +696 -696
  174. package/src/neat/telemetry/recorder/README.md +57 -57
  175. package/src/neat/telemetry/types/README.md +32 -32
  176. package/src/neat/topology-intent/README.md +75 -75
  177. package/src/utils/README.md +193 -193
  178. package/test/examples/asciiMaze/browser-entry/README.md +92 -92
  179. package/test/examples/asciiMaze/dashboardManager/README.md +109 -109
  180. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +28 -28
  181. package/test/examples/asciiMaze/evolutionEngine/README.md +1527 -1527
  182. package/test/examples/asciiMaze/mazeMovement/README.md +105 -105
  183. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +16 -16
  184. package/test/examples/asciiMaze/mazeMovement/policy/README.md +57 -57
  185. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +52 -52
  186. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +46 -46
  187. package/test/examples/flappy_bird/browser-entry/README.md +508 -508
  188. package/test/examples/flappy_bird/browser-entry/host/README.md +101 -101
  189. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +144 -144
  190. package/test/examples/flappy_bird/browser-entry/network-view/README.md +194 -194
  191. package/test/examples/flappy_bird/browser-entry/playback/README.md +278 -278
  192. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +129 -129
  193. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +502 -502
  194. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +139 -139
  195. package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +10 -10
  196. package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +43 -43
  197. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +30 -30
  198. package/test/examples/flappy_bird/browser-entry/runtime/README.md +59 -59
  199. package/test/examples/flappy_bird/browser-entry/visualization/README.md +276 -276
  200. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +16 -16
  201. package/test/examples/flappy_bird/constants/README.md +1070 -1070
  202. package/test/examples/flappy_bird/environment/README.md +22 -22
  203. package/test/examples/flappy_bird/evaluation/README.md +32 -32
  204. package/test/examples/flappy_bird/evaluation/rollout/README.md +141 -141
  205. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +425 -425
  206. package/test/examples/flappy_bird/simulation-shared/README.md +170 -170
  207. package/test/examples/flappy_bird/simulation-shared/observation/README.md +109 -109
  208. package/test/examples/flappy_bird/trainer/README.md +325 -325
  209. package/test/examples/flappy_bird/trainer/evaluation/README.md +74 -74
  210. package/scripts/analyze-trace.ts +0 -590
  211. package/scripts/copy-examples.mjs +0 -114
  212. package/scripts/export-onnx.mjs +0 -86
  213. package/scripts/generate-bench-tables.mjs +0 -182
  214. package/scripts/generate-docs.ts +0 -2900
  215. package/scripts/write-dist-docs-pkg.mjs +0 -16
@@ -43,49 +43,35 @@ from or why descriptor order must stay fixed.
43
43
 
44
44
  ## neat/multiobjective/dominance/multiobjective.dominance.ts
45
45
 
46
- ### vectorDominates
46
+ ### applyPairwiseDominance
47
47
 
48
48
  ```ts
49
- vectorDominates(
50
- valuesA: number[],
51
- valuesB: number[],
49
+ applyPairwiseDominance(
50
+ dominanceState: DominanceState,
51
+ valuesMatrixInput: number[][],
52
52
  descriptors: ObjectiveDescriptor[],
53
- ): boolean
53
+ candidateIndex: number,
54
+ opponentIndex: number,
55
+ ): void
54
56
  ```
55
57
 
56
- Determines whether vector A Pareto-dominates vector B.
57
-
58
- A dominates B iff:
59
- - A is **no worse** than B in every objective (respecting each objective’s
60
- direction: maximize/minimize), and
61
- - A is **strictly better** in at least one objective.
58
+ Applies a single pairwise dominance update between candidate and opponent.
62
59
 
63
- This helper is deliberately pair-local. It does not mutate bookkeeping or
64
- know anything about fronts; it only answers the comparison question that the
65
- wider bookkeeping pass repeats across every pair of matrix rows.
60
+ If the candidate dominates the opponent, the opponent index is appended to
61
+ `dominatedIndicesByIndex[candidateIndex]`. If the candidate is dominated by
62
+ the opponent, `dominationCounts[candidateIndex]` is incremented.
66
63
 
67
- Assumptions:
68
- - `valuesA` and `valuesB` are aligned and have the same length.
69
- - `descriptors` provides a descriptor for each objective index.
70
- - If a descriptor has no `direction`, it defaults to `'max'`.
64
+ That asymmetry is the key bookkeeping contract for the later frontier peel:
65
+ - the count answers whether the candidate can join the current front yet,
66
+ - the dominated-neighbor list tells later passes which counts to relax once
67
+ the candidate is removed as a blocker.
71
68
 
72
69
  Parameters:
73
- - `valuesA` - - Objective values for candidate A.
74
- - `valuesB` - - Objective values for candidate B.
75
- - `descriptors` - - Objective descriptors defining direction semantics.
76
-
77
- Returns: `true` if A dominates B; otherwise `false`.
78
-
79
- Example:
80
-
81
- ```ts
82
- // Maximize accuracy, minimize latency:
83
- vectorDominates([0.9, 120], [0.9, 150], [
84
- { accessor: () => 0, direction: 'max' },
85
- { accessor: () => 0, direction: 'min' },
86
- ]);
87
- // => true (equal accuracy, lower latency)
88
- ```
70
+ - `dominanceState` - - Dominance bookkeeping.
71
+ - `valuesMatrixInput` - - Matrix of objective values.
72
+ - `descriptors` - - Objective descriptors.
73
+ - `candidateIndex` - - Candidate genome index.
74
+ - `opponentIndex` - - Opponent genome index.
89
75
 
90
76
  ### buildDominanceState
91
77
 
@@ -128,41 +114,25 @@ Parameters:
128
114
 
129
115
  Returns: Dominance bookkeeping structures for ranking.
130
116
 
131
- ### DominanceState
132
-
133
- Dominance bookkeeping structures for fast non-dominated sorting.
134
-
135
- These structures are typically produced once per generation (from the values
136
- matrix) and then consumed to build Pareto fronts.
137
-
138
- They form the compact handoff between pairwise comparison mechanics and the
139
- later frontier-construction pass:
140
- - `dominationCounts` records how many opponents currently sit above each row
141
- - `dominatedIndicesByIndex` records which rows should be relaxed when a
142
- front is peeled away
143
- - `firstFrontIndices` captures the initial non-dominated frontier without
144
- re-running the full comparison loop
145
-
146
- ### resolveObjectiveDirection
117
+ ### buildIndexRange
147
118
 
148
119
  ```ts
149
- resolveObjectiveDirection(
150
- descriptors: ObjectiveDescriptor[],
151
- objectiveIndex: number,
152
- ): "max" | "min"
120
+ buildIndexRange(
121
+ populationSize: number,
122
+ ): number[]
153
123
  ```
154
124
 
155
- Resolves the objective direction for a given objective index.
125
+ Builds a stable index range for iterating the population.
156
126
 
157
- If a descriptor omits `direction`, it is treated as maximization.
158
- Keeping that default here ensures every comparison helper downstream reads
159
- one normalized direction rule instead of repeating fallback logic.
127
+ The returned range becomes the shared iteration order for candidate and
128
+ opponent loops. Using explicit indices instead of genome references keeps the
129
+ dominance state compact and guarantees later frontier code can look up rows
130
+ and genomes with the same integer keys.
160
131
 
161
132
  Parameters:
162
- - `descriptors` - - Objective descriptors.
163
- - `objectiveIndex` - - Objective index.
133
+ - `populationSize` - - Number of genomes.
164
134
 
165
- Returns: Normalized objective direction.
135
+ Returns: Array of indices `0..populationSize-1`.
166
136
 
167
137
  ### compareObjectiveValues
168
138
 
@@ -190,6 +160,40 @@ Parameters:
190
160
 
191
161
  Returns: Comparison flags for this objective.
192
162
 
163
+ ### createEmptyDominanceState
164
+
165
+ ```ts
166
+ createEmptyDominanceState(
167
+ populationSize: number,
168
+ ): DominanceState
169
+ ```
170
+
171
+ Creates an empty dominance state container sized to the population.
172
+
173
+ Every array slot maps directly to one matrix row and therefore one genome in
174
+ the ranking pass. Initializing the structure once keeps later comparison
175
+ helpers focused on bookkeeping updates rather than allocation details.
176
+
177
+ Parameters:
178
+ - `populationSize` - - Number of genomes.
179
+
180
+ Returns: An initialized dominance state with zeroed counts.
181
+
182
+ ### DominanceState
183
+
184
+ Dominance bookkeeping structures for fast non-dominated sorting.
185
+
186
+ These structures are typically produced once per generation (from the values
187
+ matrix) and then consumed to build Pareto fronts.
188
+
189
+ They form the compact handoff between pairwise comparison mechanics and the
190
+ later frontier-construction pass:
191
+ - `dominationCounts` records how many opponents currently sit above each row
192
+ - `dominatedIndicesByIndex` records which rows should be relaxed when a
193
+ front is peeled away
194
+ - `firstFrontIndices` captures the initial non-dominated frontier without
195
+ re-running the full comparison loop
196
+
193
197
  ### isCandidateDominatedByObjective
194
198
 
195
199
  ```ts
@@ -235,192 +239,188 @@ Parameters:
235
239
 
236
240
  Returns: `true` if the candidate is strictly better for this objective.
237
241
 
238
- ### updateStrictImprovement
242
+ ### isNonDominatedCandidate
239
243
 
240
244
  ```ts
241
- updateStrictImprovement(
242
- hasStrictImprovement: boolean,
243
- isStrictlyBetter: boolean,
245
+ isNonDominatedCandidate(
246
+ dominanceState: DominanceState,
247
+ candidateIndex: number,
244
248
  ): boolean
245
249
  ```
246
250
 
247
- Accumulates whether the candidate has a strict improvement across
248
- objectives.
251
+ Determines whether a candidate has zero domination count.
252
+
253
+ A zero count means the current row survived every pairwise comparison without
254
+ finding a dominating opponent, which is exactly the criterion for first-front
255
+ membership before frontier peeling begins.
249
256
 
250
257
  Parameters:
251
- - `hasStrictImprovement` - - Current strict-improvement flag.
252
- - `isStrictlyBetter` - - Whether the candidate strictly improves on the
253
- current objective.
258
+ - `dominanceState` - - Dominance bookkeeping.
259
+ - `candidateIndex` - - Candidate genome index.
254
260
 
255
- Returns: Updated strict-improvement flag.
261
+ Returns: `true` if the candidate is currently non-dominated.
256
262
 
257
- ### createEmptyDominanceState
263
+ ### resolveDominanceOutcome
258
264
 
259
265
  ```ts
260
- createEmptyDominanceState(
261
- populationSize: number,
262
- ): DominanceState
266
+ resolveDominanceOutcome(
267
+ candidateVector: number[],
268
+ opponentVector: number[],
269
+ descriptors: ObjectiveDescriptor[],
270
+ ): "dominates" | "dominated" | "indifferent"
263
271
  ```
264
272
 
265
- Creates an empty dominance state container sized to the population.
273
+ Resolves dominance outcome between two objective vectors.
266
274
 
267
- Every array slot maps directly to one matrix row and therefore one genome in
268
- the ranking pass. Initializing the structure once keeps later comparison
269
- helpers focused on bookkeeping updates rather than allocation details.
275
+ Outcome meanings:
276
+ - `'dominates'`: candidate dominates opponent.
277
+ - `'dominated'`: candidate is dominated by opponent.
278
+ - `'indifferent'`: neither dominates the other.
279
+
280
+ Pareto dominance is directional, so this helper checks both directions in a
281
+ fixed order. That keeps ties and tradeoffs explicit: many pairs in a
282
+ multi-objective population are intentionally incomparable rather than simply
283
+ "better" or "worse."
270
284
 
271
285
  Parameters:
272
- - `populationSize` - - Number of genomes.
286
+ - `candidateVector` - - Candidate objective values.
287
+ - `opponentVector` - - Opponent objective values.
288
+ - `descriptors` - - Objective descriptors.
273
289
 
274
- Returns: An initialized dominance state with zeroed counts.
290
+ Returns: Dominance outcome between candidate and opponent.
275
291
 
276
- ### buildIndexRange
292
+ ### resolveObjectiveDirection
277
293
 
278
294
  ```ts
279
- buildIndexRange(
280
- populationSize: number,
281
- ): number[]
295
+ resolveObjectiveDirection(
296
+ descriptors: ObjectiveDescriptor[],
297
+ objectiveIndex: number,
298
+ ): "max" | "min"
282
299
  ```
283
300
 
284
- Builds a stable index range for iterating the population.
301
+ Resolves the objective direction for a given objective index.
285
302
 
286
- The returned range becomes the shared iteration order for candidate and
287
- opponent loops. Using explicit indices instead of genome references keeps the
288
- dominance state compact and guarantees later frontier code can look up rows
289
- and genomes with the same integer keys.
303
+ If a descriptor omits `direction`, it is treated as maximization.
304
+ Keeping that default here ensures every comparison helper downstream reads
305
+ one normalized direction rule instead of repeating fallback logic.
290
306
 
291
307
  Parameters:
292
- - `populationSize` - - Number of genomes.
308
+ - `descriptors` - - Objective descriptors.
309
+ - `objectiveIndex` - - Objective index.
293
310
 
294
- Returns: Array of indices `0..populationSize-1`.
311
+ Returns: Normalized objective direction.
295
312
 
296
- ### updateDominanceForCandidate
313
+ ### shouldSkipSelfComparison
297
314
 
298
315
  ```ts
299
- updateDominanceForCandidate(
300
- dominanceState: DominanceState,
301
- valuesMatrixInput: number[][],
302
- descriptors: ObjectiveDescriptor[],
316
+ shouldSkipSelfComparison(
303
317
  candidateIndex: number,
304
- candidateIndices: number[],
305
- ): void
318
+ opponentIndex: number,
319
+ ): boolean
306
320
  ```
307
321
 
308
- Updates dominance bookkeeping for a candidate against all opponents.
322
+ Determines whether a pairwise comparison should be skipped.
309
323
 
310
- This iterates every opponent index and applies a pairwise dominance update.
311
- Self-comparisons are ignored.
324
+ Currently this skips only self-comparisons.
312
325
 
313
- The helper stays candidate-centric on purpose. Each pass answers "what does
314
- the rest of the matrix imply about this row?" and leaves first-front
315
- discovery to the outer orchestration once all opponent evidence has been
316
- accumulated.
326
+ Keeping the skip rule isolated makes it easier to audit the pairwise loop and
327
+ preserves the invariant that every stored relationship refers to two distinct
328
+ matrix rows.
317
329
 
318
330
  Parameters:
319
- - `dominanceState` - - Dominance bookkeeping.
320
- - `valuesMatrixInput` - - Matrix of objective values.
321
- - `descriptors` - - Objective descriptors.
322
331
  - `candidateIndex` - - Candidate genome index.
323
- - `candidateIndices` - - Indices to compare against.
332
+ - `opponentIndex` - - Opponent genome index.
324
333
 
325
- ### applyPairwiseDominance
334
+ Returns: `true` if the pair should be skipped.
335
+
336
+ ### updateDominanceForCandidate
326
337
 
327
338
  ```ts
328
- applyPairwiseDominance(
339
+ updateDominanceForCandidate(
329
340
  dominanceState: DominanceState,
330
341
  valuesMatrixInput: number[][],
331
342
  descriptors: ObjectiveDescriptor[],
332
343
  candidateIndex: number,
333
- opponentIndex: number,
344
+ candidateIndices: number[],
334
345
  ): void
335
346
  ```
336
347
 
337
- Applies a single pairwise dominance update between candidate and opponent.
348
+ Updates dominance bookkeeping for a candidate against all opponents.
338
349
 
339
- If the candidate dominates the opponent, the opponent index is appended to
340
- `dominatedIndicesByIndex[candidateIndex]`. If the candidate is dominated by
341
- the opponent, `dominationCounts[candidateIndex]` is incremented.
350
+ This iterates every opponent index and applies a pairwise dominance update.
351
+ Self-comparisons are ignored.
342
352
 
343
- That asymmetry is the key bookkeeping contract for the later frontier peel:
344
- - the count answers whether the candidate can join the current front yet,
345
- - the dominated-neighbor list tells later passes which counts to relax once
346
- the candidate is removed as a blocker.
353
+ The helper stays candidate-centric on purpose. Each pass answers "what does
354
+ the rest of the matrix imply about this row?" and leaves first-front
355
+ discovery to the outer orchestration once all opponent evidence has been
356
+ accumulated.
347
357
 
348
358
  Parameters:
349
359
  - `dominanceState` - - Dominance bookkeeping.
350
360
  - `valuesMatrixInput` - - Matrix of objective values.
351
361
  - `descriptors` - - Objective descriptors.
352
362
  - `candidateIndex` - - Candidate genome index.
353
- - `opponentIndex` - - Opponent genome index.
363
+ - `candidateIndices` - - Indices to compare against.
354
364
 
355
- ### shouldSkipSelfComparison
365
+ ### updateStrictImprovement
356
366
 
357
367
  ```ts
358
- shouldSkipSelfComparison(
359
- candidateIndex: number,
360
- opponentIndex: number,
368
+ updateStrictImprovement(
369
+ hasStrictImprovement: boolean,
370
+ isStrictlyBetter: boolean,
361
371
  ): boolean
362
372
  ```
363
373
 
364
- Determines whether a pairwise comparison should be skipped.
365
-
366
- Currently this skips only self-comparisons.
367
-
368
- Keeping the skip rule isolated makes it easier to audit the pairwise loop and
369
- preserves the invariant that every stored relationship refers to two distinct
370
- matrix rows.
374
+ Accumulates whether the candidate has a strict improvement across
375
+ objectives.
371
376
 
372
377
  Parameters:
373
- - `candidateIndex` - - Candidate genome index.
374
- - `opponentIndex` - - Opponent genome index.
378
+ - `hasStrictImprovement` - - Current strict-improvement flag.
379
+ - `isStrictlyBetter` - - Whether the candidate strictly improves on the
380
+ current objective.
375
381
 
376
- Returns: `true` if the pair should be skipped.
382
+ Returns: Updated strict-improvement flag.
377
383
 
378
- ### resolveDominanceOutcome
384
+ ### vectorDominates
379
385
 
380
386
  ```ts
381
- resolveDominanceOutcome(
382
- candidateVector: number[],
383
- opponentVector: number[],
387
+ vectorDominates(
388
+ valuesA: number[],
389
+ valuesB: number[],
384
390
  descriptors: ObjectiveDescriptor[],
385
- ): "dominates" | "dominated" | "indifferent"
391
+ ): boolean
386
392
  ```
387
393
 
388
- Resolves dominance outcome between two objective vectors.
394
+ Determines whether vector A Pareto-dominates vector B.
389
395
 
390
- Outcome meanings:
391
- - `'dominates'`: candidate dominates opponent.
392
- - `'dominated'`: candidate is dominated by opponent.
393
- - `'indifferent'`: neither dominates the other.
396
+ A dominates B iff:
397
+ - A is **no worse** than B in every objective (respecting each objective’s
398
+ direction: maximize/minimize), and
399
+ - A is **strictly better** in at least one objective.
394
400
 
395
- Pareto dominance is directional, so this helper checks both directions in a
396
- fixed order. That keeps ties and tradeoffs explicit: many pairs in a
397
- multi-objective population are intentionally incomparable rather than simply
398
- "better" or "worse."
401
+ This helper is deliberately pair-local. It does not mutate bookkeeping or
402
+ know anything about fronts; it only answers the comparison question that the
403
+ wider bookkeeping pass repeats across every pair of matrix rows.
404
+
405
+ Assumptions:
406
+ - `valuesA` and `valuesB` are aligned and have the same length.
407
+ - `descriptors` provides a descriptor for each objective index.
408
+ - If a descriptor has no `direction`, it defaults to `'max'`.
399
409
 
400
410
  Parameters:
401
- - `candidateVector` - - Candidate objective values.
402
- - `opponentVector` - - Opponent objective values.
403
- - `descriptors` - - Objective descriptors.
411
+ - `valuesA` - - Objective values for candidate A.
412
+ - `valuesB` - - Objective values for candidate B.
413
+ - `descriptors` - - Objective descriptors defining direction semantics.
404
414
 
405
- Returns: Dominance outcome between candidate and opponent.
415
+ Returns: `true` if A dominates B; otherwise `false`.
406
416
 
407
- ### isNonDominatedCandidate
417
+ Example:
408
418
 
409
419
  ```ts
410
- isNonDominatedCandidate(
411
- dominanceState: DominanceState,
412
- candidateIndex: number,
413
- ): boolean
420
+ // Maximize accuracy, minimize latency:
421
+ vectorDominates([0.9, 120], [0.9, 150], [
422
+ { accessor: () => 0, direction: 'max' },
423
+ { accessor: () => 0, direction: 'min' },
424
+ ]);
425
+ // => true (equal accuracy, lower latency)
414
426
  ```
415
-
416
- Determines whether a candidate has zero domination count.
417
-
418
- A zero count means the current row survived every pairwise comparison without
419
- finding a dominating opponent, which is exactly the criterion for first-front
420
- membership before frontier peeling begins.
421
-
422
- Parameters:
423
- - `dominanceState` - - Dominance bookkeeping.
424
- - `candidateIndex` - - Candidate genome index.
425
-
426
- Returns: `true` if the candidate is currently non-dominated.
@@ -44,51 +44,49 @@ computed in the first place.
44
44
 
45
45
  ## neat/multiobjective/fronts/multiobjective.fronts.ts
46
46
 
47
- ### buildParetoFronts
47
+ ### annotateGenomeRank
48
48
 
49
49
  ```ts
50
- buildParetoFronts(
50
+ annotateGenomeRank(
51
51
  population: default[],
52
- dominanceState: DominanceState,
53
- maxFrontRankGuard: number,
54
- ): default[][]
52
+ genomeIndex: number,
53
+ frontRank: number,
54
+ ): void
55
55
  ```
56
56
 
57
- Builds Pareto fronts from a precomputed dominance state.
58
-
59
- This performs the “peeling” phase of fast non-dominated sorting:
60
- - Start with the first front (all non-dominated genomes).
61
- - For each front, reduce domination counts of the genomes it dominates.
62
- - Each genome whose domination count becomes zero moves to the next front.
63
-
64
- The implementation is intentionally breadth-first. It never revisits pairwise
65
- comparisons; instead it trusts the dominance-state handoff and repeatedly
66
- relaxes domination counts until the next layer becomes visible.
67
-
68
- Side effects:
69
- - Annotates each genome in `population` with `_moRank` (0 = best front).
57
+ Annotates a genome with its Pareto front rank.
70
58
 
71
- Guard:
72
- - Stops when `currentFrontRank > maxFrontRankGuard` to avoid pathological
73
- infinite/degenerate runs. If the guard triggers, the returned fronts may
74
- be incomplete.
59
+ Ranking is stored directly on the genome so later selection, telemetry, and
60
+ archive helpers can read one stable annotation instead of carrying a parallel
61
+ rank table beside the population.
75
62
 
76
63
  Parameters:
77
- - `population` - - Genome population (same ordering used by dominance
78
- bookkeeping).
79
- - `dominanceState` - - Dominance bookkeeping.
80
- - `maxFrontRankGuard` - - Safety guard for ranking iterations.
64
+ - `population` - - Genome population.
65
+ - `genomeIndex` - - Index of the genome to annotate.
66
+ - `frontRank` - - Pareto front rank (0 = best front).
81
67
 
82
- Returns: Ordered Pareto fronts (rank order).
68
+ ### appendFront
83
69
 
84
- ### MAX_PARETO_FRONT_RANK_GUARD
70
+ ```ts
71
+ appendFront(
72
+ paretoFronts: default[][],
73
+ population: default[],
74
+ currentFrontIndices: number[],
75
+ ): void
76
+ ```
85
77
 
86
- Maximum number of Pareto fronts to allow during ranking before aborting.
78
+ Appends the current front (index list) as genome references to the
79
+ `paretoFronts` accumulator.
87
80
 
88
- This is a defensive guard against pathological conditions (e.g., corrupted
89
- dominance bookkeeping) that could otherwise cause long/infinite loops.
90
- A healthy ranking pass should terminate well before this threshold, so the
91
- constant exists as a safety rail rather than a normal control knob.
81
+ The accumulator stores genomes, not indices, because the returned fronts are
82
+ meant to be consumed by later crowding and archive code. The conversion from
83
+ stable indices to genome references happens only after the current layer has
84
+ been fully identified.
85
+
86
+ Parameters:
87
+ - `paretoFronts` - - Accumulator for Pareto fronts.
88
+ - `population` - - Genome population.
89
+ - `currentFrontIndices` - - Indices for the current front.
92
90
 
93
91
  ### buildNextFrontIndices
94
92
 
@@ -115,26 +113,42 @@ Parameters:
115
113
 
116
114
  Returns: Indices for the next front.
117
115
 
118
- ### annotateGenomeRank
116
+ ### buildParetoFronts
119
117
 
120
118
  ```ts
121
- annotateGenomeRank(
119
+ buildParetoFronts(
122
120
  population: default[],
123
- genomeIndex: number,
124
- frontRank: number,
125
- ): void
121
+ dominanceState: DominanceState,
122
+ maxFrontRankGuard: number,
123
+ ): default[][]
126
124
  ```
127
125
 
128
- Annotates a genome with its Pareto front rank.
126
+ Builds Pareto fronts from a precomputed dominance state.
129
127
 
130
- Ranking is stored directly on the genome so later selection, telemetry, and
131
- archive helpers can read one stable annotation instead of carrying a parallel
132
- rank table beside the population.
128
+ This performs the “peeling” phase of fast non-dominated sorting:
129
+ - Start with the first front (all non-dominated genomes).
130
+ - For each front, reduce domination counts of the genomes it dominates.
131
+ - Each genome whose domination count becomes zero moves to the next front.
132
+
133
+ The implementation is intentionally breadth-first. It never revisits pairwise
134
+ comparisons; instead it trusts the dominance-state handoff and repeatedly
135
+ relaxes domination counts until the next layer becomes visible.
136
+
137
+ Side effects:
138
+ - Annotates each genome in `population` with `_moRank` (0 = best front).
139
+
140
+ Guard:
141
+ - Stops when `currentFrontRank > maxFrontRankGuard` to avoid pathological
142
+ infinite/degenerate runs. If the guard triggers, the returned fronts may
143
+ be incomplete.
133
144
 
134
145
  Parameters:
135
- - `population` - - Genome population.
136
- - `genomeIndex` - - Index of the genome to annotate.
137
- - `frontRank` - - Pareto front rank (0 = best front).
146
+ - `population` - - Genome population (same ordering used by dominance
147
+ bookkeeping).
148
+ - `dominanceState` - - Dominance bookkeeping.
149
+ - `maxFrontRankGuard` - - Safety guard for ranking iterations.
150
+
151
+ Returns: Ordered Pareto fronts (rank order).
138
152
 
139
153
  ### collectNextFrontIndices
140
154
 
@@ -159,29 +173,6 @@ Parameters:
159
173
  - `genomeIndex` - - Index of the current genome.
160
174
  - `nextFrontIndices` - - Accumulator for the next front.
161
175
 
162
- ### appendFront
163
-
164
- ```ts
165
- appendFront(
166
- paretoFronts: default[][],
167
- population: default[],
168
- currentFrontIndices: number[],
169
- ): void
170
- ```
171
-
172
- Appends the current front (index list) as genome references to the
173
- `paretoFronts` accumulator.
174
-
175
- The accumulator stores genomes, not indices, because the returned fronts are
176
- meant to be consumed by later crowding and archive code. The conversion from
177
- stable indices to genome references happens only after the current layer has
178
- been fully identified.
179
-
180
- Parameters:
181
- - `paretoFronts` - - Accumulator for Pareto fronts.
182
- - `population` - - Genome population.
183
- - `currentFrontIndices` - - Indices for the current front.
184
-
185
176
  ### incrementFrontRank
186
177
 
187
178
  ```ts
@@ -200,6 +191,15 @@ Parameters:
200
191
 
201
192
  Returns: Incremented front rank.
202
193
 
194
+ ### MAX_PARETO_FRONT_RANK_GUARD
195
+
196
+ Maximum number of Pareto fronts to allow during ranking before aborting.
197
+
198
+ This is a defensive guard against pathological conditions (e.g., corrupted
199
+ dominance bookkeeping) that could otherwise cause long/infinite loops.
200
+ A healthy ranking pass should terminate well before this threshold, so the
201
+ constant exists as a safety rail rather than a normal control knob.
202
+
203
203
  ### shouldStopFrontRanking
204
204
 
205
205
  ```ts