# Пошаговое руководство по курсу

> Лабораторные используют локальные реализации оракулов. Для интеграции найдите точную возможность в [поиске Hub](https://modelmarket.dev/ai-market/v2/search?intent=colony.optimize%40v1&limit=5), затем используйте опубликованную схему и цену. Возможность M1 — `colony.optimize@v1`. Разрыв до нижней границы оценивает качество маршрута. В M2 проверка оптимальности по двойственному сертификату проходит по матрице затрат.

> **Для кого:** разработчики, которым нужен результат оптимизации, который проверяющий может *перепроверить*, а не просто принять на веру.
> **Язык лаб:** `COURSE_LANG=ru|en|es` · строки UI в `i18n/` · этот гайд на русском.
> **English:** [step-by-step.md](./step-by-step.md) · **Español:** [step-by-step.es.md](./step-by-step.es.md)

---

## Зачем доказательства?

Большинство кода оптимизации возвращает ответ — маршрут, план транспорта, путь, прогноз — и просит ему доверять. Курс переворачивает подход: **каждая лаба выдаёт сертификат**, который вызывающая сторона может дёшево перепроверить, не запуская решатель заново и не доверяя оракулу, выдавшему ответ.

- **TSP** возвращает маршрут *и* допустимую нижнюю оценку → можно ограничить **зазор** до оптимума.
- **Оптимальный транспорт** возвращает план *и* двойственные потенциалы → свидетельство сильной двойственности за O(m×n).
- **Маршрутизация по минимальному времени** возвращает путь *и* эйкональные потенциалы → проверка по каждому ребру, без повторного решения.
- **Гауссовские процессы** возвращают апостериор *и* воспроизводимую проверку среднего и дисперсии.

Четыре лабораторные используют локальные реализации оракулов **AIMarket** — COLONY, KANTOR, FERMAT, GAUSS, — а капстоун M5 связывает все четыре сертификата в один аудит. Это и есть паттерн проверяемых агентов: ответ, который агент ниже по цепочке может локально отклонить, если сертификат не сошёлся.

---

## Содержание

1. [Выбор трека](#выбор-трека)
2. [Установка (10 минут)](#установка-10-минут)
3. [M1 — TSP с зазором качества](#m1--tsp-с-зазором-качества)
4. [M2 — Оптимальный транспорт](#m2--оптимальный-транспорт)
5. [M3 — Маршрутизация по минимальному времени](#m3--маршрутизация-по-минимальному-времени)
6. [M4 — Гауссовские процессы](#m4--гауссовские-процессы)
7. [M5 — Капстоун: портфель доказательств](#m5--капстоун-портфель-доказательств)
8. [Упражнения и сертификат](#упражнения-и-сертификат)
9. [Наблюдаемость в каждой лабе](#наблюдаемость-в-каждой-лабе)
10. [Мост: от курса к продакшен-оракулам](#мост-от-курса-к-продакшен-оракулам)
11. [Чеклист самопроверки](#чеклист-самопроверки)
12. [Типичные проблемы](#типичные-проблемы)

---

## Выбор трека

| Трек | Модули | Время | Оракулы |
|------|--------|-------|---------|
| **Базовый** | M1 → M2 → M3 → M4 | ~2 ч | COLONY, KANTOR, FERMAT, GAUSS |
| **Продвинутый** | Базовый + капстоун M5 | +30 мин | Все четыре в одном аудите |

После каждой лабы смотрите блок `Trace` — это журнал сертификатов лабы.

---

## Установка (10 минут)

### Шаг 1 — Клон и установка

```bash
git clone https://github.com/alexar76/aimarket-courses.git
cd aimarket-courses/optimization-with-proofs-course
pip install -e ".[oracles,dev]"
```

Экстра `[oracles]` тянет `numpy`, `[dev]` — `pytest`. Нужен Python 3.11+.

**Из монорепозитория aicom** (для контрибьюторов):

```bash
cd courses/optimization-with-proofs-course
pip install -e ".[oracles,dev]"
```

Пакеты оракулов подключаются автоматически: `courselib/oracle_paths.py` поднимается до корня монорепо и добавляет в `sys.path` каталоги `oracles/oracles/{colony,kantor,fermat,gauss}` и `oracles/core` (зависимость FERMAT).

**Отдельный клон** без соседнего монорепо:

```bash
git clone --depth 1 https://github.com/alexar76/oracles.git _deps/oracles
pip install -e _deps/oracles/core
for pkg in colony kantor fermat gauss; do
  pip install -e _deps/oracles/oracles/$pkg
done
pip install -e ".[oracles,dev]"
```

### Шаг 2 — Тесты

```bash
pytest -q
```

**Ожидается:** паритет ключей i18n (en/ru/es), интеграция с оракулами оптимизации, упражнения и smoke-импорты лаб проходят.

### Шаг 3 — Язык интерфейса лаб (опционально)

```bash
export COURSE_LANG=ru   # или es, по умолчанию en
python labs/lab01_colony_tsp.py
```

`COURSE_LANG` переключает заголовки модулей, концепции и подсказки к упражнениям через `i18n/{en,ru,es,fr,zh}.json`. Числа, сертификаты и имена оракулов остаются прежними.

### Шаг 4 — Google Colab

1. Откройте [сайт курса](https://alexar76.github.io/aimarket-courses/optimization-with-proofs-course/) → **Open in Colab** на любой лабе.
2. Выполните setup-ячейку (clone + pip + срез оракулов).
3. При необходимости задайте `os.environ["COURSE_LANG"] = "ru"`.
4. Запустите ячейку лабы.

---

## M1 — TSP с зазором качества

**Концепция:** маршрут «ближайший сосед» + 2-opt с допустимой нижней оценкой.
**Лаба:** `labs/lab01_colony_tsp.py` · **~20 мин**

### Шаги

1. `python labs/lab01_colony_tsp.py`
2. Прочитайте docstring, затем смотрите **маршрут**, **длину**, **нижнюю оценку**, **зазор %** и **базу nn**.
3. Инстанс — пятиугольник с центром из `demo_tsp_points()`; `solve_tsp()` вызывает `colony.tsp.solve(...)` и добавляет флаг `certificate_valid`.
4. Убедитесь, что `certificate_valid=True` — он верен, когда `gap >= 0` **и** `length >= lower_bound` (допустимый сертификат).
5. **Упражнение:** `python labs/run_exercises.py --module m1`

**Что доказывает:** зазор `(length - lower_bound) / lower_bound` — сертификат качества: даже без оптимального маршрута можно заявить «в пределах X% от оптимума».

### Самопроверка

- [ ] Зазор неотрицателен и равен `(length - lb) / lb`
- [ ] 2-opt никогда не удлиняет маршрут NN

---

## M2 — Оптимальный транспорт

**Концепция:** точный план Канторовича с двойственным сертификатом.
**Лаба:** `labs/lab02_kantor_transport.py` · **~25 мин**

### Шаги

1. `python labs/lab02_kantor_transport.py`
2. Сравните **стоимость транспорта**, **расстояние W₂**, **двойственную цель** и **метод**.
3. `solve_transport()` вызывает `kantor.transport(...)`, затем `kantor.verify(...)`, передавая заявленную стоимость и двойственные потенциалы. KANTOR ждёт `source_points`/`sink_points`, а не `points_a`/`points_b`.
4. Убедитесь, что `verify: True` — потенциалы свидетельствуют оптимальность за O(m×n).
5. **Упражнение:** `python labs/run_exercises.py --module m2`

**Что доказывает:** сильную двойственность — стоимость ≈ `Σ aᵢuᵢ + Σ bⱼvⱼ` при `uᵢ + vⱼ ≤ Cᵢⱼ` на каждой паре. Проверяющий подтверждает это за один проход.

### Самопроверка

- [ ] Сильная двойственность: cost ≈ Σ aᵢuᵢ + Σ bⱼvⱼ
- [ ] Допустимость двойственной: uᵢ + vⱼ ≤ Cᵢⱼ на каждой паре

---

## M3 — Маршрутизация по минимальному времени

**Концепция:** эйкональные потенциалы и двойственная оптимальность в сетях агентов.
**Лаба:** `labs/lab03_fermat_route.py` · **~20 мин** · нужен M1 или M2

### Шаги

1. `python labs/lab03_fermat_route.py`
2. Смотрите путь `client → router → … → sink` и **суммарную стоимость**.
3. Граф — из `demo_routing_graph()`: рёбра смешивают **стоимость**, **задержку** и **репутацию** между пятью узлами. `route_least_time()` вызывает `fermat.eikonal.route(...)`, затем `eikonal.verify(...)`.
4. Убедитесь, что `verify: True` — `T(v) ≤ T(u) + n(u,v)` на каждом ребре, с равенством на рёбрах выбранного пути.
5. **Упражнение:** `python labs/run_exercises.py --module m3`

> FERMAT зависит от `oracle_core`; `ensure_oracles` ставит `oracle_core` перед `fermat`.

**Что доказывает:** потенциалы `T` образуют двойственный сертификат — проверяющий подтверждает минимальное время пути, не запуская Дейкстру заново.

### Самопроверка

- [ ] Потенциалы T — двойственный сертификат без повторного Дейкстры
- [ ] Рёбра пути с равенством: T(v) = T(u) + n(u,v)

---

## M4 — Гауссовские процессы

**Концепция:** апостериорная неопределённость и Expected Improvement.
**Лаба:** `labs/lab04_gauss_gp.py` · **~25 мин**

### Шаги

1. `python labs/lab04_gauss_gp.py`
2. Смотрите апостериорные **μ** и **σ** в каждой точке запроса, затем предложение Expected Improvement `x` и `EI`.
3. `gp_posterior()` вызывает `gauss.gp.field(...)`, `gauss.gp.verify(...)` и `gauss.gp.suggest(...)` с `goal="min"`. EI предлагает следующий лучший эксперимент для минимизации.
4. Убедитесь, что `verify: True` — апостериорные среднее и дисперсия воспроизводятся из обучающих данных.
5. **Упражнение:** `python labs/run_exercises.py --module m4`

**Что доказывает:** сертификат-воспроизведение — апостериор можно пересчитать из обучающих точек и отклонить несовпадающее заявление. EI превращает неопределённость в следующий запрос.

### Самопроверка

- [ ] Апостериорная дисперсия растёт вдали от обучающих точек
- [ ] EI балансирует эксплуатацию (низкое среднее) и разведку (высокая σ)

---

## M5 — Капстоун: портфель доказательств

**Концепция:** связать сертификаты TSP, транспорта, маршрута и GP в одном аудите.
**Лаба:** `labs/lab05_proof_capstone.py` · **~30 мин** · нужны M1–M4

### Шаги

1. `python labs/lab05_proof_capstone.py`
2. Смотрите каждый флаг сертификата (`success`/`blocked`): `tsp_gap_ok`, `transport_verified`, `route_verified`, `gp_verified`.
3. Прочитайте `proof_portfolio()` в `courselib/optimization.py` — он запускает все четыре оракула и собирает флаги.
4. Убедитесь, что `all_verified=True` — каждый сертификат оракула проходит.
5. **Упражнение:** `python labs/run_exercises.py --module m5`

**Что доказывает:** единый составной объект аудита — агент ниже по цепочке отклоняет весь результат, если падает хоть один сертификат; ни одному оракулу не доверяют вслепую.

### Самопроверка

- [ ] Можете объяснить, что доказывает каждый сертификат
- [ ] Проверяющий отклоняет плохой ответ, не доверяя оракулу

---

## Упражнения и сертификат

После лаб запустите проверки:

```bash
python labs/run_exercises.py                          # все упражнения модулей
python labs/run_exercises.py --module m1              # один модуль
python labs/run_exercises.py --certificate "Иван Петров" --lang ru
```

| Модуль | Проверки упражнения |
|--------|---------------------|
| M1 | Сертификат зазора TSP валиден; `length >= lower_bound`; `gap >= 0` |
| M2 | Двойственная Канторовича проходит; cost > 0 |
| M3 | Потенциалы маршрута FERMAT проходят; путь `client → sink` |
| M4 | Апостериор GP проходит; `len(mean) == len(std)` |
| M5 | Полный портфель — все четыре сертификата проходят |

`run_exercises.py` запускает все проверки и печатает `✓`/`✗` по модулям. Флаг `--certificate` генерирует `certificate.html` **только после прохождения всех упражнений** (обход — `--skip-check`). Откройте файл в браузере и **Print → Save as PDF**. ID сертификата — это SHA-256 от имени и даты, а сам сертификат локализуется по `--lang en|ru|es`.

---

## Наблюдаемость в каждой лабе

**Концепция:** каждая лаба логирует решения в `Trace` (`courselib/trace.py`) — это аудит-след для сертификатов оптимизации.

### Шаги (после каждой лабы)

1. Найдите строку **trace** в выводе (она печатает число событий).
2. Сопоставьте события с stdout: зазор TSP, стоимость транспорта, итог маршрута, проверка GP.
3. В M5 каждый флаг оракула становится событием `certificate` — соотнесите упавший флаг с событием.

### Самопроверка

- [ ] Trace фиксирует исход проверки для каждого вызова оракула
- [ ] Можете объяснить, что упадёт, если оракул соврёт об оптимальности

---

## Мост: от курса к продакшен-оракулам

**Цель:** связать концепции курса с живыми развёртываниями оракулов AIMarket (~30 мин).

1. **Читайте README оракулов** в `oracles/oracles/{colony,kantor,fermat,gauss}/`.

2. **Сопоставление курс → возможности оракула**

   | Курс | Оракул | Возможность |
   |------|--------|-------------|
   | M1 | COLONY | TSP + сертификат зазора |
   | M2 | KANTOR | `kantor.transport@v1` + `kantor.verify@v1` |
   | M3 | FERMAT | `fermat.route@v1` + `fermat.verify@v1` |
   | M4 | GAUSS | `gauss.field@v1` + `gauss.suggest@v1` + `gauss.verify@v1` |
   | M5 | Все | Составной аудит в `proof_portfolio()` |

3. **Сравните сертификаты** — проверяющий может проверить артефакт независимо от решателя. Стоимость зависит от метода: KANTOR обходит матрицу затрат, GAUSS повторяет вычисление апостериорного распределения.

---

## Чеклист самопроверки

Базовый трек:

- [ ] lab01–lab04 локально и в Colab
- [ ] Объясняете зазор TSP как сертификат качества
- [ ] Формулируете условия допустимости двойственной Канторовича
- [ ] Проверяете путь FERMAT без повторного решения
- [ ] Интерпретируете апостериорную неопределённость GP и EI

Продвинутый трек добавляет:

- [ ] lab05 и перечень всех четырёх типов сертификатов
- [ ] Набросок воркфлоу агента, отклоняющего ответы при провале `verify`

---

## Типичные проблемы

| Проблема | Решение |
|----------|---------|
| `ModuleNotFoundError: courselib` | Запуск из корня репо; лабы добавляют родителя в `sys.path` |
| `Oracle package '...' not installed` | Запуск из монорепо aicom либо `pip install -e ".[oracles]"` |
| `ImportError: Oracle package 'fermat'` | Сначала `oracle_core`, затем fermat (`ensure_oracles` это делает) |
| `provide source_points+sink_points` | KANTOR ждёт `source_points`/`sink_points`, не `points_a` |
| `'goal' must be 'max' or 'min'` | EI у GAUSS использует `goal="min"` или `"max"` |
| Нет `numpy` | `pip install -e ".[oracles,dev]"` |
| Пустые строки RU/ES | Задайте `COURSE_LANG`; проверьте паритет ключей i18n |
| Старый код в Colab | Перезапустите setup-ячейку; закрепите ветку `main` |

---

## Обновление сайта и ноутбуков

После правок лаб или i18n:

```bash
python3 scripts/build_course_assets.py
python3 scripts/labs_to_notebooks.py
```

Гайды в `docs/` правятся вручную — сначала EN, затем зеркала RU/ES.
