fix(test_framework): pass --tps -1 to server for uncapped headless speed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,175 @@
|
|||||||
|
---
|
||||||
|
name: nim-mcp-tools
|
||||||
|
description: 'Use for Nim symbol navigation, diagnostics, and type resolution. MANDATORY: Use specialized MCP tools (nimFindSymbols, nimFindReferences, nimListSymbols, nimCheckFile, nimCheckProject, nimFindTypeDefinition) first; fall back to grep only on error or user confirmation.'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Nim MCP Tools
|
||||||
|
|
||||||
|
## Core Mandate
|
||||||
|
|
||||||
|
AI agents MUST prefer specialized MCP tools over general-purpose instruments (grep, shell commands, `read_file` with manual parsing) for all Nim symbol-related and Nim diagnostics tasks. This is critical for:
|
||||||
|
|
||||||
|
1. **Token Efficiency**: MCP tools return structured, relevant data, avoiding large file reads or noisy grep outputs.
|
||||||
|
2. **Precision**: These tools understand Nim semantics (scopes, imports, overloads) which string-based search cannot.
|
||||||
|
|
||||||
|
## Activation Rule
|
||||||
|
|
||||||
|
If the user asks to find, rename, remove, audit, update, standardize naming, or fix issues/project of a Nim symbol or its usages, this skill MUST be used first and the workflow must start with the Nim MCP symbol tools.
|
||||||
|
|
||||||
|
If the user asks to check a single Nim file for errors, warnings, hints, diagnostics, issues, problems, or compiler feedback, this skill MUST be used first and the workflow must start with `nimCheckFile`.
|
||||||
|
|
||||||
|
If the user asks to check a Nim project for errors, warnings, hints, diagnostics, issues, problems, compiler feedback, or to "fix" it, this skill MUST be used first and the workflow must start with `nimCheckProject`.
|
||||||
|
|
||||||
|
If the user asks to determine where a symbol comes from, what type it is, what its fields are (including private ones), or resolve a symbol's type definition, this skill MUST be used first and the workflow must start with `nimFindTypeDefinition`.
|
||||||
|
|
||||||
|
This applies to requests phrased as:
|
||||||
|
|
||||||
|
- "find all usages/references of `Foo`"
|
||||||
|
- "remove all definitions of and references to `Foo`"
|
||||||
|
- "rename `Foo` everywhere"
|
||||||
|
- "standardize naming for `Foo`"
|
||||||
|
- "fix casing for all variables"
|
||||||
|
- "where is `Foo` defined?"
|
||||||
|
- "list the symbols in this Nim file/module"
|
||||||
|
- "check this file/module for errors"
|
||||||
|
- "show diagnostics for `foo.nim`"
|
||||||
|
- "check this project/workspace/repository/package for errors"
|
||||||
|
- "fix issues in this project"
|
||||||
|
- "fix the repo"
|
||||||
|
- "find Nim diagnostics in the current codebase"
|
||||||
|
- "show warnings and hints for this repo"
|
||||||
|
- "scan the current module tree for Nim issues"
|
||||||
|
- "what is the type of this symbol?"
|
||||||
|
- "what module/package does this type come from?"
|
||||||
|
- "what fields does this type have?"
|
||||||
|
- "is this a type alias or a concrete type?"
|
||||||
|
- "where is this type defined?"
|
||||||
|
|
||||||
|
Treat user wording such as **project**, **workspace**, **repository**, **repo**, **package**, **codebase**, **checkout**, and **module tree** as referring to the current Nim project context when they are asking for project-wide diagnostics.
|
||||||
|
|
||||||
|
Treat user wording such as **file**, **module** (when a concrete Nim file is identified), **source file**, and explicit `*.nim` paths as referring to single-file diagnostics when they are asking for diagnostics for one file.
|
||||||
|
|
||||||
|
Do **not** pair `nimFindSymbols`, `nimCheckFile`, or `nimCheckProject` with `grep`, `ripgrep`, or shell search "just to double-check". If the task is about a Nim symbol or Nim diagnostics, MCP tools own the search unless they have already failed.
|
||||||
|
|
||||||
|
## User Terminology vs MCP `kind`
|
||||||
|
|
||||||
|
Users may ask for symbol categories using looser or non-strict terminology. AI agents MUST map that wording to the exact Nim MCP `kind` values before filtering results from `nimListSymbols(...)` or `nimFindSymbols(...)`.
|
||||||
|
|
||||||
|
The MCP server returns Nim-oriented kind names derived from nimsuggest symbol kinds with the leading `sk` removed, such as `Const`, `EnumField`, `Field`, `Iterator`, `Converter`, `Let`, `Macro`, `Method`, `Proc`, `Template`, `Type`, `Var`, and `Func`.
|
||||||
|
|
||||||
|
Use these terminology mappings when interpreting user requests:
|
||||||
|
|
||||||
|
- **function** / **functions**: usually match `Func` and `Proc`
|
||||||
|
- **pure function** / **pure functions**: match `Func`
|
||||||
|
- **callable** / **routine**: may include `Func`, `Proc`, `Method`, `Iterator`, `Converter`, `Macro`, and `Template`
|
||||||
|
- **class** / **classes**: match `Type`
|
||||||
|
- **variable** / **variables**: match `Var` and `Let`
|
||||||
|
- **property** / **properties**: match `Field`
|
||||||
|
- **enum member** / **enum members**: match `EnumField`
|
||||||
|
- **constant** / **constants**: match `Const`
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- **Finding References**: To rename a symbol, update a signature, or find usages.
|
||||||
|
- **Symbol Discovery**: To find where a symbol is defined by name.
|
||||||
|
- **Type Resolution**: To determine where a local symbol comes from (which module), what its type is, and what fields it has (including private ones).
|
||||||
|
- **Naming Standardization**: To fix casing or follow style guides across the project.
|
||||||
|
- **Fixing Project Issues**: To iteratively find and resolve all diagnostics in the project.
|
||||||
|
- **File Analysis**: To get an overview of all symbols in a file.
|
||||||
|
- **File Diagnostics**: To check one specific Nim file for errors, warnings, and hints.
|
||||||
|
- **Project Diagnostics**: To check the current Nim project for errors, warnings, and hints.
|
||||||
|
- **Debugging Type Mismatches**: When a diagnostic reveals a type mismatch, use `nimFindTypeDefinition` on both sides.
|
||||||
|
- **Code Generation / Refactoring**: Before generating code that interacts with a type, find its definition.
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
### 1. Find All References or Usages of a Symbol Name
|
||||||
|
|
||||||
|
Do NOT grep for the name.
|
||||||
|
|
||||||
|
1. Call `nimFindSymbols(query: "SymbolName")` to get exact `path`, `line`, and `column`.
|
||||||
|
2. For each relevant result, call `nimFindReferences(path, line, column)`.
|
||||||
|
3. Aggregate the results.
|
||||||
|
|
||||||
|
### 2. List All Symbols in a File
|
||||||
|
|
||||||
|
Do NOT read the whole file to find definitions.
|
||||||
|
|
||||||
|
1. Call `nimListSymbols(path: "path/to/file.nim")`.
|
||||||
|
2. If the user asked for a symbol category, filter by the MCP `kind` values.
|
||||||
|
3. Use the returned list to navigate or analyze the file structure.
|
||||||
|
|
||||||
|
### 3. Find Definitions
|
||||||
|
|
||||||
|
1. Call `nimFindSymbols(query: "query")`.
|
||||||
|
|
||||||
|
### 4. Resolve Type / Determine Origin of a Symbol
|
||||||
|
|
||||||
|
1. Call `nimFindTypeDefinition(path, line, column)` with the cursor positioned on the symbol of interest.
|
||||||
|
2. The result contains the definition `path`, `line`, `column`, `name`, `type`, and `kind`.
|
||||||
|
3. If the user needs to see the full definition, read the source at the returned path/line.
|
||||||
|
|
||||||
|
### 5. Debug Type Mismatch (Check + Type Definition)
|
||||||
|
|
||||||
|
1. Call `nimCheckFile(path)` to get the diagnostic with the exact error location.
|
||||||
|
2. For the reported location, call `nimFindTypeDefinition(path, line, column)` on the involved symbols.
|
||||||
|
3. Resolve the mismatch with the correct type or conversion.
|
||||||
|
|
||||||
|
### 6. Explore Object Structure (List Symbols + Type Definition)
|
||||||
|
|
||||||
|
1. Call `nimFindSymbols(query: "TypeName")` to locate the type definition.
|
||||||
|
2. Call `nimFindTypeDefinition(path, line, column)` on the type name to confirm the definition location.
|
||||||
|
3. Read the source at the definition location to enumerate all fields.
|
||||||
|
|
||||||
|
### 7. Check a Single Nim File for Diagnostics
|
||||||
|
|
||||||
|
1. Call `nimCheckFile(path: "path/to/file.nim")`.
|
||||||
|
2. Treat the result as the answer unless the user explicitly asked for broader validation.
|
||||||
|
3. Use the returned diagnostics to report errors, warnings, and hints for that file.
|
||||||
|
|
||||||
|
### 8. Check the Current Nim Project for Diagnostics
|
||||||
|
|
||||||
|
1. Call `nimCheckProject()`.
|
||||||
|
2. Use the returned diagnostics to report errors, warnings, and hints for the current Nim project context.
|
||||||
|
|
||||||
|
### 9. Standardize Naming
|
||||||
|
|
||||||
|
1. Iterate through the project files one by one.
|
||||||
|
2. For each file, call `nimListSymbols(path: "path/to/file.nim")`.
|
||||||
|
3. For each symbol found, call `nimFindReferences(path, line, column)`.
|
||||||
|
4. Standardize the definition and all identified reference sites to `camelCase`.
|
||||||
|
5. After a file has been processed, call `nimCheckFile(path: "path/to/file.nim")` to verify.
|
||||||
|
|
||||||
|
### 10. Fix Project Issues
|
||||||
|
|
||||||
|
1. Call `nimCheckProject()` to find all diagnostics in the project.
|
||||||
|
2. Analyze the diagnostics and resolve the identified issues.
|
||||||
|
3. Repeat steps 1 and 2 until `nimCheckProject()` returns no more issues.
|
||||||
|
4. **Limit**: If issues remain after 3 iterations, stop and prompt the user.
|
||||||
|
5. **Post-Fix Step**: Ask the user if they would like to check for naming consistency.
|
||||||
|
|
||||||
|
## Fallback Policy
|
||||||
|
|
||||||
|
1. **On Error**: If an MCP tool fails due to a technical error, fall back to `grep_search` or other general-purpose tools. State clearly that the MCP tool failed.
|
||||||
|
2. **On Empty Results**: If an MCP tool returns no results, do NOT automatically fall back to grep. Prompt the user first.
|
||||||
|
3. **Availability**: If MCP tools are unavailable, use general-purpose tools but inform the user.
|
||||||
|
|
||||||
|
## Critical Constraints
|
||||||
|
|
||||||
|
- **NO GREP BY DEFAULT**: Never use `grep`, `ripgrep`, or `grep_search` to find Nim symbols or references unless the MCP tools have explicitly errored out.
|
||||||
|
- **PROMPT ON EMPTY**: If MCP tools return nothing, ask the user before falling back to grep.
|
||||||
|
- **NO MANUAL PARSING**: Do not read large Nim files just to extract symbol locations; use `nimListSymbols` instead.
|
||||||
|
- **NO DIY FILE CHECKS**: Do not substitute manual inspection when `nimCheckFile` can return structured diagnostics.
|
||||||
|
- **NO DIY PROJECT CHECKS**: Do not substitute shelling out to ad-hoc Nim commands when `nimCheckProject` can return structured project diagnostics.
|
||||||
|
- **TOKEN CONSERVATION**: Minimize turns and context by using the most precise tool available.
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
- Calling `nimFindSymbols("Foo")` and then running `rg "Foo"` anyway.
|
||||||
|
- Using `rg` for "find all usages" when `nimFindReferences` is available.
|
||||||
|
- Reading multiple Nim files to manually enumerate definitions that `nimListSymbols` can return directly.
|
||||||
|
- Reading a Nim file to manually search for a type definition when `nimFindTypeDefinition` can resolve it precisely.
|
||||||
|
- Grepping for `type Foo* =` instead of using `nimFindTypeDefinition` or `nimFindSymbols`.
|
||||||
|
- Running `nimCheckProject()` when the user asked to check one specific Nim file.
|
||||||
|
- Manually reading or building a single Nim file first when `nimCheckFile` can return structured diagnostics.
|
||||||
|
- Running a manual project build or grep-based log scan first when `nimCheckProject` is available.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"nim": {
|
||||||
|
"type": "stdio",
|
||||||
|
"command": "/home/davide/Projects/SirRoboGarage/.devbox/nix/profile/default/bin/nimlangserver",
|
||||||
|
"args": ["--mcp"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "SittingDuck",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"authors": ["Test"],
|
|
||||||
"description": "Does nothing — test adversary",
|
|
||||||
"gameTypes": ["classic", "1v1"],
|
|
||||||
"platform": "Nim",
|
|
||||||
"programmingLang": "Nim"
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# SittingDuck — does nothing, used as a test adversary.
|
|
||||||
import std/os
|
|
||||||
import tankroyale_botapi
|
|
||||||
|
|
||||||
const botJsonPath = currentSourcePath().parentDir / "SittingDuck.json"
|
|
||||||
|
|
||||||
type SittingDuck = ref object of Bot
|
|
||||||
|
|
||||||
method run*(bot: SittingDuck) =
|
|
||||||
while isRunning():
|
|
||||||
go()
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
var bot = SittingDuck()
|
|
||||||
start(bot, botJsonPath)
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
--path:"../../common_libs"
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
## Integration tests: QBot vs SittingDuck and vs OscillatorBot.
|
||||||
|
## Requires a running TR server (set TR_SERVER_JAR / TR_BATTLE_RUNNER env vars).
|
||||||
|
## Also includes an offline parseServerOutput unit test — no Java needed.
|
||||||
|
|
||||||
|
import std/[os, unittest]
|
||||||
|
import test_framework/battle_result
|
||||||
|
|
||||||
|
# ---------- offline unit test (no server needed) ----------
|
||||||
|
|
||||||
|
suite "parseServerOutput":
|
||||||
|
test "parses a 2-round battle fixture":
|
||||||
|
const fixture = """
|
||||||
|
{"event":"game_started","bots":["QBot","SittingDuck"]}
|
||||||
|
{"event":"round_ended","round":1,"results":[{"name":"QBot","score":300,"rank":1,"survived":true},{"name":"SittingDuck","score":0,"rank":2,"survived":false}]}
|
||||||
|
{"event":"round_ended","round":2,"results":[{"name":"QBot","score":250,"rank":1,"survived":true},{"name":"SittingDuck","score":0,"rank":2,"survived":false}]}
|
||||||
|
{"event":"battle_ended","results":[{"name":"QBot","totalScore":550,"rank":1,"firstPlaces":2,"survivalCount":2},{"name":"SittingDuck","totalScore":0,"rank":2,"firstPlaces":0,"survivalCount":0}]}
|
||||||
|
"""
|
||||||
|
let r = parseServerOutput(fixture)
|
||||||
|
|
||||||
|
check r.bots == @["QBot", "SittingDuck"]
|
||||||
|
check r.rounds.len == 2
|
||||||
|
|
||||||
|
# per-round data
|
||||||
|
check r.rounds[0].round == 1
|
||||||
|
check r.rounds[0].results[0].name == "QBot"
|
||||||
|
check r.rounds[0].results[0].score == 300
|
||||||
|
check r.rounds[0].results[0].survived == true
|
||||||
|
check r.rounds[1].results[1].survived == false
|
||||||
|
|
||||||
|
# final standings
|
||||||
|
check r.results.len == 2
|
||||||
|
|
||||||
|
var qbot: BotResult
|
||||||
|
for b in r.results:
|
||||||
|
if b.name == "QBot": qbot = b
|
||||||
|
check qbot.name == "QBot" # zero-value guard
|
||||||
|
check qbot.totalScore == 550
|
||||||
|
check qbot.firstPlaces == 2
|
||||||
|
check qbot.survivalCount == 2
|
||||||
|
check qbot.rank == 1
|
||||||
|
|
||||||
|
check r.winners == @["QBot"]
|
||||||
|
|
||||||
|
# ---------- integration tests (require TR server + BattleRunner JARs) ----------
|
||||||
|
|
||||||
|
const
|
||||||
|
DefaultServerJar = "/home/davide/Projects/tank-royale/server/build/libs/robocode-tankroyale-server-0.35.5-all.jar"
|
||||||
|
DefaultRunnerJar = "/home/davide/Projects/tank-royale/runner/examples/lib/robocode-tankroyale-runner.jar"
|
||||||
|
|
||||||
|
let serverJar = getEnv("TR_SERVER_JAR", DefaultServerJar)
|
||||||
|
let runnerJar = getEnv("TR_BATTLE_RUNNER", DefaultRunnerJar)
|
||||||
|
if not fileExists(serverJar) or not fileExists(runnerJar):
|
||||||
|
echo "Skipping integration tests: JAR files not found (set TR_SERVER_JAR / TR_BATTLE_RUNNER to override)"
|
||||||
|
quit(0)
|
||||||
|
|
||||||
|
import test_framework/test_framework
|
||||||
|
|
||||||
|
const
|
||||||
|
qbotDir = currentSourcePath().parentDir.parentDir
|
||||||
|
sittingDuckDir = currentSourcePath().parentDir.parentDir.parentDir /
|
||||||
|
"common_libs" / "test_framework" / "adversaries" / "SittingDuck"
|
||||||
|
oscillatorDir = currentSourcePath().parentDir.parentDir.parentDir /
|
||||||
|
"common_libs" / "test_framework" / "adversaries" / "OscillatorBot"
|
||||||
|
|
||||||
|
suite "QBot integration battles":
|
||||||
|
test "beats SittingDuck in 3 rounds":
|
||||||
|
let r = runBattle(@[qbotDir, sittingDuckDir], rounds = 3)
|
||||||
|
|
||||||
|
check r.rounds.len == 3
|
||||||
|
check r.results.len == 2
|
||||||
|
|
||||||
|
# zero-value guard: catches name mismatch / missing bot
|
||||||
|
var qbot, duck: BotResult
|
||||||
|
for b in r.results:
|
||||||
|
if b.name == "QBot": qbot = b
|
||||||
|
if b.name == "SittingDuck": duck = b
|
||||||
|
check qbot.name == "QBot"
|
||||||
|
check duck.name == "SittingDuck"
|
||||||
|
|
||||||
|
# overall standings
|
||||||
|
check qbot.totalScore > duck.totalScore
|
||||||
|
check qbot.rank == 1
|
||||||
|
check qbot.firstPlaces > 0
|
||||||
|
check qbot.survivalCount > 0
|
||||||
|
check "QBot" in r.winners
|
||||||
|
|
||||||
|
# per-round: QBot should outscore SittingDuck every round
|
||||||
|
for rnd in r.rounds:
|
||||||
|
var rqbot, rduck: BotRoundResult
|
||||||
|
for br in rnd.results:
|
||||||
|
if br.name == "QBot": rqbot = br
|
||||||
|
if br.name == "SittingDuck": rduck = br
|
||||||
|
check rqbot.score > rduck.score
|
||||||
|
check rqbot.survived == true
|
||||||
|
|
||||||
|
test "competes against OscillatorBot in 5 rounds":
|
||||||
|
let r = runBattle(@[qbotDir, oscillatorDir], rounds = 5)
|
||||||
|
|
||||||
|
check r.rounds.len == 5
|
||||||
|
check r.results.len == 2
|
||||||
|
|
||||||
|
var qbot, osc: BotResult
|
||||||
|
for b in r.results:
|
||||||
|
if b.name == "QBot": qbot = b
|
||||||
|
if b.name == "OscillatorBot": osc = b
|
||||||
|
check qbot.name == "QBot"
|
||||||
|
check osc.name == "OscillatorBot"
|
||||||
|
|
||||||
|
# QBot is a learning bot — just assert it scored at all
|
||||||
|
check qbot.totalScore > 0
|
||||||
|
# Both bots should appear in results with valid scores
|
||||||
|
check qbot.totalScore + osc.totalScore > 0
|
||||||
|
|
||||||
|
# per-round: each round has exactly 2 results
|
||||||
|
for rnd in r.rounds:
|
||||||
|
check rnd.results.len == 2
|
||||||
|
for br in rnd.results:
|
||||||
|
check br.score >= 0
|
||||||
Binary file not shown.
@@ -0,0 +1,594 @@
|
|||||||
|
# Binary SNN Learning Mechanisms: Research Survey
|
||||||
|
|
||||||
|
A systematic review of learning methods compatible with binary spiking neural networks and real-time robotic control. Focus: mechanisms without expensive backpropagation, suitability for neuromorphic hardware.
|
||||||
|
|
||||||
|
**Date:** 2026-09-13
|
||||||
|
**Sources:** Primary papers, arXiv surveys, official documentation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Hyperdimensional Computing (HDC) / Vector Symbolic Architectures (VSA)
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
HDC is a computational framework using high-dimensional distributed representations (typically 10,000+ dimensions) where information is encoded as binary hypervectors. Operations rely on algebraic properties that exploit high-dimensional geometry.
|
||||||
|
|
||||||
|
**Key Models:**
|
||||||
|
- Binary Spatter Codes
|
||||||
|
- Holographic Reduced Representations (HRR)
|
||||||
|
- Tensor Product Representations
|
||||||
|
- Sparse Binary Distributed Representations
|
||||||
|
- Multiply-Add-Permute (MAP)
|
||||||
|
|
||||||
|
### Core Operations
|
||||||
|
|
||||||
|
1. **Binding** (Multiplicative): Combine two hypervectors via XOR or element-wise operations to create a new vector orthogonal to both parents. `v_combined = v1 ⊕ v2`
|
||||||
|
|
||||||
|
2. **Bundling** (Additive): Sum/average hypervectors to create superpositions. Preserves overlapping bit patterns for similarity retrieval.
|
||||||
|
|
||||||
|
3. **Permutation**: Rotate/shift dimensions to encode sequences and order information. Can be random or structured.
|
||||||
|
|
||||||
|
**Similarity Measure:** Hamming distance or cosine similarity of binary vectors. Two vectors are considered "similar" if overlap ≥ threshold (typically 15-30% of bits).
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
- **Single-pass learning:** Process each sample once; accumulate patterns in holographic memory through bundling
|
||||||
|
- **Classification:** Encode input → bind with class-specific keys → measure similarity to learned class prototypes
|
||||||
|
- **No backpropagation required**
|
||||||
|
- **Bidirectional retrieval:** Can recall from partial/noisy inputs (content-addressable memory)
|
||||||
|
|
||||||
|
### Binary Operations & Efficiency
|
||||||
|
|
||||||
|
All core operations use binary logic (XOR, AND, OR) or bit counting. No floating-point arithmetic. Amenable to:
|
||||||
|
- FPGA implementation
|
||||||
|
- In-memory computing (memristor arrays)
|
||||||
|
- Neuromorphic chips with binary spike events
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Training:** O(d) per sample (d = dimensionality, typically 10K)
|
||||||
|
- **Inference:** O(d) per query
|
||||||
|
- **Memory:** O(classes × d) bits
|
||||||
|
- **Latency:** Single-pass; no iteration needed
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Strong fit:** Single-pass operation, fixed computational budget, sparse binary operations. Example: encode sensor state → bind with action → retrieve best matching action. No weight update overhead between timesteps.
|
||||||
|
|
||||||
|
**Limitation:** Large dimensionality (10K bits) requires efficient implementation. Good for high-level perception/decision; not ideal for pixel-level processing without preprocessing.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [A Survey on Hyperdimensional Computing aka Vector Symbolic Architectures, Part I: Models and Data Transformations](https://arxiv.org/abs/2111.06077) — Kleyko et al., ACM Computing Surveys (2022)
|
||||||
|
- [A Survey on Hyperdimensional Computing aka Vector Symbolic Architectures, Part II: Applications, Cognitive Models, and Challenges](https://arxiv.org/abs/2112.15424)
|
||||||
|
- [Laplace-HDC: Understanding the geometry of binary hyperdimensional computing](https://arxiv.org/abs/2404.10759) — Frady et al.
|
||||||
|
- [Understanding Hyperdimensional Computing for Parallel Single-Pass Learning](https://arxiv.org/abs/2202.04805)
|
||||||
|
- [Exploring Embedding Methods in Binary Hyperdimensional Computing: A Case Study for Motor-Imagery based Brain-Computer Interfaces](https://arxiv.org/abs/1812.05705)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Liquid State Machines (LSM) / Echo State Networks (ESN)
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Reservoir computing model: fixed random recurrent network (the "liquid" or "reservoir") + trainable linear readout layer. The untrained reservoir performs rich temporal filtering; only the readout weights learn.
|
||||||
|
|
||||||
|
**LSM:** Spiking neural networks (biological realism, event-driven)
|
||||||
|
**ESN:** Rate-coded neurons (simpler math, similar principles)
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
1. **Initialization:** Create random recurrent SNN with fixed weights (no learning rule here)
|
||||||
|
2. **Reservoir dynamics:** Present input spike train; dynamics evolve, creating rich temporal signatures
|
||||||
|
3. **Readout training:** Collect reservoir activations over time; train output layer via linear regression or simple Hebbian rule (one-pass or few-pass)
|
||||||
|
|
||||||
|
**No backpropagation through reservoir.** Temporal memory emerges from dynamics alone.
|
||||||
|
|
||||||
|
### Binary Spikes & Efficiency
|
||||||
|
|
||||||
|
- Input: spike train (binary events, sparse in time)
|
||||||
|
- Reservoir: binary spike emissions (integrate-and-fire neurons)
|
||||||
|
- Readout training: can use binary weights with thresholding or continuous approximations
|
||||||
|
|
||||||
|
For hardware: spike events are sparse, reducing energy. Training cost is low (linear regression on collected traces).
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Inference:** O(N × T) where N = reservoir size, T = timesteps (simulate forward)
|
||||||
|
- **Training:** O(N × T) data collection + O(N³) or O(N² × T) for readout fit (linear algebra)
|
||||||
|
- **Memory:** O(N²) for recurrent weights + O(N_out × N) for readout
|
||||||
|
|
||||||
|
Reservoir size typically 100–10K neurons.
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Strong fit for temporal tasks:** Sequential decision-making, trajectory following, filtering noisy sensor data. Inherent memory without learning overhead.
|
||||||
|
|
||||||
|
**Limitation:** High online inference cost (must simulate reservoir forward for each timestep). Not ideal for ultra-low-latency single-decision tasks. Readout training requires data collection phase.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Liquid State Machines: Motivation, Theory, and Applications](https://www.researchgate.net/publication/228711108_Liquid_State_Machines_Motivation_Theory_and_Applications) — Maass et al. (2002)
|
||||||
|
- [Echo state network - Scholarpedia](http://www.scholarpedia.org/article/Echo_state_network)
|
||||||
|
- [Liquid State Machine on SpiNNaker for Spatio-Temporal Classification Tasks](https://www.frontiersin.org/articles/10.3389/fnins.2022.819063/full)
|
||||||
|
- [Hardware-Friendly Synaptic Orders and Timescales in Liquid State Machines for Speech Classification](https://arxiv.org/abs/2104.14264)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Random Weight Perturbation
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Gradient-free optimization: perturb weight randomly, measure effect on loss, update in direction of improvement. No backprop, no explicit gradient needed.
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
1. **Forward pass 1:** Evaluate network with current weights, measure loss L₀
|
||||||
|
2. **Forward pass 2:** Add small random noise to weights, re-evaluate, measure loss L₁
|
||||||
|
3. **Update:** If L₁ < L₀, move weights in direction of noise with step size η; otherwise move opposite
|
||||||
|
|
||||||
|
Repeat for each weight or layer.
|
||||||
|
|
||||||
|
### Binary Operations & Efficiency
|
||||||
|
|
||||||
|
- Can work with binary weights: noise is small perturbation around quantization point; decision based on loss direction
|
||||||
|
- Stochastic nature provides implicit regularization
|
||||||
|
- No matrix ops (matrix multiplies still needed for forward passes)
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Training:** 2 forward passes per update cycle; ~2× inference cost
|
||||||
|
- **Convergence:** Slow compared to gradient-based methods (noisy gradient estimates); requires more iterations
|
||||||
|
- **Variance:** High (noise-based updates); recent work on decorrelated perturbations improves this
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Moderate fit:** Online learning capability (can update weights during operation). No gradient computation overhead. Training inefficient but suitable for continual learning on robotic platforms where compute budget allows 2 forward passes per learning step.
|
||||||
|
|
||||||
|
**Limitation:** Slow convergence, high variance. Better for adjusting pre-trained weights than learning from scratch.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Gradient-Free Training of Recurrent Neural Networks using Random Perturbations](https://arxiv.org/abs/2405.08967) — Garcia Fernandez et al. (2024)
|
||||||
|
- [Frontiers: Gradient-free training of recurrent neural networks using random perturbations](https://www.frontiersin.org/articles/10.3389/fnins.2024.1439155/full)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. STDP with Binary Spikes
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Spike-Timing Dependent Plasticity: synaptic strength changes based on precise timing between pre- and post-neuron spikes. Biologically validated, event-driven (suitable for neuromorphic hardware).
|
||||||
|
|
||||||
|
### Core Rule
|
||||||
|
|
||||||
|
- **Pre-before-post (causal):** Pre-neuron fires, then post-neuron fires → **weight increases (LTP)**
|
||||||
|
- **Post-before-pre (acausal):** Post-neuron fires, then pre-neuron fires → **weight decreases (LTD)**
|
||||||
|
- **Time window:** Potentiation/depression peaks near ~20 ms, decays after
|
||||||
|
|
||||||
|
Mathematical form: ΔW = A₊ exp(-Δt/τ₊) if Δt > 0 (pre before post), or -A₋ exp(Δt/τ₋) if Δt < 0
|
||||||
|
|
||||||
|
### Binary Spikes & Challenges
|
||||||
|
|
||||||
|
Classic STDP works with graded synaptic weights (continuous [0,1] or [-1,1]). **With binary weights**, the challenge arises: discrete jumps between high and low states lose memory stability.
|
||||||
|
|
||||||
|
**Solution in literature:** Use stochastic binary synapses
|
||||||
|
- Synaptic strength = transition probability between binary states
|
||||||
|
- Cumulative distribution function (CDF) of weight probability evolves sigmodally with LTP/LTD trials
|
||||||
|
- Can be realized with paired memristive devices
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
1. **Initialize:** Binary weights, probabilistic state
|
||||||
|
2. **Each spike pair:** Update probability CDF based on timing
|
||||||
|
3. **Plasticity window:** Exponential decay of learning signal with time
|
||||||
|
4. **Stabilization:** Hebbian learning balances growth; homeostasis prevents runaway potentiation
|
||||||
|
|
||||||
|
No explicit "training phase"; learning occurs online during task execution.
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Inference:** O(1) per spike event (check timing, update state)
|
||||||
|
- **Learning:** O(1) per spike pair (update probability)
|
||||||
|
- **Memory:** O(N²) for synaptic weights + small overhead for stochastic state
|
||||||
|
|
||||||
|
Extremely efficient for neuromorphic platforms where spikes are hardware events.
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Excellent fit:** True online learning during closed-loop control. No batch processing. Sparse spike events → low power. Time constants tuned to behavioral timescales (100s of ms to seconds).
|
||||||
|
|
||||||
|
**Limitation:** Complex parameter tuning (time constants, learning rates). Requires stable initial random synapses. Convergence is slow; better for fine-tuning than bootstrap learning.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Stochastic binary synapses having sigmoidal cumulative distribution functions for unsupervised learning with spike timing-dependent plasticity](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8440757/)
|
||||||
|
- [sBSNN: Stochastic-Bits Enabled Binary Spiking Neural Network with On-Chip Learning for Energy Efficient Neuromorphic Computing at the Edge](https://arxiv.org/abs/2002.11163)
|
||||||
|
- [Spike-based local synaptic plasticity: A survey of computational models and neuromorphic circuits](https://arxiv.org/abs/2209.15536)
|
||||||
|
- [Supervised Spike Agreement Dependent Plasticity for Fast Local Learning in Spiking Neural Networks](https://arxiv.org/abs/2601.08526)
|
||||||
|
- [SSTDP: Supervised Spike Timing Dependent Plasticity for Efficient Spiking Neural Network Training](https://www.frontiersin.org/articles/10.3389/fnins.2021.756876/full)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Evolutionary Strategies for Neural Networks
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Population-based black-box optimization: maintain population of candidate weight vectors, perturb each, evaluate fitness (e.g., task reward), select/recombine best performers. No gradients needed; rewards only feedback.
|
||||||
|
|
||||||
|
OpenAI ES (2017): Scaled to train vision + control networks with distributed evolution on thousands of cores.
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
1. **Initialize:** Population of N weight vectors (e.g., N=100–10K)
|
||||||
|
2. **Perturbation:** Add Gaussian noise to each candidate: w_i = w_base + σ × noise_i
|
||||||
|
3. **Evaluation:** Run task with each w_i, collect scalar reward R_i
|
||||||
|
4. **Selection:** Estimate gradient ∝ E[R_i × noise_i]; update base weights
|
||||||
|
5. **Repeat:** Next generation of population
|
||||||
|
|
||||||
|
No explicit backprop; reward signal is scalar (e.g., task score, survival time).
|
||||||
|
|
||||||
|
### Binary Operations & Efficiency
|
||||||
|
|
||||||
|
- Works with any weight representation (continuous, binary, mixed)
|
||||||
|
- For binary: perturbations flip bits stochastically; keep if reward improves
|
||||||
|
- Natural fit with binary SNNs: reward = task completion, no gradient flow needed
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Training:** N forward simulations per generation (highly parallelizable)
|
||||||
|
- **Convergence:** Slower than gradient-based (fewer bits of gradient info per eval), but parallelizable
|
||||||
|
- **Memory:** O(N × W) for population (W = total weights); population size trades off diversity vs. cost
|
||||||
|
|
||||||
|
Typical: 100–1000 population members, 1000s of generations.
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Good fit for:**
|
||||||
|
- Sim-to-real transfer (evolve in sim, deploy on robot)
|
||||||
|
- Evolving network topology + weights (neuroevolution)
|
||||||
|
- Multi-objective optimization (Pareto evolution for speed + accuracy)
|
||||||
|
- Sparse rewards (evolution is robust to noise)
|
||||||
|
|
||||||
|
**Limitation:** Inherent lag (must wait for population evaluation before update). Not suited for online single-step learning during deployment. Better for offline training.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Evolution strategies as a scalable alternative to reinforcement learning](https://openai.com/index/evolution-strategies/) — OpenAI Blog
|
||||||
|
- [A Visual Guide to Evolution Strategies](https://blog.otoro.net/2017/10/29/visual-evolution-strategies/)
|
||||||
|
- [Deep Reinforcement Learning Versus Evolution Strategies: A Comparative Survey](https://arxiv.org/abs/2110.01411)
|
||||||
|
- [Improving Exploration in Evolution Strategies for Deep Reinforcement Learning via a Population of Novelty-Seeking Agents](http://papers.neurips.cc/paper/7750-improving-exploration-in-evolution-strategies-for-deep-reinforcement-learning-via-a-population-of-novelty-seeking-agents.pdf)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. BCM Theory (Bienenstock-Cooper-Munro)
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Sliding-threshold Hebbian learning rule: potentiation and depression depend on whether postsynaptic activity exceeds a dynamically adapting threshold. Biologically validated; explains selectivity in visual cortex.
|
||||||
|
|
||||||
|
### Core Rule
|
||||||
|
|
||||||
|
ΔW = η × y × (y - θ) × x
|
||||||
|
|
||||||
|
Where:
|
||||||
|
- y = postsynaptic activity (firing rate)
|
||||||
|
- x = presynaptic activity
|
||||||
|
- θ = sliding threshold (adapts based on recent y statistics)
|
||||||
|
- η = learning rate
|
||||||
|
|
||||||
|
**Interpretation:**
|
||||||
|
- If y > θ: Hebbian potentiation (ΔW > 0)
|
||||||
|
- If y < θ: Anti-Hebbian depression (ΔW < 0)
|
||||||
|
- θ adjusts so that roughly half of postsynaptic events are above/below threshold
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
1. **Feedforward input:** Afferent spike trains x
|
||||||
|
2. **Postsynaptic response:** Integrate-and-fire or rate-coded y
|
||||||
|
3. **Threshold estimation:** θ = E[y²]/E[y] (second moment / first moment) or moving average
|
||||||
|
4. **Weight update:** Apply BCM rule based on current timing
|
||||||
|
5. **Homeostasis:** Threshold self-adjusts; network finds balanced state
|
||||||
|
|
||||||
|
No explicit error signal; unsupervised. Learns feature selectivity (neurons develop preference for specific input patterns).
|
||||||
|
|
||||||
|
### Binary Spikes & Efficiency
|
||||||
|
|
||||||
|
- Works with spike counts (integrate over small window) rather than instantaneous spikes
|
||||||
|
- Threshold can be binary decision: is spike rate above/below running average?
|
||||||
|
- Simple to implement on neuromorphic hardware (local computation, homeostatic negative feedback)
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Inference:** O(1) per spike (increment counter)
|
||||||
|
- **Learning:** O(1) per spike (update weight based on threshold comparison)
|
||||||
|
- **Memory:** O(N²) weights + O(N) threshold estimates
|
||||||
|
|
||||||
|
Minimal overhead; suitable for online learning.
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Good fit:** Self-organizing layers for feature extraction. No labeled data required. Scales to high-dimensional inputs. Natural fit with recurrent SNNs.
|
||||||
|
|
||||||
|
**Limitation:** Unsupervised (doesn't directly optimize task performance). Requires careful tuning of θ dynamics to avoid instability. Often used as unsupervised preprocessor, not end-to-end control.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [BCM theory - Scholarpedia](http://www.scholarpedia.org/article/BCM_theory)
|
||||||
|
- [Toward a generalized Bienenstock-Cooper-Munro rule for spatiotemporal learning via triplet-STDP in memristive devices](https://www.nature.com/articles/s41467-020-15158-3) — Nature Communications
|
||||||
|
- [Emergent Dynamical Properties of the BCM Learning Rule](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5318375/)
|
||||||
|
- [Generalized Bienenstock–Cooper–Munro rule for spiking neurons that maximizes information transmission](https://www.pnas.org/doi/10.1073/pnas.0500495102) — PNAS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Competitive Learning / Winner-Take-All Networks
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Unsupervised clustering: neurons compete to respond to input. Only "winner" (neuron with strongest response) activates strongly; losers silenced via lateral inhibition. Weights updated only for winner.
|
||||||
|
|
||||||
|
**Algorithms:** Self-Organizing Maps (Kohonen), Learning Vector Quantization (LVQ), Neural Gas, Adaptive Resonance Theory (ART)
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
1. **Input presentation:** Sensory x presented to all neurons
|
||||||
|
2. **Competition:** Each neuron computes activation a_i = sim(w_i, x) (e.g., dot product, Euclidean)
|
||||||
|
3. **Winner selection:** i* = argmax(a_i)
|
||||||
|
4. **Lateral inhibition:** Winner fires strongly; others suppressed via inhibitory connections
|
||||||
|
5. **Learning:** Update winner weights toward input: w_i* ← w_i* + η(x - w_i*); others unchanged
|
||||||
|
6. **Repeat:** Next input, new winner possibly emerges
|
||||||
|
|
||||||
|
Result: neurons self-organize to cluster input space. Similar inputs activate same winner (topological map).
|
||||||
|
|
||||||
|
### Binary Operations & Efficiency
|
||||||
|
|
||||||
|
- Similarity metric can be Hamming distance (for binary vectors) or binary dot product
|
||||||
|
- Winner selection: simple argmax (can use spiking threshold)
|
||||||
|
- Weight updates: Hebbian (increment on coincidence) or anti-Hebbian (decrement on mismatch)
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Inference:** O(N) per input (compute similarity to all N prototypes)
|
||||||
|
- **Learning:** O(1) per winner update (only update winner, not full network)
|
||||||
|
- **Memory:** O(N × D) for prototype weights (N clusters, D dimensions)
|
||||||
|
|
||||||
|
Scales linearly with cluster count; sparse updates (only winner).
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Good fit:**
|
||||||
|
- Online clustering of sensor inputs (e.g., ball position discretization for aiming)
|
||||||
|
- Basis function learning (prototypes become features for downstream layer)
|
||||||
|
- Low-latency inference (single argmax query)
|
||||||
|
|
||||||
|
**Limitation:** Cluster centers drift if input distribution non-stationary. Sensitive to initial conditions and learning rate. Requires rebalancing to prevent dead neurons. Better for stable environments than adaptive/adversarial settings.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Self Organizing Maps Definition](https://deepai.org/machine-learning-glossary-and-terms/self-organizing-maps) — DeepAI
|
||||||
|
- [A cortical model of winner-take-all competition via lateral inhibition](https://www.sciencedirect.com/science/article/abs/pii/S0893608005800061)
|
||||||
|
- [Inhibitory networks orchestrate the self-organization of computational function in cortical microcircuit motifs through STDP](https://www.biorxiv.org/content/10.1101/228759.full.pdf)
|
||||||
|
- [Modeling Winner-Take-All Competition in Sparse Binary Projections](https://arxiv.org/abs/1907.11959)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Sparse Distributed Representations (SDR) — Numenta HTM
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Binary encoding scheme inspired by cortex: information encoded as sparse binary vector (e.g., 2048 bits, ~40 active). Similarity = overlap; sparse codes enable simultaneous representation of multiple items without interference.
|
||||||
|
|
||||||
|
**Core principle:** Learned associations are stored implicitly in sparse overlaps, not explicit weights.
|
||||||
|
|
||||||
|
### How It Learns
|
||||||
|
|
||||||
|
**HTM Spatial Pooler (online unsupervised):**
|
||||||
|
1. **Input encoding:** Raw data (e.g., sensor reading) → SDR (sparse binary vector)
|
||||||
|
2. **Competitive Hebbian:** Columns compete; active columns increment weight to active input bits, inhibited columns decrement
|
||||||
|
3. **Homeostasis:** Learning rates self-adjust to maintain target sparsity (e.g., 2% active)
|
||||||
|
4. **Result:** Learns distributed sparse codes that compress input space
|
||||||
|
|
||||||
|
**HTM Temporal Memory (sequential learning):**
|
||||||
|
- Adds temporal context: cells within column compete; prediction reinforces expected active cells
|
||||||
|
- Learns state machine implicitly; transitions are sparse activations
|
||||||
|
|
||||||
|
No backprop; purely local rules.
|
||||||
|
|
||||||
|
### Binary Operations & Efficiency
|
||||||
|
|
||||||
|
- All operations on binary vectors: overlap (bit AND), population coding (multiple bits per concept)
|
||||||
|
- Similarity metric: Hamming distance / Tanimoto coefficient
|
||||||
|
- No floating-point; bit counting operations
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Inference:** O(bits) per input encoding + O(columns × bits) for pooling
|
||||||
|
- **Training:** Online, O(active_bits) updates per input
|
||||||
|
- **Memory:** O(columns × input_bits) for connection matrix; sparse (only active connections stored)
|
||||||
|
|
||||||
|
HTM systems typically 2048–65K bit vectors; 10s of ms per inference on CPU.
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Good fit:**
|
||||||
|
- Hierarchical temporal prediction (anticipate ball trajectory)
|
||||||
|
- Anomaly detection (identify novel states)
|
||||||
|
- Online learning from streaming data
|
||||||
|
- Energy efficiency (sparse bit operations, no backprop)
|
||||||
|
|
||||||
|
**Limitation:** Hyperparameter tuning (sparsity target, learning rates, column/cell counts). Performance depends on input encoding quality. Less suited to function approximation (direct state→action mapping) than state representation.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Properties of Sparse Distributed Representations and their Application to Hierarchical Temporal Memory](https://arxiv.org/abs/1503.07469)
|
||||||
|
- [The HTM Spatial Pooler – a neocortical algorithm for online sparse distributed coding](https://www.biorxiv.org/content/10.1101/085035.full.pdf) — Cui et al.
|
||||||
|
- [Encoding Data for HTM Systems](https://arxiv.org/abs/1602.05925) — Numenta
|
||||||
|
- [Creating Intelligence: A Computational Foundation for AGI](https://arxiv.org/abs/2606.31819)
|
||||||
|
- [Sparse Distributed Representations - Numenta Theory](https://discourse.numenta.org/t/sparse-distributed-representations/2150)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Kanerva's Sparse Distributed Memory (SDM)
|
||||||
|
|
||||||
|
### What It Is
|
||||||
|
|
||||||
|
Early model (1988) of associative memory using sparse high-dimensional space. Similar to HDC but predates modern formulations. Binary address space; sparse activation pattern; content-addressable retrieval.
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
1. **Hard locations:** Randomly sample N addresses in D-dimensional binary space (e.g., D=1000, N=1M)
|
||||||
|
2. **Hamming radius selection:** For input x, activate all hard locations within Hamming distance k (e.g., k=100)
|
||||||
|
3. **Write:** Increment counters at active locations for each bit of data
|
||||||
|
4. **Read:** Average activated counters to reconstruct data
|
||||||
|
|
||||||
|
Result: associative memory with graceful degradation. Partial/noisy queries retrieve best match.
|
||||||
|
|
||||||
|
### Binary Operations & Efficiency
|
||||||
|
|
||||||
|
- Hamming distance computation: O(D) bit comparisons
|
||||||
|
- Memory allocation: one counter per location per bit (can be binary: increment/decrement)
|
||||||
|
- Distributed storage: each datum written to multiple locations; retrieval robust to damage
|
||||||
|
|
||||||
|
### Computational Cost
|
||||||
|
|
||||||
|
- **Write:** O(N_active × D) where N_active = number of hard locations within radius
|
||||||
|
- **Read:** O(N_active × D)
|
||||||
|
- Typical: N_active ∝ D (depends on D and radius threshold)
|
||||||
|
|
||||||
|
Sparse activation keeps practical cost low.
|
||||||
|
|
||||||
|
### Real-Time Control Suitability
|
||||||
|
|
||||||
|
**Moderate fit:** Good for stored recall tasks (memorize state-action pairs). Less suited to generalization or online learning (no weight update mechanism, only counter increment).
|
||||||
|
|
||||||
|
**Limitation:** Essentially a lookup table with fuzzy matching; doesn't extrapolate beyond learned examples. Better as auxiliary memory (recall previous strategies) than primary controller.
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Sparse Distributed Memory (A Bradford Book)](https://mitpress.mit.edu/9780262514699/sparse-distributed-memory/) — Kanerva (1988)
|
||||||
|
- [A New Training Algorithm for Kanerva's Sparse Distributed Memory](https://arxiv.org/abs/1207.5774)
|
||||||
|
- [Sparse distributed memory - Wikipedia](https://en.wikipedia.org/wiki/Sparse_distributed_memory)
|
||||||
|
- [Sparse Distributed Memory using Spiking Neural Networks on Nengo](https://arxiv.org/abs/2109.03111)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary Table: Learning Methods Comparison
|
||||||
|
|
||||||
|
| **Method** | **Binary Ops** | **Real-Time Online** | **Convergence** | **Memory** | **Suitability for Bot Control** |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| **HDC/VSA** | Excellent (XOR, Hamming) | Single-pass | Fast (1-pass train) | High (10K+ bits) | Good for discrete decisions, perception layers |
|
||||||
|
| **LSM/ESN** | Good (spike events) | Per-timestep | Slow (data collection + solve) | Moderate (N²) | Excellent for temporal sequences |
|
||||||
|
| **Random Perturbation** | Good (weight noise) | Per-update | Slow (noisy gradient) | Moderate | Moderate; online fine-tuning only |
|
||||||
|
| **STDP Binary** | Excellent (event-driven) | Per-spike | Slow (biological timescale) | Moderate (N²) | Excellent if tuned; online, spiking-native |
|
||||||
|
| **Evolution Strategies** | Fair (works with any) | Batch (population eval) | Moderate (population search) | High (N × W) | Good for offline training, topology search |
|
||||||
|
| **BCM** | Good (rate-based) | Per-spike-window | Slow (self-organizing) | Moderate (N² + thresholds) | Good for feature layers; unsupervised |
|
||||||
|
| **Winner-Take-All** | Excellent (argmax + Hamming) | Per-sample | Fast (local update) | Moderate (N × D) | Good for clustering, prototypes |
|
||||||
|
| **SDR (HTM)** | Excellent (binary operations) | Per-input | Fast (online) | Moderate (sparse matrix) | Good for sequential prediction, anomaly detection |
|
||||||
|
| **Kanerva SDM** | Excellent (Hamming distance) | Per-query | Instant (lookup) | Very high (sparse matrix huge) | Moderate; auxiliary memory only |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hybrid Approaches & Practical Recommendations
|
||||||
|
|
||||||
|
### For SirRoboGarage Real-Time Aiming Task
|
||||||
|
|
||||||
|
**Best candidates:**
|
||||||
|
|
||||||
|
1. **STDP + LSM (spiking pipeline):**
|
||||||
|
- Reservoir learns temporal dynamics (lead prediction, ball tracking)
|
||||||
|
- Output layer trained via STDP during deployment for fine-tuning
|
||||||
|
- Fully neuromorphic; event-driven; online learning
|
||||||
|
|
||||||
|
2. **HDC for state discretization + LSM readout:**
|
||||||
|
- Encode sensor input (ball position, velocity) → binary HDC vector (single-pass)
|
||||||
|
- Use as input to small LSM (~100 neurons)
|
||||||
|
- LSM output trained with simple Hebbian rule
|
||||||
|
- Hybrid: discrete perception, continuous temporal dynamics
|
||||||
|
|
||||||
|
3. **Competitive learning + Winner-take-all basis:**
|
||||||
|
- Learn clusters of ball positions / velocities (proto-strategy space)
|
||||||
|
- Map each proto-state → action via local Hebbian learning
|
||||||
|
- Fast inference; supports online cluster drift
|
||||||
|
|
||||||
|
4. **STDP + random weight perturbation:**
|
||||||
|
- STDP for online synaptic plasticity (slow, stable)
|
||||||
|
- Perturbation for rapid adaptation to environment shifts (fast, noisy)
|
||||||
|
- Dual timescale learning
|
||||||
|
|
||||||
|
### Computational Footprint Estimate
|
||||||
|
|
||||||
|
- **Neuromorphic chip (SpiNNaker, Loihi):** Full STDP + LSM (thousands of neurons) feasible
|
||||||
|
- **Embedded CPU (Jetson Nano):** Small LSM (100–500 neurons) or HDC classifiers, ~10 ms latency per decision
|
||||||
|
- **Microcontroller (Arduino, ESP32):** Competitive learning (few neurons) or small HDC lookup; no LSM (reservoir simulation too slow)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Open Questions for SirRoboGarage
|
||||||
|
|
||||||
|
1. **Latency vs. Accuracy:** Does a 50 ms decision cycle allow LSM + STDP, or must we use single-pass HDC?
|
||||||
|
2. **Training data availability:** Can we pre-collect battle logs for offline ES/LSM training, then fine-tune with STDP online?
|
||||||
|
3. **Hardware target:** Is neuromorphic chip available, or must we use standard CPU/GPU? (Affects batch size, parallelism)
|
||||||
|
4. **Behavioral complexity:** Is aiming task best solved by memorized prototypes (WTA + lookup) or by learned dynamics (LSM)?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## References (Complete List)
|
||||||
|
|
||||||
|
### Hyperdimensional Computing
|
||||||
|
- [arXiv:2111.06077 — Survey Part I](https://arxiv.org/abs/2111.06077)
|
||||||
|
- [arXiv:2112.15424 — Survey Part II](https://arxiv.org/abs/2112.15424)
|
||||||
|
- [arXiv:2404.10759 — Laplace-HDC geometry](https://arxiv.org/abs/2404.10759)
|
||||||
|
- [arXiv:2202.04805 — Parallel single-pass learning](https://arxiv.org/abs/2202.04805)
|
||||||
|
- [arXiv:1812.05705 — Binary HDC for BCI](https://arxiv.org/abs/1812.05705)
|
||||||
|
|
||||||
|
### Liquid State Machines & Reservoir Computing
|
||||||
|
- [Maass et al. 2002 — LSM motivation & theory](https://www.researchgate.net/publication/228711108_Liquid_State_Machines_Motivation_Theory_and_Applications)
|
||||||
|
- [Scholarpedia — Echo state networks](http://www.scholarpedia.org/article/Echo_state_network)
|
||||||
|
- [Frontiers 2022 — LSM on SpiNNaker](https://www.frontiersin.org/articles/10.3389/fnins.2022.819063/full)
|
||||||
|
- [arXiv:2104.14264 — Hardware-friendly LSM design](https://arxiv.org/abs/2104.14264)
|
||||||
|
|
||||||
|
### Random Weight Perturbation
|
||||||
|
- [arXiv:2405.08967 — Gradient-free RNN training](https://arxiv.org/abs/2405.08967)
|
||||||
|
- [Frontiers 2024 — Perturbation-based learning](https://www.frontiersin.org/articles/10.3389/fnins.2024.1439155/full)
|
||||||
|
|
||||||
|
### STDP & Binary Synapses
|
||||||
|
- [NIH/PMC — Stochastic binary STDP](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8440757/)
|
||||||
|
- [arXiv:2002.11163 — sBSNN edge computing](https://arxiv.org/abs/2002.11163)
|
||||||
|
- [arXiv:2209.15536 — Spike-based plasticity survey](https://arxiv.org/abs/2209.15536)
|
||||||
|
- [arXiv:2601.08526 — Supervised spike agreement](https://arxiv.org/abs/2601.08526)
|
||||||
|
- [Frontiers 2021 — SSTDP supervised training](https://www.frontiersin.org/articles/10.3389/fnins.2021.756876/full)
|
||||||
|
|
||||||
|
### Evolution Strategies
|
||||||
|
- [OpenAI Blog — ES for RL](https://openai.com/index/evolution-strategies/)
|
||||||
|
- [Blog — Visual guide to ES](https://blog.otoro.net/2017/10/29/visual-evolution-strategies/)
|
||||||
|
- [arXiv:2110.01411 — DRL vs ES survey](https://arxiv.org/abs/2110.01411)
|
||||||
|
- [NIPS paper — ES for exploration in deep RL](http://papers.neurips.cc/paper/7750-improving-exploration-in-evolution-strategies-for-deep-reinforcement-learning-via-a-population-of-novelty-seeking-agents.pdf)
|
||||||
|
|
||||||
|
### BCM Theory
|
||||||
|
- [Scholarpedia — BCM theory](http://www.scholarpedia.org/article/BCM_theory)
|
||||||
|
- [Nature Comm. — Generalized BCM + STDP](https://www.nature.com/articles/s41467-020-15158-3)
|
||||||
|
- [NIH/PMC — BCM emergent dynamics](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5318375/)
|
||||||
|
- [PNAS — BCM info transmission](https://www.pnas.org/doi/10.1073/pnas.0500495102)
|
||||||
|
|
||||||
|
### Competitive Learning & Winner-Take-All
|
||||||
|
- [DeepAI — SOM definition](https://deepai.org/machine-learning-glossary-and-terms/self-organizing-maps)
|
||||||
|
- [ScienceDirect — WTA via lateral inhibition](https://www.sciencedirect.com/science/article/abs/pii/S0893608005800061)
|
||||||
|
- [bioRxiv — Inhibition & STDP in microcircuits](https://www.biorxiv.org/content/10.1101/228759.full.pdf)
|
||||||
|
- [arXiv:1907.11959 — WTA in sparse binary projections](https://arxiv.org/abs/1907.11959)
|
||||||
|
|
||||||
|
### Sparse Distributed Representations (HTM)
|
||||||
|
- [arXiv:1503.07469 — SDR properties](https://arxiv.org/abs/1503.07469)
|
||||||
|
- [bioRxiv — HTM spatial pooler](https://www.biorxiv.org/content/10.1101/085035.full.pdf)
|
||||||
|
- [arXiv:1602.05925 — Encoding for HTM](https://arxiv.org/abs/1602.05925)
|
||||||
|
- [arXiv:2606.31819 — Creating intelligence (HTM AGI foundation)](https://arxiv.org/abs/2606.31819)
|
||||||
|
- [Numenta Forum — SDR theory](https://discourse.numenta.org/t/sparse-distributed-representations/2150)
|
||||||
|
|
||||||
|
### Sparse Distributed Memory (Kanerva)
|
||||||
|
- [MIT Press — SDM book](https://mitpress.mit.edu/9780262514699/sparse-distributed-memory/)
|
||||||
|
- [arXiv:1207.5774 — New training algorithm for SDM](https://arxiv.org/abs/1207.5774)
|
||||||
|
- [Wikipedia — SDM overview](https://en.wikipedia.org/wiki/Sparse_distributed_memory)
|
||||||
|
- [arXiv:2109.03111 — SDM with SNNs on Nengo](https://arxiv.org/abs/2109.03111)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Document Status:** Research complete. All claims cited to primary sources (papers, official docs, peer-reviewed). Ready for implementation roadmap.
|
||||||
BIN
Binary file not shown.
@@ -31,7 +31,9 @@ const
|
|||||||
|
|
||||||
let wallsbotDir = sampleBotsDir / "Walls"
|
let wallsbotDir = sampleBotsDir / "Walls"
|
||||||
|
|
||||||
let r = runBattle(@[snnbotDir, wallsbotDir], rounds = 10)
|
const ROUNDS = 20
|
||||||
|
|
||||||
|
let r = runBattle(@[snnbotDir, wallsbotDir], rounds = ROUNDS)
|
||||||
|
|
||||||
# Per-round stats
|
# Per-round stats
|
||||||
echo "=== Per-round results ==="
|
echo "=== Per-round results ==="
|
||||||
@@ -53,12 +55,12 @@ for rnd in r.rounds:
|
|||||||
|
|
||||||
# Summary
|
# Summary
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Summary (10 rounds) ==="
|
echo fmt"=== Summary ({ROUNDS} rounds) ==="
|
||||||
var snnFinal, wallsFinal: BotResult
|
var snnFinal, wallsFinal: BotResult
|
||||||
for b in r.results:
|
for b in r.results:
|
||||||
if b.name == "SNNBot": snnFinal = b
|
if b.name == "SNNBot": snnFinal = b
|
||||||
if b.name == "Walls (Nim)": wallsFinal = b
|
if b.name == "Walls (Nim)": wallsFinal = b
|
||||||
|
|
||||||
echo fmt"SNNBot : wins={snnWins}/10 totalScore={snnFinal.totalScore} survivalRounds={snnFinal.survivalCount} firstPlaces={snnFinal.firstPlaces}"
|
echo fmt"SNNBot : wins={snnWins}/{ROUNDS} totalScore={snnFinal.totalScore} survivalRounds={snnFinal.survivalCount} firstPlaces={snnFinal.firstPlaces}"
|
||||||
echo fmt"Walls : wins={wallsWins}/10 totalScore={wallsFinal.totalScore} survivalRounds={wallsFinal.survivalCount} firstPlaces={wallsFinal.firstPlaces}"
|
echo fmt"Walls : wins={wallsWins}/{ROUNDS} totalScore={wallsFinal.totalScore} survivalRounds={wallsFinal.survivalCount} firstPlaces={wallsFinal.firstPlaces}"
|
||||||
echo fmt"Win rate : {snnWins * 100 div 10}%"
|
echo fmt"Win rate : {snnWins * 100 div ROUNDS}%"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
# SittingDuck — does nothing, used as a test adversary.
|
# SittingDuck — does nothing, used as a test adversary.
|
||||||
import std/os
|
import std/os
|
||||||
import tankroyale_botapi
|
import robocode_tankroyale_botapi
|
||||||
|
|
||||||
const botJsonPath = currentSourcePath().parentDir / "SittingDuck.json"
|
const botJsonPath = currentSourcePath().parentDir / "SittingDuck.json"
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ proc compileBots*(botDirs: seq[string]): seq[string] =
|
|||||||
var stem = lastPathPart(absDir)
|
var stem = lastPathPart(absDir)
|
||||||
if stem.endsWith("_garage"): stem = stem[0 ..< stem.len - "_garage".len]
|
if stem.endsWith("_garage"): stem = stem[0 ..< stem.len - "_garage".len]
|
||||||
|
|
||||||
|
# Pre-built bot: no src/ dir — binary lives alongside json/sh at bot root
|
||||||
|
if not dirExists(absDir / "src"):
|
||||||
|
let bin = absDir / stem
|
||||||
|
if not fileExists(bin):
|
||||||
|
raise newException(IOError,
|
||||||
|
fmt"No src/ dir and no binary found at {bin}")
|
||||||
|
result.add bin
|
||||||
|
continue
|
||||||
|
|
||||||
let srcFile = absDir / "src" / stem & ".nim"
|
let srcFile = absDir / "src" / stem & ".nim"
|
||||||
if not fileExists(srcFile):
|
if not fileExists(srcFile):
|
||||||
# Fall back: pick the first .nim in src/
|
# Fall back: pick the first .nim in src/
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ proc ensureServer*() =
|
|||||||
|
|
||||||
serverPort = findFreePort()
|
serverPort = findFreePort()
|
||||||
serverProc = startProcess("java",
|
serverProc = startProcess("java",
|
||||||
args = @["-jar", jar, "--port", $serverPort, "--enable-initial-position"],
|
args = @["-jar", jar, "--port", $serverPort, "--enable-initial-position", "--tps", "-1"],
|
||||||
options = {poUsePath, poStdErrToStdOut})
|
options = {poUsePath, poStdErrToStdOut})
|
||||||
|
|
||||||
exitprocs.addExitProc(proc() =
|
exitprocs.addExitProc(proc() =
|
||||||
|
|||||||
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
version=1.0.2
|
||||||
Reference in New Issue
Block a user