@reicek/neataptic-ts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +28 -0
- package/.github/workflows/ci.yml +41 -0
- package/.github/workflows/deploy-pages.yml +29 -0
- package/.github/workflows/manual_release_pipeline.yml +62 -0
- package/.github/workflows/publish.yml +85 -0
- package/.github/workflows/release_dispatch.yml +38 -0
- package/.travis.yml +5 -0
- package/CONTRIBUTING.md +92 -0
- package/LICENSE +24 -0
- package/ONNX_EXPORT.md +87 -0
- package/README.md +1173 -0
- package/RELEASE.md +54 -0
- package/dist-docs/package.json +1 -0
- package/dist-docs/scripts/generate-docs.d.ts +2 -0
- package/dist-docs/scripts/generate-docs.d.ts.map +1 -0
- package/dist-docs/scripts/generate-docs.js +536 -0
- package/dist-docs/scripts/generate-docs.js.map +1 -0
- package/dist-docs/scripts/render-docs-html.d.ts +2 -0
- package/dist-docs/scripts/render-docs-html.d.ts.map +1 -0
- package/dist-docs/scripts/render-docs-html.js +148 -0
- package/dist-docs/scripts/render-docs-html.js.map +1 -0
- package/docs/FOLDERS.md +14 -0
- package/docs/README.md +1173 -0
- package/docs/architecture/README.md +1391 -0
- package/docs/architecture/index.html +938 -0
- package/docs/architecture/network/README.md +1210 -0
- package/docs/architecture/network/index.html +908 -0
- package/docs/assets/ascii-maze.bundle.js +16542 -0
- package/docs/assets/ascii-maze.bundle.js.map +7 -0
- package/docs/index.html +1419 -0
- package/docs/methods/README.md +670 -0
- package/docs/methods/index.html +477 -0
- package/docs/multithreading/README.md +274 -0
- package/docs/multithreading/index.html +215 -0
- package/docs/multithreading/workers/README.md +23 -0
- package/docs/multithreading/workers/browser/README.md +39 -0
- package/docs/multithreading/workers/browser/index.html +70 -0
- package/docs/multithreading/workers/index.html +57 -0
- package/docs/multithreading/workers/node/README.md +33 -0
- package/docs/multithreading/workers/node/index.html +66 -0
- package/docs/neat/README.md +1284 -0
- package/docs/neat/index.html +906 -0
- package/docs/src/README.md +2659 -0
- package/docs/src/index.html +1579 -0
- package/jest.config.ts +32 -0
- package/package.json +99 -0
- package/plans/HyperMorphoNEAT.md +293 -0
- package/plans/ONNX_EXPORT_PLAN.md +46 -0
- package/scripts/generate-docs.ts +486 -0
- package/scripts/render-docs-html.ts +138 -0
- package/scripts/types.d.ts +2 -0
- package/src/README.md +2659 -0
- package/src/architecture/README.md +1391 -0
- package/src/architecture/activationArrayPool.ts +135 -0
- package/src/architecture/architect.ts +635 -0
- package/src/architecture/connection.ts +148 -0
- package/src/architecture/group.ts +406 -0
- package/src/architecture/layer.ts +804 -0
- package/src/architecture/network/README.md +1210 -0
- package/src/architecture/network/network.activate.ts +223 -0
- package/src/architecture/network/network.connect.ts +157 -0
- package/src/architecture/network/network.deterministic.ts +167 -0
- package/src/architecture/network/network.evolve.ts +426 -0
- package/src/architecture/network/network.gating.ts +186 -0
- package/src/architecture/network/network.genetic.ts +247 -0
- package/src/architecture/network/network.mutate.ts +624 -0
- package/src/architecture/network/network.onnx.ts +463 -0
- package/src/architecture/network/network.prune.ts +216 -0
- package/src/architecture/network/network.remove.ts +96 -0
- package/src/architecture/network/network.serialize.ts +309 -0
- package/src/architecture/network/network.slab.ts +262 -0
- package/src/architecture/network/network.standalone.ts +246 -0
- package/src/architecture/network/network.stats.ts +59 -0
- package/src/architecture/network/network.topology.ts +86 -0
- package/src/architecture/network/network.training.ts +1278 -0
- package/src/architecture/network.ts +1302 -0
- package/src/architecture/node.ts +1288 -0
- package/src/architecture/onnx.ts +3 -0
- package/src/config.ts +83 -0
- package/src/methods/README.md +670 -0
- package/src/methods/activation.ts +372 -0
- package/src/methods/connection.ts +31 -0
- package/src/methods/cost.ts +347 -0
- package/src/methods/crossover.ts +63 -0
- package/src/methods/gating.ts +43 -0
- package/src/methods/methods.ts +8 -0
- package/src/methods/mutation.ts +300 -0
- package/src/methods/rate.ts +257 -0
- package/src/methods/selection.ts +65 -0
- package/src/multithreading/README.md +274 -0
- package/src/multithreading/multi.ts +339 -0
- package/src/multithreading/workers/README.md +23 -0
- package/src/multithreading/workers/browser/README.md +39 -0
- package/src/multithreading/workers/browser/testworker.ts +99 -0
- package/src/multithreading/workers/node/README.md +33 -0
- package/src/multithreading/workers/node/testworker.ts +72 -0
- package/src/multithreading/workers/node/worker.ts +70 -0
- package/src/multithreading/workers/workers.ts +22 -0
- package/src/neat/README.md +1284 -0
- package/src/neat/neat.adaptive.ts +544 -0
- package/src/neat/neat.compat.ts +164 -0
- package/src/neat/neat.constants.ts +20 -0
- package/src/neat/neat.diversity.ts +217 -0
- package/src/neat/neat.evaluate.ts +328 -0
- package/src/neat/neat.evolve.ts +1026 -0
- package/src/neat/neat.export.ts +249 -0
- package/src/neat/neat.helpers.ts +235 -0
- package/src/neat/neat.lineage.ts +220 -0
- package/src/neat/neat.multiobjective.ts +260 -0
- package/src/neat/neat.mutation.ts +718 -0
- package/src/neat/neat.objectives.ts +157 -0
- package/src/neat/neat.pruning.ts +190 -0
- package/src/neat/neat.selection.ts +269 -0
- package/src/neat/neat.speciation.ts +460 -0
- package/src/neat/neat.species.ts +151 -0
- package/src/neat/neat.telemetry.exports.ts +469 -0
- package/src/neat/neat.telemetry.ts +933 -0
- package/src/neat/neat.types.ts +275 -0
- package/src/neat.ts +1042 -0
- package/src/neataptic.ts +10 -0
- package/test/architecture/activationArrayPool.capacity.test.ts +19 -0
- package/test/architecture/activationArrayPool.test.ts +46 -0
- package/test/architecture/connection.test.ts +290 -0
- package/test/architecture/group.test.ts +950 -0
- package/test/architecture/layer.test.ts +1535 -0
- package/test/architecture/network.pruning.test.ts +65 -0
- package/test/architecture/node.test.ts +1602 -0
- package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +499 -0
- package/test/examples/asciiMaze/asciiMaze.ts +41 -0
- package/test/examples/asciiMaze/browser-entry.ts +164 -0
- package/test/examples/asciiMaze/browserLogger.ts +221 -0
- package/test/examples/asciiMaze/browserTerminalUtility.ts +48 -0
- package/test/examples/asciiMaze/colors.ts +119 -0
- package/test/examples/asciiMaze/dashboardManager.ts +968 -0
- package/test/examples/asciiMaze/evolutionEngine.ts +1248 -0
- package/test/examples/asciiMaze/fitness.ts +136 -0
- package/test/examples/asciiMaze/index.html +128 -0
- package/test/examples/asciiMaze/index.ts +26 -0
- package/test/examples/asciiMaze/interfaces.ts +235 -0
- package/test/examples/asciiMaze/mazeMovement.ts +996 -0
- package/test/examples/asciiMaze/mazeUtils.ts +278 -0
- package/test/examples/asciiMaze/mazeVision.ts +402 -0
- package/test/examples/asciiMaze/mazeVisualization.ts +585 -0
- package/test/examples/asciiMaze/mazes.ts +245 -0
- package/test/examples/asciiMaze/networkRefinement.ts +76 -0
- package/test/examples/asciiMaze/networkVisualization.ts +901 -0
- package/test/examples/asciiMaze/terminalUtility.ts +73 -0
- package/test/methods/activation.test.ts +1142 -0
- package/test/methods/connection.test.ts +146 -0
- package/test/methods/cost.test.ts +1123 -0
- package/test/methods/crossover.test.ts +202 -0
- package/test/methods/gating.test.ts +144 -0
- package/test/methods/mutation.test.ts +451 -0
- package/test/methods/optimizers.advanced.test.ts +80 -0
- package/test/methods/optimizers.behavior.test.ts +105 -0
- package/test/methods/optimizers.formula.test.ts +89 -0
- package/test/methods/rate.cosineWarmRestarts.test.ts +44 -0
- package/test/methods/rate.linearWarmupDecay.test.ts +41 -0
- package/test/methods/rate.reduceOnPlateau.test.ts +45 -0
- package/test/methods/rate.test.ts +684 -0
- package/test/methods/selection.test.ts +245 -0
- package/test/multithreading/activations.functions.test.ts +54 -0
- package/test/multithreading/multi.test.ts +290 -0
- package/test/multithreading/worker.node.process.test.ts +39 -0
- package/test/multithreading/workers.coverage.test.ts +36 -0
- package/test/multithreading/workers.dynamic.import.test.ts +8 -0
- package/test/neat/neat.adaptive.complexityBudget.test.ts +34 -0
- package/test/neat/neat.adaptive.criterion.complexity.test.ts +50 -0
- package/test/neat/neat.adaptive.mutation.strategy.test.ts +37 -0
- package/test/neat/neat.adaptive.operator.decay.test.ts +31 -0
- package/test/neat/neat.adaptive.phasedComplexity.test.ts +25 -0
- package/test/neat/neat.adaptive.pruning.test.ts +25 -0
- package/test/neat/neat.adaptive.targetSpecies.test.ts +43 -0
- package/test/neat/neat.additional.coverage.test.ts +126 -0
- package/test/neat/neat.advanced.enhancements.test.ts +85 -0
- package/test/neat/neat.advanced.test.ts +589 -0
- package/test/neat/neat.diversity.autocompat.test.ts +47 -0
- package/test/neat/neat.diversity.metrics.test.ts +21 -0
- package/test/neat/neat.diversity.stats.test.ts +44 -0
- package/test/neat/neat.enhancements.test.ts +79 -0
- package/test/neat/neat.entropy.ancestorAdaptive.test.ts +133 -0
- package/test/neat/neat.entropy.compat.csv.test.ts +108 -0
- package/test/neat/neat.evolution.pruning.test.ts +39 -0
- package/test/neat/neat.fastmode.autotune.test.ts +42 -0
- package/test/neat/neat.innovation.test.ts +134 -0
- package/test/neat/neat.lineage.antibreeding.test.ts +35 -0
- package/test/neat/neat.lineage.entropy.test.ts +56 -0
- package/test/neat/neat.lineage.inbreeding.test.ts +49 -0
- package/test/neat/neat.lineage.pressure.test.ts +29 -0
- package/test/neat/neat.multiobjective.adaptive.test.ts +57 -0
- package/test/neat/neat.multiobjective.dynamic.schedule.test.ts +46 -0
- package/test/neat/neat.multiobjective.dynamic.test.ts +31 -0
- package/test/neat/neat.multiobjective.fastsort.delegation.test.ts +51 -0
- package/test/neat/neat.multiobjective.prune.test.ts +39 -0
- package/test/neat/neat.multiobjective.test.ts +21 -0
- package/test/neat/neat.mutation.undefined.pool.test.ts +24 -0
- package/test/neat/neat.objective.events.test.ts +26 -0
- package/test/neat/neat.objective.importance.test.ts +21 -0
- package/test/neat/neat.objective.lifetimes.test.ts +33 -0
- package/test/neat/neat.offspring.allocation.test.ts +22 -0
- package/test/neat/neat.operator.bandit.test.ts +17 -0
- package/test/neat/neat.operator.phases.test.ts +38 -0
- package/test/neat/neat.pruneInactive.behavior.test.ts +54 -0
- package/test/neat/neat.reenable.adaptation.test.ts +18 -0
- package/test/neat/neat.rng.state.test.ts +22 -0
- package/test/neat/neat.spawn.add.test.ts +123 -0
- package/test/neat/neat.speciation.test.ts +96 -0
- package/test/neat/neat.species.allocation.telemetry.test.ts +26 -0
- package/test/neat/neat.species.history.csv.test.ts +24 -0
- package/test/neat/neat.telemetry.advanced.test.ts +226 -0
- package/test/neat/neat.telemetry.csv.lineage.test.ts +19 -0
- package/test/neat/neat.telemetry.parity.test.ts +42 -0
- package/test/neat/neat.telemetry.stream.test.ts +19 -0
- package/test/neat/neat.telemetry.test.ts +16 -0
- package/test/neat/neat.test.ts +422 -0
- package/test/neat/neat.utilities.test.ts +44 -0
- package/test/network/__suppress_console.ts +9 -0
- package/test/network/acyclic.topoorder.test.ts +17 -0
- package/test/network/checkpoint.metricshook.test.ts +36 -0
- package/test/network/error.handling.test.ts +581 -0
- package/test/network/evolution.test.ts +285 -0
- package/test/network/genetic.test.ts +208 -0
- package/test/network/learning.capability.test.ts +244 -0
- package/test/network/mutation.effects.test.ts +492 -0
- package/test/network/network.activate.test.ts +115 -0
- package/test/network/network.activateBatch.test.ts +30 -0
- package/test/network/network.deterministic.test.ts +64 -0
- package/test/network/network.evolve.branches.test.ts +75 -0
- package/test/network/network.evolve.multithread.branches.test.ts +83 -0
- package/test/network/network.evolve.test.ts +100 -0
- package/test/network/network.gating.removal.test.ts +93 -0
- package/test/network/network.mutate.additional.test.ts +145 -0
- package/test/network/network.mutate.edgecases.test.ts +101 -0
- package/test/network/network.mutate.test.ts +101 -0
- package/test/network/network.prune.earlyexit.test.ts +38 -0
- package/test/network/network.remove.errors.test.ts +45 -0
- package/test/network/network.slab.fallbacks.test.ts +22 -0
- package/test/network/network.stats.test.ts +45 -0
- package/test/network/network.training.advanced.test.ts +149 -0
- package/test/network/network.training.basic.test.ts +228 -0
- package/test/network/network.training.helpers.test.ts +183 -0
- package/test/network/onnx.export.test.ts +310 -0
- package/test/network/onnx.import.test.ts +129 -0
- package/test/network/pruning.topology.test.ts +282 -0
- package/test/network/regularization.determinism.test.ts +83 -0
- package/test/network/regularization.dropconnect.test.ts +17 -0
- package/test/network/regularization.dropconnect.validation.test.ts +18 -0
- package/test/network/regularization.stochasticdepth.test.ts +27 -0
- package/test/network/regularization.test.ts +843 -0
- package/test/network/regularization.weightnoise.test.ts +30 -0
- package/test/network/setupTests.ts +2 -0
- package/test/network/standalone.test.ts +332 -0
- package/test/network/structure.serialization.test.ts +660 -0
- package/test/training/training.determinism.mixed-precision.test.ts +134 -0
- package/test/training/training.earlystopping.test.ts +91 -0
- package/test/training/training.edge-cases.test.ts +91 -0
- package/test/training/training.extensions.test.ts +47 -0
- package/test/training/training.gradient.features.test.ts +110 -0
- package/test/training/training.gradient.refinements.test.ts +170 -0
- package/test/training/training.gradient.separate-bias.test.ts +41 -0
- package/test/training/training.optimizer.test.ts +48 -0
- package/test/training/training.plateau.smoothing.test.ts +58 -0
- package/test/training/training.smoothing.types.test.ts +174 -0
- package/test/training/training.train.options.coverage.test.ts +52 -0
- package/test/utils/console-helper.ts +76 -0
- package/test/utils/jest-setup.ts +60 -0
- package/test/utils/test-helpers.ts +175 -0
- package/tsconfig.docs.json +12 -0
- package/tsconfig.json +21 -0
- package/webpack.config.js +49 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import type Network from '../network';
|
|
2
|
+
import { activationArrayPool } from '../activationArrayPool';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Network activation helpers (forward pass utilities).
|
|
6
|
+
*
|
|
7
|
+
* This module provides progressively lower–overhead entry points for performing
|
|
8
|
+
* forward propagation through a {@link Network}. The emphasis is on:
|
|
9
|
+
* 1. Educative clarity – each step is documented so newcomers can follow the
|
|
10
|
+
* life‑cycle of a forward pass in a neural network graph.
|
|
11
|
+
* 2. Performance – fast paths avoid unnecessary allocation and bookkeeping when
|
|
12
|
+
* gradients / evolution traces are not needed.
|
|
13
|
+
* 3. Safety – pooled buffers are never exposed directly to the public API.
|
|
14
|
+
*
|
|
15
|
+
* Exported functions:
|
|
16
|
+
* - {@link noTraceActivate}: ultra‑light inference (no gradients, minimal allocation).
|
|
17
|
+
* - {@link activateRaw}: thin semantic alias around the canonical Network.activate path.
|
|
18
|
+
* - {@link activateBatch}: simple mini‑batch loop utility.
|
|
19
|
+
*
|
|
20
|
+
* Design terminology used below:
|
|
21
|
+
* - Topological order: a sequence of nodes such that all directed connections flow forward.
|
|
22
|
+
* - Slab: a contiguous typed‑array structure packing node activations for vectorized math.
|
|
23
|
+
* - Trace / gradient bookkeeping: auxiliary data (e.g. eligibility traces, derivative caches)
|
|
24
|
+
* required for training algorithms; skipped in inference‑only modes.
|
|
25
|
+
* - Pool: an object managing reusable arrays to reduce garbage collection pressure.
|
|
26
|
+
*
|
|
27
|
+
* @module network.activate
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Perform a forward pass without creating or updating any training / gradient traces.
|
|
32
|
+
*
|
|
33
|
+
* This is the most allocation‑sensitive activation path. Internally it will attempt
|
|
34
|
+
* to leverage a compact "fast slab" routine (an optimized, vectorized broadcast over
|
|
35
|
+
* contiguous activation buffers) when the Network instance indicates that such a path
|
|
36
|
+
* is currently valid. If that attempt fails (for instance because the slab is stale
|
|
37
|
+
* after a structural mutation) execution gracefully falls back to a node‑by‑node loop.
|
|
38
|
+
*
|
|
39
|
+
* Algorithm outline:
|
|
40
|
+
* 1. (Optional) Refresh cached topological order if the network enforces acyclicity
|
|
41
|
+
* and a structural change marked the order as dirty.
|
|
42
|
+
* 2. Validate the input dimensionality.
|
|
43
|
+
* 3. Try the fast slab path; if it throws, continue with the standard path.
|
|
44
|
+
* 4. Acquire a pooled output buffer sized to the number of output neurons.
|
|
45
|
+
* 5. Iterate all nodes in their internal order:
|
|
46
|
+
* - Input nodes: directly assign provided input values.
|
|
47
|
+
* - Hidden nodes: compute activation via Node.noTraceActivate (no bookkeeping).
|
|
48
|
+
* - Output nodes: compute activation and store it (in sequence) inside the
|
|
49
|
+
* pooled output buffer.
|
|
50
|
+
* 6. Copy the pooled buffer into a fresh array (detaches user from the pool) and
|
|
51
|
+
* release the pooled buffer back to the pool.
|
|
52
|
+
*
|
|
53
|
+
* Complexity considerations:
|
|
54
|
+
* - Time: O(N + E) where N = number of nodes, E = number of inbound edges processed
|
|
55
|
+
* inside each Node.noTraceActivate call (not explicit here but inside the node).
|
|
56
|
+
* - Space: O(O) transient (O = number of outputs) due to the pooled output buffer.
|
|
57
|
+
*
|
|
58
|
+
* @param this - Bound {@link Network} instance.
|
|
59
|
+
* @param input - Flat numeric vector whose length must equal network.input.
|
|
60
|
+
* @returns Array of output neuron activations (length == network.output).
|
|
61
|
+
* @throws {Error} If the provided input vector length mismatches the network's input size.
|
|
62
|
+
* @example
|
|
63
|
+
* const out = net.noTraceActivate([0.1, 0.2, 0.3]);
|
|
64
|
+
* console.log(out); // => e.g. [0.5123, 0.0441]
|
|
65
|
+
* @remarks Safe for inference hot paths; not suitable when gradients / training traces are required.
|
|
66
|
+
*/
|
|
67
|
+
export function noTraceActivate(this: Network, input: number[]): number[] {
|
|
68
|
+
/**
|
|
69
|
+
* Reference to the network instance cast to any so internal/private helper properties
|
|
70
|
+
* (underscored fields & fast path flags) can be accessed without TypeScript complaints.
|
|
71
|
+
*/
|
|
72
|
+
const self = this as any;
|
|
73
|
+
|
|
74
|
+
// Step 1: Ensure that if we require an acyclic graph, our cached topological
|
|
75
|
+
// ordering of nodes is current. A fresh order guarantees deterministic forward propagation.
|
|
76
|
+
if (self._enforceAcyclic && self._topoDirty)
|
|
77
|
+
(this as any)._computeTopoOrder();
|
|
78
|
+
|
|
79
|
+
// Step 2: Basic validation – mismatched length typically indicates a user error.
|
|
80
|
+
if (!Array.isArray(input) || input.length !== this.input) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Input size mismatch: expected ${this.input}, got ${
|
|
83
|
+
input ? (input as any).length : 'undefined'
|
|
84
|
+
}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Step 3: Attempt a zero‑allocation vectorized activation over a packed slab. We wrap
|
|
89
|
+
// the call in a try/catch to avoid penalizing typical paths with conditional prechecks.
|
|
90
|
+
if ((this as any)._canUseFastSlab(false)) {
|
|
91
|
+
try {
|
|
92
|
+
return (this as any)._fastSlabActivate(input);
|
|
93
|
+
} catch {
|
|
94
|
+
// Silent fallback – correctness first; performance is opportunistic here.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Step 4: Acquire a pooled typed array (or array‑like) sized to the number of outputs.
|
|
99
|
+
/** Pooled buffer to collect output activations in order. */
|
|
100
|
+
/**
|
|
101
|
+
* Pooled activation output buffer sized to the number of output neurons; will be cloned
|
|
102
|
+
* into a plain array before returning to the caller to avoid external mutation of pooled memory.
|
|
103
|
+
*/
|
|
104
|
+
const output = activationArrayPool.acquire(this.output);
|
|
105
|
+
|
|
106
|
+
// Maintain a manual write index to decouple node iteration order from output layout.
|
|
107
|
+
/**
|
|
108
|
+
* Sequential index into the pooled output buffer. Increments each time we process
|
|
109
|
+
* an output node so we produce a dense, zero‑gap array matching logical output order.
|
|
110
|
+
*/
|
|
111
|
+
/** Sequential write index into the pooled output buffer. */
|
|
112
|
+
let outIndex = 0;
|
|
113
|
+
|
|
114
|
+
// Step 5: Iterate every node once. For hidden nodes we simply invoke noTraceActivate;
|
|
115
|
+
// its internal logic will read predecessor activations already set during earlier steps.
|
|
116
|
+
this.nodes.forEach((node, index) => {
|
|
117
|
+
// Input nodes: feed value directly from the corresponding slot in the provided input vector.
|
|
118
|
+
if (node.type === 'input') node.noTraceActivate(input[index]);
|
|
119
|
+
// Output nodes: compute their activation (which implicitly uses upstream hidden/input nodes) and store.
|
|
120
|
+
else if (node.type === 'output')
|
|
121
|
+
(output as any)[outIndex++] = node.noTraceActivate();
|
|
122
|
+
// Hidden nodes: just activate (value stored internally on the node itself).
|
|
123
|
+
else node.noTraceActivate();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Step 6: Copy pooled buffer to a fresh standard array so external callers cannot mutate
|
|
127
|
+
// the pooled object after it's released (which would create hard‑to‑trace bugs).
|
|
128
|
+
/** Detached plain array containing final output activations. */
|
|
129
|
+
/** Final detached output activation vector. */
|
|
130
|
+
const result = Array.from(output as any) as number[];
|
|
131
|
+
|
|
132
|
+
// Always release pooled resources promptly to keep memory pressure low for future calls.
|
|
133
|
+
activationArrayPool.release(output);
|
|
134
|
+
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Thin semantic alias to the network's main activation path.
|
|
140
|
+
*
|
|
141
|
+
* At present this simply forwards to {@link Network.activate}. The indirection is useful for:
|
|
142
|
+
* - Future differentiation between raw (immediate) activation and a mode that performs reuse /
|
|
143
|
+
* staged batching logic.
|
|
144
|
+
* - Providing a stable exported symbol for external tooling / instrumentation.
|
|
145
|
+
*
|
|
146
|
+
* @param this - Bound {@link Network} instance.
|
|
147
|
+
* @param input - Input vector (length == network.input).
|
|
148
|
+
* @param training - Whether to retain training traces / gradients (delegated downstream).
|
|
149
|
+
* @param maxActivationDepth - Guard against runaway recursion / cyclic activation attempts.
|
|
150
|
+
* @returns Implementation-defined result of Network.activate (typically an output vector).
|
|
151
|
+
* @example
|
|
152
|
+
* const y = net.activateRaw([0,1,0]);
|
|
153
|
+
* @remarks Keep this wrapper lightweight; heavy logic should live inside Network.activate itself.
|
|
154
|
+
*/
|
|
155
|
+
export function activateRaw(
|
|
156
|
+
this: Network,
|
|
157
|
+
input: number[],
|
|
158
|
+
training = false,
|
|
159
|
+
maxActivationDepth = 1000
|
|
160
|
+
): any {
|
|
161
|
+
/** Access internal flags / helpers (private-ish) via a loose cast. */
|
|
162
|
+
const self = this as any;
|
|
163
|
+
|
|
164
|
+
// If the network is not reusing activation arrays there's nothing special to do – delegate.
|
|
165
|
+
if (!self._reuseActivationArrays)
|
|
166
|
+
return (this as any).activate(input, training, maxActivationDepth);
|
|
167
|
+
|
|
168
|
+
// Even when reuse is enabled we currently still just delegate; hook point for future optimization.
|
|
169
|
+
return (this as any).activate(input, training, maxActivationDepth);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Activate the network over a mini‑batch (array) of input vectors, returning a 2‑D array of outputs.
|
|
174
|
+
*
|
|
175
|
+
* This helper simply loops, invoking {@link Network.activate} (or its bound variant) for each
|
|
176
|
+
* sample. It is intentionally naive: no attempt is made to fuse operations across the batch.
|
|
177
|
+
* For very large batch sizes or performance‑critical paths consider implementing a custom
|
|
178
|
+
* vectorized backend that exploits SIMD, GPU kernels, or parallel workers.
|
|
179
|
+
*
|
|
180
|
+
* Input validation occurs per row to surface the earliest mismatch with a descriptive index.
|
|
181
|
+
*
|
|
182
|
+
* @param this - Bound {@link Network} instance.
|
|
183
|
+
* @param inputs - Array of input vectors; each must have length == network.input.
|
|
184
|
+
* @param training - Whether each activation should keep training traces.
|
|
185
|
+
* @returns 2‑D array: outputs[i] is the activation result for inputs[i].
|
|
186
|
+
* @throws {Error} If inputs is not an array, or any contained vector has an incorrect length.
|
|
187
|
+
* @example
|
|
188
|
+
* const batchOut = net.activateBatch([[0,0,1],[1,0,0],[0,1,0]]);
|
|
189
|
+
* console.log(batchOut.length); // 3 rows
|
|
190
|
+
* @remarks For small batches this is perfectly adequate and clear.
|
|
191
|
+
*/
|
|
192
|
+
export function activateBatch(
|
|
193
|
+
this: Network,
|
|
194
|
+
inputs: number[][],
|
|
195
|
+
training = false
|
|
196
|
+
): number[][] {
|
|
197
|
+
// Global validation – ensure we can iterate as expected.
|
|
198
|
+
if (!Array.isArray(inputs))
|
|
199
|
+
throw new Error('inputs must be an array of input arrays');
|
|
200
|
+
|
|
201
|
+
/** Preallocate the output matrix at the correct height (one row per input). */
|
|
202
|
+
/** Output matrix (row-major) where each row corresponds to activation of one input vector. */
|
|
203
|
+
const out: number[][] = new Array(inputs.length);
|
|
204
|
+
|
|
205
|
+
// Iterate sequentially – early exit behavior (via throw) will surface the first invalid row.
|
|
206
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
207
|
+
/** Current input vector under evaluation. */
|
|
208
|
+
/** Input vector at batch index i currently being processed. */
|
|
209
|
+
const x = inputs[i];
|
|
210
|
+
// Validate row dimensionality with a descriptive index for easier debugging.
|
|
211
|
+
if (!Array.isArray(x) || x.length !== this.input) {
|
|
212
|
+
throw new Error(
|
|
213
|
+
`Input[${i}] size mismatch: expected ${this.input}, got ${
|
|
214
|
+
x ? x.length : 'undefined'
|
|
215
|
+
}`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
// Delegate to the network's activation (may perform tracing if training=true).
|
|
219
|
+
out[i] = (this as any).activate(x, training);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import type Network from '../network';
|
|
2
|
+
import Node from '../node';
|
|
3
|
+
import Connection from '../connection';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Network structural mutation helpers (connect / disconnect).
|
|
7
|
+
*
|
|
8
|
+
* This module centralizes the logic for adding and removing edges (connections) between
|
|
9
|
+
* nodes in a {@link Network}. By isolating the book‑keeping here we keep the primary
|
|
10
|
+
* Network class lean and ensure consistent handling of:
|
|
11
|
+
* - Acyclic constraints
|
|
12
|
+
* - Multiple low‑level connections returned by composite node operations
|
|
13
|
+
* - Gating & self‑connection invariants
|
|
14
|
+
* - Cache invalidation (topological order + packed activation slabs)
|
|
15
|
+
*
|
|
16
|
+
* Exported functions:
|
|
17
|
+
* - {@link connect}: Create one or more connections from a source node to a target node.
|
|
18
|
+
* - {@link disconnect}: Remove (at most) one direct connection from source to target.
|
|
19
|
+
*
|
|
20
|
+
* Key terminology:
|
|
21
|
+
* - Self‑connection: An edge where from === to (loop). Usually disallowed under acyclicity.
|
|
22
|
+
* - Gating: A mechanism where a third node modulates (gates) the weight / influence of a connection.
|
|
23
|
+
* - Slab: Packed typed‑array representation of connections for vectorized forward passes.
|
|
24
|
+
*
|
|
25
|
+
* @module network.connect
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create and register one (or multiple) directed connection objects between two nodes.
|
|
30
|
+
*
|
|
31
|
+
* Some node types (or future composite structures) may return several low‑level connections when
|
|
32
|
+
* their {@link Node.connect} is invoked (e.g., expanded recurrent templates). For that reason this
|
|
33
|
+
* function always treats the result as an array and appends each edge to the appropriate collection.
|
|
34
|
+
*
|
|
35
|
+
* Algorithm outline:
|
|
36
|
+
* 1. (Acyclic guard) If acyclicity is enforced and the source node appears after the target node in
|
|
37
|
+
* the network's node ordering, abort early and return an empty array (prevents back‑edge creation).
|
|
38
|
+
* 2. Delegate to sourceNode.connect(targetNode, weight) to build the raw Connection object(s).
|
|
39
|
+
* 3. For each created connection:
|
|
40
|
+
* a. If it's a self‑connection: either ignore (acyclic mode) or store in selfconns.
|
|
41
|
+
* b. Otherwise store in standard connections array.
|
|
42
|
+
* 4. If any connection was added, mark structural caches dirty (_topoDirty & _slabDirty) so lazy
|
|
43
|
+
* rebuild can occur before the next forward pass.
|
|
44
|
+
*
|
|
45
|
+
* Complexity:
|
|
46
|
+
* - Time: O(k) where k is the number of low‑level connections returned (typically 1).
|
|
47
|
+
* - Space: O(k) new Connection instances (delegated to Node.connect).
|
|
48
|
+
*
|
|
49
|
+
* Edge cases & invariants:
|
|
50
|
+
* - Acyclic mode silently refuses back‑edges instead of throwing (makes evolutionary search easier).
|
|
51
|
+
* - Self‑connections are skipped entirely when acyclicity is enforced.
|
|
52
|
+
* - Weight initialization policy is delegated to Node.connect if not explicitly provided.
|
|
53
|
+
*
|
|
54
|
+
* @param this - Bound {@link Network} instance.
|
|
55
|
+
* @param from - Source node (emits signal).
|
|
56
|
+
* @param to - Target node (receives signal).
|
|
57
|
+
* @param weight - Optional explicit initial weight value.
|
|
58
|
+
* @returns Array of created {@link Connection} objects (possibly empty if acyclicity rejected the edge).
|
|
59
|
+
* @example
|
|
60
|
+
* const [edge] = net.connect(nodeA, nodeB, 0.5);
|
|
61
|
+
* @remarks For bulk layer-to-layer wiring see higher-level utilities that iterate groups.
|
|
62
|
+
*/
|
|
63
|
+
export function connect(
|
|
64
|
+
this: Network,
|
|
65
|
+
from: Node,
|
|
66
|
+
to: Node,
|
|
67
|
+
weight?: number
|
|
68
|
+
): Connection[] {
|
|
69
|
+
// Step 1: Acyclic pre‑check – prevents cycles by disallowing edges that point "backwards" in order.
|
|
70
|
+
if (
|
|
71
|
+
(this as any)._enforceAcyclic &&
|
|
72
|
+
this.nodes.indexOf(from) > this.nodes.indexOf(to)
|
|
73
|
+
)
|
|
74
|
+
return [];
|
|
75
|
+
|
|
76
|
+
// Step 2: Delegate creation to the node. May return >1 low‑level connections (treat generically).
|
|
77
|
+
/** Array of new connection objects produced by the source node. */
|
|
78
|
+
const connections = from.connect(to, weight);
|
|
79
|
+
|
|
80
|
+
// Step 3: Register each new connection in the appropriate collection.
|
|
81
|
+
for (const c of connections) {
|
|
82
|
+
// c: individual low‑level connection
|
|
83
|
+
if (from !== to) {
|
|
84
|
+
// Standard edge (feed‑forward or recurrent) tracked in 'connections'.
|
|
85
|
+
this.connections.push(c);
|
|
86
|
+
} else {
|
|
87
|
+
// Self‑connection: only valid when acyclicity is not enforced.
|
|
88
|
+
if ((this as any)._enforceAcyclic) continue; // Skip silently to preserve invariant.
|
|
89
|
+
this.selfconns.push(c);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Step 4: Invalidate caches if we materially changed structure (at least one edge added).
|
|
94
|
+
if (connections.length) {
|
|
95
|
+
(this as any)._topoDirty = true; // Topological ordering must be recomputed lazily.
|
|
96
|
+
(this as any)._slabDirty = true; // Packed connection slab requires rebuild for fast activation path.
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return connections; // Return created edges so caller can inspect / further manipulate (e.g., gating).
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Remove (at most) one directed connection from source 'from' to target 'to'.
|
|
104
|
+
*
|
|
105
|
+
* Only a single direct edge is removed because typical graph configurations maintain at most
|
|
106
|
+
* one logical connection between a given pair of nodes (excluding potential future multi‑edge
|
|
107
|
+
* semantics). If the target edge is gated we first call {@link Network.ungate} to maintain
|
|
108
|
+
* gating invariants (ensuring the gater node's internal gate list remains consistent).
|
|
109
|
+
*
|
|
110
|
+
* Algorithm outline:
|
|
111
|
+
* 1. Choose the correct list (selfconns vs connections) based on whether from === to.
|
|
112
|
+
* 2. Linear scan to find the first edge with matching endpoints.
|
|
113
|
+
* 3. If gated, ungate to detach gater bookkeeping.
|
|
114
|
+
* 4. Splice the edge out; exit loop (only one expected).
|
|
115
|
+
* 5. Delegate per‑node cleanup via from.disconnect(to) (clears reverse references, traces, etc.).
|
|
116
|
+
* 6. Mark structural caches dirty for lazy recomputation.
|
|
117
|
+
*
|
|
118
|
+
* Complexity:
|
|
119
|
+
* - Time: O(m) where m is length of the searched list (connections or selfconns).
|
|
120
|
+
* - Space: O(1) extra.
|
|
121
|
+
*
|
|
122
|
+
* Idempotence: If no such edge exists we still perform node-level disconnect and flag caches dirty –
|
|
123
|
+
* this conservative approach simplifies callers (they need not pre‑check existence).
|
|
124
|
+
*
|
|
125
|
+
* @param this - Bound {@link Network} instance.
|
|
126
|
+
* @param from - Source node.
|
|
127
|
+
* @param to - Target node.
|
|
128
|
+
* @example
|
|
129
|
+
* net.disconnect(nodeA, nodeB);
|
|
130
|
+
* @remarks For removing many edges consider higher‑level bulk utilities to avoid repeated scans.
|
|
131
|
+
*/
|
|
132
|
+
export function disconnect(this: Network, from: Node, to: Node): void {
|
|
133
|
+
// Step 1: Select list to search: selfconns for loops, otherwise normal connections.
|
|
134
|
+
/** Candidate list of connections to inspect for removal. */
|
|
135
|
+
const list = from === to ? this.selfconns : this.connections;
|
|
136
|
+
|
|
137
|
+
// Step 2: Linear scan – lists are typically small relative to node count; acceptable trade‑off.
|
|
138
|
+
for (let i = 0; i < list.length; i++) {
|
|
139
|
+
/** Connection currently inspected. */
|
|
140
|
+
const c = list[i];
|
|
141
|
+
if (c.from === from && c.to === to) {
|
|
142
|
+
// Found target edge
|
|
143
|
+
// Step 3: If gated, maintain gating invariants by ungating before removal.
|
|
144
|
+
if (c.gater) this.ungate(c);
|
|
145
|
+
// Step 4: Remove and exit (only one expected between a pair of nodes).
|
|
146
|
+
list.splice(i, 1);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Step 5: Node-level cleanup (clears internal references, derivative / eligibility traces, etc.).
|
|
152
|
+
from.disconnect(to);
|
|
153
|
+
|
|
154
|
+
// Step 6: Structural mutation => mark caches dirty so next activation can rebuild fast-path artifacts.
|
|
155
|
+
(this as any)._topoDirty = true;
|
|
156
|
+
(this as any)._slabDirty = true;
|
|
157
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type Network from '../network';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Deterministic pseudo‑random number generation (PRNG) utilities for {@link Network}.
|
|
5
|
+
*
|
|
6
|
+
* Why this module exists:
|
|
7
|
+
* - Facilitates reproducible evolutionary runs / gradient training by allowing explicit seeding.
|
|
8
|
+
* - Centralizes RNG state management & snapshot/restore operations (useful for rollbacks or
|
|
9
|
+
* deterministic tests around mutation sequences).
|
|
10
|
+
* - Keeps the core Network class focused by extracting ancillary RNG concerns.
|
|
11
|
+
*
|
|
12
|
+
* Implementation notes:
|
|
13
|
+
* - Uses a small, fast 32‑bit xorshift / mix style generator (same semantics as the legacy inline version)
|
|
14
|
+
* combining an additive Weyl sequence step plus a few avalanche-style integer mixes.
|
|
15
|
+
* - Not cryptographically secure. Do not use for security / fairness sensitive applications.
|
|
16
|
+
* - Produces floating point numbers in [0,1) with 2^32 (~4.29e9) discrete possible mantissa states.
|
|
17
|
+
*
|
|
18
|
+
* Public surface:
|
|
19
|
+
* - {@link setSeed}: Initialize deterministic generator with a numeric seed.
|
|
20
|
+
* - {@link snapshotRNG}: Capture current training step + raw internal RNG state.
|
|
21
|
+
* - {@link restoreRNG}: Provide an externally saved RNG function (advanced) & clear stored state.
|
|
22
|
+
* - {@link getRNGState} / {@link setRNGState}: Low-level accessors for the internal 32‑bit state word.
|
|
23
|
+
* - {@link getRandomFn}: Retrieve the active random() function reference (primarily for tests / tooling).
|
|
24
|
+
*
|
|
25
|
+
* Design rationale:
|
|
26
|
+
* - Storing both a state integer (_rngState) and a function (_rand) allows hot-swapping alternative
|
|
27
|
+
* RNG implementations (e.g., for benchmarking or pluggable randomness strategies) without rewriting
|
|
28
|
+
* callsites inside Network algorithms.
|
|
29
|
+
*
|
|
30
|
+
* @module network.deterministic
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/** Shape of an RNG snapshot object. */
|
|
34
|
+
export interface RNGSnapshot {
|
|
35
|
+
step: number | undefined;
|
|
36
|
+
state: number | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Seed the internal PRNG and install a deterministic random() implementation on the Network instance.
|
|
41
|
+
*
|
|
42
|
+
* Process:
|
|
43
|
+
* 1. Coerce the provided seed to an unsigned 32‑bit integer (>>> 0) for predictable wraparound behavior.
|
|
44
|
+
* 2. Define an inline closure that advances an internal 32‑bit state using:
|
|
45
|
+
* a. A Weyl increment (adding constant 0x6D2B79F5 each call) ensuring full-period traversal of
|
|
46
|
+
* the 32‑bit space when combined with mixing.
|
|
47
|
+
* b. Two rounds of xorshift / integer mixing (xor, shifts, multiplications) to decorrelate bits.
|
|
48
|
+
* c. Normalization to [0,1) by dividing the final 32‑bit unsigned integer by 2^32.
|
|
49
|
+
*
|
|
50
|
+
* Bit-mixing explanation (rough intuition):
|
|
51
|
+
* - XOR with shifted versions spreads high-order entropy to lower bits.
|
|
52
|
+
* - Multiplication (Math.imul) with carefully chosen odd constants introduces non-linear mixing.
|
|
53
|
+
* - The final right shift & xor avalanche aims to reduce sequential correlation.
|
|
54
|
+
*
|
|
55
|
+
* @param this - Bound {@link Network} instance.
|
|
56
|
+
* @param seed - Any finite number; only its lower 32 bits are used.
|
|
57
|
+
* @example
|
|
58
|
+
* net.setSeed(1234);
|
|
59
|
+
* const a = net.getRandomFn()(); // deterministic given the seed
|
|
60
|
+
* net.setSeed(1234);
|
|
61
|
+
* const b = net.getRandomFn()(); // a === b
|
|
62
|
+
*/
|
|
63
|
+
export function setSeed(this: Network, seed: number): void {
|
|
64
|
+
// Store 32-bit unsigned state (bitwise ops in JS operate on signed 32-bit but we keep consistency via >>> 0).
|
|
65
|
+
(this as any)._rngState = seed >>> 0;
|
|
66
|
+
// Install PRNG closure referencing _rngState by name for mutation on each invocation.
|
|
67
|
+
(this as any)._rand = () => {
|
|
68
|
+
// Add Weyl constant (chosen odd constant) & coerce to uint32 wraparound.
|
|
69
|
+
(this as any)._rngState = ((this as any)._rngState + 0x6d2b79f5) >>> 0;
|
|
70
|
+
// First mix: xor with shifted self and multiply (Math.imul preserves 32-bit overflow semantics).
|
|
71
|
+
let r = Math.imul(
|
|
72
|
+
(this as any)._rngState ^ ((this as any)._rngState >>> 15),
|
|
73
|
+
1 | (this as any)._rngState
|
|
74
|
+
);
|
|
75
|
+
// Second mix: avalanche style bit diffusion.
|
|
76
|
+
r ^= r + Math.imul(r ^ (r >>> 7), 61 | r);
|
|
77
|
+
// Final xor/shift; convert to unsigned, then scale to [0,1).
|
|
78
|
+
return ((r ^ (r >>> 14)) >>> 0) / 4294967296; // 2^32
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Capture a snapshot of the RNG state together with the network's training step.
|
|
84
|
+
*
|
|
85
|
+
* Useful for implementing speculative evolutionary mutations where you may revert both the
|
|
86
|
+
* structural change and the randomness timeline if accepting/rejecting a candidate.
|
|
87
|
+
*
|
|
88
|
+
* @param this - Bound {@link Network} instance.
|
|
89
|
+
* @returns Object containing current training step & 32‑bit RNG state (both possibly undefined if unseeded).
|
|
90
|
+
* @example
|
|
91
|
+
* const snap = net.snapshotRNG();
|
|
92
|
+
* // ... perform operations
|
|
93
|
+
* net.setRNGState(snap.state!);
|
|
94
|
+
*/
|
|
95
|
+
export function snapshotRNG(this: Network): RNGSnapshot {
|
|
96
|
+
return { step: (this as any)._trainingStep, state: (this as any)._rngState };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Restore a previously captured RNG function implementation (advanced usage).
|
|
101
|
+
*
|
|
102
|
+
* This does NOT rehydrate _rngState (it explicitly sets it to undefined). Intended for scenarios
|
|
103
|
+
* where a caller has customly serialized a full RNG closure or wants to inject a deterministic stub.
|
|
104
|
+
* If you only need to restore the raw state word produced by {@link snapshotRNG}, prefer
|
|
105
|
+
* {@link setRNGState} instead.
|
|
106
|
+
*
|
|
107
|
+
* @param this - Bound {@link Network} instance.
|
|
108
|
+
* @param fn - Function returning a pseudo‑random number in [0,1). Caller guarantees determinism if required.
|
|
109
|
+
* @example
|
|
110
|
+
* const original = net.getRandomFn();
|
|
111
|
+
* net.restoreRNG(() => 0.5); // force constant RNG for a test
|
|
112
|
+
* // ... test invariants ...
|
|
113
|
+
* net.restoreRNG(original); // restore
|
|
114
|
+
*/
|
|
115
|
+
export function restoreRNG(this: Network, fn: () => number): void {
|
|
116
|
+
(this as any)._rand = fn;
|
|
117
|
+
(this as any)._rngState = undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get the current internal 32‑bit RNG state value.
|
|
122
|
+
*
|
|
123
|
+
* @param this - Bound {@link Network} instance.
|
|
124
|
+
* @returns Unsigned 32‑bit state integer or undefined if generator not yet seeded or was reset.
|
|
125
|
+
*/
|
|
126
|
+
export function getRNGState(this: Network): number | undefined {
|
|
127
|
+
return (this as any)._rngState as number | undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Explicitly set (override) the internal 32‑bit RNG state without changing the generator function.
|
|
132
|
+
*
|
|
133
|
+
* This is a low‑level operation; typical clients should call {@link setSeed}. Provided for advanced
|
|
134
|
+
* replay functionality where the same PRNG algorithm is assumed but you want to resume exactly at a
|
|
135
|
+
* known state word.
|
|
136
|
+
*
|
|
137
|
+
* @param this - Bound {@link Network} instance.
|
|
138
|
+
* @param state - Any finite number (only low 32 bits used). Ignored if not numeric.
|
|
139
|
+
*/
|
|
140
|
+
export function setRNGState(this: Network, state: number): void {
|
|
141
|
+
if (typeof state === 'number') (this as any)._rngState = state >>> 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Retrieve the active random function reference (for testing, instrumentation, or swapping).
|
|
146
|
+
*
|
|
147
|
+
* Mutating the returned function's closure variables (if any) is not recommended; prefer using
|
|
148
|
+
* higher-level APIs (setSeed / restoreRNG) to manage state.
|
|
149
|
+
*
|
|
150
|
+
* @param this - Bound {@link Network} instance.
|
|
151
|
+
* @returns Function producing numbers in [0,1). May be undefined if never seeded (call setSeed first).
|
|
152
|
+
*/
|
|
153
|
+
export function getRandomFn(this: Network): (() => number) | undefined {
|
|
154
|
+
return (this as any)._rand as () => number;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Default export bundle for convenient named imports.
|
|
159
|
+
*/
|
|
160
|
+
export default {
|
|
161
|
+
setSeed,
|
|
162
|
+
snapshotRNG,
|
|
163
|
+
restoreRNG,
|
|
164
|
+
getRNGState,
|
|
165
|
+
setRNGState,
|
|
166
|
+
getRandomFn,
|
|
167
|
+
};
|