# Архитектура Kokao Engine v1.0

Этот документ описывает жизненный цикл тензора и поток данных внутри движка.

## 1. Ядро `KokaoCoreV9`

Ядро хранит веса `w` (тензор, нормализованный так, что `∑|w| = 100`). Основные методы:

- `signal(x)` – прямое вычисление `S = wᵀx`.
- `train(x, target)` – классическое обучение по правилу Косякова (без градиентов).
- `train_many(X, target, epochs, lr)` – градиентное обучение с Adam.
- `forget(rate)` – уменьшение весов и перенормализация.

Ядро поддерживает autograd, поэтому градиенты могут течь через него (используется в инверсии).

---

## 2. Поток данных при инверсии

### 2.1 CounterfactualKokao

1. Принимает исходный вектор `x` и желаемое изменение сигнала `delta`.
2. Клонирует `x` с `requires_grad=True`, создаёт оптимизатор (Adam).
3. На каждой итерации:
   - Вычисляет `S = core.signal(x_c)`.
   - Считает потерю `(S - (S0 + delta))² + λ‖x_c - x‖₁`.
   - `loss.backward()` – градиенты по `x_c`.
   - Оптимизатор обновляет `x_c`.
4. Возвращает изменённый вектор.

### 2.2 KokaoDecoder

1. Принимает целевой сигнал `target_S`.
2. Инициализирует случайный вектор `x` с `requires_grad=True`.
3. Оптимизирует его, чтобы `S(x)` приближалось к `target_S` (аналогично, но без привязки к исходному `x`).
4. Возвращает сгенерированный вектор.

---

## 3. Генетическая оптимизация `EvolveKokao`

- Не использует градиенты.
- Рассматривает веса `w` как хромосому.
- Создаёт популяцию, скрещивает, мутирует.
- Фитнес-функция: `1 / (потеря после обучения на случайном батче + ε)`.
- Возвращает лучшие веса.

---

## 4. Взаимодействие модулей

Все модули общаются с ядром через его методы (`signal`, `train`). Ни один модуль не изменяет ядро напрямую, что гарантирует стабильность и обратную совместимость.

### Схема потока данных (текстовая)

```
User input (x)
↓
[optional: normalize Σ|x| = 100]
↓
core.signal(x) → S
↓
if inversion (CF/Decoder):
    x_c = x.detach().clone().requires_grad_(True)
    optimizer = Adam([x_c], lr=...)
    for step in steps:
        S_c = core.signal(x_c)
        loss = (S_c - target)**2 + λ·L1(x_c - x)
        loss.backward()
        optimizer.step()
    return x_c.detach()

if evolution:
    population ← random_individuals
    for generation in n_gen:
        evaluate each individual (create core, train on random x, compute loss)
        select best, crossover, mutate
    return best individual (weights)
```

Все компоненты взаимозаменяемы: ядро работает как функция без состояния, а инверсия и эволюция — это отдельные алгоритмы, которые многократно его вызывают.
