Лекция 2_08: Сетевые графики. Критический путь
Задача о пути максимального веса
Сначала мы рассмотрим одну экстремальную задачу, очень похожую на задачи
прошлой лекции, а затем обсудим, для чего эти задачи нужны.
Пусть задан граф <M,N> , в котором выделены две вершины,
iB и iE .
Будем предполагать, что в этом графе нет контуров и что любая дуга лежит на каком-нибудь
пути из iB в iE .
Пусть каждой дуге j О N
сопоставлено неотрицательное число время выполнения этой дуги.
t[j] .
Временем выполнения пути будет называться сумма времен дуг,
входящих в этот путь. Требуется найти путь с наибольшим временем выполнения.
Для решения этой задачи можно использовать метод, похожий на метод Дейкстры.
Мы определяем и пересчитываем вектор τ[M]
максимальных времен выполнения путей до каждой вершины. Естественно, что
начальные значения должны приниматься нулевыми, а значение в вершине
пересчитывается, если предложено значение выше имеющегося.
Более существенно отличие от метода Дейкстры в способе, которым выбирается вершина,
переводимая из множества M1
в множество M0 .
Именно, считаются вычисленными расстояния до тех вершин, для которых просмотрены
все входящие в них дуги.
|
Поиск максимального пути
Итак, как в методе Дейкстры, разобьем множество вершин на три подмножества
M = M0
∪ M1 ∪ M2,
где
M0 — множество обработанных вершин,
M1 — множество необработанных вершин,
в которых τ[i] вычислено окончательно,
M2 — множество вершин,
в которых возможны изменения.
Первоначально множество M0 пусто,
M1 состоит
из начальной вершины со значением τ=0 , остальные вершины находятся
в M2 .
В подготовку вычислений входит вычисление количества дуг, входящих в каждую вершину.
Для хранения этих данных мы используем массив Count[M] , который
заполняется двумя простыми циклами. Именно эти счетчики используются при решении,
какие вершины нужно переводить в множество M1
for i in M do Count[i] := 0 od;
for j in N do Count[iEnd[j]] +:= 1 od;
Вычислительный процесс представляет собой цикл, который продолжается до тех пор,
пока не исчерпается множество M1 (на каждой итерации из него
одна вершина убирается, но множество может и пополняться), либо
пока требуемая нам вершина не попадет в множество M0 .
bContinue := TRUE;
while bContinue do
GET_AND_TREATE_A_VERTEX;
bContinue := IS_NONEMPTY_M1;
od;
Выбор вершины в множестве M1 здесь очень прост.
GET_AND_TREATE_A_VERTEX ≡
i0 := FIRST_VERTEX_IN_M1;
MOVE_FROM_M1_TO_M0(i0);
SCAN_ARCS_EXITING_FROM(i0);
Берется первая вершина в цепном списке
и переводится в множество M0 — это просто.
Выполняется цикл просмотра дуг, выходящих из вершины i0 .
SCAN_ARCS_EXITING_FROM(i0) ≡
for j in EXIT_ARCS(i0) do
TREATE_ARC(j)
od;
Обработка дуг несколько отличается от того, что было раньше.
TREATE_ARC(j) ≡
iE := iEnd(j); τ1 := τ[i0]+w[j]; Count[iE] -:= 1;
if τ[iE] < τ1 then UPDATE(iE,τ1,j) fi;
if Count[iE] = 0 then MOVE_FROM_M2_TO_M1(iE) fi;
Поясним, что здесь делается. Получив номер дуги j , мы фиксируем
ее параметры и уменьшаем на единицу счетчик конца дуги.
Если нужно, увеличиваем значение .
Если у вершины iE обработаны все дуги, переводим ее в
множество M1 .
Элементы этого множества могут обрабатываться в любом порядке,
и нам проще всего устроить цепной список со стековой дисциплиной.
Алгоритм очень простой. Можно было бы вести вычисления, начиная не с начальной вершины
графа, а с конечной. Сейчас мы посмотрим. где применяется эта задача.
|
Графы и организация производства
Сначала немного истории.
В начале XX века в Соединенных Штатах Америки появился интерес к
научной организации труда , направлению, которое связывается с именем
американского инженера Фредерика Тейлора. Одним из сторонников Тейлора был изображенный
на снимке слева Генри Гант (1861—1919) . он предложил простое и
эффективное средство визуализации расписаний, известное как
ленточная диаграмма .
В случаях, когда требуется аналозировать совместную работу нескольких исполнителей
над отдельными заданиями, Гант предложил изображать периоды занятости исполнителей
задачами на календарных осях. Здесь каждому исполнителю соответствует своя
горизонтальная лента, а каждое задание занимает на этих осях отрезки,
соответствующие запланированным периодам, когда данный исполнитель должен выполнять
данное задание.
Пример такой диаграммы я сделал по мотивам книги Б.Ю.Левита «Диаграммы Excel в
экономических моделях». Как видите,
ленточные диаграммы Ганта популярны до сих пор. К сожалению, моя диаграмма оказалось
не так красива, как у автора.
В середине XX века проектные разработки чудовищно усложнились, и диаграммы Ганта
утратили для них свою наглядность. Следующим шагом в визуализации контроля над
сложными работами стало использование техники графов.
В этом подходе особое внимание уделялось взамным зависимостям выполняемых работ.
Эти зависимости (не очень хорошо просматриваемые в ленточных диаграммах) влияют на
последовательность выполнения работ и определяют общую продолжительность выполнения
проекта.
Было создано много вариантов такой системы, наиболее известные названия —
это Система PERT (Program Evaluation and Review Technique) , а также
CPM (Critical Path Method) .
Критическим путем в этих методах сетевого планирования
называется путь наибольшей продолжительности, идущий от начала и до конца проекта.
Именно здесь и появляется задача, о которой шла речь в начале лекции.
Сейчас мы обсудим некоторые аспекты построения сетевого графика
— графа, в котором ищется этот критический путь.
|
Сетевой график: «работы-вершины» или «работы-дуги»?
Первоначально мы имеем некоторое множество работ, и задано некоторое отношение
предшествования: для некоторых пар работ поставлено условие: одна из работ должна
быть выполнена раньше другой.
Легко привести пример: Стена в квартире должна быть оштукатурена до того, как она
будет покрашена.
В термин отношение предшествования естественно входит условие
его транзитивности: стена должна быть поставлена до того, как будет оштукатурена,
и, следовательно, до ее окраски.
Казалось бы, мы можем прямо строить граф <M,N> ,
в котором вершинами будут работы, а дугами попарные связи предшествования работ.
Смотрите, как все хорошо видно. У нас есть шесть работ, они разбиты на три этапа.
Работы A и B предшествуют работам C и D, которые в свою очередь предшествуют работе F,
работа E имеет свою особенность, ей предшествует только работа C.
Но далеко не всегда то, что хорошо на маленьком учебном примере, оказывается
удобным в реальном применении. Рассмотрим еще один пример.
Новый пример совсем ненамного больше предыдущего. А этапов в нем даже меньше —
всего два. Все работы разбиты на два этапа, и каждая работа первого этапа предшествует
каждой работе второго. Но, посмотрите на правый рисунок. В нем на одну дугу меньше,
дугу из вершины 2 в вершину D я специально убрал. Контролировать правильность такого
рисунка стало труднее.
В реальных условиях трудности возрастают неизмеримо. Поэтому в модели проекта,
принятой в сетевых графиках используется схема, в которой работы представляются
дугами. Естественно возникает вопрос, чему в этой модели соответствуют вершины.
На рисунке слева изображена модель той же зависимости между 10 работами.
Как видите, все выглядит гораздо привлекательнее. Вершинами этого графа являются начала
и концы этапов. Появилось общее начало и общее завершение.
Что же делать, если первоначально мы никаких этапов не ввели и ввести не могли?
Стандартные руководства по сетевому планированию описывают вершины графа как
события , которые беспомощно определяются
как «начала и концы работ». Рекомендуется просто строить граф, вводя события
по мере надобности.
При этом в случаях, когда из-за
сложных зависимостей построить граф не удается, рекомендуется вводить дополнительные
дуги которые соответствуют фиктивным работам (dummy jobs).
На рисунке справа вы видите граф «работы-дуги», построенный для
первого, самого простого, примера. В нем, при всей его простоте, там понадобилась
фиктивная работа, которая изображена на картинке красным пунктиром.
Сейчас мы рассмотрим принципиальный способ построения сетевого графика, в котором
одновременно получаются и вершины графа и необходимые фиктивные дуги. Нужно
предупредить, что эта модель слишком громоздка для практического применения
— есть программы, которые строят (неизвестно что!) гораздо проще.
|
Построение сетевого графика
Построение сетевой модели начинается с того, что составляется множество
J работ, из которых состоит контролируемый
процесс. При этом опрашиваются специалисты, и они каждой
работе jО J сопоставляют
множество P(j) работ, которые должны быть
выполнены перед ней (именно перед ней, а не после, — это специалисты знают
лучше). Составление этих списков может потребовать уточнения списка работ.
Составители множеств P(j) не в силах
предусмотреть всех предшественников своих работ, они четко должны видеть
непосредственных предшественников, но иногда могут включать в список и более далекие
работы. Для унификации этих данных их нужно транзитивно замкнуть
— здесь этот термин вполне применим, так как строится отношение на
множестве J . Обозначим через
PT(j) транзитивно замкнутое множество
предшественников работы j .
Эти множества очень важны, они определяют для каждой работы условия начала
ее выполнения. Значит, работы с одинаковыми множествами предшествования должны
изображаться дугами, начинающимися в одной и той же вершине. Таким образом, среди
множеств PT(j) нам следует выбрать
различные и как-то их проиндексировать. Получится некоторое множество индексов
K
Полезно привести маленький пример. Рассмотрим приведенную выше модель
с шестью работами. В ней J =
{ A,B,C,D,E,F } .
Очевидно, что множества P(A) и
P(B) пусты,
P(C) = P(D) =
{ A,B } , выберем
P(E) =
{ C } ,
P(F) = P() =
{ A,C,D } .
При транзитивном замыкании получаем
PT(A) и
PT(B) пусты,
PT(C) = PT(D) =
{ A,B } ,
PT(E) =
{ A,B,C } ,
PT(F) =
{A,B,C,D } .
Таким образом, у нас получилось четыре разных множества предшествующих работ.
Обозначим их через bA , bC ,
bE , bF .
Что же касается концов дуг, то они должны быть одинаковы у работ, одинаково
влияющих на другие работы. Например, таковы работы A и
B , а также E и
F , которые ни на что не влияют.
Обозначим эти множества через eA ,
eC ,
eD , eE .
В общем случае эти множества получаются как части разбиения, являющегося
произведением разбиений, соответствующих множествам
PT(j) и их дополнениям
до J .
Теперь на нашем примере пора посмотреть, как собирается наш граф и чего нам еще
недостает.
Нарисовав в виде дуг все работы и их начала и концы, мы видим, что граф у нас
«не собрался» и нужна еще какая-то информация. Замечаем, что у нас
совпадают множества работ, обозначенные как eA
и bC , а также eC
и bE . Что же касается множества
bF , то оно является объединением
eC и eD .
Чтобы показать зависимость каждой работы от предшествующих работ, мы должны
подвести эти работы (прямо или косвенно) к началу данной работы.
Проведем (красным пунктиром) линии, «составляющие» множества
b... из множеств e... .
Получится черновой вариант сетевого графика — такой граф строится всегда.
Теперь нам достаточно убрать дополнительные дуги там, где без них можно обойтись.
Получится граф, изображенный ранее.
|
Использование сетевого графика
Уже само построение сетевого графика является важной организующей процедурой,
при которой проясняется содержание проекта.
Однако, на этом работа с сетевым графиком не кончается. Каждой работе
j , входящей в график сопоставляется время
t[j] , необходимое для выполнения этой работы.
Разумеется, указать это время точно невозможно, используются оценки (замечу, что
специалисты считают это время случайным и часто используют так называемое
бета-распределение (мы такого распределения не проходили!). Но полезна и
приблизительная оценка.
По найденным оценкам строится критический путь от начального события до завершающего
события. Более того, находятся все дуги, входящие в критические пути и в пути,
продолжительность которых близка к максимальной. Эти работы становятся объектом
пристального внимания администрации проекта.
Прежде всего, по такому расчету видно, укладывается ли выполнение проекта
в намеченный срок. Если нет, то может потребоваться изменение последовательности работ
и смена технологии в некоторых частях проекта.
Когда график исполнения проекта составлен окончательно, все время идет
«мониторинг» этого исполнения — вносятся данные о реальных временах
исполнения отдельных работ, об изменении технологических зависимостей и т. д.,
и критические пути постоянно пересчитываются, что совсем не сложно.
Нужно иметь в виду, что сама сетевая модель слишком проста, обычно она усложняется
многими факторами, среди которых самый важный — это ограниченность технических
средств, из-за которой не все запланированные работы могут выполняться одновременно.
Поэтому сетевые графики включаются сейчас в гораздо более сложные компьютерные
системы управления процессами, где они сочетаются с методами так называемых
теории расписаний и теории управления запасами .
|
Рекомендуемые книги
Математических книг по сетевому планированию теперь, похоже уже не пишут.
Вероятно, наиболее математической остается книга С. И. Зуховицкого и И. А. Радчик
«Математические модели сетевого планирования»,
выпущенная издательством Физматлит в 1965 году. Ей чуть-чуть недостает возраста
для попадания в категорию антиквариата.
Справа вы видите обложку совсем новой книги К. Четфилда и Д. Джонсона
«Microsoft Office Project 2007. Шаг за шагом», ЭКОМ Паблишерз, 2007.
Это учебник, выпущенный для фирменных курсов, на которых изучается известный
программный продукт. Другая крайность. Вас учат нажимать кнопки, в частности,
при построении упоминавшейся нами диаграммы Ганта и сетевого графика, но что это
такое вам здесь не объяснят.
|
Экзаменационные вопросы
- Нахождение критического пути.
- Построение сетевого графика.
|
|