betterwithage commited on
Commit
af3241e
·
verified ·
1 Parent(s): bcde676

chore(sync): mirror backend .py + Dockerfile to Space (hf-sync-backend)

Browse files

Automated 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.

Files changed (3) hide show
  1. Dockerfile +1 -1
  2. serve.py +20 -0
  3. 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()