Лекция 2.7. Транспортная задача: линейное программирование
Содержание
- Лекция 2.7. Транспортная задача: линейное программирование
- Содержание
- Постановка транспортной задачи
- Математическая модель
- Свойства транспортной задачи
- Методы построения начального плана
- Решение примера методом минимального элемента
- Метод потенциалов
- Инструменты решения
- Транспортная задача большой размерности
- Учёт ограничений инфраструктуры
- Сравнение Excel и Python
- Применение на машиностроительном предприятии
- Связь с лабораторной работой
- Ключевые выводы по лекции
- Контрольные вопросы
- Рекомендуемая литература
Постановка транспортной задачи
Транспортная задача — задача оптимизации перевозок грузов от поставщиков к потребителям с минимальными затратами при соблюдении ограничений по запасам и спросу.
Это классическая задача линейного программирования (ЛП), имеющая, однако, специальную структуру, которая позволяет решать её эффективнее общего симплекс-метода — табличными алгоритмами (метод потенциалов) и специализированными решателями (min-cost flow).
Исходные данные
Поставщики:
- $m$ поставщиков с запасами $A_1, A_2, …, A_m$;
Потребители:
- $n$ потребителей со спросом $B_1, B_2, …, B_n$;
Стоимости перевозки:
- $C_{ij}$ — стоимость перевозки 1 единицы от поставщика $i$ к потребителю $j$.
Данные сводятся в таблицу транспортных затрат — основной рабочий документ метода:
| П1 | П2 | … | Пn | Запас | |
|---|---|---|---|---|---|
| С1 | $c_{11}$ | $c_{12}$ | … | $c_{1n}$ | $A_1$ |
| С2 | $c_{21}$ | $c_{22}$ | … | $c_{2n}$ | $A_2$ |
| … | … | … | … | … | … |
| Сm | $c_{m1}$ | $c_{m2}$ | … | $c_{mn}$ | $A_m$ |
| Спрос | $B_1$ | $B_2$ | … | $B_n$ | — |
Содержательная интерпретация
В логистике под «поставщиком» и «потребителем» могут пониматься объекты самой разной природы:
| Постановка | Поставщики | Потребители | Единица $x_{ij}$ |
|---|---|---|---|
| Перевозка со складов в магазины | Распределительные центры | Розничные точки | Тонны, паллеты |
| Внутризаводские перевозки | Цеха-изготовители | Цеха-потребители полуфабрикатов | Единицы деталей |
| Порожний пробег вагонов | Станции с избытком вагонов | Станции с дефицитом | Вагоны |
| Назначение поставщиков потребителям | Поставщики материалов | Производственные переделы | Объём поставки |
| Размещение заказов | Заводы-изготовители | Региональные склады | Единицы продукции |
Пример
Данные:
| Поставщик \ Потребитель | П1 | П2 | П3 | Запас |
|---|---|---|---|---|
| С1 | 5 | 8 | 3 | 100 |
| С2 | 4 | 6 | 7 | 150 |
| С3 | 9 | 5 | 4 | 200 |
| Спрос | 120 | 180 | 150 | — |
Проверка баланса: $100 + 150 + 200 = 450$; $120 + 180 + 150 = 450$ — модель закрытая.
Вопрос: Сколько и куда перевозить для минимизации затрат?
Транспортная задача как частный случай линейного программирования
Общая задача ЛП: найти $\min c^T x$ при ограничениях $Ax \leq b$, $x \geq 0$, решаемую симплекс-методом. Транспортная задача отличается тем, что:
- все ограничения — равенства баланса (в закрытой модели);
- матрица ограничений состоит только из 0 и 1 (каждая переменная входит ровно в два ограничения — по строке и по столбцу);
- при целочисленных $A_i$ и $B_j$ оптимальный план автоматически целочисленный — округление не требуется.
Эти свойства делают возможным простой табличный алгоритм решения без построения симплекс-таблиц.
Математическая модель
Целевая функция
Минимизация совокупных затрат:
\[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\]Открытая модель (требуется балансировка):
- Если предложение > спроса — вводится фиктивный потребитель со спросом $B_{n+1} = \sum A_i - \sum B_j$ и нулевыми тарифами;
- Если спрос > предложения — вводится фиктивный поставщик с запасом $A_{m+1} = \sum B_j - \sum A_i$ и нулевыми тарифами.
Перевозки фиктивному участнику интерпретируются как невыполненные (оставленный на складе запас или неудовлетворённый спрос) — их величина в оптимальном плане показывает, какие реальные перевозки окажутся «лишними» или «недостающими».
Открытая модель: балансировка фиктивным участником
Пример. Пусть запасы уменьшились: $A_1 = 50$, $A_2 = 60$, $A_3 = 70$ (итого 180), а спрос прежний — 200. Дефицит: $200 - 180 = 20$ ед. Вводим фиктивного поставщика С4 с запасом 20 и нулевыми тарифами:
| С \ П | П1 | П2 | П3 | П4 | Запас |
|---|---|---|---|---|---|
| С1 | 2 | 4 | 8 | 7 | 50 |
| С2 | 5 | 3 | 6 | 9 | 60 |
| С3 | 8 | 7 | 4 | 2 | 70 |
| С4 (фикт.) | 0 | 0 | 0 | 0 | 20 |
| Спрос | 40 | 50 | 60 | 50 | 200 |
Решение методом минимального элемента (нулевые тарифы выбираются первыми):
- Минимум 0 (С4–П1): $x_{41} = \min(20, 40) = 20$ → С4 исчерпан, П1 осталось 20;
- Минимум 2 (С1–П1): $x_{11} = 20$ → П1 удовлетворён, С1 осталось 30;
- Минимум 2 (С3–П4): $x_{34} = 50$ → П4 удовлетворён, С3 осталось 20;
- Минимум 3 (С2–П2): $x_{22} = 50$ → П2 удовлетворён, С2 осталось 10;
- Минимум 4 (С3–П3): $x_{33} = 20$ → С3 исчерпан, П3 осталось 40;
- Минимум 6 (С2–П3): $x_{23} = 10$ → С2 исчерпан, П3 осталось 30;
- Минимум 8 (С1–П3): $x_{13} = 30$ → всё распределено.
Интерпретация: $x_{41} = 20$ означает, что потребитель П1 недополучит 20 единиц (его потребность 40 удовлетворена лишь на 20 со склада С1). Реальные транспортные затраты: $20 \cdot 2 + 50 \cdot 2 + 50 \cdot 3 + 20 \cdot 4 + 10 \cdot 6 + 30 \cdot 8 = 40 + 100 + 150 + 80 + 60 + 240 = 670$ руб.
Свойства транспортной задачи
Ранг системы ограничений и базис
Система из $m + n$ уравнений баланса линейно зависима: сумма уравнений по строкам тождественно равна сумме уравнений по столбцам (обе равны общему объёму перевозок). Поэтому ранг системы равен $m + n - 1$ — столько же должно быть ненулевых (базисных) клеток в опорном плане.
Правило контроля: после построения начального плана сосчитайте занятые клетки. Если их ровно $m + n - 1$ — план невырожденный. Если меньше — план вырожденный, и для работы метода потенциалов одну из свободных клеток следует объявить базисной с нулевой поставкой.
Для примера 3×3 (раздел «Постановка»): $m + n - 1 = 3 + 3 - 1 = 5$ базисных клеток; для примера 3×4, решаемого ниже: $3 + 4 - 1 = 6$.
Опорный план и вырожденность
Опорный план — любой допустимый план перевозок (удовлетворяющий ограничениям) с $m + n - 1$ базисными клетками. Вырожденность возникает, когда число занятых клеток меньше $m + n - 1$ (например, когда на шаге распределения одновременно обнуляются и строка, и столбец).
Теорема (существование решения): если модель закрытая и сбалансированная, оптимальный план всегда существует и конечен.
Теорема (целочисленность): при целых запасах и спросе существует оптимальный план с целыми $x_{ij}$ — важное свойство для практики (грузы неделимы: контейнеры, вагоны, паллеты).
Методы построения начального плана
Сравнение методов
| Метод | Идея | Качество начального плана | Трудоёмкость |
|---|---|---|---|
| Северо-западный угол | Заполнение с левого верхнего угла без учёта тарифов | Низкое (далёк от оптимума) | Минимальная |
| Минимальный элемент | Сначала самые дешёвые клетки | Хорошее (близок к оптимуму) | Низкая |
| Метод Фогеля (аппроксимации) | Учёт разницы двух минимальных тарифов в строке/столбце | Наилучшее из эвристик | Средняя |
| Двойственный метод (Йоффе) | Оценка по минимумам строк и столбцов | Высокое | Средняя |
Метод северо-западного угла
Алгоритм: начать с клетки (1,1), назначить $x_{11} = \min(A_1, B_1)$, исчерпанную строку/столбец исключить, перейти к следующей северо-западной клетке оставшейся подтаблицы.
Метод не учитывает стоимость и даёт худший начальный план, но прост и полезен для понимания структуры алгоритма. Для примера 3×3 из начала лекции он даёт план $x_{11} = 100$, $x_{21} = 20$, $x_{22} = 130$, $x_{32} = 50$, $x_{33} = 150$ с затратами $100 \cdot 5 + 20 \cdot 4 + 130 \cdot 6 + 50 \cdot 5 + 150 \cdot 4 = 500 + 80 + 780 + 250 + 600 = 2210$ руб. против 1970 руб. по методу минимального элемента — сразу на 12% дороже.
Метод минимального элемента: алгоритм
Шаг 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 до полного распределения.
Шаг 6. Проверить число базисных клеток: должно быть $m + n - 1$.
Решение примера методом минимального элемента
Рассмотрим полную задачу 3×4 — поставка материалов с трёх складов АО «Ракета» (склад обеспечения, склад цеха микросборки, склад цеха агрегатов) четырём производственным участкам-потребителям.
Условие (закрытая модель):
- Запасы: $A_1 = 50$, $A_2 = 60$, $A_3 = 90$ (итого 200 ед.);
- Спрос: $B_1 = 40$, $B_2 = 50$, $B_3 = 60$, $B_4 = 50$ (итого 200 ед.);
- Матрица тарифов $C_{ij}$ (руб./ед.):
| С \ П | П1 | П2 | П3 | П4 | Запас |
|---|---|---|---|---|---|
| С1 | 2 | 4 | 8 | 7 | 50 |
| С2 | 5 | 3 | 6 | 9 | 60 |
| С3 | 8 | 7 | 4 | 2 | 90 |
| Спрос | 40 | 50 | 60 | 50 | 200 |
Итерации распределения
Итерация 1. Минимальный тариф — $c_{11} = 2$ (С1–П1). Назначаем:
\[x_{11} = \min(50, 40) = 40\]П1 удовлетворён (столбец исключаем), у С1 осталось $50 - 40 = 10$.
| С \ П | П1 | П2 | П3 | П4 | Остаток |
|---|---|---|---|---|---|
| С1 | 40 | 4 | 8 | 7 | 10 |
| С2 | × | 3 | 6 | 9 | 60 |
| С3 | × | 7 | 4 | 2 | 90 |
| Остаток спроса | — | 50 | 60 | 50 |
Итерация 2. Минимальный тариф среди доступных — $c_{34} = 2$ (С3–П4):
\[x_{34} = \min(90, 50) = 50\]П4 удовлетворён (столбец исключаем), у С3 осталось $90 - 50 = 40$.
Итерация 3. Минимум — $c_{22} = 3$ (С2–П2):
\[x_{22} = \min(60, 50) = 50\]П2 удовлетворён, у С2 осталось $60 - 50 = 10$.
Итерация 4. Минимум — $c_{33} = 4$ (С3–П3):
\[x_{33} = \min(40, 60) = 40\]С3 исчерпан (строку исключаем), П3 осталось $60 - 40 = 20$.
Итерация 5. Минимум среди оставшихся (строки С1, С2; столбец П3) — $c_{23} = 6$ (С2–П3):
\[x_{23} = \min(10, 20) = 10\]С2 исчерпан, П3 осталось $20 - 10 = 10$.
Итерация 6. Единственная доступная клетка — $c_{13} = 8$ (С1–П3):
\[x_{13} = \min(10, 10) = 10\]Все запасы распределены, весь спрос удовлетворён.
Итоговый опорный план
| С \ П | П1 | П2 | П3 | П4 | Запас |
|---|---|---|---|---|---|
| С1 | 40 | — | 10 | — | 50 |
| С2 | — | 50 | 10 | — | 60 |
| С3 | — | — | 40 | 50 | 90 |
| Спрос | 40 | 50 | 60 | 50 | 200 |
Проверка вырожденности: занятых клеток 6 = $m + n - 1 = 3 + 4 - 1 = 6$ — план невырожденный.
Затраты опорного плана:
\[F_0 = 40 \cdot 2 + 10 \cdot 8 + 50 \cdot 3 + 10 \cdot 6 + 40 \cdot 4 + 50 \cdot 2 = 80 + 80 + 150 + 60 + 160 + 100 = 630\ \text{руб.}\]Справка. Для сравнения: метод северо-западного угла на тех же данных даёт план $x = {40, 10, 40, 20, 40, 50}$ (по клеткам С1П1, С1П2, С2П2, С2П3, С3П3, С3П4) с затратами $80 + 40 + 120 + 120 + 160 + 100 = 620$ руб. — случайно совпавшими с оптимумом. Это иллюстрирует важный принцип: начальный план может оказаться любым по качеству; только проверка методом потенциалов доказывает оптимальность.
Метод потенциалов
Теоретическая основа метода
Метод потенциалов — применение условия оптимальности двойственной задачи ЛП к транспортной задаче. Каждому поставщику $i$ сопоставляется потенциал $u_i$, каждому потребителю $j$ — потенциал $v_j$.
Условие оптимальности (теорема): опорный план оптимален тогда и только тогда, когда существуют потенциалы, удовлетворяющие системе:
- для базисных клеток: $u_i + v_j = C_{ij}$;
- для свободных клеток: $\Delta_{ij} = C_{ij} - (u_i + v_j) \geq 0$.
Алгоритм проверки оптимальности
Шаг 1. Назначить потенциалы $u_i$ и $v_j$ так, чтобы для всех базисных клеток выполнялось $u_i + v_j = C_{ij}$ (система из $m + n - 1$ уравнений с $m + n$ неизвестными — одно значение задаётся произвольно).
Шаг 2. Принять $u_1 = 0$ и последовательно вычислить остальные потенциалы через базисные клетки.
Шаг 3. Вычислить оценки свободных клеток:
\[\Delta_{ij} = C_{ij} - (u_i + v_j)\]Шаг 4. Проверить оптимальность:
- если все $\Delta_{ij} \geq 0$ — план оптимален;
- если есть $\Delta_{ij} < 0$ — план можно улучшить; выбирается клетка с наиболее отрицательной оценкой.
Шаг 5. Для улучшающей клетки построить цикл перераспределения — замкнутую ломаную из горизонтальных и вертикальных отрезков, вершины которой лежат в базисных клетках (плюс вводимая клетка). Знаки в вершинах цикла чередуются: «+» во вводимой клетке, далее поочерёдно «−» и «+».
| Шаг 6. Найти $\theta = \min{x_{ij}\ | \ (i,j)\ \text{со знаком «−»}}$ и пересчитать план: $x_{ij} + \theta$ в плюсовых клетках, $x_{ij} - \theta$ в минусовых. Одна из минусовых клеток освобождается (становится свободной). |
Шаг 7. Вернуться к шагу 1 до достижения оптимальности.
Итерация 1: проверка плана ММЕ
Расставим потенциалы по базисным клеткам плана $F_0 = 630$: $x_{11} = 40$, $x_{13} = 10$, $x_{22} = 50$, $x_{23} = 10$, $x_{33} = 40$, $x_{34} = 50$.
- Задаём $u_1 = 0$.
- Из клетки С1–П1 ($x_{11} = 40$): $v_1 = c_{11} - u_1 = 2 - 0 = 2$.
- Из клетки С1–П3 ($x_{13} = 10$): $v_3 = c_{13} - u_1 = 8 - 0 = 8$.
- Из клетки С2–П2 ($x_{22} = 50$): нужно $u_2$ — получим из С2–П3.
- Из клетки С2–П3 ($x_{23} = 10$): $u_2 = c_{23} - v_3 = 6 - 8 = -2$; тогда $v_2 = c_{22} - u_2 = 3 - (-2) = 5$.
- Из клетки С3–П3 ($x_{33} = 40$): $u_3 = c_{33} - v_3 = 4 - 8 = -4$.
- Из клетки С3–П4 ($x_{34} = 50$): $v_4 = c_{34} - u_3 = 2 - (-4) = 6$.
Таблица потенциалов (в клетках — тариф, под ним в скобках — объём; «Δ» — оценки свободных):
| С \ П | П1 ($v_1 = 2$) | П2 ($v_2 = 5$) | П3 ($v_3 = 8$) | П4 ($v_4 = 6$) | $u_i$ |
|---|---|---|---|---|---|
| С1 | 2 (40) | 4 Δ=−1 | 8 (10) | 7 Δ=+1 | 0 |
| С2 | 5 Δ=+5 | 3 (50) | 6 (10) | 9 Δ=+5 | −2 |
| С3 | 8 Δ=+10 | 7 Δ=+6 | 4 (40) | 2 (50) | −4 |
Расчёт оценок свободных клеток:
- $\Delta_{12} = 4 - (0 + 5) = -1 < 0$ — план не оптимален;
- $\Delta_{14} = 7 - (0 + 6) = +1$;
- $\Delta_{21} = 5 - (-2 + 2) = +5$;
- $\Delta_{24} = 9 - (-2 + 6) = +5$;
- $\Delta_{31} = 8 - (-4 + 2) = +10$;
- $\Delta_{32} = 7 - (-4 + 5) = +6$.
Улучшающая клетка — С1–П2 ($\Delta_{12} = -1$).
Перераспределение по циклу
Строим цикл через вводимую клетку С1П2 и базисные клетки:
\[С1П2\ (+) \to С1П3\ (-) \to С2П3\ (+) \to С2П2\ (-) \to С1П2\](движение: по строке С1 до базисной С1П3, по столбцу П3 до базисной С2П3, по строке С2 до базисной С2П2, по столбцу П2 обратно в С1П2).
Шаг 1. Определяем θ по минусовым клеткам: $\theta = \min(x_{13}, x_{22}) = \min(10, 50) = 10$.
Шаг 2. Пересчитываем план:
| Клетка | Знак | Было | Стало |
|---|---|---|---|
| С1П2 | + | — | 10 |
| С1П3 | − | 10 | 0 (освобождается) |
| С2П3 | + | 10 | 20 |
| С2П2 | − | 50 | 40 |
Новый план: $x_{11} = 40$, $x_{12} = 10$, $x_{22} = 40$, $x_{23} = 20$, $x_{33} = 40$, $x_{34} = 50$ (базисных клеток снова 6).
Новые затраты:
\[F_1 = 40 \cdot 2 + 10 \cdot 4 + 40 \cdot 3 + 20 \cdot 6 + 40 \cdot 4 + 50 \cdot 2 = 80 + 40 + 120 + 120 + 160 + 100 = 620\ \text{руб.}\]| Улучшение: $630 - 620 = 10$ руб. — ровно $\theta \cdot | \Delta_{12} | = 10 \cdot 1$, что подтверждает смысл оценки $\Delta_{ij}$: она показывает, на сколько рублей изменятся затраты при перевозке одной единицы по этой клетке. |
Итерация 2: проверка улучшенного плана
Расставляем потенциалы заново по новому базису. Пусть $u_1 = 0$:
- С1П1: $v_1 = 2 - 0 = 2$.
- С1П2: $v_2 = 4 - 0 = 4$.
- С2П2: $u_2 = 3 - 4 = -1$.
- С2П3: $v_3 = 6 - (-1) = 7$.
- С3П3: $u_3 = 4 - 7 = -3$.
- С3П4: $v_4 = 2 - (-3) = 5$.
| С \ П | П1 ($v_1 = 2$) | П2 ($v_2 = 4$) | П3 ($v_3 = 7$) | П4 ($v_4 = 5$) | $u_i$ |
|---|---|---|---|---|---|
| С1 | 2 (40) | 4 (10) | 8 Δ=+1 | 7 Δ=+2 | 0 |
| С2 | 5 Δ=+4 | 3 (40) | 6 (20) | 9 Δ=+5 | −1 |
| С3 | 8 Δ=+9 | 7 Δ=+6 | 4 (40) | 2 (50) | −3 |
Оценки свободных клеток: $\Delta_{13} = +1$, $\Delta_{14} = +2$, $\Delta_{21} = +4$, $\Delta_{24} = +5$, $\Delta_{31} = +9$, $\Delta_{32} = +6$ — все Δ ≥ 0, план оптимален.
Оптимальный план и затраты:
\[F^* = 620\ \text{руб.}, \quad x^* = \begin{pmatrix} 40 & 10 & 0 & 0 \\ 0 & 40 & 20 & 0 \\ 0 & 0 & 40 & 50 \end{pmatrix}\]Сводка итераций:
| Итерация | План (базисные клетки) | Затраты, руб. | Минимальная Δ | Статус |
|---|---|---|---|---|
| 0 (ММЕ) | 40/10/50/10/40/50 | 630 | −1 (С1П2) | Не оптимален |
| 1 | 40/10/40/20/40/50 | 620 | +1 | Оптимален |
Экономическая интерпретация потенциалов
Потенциалы имеют содержательный смысл условных (теневых) цен:
- $v_j$ — «цена доставки» единицы груза потребителю $j$ при оптимальном плане;
- $u_i$ — «цена отгрузки» с пункта $i$;
- $\Delta_{ij} \geq 0$ означает: перевозка по маршруту $(i, j)$ невыгодна — удорожание на $\Delta_{ij}$ руб./ед. по сравнению с используемыми маршрутами;
- $\Delta_{ij} = 0$ в свободной клетке — признак альтернативного оптимума: существует второй оптимальный план с теми же затратами (задача имеет несколько равноценных решений — полезно при выборе маршрута по дополнительным критериям, например надёжности).
---
config:
look: handDrawn
theme: neutral
---
flowchart TD
A[Проверка баланса<br/>ΣA = ΣB?] -->|нет| B[Ввести фиктивного<br/>поставщика / потребителя]
A -->|да| C[Построить опорный план<br/>метод минимального элемента]
B --> C
C --> D[Проверить вырожденность:<br/>занятых клеток = m+n−1?]
D -->|меньше| E[Добавить нулевую<br/>базисную клетку]
D -->|да| F[Расставить потенциалы<br/>u₁ = 0, uᵢ+vⱼ=cᵢⱼ]
E --> F
F --> G[Вычислить Δᵢⱼ свободных клеток]
G --> H{Все Δᵢⱼ ≥ 0?}
H -->|да| I[План оптимален<br/>F* — минимальные затраты]
H -->|нет| J[Выбрать клетку<br/>с min Δᵢⱼ < 0]
J --> K[Построить цикл,<br/>найти θ, пересчитать план]
K --> F
style H fill:#fff9c4,stroke:#333,stroke-width:3px
style I fill:#c8e6c9,stroke:#333,stroke-width:2px
Инструменты решения
Excel («Поиск решения»)
Настройка (по методике Шадриной Н. И.):
- Создать таблицу перевозок: блок ячеек $x_{ij}$ (искомые), рядом — матрица $C_{ij}$, по строкам и столбцам — суммы.
- Формула целевой функции:
=СУММПРОИЗВ(матрица_перевозок; матрица_стоимостей). - Ограничения:
- Сумма по строкам ≤ запасы (в закрытой модели — = запасы);
- Сумма по столбцам ≥ спрос (= спрос);
- $x_{ij} \geq 0$.
- Запустить «Поиск решения»: метод Симплекс ЛП (Simplex LP), целевая ячейка — минимум.
- В параметрах solver’а убедиться, что переменные не ограничены целочисленностью (транспортная задача сама даёт целочисленный ответ при целых данных).
Типовая ошибка: выбор метода ОПГ (GRG Nonlinear) вместо «Симплекс ЛП» — задача линейная, нелинейный решатель может остановиться в локальной точке или выдать предупреждение о нелинейности.
Python (Google OR-Tools)
from ortools.linear_solver import pywraplp
# Создание решателя
solver = pywraplp.Solver('Transport', pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
# Данные задачи 3x4 из примера лекции
costs = [[2, 4, 8, 7],
[5, 3, 6, 9],
[8, 7, 4, 2]]
supply = [50, 60, 90]
demand = [40, 50, 60, 50]
m, n = len(supply), len(demand)
# Переменные решения
x = {}
for i in range(m):
for j in range(n):
x[i, j] = solver.NumVar(0, solver.infinity(), f'x[{i},{j}]')
# Целевая функция: min sum C_ij * x_ij
solver.Minimize(solver.Sum(
costs[i][j] * x[i, j] for i in range(m) for j in range(n)))
# Ограничения по запасам: sum_j x_ij = A_i
for i in range(m):
solver.Add(solver.Sum(x[i, j] for j in range(n)) == supply[i])
# Ограничения по спросу: sum_i x_ij = B_j
for j in range(n):
solver.Add(solver.Sum(x[i, j] for i in range(m)) == demand[j])
# Решение
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
print(f'Минимальные затраты: {solver.Objective().Value():.0f} руб.')
for i in range(m):
for j in range(n):
if x[i, j].solution_value() > 0:
print(f' С{i+1} -> П{j+1}: {x[i, j].solution_value():.0f} ед.')
# Вывод: затраты 620 руб.; план совпадает с ручным решением
Для больших задач предпочтительна специализированная постановка min-cost flow (ortools.graph.python.min_cost_flow) — она решает транспортную задачу на порядки быстрее общего ЛП-решателя.
Python (PuLP)
from pulp import (LpProblem, LpMinimize, LpVariable, LpStatus,
lpSum, value)
costs = [[2, 4, 8, 7], [5, 3, 6, 9], [8, 7, 4, 2]]
supply = [50, 60, 90]
demand = [40, 50, 60, 50]
m, n = len(supply), len(demand)
# Модель
model = LpProblem('Transport', LpMinimize)
# Переменные
x = {(i, j): LpVariable(f'x_{i}_{j}', lowBound=0)
for i in range(m) for j in range(n)}
# Целевая функция
model += lpSum(costs[i][j] * x[(i, j)]
for i in range(m) for j in range(n))
# Ограничения баланса
for i in range(m):
model += lpSum(x[(i, j)] for j in range(n)) == supply[i]
for j in range(n):
model += lpSum(x[(i, j)] for i in range(m)) == demand[j]
# Решение (по умолчанию CBC)
model.solve()
print('Статус:', LpStatus[model.status])
print('Затраты:', value(model.objective))
Python (SciPy: linprog)
Для быстрой верификации без установки OR-Tools подойдёт встроенный в SciPy решатель HiGHS:
import numpy as np
from scipy.optimize import linprog
C = np.array([[2, 4, 8, 7], [5, 3, 6, 9], [8, 7, 4, 2]])
a, b = np.array([50, 60, 90]), np.array([40, 50, 60, 50])
m, n = C.shape
# Переменные упорядочены по строкам: x11..x14, x21..x24, x31..x34
res = linprog(
c=C.flatten(), # коэффициенты целевой функции
A_eq=np.vstack([ # матрица равенств баланса
np.kron(np.eye(m), np.ones((1, n))), # по строкам (запасы)
np.kron(np.ones((1, m)), np.eye(n)), # по столбцам (спрос)
]),
b_eq=np.concatenate([a, b])[:-1], # последнее равенство избыточно
bounds=(0, None),
)
print('Оптимум:', res.fun) # 620.0
print('План:\n', res.x.reshape(m, n))
Верификация ручного решения
Три независимых инструмента (ручной метод потенциалов, OR-Tools, SciPy HiGHS) дали одинаковый результат: 620 руб. Совпадение решений — обязательный контроль качества: в ручных расчётах типичны арифметические ошибки при расстановке потенциалов и поиске θ.
Транспортная задача большой размерности
Проблемы большой размерности
При большом количестве поставщиков и потребителей:
- экспоненциальный рост числа переменных ($m \cdot n$);
- длительное время решения ручными методами (неприменимы);
- проблемы с памятью при плотной матрице тарифов;
- трудность верификации результата.
Пример масштаба сетевой компании:
- 100 поставщиков × 500 потребителей = 50 000 переменных;
- 100 + 500 = 600 ограничений;
- ручной метод потенциалов: нереализуем; Excel Solver: на пределе (лимит ~200 переменных в бесплатной версии); OR-Tools: решение за доли секунды.
Методы решения
1. Декомпозиция
- Разбиение на подзадачи меньшего размера (по регионам, продуктовым группам).
- Последовательное решение с координацией (итеративная схема).
2. Специализированные алгоритмы
- Min-cost flow — потоковые алгоритмы (successive shortest paths, network simplex): учитывают специальную структуру задачи, на порядки быстрее общего ЛП.
- Network simplex — симплекс-метод на сети, стандарт для промышленных задач.
3. Приближённые алгоритмы (при усложнении постановки)
- Жадные алгоритмы и эвристики.
- Генетические алгоритмы, метод роя частиц — для задач с дополнительными нелинейными ограничениями (например, маршрутизация с окнами времени).
4. Специализированные решатели
- Gurobi, CPLEX — коммерческие (лидеры по скорости на сверхбольших задачах);
- Google OR-Tools, CBC, HiGHS — открытые (достаточны для задач учебного и большинства практических масштабов).
| Размерность | Рекомендуемый инструмент | Время решения |
|---|---|---|
| До 5×5 | Ручной расчёт (обучение, проверка логики) | Минуты |
| До 50×50 | Excel Solver | Секунды |
| До 1000×1000 | OR-Tools / PuLP (LP) | Секунды |
| Свыше 10 000 переменных | OR-Tools min-cost flow, Gurobi | Секунды–минуты |
| С нелинейными ограничениями | Метаэвристики (генетические алгоритмы) | Минуты–часы |
Учёт ограничений инфраструктуры
Типы ограничений
Пропускная способность маршрутов:
\[x_{ij} \leq Capacity_{ij}\]Ограничения по типу транспорта:
- только определённые маршруты для опасных грузов;
- ограничения по весу/габаритам;
- специальный подвижной состав (термостаты, платформы для крупногабаритной техники).
Временные окна:
- доставка в определённые часы;
- ограничения на ночные перевозки.
Парк подвижного состава:
\[\sum_{j} x_{ij} \leq Fleet_i \cdot Capacity_{vehicle}\]Запрещённые маршруты задаются тарифом $C_{ij} = \infty$ (или большим числом M): такие клетки исключаются из базиса автоматически.
Пример с ограничениями
Дополнительные условия к базовой задаче 3×4:
- Маршрут С1–П3: максимум 80 единиц (ремонт дороги);
- Маршрут С2–П1: минимум 50 единиц (договорные обязательства);
- Маршрут С3–П2 запрещён (нет подъездных путей для тяжёлого транспорта).
Модификация модели (OR-Tools):
# Пропускная способность: x[0,2] <= 80
solver.Add(x[0, 2] <= 80)
# Договорной минимум: x[1,0] >= 50
solver.Add(x[1, 0] >= 50)
# Запрещённый маршрут: фиксация нулём (или Big-M тариф)
solver.Add(x[2, 1] == 0)
Влияние ограничений на решение: каждое дополнительное ограничение сужает допустимое множество и, как правило, увеличивает минимальные затраты (или делает задачу неразрешимой при противоречивых условиях). Разность $F_{огр} - F^*$ — цена ограничения, полезная величина для переговоров: она показывает, сколько стоит ремонт дороги или договорное обязательство.
Многопродуктовая транспортная задача
Если перевозится несколько видов грузов с общей пропускной способностью маршрутов, модель расширяется индексом продукта $k$: переменные $x_{ij}^k$, отдельные балансы по каждому продукту и общие ограничения пропускной способности:
\[\sum_k x_{ij}^k \leq Capacity_{ij}, \quad \sum_j x_{ij}^k = A_i^k, \quad \sum_i x_{ij}^k = B_j^k\]Такая постановка типична для распределения разнородных материалов (электронные компоненты, металлопрокат, кабельная продукция) с одного узла перевозок.
Сравнение Excel и Python
| Критерий | Excel | Python |
|---|---|---|
| Простота использования | Высокая (GUI) | Средняя (требуется код) |
| Размерность задачи | До 200 переменных | До 1 000 000+ переменных |
| Время решения | Секунды–минуты | Секунды для больших задач |
| Ручная верификация | Наглядно (таблица видна) | Требует вывода результата |
| Интеграция | Ограниченная | Полная (API, базы данных) |
| Стоимость | Входит в Office | Бесплатно (OR-Tools, PuLP) |
| Визуализация | Встроенная | Через matplotlib, seaborn |
| Воспроизводимость | Ручные шаги | Скрипт (версионируется в git) |
Рекомендации по выбору
| Ситуация | Инструмент |
|---|---|
| Малые задачи (до 50 переменных), обучение | Excel + ручной расчёт |
| Средние задачи (50–500 переменных) | Excel или Python |
| Большие задачи (500+ переменных) | Python (OR-Tools min-cost flow) |
| Интеграция с ERP/WMS/TMS | Python |
| Быстрый прототип, презентация руководству | Excel |
| Промышленное решение, регулярный пересчёт | Python (автоматизация, CI) |
Применение на машиностроительном предприятии
Транспортные задачи АО «Ракета»
На машиностроительном предприятии — кейсе курса (АО «Ракета», см. лекцию 1.1) транспортная задача возникает на нескольких уровнях:
| Уровень | Поставщики | Потребители | Периодичность решения |
|---|---|---|---|
| Внутризаводской | Склад обеспечения, промежуточные склады цехов | Переделы: микросборка, агрегаты, сборка | Ежедневно/ежесменно |
| Закупочный | Поставщики материалов и электронных компонентов (несколько по каждой позиции) | Склад обеспечения | Ежемесячно (план закупок) |
| Сбытовой | Склад готовой продукции | Заказчики / головной сборочный комплекс | По графику отгрузок государственного контракта |
| Межзаводской | Заводы-смежники по кооперации | Сборочные площадки | По кооперированным поставкам |
Пример внутризаводской постановки. Три склада (обеспечения, цеха микросборки, цеха агрегатов) снабжают четыре участка комплектами электронных компонентов. Тариф — стоимость доставки одной партии электротележкой/автопогрузчиком (включая время в пути и обработку). Решение задачи 3×4 из примера выше показывает: оптимально вывозить с дальнего склада (С3) на дальние участки (П4), а ближайший склад (С1) ориентировать на участок П1 — затраты 620 руб. вместо 630 руб. при «жадном» распределении ММЕ.
Особенности задач промышленного предприятия
| Особенность | Следствие для модели |
|---|---|
| Приоритет государственного контракта | Спрос подразделений, работающих по государственному контракту, — жёсткое равенство; коммерческие заказы — мягкие ограничения |
| Ограничения на маршруты перевозок | Часть маршрутов закрыта (внутризаводские КПП, сопровождение груза) → клетки с $C_{ij} = M$ |
| Спецтранспорт | Ограничения пропускной способности по типам ТС; опасные грузы — только сертифицированные маршруты |
| Прослеживаемость партий | Задача дополняется учётом партий (нельзя смешивать поставки разных поставщиков в одной клетке) |
| Срыв = санкции | Целевая функция может включать не только стоимость, но и штраф за риск срыва (двухкритериальная постановка) |
Связь с лабораторной работой
Материал лекции является теоретической основой лабораторной работы «Оптимизация транспортных потоков» (семестр 2, выполняется вручную и в Python: Google OR-Tools; результаты сверяются с решением в Excel).
| Этап ЛР | Теоретическая база лекции |
|---|---|
| Формализация задачи как транспортной задачи ЛП | Постановка, математическая модель, проверка баланса, открытая/закрытая модель |
| Решение методом минимального элемента (ручной расчёт) | Алгоритм ММЕ, пошаговые таблицы распределения, контроль $m + n - 1$ |
| Проверка оптимальности методом потенциалов | Расстановка потенциалов, оценки $\Delta_{ij}$, цикл перераспределения, θ |
| Реализация в Python (Google OR-Tools) | Примеры кода (pywraplp, min-cost flow), PuLP, SciPy |
| Сравнение результатов с решением в Excel | Таблица сравнения инструментов, верификация тремя способами |
| Анализ устойчивости решения к изменению спроса | Открытая модель с фиктивным участником, альтернативный оптимум ($\Delta_{ij} = 0$) |
Рекомендации по выполнению:
- Начинайте с проверки баланса: $\sum A_i = \sum B_j$; при несовпадении введите фиктивного участника и интерпретируйте его загрузку.
- Вручную дойдите до оптимального плана и зафиксируйте таблицы всех итераций (потенциалы, оценки, циклы, θ) — это обязательная часть отчёта.
- В OR-Tools используйте равенства баланса для закрытой модели; сверьте затраты с ручным решением — расхождение указывает на арифметическую ошибку.
- Для анализа устойчивости уменьшите спрос одного потребителя на 10–20% и пересчитайте: сравните изменение затрат с величиной потенциалов.
- Проверяйте вырожденность: если занятых клеток меньше $m + n - 1$, метод потенциалов даст неполную систему — добавьте нулевую клетку.
Типовые ошибки при выполнении ЛР:
- Потеря клетки при одновременном обнулении строки и столбца (вырожденность не обработана).
- Ошибка знака при расстановке потенциалов ($u_i = c_{ij} - v_j$, а не наоборот).
- Выбор θ по плюсовым клеткам цикла вместо минусовых.
- Сравнение с Excel при разных постановках (в Solver заданы ≤ вместо =).
Ключевые выводы по лекции
-
Транспортная задача минимизирует затраты на перевозки при ограничениях по запасам и спросу; это частный случай ЛП со специальной структурой матрицы ограничений.
-
Математическая модель: целевая функция $min \sum\sum C_{ij} x_{ij}$ + ограничения баланса; закрытая модель требует $\sum A_i = \sum B_j$, открытая балансируется фиктивным участником.
-
Число базисных клеток равно $m + n - 1$; при целых исходных данных оптимум целочисленный автоматически.
-
Метод минимального элемента строит хороший начальный план (в примере 3×4: 630 руб.); метод северо-западного угла — простейший, но без учёта тарифов; качество начального плана гарантирует только проверка.
-
Метод потенциалов проверяет оптимальность: все $\Delta_{ij} \geq 0$; при $\Delta_{ij} < 0$ строится цикл, находится $\theta$, план улучшается (в примере: 630 → 620 руб. за одну итерацию).
-
Экономический смысл оценок: $\Delta_{ij}$ — удорожание перевозки единицы по свободному маршруту; $\Delta_{ij} = 0$ — признак альтернативного оптимума.
-
Инструменты: Excel (Solver, Симплекс ЛП), Python (OR-Tools, PuLP, SciPy); верификация тремя способами обязательна.
-
Большая размерность решается потоковыми алгоритмами (min-cost flow, network simplex) и специализированными решателями (Gurobi, OR-Tools).
-
Ограничения инфраструктуры (пропускная способность, договорные минимумы, запрещённые маршруты) добавляются в модель; их «цена» — разность $F_{огр} - F^*$.
-
На машиностроительном предприятии модель дополняется приоритетом государственного контракта, ограничениями на маршруты перевозок и прослеживаемостью партий.
Контрольные вопросы
- Дайте определение транспортной задачи.
- Запишите математическую модель транспортной задачи.
- Опишите алгоритм метода минимального элемента.
- Как проверяется оптимальность плана методом потенциалов?
- Какие инструменты используются для решения транспортных задач?
Рекомендуемая литература
Основная:
- Шадрина Н. И. Решение задач оптимизации в Microsoft Excel 2010: учеб. пособие. — Хабаровск: Изд-во ТОГУ, 2016.
- Google OR-Tools: документация. — URL: https://developers.google.com/optimization
Дополнительная:
- Рахмангулов А. Н. Методологические основы организации функционирования ж.-д. промышленных транспортно-технологических систем: автореф. дис. — Москва, 2013.
Полный каталог и содержание источников — в обзоре литературы.