From 445c873316968971f97240ff28c45be781b295cb Mon Sep 17 00:00:00 2001 From: Davide Cappellini Date: Mon, 14 Sep 2026 23:31:31 +0200 Subject: [PATCH] fix(SNNBot): replace correct bin weights instead of OR to prevent saturation OR-only reinforcement caused all bins to fill with set bits over time, making all scores similar and the winner random. Now the correct bin is REPLACED with the exact input pattern (no accumulation). Neighbors still OR for generalization. Co-Authored-By: Claude Opus 4.6 --- SNNBot_garage/src/reservoir.nim | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/SNNBot_garage/src/reservoir.nim b/SNNBot_garage/src/reservoir.nim index 16d6775..638b6ae 100644 --- a/SNNBot_garage/src/reservoir.nim +++ b/SNNBot_garage/src/reservoir.nim @@ -59,11 +59,15 @@ proc interpolatedAngle*(a: BinaryAimer, winnerBin: int): float = result = radToDeg(arctan2(sinAvg, cosAvg)) proc learn*(a: var BinaryAimer, input: BitVec80, correctAngle: float) = - ## WTA Hebbian: reinforce correct bin + ±2 neighbors, punish worst wrong bin (>2° away) + ## WTA Hebbian: replace correct bin, OR neighbors for generalization, punish worst wrong bin (>2° away) let correctBin = angleToBin(correctAngle) - # Reinforce correct bin + 2 neighbors on each side - for offset in -2 .. 2: + # Replace correct bin with input (prevents bit accumulation saturation) + for w in 0 ..< WORDS_IN: + a.readout[correctBin][w] = input[w] + + # OR neighbors ±1, ±2 for generalization (not correct bin itself) + for offset in [-2, -1, 1, 2]: let bin = (correctBin + offset + N_BINS) mod N_BINS for w in 0 ..< WORDS_IN: a.readout[bin][w] = a.readout[bin][w] or input[w]