Реализация многошагового пайплайна для задачи оптимизации маршрутов курьеров (VRP-подобная постановка), выполненная в рамках хакатона. В задаче предполагается порядка 20k заказов и 200 курьеров. В качестве целевой функции выступает суммарное время затраченное всеми курьерами на доставку + 3000 * число неназначенных заказов.
В папке должны лежать файлы:
ml_ozon_logistic_dataDurations.json- база данных расстояний между точкамиml_ozon_logistic_dataSetCouriers.json- данные о курьерах и их сервисных временахml_ozon_logistic_dataSetOrders.json- данные о заказах и их локациях
Скачать их можно по ссылке:
python baseline.py --orders ml_ozon_logistic_dataSetOrders.json --couriers ml_ozon_logistic_dataSetCouriers.json --durations_json ml_ozon_logistic_dataDurations.json --durations_db durations.sqlite --output solution.json-
Загрузка данных
- Загружает заказы и курьеров из JSON файлов
- Использует только первые 280 курьеров из доступных
-
Построение SQLite базы расстояний
- Конвертирует JSON с расстояниями в SQLite для быстрого доступа
- Создает индексы для оптимизации запросов
- Обрабатывает файл потоково для экономии памяти
-
Алгоритм маршрутизации
- Группировка по микро-полигонам: Заказы группируются по MpId (микро-полигон)
- Внутренняя оптимизация: Внутри каждого полигона используется алгоритм ближайшего соседа (Nearest Neighbor)
- Назначение курьерам: Полигоны назначаются курьерам жадным алгоритмом с учетом ограничений:
- Максимальное время работы: 12 часов (43200 секунд)
- Штраф за неразмещенные заказы: 3000 секунд
-
Оптимизация маршрутов
- Вычисляет время маршрута с учетом:
- Расстояний между точками
- Сервисного времени курьера в каждой точке
- Возврата на склад
- Использует fallback через склад для отсутствующих прямых связей
- Вычисляет время маршрута с учетом:
-
Выходные данные
- Создает файл
solution.jsonс маршрутами для каждого курьера - Формат:
{"routes": [{"courier_id": X, "route": [0, order1, order2, ..., 0]}]}
- Создает файл
python scoring.py --orders ml_ozon_logistic_dataSetOrders.json --couriers ml_ozon_logistic_dataSetCouriers.json --durations_db durations.sqlite --submission solution.json-
Валидация решения
- Проверяет корректность формата submission.json
- Валидирует ID курьеров и заказов
- Проверяет уникальность заказов между маршрутами
- Убеждается, что заказы из одного микро-полигона не разделены между курьерами
-
Вычисление расстояний
- Ищет прямые связи между точками
- При отсутствии прямых связей ищет обратные
- В крайнем случае использует маршрут через склад (ID=0)
-
Расчет финального скора
- Суммирует время всех маршрутов
- Добавляет штраф за неразмещенные закады (3000 сек за заказ)
- Проверяет ограничение 12 часов на маршрут
-
Выходные данные
- Выводит статистику по типам связей (прямые, обратные, через склад)
- Количество неразмещенных заказов
- Финальный скор в секундах
- Жадная стратегия: Полигоны назначаются курьерам по принципу "первый подходящий"
- Fallback маршрутизация: При отсутствии прямых связей используется маршрут через склад
- Оптимизация памяти: Потоковая обработка больших файлов, LRU кэширование
- Балансировка нагрузки: Учет текущего времени работы курьера при назначении новых полигонов
Проект состоит из нескольких стадий (stage0 ... stage5), каждая из которых постепенно улучшает решение:
- Stage0–Stage3 — предобработка данных, построение карт и полигонов заказов.
- Stage4 — базовое построение маршрутов жадными и DP-подобными методами.
- Stage5 — финальная улучшалка на основе Adaptive Large Neighborhood Search (ALNS) с приёмкой через Late Acceptance Hill Climbing (LAHC).
Ключевые особенности:
- Кэширование вычислений (intra-time, portal-time, service-time).
- Собственная реализация операторов удаления/вставки: Random, Segment, Worst-Route, Shaw, Block, Regret-K Insertion.
- Ограничение длительности маршрута ≤ 12h.
- Поддержка восстановления заказов через «Critical Route Pool».
- Лёгкая отладка через
DEBUG-флаг. - Сохранение результатов в
solution.jsonв формате, совместимом сscoring.py.
- Python 3.9+
- Numba можно подключить для ускорения «тяжёлых» циклов
- Базовый greedy (Stage4): ~3.96 млн score
- Stage5 (ALNS+LAHC, 1 минута): ~3.83 млн
- Stage5 (ALNS+LAHC, 1 час): ~3.18 млн
python baseline.py \
--orders data/ml_ozon_logistic_dataSetOrders.json \
--couriers data/ml_ozon_logistic_dataSetCouriers.json \
--durations_db data/durations.sqlite