Лекция 2.7. Транспортная задача: линейное программирование
Содержание
- Лекция 2.7. Транспортная задача: линейное программирование
Постановка транспортной задачи
Транспортная задача — задача оптимизации перевозок грузов от поставщиков к потребителям с минимальными затратами при соблюдении ограничений по запасам и спросу.
Исходные данные
Поставщики:
- $m$ поставщиков с запасами $A_1, A_2, …, A_m$
Потребители:
- $n$ потребителей со спросом $B_1, B_2, …, B_n$
Стоимости перевозки:
- $C_{ij}$ — стоимость перевозки 1 единицы от поставщика $i$ к потребителю $j$
Пример
Данные:
| Поставщик \ Потребитель | П1 | П2 | П3 | Запас |
|---|---|---|---|---|
| С1 | 5 | 8 | 3 | 100 |
| С2 | 4 | 6 | 7 | 150 |
| С3 | 9 | 5 | 4 | 200 |
| Спрос | 120 | 180 | 150 | — |
Вопрос: Сколько и куда перевозить для минимизации затрат?
Математическая модель
Целевая функция
Минимизация совокупных затрат:
\[min \\sum_{i=1}^{m}\\sum_{j=1}^{n} C_{ij} \\cdot x_{ij}\]Где:
- $x_{ij}$ — объём перевозки от поставщика $i$ к потребителю $j$
- $C_{ij}$ — стоимость перевозки единицы груза
Ограничения
По запасам поставщиков: \(\\sum_{j=1}^{n} x_{ij} \\leq A_i, \\quad i = 1, ..., m\)
По спросу потребителей: \(\\sum_{i=1}^{m} x_{ij} \\geq B_j, \\quad j = 1, ..., n\)
Неотрицательность: \(x_{ij} \\geq 0\)
Балансовое условие
Закрытая модель (спрос = предложение): \(\\sum_{i=1}^{m} A_i = \\sum_{j=1}^{n} B_j\)
Открытая модель (требуется балансировка):
- Если предложение > спроса — вводится фиктивный потребитель
- Если спрос > предложения — вводится фиктивный поставщик
Метод минимального элемента
Алгоритм
Шаг 1. Найти клетку с минимальной стоимостью $C_{ij}$
Шаг 2. Назначить максимальную перевозку: \(x_{ij} = min(A_i, B_j)\)
Шаг 3. Скорректировать запасы и спрос:
- $A_i = A_i - x_{ij}$
- $B_j = B_j - x_{ij}$
Шаг 4. Исключить удовлетворённую строку или столбец
Шаг 5. Повторять шаги 1–4 до полного распределения
Пример решения
Исходная матрица:
| С \ П | П1 | П2 | П3 | Запас |
|---|---|---|---|---|
| С1 | 5 | 8 | 3 | 100 |
| С2 | 4 | 6 | 7 | 150 |
| С3 | 9 | 5 | 4 | 200 |
| Спрос | 120 | 180 | 150 | — |
Шаги:
- Минимум = 3 (С1-П3): $x_{13} = min(100, 150) = 100$
- С1 исчерпан, П3 осталось 50
- Минимум = 4 (С2-П1): $x_{21} = min(150, 120) = 120$
- П1 удовлетворён, С2 осталось 30
- Минимум = 5 (С3-П2): $x_{32} = min(200, 180) = 180$
- П2 удовлетворён, С3 осталось 20
- Минимум = 4 (С3-П3): $x_{33} = min(20, 50) = 20$
- С3 исчерпан, П3 осталось 30
- Минимум = 7 (С2-П3): $x_{23} = min(30, 30) = 30$
- Всё распределено
Результат:
| С \ П | П1 | П2 | П3 |
|---|---|---|---|
| С1 | 0 | 0 | 100 |
| С2 | 120 | 0 | 30 |
| С3 | 0 | 180 | 20 |
Затраты: $100×3 + 120×4 + 30×7 + 180×5 + 20×4 = 300 + 480 + 210 + 900 + 80 = 1970$ руб.
Метод потенциалов
Алгоритм проверки оптимальности
Шаг 1. Назначить потенциалы $u_i$ и $v_j$ так, чтобы для всех базисных клеток: \(u_i + v_j = C_{ij}\)
Шаг 2. Принять $u_1 = 0$
Шаг 3. Вычислить оценки свободных клеток: \(\\Delta_{ij} = C_{ij} - (u_i + v_j)\)
Шаг 4. Проверить оптимальность:
- Если все $\Delta_{ij} \geq 0$ — план оптимален
- Если есть $\Delta_{ij} < 0$ — план можно улучшить
Пример проверки
Потенциалы для базисных клеток:
| С \ П | П1 ($v_1$) | П2 ($v_2$) | П3 ($v_3$) | $u_i$ |
|---|---|---|---|---|
| С1 ($u_1=0$) | — | — | 3 | 0 |
| С2 ($u_2$) | 4 | — | 7 | -1 |
| С3 ($u_3$) | — | 5 | 4 | 0 |
| $v_j$ | 5 | 5 | 3 | — |
Расчёт оценок свободных клеток:
- $\Delta_{11} = 5 - (0 + 5) = 0$
- $\Delta_{12} = 8 - (0 + 5) = 3$
- $\Delta_{22} = 6 - (-1 + 5) = 2$
- $\Delta_{31} = 9 - (0 + 5) = 4$
Вывод: Все $\Delta_{ij} \geq 0$ → план оптимален!
Инструменты решения
Excel («Поиск решения»)
Настройка:
- Создать таблицу перевозок
- Формула целевой функции:
=СУММПРОИЗВ(матрица_перевозок; матрица_стоимостей) - Ограничения:
- Сумма по строкам ≤ запасы
- Сумма по столбцам ≥ спрос
- Запустить «Поиск решения» (Solver)
Python (Google OR-Tools)
from ortools.linear_solver import pywraplp
# Создание решателя
solver = pywraplp.Solver('Transport', pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
# Данные
costs = [[5, 8, 3], [4, 6, 7], [9, 5, 4]]
supply = [100, 150, 200]
demand = [120, 180, 150]
# Переменные решения
x = {}
for i in range(3):
for j in range(3):
x[i, j] = solver.NumVar(0, solver.infinity(), f'x[{i},{j}]')
# Целевая функция
solver.Minimize(solver.Sum(costs[i][j] * x[i, j] for i in range(3) for j in range(3)))
# Ограничения по запасам
for i in range(3):
solver.Add(solver.Sum(x[i, j] for j in range(3)) <= supply[i])
# Ограничения по спросу
for j in range(3):
solver.Add(solver.Sum(x[i, j] for i in range(3)) >= demand[j])
# Решение
status = solver.Solve()
print(f'Минимальные затраты: {solver.Objective().Value()}')
Python (PuLP)
from pulp import *
# Модель
model = LpProblem('Transport', LpMinimize)
# Переменные
x = LpVariable.dicts('x', [(i, j) for i in range(3) for j in range(3)], lowBound=0)
# Целевая функция
model += lpSum(costs[i][j] * x[(i, j)] for i in range(3) for j in range(3))
# Ограничения
for i in range(3):
model += lpSum(x[(i, j)] for j in range(3)) <= supply[i]
for j in range(3):
model += lpSum(x[(i, j)] for i in range(3)) >= demand[j]
# Решение
model.solve()
Транспортная задача большой размерности
Проблемы большой размерности
При большом количестве поставщиков и потребителей:
- Экспоненциальный рост числа переменных
- Длительное время решения
- Проблемы с памятью
Пример:
- 100 поставщиков × 500 потребителей = 50 000 переменных
- 100 + 500 = 600 ограничений
Методы решения
1. Декомпозиция
- Разбиение на подзадачи меньшего размера
- Последовательное решение с координацией
2. Приближённые алгоритмы
- Жадные алгоритмы
- Генетические алгоритмы
- Метод роя частиц
3. Специализированные решатели
- Gurobi, CPLEX — коммерческие
- Google OR-Tools, CBC — открытые
Учёт ограничений инфраструктуры
Типы ограничений
Пропускная способность маршрутов: \(x_{ij} \\leq Capacity_{ij}\)
Ограничения по типу транспорта:
- Только определённые маршруты для опасных грузов
- Ограничения по весу/габаритам
Временные окна:
- Доставка в определённые часы
- Ограничения на ночные перевозки
Парк подвижного состава: \(\\sum_{j} x_{ij} \\leq Fleet_i \\cdot Capacity_{vehicle}\)
Пример с ограничениями
Дополнительные условия:
- Маршрут С1-П3: максимум 80 единиц (ремонт дороги)
- Маршрут С2-П1: минимум 50 единиц (договорные обязательства)
Модификация модели:
x[1,3] <= 80
x[2,1] >= 50
Сравнение Excel и Python
| Критерий | Excel | Python |
|---|---|---|
| Простота использования | Высокая (GUI) | Средняя (требуется код) |
| Размерность задачи | До 200 переменных | До 1 000 000+ переменных |
| Время решения | Секунды–минуты | Секунды для больших задач |
| Интеграция | Ограниченная | Полная (API, базы данных) |
| Стоимость | Входит в Office | Бесплатно (OR-Tools, PuLP) |
| Визуализация | Встроенная | Через matplotlib, seaborn |
Рекомендации по выбору
| Ситуация | Инструмент |
|---|---|
| Малые задачи (до 50 переменных) | Excel |
| Средние задачи (50–500 переменных) | Excel или Python |
| Большие задачи (500+ переменных) | Python |
| Интеграция с другими системами | Python |
| Быстрый прототип | Excel |
| Промышленное решение | Python |
Ключевые выводы по лекции
-
Транспортная задача минимизирует затраты на перевозки при ограничениях по запасам и спросу.
-
Математическая модель: целевая функция минимизации затрат + ограничения баланса.
-
Метод минимального элемента строит начальный план.
-
Метод потенциалов проверяет оптимальность: все $\Delta_{ij} \geq 0$.
-
Инструменты: Excel (Solver), Python (OR-Tools, PuLP).
-
Большая размерность требует декомпозиции или специализированных решателей.
-
Ограничения инфраструктуры учитываются в модели дополнительными условиями.
-
Выбор инструмента зависит от размерности задачи и требований к интеграции.
Контрольные вопросы
- Дайте определение транспортной задачи.
- Запишите математическую модель транспортной задачи.
- Опишите алгоритм метода минимального элемента.
- Как проверяется оптимальность плана методом потенциалов?
- Какие инструменты используются для решения транспортных задач?