@reicek/neataptic-ts 0.1.26 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/agents/boundary-mapper.agent.md +13 -8
- package/.github/agents/docs-scout.agent.md +14 -9
- package/.github/agents/plan-scout.agent.md +11 -6
- package/.github/agents/solid-split.agent.md +33 -17
- package/.github/copilot-instructions.md +100 -88
- package/.github/skills/educational-docs/SKILL.md +90 -40
- package/.github/skills/educational-docs/assets/mermaid-diagram-playbook.md +141 -141
- package/.github/skills/educational-docs/assets/visual-style-guide.md +1 -1
- package/.github/skills/plan-alignment/SKILL.md +1 -1
- package/.github/skills/solid-split/SKILL.md +54 -35
- package/.github/skills/solid-split/assets/docs-checklist.md +1 -1
- package/.github/skills/solid-split/assets/split-plan-template.md +41 -12
- package/.github/skills/solid-split/assets/split-workflow-checklist.md +4 -1
- package/.github/skills/test-fix-workflow/SKILL.md +12 -7
- package/.github/skills/trace-analyzer-extension/SKILL.md +1 -1
- package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
- package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
- package/.github/skills/trace-audit-reporting/SKILL.md +1 -1
- package/.github/skills/trace-audit-reporting/assets/performance-report-template.md +1 -1
- package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
- package/.github/skills/tracker-handoff/SKILL.md +53 -5
- package/package.json +1 -1
- package/plans/Flappy_Bird_Folder_Documentation_Pass.logs.md +42 -0
- package/plans/Flappy_Bird_Folder_Documentation_Pass.md +22 -104
- package/plans/README.md +6 -2
- package/plans/Roadmap.md +35 -31
- package/plans/analyze-trace-solid-split.logs.md +35 -0
- package/plans/analyze-trace-solid-split.plans.md +21 -52
- package/plans/architecture-solid-split.logs.md +44 -0
- package/plans/architecture-solid-split.plans.md +20 -653
- package/plans/asciiMaze-typescript-repair.logs.md +35 -0
- package/plans/asciiMaze-typescript-repair.plans.md +30 -36
- package/plans/generate-docs-solid-split.logs.md +36 -0
- package/plans/generate-docs-solid-split.plans.md +21 -73
- package/plans/methods-docs.logs.md +37 -0
- package/plans/methods-docs.plans.md +22 -183
- package/plans/methods-solid-split.logs.md +41 -0
- package/plans/methods-solid-split.plans.md +23 -65
- package/plans/neat-docs.logs.md +38 -0
- package/plans/neat-docs.plans.md +21 -63
- package/plans/neat-test-surface-repair.logs.md +38 -0
- package/plans/neat-test-surface-repair.plans.md +24 -24
- package/plans/readme-first-section-pass.logs.md +63 -0
- package/plans/readme-first-section-pass.plans.md +42 -0
- package/plans/render-docs-html-solid-split.logs.md +36 -0
- package/plans/render-docs-html-solid-split.plans.md +20 -54
- package/plans/src-no-explicit-any-cleanup.logs.md +39 -0
- package/plans/src-no-explicit-any-cleanup.plans.md +23 -161
- package/plans/utils-docs.logs.md +37 -0
- package/plans/utils-docs.plans.md +20 -35
- package/src/README.md +88 -22
- package/src/architecture/README.md +94 -17
- package/src/architecture/activationArrayPool/README.md +53 -0
- package/src/architecture/activationArrayPool/activationArrayPool.ts +53 -0
- package/src/architecture/layer/README.md +94 -5
- package/src/architecture/layer/layer.ts +94 -5
- package/src/architecture/network/README.md +85 -14
- package/src/architecture/network/activate/README.md +301 -213
- package/src/architecture/network/activate/docs.order.json +9 -0
- package/src/architecture/network/activate/network.activate.utils.ts +90 -0
- package/src/architecture/network/connect/README.md +80 -3
- package/src/architecture/network/connect/docs.order.json +9 -0
- package/src/architecture/network/connect/network.connect.utils.ts +79 -0
- package/src/architecture/network/deterministic/README.md +96 -12
- package/src/architecture/network/deterministic/docs.order.json +10 -0
- package/src/architecture/network/deterministic/network.deterministic.utils.ts +90 -0
- package/src/architecture/network/evolve/README.md +286 -228
- package/src/architecture/network/evolve/docs.order.json +11 -0
- package/src/architecture/network/evolve/network.evolve.utils.ts +59 -0
- package/src/architecture/network/gating/README.md +58 -16
- package/src/architecture/network/gating/docs.order.json +9 -0
- package/src/architecture/network/gating/network.gating.utils.ts +43 -0
- package/src/architecture/network/genetic/README.md +75 -36
- package/src/architecture/network/genetic/docs.order.json +10 -0
- package/src/architecture/network/genetic/network.genetic.utils.ts +53 -17
- package/src/architecture/network/network.ts +91 -46
- package/src/architecture/network/standalone/README.md +309 -285
- package/src/architecture/network/standalone/docs.order.json +13 -0
- package/src/architecture/network/standalone/network.standalone.utils.ts +51 -28
- package/src/architecture/network.ts +94 -17
- package/src/architecture/nodePool/README.md +53 -0
- package/src/architecture/nodePool/nodePool.ts +53 -0
- package/src/methods/README.md +80 -34
- package/src/methods/methods.ts +80 -34
- package/src/methods/mutation/README.md +39 -93
- package/src/methods/mutation/mutation.ts +58 -0
- package/src/multithreading/README.md +114 -14
- package/src/multithreading/docs.order.json +5 -0
- package/src/multithreading/multi.ts +103 -7
- package/src/multithreading/types.ts +6 -1
- package/src/multithreading/workers/README.md +72 -2
- package/src/multithreading/workers/browser/README.md +39 -0
- package/src/multithreading/workers/browser/testworker.ts +40 -0
- package/src/multithreading/workers/node/README.md +50 -11
- package/src/multithreading/workers/node/docs.order.json +4 -0
- package/src/multithreading/workers/node/testworker.ts +43 -3
- package/src/multithreading/workers/workers.ts +36 -1
- package/src/neat/README.md +230 -152
- package/src/neat/adaptive/core/README.md +99 -42
- package/src/neat/adaptive/core/adaptive.core.ts +71 -14
- package/src/neat/adaptive/core/docs.order.json +8 -0
- package/src/neat/docs.order.json +9 -0
- package/src/neat/lineage/README.md +118 -16
- package/src/neat/lineage/lineage.ts +115 -13
- package/src/neat/neat.defaults.constants.ts +91 -13
- package/src/neat.ts +86 -20
- package/src/utils/README.md +71 -21
- package/src/utils/memory.ts +69 -19
- package/test/examples/asciiMaze/browser-entry/README.md +81 -8
- package/test/examples/asciiMaze/browser-entry/browser-entry.ts +81 -8
- package/test/examples/asciiMaze/dashboardManager/README.md +68 -4
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +68 -4
- package/test/examples/asciiMaze/evolutionEngine/README.md +1259 -1174
- package/test/examples/asciiMaze/evolutionEngine/docs.order.json +10 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +87 -0
- package/test/examples/asciiMaze/mazeMovement/README.md +81 -4
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +81 -4
- package/test/examples/flappy_bird/browser-entry/README.md +64 -21
- package/test/examples/flappy_bird/browser-entry/browser-entry.ts +64 -21
- package/test/examples/flappy_bird/flappy-evolution-worker/README.md +98 -10
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +98 -10
- package/test/examples/flappy_bird/simulation-shared/README.md +88 -4
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.types.ts +88 -4
|
@@ -1,117 +1,63 @@
|
|
|
1
1
|
# methods/mutation
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
overgrown search,
|
|
29
|
-
- parameter-tuning operators such as `MOD_WEIGHT`, `MOD_BIAS`, and
|
|
30
|
-
`REINIT_WEIGHT` change numeric behavior without rewriting the graph,
|
|
31
|
-
- behavior-shaping operators such as `MOD_ACTIVATION`, `ADD_GATE`,
|
|
32
|
-
`SUB_GATE`, and `SWAP_NODES` change how existing structure computes,
|
|
33
|
-
- architecture-expansion operators such as `ADD_LSTM_NODE` and
|
|
34
|
-
`ADD_GRU_NODE` introduce memory-oriented building blocks.
|
|
35
|
-
|
|
36
|
-
A practical reading order is:
|
|
37
|
-
|
|
38
|
-
1. start with `MOD_WEIGHT` and `MOD_BIAS` to understand the gentlest search
|
|
39
|
-
moves,
|
|
40
|
-
2. then compare `ADD_CONN` and `ADD_NODE` to see how structure starts to
|
|
41
|
-
grow,
|
|
42
|
-
3. then read the recurrent and gating operators when you want temporal
|
|
43
|
-
behavior or context-sensitive routing,
|
|
44
|
-
4. finish with `ALL` and `FFW`, which summarize which operators belong in a
|
|
45
|
-
broad search versus a strictly feedforward one.
|
|
46
|
-
|
|
47
|
-
A practical chooser for first experiments:
|
|
48
|
-
|
|
49
|
-
- begin with weight and bias mutations when the topology is already plausible
|
|
50
|
-
and you mainly want numeric refinement,
|
|
51
|
-
- allow `ADD_CONN` and `ADD_NODE` when the current architecture feels too
|
|
52
|
-
rigid or too shallow,
|
|
53
|
-
- enable gating or back-connections only when temporal memory or dynamic
|
|
54
|
-
routing is actually part of the task,
|
|
55
|
-
- prefer `FFW` as the safe shelf when a run must remain strictly
|
|
56
|
-
feedforward.
|
|
3
|
+
Mutation policy shelf for neuroevolution runs.
|
|
4
|
+
|
|
5
|
+
This chapter belongs in `methods/` rather than `architecture/network/mutate/`
|
|
6
|
+
because it does not execute one mutation against one concrete graph. It
|
|
7
|
+
defines the reusable operator vocabulary that higher-level controllers pick
|
|
8
|
+
from before any specific network is touched. The network chapter later uses
|
|
9
|
+
that vocabulary to dispatch real edits.
|
|
10
|
+
|
|
11
|
+
Read the shelf in five families. Growth operators add structure. Pruning
|
|
12
|
+
operators remove it. Parameter operators retune weights and biases without
|
|
13
|
+
rewriting topology. Behavior operators change activation or gating policy.
|
|
14
|
+
Memory operators add recurrent building blocks when the search should be
|
|
15
|
+
allowed to invent stateful behavior.
|
|
16
|
+
|
|
17
|
+
Those families matter because mutation is where an evolutionary run decides
|
|
18
|
+
whether it is mostly refining a plausible graph or still exploring new
|
|
19
|
+
architectures. A shelf dominated by `MOD_WEIGHT` and `MOD_BIAS` behaves like
|
|
20
|
+
local numeric search. A shelf that also allows `ADD_NODE`, `ADD_CONN`, and
|
|
21
|
+
gating or recurrent operators gives the run permission to change what the
|
|
22
|
+
network can represent at all.
|
|
23
|
+
|
|
24
|
+
`ALL` and `FFW` are the two convenience summaries at the bottom of the
|
|
25
|
+
chapter. `ALL` keeps the widest search surface, including recurrence and
|
|
26
|
+
memory additions. `FFW` keeps the feedforward-safe subset for runs that must
|
|
27
|
+
remain acyclic.
|
|
57
28
|
|
|
58
29
|
```mermaid
|
|
59
30
|
flowchart TD
|
|
60
|
-
Mutation[Mutation
|
|
31
|
+
Mutation[Mutation shelf] --> Grow[Grow structure]
|
|
61
32
|
Mutation --> Prune[Prune structure]
|
|
62
33
|
Mutation --> Tune[Tune parameters]
|
|
63
34
|
Mutation --> Shape[Reshape behavior]
|
|
64
35
|
Mutation --> Memory[Add memory blocks]
|
|
65
|
-
Grow --> GrowItems[ADD_NODE ADD_CONN ADD_SELF_CONN ADD_BACK_CONN]
|
|
66
|
-
Prune --> PruneItems[SUB_NODE SUB_CONN SUB_SELF_CONN SUB_BACK_CONN]
|
|
67
|
-
Tune --> TuneItems[MOD_WEIGHT MOD_BIAS REINIT_WEIGHT]
|
|
68
|
-
Shape --> ShapeItems[MOD_ACTIVATION ADD_GATE SUB_GATE SWAP_NODES]
|
|
69
|
-
Memory --> MemoryItems[ADD_LSTM_NODE ADD_GRU_NODE]
|
|
70
36
|
```
|
|
71
37
|
|
|
72
|
-
|
|
38
|
+
For compact background on why mutation pressure matters in evolutionary
|
|
39
|
+
search, see Wikipedia contributors,
|
|
40
|
+
[Mutation (genetic algorithm)](https://en.wikipedia.org/wiki/Mutation_(genetic_algorithm)).
|
|
41
|
+
|
|
42
|
+
Example: keep a feedforward-safe shelf for searches that must remain simple
|
|
43
|
+
and acyclic.
|
|
73
44
|
|
|
74
45
|
```ts
|
|
75
|
-
const
|
|
46
|
+
const feedforwardOnly = mutation.FFW;
|
|
47
|
+
```
|
|
76
48
|
|
|
77
|
-
|
|
49
|
+
Example: widen the shelf when structural exploration is part of the goal.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const structuralExploration = [
|
|
78
53
|
mutation.ADD_CONN,
|
|
79
54
|
mutation.ADD_NODE,
|
|
80
55
|
mutation.MOD_WEIGHT,
|
|
81
|
-
mutation.MOD_BIAS,
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
const recurrentSearchShelf = [
|
|
85
|
-
...structuralSearchShelf,
|
|
86
56
|
mutation.ADD_GATE,
|
|
87
|
-
mutation.ADD_BACK_CONN,
|
|
88
57
|
];
|
|
89
58
|
```
|
|
90
59
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
- `ADD_NODE`: Adds a new node by splitting an existing connection.
|
|
94
|
-
- `SUB_NODE`: Removes a hidden node and its connections.
|
|
95
|
-
- `ADD_CONN`: Adds a new connection between two unconnected nodes.
|
|
96
|
-
- `SUB_CONN`: Removes an existing connection.
|
|
97
|
-
- `MOD_WEIGHT`: Modifies the weight of an existing connection.
|
|
98
|
-
- `MOD_BIAS`: Modifies the bias of a node.
|
|
99
|
-
- `MOD_ACTIVATION`: Changes the activation function of a node.
|
|
100
|
-
- `ADD_SELF_CONN`: Adds a self-connection (recurrent loop) to a node.
|
|
101
|
-
- `SUB_SELF_CONN`: Removes a self-connection from a node.
|
|
102
|
-
- `ADD_GATE`: Adds a gating mechanism to a connection.
|
|
103
|
-
- `SUB_GATE`: Removes a gating mechanism from a connection.
|
|
104
|
-
- `ADD_BACK_CONN`: Adds a recurrent (backward) connection between nodes.
|
|
105
|
-
- `SUB_BACK_CONN`: Removes a recurrent (backward) connection.
|
|
106
|
-
- `SWAP_NODES`: Swaps the roles (bias and activation) of two nodes.
|
|
107
|
-
- `REINIT_WEIGHT`: Reinitializes all weights for a node.
|
|
108
|
-
- `BATCH_NORM`: Marks a node for batch normalization (stub).
|
|
109
|
-
- `ADD_LSTM_NODE`: Adds a new LSTM node (memory cell with gates).
|
|
110
|
-
- `ADD_GRU_NODE`: Adds a new GRU node (gated recurrent unit).
|
|
111
|
-
|
|
112
|
-
Summary shelves:
|
|
113
|
-
- `ALL`: all mutation methods, including recurrent and memory-oriented ones.
|
|
114
|
-
- `FFW`: the feedforward-safe subset that avoids recurrence and gating.
|
|
60
|
+
## methods/mutation/mutation.ts
|
|
115
61
|
|
|
116
62
|
### MutationConfig
|
|
117
63
|
|
|
@@ -1,3 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mutation policy shelf for neuroevolution runs.
|
|
3
|
+
*
|
|
4
|
+
* This chapter belongs in `methods/` rather than `architecture/network/mutate/`
|
|
5
|
+
* because it does not execute one mutation against one concrete graph. It
|
|
6
|
+
* defines the reusable operator vocabulary that higher-level controllers pick
|
|
7
|
+
* from before any specific network is touched. The network chapter later uses
|
|
8
|
+
* that vocabulary to dispatch real edits.
|
|
9
|
+
*
|
|
10
|
+
* Read the shelf in five families. Growth operators add structure. Pruning
|
|
11
|
+
* operators remove it. Parameter operators retune weights and biases without
|
|
12
|
+
* rewriting topology. Behavior operators change activation or gating policy.
|
|
13
|
+
* Memory operators add recurrent building blocks when the search should be
|
|
14
|
+
* allowed to invent stateful behavior.
|
|
15
|
+
*
|
|
16
|
+
* Those families matter because mutation is where an evolutionary run decides
|
|
17
|
+
* whether it is mostly refining a plausible graph or still exploring new
|
|
18
|
+
* architectures. A shelf dominated by `MOD_WEIGHT` and `MOD_BIAS` behaves like
|
|
19
|
+
* local numeric search. A shelf that also allows `ADD_NODE`, `ADD_CONN`, and
|
|
20
|
+
* gating or recurrent operators gives the run permission to change what the
|
|
21
|
+
* network can represent at all.
|
|
22
|
+
*
|
|
23
|
+
* `ALL` and `FFW` are the two convenience summaries at the bottom of the
|
|
24
|
+
* chapter. `ALL` keeps the widest search surface, including recurrence and
|
|
25
|
+
* memory additions. `FFW` keeps the feedforward-safe subset for runs that must
|
|
26
|
+
* remain acyclic.
|
|
27
|
+
*
|
|
28
|
+
* ```mermaid
|
|
29
|
+
* flowchart TD
|
|
30
|
+
* Mutation[Mutation shelf] --> Grow[Grow structure]
|
|
31
|
+
* Mutation --> Prune[Prune structure]
|
|
32
|
+
* Mutation --> Tune[Tune parameters]
|
|
33
|
+
* Mutation --> Shape[Reshape behavior]
|
|
34
|
+
* Mutation --> Memory[Add memory blocks]
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* For compact background on why mutation pressure matters in evolutionary
|
|
38
|
+
* search, see Wikipedia contributors,
|
|
39
|
+
* [Mutation (genetic algorithm)](https://en.wikipedia.org/wiki/Mutation_(genetic_algorithm)).
|
|
40
|
+
*
|
|
41
|
+
* Example: keep a feedforward-safe shelf for searches that must remain simple
|
|
42
|
+
* and acyclic.
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* const feedforwardOnly = mutation.FFW;
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* Example: widen the shelf when structural exploration is part of the goal.
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* const structuralExploration = [
|
|
52
|
+
* mutation.ADD_CONN,
|
|
53
|
+
* mutation.ADD_NODE,
|
|
54
|
+
* mutation.MOD_WEIGHT,
|
|
55
|
+
* mutation.ADD_GATE,
|
|
56
|
+
* ];
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
1
59
|
import Activation from '../activation/activation';
|
|
2
60
|
|
|
3
61
|
/**
|
|
@@ -1,24 +1,112 @@
|
|
|
1
1
|
# multithreading
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Worker-oriented evaluation helpers and serialization compatibility shelf.
|
|
4
|
+
|
|
5
|
+
This chapter exists for a practical scaling problem: evolutionary evaluation
|
|
6
|
+
is usually embarrassingly parallel, but live `Network` instances, activation
|
|
7
|
+
closures, and environment-specific worker APIs do not cross thread boundaries
|
|
8
|
+
cleanly. The multithreading root turns that mismatch into a teachable
|
|
9
|
+
contract: flatten the network and dataset into portable numeric arrays, keep
|
|
10
|
+
activation functions in a stable index order, and let browser or Node workers
|
|
11
|
+
evaluate the same payload shape without needing the whole runtime object
|
|
12
|
+
graph.
|
|
13
|
+
|
|
14
|
+
The most important idea here is not "threads are faster." It is boundary
|
|
15
|
+
control. A worker can only do useful NEAT work if the training host and the
|
|
16
|
+
worker agree on three things: how a network is serialized, how activations
|
|
17
|
+
are decoded, and how the result comes back as a scalar score. This root file
|
|
18
|
+
keeps that contract explicit so the rest of the library can talk about
|
|
19
|
+
parallel evaluation without hand-waving away the serialization boundary.
|
|
20
|
+
|
|
21
|
+
The chapter is intentionally narrow. It does not implement a generic
|
|
22
|
+
scheduler or a broad actor framework. It exposes a small compatibility shelf
|
|
23
|
+
around two tasks that matter for evaluation: ship datasets and networks
|
|
24
|
+
across a worker boundary, and run the same ordered activation logic on the
|
|
25
|
+
other side. That makes the boundary useful both for actual worker-backed
|
|
26
|
+
evaluation and for teaching how data-parallel neural evaluation is shaped.
|
|
27
|
+
|
|
28
|
+
Read the root in three passes:
|
|
29
|
+
|
|
30
|
+
1. `serializeDataSet()` and `deserializeDataSet()` for the portable sample
|
|
31
|
+
format.
|
|
32
|
+
2. `activations` and `activateSerializedNetwork()` for the flat execution
|
|
33
|
+
contract.
|
|
34
|
+
3. `getBrowserTestWorker()` and `getNodeTestWorker()` for the runtime-
|
|
35
|
+
specific loader boundary.
|
|
36
|
+
|
|
37
|
+
`browser/` and `node/` own the environment-specific worker wrappers, while
|
|
38
|
+
`multi.utils.ts` owns the flat-array execution mechanics. The root stays
|
|
39
|
+
orchestration-first for the same reason as the rest of the repo: readers
|
|
40
|
+
should see the contract before they see the inner loops.
|
|
41
|
+
|
|
42
|
+
The background idea here is close to what distributed-systems and HPC writing
|
|
43
|
+
often call an embarrassingly parallel workload: each genome can be evaluated
|
|
44
|
+
independently once its inputs and scoring context are serialized. See
|
|
45
|
+
Wikipedia contributors,
|
|
46
|
+
[Embarrassingly parallel](https://en.wikipedia.org/wiki/Embarrassingly_parallel),
|
|
47
|
+
for compact background on why evolutionary evaluation is such a natural fit
|
|
48
|
+
for worker-style execution.
|
|
49
|
+
|
|
50
|
+
```mermaid
|
|
51
|
+
flowchart LR
|
|
52
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
53
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
54
|
+
|
|
55
|
+
Host[Training or test host]:::base --> Serialize[Flatten dataset and network]:::accent
|
|
56
|
+
Serialize --> Worker[Browser or Node worker]:::base
|
|
57
|
+
Worker --> Activate[Run ordered activation logic]:::base
|
|
58
|
+
Activate --> Score[Return scalar evaluation]:::accent
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```mermaid
|
|
62
|
+
flowchart TD
|
|
63
|
+
classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
64
|
+
classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
65
|
+
|
|
66
|
+
Multi[Multi root facade]:::accent --> Dataset[serializeDataSet / deserializeDataSet]:::base
|
|
67
|
+
Multi --> Runtime[Browser and Node worker loaders]:::base
|
|
68
|
+
Multi --> Activations[Stable activation index registry]:::base
|
|
69
|
+
Activations --> FlatExecution[activateSerializedNetwork]:::base
|
|
70
|
+
Runtime --> Workers[workers/]:::base
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Example: serialize one dataset once and evaluate a network in a Node worker.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const serializedSet = Multi.serializeDataSet([
|
|
77
|
+
{ input: [0, 0], output: [0] },
|
|
78
|
+
{ input: [1, 1], output: [1] },
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
const NodeWorker = await Multi.getNodeTestWorker();
|
|
82
|
+
const worker = new NodeWorker(serializedSet, { name: 'mse' });
|
|
83
|
+
const score = await worker.evaluate(network);
|
|
84
|
+
worker.terminate();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Example: run the worker-compatible flat activation path locally.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
const [activationValues, stateValues, serializedNetwork] = network.serialize();
|
|
91
|
+
const outputValues = Multi.activateSerializedNetwork(
|
|
92
|
+
[0, 1],
|
|
93
|
+
activationValues.slice(),
|
|
94
|
+
stateValues.slice(),
|
|
95
|
+
serializedNetwork,
|
|
96
|
+
Multi.activations,
|
|
97
|
+
);
|
|
98
|
+
```
|
|
4
99
|
|
|
5
100
|
## multithreading/multi.ts
|
|
6
101
|
|
|
7
|
-
### multi
|
|
8
|
-
|
|
9
|
-
Multi-threading utilities for neural network operations.
|
|
10
|
-
|
|
11
|
-
This class provides methods for serializing datasets, activating serialized networks,
|
|
12
|
-
and testing serialized datasets. These utilities align with the Instinct algorithm's
|
|
13
|
-
emphasis on efficient evaluation and mutation of neural networks in parallel environments.
|
|
14
|
-
|
|
15
102
|
### Multi
|
|
16
103
|
|
|
17
|
-
|
|
104
|
+
Stable compatibility facade for worker-oriented evaluation helpers.
|
|
18
105
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
106
|
+
Read `Multi` as the small public shelf around three related contracts:
|
|
107
|
+
portable dataset serialization, flat-array network activation, and runtime-
|
|
108
|
+
specific worker loading. The heavier mechanics live in `multi.utils.ts` and
|
|
109
|
+
`workers/`, but the class keeps the outside-facing API compact and familiar.
|
|
22
110
|
|
|
23
111
|
### default
|
|
24
112
|
|
|
@@ -301,6 +389,13 @@ Workers for multi-threading
|
|
|
301
389
|
|
|
302
390
|
## multithreading/types.ts
|
|
303
391
|
|
|
392
|
+
Shared contracts for the multithreading boundary.
|
|
393
|
+
|
|
394
|
+
These types keep the worker-facing evaluation surface small: ordered
|
|
395
|
+
activation functions, serialized input/output samples, a serializable network
|
|
396
|
+
shape, and the worker constructor protocol used by the browser and Node test
|
|
397
|
+
worker wrappers.
|
|
398
|
+
|
|
304
399
|
### ActivationFn
|
|
305
400
|
|
|
306
401
|
```ts
|
|
@@ -309,7 +404,12 @@ ActivationFn(
|
|
|
309
404
|
): number
|
|
310
405
|
```
|
|
311
406
|
|
|
312
|
-
Shared
|
|
407
|
+
Shared contracts for the multithreading boundary.
|
|
408
|
+
|
|
409
|
+
These types keep the worker-facing evaluation surface small: ordered
|
|
410
|
+
activation functions, serialized input/output samples, a serializable network
|
|
411
|
+
shape, and the worker constructor protocol used by the browser and Node test
|
|
412
|
+
worker wrappers.
|
|
313
413
|
|
|
314
414
|
### SerializableNetwork
|
|
315
415
|
|
|
@@ -1,3 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker-oriented evaluation helpers and serialization compatibility shelf.
|
|
3
|
+
*
|
|
4
|
+
* This chapter exists for a practical scaling problem: evolutionary evaluation
|
|
5
|
+
* is usually embarrassingly parallel, but live `Network` instances, activation
|
|
6
|
+
* closures, and environment-specific worker APIs do not cross thread boundaries
|
|
7
|
+
* cleanly. The multithreading root turns that mismatch into a teachable
|
|
8
|
+
* contract: flatten the network and dataset into portable numeric arrays, keep
|
|
9
|
+
* activation functions in a stable index order, and let browser or Node workers
|
|
10
|
+
* evaluate the same payload shape without needing the whole runtime object
|
|
11
|
+
* graph.
|
|
12
|
+
*
|
|
13
|
+
* The most important idea here is not "threads are faster." It is boundary
|
|
14
|
+
* control. A worker can only do useful NEAT work if the training host and the
|
|
15
|
+
* worker agree on three things: how a network is serialized, how activations
|
|
16
|
+
* are decoded, and how the result comes back as a scalar score. This root file
|
|
17
|
+
* keeps that contract explicit so the rest of the library can talk about
|
|
18
|
+
* parallel evaluation without hand-waving away the serialization boundary.
|
|
19
|
+
*
|
|
20
|
+
* The chapter is intentionally narrow. It does not implement a generic
|
|
21
|
+
* scheduler or a broad actor framework. It exposes a small compatibility shelf
|
|
22
|
+
* around two tasks that matter for evaluation: ship datasets and networks
|
|
23
|
+
* across a worker boundary, and run the same ordered activation logic on the
|
|
24
|
+
* other side. That makes the boundary useful both for actual worker-backed
|
|
25
|
+
* evaluation and for teaching how data-parallel neural evaluation is shaped.
|
|
26
|
+
*
|
|
27
|
+
* Read the root in three passes:
|
|
28
|
+
*
|
|
29
|
+
* 1. `serializeDataSet()` and `deserializeDataSet()` for the portable sample
|
|
30
|
+
* format.
|
|
31
|
+
* 2. `activations` and `activateSerializedNetwork()` for the flat execution
|
|
32
|
+
* contract.
|
|
33
|
+
* 3. `getBrowserTestWorker()` and `getNodeTestWorker()` for the runtime-
|
|
34
|
+
* specific loader boundary.
|
|
35
|
+
*
|
|
36
|
+
* `browser/` and `node/` own the environment-specific worker wrappers, while
|
|
37
|
+
* `multi.utils.ts` owns the flat-array execution mechanics. The root stays
|
|
38
|
+
* orchestration-first for the same reason as the rest of the repo: readers
|
|
39
|
+
* should see the contract before they see the inner loops.
|
|
40
|
+
*
|
|
41
|
+
* The background idea here is close to what distributed-systems and HPC writing
|
|
42
|
+
* often call an embarrassingly parallel workload: each genome can be evaluated
|
|
43
|
+
* independently once its inputs and scoring context are serialized. See
|
|
44
|
+
* Wikipedia contributors,
|
|
45
|
+
* [Embarrassingly parallel](https://en.wikipedia.org/wiki/Embarrassingly_parallel),
|
|
46
|
+
* for compact background on why evolutionary evaluation is such a natural fit
|
|
47
|
+
* for worker-style execution.
|
|
48
|
+
*
|
|
49
|
+
* ```mermaid
|
|
50
|
+
* flowchart LR
|
|
51
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
52
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
53
|
+
*
|
|
54
|
+
* Host[Training or test host]:::base --> Serialize[Flatten dataset and network]:::accent
|
|
55
|
+
* Serialize --> Worker[Browser or Node worker]:::base
|
|
56
|
+
* Worker --> Activate[Run ordered activation logic]:::base
|
|
57
|
+
* Activate --> Score[Return scalar evaluation]:::accent
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* ```mermaid
|
|
61
|
+
* flowchart TD
|
|
62
|
+
* classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
|
|
63
|
+
* classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;
|
|
64
|
+
*
|
|
65
|
+
* Multi[Multi root facade]:::accent --> Dataset[serializeDataSet / deserializeDataSet]:::base
|
|
66
|
+
* Multi --> Runtime[Browser and Node worker loaders]:::base
|
|
67
|
+
* Multi --> Activations[Stable activation index registry]:::base
|
|
68
|
+
* Activations --> FlatExecution[activateSerializedNetwork]:::base
|
|
69
|
+
* Runtime --> Workers[workers/]:::base
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* Example: serialize one dataset once and evaluate a network in a Node worker.
|
|
73
|
+
*
|
|
74
|
+
* ```ts
|
|
75
|
+
* const serializedSet = Multi.serializeDataSet([
|
|
76
|
+
* { input: [0, 0], output: [0] },
|
|
77
|
+
* { input: [1, 1], output: [1] },
|
|
78
|
+
* ]);
|
|
79
|
+
*
|
|
80
|
+
* const NodeWorker = await Multi.getNodeTestWorker();
|
|
81
|
+
* const worker = new NodeWorker(serializedSet, { name: 'mse' });
|
|
82
|
+
* const score = await worker.evaluate(network);
|
|
83
|
+
* worker.terminate();
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* Example: run the worker-compatible flat activation path locally.
|
|
87
|
+
*
|
|
88
|
+
* ```ts
|
|
89
|
+
* const [activationValues, stateValues, serializedNetwork] = network.serialize();
|
|
90
|
+
* const outputValues = Multi.activateSerializedNetwork(
|
|
91
|
+
* [0, 1],
|
|
92
|
+
* activationValues.slice(),
|
|
93
|
+
* stateValues.slice(),
|
|
94
|
+
* serializedNetwork,
|
|
95
|
+
* Multi.activations,
|
|
96
|
+
* );
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
1
99
|
import { Workers } from './workers/workers';
|
|
2
100
|
import type {
|
|
3
101
|
ActivationFn,
|
|
@@ -29,14 +127,12 @@ import {
|
|
|
29
127
|
} from './multi.utils';
|
|
30
128
|
|
|
31
129
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* This class provides methods for serializing datasets, activating serialized networks,
|
|
35
|
-
* and testing serialized datasets. These utilities align with the Instinct algorithm's
|
|
36
|
-
* emphasis on efficient evaluation and mutation of neural networks in parallel environments.
|
|
130
|
+
* Stable compatibility facade for worker-oriented evaluation helpers.
|
|
37
131
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
132
|
+
* Read `Multi` as the small public shelf around three related contracts:
|
|
133
|
+
* portable dataset serialization, flat-array network activation, and runtime-
|
|
134
|
+
* specific worker loading. The heavier mechanics live in `multi.utils.ts` and
|
|
135
|
+
* `workers/`, but the class keeps the outside-facing API compact and familiar.
|
|
40
136
|
*/
|
|
41
137
|
export default class Multi {
|
|
42
138
|
/** Workers for multi-threading */
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared
|
|
2
|
+
* Shared contracts for the multithreading boundary.
|
|
3
|
+
*
|
|
4
|
+
* These types keep the worker-facing evaluation surface small: ordered
|
|
5
|
+
* activation functions, serialized input/output samples, a serializable network
|
|
6
|
+
* shape, and the worker constructor protocol used by the browser and Node test
|
|
7
|
+
* worker wrappers.
|
|
3
8
|
*/
|
|
4
9
|
export type ActivationFn = (x: number) => number;
|
|
5
10
|
|
|
@@ -1,12 +1,82 @@
|
|
|
1
1
|
# multithreading/workers
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Runtime loader shelf for browser and Node evaluation workers.
|
|
4
|
+
|
|
5
|
+
The multithreading root explains the serialization contract. This file
|
|
6
|
+
answers a narrower question: once a dataset and a network have already been
|
|
7
|
+
flattened into portable arrays, which runtime-specific worker wrapper should
|
|
8
|
+
own the evaluation run?
|
|
9
|
+
|
|
10
|
+
Keeping that choice behind one tiny loader shelf has two benefits. The host
|
|
11
|
+
runtime can defer importing browser-only or Node-only code until it actually
|
|
12
|
+
needs it, and the rest of the library can talk about one worker boundary
|
|
13
|
+
without pretending that Web Workers and forked Node helpers expose the same
|
|
14
|
+
constructor surface.
|
|
15
|
+
|
|
16
|
+
`getBrowserTestWorker()` loads the wrapper that creates a blob-backed worker
|
|
17
|
+
in the browser. `getNodeTestWorker()` loads the wrapper that forks a helper
|
|
18
|
+
process in Node. Both wrappers consume the same serialized payload shape and
|
|
19
|
+
return the same scalar evaluation contract.
|
|
20
|
+
|
|
21
|
+
```mermaid
|
|
22
|
+
flowchart LR
|
|
23
|
+
Host[Host runtime] --> Choose[Choose worker wrapper]
|
|
24
|
+
Choose --> Browser[Browser worker facade]
|
|
25
|
+
Choose --> Node[Node worker facade]
|
|
26
|
+
Browser --> Score[Scalar evaluation]
|
|
27
|
+
Node --> Score
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Example: choose the runtime-specific worker facade without importing both
|
|
31
|
+
implementations up front.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const WorkerClass =
|
|
35
|
+
typeof window === 'undefined'
|
|
36
|
+
? await Workers.getNodeTestWorker()
|
|
37
|
+
: await Workers.getBrowserTestWorker();
|
|
38
|
+
```
|
|
4
39
|
|
|
5
40
|
## multithreading/workers/workers.ts
|
|
6
41
|
|
|
7
42
|
### Workers
|
|
8
43
|
|
|
9
|
-
|
|
44
|
+
Runtime loader shelf for browser and Node evaluation workers.
|
|
45
|
+
|
|
46
|
+
The multithreading root explains the serialization contract. This file
|
|
47
|
+
answers a narrower question: once a dataset and a network have already been
|
|
48
|
+
flattened into portable arrays, which runtime-specific worker wrapper should
|
|
49
|
+
own the evaluation run?
|
|
50
|
+
|
|
51
|
+
Keeping that choice behind one tiny loader shelf has two benefits. The host
|
|
52
|
+
runtime can defer importing browser-only or Node-only code until it actually
|
|
53
|
+
needs it, and the rest of the library can talk about one worker boundary
|
|
54
|
+
without pretending that Web Workers and forked Node helpers expose the same
|
|
55
|
+
constructor surface.
|
|
56
|
+
|
|
57
|
+
`getBrowserTestWorker()` loads the wrapper that creates a blob-backed worker
|
|
58
|
+
in the browser. `getNodeTestWorker()` loads the wrapper that forks a helper
|
|
59
|
+
process in Node. Both wrappers consume the same serialized payload shape and
|
|
60
|
+
return the same scalar evaluation contract.
|
|
61
|
+
|
|
62
|
+
```mermaid
|
|
63
|
+
flowchart LR
|
|
64
|
+
Host[Host runtime] --> Choose[Choose worker wrapper]
|
|
65
|
+
Choose --> Browser[Browser worker facade]
|
|
66
|
+
Choose --> Node[Node worker facade]
|
|
67
|
+
Browser --> Score[Scalar evaluation]
|
|
68
|
+
Node --> Score
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Example: choose the runtime-specific worker facade without importing both
|
|
72
|
+
implementations up front.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
const WorkerClass =
|
|
76
|
+
typeof window === 'undefined'
|
|
77
|
+
? await Workers.getNodeTestWorker()
|
|
78
|
+
: await Workers.getBrowserTestWorker();
|
|
79
|
+
```
|
|
10
80
|
|
|
11
81
|
#### getBrowserTestWorker
|
|
12
82
|
|
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# multithreading/workers/browser
|
|
2
2
|
|
|
3
|
+
Browser-side evaluation worker wrapper for serialized networks.
|
|
4
|
+
|
|
5
|
+
This chapter is the Web Worker half of the multithreading boundary. It does
|
|
6
|
+
not teach activation math again. Its job is to take the flat dataset and
|
|
7
|
+
network contract from `multithreading/`, package it into browser-friendly
|
|
8
|
+
transfer buffers, and return one scalar error without blocking the main
|
|
9
|
+
thread.
|
|
10
|
+
|
|
11
|
+
The lifecycle is intentionally coarse grained. The constructor transfers the
|
|
12
|
+
dataset once and creates a blob-backed worker program. Each `evaluate()` call
|
|
13
|
+
then sends only the activation, state, and connection buffers for one
|
|
14
|
+
candidate network. That keeps the wrapper focused on whole-network scoring
|
|
15
|
+
jobs rather than chatty per-layer messaging.
|
|
16
|
+
|
|
17
|
+
Read the file in runtime order: constructor first, `evaluate()` second,
|
|
18
|
+
`_createBlobString()` last. That matches the actual browser story: bootstrap
|
|
19
|
+
a worker, run repeated evaluations, then inspect how the inline worker code
|
|
20
|
+
is assembled.
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart LR
|
|
24
|
+
Host[Browser host] --> Dataset[Transfer dataset once]
|
|
25
|
+
Dataset --> Blob[Create blob worker]
|
|
26
|
+
Blob --> Evaluate[Transfer network buffers]
|
|
27
|
+
Evaluate --> Error[Return scalar error]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For background on the browser primitive behind this wrapper, see MDN Web
|
|
31
|
+
Docs,
|
|
32
|
+
[Using Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
|
|
33
|
+
|
|
34
|
+
Example: create one browser worker and reuse it across repeated evaluations.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const worker = new TestWorker(serializedSet, { name: 'mse' });
|
|
38
|
+
const score = await worker.evaluate(network);
|
|
39
|
+
worker.terminate();
|
|
40
|
+
```
|
|
41
|
+
|
|
3
42
|
## multithreading/workers/browser/testworker.ts
|
|
4
43
|
|
|
5
44
|
### CostFunction
|