Валидатор первым: метод работы¶
Главное организационное решение проекта. Всё остальное — следствия.
Почему¶
Режим работы — код пишут агенты, один человек ревьюит. В таком режиме единственный масштабируемый способ контроля — числовой:
Вы можете контролировать агентов только в том, что умеете проверить.
Читать весь код нереально. Доверять уверенным объяснениям нельзя — они правдоподобны ровно в той же мере, что и верные. Остаётся одно: независимая функция, которая берёт план и возвращает числа. Дальше агенты гоняют хоть сто итераций — ревьюер смотрит в таблицу метрик.
Эта задача выбрана именно потому, что в ней такая функция существует
(60-decisions/01 (../60-decisions/01-why-task-5.md)). Не воспользоваться этим было бы странно.
Порядок работ¶
1. Схемы входа и выхода ← без них нечего валидировать
2. Генератор тестовых сценариев ← без них не на чем гонять
3. Валидатор метрик ← без него нечем мерить
4. Наивный бейзлайн ← без него метрики ни с чем не сравнить
─────────────────────── только теперь ───────────────────────
5. Геометрия съёмки
6. Покрытие
7. Распределение
8. Экспорт
9. Фронтенд
Шаги 1–4 — это полтора-два дня, и они окупаются немедленно: после них любое изменение в алгоритме немедленно выражается в дельте метрик.
Что считает валидатор¶
Скрипт берёт сценарий и план как данные и пересчитывает всё заново по геометрии.
Жёсткие проверки — любое ненулевое значение означает невалидный план¶
| Метрика | Условие |
|---|---|
violations.nfz |
длина траектории внутри бесполётных зон = 0 |
violations.airspace |
длина траектории вне разрешённого ВП = 0 |
violations.endurance |
ни один вылет не превышает endurance · (1 − reserve) |
violations.wind |
W ≤ wind_max для всех задействованных бортов; |W⊥| < V_a на каждом галсе |
violations.payload |
тип съёмки каждого галса совместим с нагрузкой назначенного борта |
violations.altitude |
высота в пределах потолков борта, не ниже точки старта |
violations.turnaround |
интервал между вылетами борта ≥ времени оборота |
unassigned |
список неназначенных галсов с причиной — пустой или объяснённый |
Метрики качества — то, что оптимизируем¶
| Метрика | Смысл |
|---|---|
coverage_fraction |
площадь объединения полос захвата ∩ полигон / площадь полигона |
makespan_s |
R-OPT-1 |
total_flight_time_s |
R-OPT-2 |
transects_total, turns_total |
косвенно — качество выбора угла |
turn_time_fraction |
доля времени на разворотах; показывает, насколько наивная оценка врёт |
uavs_used, sorties_total |
загрузка парка |
solve_time_s |
масштабируемость |
Принцип независимости¶
Валидатор не импортирует ничего из coverage/ и routing/. Если он использует те же функции,
что и решатель, он воспроизведёт ту же ошибку и промолчит.
Геометрию он считает сам: берёт координаты из плана, строит буферы полос захвата, пересекает с полигонами и зонами. Медленнее — и это нормально, он не в горячем пути.
Формат отчёта¶
Одна команда, одна таблица:
$ python -m validator run --scenarios scenarios/ --criteria makespan,total_time
scenario crit makespan total_fl cover turns% solve viol
─────────────────────────────────────────────────────────────────────────────────
s01-single-simple makespan 0:22:14 0:22:14 1.000 18% 0.4s 0
s01-single-simple total_time 0:22:14 0:22:14 1.000 18% 0.3s 0
s02-nonconvex-nfz makespan 0:41:07 1:58:22 0.998 24% 3.1s 0
s02-nonconvex-nfz total_time 0:58:40 1:44:05 0.998 22% 2.8s 0
s03-mixed-payloads makespan 1:28:00 3:51:12 0.996 21% 12.4s 0
...
─────────────────────────────────────────────────────────────────────────────────
БЕЙЗЛАЙН (равное деление)
s03-mixed-payloads naive 2:14:30 4:02:55 0.994 29% 0.1s 0
↑ −34,5% ↑ −4,8%
Три свойства, которые делают эту таблицу рабочим инструментом:
- Одна команда — никаких «запусти сервер, открой браузер, кликни».
- Бейзлайн в той же таблице — сразу виден процент улучшения.
- Колонка
violс нулями — первое, куда смотрит ревьюер. Ненулевое значение отменяет всё остальное.
Как это встраивается в цикл разработки¶
задача агенту → агент пишет → валидатор гоняет 10 сценариев → таблица
↑ │
└──────────── ревьюер смотрит дельту метрик ───────────────────┘
Правила ревью:
violне ноль — отклонить не читая.- Метрики не изменились — рефакторинг безопасен, можно не вчитываться.
- Метрики улучшились — проверить, что улучшение не за счёт нарушения (например, покрытие упало ниже порога, а makespan «улучшился»).
- Метрики ухудшились — разбираться предметно.
Последний пункт — единственный случай, где нужно читать код. В остальных хватает таблицы.
Регрессионные тесты как страховка от отката¶
Отдельная категория тестов — те, что ловят возврат к наивным формулам:
| Тест | Что ловит |
|---|---|
T_план ≥ L_total / V_g строго |
убрали учёт разворотов |
| площадь в проекции = геодезической ±0,1 % | считают в градусах |
| центроид выгрузки внутри bbox входа | перепутали lon/lat |
в каждом LineString KML есть altitudeMode |
потеряли высоты |
| makespan монотонно не растёт с ростом числа бортов | сломали SetGlobalSpanCostCoefficient |
| GSD на контрольных высотах совпадает с таблицей | сломали геометрию съёмки |
| round-trip экспорт → импорт сохраняет геометрию | сломали конвертер |
при фиксированном seed результат воспроизводим |
потеряли детерминизм |
Эти тесты стоят по несколько строк каждый и ловят ровно те ошибки, которые агент может внести «улучшая» код.
Валидатор как часть продукта¶
Ещё один аргумент за: валидатор можно выставить наружу как POST /validate. Тогда на защите звучит:
Вот наш план. Вот наш же валидатор — он считает метрики независимо от решателя. Загрузите любой другой план, хоть от конкурентов, он проверит и его.
Стоит 0,2 дня, а на критерий «обоснованность подхода» работает сильно.
Связь с автодизайном эвристик¶
Схема ReEvo/EoH (50-stack/02 (../50-stack/02-llm-and-ml.md)) требует ровно одного — функции оценки,
возвращающей число по сгенерированному коду. Это тот же валидатор. То есть полтора дня,
вложенные в него, открывают ИИ-слой бесплатно.
Порядок при этом не меняется: сначала валидатор, потому что без него ни оптимизатор, ни LLM-эволюция просто не с чем работать.