Wiki: rewrite as a connected chain of pages with project engineering details

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFVgZ8Nct8BEh9k7bjuRdw
This commit is contained in:
Claude 2026-10-19 11:02:28 +00:00
parent 69ad76bde2
commit 597e40afaf
No known key found for this signature in database
3 changed files with 763 additions and 446 deletions

View file

@ -82,11 +82,8 @@
.content .w-bar::after { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; background: var(--text); opacity: .5; }
.content .w-bar i { position: absolute; inset: 0 auto 0 0; border-radius: 99px; background: var(--w-good); }
.content .w-bar i.no { background: var(--w-bad); }
.content .def { border-left: 2px solid var(--text); padding: .2rem 0 .2rem 1rem; margin: 1rem 0 1.4rem; font-size: 1.08em; }
.content .facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin: 1.2rem 0 1.6rem; }
.content .facts div { border: 1px solid var(--border); border-radius: 16px; padding: 12px 14px; background: var(--shell); display: flex; flex-direction: column; gap: 2px; }
.content .facts b { font-size: 1.5em; font-weight: 600; font-variant-numeric: tabular-nums; }
.content .facts span { color: var(--muted); font-size: .88em; }
@media (max-width: 640px) { .content .w-px { width: 96px; height: 96px; } .content .w-kv { grid-template-columns: 1fr; } }
@media print { .content .w-card { display: none; } }
@media (prefers-reduced-motion: reduce) { .content * { transition: none !important; } }
.content .next { margin-top: 2.4rem; padding-top: 1rem; border-top: 1px solid var(--border); color: var(--muted); }
.content .next a { font-weight: 600; }

View file

@ -270,29 +270,12 @@
init(); draw();
};
/* 6. Сетка ядер Алтая */
W.chipgrid = (el) => {
card(el); const svg = s("svg", { viewBox: "0 0 420 420", class: "w-svg", role: "img", "aria-label": "Сетка 4×4 ядра" }), say = note("Нажмите на ядро: пакет со спайком войдёт через порт и пройдёт по соседям."); let path = [], step = 0, target = null, timer = null;
const gx = (i) => 40 + i * 90, gy = (j) => 80 + j * 82;
function draw() { const c = C(); svg.replaceChildren(); svg.append(s("rect", { x: 34, y: 18, width: 352, height: 30, rx: 10, fill: c.spike, opacity: .18 }), s("text", { x: 210, y: 38, "text-anchor": "middle", fill: c.text, "font-size": 13 }, "порт: вход с камеры и выход ответа"));
for (let i = 0; i < 4; i++) { svg.append(s("line", { x1: gx(i) + 35, y1: 48, x2: gx(i) + 35, y2: gy(0), stroke: c.border, "stroke-width": 3 })); for (let j = 0; j < 3; j++) svg.append(s("line", { x1: gx(i) + 35, y1: gy(j) + 70, x2: gx(i) + 35, y2: gy(j + 1), stroke: c.border, "stroke-width": 3 }), s("line", { x1: gx(j) + 70, y1: gy(i) + 35, x2: gx(j + 1), y2: gy(i) + 35, stroke: c.border, "stroke-width": 3 })); }
const vis = new Set(path.slice(0, step + 1).map((p) => p.join()));
for (let j = 0; j < 4; j++) for (let i = 0; i < 4; i++) { const isT = target && target[0] === i && target[1] === j, v = vis.has(i + "," + j);
const r = s("rect", { x: gx(i), y: gy(j), width: 70, height: 70, rx: 14, fill: isT ? c.spike : v ? c.control : c.shell, stroke: v ? c.spike : c.text, "stroke-width": 1.5, tabindex: 0, role: "button", "aria-label": "ядро " + (j * 4 + i + 1), style: "cursor:pointer" });
r.addEventListener("click", () => send(i, j)); r.addEventListener("keydown", (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); send(i, j); } });
svg.append(r, s("text", { x: gx(i) + 35, y: gy(j) + 33, "text-anchor": "middle", fill: isT ? "#fff" : c.text, "font-size": 13, "pointer-events": "none" }, "ядро " + (j * 4 + i + 1)), s("text", { x: gx(i) + 35, y: gy(j) + 51, "text-anchor": "middle", fill: isT ? "#fff" : c.muted, "font-size": 11, "pointer-events": "none" }, "≈512 нейр.")); }
if (path.length) { const p = path[Math.min(step, path.length - 1)]; svg.append(s("circle", { cx: gx(p[0]) + 35, cy: p[1] < 0 ? 33 : gy(p[1]) + 35, r: 8, fill: c.spike, stroke: c.shell, "stroke-width": 2 })); } }
function send(i, j) { target = [i, j]; path = [[i, -1]]; for (let y = 0; y <= j; y++) path.push([i, y]); step = 0; clearInterval(timer);
timer = setInterval(() => { if (!el.isConnected) return clearInterval(timer); step++; draw(); if (step >= path.length - 1) { clearInterval(timer); say.textContent = `Пакет вошёл через порт и дошёл до ядра ${j * 4 + i + 1} за ${j + 1} переход(а). Чем дальше ядро и чем больше пакетов, тем дольше путь — поэтому размещатель кладёт связанные нейроны рядом.`; } }, 260); draw(); }
el.append(svg, say); draw(); alive(el, draw);
};
/* 7. Кроссбар ядра */
W.crossbar = (el) => {
card(el); const cyc = [0, 2, 3, 4, 5, 6, 8, -3, -5]; let Wt = [[4, 2, 0, 3], [4, 0, 5, 3], [3, 4, 0, 0], [0, 4, 6, 2], [0, 0, 3, 5], [-3, 0, 0, -5]], on = [true, true, false, false, false, false], sums = null;
const tb = h("div", { class: "w-xb" }), say = note("");
function draw() { tb.replaceChildren(); tb.append(h("span", { class: "w-cap", text: "аксон ↓ / нейрон →" })); for (let n2 = 0; n2 < 4; n2++) tb.append(h("span", { class: "w-cap", text: "нейрон " + (n2 + 1) }));
Wt.forEach((r, a) => { tb.append(h("button", { type: "button", class: "w-btn", "aria-pressed": String(on[a]), text: "аксон " + (a + 1), onclick: () => { on[a] = !on[a]; sums = null; draw(); } }));
function draw() { tb.replaceChildren(); tb.append(h("span", { class: "w-cap", text: "линия ↓ / нейрон →" })); for (let n2 = 0; n2 < 4; n2++) tb.append(h("span", { class: "w-cap", text: "нейрон " + (n2 + 1) }));
Wt.forEach((r, a) => { tb.append(h("button", { type: "button", class: "w-btn", "aria-pressed": String(on[a]), text: "линия " + (a + 1), onclick: () => { on[a] = !on[a]; sums = null; draw(); } }));
r.forEach((w, n2) => tb.append(h("button", { type: "button", class: "w-cell" + (w > 0 ? " pos" : w < 0 ? " neg" : ""), text: w ? (w > 0 ? "+" + w : String(w)) : "·", "aria-label": `вес ${w}`, onclick: () => { r[n2] = cyc[(cyc.indexOf(w) + 1) % cyc.length]; sums = null; draw(); } }))); });
tb.append(h("span", { class: "w-cap", text: "разных весов" }));
const bad = []; for (let n2 = 0; n2 < 4; n2++) { const k = new Set(Wt.map((r) => Math.abs(r[n2])).filter(Boolean)).size; if (k > 4) bad.push(n2 + 1); tb.append(h("span", { class: "w-cnt " + (k > 4 ? "no" : "ok"), text: k + " из 4" })); }
@ -336,29 +319,7 @@
};
/* 10. Схема трёх архитектур */
W.arch = (el) => {
card(el); let mode = 0; const svg = s("svg", { viewBox: "0 0 700 300", class: "w-svg w-wide", role: "img", "aria-label": "Схема архитектуры" }), tab = h("div", { class: "w-kv" });
const ROWS = [
[["Слои", "пиксели → 10 колонок × 20 нейронов"], ["Ответ", "колонка, которая выстрелила больше"], ["Обучение", "в KNP: STDP и дофамин, без учителя ошибок"], ["Слабость", "учит трафареты, не видит отсутствие линий"]],
[["Слои", "пиксели → 256 скрытых → 160 «за/против»"], ["Ответ", "«за» минус «против», максимум"], ["Обучение", "обычная сеть на компьютере → перенос весов"], ["Цена", "32 такта частотного кода, сотни тысяч синаптических событий"]],
[["Слои", "пиксели → 256 скрытых → 10 выходов"], ["Ответ", "больше спайков, при равенстве — раньше"], ["Обучение", "градиент прямо по тактам динамики Алтая"], ["Выигрыш", "каждый пиксель стреляет один раз, ответ за несколько тактов"]]];
const txt = (x, y, t, size = 12, color, weight = 400, anchor = "middle") => svg.append(s("text", { x, y, "text-anchor": anchor, fill: color || C().muted, "font-size": size, "font-weight": weight }, t));
function draw() { const c = C(); svg.replaceChildren(); const lines = [];
const D7 = [[1, 0], [2, 0], [3, 0], [4, 0], [4, 1], [3, 2], [2, 3], [2, 4], [2, 5]];
for (let y = 0; y < 6; y++) for (let x = 0; x < 6; x++) svg.append(s("rect", { x: 16 + x * 13, y: 110 + y * 13, width: 11, height: 11, rx: 2, fill: D7.some(([a, b]) => a === x && b === y) ? c.text : c.control }));
txt(55, 96, mode === 2 ? "пиксели → один спайк" : "пиксели → спайки");
if (mode === 0) { for (let k = 0; k < 10; k++) { const cx = 190 + k * 36, win = k === 7; svg.append(s("rect", { x: cx - 14, y: 56, width: 28, height: 176, rx: 9, fill: win ? c.control : "none", stroke: win ? c.spike : c.border, "stroke-width": win ? 2 : 1 })); for (let n2 = 0; n2 < 10; n2++) svg.append(s("circle", { cx: cx - 5 + (n2 % 2) * 10, cy: 70 + Math.floor(n2 / 2) * 34, r: 4, fill: win && n2 < 6 ? c.spike : c.pot })); txt(cx, 252, String(k), 13, win ? c.spike : c.text, 600); lines.push([96, 145, cx - 14, 90 + (k * 37) % 120]); }
txt(352, 40, "10 колонок по 20 нейронов: каждая колонка — трафарет своей цифры", 12, c.text, 600); txt(352, 280, "ответ — колонка «7»: выстрелила больше всех", 13, c.text, 600); }
else { const hx = 210, hy = 70; for (let i = 0; i < 64; i++) svg.append(s("circle", { cx: hx + (i % 8) * 16, cy: hy + Math.floor(i / 8) * 20, r: 4.5, fill: (i * 29) % 7 < 2 ? c.spike : c.pot })); txt(hx + 56, 50, "256 скрытых нейронов (показана четверть)", 12, c.text, 600); for (let k = 0; k < 8; k++) lines.push([96, 145, hx - 6, hy + k * 20]);
const ox = 420, oy = 64;
if (mode === 1) { for (let d = 0; d < 10; d++) { const y = oy + d * 19; txt(ox - 10, y + 5, String(d), 12, d === 7 ? c.spike : c.text, 600, "end"); for (let g2 = 0; g2 < 8; g2++) svg.append(s("rect", { x: ox + g2 * 9, y: y - 5, width: 7, height: 10, rx: 2, fill: c.good, opacity: d === 7 ? 1 : .3 }), s("rect", { x: ox + 80 + g2 * 9, y: y - 5, width: 7, height: 10, rx: 2, fill: c.bad, opacity: d === 4 || d === 9 ? .9 : .25 })); lines.push([hx + 118, hy + (d * 31) % 140, ox - 2, y]); }
txt(ox + 32, 48, "за ×8", 11, c.good, 600); txt(ox + 112, 48, "против ×8", 11, c.bad, 600); svg.append(s("rect", { x: 600, y: 140, width: 90, height: 54, rx: 12, fill: c.text })); txt(645, 163, "хост:", 11, c.shell, 600); txt(645, 181, "за − против", 11, c.shell); txt(330, 282, "32 такта · каждый пиксель стреляет до 32 раз", 13, c.text, 600); }
else { for (let d = 0; d < 10; d++) { const y = oy + d * 19; txt(ox - 10, y + 5, String(d), 12, d === 7 ? c.spike : c.text, 600, "end"); svg.append(s("circle", { cx: ox + 10, cy: y, r: 6, fill: d === 7 ? c.spike : c.pot })); for (let t = 0; t < 8; t++) svg.append(s("rect", { x: ox + 26 + t * 12, y: y - 4, width: 9, height: 8, rx: 2, fill: d === 7 && t >= 3 && t % 2 ? c.spike : c.control })); lines.push([hx + 118, hy + (d * 31) % 140, ox + 4, y]); }
txt(ox + 74, 48, "такты 0…7", 11, c.text, 600); txt(330, 282, "8 тактов · каждый пиксель стреляет один раз", 13, c.text, 600); } }
lines.forEach(([x1, y1, x2, y2]) => svg.prepend(s("line", { x1, y1, x2, y2, stroke: c.border })));
tab.replaceChildren(...ROWS[mode].flatMap(([k, v]) => [h("b", { text: k }), h("span", { text: v })])); }
el.append(seg(["Колонки STDP", "Нативная сеть", "Импульсная по тактам"], (i) => { mode = i; draw(); }), h("div", { class: "w-scroll" }, svg), tab); draw(); alive(el, draw);
};
/* 11. Одна цифра — три сети */
W.compare = (el) => {

File diff suppressed because it is too large Load diff