Техническое задание на разработку Системы планирования и диспетчеризации поставок жидкого цемента «CementFlow»
1. ВВЕДЕНИЕ
1.1. Наименование проекта
Система автоматизированного планирования и диспетчеризации поставок жидкого цемента «CementFlow» с поддержкой каскадного перерасчёта.
1.2. Краткое описание
Разрабатываемая система предназначена для оптимального распределения грузовиков-миксеров для выполнения заказов на доставку жидкого цемента в течение 12-часовой рабочей смены. Система обеспечивает автоматическое планирование поставок, мониторинг исполнения в реальном времени и интеллектуальный перерасчёт расписания при возникновении сбоев (поломки техники, ДТП, задержки).
1.3. Область применения
Система предназначена для использования:
-
Бетонными заводами и производственными комплексами
-
Логистическими компаниями, специализирующимися на перевозке строительных материалов
-
Диспетчерскими службами строительных компаний
1.4. Цели разработки
-
Повышение эффективности использования парка машин на 25-30%
-
Снижение простоев грузовиков-миксеров на 35-40%
-
Минимизация потерь бетона из-за превышения времени жизни
-
Обеспечение 95% своевременности доставок
-
Сокращение времени реакции на сбои с 30-60 минут до 5-10 минут
2. ОБЩИЕ ТРЕБОВАНИЯ
2.1. Функциональное назначение
Система должна обеспечивать:
2.1.1. Основные функции:
-
Планирование смены - формирование оптимального расписания поставок на 12-часовую смену
-
Распределение грузовиков - автоматический подбор машин для выполнения поставок
-
Мониторинг исполнения - отслеживание статуса поставок в реальном времени
-
Каскадный перерасчёт - автоматическое перепланирование при возникновении сбоев
-
Визуализация - отображение расписания в виде интерактивной диаграммы Ганта
2.1.2. Вспомогательные функции:
-
Управление справочниками (машины, водители, клиенты, объекты)
-
Формирование отчётности и аналитика
-
Интеграция с внешними системами (GPS, ERP, CRM)
-
Уведомления и оповещения
2.2. Пользователи системы
| Роль пользователя | Основные функции | Доступ |
|---|---|---|
| Диспетчер | Полный доступ ко всем функциям планирования и мониторинга | Веб-интерфейс |
| Руководитель смены | Просмотр, утверждение расписания, анализ эффективности | Веб-интерфейс |
| Водитель | Получение заданий, отметка о выполнении этапов, сообщение о проблемах | Мобильное приложение |
| Администратор | Управление пользователями, настройка системы, техническая поддержка | Веб-интерфейс |
| Клиент (опционально) | Просмотр статуса своего заказа, получение уведомлений | Веб-портал/SMS |
3. ТЕХНОЛОГИЧЕСКИЕ ТРЕБОВАНИЯ
3.1. Архитектурные требования
-
Микросервисная архитектура с разделением на независимые модули
-
Событийно-ориентированная архитектура для обработки событий в реальном времени
-
REST API для интеграции с внешними системами
-
Веб-сокеты для обновления интерфейса в реальном времени
-
Поддержка горизонтального масштабирования
3.2. Технологический стек
| Компонент | Технологии |
|---|---|
| Бэкенд | .NET 8, C# 12, ASP.NET Core |
| Фронтенд | React 18 + TypeScript, Redux Toolkit/ Svelte SvelteKit + TypeScript |
| База данных | PostgreSQL 16 (основная), Redis 7 (кэш) |
| Очереди сообщений | RabbitMQ или Azure Service Bus |
| Контейнеризация | Docker, Docker Compose |
| Оркестрация | Kubernetes (опционально) |
| Мониторинг | Grafana, Prometheus |
| CI/CD | GitLab CI/CD или GitHub Actions |
3.3. Требования к производительности
| Параметр | Требование |
|---|---|
| Время отклика API | ≤ 200 мс для 95% запросов |
| Время планирования смены | ≤ 30 секунд для 100 заказов |
| Время каскадного перерасчёта | ≤ 10 секунд |
| Поддержка одновременных пользователей | ≥ 50 диспетчеров |
| Доступность системы | 99.5% (SLA) |
| Время восстановления | ≤ 15 минут |
4. ДЕТАЛЬНОЕ ОПИСАНИЕ ФУНКЦИОНАЛА
4.1. Модуль управления заказами
4.1.1. Создание и редактирование заказов
-
Форма создания заказа с полями:
-
Клиент (выбор из справочника)
-
Объект доставки (адрес, контактное лицо, телефон)
-
Объём бетона (м³)
-
Марка бетона, подвижность
-
Желаемое время доставки (окно или точное время)
-
Приоритет (нормальный, высокий, критический)
-
Особые требования (непрерывная заливка, бетононасос и т.д.)
-
4.1.2. Автоматическое разбиение заказов на поставки
-
Алгоритм разбиения учитывает:
-
Вместимость доступных машин
-
Требование непрерывной заливки
-
Оптимальное заполнение миксера (минимизация остатков)
-
4.2. Модуль планирования
4.2.1. Алгоритм первоначального распределения
Детальное описание приведено в Приложении №1.
Входные данные:
-
Список всех заказов смены
-
Парк доступных машин с характеристиками
-
Расписание работы завода
Этапы алгоритма:
-
Группировка заказов по приоритету и временным окнам
-
Разбиение на поставки с учётом непрерывности заливки
-
Распределение по машинам по критериям:
-
Минимизация порожнего пробега
-
Максимальное использование вместимости
-
Учёт приоритета клиента
-
-
Расчёт временных окон с учётом:
-
Времени жизни бетона (90-120 минут)
-
Времени на погрузку, путь, разгрузку, возврат
-
Буфера на форс-мажор (10-15%)
-
-
Формирование диаграммы Ганта
4.2.2. Критерии выбора машины
Формула оценки приоритета машины:
Score = (W1 × DistanceScore) + (W2 × CapacityUtilization) + (W3 × TimeWindowFit) + PriorityBonus
где:
-
DistanceScore - оценка расстояния до завода (ближе = лучше)
-
CapacityUtilization - коэффициент заполнения миксера
-
TimeWindowFit - соответствие временному окну клиента
-
PriorityBonus - бонус за приоритет клиента
-
W1, W2, W3 - весовые коэффициенты (настраиваемые)
4.3. Модуль каскадного перерасчёта
4.3.1. Типы обрабатываемых событий
-
Поломка машины - машина выходит из строя
-
ДТП - авария с участием машины
-
Задержка на разгрузке - превышение планового времени разгрузки
-
Пробки - увеличение времени в пути
-
Изменение заказа - корректировка клиентом
-
Новая доступная машина - ввод машины в эксплуатацию
4.3.2. Алгоритм перерасчёта
Детально приведен в Приложении №2.
Шаг 1: Анализ воздействия
-
Определение всех затронутых поставок
-
Оценка степени влияния на график
Шаг 2: Локализация проблемы
-
Ограничение области перерасчёта ближайшими поставками
-
Сохранение неизменными поставок, которые не затрагиваются
Шаг 3: Перераспределение
-
Попытка назначить затронутые поставки другим машинам
-
Использование резервного времени и буферов
-
Приоритизация критических поставок
Шаг 4: Каскадный сдвиг
-
Последовательный сдвиг зависимых поставок
-
Контроль накопления задержек
-
Проверка соблюдения времени жизни бетона
Шаг 5: Эскалация
-
Если автоматическое решение невозможно → уведомление диспетчера
-
Предложение вариантов для ручного выбора
4.4. Модуль визуализации
4.4.1. Диаграмма Ганта
Требования к отображению:
-
По горизонтали - временная шкала смены (12 часов)
-
По вертикали - список машин
-
Для каждой машины - цветные блоки поставок
-
Цветовая индикация статуса:
-
Зелёный - выполняется по плану
-
Жёлтый - есть риски/небольшие отклонения
-
Красный - критические отклонения/просрочки
-
Серый - завершено
-
Интерактивные возможности:
-
Drag-and-drop для ручного перемещения поставок
-
Масштабирование (часы/минуты)
-
Фильтрация по клиентам, объектам, статусам
-
Подсказки при наведении (детали поставки)
4.4.2. Карта перемещений
-
Отображение местоположения машин в реальном времени
-
Маршруты движения
-
Точки погрузки и разгрузки
-
Пробки и дорожная обстановка (интеграция с картами)
4.5. Модуль интеграций
4.5.1. Внешние системы
| Система | Тип интеграции | Назначение |
|---|---|---|
| GPS/телематика | REST API/WebSocket | Отслеживание местоположения, статуса машин |
| Картографические сервисы | API (Яндекс.Карты/Google Maps) | Расчёт маршрутов и времени в пути |
| ERP система | REST API | Импорт заказов, экспорт выполненных работ |
| CRM система | REST API | Получение информации о клиентах |
| СМС-сервис | REST API | Уведомления водителей и клиентов |
| Погодный сервис | REST API | Учёт погодных условий в планировании |
5. ТРЕБОВАНИЯ К ДАННЫМ
5.1. Структура базы данных
5.1.1. Основные таблицы:
-
Orders - заказы клиентов
-
Deliveries - поставки (части заказов)
-
Trucks - грузовики-миксеры
-
Drivers - водители
-
Clients - клиенты
-
ConstructionSites - объекты строительства
-
ScheduleSlots - слоты в расписании
-
Events - события системы
-
RoutePoints - точки маршрутов
5.1.2. Требования к хранению:
-
История изменений расписания - 90 дней
-
Архив выполненных поставок - 3 года
-
Логи событий - 30 дней
-
Оперативные данные - в кэше Redis
5.2. Форматы данных
5.2.1. JSON API форматы:
{
"order": {
"id": "ORD-2024-001",
"client": {
"id": "CL-001",
"name": "ООО СтройГрад",
"priority": "high"
},
"site": {
"address": "ул. Строителей, 15",
"coordinates": {"lat": 55.7558, "lng": 37.6176}
},
"details": {
"volume": 15.0,
"concreteGrade": "M300",
"slump": 15,
"requiredWindow": {
"start": "2024-01-15T09:00:00",
"end": "2024-01-15T12:00:00"
},
"continuousPouring": true,
"maxInterval": "PT30M"
}
}
}
6. ТРЕБОВАНИЯ К ИНТЕРФЕЙСУ
6.1. Веб-интерфейс диспетчера
6.1.1. Основной экран:
-
Левая панель - список заказов с фильтрами
-
Центральная область - диаграмма Ганта
-
Правая панель - детали выбранного элемента, уведомления
-
Верхняя панель - управление сменой, поиск, настройки
6.1.2. Экран планирования:
-
Календарь смен
-
Форма массового планирования
-
Инструменты оптимизации
-
Предпросмотр нагрузки на завод
6.1.3. Экран мониторинга:
-
Карта с движением машин
-
Панель статусов в реальном времени
-
Графики загрузки и эффективности
-
Оповещения о проблемах
6.2. Мобильное приложение водителя
6.2.1. Основные экраны:
-
Задания на день - список поставок
-
Текущее задание - детали, карта маршрута
-
Отметки о выполнении - кнопки для отметки этапов
-
Сообщения - связь с диспетчером
-
Проблемы - форма сообщения о сбоях
6.2.2. Функционал:
-
Авторизация по QR-коду или логину
-
Офлайн-работа с последующей синхронизацией
-
GPS-трекинг
-
Фотоотчётность (по требованию)
7. ТРЕБОВАНИЯ К НАДЁЖНОСТИ И БЕЗОПАСНОСТИ
7.1. Надёжность
-
Резервирование всех критических компонентов
-
Автоматическое восстановление после сбоев
-
Ежедневное резервное копирование с хранением 7 дней
-
Мониторинг доступности и производительности
7.2. Безопасность
-
Аутентификация по логину/паролю + 2FA для администраторов
-
Ролевая модель доступа (RBAC)
-
HTTPS для всех соединений
-
Защита от DDoS атак
-
Аудит действий пользователей
-
Шифрование конфиденциальных данных
8. ТРЕБОВАНИЯ К РАЗВЁРТЫВАНИЮ И ЭКСПЛУАТАЦИИ
8.1. Развёртывание
-
Контейнерная поставка всех компонентов
-
Автоматическое развёртывание через CI/CD
-
Документация по установке и настройке
-
Миграционные скрипты для обновлений
8.2. Эксплуатация
-
Техническая поддержка 24/7 для критических инцидентов
-
Обновления - 1 раз в месяц (патчи), 1 раз в квартал (версии)
-
Мониторинг - дашборды, алертинг, логирование
-
Резервное копирование - автоматическое, ежедневно
9. ЭТАПЫ РАЗРАБОТКИ
Этап 1: Прототип и архитектура (1-2 месяца)
-
Разработка архитектуры
-
Создание прототипа алгоритмов планирования
-
Проектирование БД и API
-
Базовый веб-интерфейс
Этап 2: Ядро системы (3-4 месяца)
-
Реализация основных модулей
-
Алгоритмы распределения и перерасчёта
-
Веб-интерфейс диспетчера
-
Интеграция с GPS/картами
Этап 3: Доработка и тестирование (2-3 месяца)
-
Мобильное приложение для водителей
-
Расширенная аналитика
-
Стресс-тестирование
-
Пилотная эксплуатация
Этап 4: Внедрение и поддержка (постоянно)
-
Внедрение у заказчика
-
Обучение пользователей
-
Техническая поддержка
-
Доработки по обратной связи
10. КРИТЕРИИ ПРИЁМКИ
10.1. Функциональные критерии
-
Система корректно планирует смену для 100+ заказов
-
Автоматический перерасчёт выполняется за ≤10 секунд
-
Диаграмма Ганта отображает все поставки без пересечений
-
Интеграция с GPS работает в реальном времени
-
Мобильное приложение работает офлайн
10.2. Нефункциональные критерии
-
Время отклика интерфейса ≤200 мс
-
Система выдерживает нагрузку 50+ одновременных пользователей
-
Доступность 99.5% в рабочее время
-
Данные сохраняются при перезапуске системы
10.3. Приёмочные испытания
-
Тестирование на тестовых данных - 7 дней
-
Пилотная эксплуатация - 14 дней
-
Стресс-тестирование - имитация сбоев и высокой нагрузки
-
Проверка безопасности - пентест
11. ГАРАНТИИ И ПОДДЕРЖКА
11.1. Гарантийный период
-
12 месяцев с момента подписания акта приёмки
-
Исправление критических багов - в течение 24 часов
-
Исправление некритических багов - в течение 5 рабочих дней
11.2. Техническая поддержка
-
Поддержка 24/7 для критических инцидентов
-
Консультации по использованию системы
-
Обновления и доработки по согласованию
-
Резервное копирование и восстановление данных
ПРИЛОЖЕНИЯ
Приложение A: Словарь терминов
-
Слот - временной интервал, выделенный машине для выполнения поставки
-
Каскадный перерасчёт - последовательное перепланирование зависимых поставок
-
Время жизни бетона - период от замеса до начала схватывания (90-120 минут)
-
Непрерывная заливка - требование минимального интервала между поставками на объект
Приложение B: Схемы интеграций
(Диаграммы последовательности и архитектурные схемы)
Приложение C: Макеты интерфейсов
(Визуальные макеты всех экранов системы)
ИСПОЛНИТЕЛЬ: [Наименование организации-исполнителя]
ЗАКАЗЧИК: [Наименование организации-заказчика]
СРОК РАЗРАБОТКИ: 8-12 месяцев
СТОИМОСТЬ РАЗРАБОТКИ: [Сумма] руб.
СРОК ДЕЙСТВИЯ ТЗ: до [Дата]
Документ утверждён:
[Подпись Заказчика] [Подпись Исполнителя]
[Дата] [Дата]
Приложение №1
ДЕТАЛЬНОЕ ОПИСАНИЕ АЛГОРИТМА ПЕРВОНАЧАЛЬНОГО РАСПРЕДЕЛЕНИЯ
1. ОБЩИЙ ПРИНЦИП РАБОТЫ АЛГОРИТМА
Алгоритм первоначального распределения — это многоуровневая жадная эвристика с обратной связью, которая преобразует список заказов клиентов в оптимизированное расписание поставок для всего парка машин на 12-часовую смену. Алгоритм работает по принципу "наиболее ограниченные задачи решаются первыми".
Ключевая идея: Сначала назначаются самые сложные и критичные поставки, затем менее сложные, что позволяет избежать ситуаций, когда критичные задачи невозможно выполнить из-за того, что все ресурсы уже заняты менее важными задачами.
2. ПОШАГОВЫЙ АЛГОРИТМ С РАСЧЁТАМИ
Этап 0: Подготовка данных (Pre-processing)
Входные данные:
-
Список заказов на смену (N заказов)
-
Парк доступных машин (M единиц)
-
Параметры смены (начало T_start, конец T_end, координаты завода)
-
Технологические константы (время погрузки, средняя скорость и т.д.)
Шаг 0.1: Валидация и нормализация данных
Для каждого заказа: 1. Проверить корректность данных 2. Рассчитать минимальное и максимальное время доставки 3. Привести желаемое окно клиента к стандартному формату 4. Вычислить коэффициент срочности = (дедлайн - текущее время) / общее время смены
Шаг 0.2: Сортировка заказов по сложности выполнения
Сложность_заказа = (Приоритет_клиента × 0.4) +
(Коэффициент_срочности × 0.3) +
(Объём_заказа / Стандартный_объём × 0.2) +
(Сложность_логистики × 0.1)
Сортируем заказы по убыванию Сложности_заказа
Этап 1: Разбиение заказов на атомарные поставки
Шаг 1.1: Определение оптимального размера поставки
Для каждого заказа:
Если Объём_заказа ≤ Максимальная_вместимость_машины:
Количество_поставок = 1
Объём_поставки = Объём_заказа
Иначе:
Найти все доступные вместимости машин: C1, C2, ..., Ck
Найти оптимальное разбиение, минимизирующее:
Целевая_функция = α × Количество_поставок +
β × (Сумма_остатков_в_машинах) +
γ × (Максимальный_интервал_между_поставками)
Пример расчёта для заказа 15 м³:
Доступные вместимости машин: 5 м³, 7 м³, 10 м³ Варианты разбиения: 1) 3 × 5 м³ = 15 м³ (остаток 0) ✓ 2) 2 × 7 м³ = 14 м³ (остаток 1 м³ - требует доп. машину 5 м³) 3) 1 × 10 м³ + 1 × 5 м³ = 15 м³ (остаток 0) ✓ Выбираем вариант 3, так как минимизирует количество поставок
Шаг 1.2: Создание сущностей поставок
Для каждой поставки:
1. Присвоить уникальный ID
2. Унаследовать данные от родительского заказа
3. Рассчитать параметры:
- Минимальное время выполнения = Погрузка + Путь_туда + Разгрузка + Возврат
- Время жизни бетона = 90 минут (для стандартного бетона)
- Окончательный дедлайн = MIN(Дедлайн_клиента, Время_начала + Время_жизни)
Этап 2: Группировка поставок для параллельной обработки
Шаг 2.1: Создание групп по ограничениям
Группа А: Поставки с жёсткими временными окнами (нельзя сдвигать) Группа Б: Поставки, требующие непрерывной заливки Группа В: Поставки для VIP-клиентов Группа Г: Стандартные поставки Группа Д: Поставки с гибкими временами Приоритет обработки: А → Б → В → Г → Д
Шаг 2.2: Внутригрупповая сортировка
Для каждой группы сортировка по: 1. Времени начала окна (от более раннего к более позднему) 2. Длительности окна (от более узкого к более широкому) 3. Объёму (от большего к меньшему)
Этап 3: Распределение поставок по машинам
Цикл обработки поставок:
Для каждой поставки в порядке приоритета групп:
Шаг 3.1: Формирование пула кандидатов
Для каждой машины проверяем:
1. Вместимость ≥ Объём_поставки
2. Техническая исправность = true
3. Машина доступна в течение смены
4. Машина может прибыть на завод к нужному времени
Шаг 3.2: Предварительная оценка кандидатов
Для каждой машины-кандидата рассчитываем:
Время_начала_минимальное = MAX(Текущее_свободное_время, Время_прибытия_на_завод)
Время_окончания = Время_начала + Длительность_поставки
Отсеиваем кандидатов, у которых:
- Время_окончания > Окончательный_дедлайн
- Время_окончания > Конец_смены
- Время_разгрузки > Время_начала + Время_жизни_бетона
Шаг 3.3: Детальный расчёт для каждого кандидата
Для каждого оставшегося кандидата:
1. Рассчитать точное время всех этапов:
- Выезд на завод: Время_начала - Путь_до_завода
- Погрузка: 15-20 минут (зависит от объёма)
- Путь к клиенту: Расстояние / Средняя_скорость × Коэффициент_пробок
- Разгрузка: 2-3 минуты на м³
- Возврат: Расстояние_обратно / Средняя_скорость
2. Проверить пересечения с существующими слотами машины
3. Рассчитать буферы:
- Операционный буфер: 10% от времени в пути
- Рисковый буфер: 5-15 минут (зависит от сложности объекта)
Шаг 3.4: Оценка и выбор лучшего кандидата
Оценочная_функция(Машина, Поставка) =
W1 × Оценка_времени +
W2 × Оценка_расстояния +
W3 × Оценка_использования +
W4 × Оценка_качества
Где:
Оценка_времени = 1 / (Время_начала - Идеальное_время_начала)²
Оценка_расстояния = 1 / (Порожний_пробег + 1)
Оценка_использования = Объём_поставки / Вместимость_машины
Оценка_качества = Коэффициент_приоритета_клиента
W1, W2, W3, W4 — настраиваемые веса (по умолчанию: 0.4, 0.3, 0.2, 0.1)
Шаг 3.5: Назначение и фиксация
Если найден подходящий кандидат:
- Закрепляем поставку за машиной
- Создаём слот с рассчитанными временами
- Обновляем доступное время машины
- Добавляем в расписание
Иначе:
- Перемещаем поставку в очередь проблемных
- Записываем причину неудачи
Этап 4: Обработка поставок, требующих непрерывной заливки
Особый алгоритм для заказов с непрерывной заливкой:
Для каждого заказа с требованием непрерывности:
1. Собрать все поставки этого заказа в группу
2. Определить требуемый интервал между поставками (например, ≤30 минут)
3. Найти машины, которые могут выполнить несколько поставок подряд:
- Проверить возможность выполнения N поставок одной машиной
- Рассчитать суммарное время и проверить попадание в окно клиента
4. Если одной машиной невозможно:
- Найти несколько машин с максимально близкими временами разгрузки
- Синхронизировать их расписание для минимизации интервалов
5. Провести корректировку:
- Сдвинуть поставки для соблюдения интервала
- Убедиться, что сдвиг не нарушает другие ограничения
Этап 5: Пост-обработка и оптимизация
Шаг 5.1: Балансировка нагрузки
Для каждой машины рассчитываем: Коэффициент_загрузки = Суммарное_время_работы / Длительность_смены Средний_коэффициент = SUM(Коэффициент_загрузки) / Количество_машин Для машин с Коэффициент_загрузки > Средний_коэффициент + 0.2: Попробовать перенести часть поставок на менее загруженные машины
Шаг 5.2: Минимизация порожних пробегов
Для каждой последовательности поставок у машины: Рассчитать маршрут: База → Завод → Объект1 → Завод → Объект2 → ... Оценить порожний пробег между объектами Попробовать переставить поставки в последовательности для: - Уменьшения расстояния между объектами - Группировки поставок по географическим зонам
Шаг 5.3: Добавление защитных буферов
Для каждого слота в расписании:
Если поставка критичная или объект сложный:
Добавить_буфер = 15-20 минут
Иначе если время в пути > 60 минут:
Добавить_буфер = 10% от времени в пути
Иначе:
Добавить_буфер = 5 минут
Распределить буфер:
- 50% добавить перед разгрузкой (на случай задержек в пути)
- 50% добавить после разгрузки (на случай задержек на объекте)
Этап 6: Обработка проблемных поставок
Шаг 6.1: Анализ причин неудачи
Типичные причины: 1. Нехватка машин нужной вместимости 2. Отсутствие временных окон 3. Противоречивые ограничения 4. Невозможность соблюсти время жизни бетона
Шаг 6.2: Попытка перераспределения
Для каждой проблемной поставки:
1. Ослабить ограничения (если возможно):
- Расширить временное окно
- Разрешить использование машин большей вместимости
- Увеличить максимальный интервал для непрерывной заливки
2. Попробовать занять резервное время других машин
3. Предложить разбить поставку на меньшие части
Шаг 6.3: Эскалация к диспетчеру
Если автоматическое распределение невозможно:
1. Сформировать отчёт с причинами
2. Предложить варианты решения:
- Добавить дополнительную машину
- Перенести заказ на другую смену
- Увеличить временное окно
- Изменить параметры заказа
3. Передать задачу диспетчеру для ручного решения
3. МАТЕМАТИЧЕСКАЯ ФОРМАЛИЗАЦИЯ
Основная целевая функция:
Минимизировать: Z = α×Z₁ + β×Z₂ + γ×Z₃ + δ×Z₄ Где: Z₁ = Σ(Время_доставки - Идеальное_время)² # Минимизация отклонений Z₂ = Σ(Порожний_пробег) # Минимизация пробегов Z₃ = Σ(1 - Коэффициент_заполнения)² # Максимизация использования Z₄ = Σ(Штрафы_за_нарушение_ограничений) # Минимизация нарушений
Ограничения:
1. ∀i: Время_начала_слота_i ≥ Время_окончания_слота_{i-1} + Время_перехода
2. ∀i: Время_разгрузки_i ≤ Время_погрузки_i + Время_жизни_бетона
3. ∀j: Σ(Объём_поставок_заказа_j) = Объём_заказа_j
4. ∀k: Σ(Время_работы_машины_k) ≤ Длительность_смены
5. ∀l,m: |Время_разгрузки_l - Время_разгрузки_m| ≤ Максимальный_интервал,
если l и m принадлежат одному заказу с непрерывной заливкой
4. ПРИМЕР РАСЧЁТА ДЛЯ КОНКРЕТНОГО СЦЕНАРИЯ
Исходные данные:
-
Смена: 07:00 - 19:00 (12 часов)
-
Парк: 5 машин (вместимости: 5, 5, 7, 7, 10 м³)
-
Завод: Координаты (55.7558, 37.6176)
-
Средняя скорость: 40 км/ч в городе, 60 км/ч за городом
Заказ 1:
-
Клиент: СтройГрад (приоритет: высокий)
-
Объём: 15 м³
-
Объект: 10 км от завода
-
Окно: 09:00 - 12:00
-
Требуется непрерывная заливка, макс. интервал 30 мин
Расчёт алгоритма:
Шаг 1: Разбиение заказа
Оптимальное разбиение: 10 м³ + 5 м³ Обоснование: Минимизация количества поставок (2 вместо 3)
Шаг 2: Расчёт временных параметров для поставки 10 м³
Время погрузки: 10 м³ × 3 мин/м³ = 30 минут Время в пути: 10 км / 40 км/ч = 15 минут Время разгрузки: 10 м³ × 2.5 мин/м³ = 25 минут Возврат: 10 км / 40 км/ч = 15 минут Итого: 30 + 15 + 25 + 15 = 85 минут Буфер: 10% = 9 минут Общее время слота: 94 минуты ≈ 1 час 34 минуты
Шаг 3: Поиск подходящей машины
Кандидаты по вместимости: машины 7 м³ и 10 м³ Машина 1 (7 м³): не подходит - объём 10 > 7 Машина 2 (7 м³): не подходит Машина 3 (10 м³): свободна с 07:00 Расчёт для машины 3: Выезд с базы: 07:00 Прибытие на завод: 07:15 Погрузка: 07:15 - 07:45 Путь к клиенту: 07:45 - 08:00 Разгрузка: 08:00 - 08:25 Возврат: 08:25 - 08:40 Проверка ограничений: ✓ Попадание в окно клиента (08:00 ∈ [09:00-12:00] - требуется корректировка) ✓ Время жизни бетона: 08:00 - 07:45 = 15 минут < 90 минут ✓ Конец слота 08:40 < конец смены 19:00
Шаг 4: Корректировка времени
Требуется сдвинуть на 1 час позже: Погрузка: 08:15 - 08:45 Разгрузка: 09:00 - 09:25 (попадает в окно) Обновлённый слот: 08:00 - 09:40
Шаг 5: Аналогичный расчёт для поставки 5 м³
Выбираем машину 5 м³, начинаем на 30 минут позже первой поставки для соблюдения непрерывной заливки: Разгрузка: 09:25 - 09:40 (интервал 0 минут ✓)
5. ОСОБЕННОСТИ РЕАЛИЗАЦИИ
5.1. Эвристические правила, используемые в алгоритме:
-
Правило ближайшего соседа:
-
После выполнения поставки на объекте, следующая поставка назначается на ближайший объект
-
-
Правило заполнения до конца:
-
Если осталось мало времени до конца смены, назначаются короткие поставки рядом с базой
-
-
Правило резервирования VIP:
-
Для VIP-клиентов резервируется 10% времени у лучших машин
-
-
Правило избегания пиков:
-
Стараться не назначать разгрузку в часы пик (08:00-10:00, 17:00-19:00)
-
5.2. Обработка конфликтов и тупиковых ситуаций:
Тупиковая ситуация: Нельзя назначить поставку без нарушения ограничений
Стратегии выхода:
-
Откат (Backtracking): Отменить последнее назначение и попробовать другой вариант
-
Ослабление ограничений: Временно разрешить небольшое нарушение
-
Разделение проблемы: Разделить сложную поставку на части
-
Перенос на потом: Отложить решение до обработки других поставок
5.3. Оптимизационные улучшения:
-
Локальный поиск: После построения расписания пытаться улучшить его небольшими изменениями
-
Табу-поиск: Запрещать возврат к недавно рассмотренным решениям
-
Имитация отжига: Иногда разрешать ухудшения для выхода из локальных оптимумов
6. ПРОИЗВОДИТЕЛЬНОСТЬ И МАСШТАБИРУЕМОСТЬ
Временная сложность:
O(N × M × K × L) Где: N - количество поставок M - количество машин K - среднее количество временных окон у машины L - сложность проверки ограничений Для типичного сценария (50 поставок, 10 машин): ≈ 50 × 10 × 5 × 10 = 25,000 операций Время выполнения: ~2-3 секунды
Память:
Требуется хранить: - Матрицу назначений: N × M элементов - Расписание каждой машины: M списков по ~10 элементов - Кэш рассчитанных расстояний: ~N² элементов Общий объём: O(N² + M × N) ≈ 100-500 КБ для типичного сценария
7. ВАЛИДАЦИЯ И ТЕСТИРОВАНИЕ АЛГОРИТМА
Тестовые сценарии:
-
Идеальный случай: Все поставки могут быть назначены без конфликтов
-
Предельная загрузка: Количество поставок на пределе возможностей парка
-
Конфликт ограничений: Противоречивые требования клиентов
-
Каскадный сбой: Отказ ключевой машины в начале смены
Метрики качества расписания:
1. Коэффициент использования машин: Должен быть 70-90% 2. Среднее отклонение от идеального времени: Должно быть < 30 минут 3. Количество нарушений ограничений: Должно быть 0 4. Суммарный порожний пробег: Минимизируется 5. Баланс загрузки: Разница загрузки машин < 20%
8. ИНТЕГРАЦИЯ С ДРУГИМИ СИСТЕМАМИ
Алгоритм получает данные из:
-
CRM-системы — информация о клиентах и их приоритетах
-
ERP-системы — данные о заказах и производственных мощностях
-
GPS-трекера — текущее положение машин
-
Картографических сервисов — актуальные данные о пробках и маршрутах
-
Погодных сервисов — прогноз для корректировки времени в пути
9. НАСТРОЙКА И КАЛИБРОВКА
Алгоритм имеет настраиваемые параметры:
# Веса в оценочной функции
WEIGHTS = {
'time_deviation': 0.4, # Важность соблюдения времени
'distance': 0.3, # Важность минимизации пробега
'capacity_utilization': 0.2, # Важность заполнения машины
'client_priority': 0.1 # Важность приоритета клиента
}
# Буферы и допуски
TOLERANCES = {
'time_window': 15, # Допустимое отклонение от окна (мин)
'continuous_pouring': 5, # Допуск по интервалу непрерывности (мин)
'concrete_lifetime': 10 # Запас по времени жизни бетона (мин)
}
# Стратегические параметры
STRATEGY = {
'reserve_vip_capacity': 0.1, # Резерв для VIP-клиентов (10%)
'max_backtracking_depth': 3, # Макс. глубина отката
'optimization_iterations': 100 # Количество итераций оптимизации
}
10. ПРАКТИЧЕСКИЕ РЕКОМЕНДАЦИИ ПО РЕАЛИЗАЦИИ
-
Начинать с простого: Сначала реализовать базовый жадный алгоритм без оптимизации
-
Добавлять сложность постепенно: Поэтапно вводить дополнительные ограничения и оптимизации
-
Использовать кэширование: Кэшировать результаты расчёта расстояний и проверок
-
Реализовать инкрементальное обновление: При изменении одной поставки не пересчитывать всё расписание
-
Предусмотреть ручное вмешательство: Возможность диспетчера корректировать автоматические решения
ЗАКЛЮЧЕНИЕ
Алгоритм первоначального распределения представляет собой сбалансированную комбинацию эвристических правил и оптимизационных техник, которая позволяет быстро строить качественное расписание даже для сложных сценариев. Его ключевые преимущества:
-
Гарантированное нахождение решения (если оно существует)
-
Учёт всех технологических ограничений цементной логистики
-
Баланс между оптимальностью и скоростью работы
-
Возможность каскадной обработки — сначала сложные, потом простые задачи
-
Интеграция с системами реального времени для учёта текущей обстановки
Алгоритм является основой всей системы планирования и обеспечивает стабильную работу даже в условиях высокой нагрузки и неопределённости.
Приложение №2
ДЕТАЛЬНОЕ ОПИСАНИЕ АЛГОРИТМА КАСКАДНОГО ПЕРЕРАСЧЕТА
1. ФИЛОСОФИЯ АЛГОРИТМА: УПРАВЛЕНИЕ ХАОСОМ В РЕАЛЬНОМ ВРЕМЕНИ
Алгоритм каскадного перерасчёта — это интеллектуальная система экстренного реагирования, которая превращает хаотичные сбои в управляемые изменения расписания. Он работает по принципу "минимального необходимого вмешательства" — как хирург, который делает точечные разрезы, а не ампутирует конечности.
Ментальная модель: Представьте домино. Одно падающее костяшка (сбой) может уронить всю цепь (расписание). Наш алгоритм — это рука, которая подхватывает упавшие костяшки и расставляет их на новые места, не давая упасть остальным.
2. КЛАССИФИКАЦИЯ СОБЫТИЙ И СТРАТЕГИИ РЕАКЦИИ
2.1. Матрица событий и их каскадных эффектов:
| Событие | Непосредственный эффект | Каскадный эффект | Время реакции | Приоритет обработки |
|---|---|---|---|---|
| Полный отказ машины | Машина выбывает до конца смены | Все будущие слоты освобождаются | 0-2 минуты | Критический (1) |
| Частичная поломка | Машина встанет на 2-4 часа | Слоты в периоде простоя сдвигаются | 2-5 минут | Высокий (2) |
| ДТП без пострадавших | Машина задержана на 1-3 часа | Текущая поставка отменяется, следующие сдвигаются | 5-10 минут | Высокий (2) |
| Задержка на разгрузке | Текущий слот удлиняется на X минут | Последующие слоты этой машины сдвигаются | 1-3 минуты | Средний (3) |
| Пробки на маршруте | Увеличение времени в пути на Y% | Риск превышения времени жизни бетона | 2-5 минут | Средний (3) |
| Отмена заказа клиентом | Освобождается N слотов | Появляется резерв для других поставок | 1-2 минуты | Низкий (4) |
| Новая доступная машина | Увеличивается мощность парка | Возможность оптимизации нагрузки | 3-7 минут | Низкий (4) |
2.2. Жизненный цикл обработки события:
1. ДЕТЕКЦИЯ (0-30 секунд) │ 2. ВАЛИДАЦИЯ (30-60 секунд) │ 3. ОЦЕНКА ВОЗДЕЙСТВИЯ (60-90 секунд) │ 4. РАЗРАБОТКА СТРАТЕГИИ (90-120 секунд) │ 5. ВЫПОЛНЕНИЕ ПЕРЕРАСЧЕТА (120-300 секунд) │ 6. ВАЛИДАЦИЯ РЕЗУЛЬТАТА (300-360 секунд) │ 7. УВЕДОМЛЕНИЕ СТОРОН (360-420 секунд)
3. ДЕТАЛЬНЫЙ АЛГОРИТМ ДЛЯ КРИТИЧЕСКОГО СОБЫТИЯ: ПОЛНАЯ ПОЛОМКА МАШИНЫ
ФАЗА 1: ЭКСПРЕСС-ДИАГНОСТИКА (0-60 секунд)
def emergency_assessment(event):
"""
Молниеносная оценка ситуации
"""
# Шаг 1.1: Определение точки невозврата
breakdown_time = event.occurred_at
truck = event.related_truck
# Какие поставки УЖЕ НЕВОЗМОЖНО выполнить
immediate_impact = []
for slot in truck.schedule:
if slot.start_time <= breakdown_time <= slot.end_time:
# Текущая поставка - экстренная ситуация
current_delivery = slot.delivery
if current_delivery.is_in_transit():
# Бетон уже в пути - критично!
cement_age = breakdown_time - current_delivery.mixing_start_time
remaining_lifetime = current_delivery.concrete_lifetime - cement_age
if remaining_lifetime < TimeSpan.FromMinutes(30):
# Бетон скоро схватится - нужна срочная замена
immediate_impact.append({
'delivery': current_delivery,
'type': 'CRITICAL_CEMENT_AT_RISK',
'remaining_minutes': remaining_lifetime.total_minutes,
'required_action': 'IMMEDIATE_REASSIGNMENT'
})
# Шаг 1.2: Быстрая инвентаризация ресурсов
available_trucks = get_available_trucks(
from_time=breakdown_time,
min_capacity=5, # минимальная вместимость
proximity_to_plant=True
)
# Шаг 1.3: Расчет окна возможностей
opportunity_window = calculate_opportunity_window(
broken_truck=truck,
available_trucks=available_trucks,
time_now=breakdown_time
)
return {
'immediate_crises': immediate_impact,
'available_resources': available_trucks,
'window_of_opportunity': opportunity_window,
'severity_level': calculate_severity(immediate_impact)
}
ФАЗА 2: СТРАТЕГИЧЕСКОЕ ПЛАНИРОВАНИЕ (60-120 секунд)
def develop_rescue_strategy(assessment):
"""
Разработка многоуровневой стратегии спасения
"""
strategy = {
'phase_1': [], # Действия в ближайшие 15 минут
'phase_2': [], # Действия в ближайший час
'phase_3': [], # Действия на оставшуюся смену
'fallback_plans': [] # Резервные варианты
}
# УРОВЕНЬ 1: Спасение бетона, который уже в пути
for crisis in assessment['immediate_crises']:
if crisis['type'] == 'CRITICAL_CEMENT_AT_RISK':
rescue_plan = create_cement_rescue_plan(
delivery=crisis['delivery'],
time_limit=crisis['remaining_minutes'],
available_trucks=assessment['available_resources']
)
if rescue_plan['feasible']:
strategy['phase_1'].append({
'action': 'EMERGENCY_TRANSFER',
'plan': rescue_plan,
'priority': 'CRITICAL'
})
else:
# Невозможно спасти - план минимизации убытков
strategy['phase_1'].append({
'action': 'DAMAGE_CONTROL',
'plan': create_damage_control_plan(crisis['delivery']),
'priority': 'CRITICAL'
})
# УРОВЕНЬ 2: Перераспределение ближайших поставок (15-60 минут)
immediate_slots = get_immediate_slots(
truck=assessment['broken_truck'],
time_horizon=TimeSpan.FromHours(2),
from_time=assessment['breakdown_time']
)
for slot in immediate_slots:
reassignment_plan = create_slot_reassignment_plan(
slot=slot,
available_trucks=assessment['available_resources'],
strategy='NEAREST_FIT'
)
strategy['phase_2'].append({
'action': 'SLOT_REASSIGNMENT',
'slot': slot,
'plan': reassignment_plan,
'priority': 'HIGH' if slot.delivery.client.priority >= 8 else 'MEDIUM'
})
# УРОВЕНЬ 3: Оптимизация оставшейся смены
remaining_slots = get_remaining_slots(
truck=assessment['broken_truck'],
from_time=assessment['breakdown_time'] + TimeSpan.FromHours(2)
)
optimization_strategy = create_optimization_strategy(
slots=remaining_slots,
available_trucks=assessment['available_resources'],
time_constraints=assessment['window_of_opportunity']
)
strategy['phase_3'] = optimization_strategy
# Резервные планы
strategy['fallback_plans'] = create_fallback_plans(strategy)
return strategy
ФАЗА 3: КАСКАДНЫЙ ПЕРЕРАСЧЕТ С УПРАВЛЯЕМЫМ РАСПРОСТРАНЕНИЕМ
def execute_cascade_reschedule(strategy, original_schedule):
"""
Выполнение каскадного перерасчета с контролем распространения
"""
# Шаг 3.1: Создание "песочницы" для экспериментов
sandbox_schedule = original_schedule.clone()
change_log = []
# Шаг 3.2: Последовательное выполнение фаз стратегии
for phase_name in ['phase_1', 'phase_2', 'phase_3']:
phase_actions = strategy[phase_name]
for action in phase_actions:
result = execute_action_in_sandbox(
action=action,
schedule=sandbox_schedule,
change_log=change_log
)
if not result['success']:
# Действие не удалось - активируем механизм компенсации
compensation = create_compensation_plan(
failed_action=action,
failure_reason=result['reason'],
current_state=sandbox_schedule
)
# Пытаемся выполнить компенсацию
compensation_result = execute_compensation(
compensation_plan=compensation,
schedule=sandbox_schedule
)
if not compensation_result['success']:
# Каскадная неудача - эскалация
escalate_to_human(
action=action,
compensation=compensation,
current_state=sandbox_schedule
)
# Шаг 3.3: Проверка целостности нового расписания
integrity_check = validate_schedule_integrity(sandbox_schedule)
if integrity_check['valid']:
# Шаг 3.4: Постепенное применение изменений
final_schedule = apply_changes_gradually(
original=original_schedule,
new=sandbox_schedule,
change_log=change_log
)
return {
'success': True,
'schedule': final_schedule,
'changes_made': len(change_log),
'cascade_depth': calculate_cascade_depth(change_log),
'estimated_impact': calculate_impact_metrics(change_log)
}
else:
# Не удалось построить валидное расписание
return {
'success': False,
'reason': integrity_check['violations'],
'fallback_activated': True
}
4. АЛГОРИТМ ПЕРЕРАСЧЕТА ПРИ ЗАДЕРЖКЕ НА РАЗГРУЗКЕ
Специфика: Задержка вызывает цепную реакцию, но не требует смены машины.
def handle_unloading_delay(event):
"""
Обработка задержки на разгрузке с минимизацией каскадного эффекта
"""
# Шаг 1: Точное измерение задержки
delay = event.delay_minutes
affected_slot = event.related_slot
truck = affected_slot.truck
# Шаг 2: Анализ "эластичности" временных окон
elasticity_analysis = analyze_time_elasticity(
slot=affected_slot,
requested_delay=delay
)
# Шаг 3: Многоуровневая стратегия поглощения задержки
# Уровень 1: Поглощение за счет внутренних резервов
if elasticity_analysis['can_absorb_without_shift']:
# Задержку можно поглотить за счет буферов
adjusted_schedule = absorb_delay_internally(
schedule=current_schedule,
slot=affected_slot,
delay=delay
)
# Уровень 2: Минимальный сдвиг с компенсацией
elif elasticity_analysis['can_shift_with_minimal_impact']:
# Находим оптимальную точку сдвига
shift_point = find_optimal_shift_point(
truck_schedule=truck.schedule,
delayed_slot=affected_slot,
delay=delay
)
# Выполняем "умный" сдвиг
adjusted_schedule = execute_smart_shift(
schedule=current_schedule,
shift_from=shift_point,
shift_amount=delay,
strategy='MINIMAL_DISTURBANCE'
)
# Уровень 3: Каскадный перерасчет с изоляцией
else:
# Изолируем область воздействия
impact_zone = isolate_impact_zone(
schedule=current_schedule,
epicenter=affected_slot,
max_ripple_hours=2 # Ограничиваем распространение 2 часами
)
# Перераспределяем в изолированной зоне
adjusted_schedule = reschedule_within_zone(
schedule=current_schedule,
impact_zone=impact_zone,
delay_source=affected_slot
)
# Шаг 4: Проверка и компенсация
compensation_needed = check_for_compensation_needs(adjusted_schedule)
if compensation_needed:
adjusted_schedule = apply_compensation_measures(
schedule=adjusted_schedule,
compensation_plan=compensation_needed
)
return adjusted_schedule
5. ИНТЕЛЛЕКТУАЛЬНЫЙ МЕХАНИЗМ ПРЕДОТВРАЩЕНИЯ КАСКАДНЫХ СБОЕВ
5.1. Алгоритм "Умной изоляции":
def intelligent_impact_isolation(schedule, failure_point):
"""
Изоляция области воздействия сбытия с минимизацией распространения
"""
# Шаг 1: Определение "эпицентра" и "эпицентральной зоны"
epicenter = failure_point
epicentral_zone = calculate_epicentral_zone(
epicenter=epicenter,
radius_hours=1, # Первый час - максимальное воздействие
schedule=schedule
)
# Шаг 2: Идентификация "амортизаторов" - поставок, которые могут сдвинуться без последствий
shock_absorbers = identify_shock_absorbers(
schedule=schedule,
around_zone=epicentral_zone,
buffer_size=2 # 2 слота в каждую сторону
)
# Шаг 3: Создание "защитного периметра"
protective_perimeter = create_protective_perimeter(
schedule=schedule,
inner_zone=epicentral_zone,
outer_radius_hours=3
)
# Шаг 4: Расчет "коэффициента упругости" для каждого слота
elasticity_map = calculate_slot_elasticity(
schedule=schedule,
zone=epicentral_zone + protective_perimeter
)
return {
'epicenter': epicenter,
'epicentral_zone': epicentral_zone,
'shock_absorbers': shock_absorbers,
'protective_perimeter': protective_perimeter,
'elasticity_map': elasticity_map,
'isolation_strategy': 'ADAPTIVE_CONTAINMENT'
}
5.2. Алгоритм "Приоритетного спасения":
def priority_based_rescue(schedule, affected_slots):
"""
Спасение поставок по приоритету с учетом многомерных критериев
"""
# Многомерная оценка критичности каждой поставки
criticality_scores = []
for slot in affected_slots:
score = calculate_multidimensional_criticality(
slot=slot,
dimensions=[
'CLIENT_PRIORITY', # Важность клиента
'CEMENT_VIABILITY', # Риск схватывания бетона
'CONTRACT_PENALTY', # Штрафы за срыв
'LOGISTIC_COMPLEXITY', # Сложность замены
'IMPACT_ON_OTHERS' # Влияние на другие поставки
]
)
criticality_scores.append({
'slot': slot,
'score': score,
'rescue_window': calculate_rescue_window(slot),
'rescue_options': find_rescue_options(slot, schedule)
})
# Сортировка по критичности и доступности вариантов спасения
criticality_scores.sort(
key=lambda x: (
-x['score']['overall'], # По убыванию критичности
len(x['rescue_options']), # По количеству вариантов
x['rescue_window']['minutes_remaining'] # По оставшемуся времени
)
)
# Последовательное спасение
rescued_slots = []
failed_rescues = []
for item in criticality_scores:
rescue_result = attempt_slot_rescue(
slot=item['slot'],
options=item['rescue_options'],
schedule=schedule,
time_limit=item['rescue_window']['minutes_remaining']
)
if rescue_result['success']:
rescued_slots.append({
'slot': item['slot'],
'new_assignment': rescue_result['new_assignment']
})
schedule = rescue_result['updated_schedule']
else:
failed_rescues.append({
'slot': item['slot'],
'reason': rescue_result['failure_reason'],
'suggested_actions': rescue_result['suggestions']
})
return {
'rescued_count': len(rescued_slots),
'failed_count': len(failed_rescues),
'rescued_slots': rescued_slots,
'failed_rescues': failed_rescues,
'final_schedule': schedule,
'rescue_efficiency': len(rescued_slots) / len(affected_slots)
}
6. АЛГОРИТМ ОБРАБОТКИ МНОЖЕСТВЕННЫХ СБОЕВ
Сценарий: Одновременная поломка 2 машин + задержка на 3 объектах
def handle_multiple_failures(failure_events):
"""
Обработка множественных одновременных сбоев
"""
# Шаг 1: Кластеризация сбоев по времени и местоположению
failure_clusters = cluster_failures(
events=failure_events,
time_threshold=TimeSpan.FromMinutes(30),
location_threshold=5 # км
)
# Шаг 2: Определение доминирующего сбоя в каждом кластере
dominant_failures = []
for cluster in failure_clusters:
dominant = find_dominant_failure(cluster)
dominant_failures.append(dominant)
# Шаг 3: Последовательная обработка доминирующих сбоев
# с учетом их взаимного влияния
current_schedule = get_current_schedule()
for i, failure in enumerate(dominant_failures):
# Учитываем изменения, внесенные обработкой предыдущих сбоев
impact_forecast = forecast_cross_impact(
failure=failure,
already_handled=dominant_failures[:i],
current_schedule=current_schedule
)
# Адаптивная стратегия с учетом прогноза
strategy = adapt_strategy_based_on_forecast(
base_strategy=get_base_strategy(failure),
impact_forecast=impact_forecast,
remaining_failures=dominant_failures[i+1:]
)
# Выполнение с компенсацией побочных эффектов
result = execute_with_side_effect_compensation(
strategy=strategy,
schedule=current_schedule,
compensation_buffer=TimeSpan.FromMinutes(15)
)
current_schedule = result['schedule']
# Если достигнут предел устойчивости - остановка
if result['system_stability'] < 0.6: # Порог устойчивости
emergency_stabilization(current_schedule)
break
# Шаг 4: Глобальная оптимизация после экстренных мер
optimized_schedule = global_post_crisis_optimization(
schedule=current_schedule,
optimization_criteria=['STABILITY', 'FAIRNESS', 'EFFICIENCY']
)
return optimized_schedule
7. МЕХАНИЗМЫ КОМПЕНСАЦИИ И ВОССТАНОВЛЕНИЯ
7.1. Алгоритм распределения компенсационных буферов:
def redistribute_compensation_buffers(schedule, stress_points):
"""
Перераспределение временных буферов для компенсации сбоев
"""
# Шаг 1: Идентификация "доноров" буферов
buffer_donors = find_buffer_donors(
schedule=schedule,
criteria=[
'HAS_EXCESS_BUFFER', # Имеет избыточный буфер
'LOW_RISK_PROFILE', # Низкий риск сбоев
'FLEXIBLE_TIME_WINDOW', # Гибкое временное окно
'NON_CRITICAL_CLIENT' # Не критичный клиент
]
)
# Шаг 2: Идентификация "реципиентов" буферов
buffer_recipients = find_buffer_recipients(
schedule=schedule,
stress_points=stress_points,
criteria=[
'HIGH_RISK_PROFILE', # Высокий риск
'TIGHT_TIME_WINDOW', # Жесткое окно
'CRITICAL_CLIENT', # Важный клиент
'MINIMAL_BUFFER' # Мало буфера
]
)
# Шаг 3: Оптимальное перераспределение
redistribution_plan = optimize_buffer_redistribution(
donors=buffer_donors,
recipients=buffer_recipients,
schedule=schedule,
objective='MAXIMIZE_SYSTEM_STABILITY'
)
# Шаг 4: Поэтапное применение
new_schedule = apply_buffer_redistribution(
schedule=schedule,
plan=redistribution_plan,
phase_duration=TimeSpan.FromMinutes(5) # Постепенно, по 5 минут
)
return new_schedule
7.2. Алгоритм восстановления после каскадного сбоя:
def post_cascade_recovery(schedule, cascade_event):
"""
Восстановление системы после серьезного каскадного сбоя
"""
recovery_phases = [
{
'name': 'СТАБИЛИЗАЦИЯ',
'duration': TimeSpan.FromMinutes(30),
'objectives': ['STOP_CASCADE', 'PROTECT_CRITICAL', 'ISOLATE_DAMAGE']
},
{
'name': 'ВОССТАНОВЛЕНИЕ',
'duration': TimeSpan.FromHours(2),
'objectives': ['RESTORE_CAPACITY', 'REASSIGN_URGENT', 'OPTIMIZE_LOCALLY']
},
{
'name': 'ОПТИМИЗАЦИЯ',
'duration': TimeSpan.FromHours(4),
'objectives': ['GLOBAL_OPTIMIZATION', 'LOAD_BALANCING', 'BUFFER_RESTORATION']
}
]
recovered_schedule = schedule
for phase in recovery_phases:
phase_strategy = create_recovery_strategy(
phase=phase,
current_state=recovered_schedule,
cascade_history=cascade_event.history
)
phase_result = execute_recovery_phase(
strategy=phase_strategy,
schedule=recovered_schedule,
time_limit=phase['duration']
)
recovered_schedule = phase_result['schedule']
# Проверка готовности к следующей фазе
if not phase_result['phase_successful']:
# Расширяем текущую фазу
phase['duration'] += TimeSpan.FromMinutes(15)
continue
# Мониторинг прогресса восстановления
recovery_metrics = calculate_recovery_metrics(
original=schedule,
current=recovered_schedule,
phase=phase['name']
)
if recovery_metrics['stability_index'] >= 0.8:
# Достигнута достаточная стабильность - переход к следующей фазе
continue
else:
# Требуется дополнительное время
phase['duration'] += TimeSpan.FromMinutes(30)
# Финальная проверка
final_validation = validate_recovery_completion(
original_schedule=schedule,
recovered_schedule=recovered_schedule,
cascade_event=cascade_event
)
if final_validation['recovery_successful']:
return {
'status': 'FULL_RECOVERY',
'schedule': recovered_schedule,
'recovery_time': final_validation['total_recovery_time'],
'efficiency_loss': final_validation['efficiency_loss_percentage']
}
else:
return {
'status': 'PARTIAL_RECOVERY',
'schedule': recovered_schedule,
'unresolved_issues': final_validation['remaining_issues'],
'human_intervention_required': True
}
8. ИНТЕЛЛЕКТУАЛЬНАЯ СИСТЕМА ПРИНЯТИЯ РЕШЕНИЙ
8.1. Нейросетевая оценка вариантов перерасчета:
Архитектура нейросети для оценки вариантов: Входной слой (12 параметров): 1. Количество затронутых поставок 2. Средний приоритет клиентов 3. Общий объем риска (м³×приоритет) 4. Временной горизонт воздействия 5. Количество доступных машин 6. Среднее расстояние до объектов 7. Коэффициент заполнения машин 8. Запас по времени жизни бетона 9. Сложность логистики (1-10) 10. Погодные условия (индекс) 11. Дорожная ситуация (индекс) 12. Историческая надежность варианта Скрытые слои (3 слоя по 8 нейронов): - Анализ взаимосвязей параметров - Выявление неочевидных паттернов - Оценка рисков и возможностей Выходной слой (4 оценки): 1. Вероятность успеха (0-1) 2. Ожидаемое время восстановления (минуты) 3. Прогнозируемые потери (денежные) 4. Качество расписания после (0-100)
8.2. Алгоритм принятия решений на основе ML:
def ml_enhanced_decision_making(options, historical_data):
"""
Принятие решений с использованием машинного обучения
"""
# Шаг 1: Извлечение признаков для каждого варианта
feature_vectors = []
for option in options:
features = extract_features(option)
feature_vectors.append(features)
# Шаг 2: Прогнозирование результатов с помощью обученной модели
predictions = prediction_model.predict(feature_vectors)
# Шаг 3: Многокритериальная оптимизация
optimal_option = multi_criteria_optimization(
options=options,
predictions=predictions,
criteria_weights={
'success_probability': 0.35,
'recovery_time': 0.25,
'financial_impact': 0.20,
'schedule_quality': 0.20
}
)
# Шаг 4: Проверка на аномалии
anomaly_check = detect_anomalies(
selected_option=optimal_option,
historical_patterns=historical_data
)
if anomaly_check['is_anomaly']:
# Выбор второго лучшего варианта
optimal_option = get_second_best(
options=options,
predictions=predictions
)
return optimal_option
9. СИСТЕМА МОНИТОРИНГА И ПРОГНОЗИРОВАНИЯ КАСКАДОВ
9.1. Алгоритм раннего предупреждения:
def early_cascade_warning_system(schedule):
"""
Система раннего предупреждения о потенциальных каскадных сбоях
"""
# Шаг 1: Поиск "точек напряжения" в расписании
stress_points = find_schedule_stress_points(
schedule=schedule,
indicators=[
'BACK_TO_BACK_SLOTS', # Слоты без буфера
'TIGHT_TIME_WINDOWS', # Жесткие окна клиентов
'HIGH_RISK_COMBINATIONS', # Рискованные комбинации поставок
'OVERLOADED_TRUCKS', # Перегруженные машины
'GEOGRAPHIC_CONFLICTS' # Географические конфликты
]
)
# Шаг 2: Расчет "индекса каскадного риска" для каждой точки
cascade_risk_index = {}
for point in stress_points:
risk_score = calculate_cascade_risk(
stress_point=point,
schedule=schedule,
historical_failures=load_failure_history()
)
cascade_risk_index[point] = risk_score
# Шаг 3: Прогнозирование потенциальных каскадов
potential_cascades = forecast_potential_cascades(
stress_points=stress_points,
risk_index=cascade_risk_index,
simulation_count=1000 # Монте-Карло симуляция
)
# Шаг 4: Генерация превентивных рекомендаций
preventive_recommendations = generate_preventive_recommendations(
potential_cascades=potential_cascades,
schedule=schedule,
intervention_cost_threshold=10000 # Максимальная стоимость вмешательства
)
return {
'high_risk_points': cascade_risk_index,
'potential_cascades': potential_cascades,
'preventive_actions': preventive_recommendations,
'overall_risk_level': calculate_overall_risk_level(cascade_risk_index)
}
10. ПРАКТИЧЕСКАЯ РЕАЛИЗАЦИЯ: ОГРАНИЧЕНИЯ И ОПТИМИЗАЦИИ
10.1. Ограничения реального времени:
def real_time_constrained_rescheduling(event, time_budget):
"""
Перерасчет с жестким ограничением по времени
"""
# Шаг 1: Быстрая оценка сложности
complexity = estimate_rescheduling_complexity(event)
# Шаг 2: Выбор стратегии в зависимости от доступного времени
if time_budget < TimeSpan.FromMinutes(2):
strategy = 'ULTRA_FAST_HEURISTIC'
max_iterations = 100
search_depth = 1
elif time_budget < TimeSpan.FromMinutes(5):
strategy = 'FAST_LOCAL_SEARCH'
max_iterations = 1000
search_depth = 2
elif time_budget < TimeSpan.FromMinutes(10):
strategy = 'BALANCED_OPTIMIZATION'
max_iterations = 5000
search_depth = 3
else:
strategy = 'COMPREHENSIVE_SEARCH'
max_iterations = 20000
search_depth = 4
# Шаг 3: Адаптивный алгоритм с контролем времени
start_time = datetime.now()
best_solution = None
while (datetime.now() - start_time) < time_budget:
candidate = generate_candidate_solution(
event=event,
strategy=strategy,
current_best=best_solution
)
candidate_score = evaluate_solution(candidate)
if best_solution is None or candidate_score > best_solution['score']:
best_solution = {
'schedule': candidate,
'score': candidate_score,
'time_spent': datetime.now() - start_time
}
# Проверка прогресса
if should_terminate_early(
current_best=best_solution,
time_remaining=time_budget - (datetime.now() - start_time),
progress_rate=calculate_progress_rate()
):
break
return best_solution['schedule']
10.2. Балансировка качества и скорости:
| Режим работы | Время на перерасчет | Качество решения | Используется когда |
|---|---|---|---|
| Экстренный | 30-60 секунд | 60-70% от оптимального | Поломка в час пик, риск схватывания бетона |
| Оперативный | 2-5 минут | 75-85% от оптимального | Стандартные сбои в рабочее время |
| Тщательный | 5-10 минут | 85-95% от оптимального | Плановые изменения, оптимизация |
| Аналитический | 10-20 минут | 95-99% от оптимального | Анализ после смены, обучение системы |
ЗАКЛЮЧЕНИЕ: ФИЛОСОФИЯ УПРАВЛЕНИЯ ХАОСОМ
Алгоритм каскадного перерасчета — это живая, адаптивная система, которая эволюционирует с каждым обработанным сбоем. Её ключевые принципы:
-
Принцип минимального вмешательства: Менять только то, что необходимо
-
Принцип управляемого распространения: Контролировать границы воздействия
-
Принцип приоритетного спасения: Сначала важное, потом остальное
-
Принцип обучаемости: Каждый сбой делает систему умнее
-
Принцип отказоустойчивости: Всегда иметь план Б, В и Г
Итоговая формула успеха:
Эффективность_перерасчета = (Скорость_реакции × 0.3) + (Качество_решения × 0.4) + (Минимизация_изменений × 0.2) + (Удовлетворенность_клиентов × 0.1)
Этот алгоритм превращает хаотичные сбои из угрозы в возможность — возможность оптимизировать, учиться и становиться устойчивее с каждым днем.