Перейти к основному содержимому

Задача максимального потока

Задача максимального потока заключается в определении наибольшего объема потока, который может быть передан из истока (начального узла) в сток (конечный узел) по направленному графу с ограничениями на пропускную способность дуг.

Каждая дуга графа имеет заданную пропускную способность — неотрицательное значение, определяющее максимальное количество потока, которое может быть передано по ней.

Задача применяется при моделировании и оптимизации транспортных, логистических, коммуникационных и других систем, где необходимо эффективно использовать ограниченные ресурсы для передачи потоков между узлами.

Условия задачи​

В следующем примере логистическому планировщику необходимо найти максимальный поток через транспортную сеть при соблюдении следующих условий:

  • Сеть состоит из узлов, соединенных направленными дугами;
  • Каждая дуга имеет ограниченную пропускную способность;
  • Поток начинается в истоке (узел 0) и заканчивается в стоке (узел 4);
  • Цель - найти максимально возможный поток от истока к стоку.

Дуги графа и их пропускные способности:

  • 0 → 1 (20 ед.)
  • 0 → 2 (30 ед.)
  • 0 → 3 (10 ед.)
  • 1 → 2 (40 ед.)
  • 1 → 4 (30 ед.)
  • 2 → 3 (10 ед.)
  • 2 → 4 (20 ед.)
  • 3 → 2 (5 ед.)
  • 3 → 4 (20 ед.)

Решение задачи​

Далее поэтапно рассмотрим реализацию решения задачи максимального потока.

1. Выбор модели​

Для решения задачи максимального потока мы воспользуемся специализированной моделью. МодельМаксимальногоПотока специально предназначена для решения подобных задач.

2. Создание модели​

Инициализируется объект модели максимального потока.

Модель = О2
.Модели()
.МодельМаксимальногоПотока()
.СоздатьМодель();

3. Ввод данных​

Для решения задачи задаются основные параметры графа: начальные и конечные узлы дуг, а также их пропускные способности.

// Входные данные
УзелИсток = 0;
УзелСток = 4;

// Входные данные дуг (хвост, голова, максимальный поток)
ДанныеДуг = Новый Массив;
ДанныеДуг.Добавить("0, 1, 20");
ДанныеДуг.Добавить("0, 2, 30");
ДанныеДуг.Добавить("0, 3, 10");
ДанныеДуг.Добавить("1, 2, 40");
ДанныеДуг.Добавить("1, 4, 30");
ДанныеДуг.Добавить("2, 3, 10");
ДанныеДуг.Добавить("2, 4, 20");
ДанныеДуг.Добавить("3, 2, 5");
ДанныеДуг.Добавить("3, 4, 20");

// Преобразуем входные данные в числовой формат
Для К = 0 По ДанныеДуг.ВГраница() Цикл
ДанныеДуг[К] = О2.Утилиты().МассивЧиселИзСтроки(ДанныеДуг[К]);
КонецЦикла;

Для преобразования данных в числовой формат мы воспользовались вспомогательной функцией МассивЧиселИзСтроки.

4. Добавление дуг​

Добавим дуги в созданную модель и сохраним их в массиве для дальнейшего вывода результатов.

// Добавляем дуги в модель
Дуги = Новый Массив;
Для К = 0 По ДанныеДуг.ВГраница() Цикл
Дуга = Модель.Дуги().Добавить(ДанныеДуг[К][0], ДанныеДуг[К][1], ДанныеДуг[К][2]);
Дуги.Добавить(Дуга);
КонецЦикла;

5. Установка истока и стока​

Укажем в модели узлы, которые являются истоком и стоком.

// Устанавливаем исток и сток
Модель.Граф().УстановитьИсток(УзелИсток);
Модель.Граф().УстановитьСток(УзелСток);

6. Решение модели​

Для получения решения достаточно вызвать метод Решить объекта модели.

// Запускаем поиск решения
Решение = Модель.Решить();

7. Вывод результатов​

// Вывод результатов
Статус = Решение.Статус();
Если Не Решение.РешениеНайдено() Тогда
Сообщить("Обнаружена проблема с входными данными.");
Сообщить("Статус: " + Статус);
Возврат;
КонецЕсли;

// Выводим максимальный поток
Сообщить("Максимальный поток: " + Строка(Решение.ОптимальныйПоток()));

// Выводим информацию о потоках по дугам
Сообщить("Потоки дуг:");

// Получаем потоки решения для всех дуг
Для Каждого Дуга Из Дуги Цикл
ПотокДуги = Решение.ЗначениеПотока(Дуга);

Сообщить(
СтрШаблон(
"%1 → %2 %3 из %4",
Дуга.Хвост,
Дуга.Голова,
ПотокДуги,
Дуга.МаксимальныйПоток
)
);
КонецЦикла;

Для получения расчетного значения потока мы использовали метод ЗначениеПотока объекта решения.

Полный код решения задачи​

Ниже представлен полный код решения. Вы также можете скачать пример в виде готовой обработки.

// Создаем объект модели
Модель = О2
.Модели()
.МодельМаксимальногоПотока()
.СоздатьМодель();

// Входные данные
УзелИсток = 0;
УзелСток = 4;

// Входные данные дуг (хвост, голова, максимальный поток)
ДанныеДуг = Новый Массив;
ДанныеДуг.Добавить("0, 1, 20");
ДанныеДуг.Добавить("0, 2, 30");
ДанныеДуг.Добавить("0, 3, 10");
ДанныеДуг.Добавить("1, 2, 40");
ДанныеДуг.Добавить("1, 4, 30");
ДанныеДуг.Добавить("2, 3, 10");
ДанныеДуг.Добавить("2, 4, 20");
ДанныеДуг.Добавить("3, 2, 5");
ДанныеДуг.Добавить("3, 4, 20");

// Преобразуем входные данные в числовой формат
Для К = 0 По ДанныеДуг.ВГраница() Цикл
ДанныеДуг[К] = О2.Утилиты().МассивЧиселИзСтроки(ДанныеДуг[К]);
КонецЦикла;

// Добавляем дуги в модель
Дуги = Новый Массив();
Для К = 0 По ДанныеДуг.ВГраница() Цикл
Дуга = Модель.Дуги().Добавить(ДанныеДуг[К][0], ДанныеДуг[К][1], ДанныеДуг[К][2]);
Дуги.Добавить(Дуга);
КонецЦикла;

// Устанавливаем исток и сток
Модель.Граф().УстановитьИсток(УзелИсток);
Модель.Граф().УстановитьСток(УзелСток);

// Запускаем поиск решения
Решение = Модель.Решить();

// Вывод результатов
Статус = Решение.Статус();
Если Не Решение.РешениеНайдено() Тогда
Сообщить("Обнаружена проблема с входными данными.");
Сообщить("Статус: " + Статус);
Возврат;
КонецЕсли;

// Выводим максимальный поток
Сообщить("Максимальный поток: " + Строка(Решение.ОптимальныйПоток()));

// Выводим информацию о потоках по дугам
Сообщить("Потоки дуг:");

// Получаем потоки решения для всех дуг
Для Каждого Дуга Из Дуги Цикл
ПотокДуги = Решение.ЗначениеПотока(Дуга);

Сообщить(
СтрШаблон(
"%1 → %2 %3 из %4",
Дуга.Хвост,
Дуга.Голова,
ПотокДуги,
Дуга.МаксимальныйПоток
)
);
КонецЦикла;
  Скачать пример