@reicek/neataptic-ts 0.1.13 → 0.1.15

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.
@@ -26,8 +26,8 @@
26
26
  <div id="ascii-maze-status" aria-live="polite" style="margin-top:8px;color:#f88"></div>
27
27
  <!-- Deterministic script path (test environment -> docs assets) -->
28
28
  <script
29
- src="../../../docs/assets/ascii-maze.bundle.js"
30
- data-ascii-maze-root="../../../docs/assets/"
29
+ src="../../assets/ascii-maze.bundle.js"
30
+ data-ascii-maze-root="../../assets/"
31
31
  defer
32
32
  onload="(window.asciiMazeStart ? window.asciiMazeStart('ascii-maze-output') : (window.asciiMaze && window.asciiMaze.start && window.asciiMaze.start()))"
33
33
  onerror="document.getElementById('ascii-maze-status').textContent='Failed to load ascii-maze.bundle.js';"
package/docs/index.html CHANGED
@@ -112,8 +112,7 @@ console.log(&#39;best score&#39;, neat.getBest()?.score);
112
112
 
113
113
  const neatMo = new Neat(2, 1, fitness, {
114
114
  popsize: 60,
115
- multiObjective: { enabled: true, complexityMetric: &#39;nodes&#39; },
116
- novelty: { enabled: true, descriptor: g =&gt; [g.nodes.length, g.connections.length], k: 8, blendFactor: 0.25 },
115
+ multiObjective: { enabled: true },
117
116
  seed: 7,
118
117
  });
119
118
  await neatMo.evaluate();
@@ -267,10 +266,12 @@ writeFileSync(&#39;telemetry.csv&#39;, csv);
267
266
  </tbody></table>
268
267
  <hr>
269
268
  <h2 id="performance-shorthand">Performance shorthand</h2><p>Fast iteration recipe:</p>
270
- <pre><code class="language-ts">const neat = new Neat(inp, out, fit, {
269
+ <pre><code class="language-ts">import { cpus } from &#39;node:os&#39;;
270
+
271
+ const neat = new Neat(inp, out, fit, {
271
272
  popsize: 120,
272
273
  fastMode: true,
273
- threads: (require(&#39;os&#39;).cpus().length - 1),
274
+ threads: cpus().length &gt; 1 ? cpus().length - 1 : 1,
274
275
  adaptiveMutation: { enabled: true, strategy: &#39;twoTier&#39; },
275
276
  telemetry: { enabled: true, performance: true, complexity: true }
276
277
  });
@@ -310,7 +311,10 @@ writeFileSync(&#39;telemetry.csv&#39;, csv);
310
311
  <hr>
311
312
  <h2 id="training-optional-polish-phase">Training (optional polish phase)</h2><p>Evolve topology first, then fine‑tune weights:</p>
312
313
  <pre><code class="language-ts">const best = neat.getBest();
313
- await best?.train(data, { iterations: 500, rate: 0.01, optimizer: &#39;adam&#39;,
314
+ await best?.train(data, {
315
+ iterations: 500,
316
+ rate: 0.01,
317
+ optimizer: &#39;adam&#39;,
314
318
  gradientClip: { mode: &#39;norm&#39;, maxNorm: 1 },
315
319
  movingAverageWindow: 5,
316
320
  });
@@ -323,7 +327,7 @@ await best?.train(data, { iterations: 500, rate: 0.01, optimizer: &#39;adam&#39;
323
327
  optimizer: &#39;adamw&#39;,
324
328
  gradientClip: { mode: &#39;norm&#39;, maxNorm: 1 },
325
329
  movingAverageWindow: 7,
326
- metricsHook: m =&gt; console.log(m.iteration, m.error, m.gradNorm)
330
+ metricsHook: m =&gt; console.log(m.iteration, m.error, m.gradNorm),
327
331
  });
328
332
  </code></pre>
329
333
  <p>Training docs cover scheduler composition (e.g. warmup → plateau) &amp; pruning schedules.</p>
@@ -461,7 +465,7 @@ const roundTrip = importFromONNX(bytes);
461
465
  <td>Prevents runaway long runs during tuning passes.</td>
462
466
  </tr>
463
467
  </tbody></table>
464
- <h3 id="structural-complexity-caching">Structural Complexity Caching</h3><p><code>network.evolve</code> caches per-genome complexity metrics (nodes / connections / gates). This avoids recomputing counts each evaluation when unchanged, reducing overhead for large populations or deep architectures.</p>
468
+ <h3 id="structural-complexity-caching">Structural Complexity Caching</h3><p><code>neat.evolve</code> caches per-genome complexity metrics (nodes / connections / gates). This avoids recomputing counts each evaluation when unchanged, reducing overhead for large populations or deep architectures.</p>
465
469
  <h3 id="profiling">Profiling</h3><p>Enable <code>telemetry:{ performance:true }</code> to capture per-generation evaluation &amp; evolve timings. Use these to:</p>
466
470
  <ol>
467
471
  <li>Identify evaluation bottlenecks (cost function vs structural overhead).</li>
@@ -480,8 +484,6 @@ const roundTrip = importFromONNX(bytes);
480
484
  popsize: 120,
481
485
  threads: 8,
482
486
  telemetry: { enabled: true, performance: true },
483
- telemetrySelect: [&#39;performance&#39;, &#39;complexity&#39;],
484
- adaptiveMutation: { enabled: true, strategy: &#39;twoTier&#39; },
485
487
  fastMode: true,
486
488
  });
487
489
  </code></pre>
@@ -511,7 +513,7 @@ const roundTrip = importFromONNX(bytes);
511
513
  <li>A direct input→output shortcut is removed once at least one hidden node exists, ensuring depth grows.</li>
512
514
  </ul>
513
515
  <p>Intended Usage:</p>
514
- <pre><code class="language-ts">import { config } from &#39;neataptic&#39;;
516
+ <pre><code class="language-ts">import { config, methods } from &#39;@reicek/neataptic-ts&#39;;
515
517
  config.deterministicChainMode = true; // enable
516
518
  const net = new Network(1, 1);
517
519
  for (let i = 0; i &lt; 5; i++) net.mutate(methods.mutation.ADD_NODE); // guaranteed 5 hidden chain
@@ -641,9 +643,7 @@ for each Fi: decrement dominanceCount of genomes they dominate; those reaching 0
641
643
  multiObjective: { enabled: true, complexityMetric: &#39;nodes&#39; },
642
644
  });
643
645
  // Add structural entropy (maximize)
644
- neat.registerObjective(&#39;entropy&#39;, &#39;max&#39;, (g) =&gt;
645
- (neat as any)._structuralEntropy(g)
646
- );
646
+ neat.registerObjective(&#39;entropy&#39;, &#39;max&#39;, g =&gt; (neat as any)._structuralEntropy(g));
647
647
  await neat.evaluate();
648
648
  await neat.evolve();
649
649
  console.log(neat.getObjectives()); // [{key:&#39;fitness&#39;,...},{key:&#39;complexity&#39;,...},{key:&#39;entropy&#39;,...}]
@@ -722,16 +722,16 @@ console.log(neat.getTelemetry().slice(-1)[0].complexity); // { meanNodes, meanCo
722
722
  </tbody></table>
723
723
  <p>Configure an adaptive schedule that expands limits when improvement slope is positive and contracts during stagnation. This mirrors a common parsimony heuristic: permit complexification only while marginal fitness gain per added structural unit remains appreciable; otherwise bias toward consolidation to reduce evaluation cost and overfitting risk:</p>
724
724
  <pre><code class="language-ts">complexityBudget: {
725
- enabled:true,
726
- mode:&#39;adaptive&#39;,
727
- maxNodesStart: input+output+2,
728
- maxNodesEnd: (input+output+2)*6,
729
- improvementWindow: 8,
730
- increaseFactor:1.15,
731
- stagnationFactor:0.93,
732
- minNodes: input+output+2,
733
- maxConnsStart: 40,
734
- maxConnsEnd: 400
725
+ enabled: true,
726
+ mode: &#39;adaptive&#39;,
727
+ maxNodesStart: 4,
728
+ maxNodesEnd: 24,
729
+ improvementWindow: 8,
730
+ increaseFactor: 1.15,
731
+ stagnationFactor: 0.93,
732
+ minNodes: 4,
733
+ maxConnsStart: 40,
734
+ maxConnsEnd: 400,
735
735
  }
736
736
  </code></pre>
737
737
  <p>Linear schedule alternative: set <code>mode:&#39;linear&#39;</code> and optionally <code>horizon</code> (generations) to interpolate from <code>maxNodesStart</code> to <code>maxNodesEnd</code>.</p>
@@ -808,22 +808,22 @@ console.log(neat.getTelemetry().slice(-1)[0].complexity); // { meanNodes, meanCo
808
808
  <pre><code class="language-ts">diversityPressure:{ enabled:true, motifSample:25, penaltyStrength:0.05 }
809
809
  </code></pre>
810
810
  <p>Adaptive novelty threshold targeting an archive insertion rate:</p>
811
- <pre><code class="language-ts">novelty:{
812
- enabled:true,
813
- descriptor:g=&gt;[g.nodes.length, g.connections.length],
814
- archiveAddThreshold:0.5,
815
- dynamicThreshold:{ enabled:true, targetRate:0.15, adjust:0.1, min:0.01, max:10 }
811
+ <pre><code class="language-ts">novelty: {
812
+ enabled: true,
813
+ descriptor: g =&gt; [g.nodes.length, g.connections.length],
814
+ archiveAddThreshold: 0.5,
815
+ dynamicThreshold: { enabled: true, targetRate: 0.15, adjust: 0.1, min: 0.01, max: 10 },
816
816
  }
817
817
  </code></pre>
818
818
  <p>After each evaluation the threshold is nudged up/down so the fraction of inserted descriptors approximates <code>targetRate</code>.</p>
819
819
  <h3 id="inactive-objective-pruning">Inactive Objective Pruning</h3><p>If you experiment with many custom objectives it is common for some to become constant (providing no ranking discrimination). Enable automatic removal of such stagnant objectives:</p>
820
- <pre><code class="language-ts">multiObjective:{
821
- enabled:true,
822
- objectives:[
823
- { key:&#39;fitness&#39;, direction:&#39;max&#39;, accessor: g =&gt; g.score },
824
- { key:&#39;novelty&#39;, direction:&#39;max&#39;, accessor: g =&gt; (g as any)._novelty }
825
- ],
826
- pruneInactive:{ enabled:true, window:5, rangeEps:1e-9, protect:[&#39;fitness&#39;] }
820
+ <pre><code class="language-ts">multiObjective: {
821
+ enabled: true,
822
+ objectives: [
823
+ { key: &#39;fitness&#39;, direction: &#39;max&#39;, accessor: g =&gt; g.score },
824
+ { key: &#39;novelty&#39;, direction: &#39;max&#39;, accessor: g =&gt; (g as any)._novelty },
825
+ ],
826
+ pruneInactive: { enabled: true, window: 5, rangeEps: 1e-9, protect: [&#39;fitness&#39;] },
827
827
  }
828
828
  </code></pre>
829
829
  <p>Mechanics:</p>
@@ -862,13 +862,13 @@ Telemetry <code>lineage</code> block now also includes:</li>
862
862
  </ul>
863
863
  <p>Use these to detect genealogical stagnation (both remaining near zero) vs broad exploration (rising pair distance).</p>
864
864
  <h3 id="lineage-pressure-anti-inbreeding-optional">Lineage Pressure & Anti-Inbreeding (Optional)</h3><p>Apply score adjustments based on lineage structure (depth dispersion) or penalize inbreeding (high ancestor overlap):</p>
865
- <pre><code class="language-ts">lineagePressure:{
866
- enabled:true,
867
- mode:&#39;antiInbreeding&#39;, // &#39;penalizeDeep&#39; | &#39;rewardShallow&#39; | &#39;spread&#39; | &#39;antiInbreeding&#39;
868
- strength:0.02, // generic scaling for depth modes
869
- ancestorWindow:4, // generations to look back when computing ancestor sets
870
- inbreedingPenalty:0.04, // override penalty scaling (defaults to strength*2)
871
- diversityBonus:0.02 // bonus scaling for very distinct parent lineages
865
+ <pre><code class="language-ts">lineagePressure: {
866
+ enabled: true,
867
+ mode: &#39;antiInbreeding&#39;, // &#39;penalizeDeep&#39; | &#39;rewardShallow&#39; | &#39;spread&#39; | &#39;antiInbreeding&#39;
868
+ strength: 0.02, // generic scaling for depth modes
869
+ ancestorWindow: 4, // generations to look back when computing ancestor sets
870
+ inbreedingPenalty: 0.04, // override penalty scaling (defaults to strength*2)
871
+ diversityBonus: 0.02, // bonus scaling for very distinct parent lineages
872
872
  }
873
873
  </code></pre>
874
874
  <p>Modes:</p>
@@ -916,7 +916,7 @@ neat2.importRNGState(json);
916
916
  </tr>
917
917
  </tbody></table>
918
918
  <p>Per-genome mutation rate/amount adapt each generation under strategies (<code>twoTier</code>, <code>exploreLow</code>, <code>anneal</code>). Use:</p>
919
- <pre><code class="language-ts">adaptiveMutation:{ enabled:true, strategy:&#39;twoTier&#39;, sigma:0.08, adaptAmount:true }
919
+ <pre><code class="language-ts">adaptiveMutation: { enabled: true, strategy: &#39;twoTier&#39;, sigma: 0.08, adaptAmount: true }
920
920
  </code></pre>
921
921
  <p>Operator success statistics (bandit + weighting):</p>
922
922
  <pre><code class="language-ts">neat.getOperatorStats(); // [{ name, success, attempts }, ...]
@@ -978,7 +978,7 @@ const csv = neat.exportSpeciesHistoryCSV();
978
978
  // Columns include generation plus dynamic keys: id,size,best,lastImproved,age,meanNodes,meanConns,meanScore,meanNovelty,meanCompat,meanEntropy,varNodes,varConns,deltaMeanNodes,deltaMeanConns,deltaBestScore,turnoverRate,meanInnovation,innovationRange,enabledRatio (when extendedHistory enabled)
979
979
  </code></pre>
980
980
  <p>These APIs are evolving; consult source <code>src/neat.ts</code> for full option surfaces while docs finalize.</p>
981
- <p>Full option &amp; telemetry reference: <a href="./docs/API.md">docs/API.md</a></p>
981
+ <p>Full option &amp; telemetry reference: See the generated documentation in the <code>docs/</code> directory.</p>
982
982
  <h1 id="network-constructor-update">Network Constructor Update</h1><p>The <code>Network</code> class constructor now supports an optional third parameter for configuration:</p>
983
983
  <pre><code class="language-ts">new Network(input: number, output: number, options?: { minHidden?: number })
984
984
  </code></pre>
@@ -986,26 +986,31 @@ const csv = neat.exportSpeciesHistoryCSV();
986
986
  <li><code>input</code>: Number of input nodes (required)</li>
987
987
  <li><code>output</code>: Number of output nodes (required)</li>
988
988
  <li><code>options.minHidden</code>: (optional) If set, enforces a minimum number of hidden nodes. If omitted or 0, no minimum is enforced. This allows true 1-1 (input-output only) networks.</li>
989
+ <li><code>options.seed</code>: (optional) A numeric seed for the random number generator to ensure reproducible initial weights and biases.</li>
989
990
  </ul>
990
991
  <p><strong>Example:</strong></p>
991
992
  <pre><code class="language-ts">// Standard 1-1 network (no hidden nodes)
992
993
  const net = new Network(1, 1);
993
994
 
994
- // Enforce at least 3 hidden nodes
995
- const netWithHidden = new Network(2, 1, { minHidden: 3 });
995
+ // Enforce at least 3 hidden nodes and set a seed
996
+ const netWithHidden = new Network(2, 1, { minHidden: 3, seed: 123 });
996
997
  </code></pre>
997
- <h1 id="neat-evolution-minhidden-option">Neat Evolution minHidden Option</h1><p>The <code>minHidden</code> option can also be passed to the <code>Neat</code> class to enforce a minimum number of hidden nodes in all evolved networks:</p>
998
- <pre><code class="language-ts">import Neat from &#39;./src/neat&#39;;
999
- const neat = new Neat(2, 1, fitnessFn, { popsize: 50, minHidden: 5 });
998
+ <h1 id="neat-evolution-options">Neat Evolution Options</h1><p>The <code>Neat</code> class constructor accepts an options object that includes all <code>Network</code> options (<code>minHidden</code>, <code>seed</code>) plus evolution-specific settings.</p>
999
+ <pre><code class="language-ts">import { Neat } from &#39;@reicek/neataptic-ts&#39;;
1000
+ const neat = new Neat(2, 1, fitnessFn, {
1001
+ popsize: 50,
1002
+ minHidden: 5, // Passed to Network constructor
1003
+ seed: 4242, // Passed to both Neat and Network constructors
1004
+ });
1000
1005
  </code></pre>
1001
1006
  <ul>
1002
1007
  <li>All networks created by the evolutionary process will have at least 5 hidden nodes.</li>
1003
- <li>This is useful for ensuring a minimum network complexity during neuro-evolution.</li>
1008
+ <li>The <code>seed</code> ensures that the entire evolutionary process, including initial population creation, is reproducible.</li>
1004
1009
  </ul>
1005
1010
  <p>See tests in <code>test/neat.ts</code> for usage and verification.</p>
1006
1011
  <hr>
1007
1012
  <h1 id="onnx-import-export">ONNX Import/Export</h1><p>Interoperability layer for exchanging strictly layered MLP (and experimental recurrent) networks with ONNX tooling. Scope today: feed-forward layered perceptrons plus heuristic detection of simple recurrent gate groupings; arbitrary graphs not guaranteed.</p>
1008
- <h3 id="basic-usage">Basic Usage</h3><pre><code class="language-ts">import { exportToONNX, importFromONNX } from &#39;./src/architecture/onnx&#39;;
1013
+ <h3 id="basic-usage">Basic Usage</h3><pre><code class="language-ts">import { exportToONNX, importFromONNX } from &#39;@reicek/neataptic-ts&#39;;
1009
1014
 
1010
1015
  // Export
1011
1016
  const onnxModel = exportToONNX(network, { includeMetadata: true });
@@ -1224,7 +1229,7 @@ net.train(data, {
1224
1229
  <li>Deterministic seeding: <code>new Network(4,2,{ seed:123 })</code> or later <code>net.setSeed(123)</code> ensures reproducible initial weights, biases, connection order, and mutation randomness for training (excluding certain static reconstruction paths). For NEAT evolution pass <code>seed</code> in <code>new Neat(...,{ seed:999 })</code>.</li>
1225
1230
  <li>Overflow telemetry: during mixed precision training, <code>overflowCount</code> increments on detected NaN/Inf when unscaling gradients; <code>scaleUps</code> / <code>scaleDowns</code> count dynamic loss scale adjustments.</li>
1226
1231
  </ul>
1227
- <h3 id="learning-rate-scheduler-usage">Learning Rate Scheduler Usage</h3><pre><code class="language-ts">import methods from &#39;./src/methods/methods&#39;;
1232
+ <h3 id="learning-rate-scheduler-usage">Learning Rate Scheduler Usage</h3><pre><code class="language-ts">import { methods } from &#39;@reicek/neataptic-ts&#39;;
1228
1233
  const ratePolicy = methods.Rate.cosineAnnealingWarmRestarts(200, 1e-5, 2);
1229
1234
  net.train(data, { iterations: 1000, rate: 0.1, ratePolicy });
1230
1235
  </code></pre>
@@ -1543,12 +1548,7 @@ net.disableDropConnect();
1543
1548
  <td>Rectifies variance early in training</td>
1544
1549
  </tr>
1545
1550
  <tr>
1546
- <td>lion</td>
1547
- <td>beta1, beta2</td>
1548
- <td>Direction = sign(beta1<em>m + beta2</em>m2)</td>
1549
- </tr>
1550
- <tr>
1551
- <td>adabelief</td>
1551
+ <td>AdaBelief</td>
1552
1552
  <td>beta1, beta2, eps</td>
1553
1553
  <td>Second moment of (g - m) (gradient surprise)</td>
1554
1554
  </tr>
@@ -1887,87 +1887,4 @@ neat.importRNGState(json); // restore from JSON
1887
1887
  });
1888
1888
  </code></pre>
1889
1889
  <p>Use when raw search space contains huge numbers of trivial zero-score genomes (e.g. all-linear tiny nets). The filter prevents them from influencing speciation/dominance ordering; they still evolve structurally until criterion passes.</p>
1890
- <pre><code>
1891
- #### Adaptive Sharing
1892
-
1893
- If `adaptiveSharing.enabled` the system adjusts `sharingSigma` each generation:
1894
- </code></pre>
1895
- <p>sigma += step * sign(fragmentation - target)</p>
1896
- <pre><code>
1897
- within `[minSigma,maxSigma]`.
1898
-
1899
- #### Multi-Objective Notes &amp; Strategy {#multi-objective-notes--strategy}
1900
-
1901
- Implements a simplified NSGA-II style pass: fast non-dominated sort (O(N^2) current implementation) + crowding distance; final ordering uses (rank asc, crowding desc, fitness desc) before truncation. Practical guidance:
1902
-
1903
- - Start single-objective until baseline performance plateaus, then enable `multiObjective.enabled` with `complexityMetric:&#39;nodes&#39;`.
1904
- - If early search stagnates due to premature parsimony, delay complexity with `multiObjective.dynamic.addComplexityAt`.
1905
- - Use `autoEntropy` to seed a third diversity proxy objective only when structural collapse is observed (few species, low ancestor uniqueness).
1906
- - Monitor front size; if it grows too large relative to population, enable `adaptiveEpsilon` to tighten dominance criteria.
1907
-
1908
- Planned (future): faster dominance (divide-and-conquer), richer motif diversity pressure, automated compatibility coefficient tuning.
1909
-
1910
- ## ASCII Maze Example: 6‑Input Long-Range Vision (MazeVision)
1911
-
1912
- The ASCII maze example uses a compact 6‑input perception schema (&quot;MazeVision&quot;) with long‑range lookahead via a precomputed distance map. Inputs (order fixed):
1913
-
1914
- 1. compassScalar: Encodes the direction of the globally best next step toward the exit as a discrete scalar in {0,0.25,0.5,0.75} corresponding to N,E,S,W. Uses an extended horizon (H_COMPASS=5000) so it can see deeper than openness ratios.
1915
- 2. openN
1916
- 3. openE
1917
- 4. openS
1918
- 5. openW
1919
- 6. progressDelta: Normalized recent progress signal around 0.5 ( &gt;0.5 improving, &lt;0.5 regressing ).
1920
-
1921
- ### Openness Semantics (openN/E/S/W) {#openness-semantics}
1922
-
1923
- Each openness value describes the quality of the shortest path to the exit if the agent moves first in that direction, using a bounded lookahead horizon H=1000 over the distance map.
1924
-
1925
- Value encoding:
1926
-
1927
- - 1: Direction(s) whose total path length Ldir is minimal among all strictly improving neighbors (ties allowed; multiple 1s possible).
1928
- - Ratio 0 &lt; Lmin / Ldir &lt; 1: Direction is a valid strictly improving path but longer than the best (Lmin is the shortest improving path cost; Ldir = 1 + distance of neighbor cell). This supplies graded preference rather than binary pruning.
1929
- - 0: Wall, unreachable cell, dead end, or any non‑improving move (neighbor distance &gt;= current distance) – all treated uniformly.
1930
- - 0.001: Special back‑only escape marker. When all four openness values would otherwise be 0 but the opposite of the previous successful action is traversable, that single opposite direction is set to 0.001 to indicate a pure retreat (pattern e.g. [0,0,0,0.001]).
1931
-
1932
- Rules / Notes:
1933
-
1934
- - Strict improvement filter: Only neighbors whose distanceMap value is strictly less than the current cell distance are considered for 1 or ratio values.
1935
- - Horizon clipping: Paths with Ldir &gt; H are treated as unreachable (value 0) to bound search cost.
1936
- - Multiple bests: Corridors that fork into equivalently short routes produce multiple 1s, encouraging neutrality across equally optimal choices.
1937
- - Backtrack marker is intentionally very small (0.001) so evolution distinguishes &quot;retreat only&quot; states from true walls without overweighting them.
1938
- - Supervised refinement dataset intentionally contains ONLY deterministic single‑path cases (exactly one openness=1, others 0) for clarity; richer ratio/backtrack patterns appear only in the Lamarckian / evolutionary phase.
1939
-
1940
- ### progressDelta
1941
-
1942
- Computed from recent distance improvement: delta = prevDistance - currentDistance, clipped to [-2,2], then mapped to [0,1] as 0.5 + delta/4. Values &gt;0.5 mean progress toward exit; &lt;0.5 regression or stalling.
1943
-
1944
- ### Debugging
1945
-
1946
- Set ASCII_VISION_DEBUG=1 to emit periodic vision lines: current position, compassScalar, input vector, and per‑direction distance/ratio breakdown for auditing mismatches between maze geometry and distance map.
1947
-
1948
- ### Quick Reference
1949
-
1950
- | Signal | Meaning |
1951
- | ------ | --------------------------------------------------- |
1952
- | 1 | Best strictly improving path(s) (minimal Ldir) |
1953
- | (0,1) | Longer but improving path (ratio Lmin/Ldir) |
1954
- | 0.001 | Only backtrack available (opposite of prior action) |
1955
- | 0 | Wall / dead end / non‑improving / unreachable |
1956
-
1957
- Implementation: `test/examples/asciiMaze/mazeVision.ts` (function `MazeVision.buildInputs6`).
1958
-
1959
- This design minimizes input size (6 vs earlier large encodings) while preserving directional discrimination and long‑range planning cues, aiding faster evolutionary convergence and avoiding overfitting to local dead‑end noise.
1960
-
1961
- ## Roadmap / Backlog
1962
-
1963
- Planned or partially designed enhancements not yet merged:
1964
-
1965
- - Structural motif diversity pressure: penalize over-represented connection patterns (entropy-based sharing) to sustain innovation.
1966
- - Automated compatibility coefficient tuning: search or adapt excess/disjoint/weight coefficients to stabilize species counts without manual calibration.
1967
- - Faster Pareto sorting: divide-and-conquer or incremental dominance maintenance to reduce O(N^2) overhead for large populations.
1968
- - Connection complexity budget (current budget targets nodes only) and dual-objective weighting option.
1969
- - Diversity-aware parent selection leveraging motif entropy and archive dispersion.
1970
- - Extended novelty descriptors helper utilities (e.g. built-in graph metrics: depth, feedforwardness, clustering).
1971
- - Visualization hooks (species lineage graph, archive embedding projection) for diagnostics.
1972
- </code></pre>
1973
1890
  <footer class="site-footer">Generated from source JSDoc • <a href="https://github.com/reicek/NeatapticTS">GitHub</a></footer></main><aside class="toc"></aside></div></body></html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reicek/neataptic-ts",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Architecture-free neural network library with genetic algorithm implementations",
5
5
  "main": "./dist/neataptic.js",
6
6
  "module": "./dist/neataptic.js",