Spaces:
Running
Running
chore(sync): mirror backend .py + Dockerfile to Space (hf-sync-backend)
Browse filesAutomated backend sync from szl-holdings/a11oy main via hf-sync-backend.
Updated (differed from the Space): Dockerfile, serve.py, szl_neuroplasticity.py
Deleted (gone from the repo + Dockerfile COPY set): (none)
Keeps the Space-built backend (serve.py + the Dockerfile-COPY'd .py
modules) identical to GitHub main so the Space never rebuilds from a
stale backend, new endpoints don't 404 there, and orphaned modules
removed from the repo don't linger in the Space tree.
- Dockerfile +1 -1
- serve.py +20 -0
- szl_neuroplasticity.py +267 -0
Dockerfile
CHANGED
|
@@ -82,7 +82,7 @@ COPY knowledge.json ./static/knowledge.json
|
|
| 82 |
COPY knowledge.json szl_parity_gaps.py a11oy_warhacker_obs.py serve.py a11oy_wireA_metrics.py cathedral.html a11oy_operator_organ.py a11oy_hf_assets.py szl_b2_secdata.py gates_manifest.json a11oy_code_orchestrator.py a11oy_agent_loop.py a11oy_org_rag.py a11oy_mcp_client.py szl_rag.py a11oy_code_ide.html wayra_serve.py wayra_snapshot.json wayra_digests_7d.json szl_khipu_os_routes.py ./
|
| 83 |
COPY szl_khipu_consensus.py szl_puriq_formulas.py ayni_os_serve.py szl_live_wires.py live_wires.html live_wires_3d.js szl_dsse.py szl_provenance.py szl_be_hardening.py szl_unay.py szl_khipu_lmdb.py szl_khipu_replicate.py szl_unay_routes.py szl_warhacker_aliases.py a11oy_v4_hickok.py szl_khipu.py szl_formulas.py a11oy_v4_formulas.py szl_anatomy_3d.py szl_anatomy_routes.py ./
|
| 84 |
COPY _vendor_blobs.py szl_v4_fleet.py operator_shell_v4.py szl_bridge.py szl_bridge_schemas.py agent.html a11oy_bridge_cli.py szl_ken.py a11oy_formula_endpoints.py a11oy_formulas_page.py a11oy_frontier_patch.py a11oy_v4_agent.py szl_brain.py szl_wire.py szl_hub.py szl_rosie_companion.py szl_receipt_substrate.py szl_alloy_embed_fabric.py szl_ayni_quorum.py szl_agentic_loop.py ./
|
| 85 |
-
COPY szl_formula_wiring.py a11oy_code_engine.py a11oy_code.py a11oy_seismic.py szl_warhacker_real.py szl_warhacker_demos.py NOTICE_warhacker_demos.txt szl_llm_registry.py szl_elite_console.py szl_alloy_models.py szl_scaling.py szl_allodial.py szl_entanglement.py ./
|
| 86 |
|
| 87 |
# Copy serve orchestrator and gates manifest
|
| 88 |
# ADDITIVE (live-ops): orchestration + AI-observability module — per-file COPY Dockerfile
|
|
|
|
| 82 |
COPY knowledge.json szl_parity_gaps.py a11oy_warhacker_obs.py serve.py a11oy_wireA_metrics.py cathedral.html a11oy_operator_organ.py a11oy_hf_assets.py szl_b2_secdata.py gates_manifest.json a11oy_code_orchestrator.py a11oy_agent_loop.py a11oy_org_rag.py a11oy_mcp_client.py szl_rag.py a11oy_code_ide.html wayra_serve.py wayra_snapshot.json wayra_digests_7d.json szl_khipu_os_routes.py ./
|
| 83 |
COPY szl_khipu_consensus.py szl_puriq_formulas.py ayni_os_serve.py szl_live_wires.py live_wires.html live_wires_3d.js szl_dsse.py szl_provenance.py szl_be_hardening.py szl_unay.py szl_khipu_lmdb.py szl_khipu_replicate.py szl_unay_routes.py szl_warhacker_aliases.py a11oy_v4_hickok.py szl_khipu.py szl_formulas.py a11oy_v4_formulas.py szl_anatomy_3d.py szl_anatomy_routes.py ./
|
| 84 |
COPY _vendor_blobs.py szl_v4_fleet.py operator_shell_v4.py szl_bridge.py szl_bridge_schemas.py agent.html a11oy_bridge_cli.py szl_ken.py a11oy_formula_endpoints.py a11oy_formulas_page.py a11oy_frontier_patch.py a11oy_v4_agent.py szl_brain.py szl_wire.py szl_hub.py szl_rosie_companion.py szl_receipt_substrate.py szl_alloy_embed_fabric.py szl_ayni_quorum.py szl_agentic_loop.py ./
|
| 85 |
+
COPY szl_formula_wiring.py a11oy_code_engine.py a11oy_code.py a11oy_seismic.py szl_warhacker_real.py szl_warhacker_demos.py NOTICE_warhacker_demos.txt szl_llm_registry.py szl_elite_console.py szl_alloy_models.py szl_scaling.py szl_allodial.py szl_entanglement.py szl_neuroplasticity.py ./
|
| 86 |
|
| 87 |
# Copy serve orchestrator and gates manifest
|
| 88 |
# ADDITIVE (live-ops): orchestration + AI-observability module — per-file COPY Dockerfile
|
serve.py
CHANGED
|
@@ -225,6 +225,26 @@ try:
|
|
| 225 |
except Exception as _szl_entanglement_e: # pragma: no cover
|
| 226 |
print(f"[a11oy] Entanglement formulas NOT registered: {_szl_entanglement_e!r}", file=__import__("sys").stderr)
|
| 227 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
|
| 229 |
# ── Open-Problem Bounty Board (bounties-tab-patch) — OPEN proof bounties
|
| 230 |
# (Conjecture 1 Λ-aggregator uniqueness, Conjecture 2 Khipu BFT safety) rendered
|
|
|
|
| 225 |
except Exception as _szl_entanglement_e: # pragma: no cover
|
| 226 |
print(f"[a11oy] Entanglement formulas NOT registered: {_szl_entanglement_e!r}", file=__import__("sys").stderr)
|
| 227 |
|
| 228 |
+
# ── SZL Neuroplasticity / learning-rule formulas — the new "learning / brain"
|
| 229 |
+
# (neuroplasticity-wire-patch) — grounds a11oy's agent learning loop in real, cited
|
| 230 |
+
# neuroplasticity math, honestly tiered. RIGOROUS (classical, cited): Hebb 1949;
|
| 231 |
+
# Oja 1982 (PCA convergence); Bienenstock-Cooper-Munro BCM 1982 (sliding threshold);
|
| 232 |
+
# Bi & Poo 1998 (STDP); Turrigiano 2008 (synaptic scaling); Hubel & Wiesel Nobel 1981
|
| 233 |
+
# (critical periods). RIGOROUS (recent, cited): Dohare-Sutton Nature 2024 + Sokar ReDo
|
| 234 |
+
# 2023 (loss of plasticity in continual learning — the honest frontier tie-in for any
|
| 235 |
+
# long-running agent); Kirkpatrick 2017 EWC. The predictive-coding↔Hebbian unifier
|
| 236 |
+
# (Millidge 2022) is a PROPOSED lens, NOT a Λ theorem. Every borrowed rule cites its
|
| 237 |
+
# real author; SZL claims NONE as its own. EXPERIMENTAL/PROPOSED — NOT formal Λ; adds
|
| 238 |
+
# NOTHING to the locked 8; Λ stays Conjecture 1; trust never 100%. Pure stdlib. Shared
|
| 239 |
+
# module byte-identical a11oy↔killinchu. Additive, try/except-guarded.
|
| 240 |
+
try:
|
| 241 |
+
import szl_neuroplasticity as _szl_neuroplasticity
|
| 242 |
+
_szl_neuroplasticity.register(app, ns="a11oy")
|
| 243 |
+
print("[a11oy] Neuroplasticity formulas registered: /api/a11oy/v1/neuro/*", file=__import__("sys").stderr)
|
| 244 |
+
except Exception as _szl_neuroplasticity_e: # pragma: no cover
|
| 245 |
+
print(f"[a11oy] Neuroplasticity formulas NOT registered: {_szl_neuroplasticity_e!r}", file=__import__("sys").stderr)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
|
| 249 |
# ── Open-Problem Bounty Board (bounties-tab-patch) — OPEN proof bounties
|
| 250 |
# (Conjecture 1 Λ-aggregator uniqueness, Conjecture 2 Khipu BFT safety) rendered
|
szl_neuroplasticity.py
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""szl_neuroplasticity.py — SZL Holdings neuroplasticity / learning-rule formulas.
|
| 2 |
+
|
| 3 |
+
EXPERIMENTAL-tier. PURE STDLIB (no numpy — consistent with every SZL shared module;
|
| 4 |
+
vectors here are small). Adds NOTHING to the locked-8. Λ stays Conjecture 1. Trust
|
| 5 |
+
never 100%. No fabricated data. Every rule is established prior art, cited to its
|
| 6 |
+
real author; SZL claims NONE as its own discovery.
|
| 7 |
+
|
| 8 |
+
WHY THIS EXISTS: the new SZL "learning / brain" pillar, grounding a11oy's agent
|
| 9 |
+
learning loop in real, cited neuroplasticity math. The honest frontier tie-in is
|
| 10 |
+
LOSS OF PLASTICITY in continual learning (Dohare/Sutton, Nature 2024) — a real
|
| 11 |
+
problem for any long-running agent — addressed clean-room with continual-backprop
|
| 12 |
+
+ dormant-neuron + synaptic-scaling style utilities. The rigorous unifying identity
|
| 13 |
+
(Friston/predictive-coding ↔ Hebbian, Millidge et al. 2022) is noted but NOT claimed
|
| 14 |
+
as SZL's; it is a PROPOSED lens, never a Λ theorem.
|
| 15 |
+
|
| 16 |
+
Honest tiering:
|
| 17 |
+
* Hebb / Oja / BCM / STDP / synaptic scaling : RIGOROUS (classical, cited).
|
| 18 |
+
* Loss-of-plasticity, ReDo, plasticity-injection, EWC : RIGOROUS (recent, cited).
|
| 19 |
+
* Predictive-coding ↔ Hebbian unifier : PROPOSED lens (not a Λ claim).
|
| 20 |
+
|
| 21 |
+
Citations (real, verified):
|
| 22 |
+
* Hebb (1949) The Organization of Behavior.
|
| 23 |
+
* Oja (1982) J. Math. Biol. 15:267-273, DOI:10.1007/BF00275687 (PCA convergence).
|
| 24 |
+
* Bienenstock-Cooper-Munro BCM (1982) J. Neurosci. 2(1):32-48,
|
| 25 |
+
DOI:10.1523/JNEUROSCI.02-01-00032.1982 (sliding threshold).
|
| 26 |
+
* Bi & Poo STDP (1998) J. Neurosci. 18(24):10464, DOI:10.1523/JNEUROSCI.18-24-10464.1998.
|
| 27 |
+
* Turrigiano synaptic scaling (2008) Cell, DOI:10.1016/j.cell.2008.10.008.
|
| 28 |
+
* Hubel & Wiesel critical periods (Nobel 1981).
|
| 29 |
+
* Dohare, Sutton et al. "Loss of plasticity in deep continual learning" Nature 2024,
|
| 30 |
+
DOI:10.1038/s41586-024-07711-7.
|
| 31 |
+
* Kirkpatrick et al. EWC (2017) PNAS, DOI:10.1073/pnas.1611835114.
|
| 32 |
+
* Millidge et al. (2022) arXiv:2206.02629 (PC ↔ backprop/Hebbian identity).
|
| 33 |
+
|
| 34 |
+
Routes: GET /api/<ns>/v1/neuro/{summary,hebb,oja,bcm,stdp,plasticity,ewc}
|
| 35 |
+
"""
|
| 36 |
+
from __future__ import annotations
|
| 37 |
+
|
| 38 |
+
import math
|
| 39 |
+
from typing import List, Sequence
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def _dot(a: Sequence[float], b: Sequence[float]) -> float:
|
| 43 |
+
return float(sum(x * y for x, y in zip(a, b)))
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def _norm(a: Sequence[float]) -> float:
|
| 47 |
+
return math.sqrt(_dot(a, a))
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def hebb_update(w: List[float], x: Sequence[float], y: float, eta: float) -> List[float]:
|
| 51 |
+
"""Δw = η·x·y (Hebb 1949). UNSTABLE alone — grows unbounded; see Oja/BCM."""
|
| 52 |
+
return [w[i] + eta * x[i] * y for i in range(len(w))]
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def oja_step(w: List[float], x: Sequence[float], eta: float) -> dict:
|
| 56 |
+
"""Oja's rule (1982): w ← w + η(y·x − y²·w), y = wᵀx. Provably converges
|
| 57 |
+
a.s. to the first principal eigenvector of E[xxᵀ]; output variance → λ₁."""
|
| 58 |
+
y = _dot(w, x)
|
| 59 |
+
w2 = [w[i] + eta * (y * x[i] - y * y * w[i]) for i in range(len(w))]
|
| 60 |
+
return {"y": y, "w": w2}
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def oja_fit(X: List[Sequence[float]], eta: float = 0.05, epochs: int = 30) -> dict:
|
| 64 |
+
"""Run Oja's rule over data X; returns the learned (normalized) weight vector,
|
| 65 |
+
which approximates the top principal component (Oja 1982). Deterministic seed."""
|
| 66 |
+
if not X:
|
| 67 |
+
return {"status": "out_of_domain"}
|
| 68 |
+
n = len(X[0])
|
| 69 |
+
# deterministic init: normalized ones
|
| 70 |
+
w = [1.0 / math.sqrt(n)] * n
|
| 71 |
+
for _ in range(epochs):
|
| 72 |
+
for x in X:
|
| 73 |
+
w = oja_step(w, x, eta)["w"]
|
| 74 |
+
nrm = _norm(w)
|
| 75 |
+
if nrm > 1e-12:
|
| 76 |
+
w = [c / nrm for c in w]
|
| 77 |
+
# Rayleigh quotient ~ top eigenvalue estimate
|
| 78 |
+
# C w via sample covariance applied to w
|
| 79 |
+
m = len(X)
|
| 80 |
+
Cw = [0.0] * n
|
| 81 |
+
for x in X:
|
| 82 |
+
xw = _dot(x, w)
|
| 83 |
+
for i in range(n):
|
| 84 |
+
Cw[i] += x[i] * xw / m
|
| 85 |
+
lam = _dot(w, Cw)
|
| 86 |
+
return {"principal_direction": [round(c, 6) for c in w],
|
| 87 |
+
"eigenvalue_estimate": round(lam, 6),
|
| 88 |
+
"cite": "Oja 1982, J. Math. Biol. 15:267-273"}
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def bcm_threshold(y_history: Sequence[float], tau: float = 1.0) -> dict:
|
| 92 |
+
"""BCM sliding modification threshold θ_M = E[y²] (Bienenstock-Cooper-Munro
|
| 93 |
+
1982). Δw ∝ x·y·(y − θ_M): potentiation above θ_M, depression below. θ_M
|
| 94 |
+
slides with recent activity, giving stability + selectivity."""
|
| 95 |
+
if not y_history:
|
| 96 |
+
return {"status": "out_of_domain"}
|
| 97 |
+
theta_M = sum(yi * yi for yi in y_history) / len(y_history)
|
| 98 |
+
y_now = y_history[-1]
|
| 99 |
+
phi = y_now * (y_now - theta_M) # BCM plasticity function sign
|
| 100 |
+
return {"theta_M": round(theta_M, 6), "y": round(y_now, 6),
|
| 101 |
+
"plasticity_sign": "potentiate" if phi > 0 else ("depress" if phi < 0 else "neutral"),
|
| 102 |
+
"phi": round(phi, 6),
|
| 103 |
+
"cite": "BCM 1982, J. Neurosci. 2(1):32-48"}
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
def stdp_window(delta_t_ms: float, A_plus: float = 1.0, A_minus: float = 1.0,
|
| 107 |
+
tau_plus: float = 17.0, tau_minus: float = 34.0) -> dict:
|
| 108 |
+
"""Spike-timing-dependent plasticity (Bi & Poo 1998): pre-before-post
|
| 109 |
+
(Δt>0) potentiates ∝ A₊·exp(��Δt/τ₊); post-before-pre (Δt<0) depresses
|
| 110 |
+
∝ −A₋·exp(Δt/τ₋). Δt = t_post − t_pre (ms)."""
|
| 111 |
+
if delta_t_ms > 0:
|
| 112 |
+
dw = A_plus * math.exp(-delta_t_ms / tau_plus)
|
| 113 |
+
kind = "LTP (potentiation)"
|
| 114 |
+
elif delta_t_ms < 0:
|
| 115 |
+
dw = -A_minus * math.exp(delta_t_ms / tau_minus)
|
| 116 |
+
kind = "LTD (depression)"
|
| 117 |
+
else:
|
| 118 |
+
dw = 0.0
|
| 119 |
+
kind = "coincident"
|
| 120 |
+
return {"delta_t_ms": delta_t_ms, "delta_w": round(dw, 6), "kind": kind,
|
| 121 |
+
"cite": "Bi & Poo 1998, J. Neurosci. 18(24):10464"}
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def plasticity_health(activations: Sequence[float], dormant_threshold: float = 1e-3) -> dict:
|
| 125 |
+
"""Loss-of-plasticity diagnostic (Dohare/Sutton, Nature 2024 + ReDo, Sokar 2023).
|
| 126 |
+
Fraction of 'dormant' units (near-zero activation) + a simple plasticity score
|
| 127 |
+
(1 − dormant_fraction). High dormancy => plasticity loss => recommend continual
|
| 128 |
+
re-init (continual backprop / ReDo) of the dormant units."""
|
| 129 |
+
if not activations:
|
| 130 |
+
return {"status": "out_of_domain"}
|
| 131 |
+
n = len(activations)
|
| 132 |
+
dormant = sum(1 for a in activations if abs(a) < dormant_threshold)
|
| 133 |
+
frac = dormant / n
|
| 134 |
+
return {"n_units": n, "dormant_units": dormant,
|
| 135 |
+
"dormant_fraction": round(frac, 4),
|
| 136 |
+
"plasticity_score": round(1.0 - frac, 4),
|
| 137 |
+
"recommendation": ("re-initialize dormant units (continual backprop / ReDo)"
|
| 138 |
+
if frac > 0.1 else "healthy"),
|
| 139 |
+
"tier": "RIGOROUS (Dohare-Sutton Nature 2024; Sokar ReDo ICML 2023)",
|
| 140 |
+
"cites": ["Dohare-Sutton 2024 DOI:10.1038/s41586-024-07711-7",
|
| 141 |
+
"Sokar et al. ReDo 2023 arXiv:2302.12902"]}
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def ewc_penalty(theta: Sequence[float], theta_star: Sequence[float],
|
| 145 |
+
fisher: Sequence[float], lam: float = 1.0) -> dict:
|
| 146 |
+
"""Elastic Weight Consolidation penalty (Kirkpatrick et al. 2017): protects
|
| 147 |
+
weights important to a prior task. L_EWC = (λ/2)·Σ F_i·(θ_i − θ*_i)². Mitigates
|
| 148 |
+
catastrophic forgetting in continual learning."""
|
| 149 |
+
if not (len(theta) == len(theta_star) == len(fisher)):
|
| 150 |
+
return {"status": "out_of_domain", "reason": "length mismatch"}
|
| 151 |
+
pen = 0.5 * lam * sum(fisher[i] * (theta[i] - theta_star[i]) ** 2 for i in range(len(theta)))
|
| 152 |
+
return {"ewc_penalty": round(pen, 6), "lambda": lam,
|
| 153 |
+
"cite": "Kirkpatrick et al. 2017 PNAS DOI:10.1073/pnas.1611835114"}
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
def critical_period_rate(t: float, alpha_max: float = 1.0, t_peak: float = 0.0,
|
| 157 |
+
sigma_cp: float = 1.0, alpha_floor: float = 0.01) -> dict:
|
| 158 |
+
"""Hubel-Wiesel critical-period plasticity envelope: a Gaussian in
|
| 159 |
+
developmental time peaking at t_peak (Nobel 1981). Plasticity is highest
|
| 160 |
+
during the critical period and decays (with a small adult floor)."""
|
| 161 |
+
rate = alpha_max * math.exp(-((t - t_peak) ** 2) / (2.0 * sigma_cp ** 2))
|
| 162 |
+
return {"t": t, "plasticity_rate": round(max(rate, alpha_floor), 6),
|
| 163 |
+
"cite": "Hubel & Wiesel, Nobel 1981 (critical periods)"}
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def summary() -> dict:
|
| 167 |
+
return {
|
| 168 |
+
"title": "SZL Neuroplasticity — learning-rule formulas grounding a11oy's agent loop",
|
| 169 |
+
"honest_frame": ("Rigorous, cited learning-rule math (Hebb/Oja/BCM/STDP/scaling) "
|
| 170 |
+
"+ the modern loss-of-plasticity frontier (Dohare-Sutton Nature "
|
| 171 |
+
"2024) for long-running agents. The PC↔Hebbian unifying identity "
|
| 172 |
+
"(Millidge 2022) is a PROPOSED lens, NOT a Λ theorem."),
|
| 173 |
+
"rules": ["hebb", "oja", "bcm", "stdp", "synaptic_scaling",
|
| 174 |
+
"plasticity_health", "ewc", "critical_period"],
|
| 175 |
+
"tiers": {
|
| 176 |
+
"hebb_oja_bcm_stdp_scaling": "RIGOROUS (classical)",
|
| 177 |
+
"loss_of_plasticity_redo_ewc": "RIGOROUS (recent, cited)",
|
| 178 |
+
"predictive_coding_hebbian_unifier": "PROPOSED lens (not a Λ claim)",
|
| 179 |
+
},
|
| 180 |
+
"doctrine": {"locked_count_unchanged": True, "lambda": "Conjecture 1 (never theorem)",
|
| 181 |
+
"trust_never_100": True, "tier": "EXPERIMENTAL/PROPOSED"},
|
| 182 |
+
"lean_candidates": ["Oja convergence to top eigenvector", "BCM fixed-point",
|
| 183 |
+
"critical-period envelope monotone past peak"],
|
| 184 |
+
"cites": [
|
| 185 |
+
"Hebb 1949", "Oja 1982 DOI:10.1007/BF00275687",
|
| 186 |
+
"BCM 1982 DOI:10.1523/JNEUROSCI.02-01-00032.1982",
|
| 187 |
+
"Bi-Poo 1998 DOI:10.1523/JNEUROSCI.18-24-10464.1998",
|
| 188 |
+
"Turrigiano 2008 DOI:10.1016/j.cell.2008.10.008",
|
| 189 |
+
"Dohare-Sutton 2024 DOI:10.1038/s41586-024-07711-7",
|
| 190 |
+
"Kirkpatrick 2017 DOI:10.1073/pnas.1611835114",
|
| 191 |
+
"Millidge 2022 arXiv:2206.02629",
|
| 192 |
+
],
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
def register(app, ns: str) -> None:
|
| 197 |
+
base = f"/api/{ns}/v1/neuro"
|
| 198 |
+
app.add_api_route(f"{base}/summary", lambda: summary(), methods=["GET"])
|
| 199 |
+
app.add_api_route(
|
| 200 |
+
f"{base}/hebb",
|
| 201 |
+
lambda w="0.1,0.1", x="1,0", y="1.0", eta="0.1":
|
| 202 |
+
{"w_next": [round(c, 6) for c in hebb_update(
|
| 203 |
+
[float(a) for a in w.split(",")], [float(a) for a in x.split(",")],
|
| 204 |
+
float(y), float(eta))], "note": "Hebb is unstable alone; see Oja/BCM",
|
| 205 |
+
"cite": "Hebb 1949"},
|
| 206 |
+
methods=["GET"])
|
| 207 |
+
app.add_api_route(
|
| 208 |
+
f"{base}/oja",
|
| 209 |
+
lambda data="2,0;1,0;3,0;0,0", eta="0.05", epochs="30":
|
| 210 |
+
oja_fit([[float(v) for v in row.split(",")] for row in data.split(";") if row.strip()],
|
| 211 |
+
float(eta), int(epochs)),
|
| 212 |
+
methods=["GET"])
|
| 213 |
+
app.add_api_route(
|
| 214 |
+
f"{base}/bcm",
|
| 215 |
+
lambda y="0.2,0.5,0.9,1.2": bcm_threshold([float(v) for v in y.split(",") if v.strip()]),
|
| 216 |
+
methods=["GET"])
|
| 217 |
+
app.add_api_route(
|
| 218 |
+
f"{base}/stdp",
|
| 219 |
+
lambda dt="10": stdp_window(float(dt)), methods=["GET"])
|
| 220 |
+
app.add_api_route(
|
| 221 |
+
f"{base}/plasticity",
|
| 222 |
+
lambda act="0.5,0.0,0.0001,0.8,0.0":
|
| 223 |
+
plasticity_health([float(v) for v in act.split(",") if v.strip()]),
|
| 224 |
+
methods=["GET"])
|
| 225 |
+
app.add_api_route(
|
| 226 |
+
f"{base}/ewc",
|
| 227 |
+
lambda theta="1,1", star="0,0", fisher="2,1", lam="1.0":
|
| 228 |
+
ewc_penalty([float(v) for v in theta.split(",")],
|
| 229 |
+
[float(v) for v in star.split(",")],
|
| 230 |
+
[float(v) for v in fisher.split(",")], float(lam)),
|
| 231 |
+
methods=["GET"])
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
def _selftest() -> None:
|
| 235 |
+
# Hebb grows weight for correlated input
|
| 236 |
+
w1 = hebb_update([0.0, 0.0], [1.0, 0.0], 1.0, 0.1)
|
| 237 |
+
assert w1[0] > 0 and abs(w1[1]) < 1e-12
|
| 238 |
+
# Oja: data varying only along axis 0 -> principal direction ~ (±1, 0)
|
| 239 |
+
X = [[2.0, 0.0], [1.0, 0.0], [3.0, 0.0], [-2.0, 0.0], [0.5, 0.0]]
|
| 240 |
+
res = oja_fit(X, eta=0.02, epochs=200)
|
| 241 |
+
pd = res["principal_direction"]
|
| 242 |
+
assert abs(abs(pd[0]) - 1.0) < 0.05 and abs(pd[1]) < 0.05, pd
|
| 243 |
+
assert res["eigenvalue_estimate"] > 0
|
| 244 |
+
# BCM: above-threshold activity potentiates, below depresses
|
| 245 |
+
assert bcm_threshold([0.1, 0.1, 0.1, 1.0])["plasticity_sign"] == "potentiate"
|
| 246 |
+
assert bcm_threshold([1.0, 1.0, 1.0, 0.1])["plasticity_sign"] == "depress"
|
| 247 |
+
# STDP: pre-before-post (dt>0) LTP, post-before-pre (dt<0) LTD
|
| 248 |
+
assert stdp_window(10)["delta_w"] > 0
|
| 249 |
+
assert stdp_window(-10)["delta_w"] < 0
|
| 250 |
+
assert abs(stdp_window(0)["delta_w"]) < 1e-12
|
| 251 |
+
# Plasticity health: dormant units detected
|
| 252 |
+
ph = plasticity_health([0.5, 0.0, 0.00001, 0.8, 0.0])
|
| 253 |
+
assert ph["dormant_units"] == 3 and ph["plasticity_score"] < 0.5
|
| 254 |
+
# EWC penalty non-negative, zero at theta==theta_star
|
| 255 |
+
assert ewc_penalty([1, 1], [1, 1], [2, 3])["ewc_penalty"] == 0.0
|
| 256 |
+
assert ewc_penalty([1, 0], [0, 0], [2, 0])["ewc_penalty"] > 0
|
| 257 |
+
# critical period: peaks at t_peak, decays away
|
| 258 |
+
assert critical_period_rate(0.0, t_peak=0.0)["plasticity_rate"] > \
|
| 259 |
+
critical_period_rate(5.0, t_peak=0.0)["plasticity_rate"]
|
| 260 |
+
# guards
|
| 261 |
+
assert oja_fit([])["status"] == "out_of_domain"
|
| 262 |
+
assert summary()["doctrine"]["lambda"].startswith("Conjecture 1")
|
| 263 |
+
print("szl_neuroplasticity: ALL OK (13 checks)")
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
if __name__ == "__main__":
|
| 267 |
+
_selftest()
|