371 lines
24 KiB
Markdown
371 lines
24 KiB
Markdown
# Szilassi — поиск геометрических реализаций многогранников
|
||
|
||
Репозиторий содержит CUDA/CPU-систему поиска геометрических реализаций для 59
|
||
комбинаторных топологий соседственных 12-гранных многогранников. Для каждой
|
||
топологии программа подбирает 12 плоскостей, восстанавливает вершины и минимизирует
|
||
геометрические дефекты.
|
||
|
||
Проект предназначен для вычислительного исследования и не является доказательством
|
||
существования или невозможности бездефектной реализации.
|
||
|
||
## Происхождение
|
||
|
||
Проект основан на исходной кодовой базе CodeParade
|
||
[HackerPoet/NeighborlyPolyhedra](https://github.com/HackerPoet/NeighborlyPolyhedra).
|
||
Постановка задачи и исходное исследование представлены в
|
||
[видео CodeParade](https://youtu.be/5dd8_N_nKRI). Текущая версия существенно
|
||
расширяет исходную реализацию: добавлены CUDA FP32-поиск, CPU/DD-верификация,
|
||
продолжаемые checkpoint, многотопологический планировщик, MAP-Elites/CEM,
|
||
online-MLP, общий Set Transformer ranker и локальный долговременный ML-датасет.
|
||
|
||
## Критерии результата
|
||
|
||
В логах и файлах результатов используются два целочисленных счётчика:
|
||
|
||
- `C` (`crossings`) — самопересечения границы отдельной грани после проекции на
|
||
плоскость этой грани;
|
||
- `I` (`intersections`) — пересечения внутренности грани с рёбрами, которые не
|
||
инцидентны этой грани. Пересечение продолжений вне отрезка или вне многоугольника
|
||
не учитывается.
|
||
|
||
Кандидаты сравниваются лексикографически по кортежу
|
||
`(C + I, max(C, I), C, energy)`. Поэтому уменьшение точного количества дефектов
|
||
важнее гладких штрафов и эвристических оценок.
|
||
|
||
Массовый поиск выполняется на GPU в FP32. Отобранные кандидаты пересчитываются на
|
||
CPU в `double`; состояния около цели дополнительно классифицируются реализацией
|
||
double-double (`WideReal`, примерно 31 десятичный знак). Заявленный результат
|
||
`C/I = 0/0` проходит повторные проверки с несколькими допусками.
|
||
|
||
## Как устроен поиск
|
||
|
||
- Постоянные CUDA-цепочки сохраняют RNG, температуру, шаг, стагнацию и состояние
|
||
между короткими пакетами.
|
||
- Портфель стратегий включает базовый simulated annealing, replica exchange,
|
||
адаптивные ходы, population-based transfer и инъекцию состояний из MAP-Elites,
|
||
CEM и нейросетевой подсказки.
|
||
- Планировщик распределяет работу между топологиями с учётом качества,
|
||
улучшений, неопределённости и давности последнего запуска. Режим проработки
|
||
худших вариантов меняет приоритет, но сохраняет исследование остальных топологий.
|
||
- MAP-Elites поддерживает разнообразие по обусловленности геометрии и локализации
|
||
дефектов. Диагональный CEM строит новые стартовые состояния по успешным потомкам.
|
||
- Небольшой SPSA+Adam этап выполняется на CPU; его результат округляется обратно
|
||
в FP32 и проверяется заново.
|
||
- Нейросеть является только источником предложений. Она не может заменить точную
|
||
CPU/DD-проверку или отключить базовую долю независимого поиска.
|
||
- Общий для 59 топологий Set Transformer ранжирует только управляемую часть
|
||
injected-пула. Из 64 seed-кандидатов 48 по-прежнему формируются MAP-Elites,
|
||
CEM и независимым поиском, 4 управляемых seed остаются контрольными без
|
||
ранжирования, и только 12 выбираются трансформером. Повреждённая,
|
||
несовместимая или неутверждённая модель автоматически отключается.
|
||
|
||
Штраф вырождения намеренно мягкий. По умолчанию полностью учитывается худший из
|
||
барьеров определителя, короткого ребра, малого угла поворота и чрезмерного размера;
|
||
остальные барьеры дают по 5% вклада. Вес штрафа — `0.01`.
|
||
|
||
Поисковый процесс и CUDA stream запускаются с низким приоритетом. Искусственного
|
||
ограничения загрузки GPU нет; короткие kernels обеспечивают отзывчивую остановку
|
||
и устойчивость под Windows WDDM.
|
||
|
||
## Структура репозитория
|
||
|
||
- `projects/Szilassi` — основной CLI-поиск;
|
||
- `projects/PolyhedronGui` — Windows GUI для штатного CUDA-поиска;
|
||
- `projects/VerifyCpp` — отдельная проверка OBJ-кандидатов;
|
||
- `projects/TransformerTrainingExport` — потоковый read-only экспорт размеченных
|
||
trajectory из immutable `.sztd` для обучения;
|
||
- `src/NeighborlyCore` — геометрия, точные предикаты и общие типы;
|
||
- `src/CudaSearch` — FP32 CUDA backend и диагностический CPU stub;
|
||
- `src/Checkpoint` — CRC-защищённые поколения checkpoint;
|
||
- `src/SearchArchive` — mergeable MAP-Elites delta-файлы;
|
||
- `src/OnlineSurrogate` — локальная online residual-MLP модель;
|
||
- `src/TrainingArchive` — локальный долговременный ML-датасет и crash recovery;
|
||
- `src/TransformerRanker` — нативный FP32 inference общей transformer-модели;
|
||
- `tests/TrainingArchiveSelfTest` — тест формата, CRC, WAL, восстановления и лимита;
|
||
- `tests/TransformerRankerSelfTest` — тест features, формата модели, CRC и fallback;
|
||
- `tools/train_transformer.py` — CUDA/PyTorch-обучение и публикация модели;
|
||
- `data` — описание топологий и входные модели;
|
||
- `results/topologies` и `results/showcases` — сохранённые исследовательские модели;
|
||
- `results/search` — продолжаемое геометрическое состояние поиска;
|
||
- `runtime` — временные тестовые прогоны, отчёты и локальные файлы;
|
||
- `build` — централизованный вывод CMake и MSBuild.
|
||
|
||
Общего solution-файла в репозитории нет. Основной поддерживаемый способ сборки —
|
||
CMake; проекты Visual Studio можно собирать по отдельности.
|
||
|
||
## Требования
|
||
|
||
- Windows x64;
|
||
- компилятор с поддержкой C++17;
|
||
- Visual Studio 18 / 2026 с workload для C++ desktop development;
|
||
- CUDA Toolkit 13.3 с интеграцией в Visual Studio для GPU-поиска;
|
||
- NVIDIA GPU с поддерживаемой архитектурой. Сборка содержит цели для Ada `sm_89`
|
||
и Blackwell `sm_120`;
|
||
- Eigen 3.4.0 уже находится в `external/eigen-3.4.0`.
|
||
|
||
Для самого поиска Python не нужен. Для переобучения трансформера дополнительно
|
||
нужны Python 3.12, NumPy и CUDA-сборка PyTorch. Эти зависимости устанавливаются
|
||
в локальную `.venv` и не входят в штатный exe.
|
||
|
||
Без CUDA проект собирает диагностический stub. Запуск с `--cuda` в такой сборке
|
||
завершается с понятной ошибкой и не переключается на CPU незаметно.
|
||
|
||
## Сборка через CMake
|
||
|
||
Из корня репозитория:
|
||
|
||
```powershell
|
||
cmake --preset vs2026-x64
|
||
cmake --build --preset vs2026-release
|
||
ctest --test-dir build/vs2026 -C Release --output-on-failure
|
||
```
|
||
|
||
Основные исполняемые файлы появятся в `build/vs2026/Release`:
|
||
|
||
- `neighborly_main.exe` — поиск;
|
||
- `polyhedron_gui.exe` — GUI;
|
||
- `verify_cpp.exe` — проверка OBJ;
|
||
- `training_archive_selftest.exe` — regression/self-test локального ML-архива.
|
||
- `transformer_training_export.exe` — потоковый экспорт trajectory;
|
||
- `transformer_ranker_selftest.exe` — regression/self-test transformer runtime.
|
||
|
||
Для сборки без CUDA используется отдельный каталог:
|
||
|
||
```powershell
|
||
cmake -S . -B build/cpu -G "Visual Studio 18 2026" -A x64 -DSZILASSI_ENABLE_CUDA=OFF
|
||
cmake --build build/cpu --config Release
|
||
```
|
||
|
||
## Сборка отдельных проектов Visual Studio
|
||
|
||
Если CMake не используется, каждый `.vcxproj` собирается отдельно:
|
||
|
||
```powershell
|
||
msbuild projects\Szilassi\Szilassi.vcxproj /m /p:Configuration=Release /p:Platform=x64
|
||
msbuild projects\PolyhedronGui\PolyhedronGui.vcxproj /m /p:Configuration=Release /p:Platform=x64
|
||
msbuild projects\VerifyCpp\VerifyCpp.vcxproj /m /p:Configuration=Release /p:Platform=x64
|
||
msbuild projects\TransformerTrainingExport\TransformerTrainingExport.vcxproj /m /p:Configuration=Release /p:Platform=x64
|
||
msbuild tests\TrainingArchiveSelfTest\TrainingArchiveSelfTest.vcxproj /m /p:Configuration=Release /p:Platform=x64
|
||
msbuild tests\TransformerRankerSelfTest\TransformerRankerSelfTest.vcxproj /m /p:Configuration=Release /p:Platform=x64
|
||
```
|
||
|
||
Вывод этих проектов находится в `build/msbuild/bin/x64/Release`.
|
||
|
||
## Штатный запуск через GUI
|
||
|
||
Запустите `polyhedron_gui.exe` из CMake-сборки или `PolyhedronGui.exe` из
|
||
MSBuild-сборки. В интерфейсе остаются две управляющие кнопки:
|
||
|
||
- `Запустить поиск` — продолжает исследование с учётом найденных checkpoint;
|
||
- `Остановить поиск` — ждёт окончания короткого CUDA-пакета и сохраняет изменённое
|
||
состояние перед завершением процесса.
|
||
|
||
Настройки GUI:
|
||
|
||
- количество GPU-цепочек (`0` — автоматический выбор по GPU и occupancy);
|
||
- число итераций в одном коротком CUDA-пакете;
|
||
- длительность запуска;
|
||
- включительный диапазон топологий `0..58`;
|
||
- период durable checkpoint;
|
||
- обычный режим или приоритет проработки худших топологий.
|
||
|
||
GUI автоматически создаёт seed нового процесса. Seed и параметры сохраняются в
|
||
`run.tsv`, поэтому запуск можно воспроизвести без поля Seed в интерфейсе.
|
||
|
||
## Запуск через CLI
|
||
|
||
Пример CUDA-поиска топологий 20–29 в течение восьми часов:
|
||
|
||
```powershell
|
||
.\build\vs2026\Release\neighborly_main.exe --global-search --cuda `
|
||
--topology-from 20 --topology-to 29 --minutes 480 `
|
||
--cuda-chains 0 --cuda-iters 64 --checkpoint-seconds 30 `
|
||
--seed 30000157
|
||
```
|
||
|
||
По умолчанию геометрическое состояние находится в `results/search`. Другой каталог
|
||
задаётся через `--global-dir`. Повторный запуск с тем же каталогом продолжает поиск.
|
||
|
||
Дополнительные режимы можно посмотреть через `--help`:
|
||
|
||
- `--study <obj>` — продолжение оптимизации существующего OBJ;
|
||
- `--repair-local <obj>` — локальная координатная коррекция;
|
||
- `--hunt-local <obj>` — сфокусированный поиск около известных дефектов;
|
||
- `--batch-hunt <obj>` — серия независимых локальных запусков;
|
||
- запуск без режима — интерактивный legacy solver.
|
||
|
||
Проверка модели:
|
||
|
||
```powershell
|
||
.\build\vs2026\Release\verify_cpp.exe --obj path\candidate.obj `
|
||
--topology 42 --eps 1e-13 --report runtime\verify.md
|
||
```
|
||
|
||
## Геометрическое состояние и восстановление
|
||
|
||
Состояние штатного поиска хранится в `results/search`:
|
||
|
||
- `topology_N/resume.planes`, `resume.obj`, `resume.meta` — удобное текущее
|
||
представление лучшего результата;
|
||
- `runs/<UUID>/topology_N/checkpoints/*.szcp` — immutable поколения checkpoint с CRC;
|
||
- `runs/<UUID>/topology_N/archive/*.szar` — MAP-Elites delta-файлы;
|
||
- `runs/<UUID>/run.tsv` и `metrics.tsv` — seed, конфигурация и телеметрия запуска.
|
||
|
||
Новые поколения публикуются атомарно после flush. Повреждённое последнее поколение
|
||
не уничтожает предыдущее валидное. При штатной остановке сохраняются все изменённые
|
||
топологии, а ошибка durable-записи приводит к безопасному завершению с ошибкой.
|
||
|
||
`leaderboard.tsv`, временные файлы и логи являются производными и игнорируются Git;
|
||
leaderboard восстанавливается при следующем запуске.
|
||
|
||
## Локальный ML-датасет
|
||
|
||
Обучающие данные и производные neural-модели являются локальным кэшем и **не входят
|
||
в Git**:
|
||
|
||
- `results/search/runs/<UUID>/training` — `.sztd` shards и активный WAL;
|
||
- `results/search/topology_N/neural` — online-модель `.szonn` и служебные receipts;
|
||
- `results/search/neural/transformer` — immutable поколения `.sztf`, активная
|
||
`current.sztf` и отчёты обучения;
|
||
- временные варианты этих файлов и marker достижения лимита.
|
||
|
||
`.gitignore` исключает каталоги `training`, `neural`, все `.sztd/.szonn/.sztf` и их
|
||
временные варианты. Не используйте `git add -f` для этих путей.
|
||
|
||
Schema v3 сохраняет пригодные для последующего обучения факты: каждый успешный и
|
||
неуспешный CPU-верифицированный кандидат, FP32 chain-best выборку с точным `K/N`,
|
||
CUDA lineage и полный RNG snapshot, начальные и injected предложения, проверенные
|
||
rollout, SPSA double-траектории и старый replay в lossless-виде.
|
||
|
||
WAL имеет CRC и durable commit boundary. После сбоя питания незавершённый хвост
|
||
отбрасывается, а подтверждённые записи сохраняются. Завершённые shards immutable.
|
||
|
||
Общий локальный лимит ML-кэша равен ровно `200000000000` байт (200 GB, не GiB).
|
||
В расчёт входят существующие neural-файлы, резерв 59 online-моделей, transformer
|
||
generation/current и временные файлы атомарной замены. При достижении лимита:
|
||
|
||
- новые обучающие записи больше не создаются;
|
||
- online-обучение замораживается;
|
||
- геометрический поиск, CPU/DD-проверка и checkpoint продолжаются;
|
||
- программа выводит предупреждение о необходимости пересмотреть формат/политику
|
||
хранения перед дальнейшим накоплением.
|
||
|
||
Лимит рассчитан для одного поискового процесса в одном checkout.
|
||
|
||
## Обучение трансформера
|
||
|
||
Transformer обучается на GPU, но штатный поиск выполняет его маленький FP32
|
||
inference на CPU, не отнимая CUDA-ресурсы у геометрических цепочек. Основные labels
|
||
берутся только из `InjectedTrajectory`: `SeedProposal` без результата считается
|
||
неизвестным, а не неудачным исходом.
|
||
|
||
Тренер сначала фиксирует список завершённых `.sztd`, проверяет их CRC штатным C++
|
||
reader и создаёт временный бинарный snapshot. Активный WAL и shards, появившиеся
|
||
после начала обучения, в этот snapshot не входят и попадут в следующее
|
||
переобучение. Поэтому накопление архива можно продолжать; временный snapshot после
|
||
успеха или ошибки удаляется, если не указан `--keep-snapshot`.
|
||
|
||
Первичная настройка локального окружения:
|
||
|
||
```powershell
|
||
python -m venv .venv
|
||
.\.venv\Scripts\python.exe -m pip install numpy
|
||
.\.venv\Scripts\python.exe -m pip install torch==2.13.0 `
|
||
--index-url https://download.pytorch.org/whl/cu130
|
||
```
|
||
|
||
Обучение на текущих четырёх независимых seed-run:
|
||
|
||
```powershell
|
||
.\scripts\TrainTransformer.bat
|
||
```
|
||
|
||
Скрипт проверяет `torch.cuda.is_available()` и пропускает Python-окружения с
|
||
CPU-only PyTorch. Если CUDA-Python не находится автоматически, его можно указать
|
||
без изменения файлов проекта:
|
||
|
||
```powershell
|
||
$env:SZILASSI_PYTHON = "C:\path\to\python.exe"
|
||
.\scripts\TrainTransformer.bat
|
||
```
|
||
|
||
Train/validation/test делятся целыми run UUID, а не случайными соседними
|
||
записями. Модель публикуется только после проверки AP, Brier и top-decile uplift
|
||
на отдельных запусках. Затем deployment-ensemble заново обучается на всех четырёх
|
||
run и атомарно публикуется как `results/search/neural/transformer/current.sztf`.
|
||
Предыдущие `model_<digest>.sztf` не переписываются, а идентификатор загруженного
|
||
поколения сохраняется в `run.tsv` и algorithm fingerprint обучающих записей.
|
||
|
||
При будущем переобучении на всём накопившемся архиве, включая новые run:
|
||
|
||
```powershell
|
||
.\scripts\TrainTransformer.bat --deployment-all-runs
|
||
```
|
||
|
||
После публикации достаточно снова нажать `Запустить поиск`. Сбор `.sztd`, online-MLP,
|
||
MAP-Elites/CEM, CUDA-поиск и CPU/DD-проверка продолжают работать независимо от
|
||
наличия transformer-модели.
|
||
|
||
## Работа на нескольких компьютерах
|
||
|
||
Для параллельного исследования задавайте непересекающиеся диапазоны топологий.
|
||
Каждый запуск создаёт отдельный UUID, поэтому `.szcp`, `.szar`, манифесты и метрики
|
||
объединяются обычным Git merge без отдельного merge-скрипта.
|
||
|
||
Через Git переносятся только геометрическое состояние и небольшая телеметрия.
|
||
Локальный ML-датасет и neural-модели между компьютерами автоматически не
|
||
объединяются. Не добавляйте весь `results/search` принудительно; проверяйте
|
||
`git status` перед коммитом.
|
||
|
||
## Если локальный ML-кэш уже отслеживается Git
|
||
|
||
Следующая команда удаляет только записи из индекса и сохраняет сами файлы на диске:
|
||
|
||
```powershell
|
||
git rm -r --cached --ignore-unmatch -- `
|
||
":(glob)results/search/**/training/**" `
|
||
":(glob)results/search/**/neural/**" `
|
||
":(glob)results/search/**/*.sztd" `
|
||
":(glob)results/search/**/*.sztd.*" `
|
||
":(glob)results/search/**/*.szonn" `
|
||
":(glob)results/search/**/*.szonn.*" `
|
||
":(glob)results/search/**/*.sztf" `
|
||
":(glob)results/search/**/*.sztf.*" `
|
||
":(glob)results/search/**/TRAINING_DATA_LIMIT_REACHED_REWRITE_REQUIRED.tsv"
|
||
```
|
||
|
||
После этого проверьте результат:
|
||
|
||
```powershell
|
||
git status --short
|
||
git ls-files -ci --exclude-standard -- results/search
|
||
```
|
||
|
||
Затем изменения `.gitignore` и удаление из индекса можно закоммитить и отправить
|
||
обычным способом. `git rm --cached` не очищает старые commits. Если большие файлы
|
||
уже были опубликованы и должны исчезнуть из истории сервера, требуется отдельное
|
||
согласованное переписывание истории (`git filter-repo` и force-push); после него
|
||
остальные клоны необходимо пересоздать или синхронизировать вручную.
|
||
|
||
## Тесты
|
||
|
||
`TrainingArchiveSelfTest` проверяет byte-exact round-trip schema v3, CRC, corruption
|
||
detection, частичные WAL, recovery после сбоя, immutable publication и точную границу
|
||
200 GB.
|
||
|
||
`TransformerRankerSelfTest` проверяет byte-exact размер модели, единую нормализацию
|
||
features, batch inference, CRC, отклонение повреждённой модели и сохранение
|
||
последней валидной модели при неудачной загрузке.
|
||
|
||
Запуск через CTest:
|
||
|
||
```powershell
|
||
ctest --test-dir build/vs2026 -C Release --output-on-failure
|
||
```
|
||
|
||
Для проверки отдельного OBJ используется `verify_cpp.exe`.
|
||
|
||
## Лицензия
|
||
|
||
Условия использования находятся в [LICENSE](LICENSE).
|