Дискретные задачи оптимизации в экономике, планировании и управлении. Учебное пособие
.pdf
2 |
3 |
|
|
k |
i |
j |
dij |
|
|
|
|
1 |
1 |
2 |
5 |
|
|
|
|
2 |
1 |
4 |
5 |
|
|
|
|
3 |
1 |
8 |
4 |
|
4 |
5 |
|
4 |
1 |
9 |
2,5 |
|
|
|
|
5 |
2 |
3 |
4 |
|
|
|
|
6 |
3 |
4 |
2 |
|
|
|
|
7 |
3 |
5 |
2,5 |
|
|
|
|
8 |
4 |
5 |
1,5 |
|
6 |
|
7 |
9 |
4 |
6 |
2 |
|
|
|
|
|
|
|
|
|
|
|
|
10 |
5 |
7 |
2,5 |
1 |
8 |
|
|
11 |
6 |
7 |
3 |
|
|
|
|
|
|
|
|
|
|
|
|
12 |
6 |
8 |
1 |
|
|
|
|
|
|
|
|
9 |
10 |
|
|
13 |
7 |
11 |
5 |
|
|
|
|
|
|
||
|
|
|
|
14 |
8 |
10 |
1,5 |
|
|
|
|
|
|
|
|
|
|
|
|
15 |
9 |
10 |
2 |
|
|
|
|
|
|
|
|
|
11 |
|
|
16 |
9 |
11 |
2,5 |
|
|
|
|
17 |
10 |
11 |
1,5 |
|
|
|
|
|
|
|
|
Рис. 2.3. Данные для задачи о кратчайшем остовном дереве
Рассмотрим объем вычислений для обоих методов. Собственно, выбор er для алгоритма Краскала является менее трудоемким. Вес ребра er заведомо больше, чем для всех ребер V(r–1). В самом деле, иначе бы оно было включено в V(r–1) вместо ребра с большим весом, так как его концы принадлежат разным деревьям не только леса T(r–1), но и всех предшествующих. Поэтому для поиска er для всех r достаточно один раз пройти список ребер в порядке весов, проверяя каждый раз лишь принадлежность их концов разным деревьям. В алгоритме Прима нужно каждый раз решать задачу минимизации длины ребра среди всех ребер, концы которых имеют разные пометки, что сложнее.
6
1 |
8 |
9 10
Рис. 2.4. Результат 4 итераций по алгоритму Прима
21
С другой стороны, в алгоритме Прима пометка каждой вершины меняется только один раз, на что требуется линейный относительно m объем вычислений. В алгоритме Краскала некоторые вершины будут менять свои пометки неоднократно. В наихудшем варианте каждое частичное дерево соединяется на итерации с другим, имеющим такое же количество вершин. В точности такая ситуация может иметь место, когда граф имеет m = 2H вершин. Тогда на заключительном этапе объединяются частичные деревья, имеющие по m/2 = 2H–1 вершин, каждое из этих деревьев получается из деревьев, имеющих по m/4 = 2H–2, и т.д. В итоге каждая вершина проходит через H = log2m объединений, всего же изменений принадлежности вершин будет (m/2)log2m.
2 |
3 |
4 |
5 |
|
6 |
7 |
1 |
8 |
|
9 |
10 |
|
11
Рис. 2.5. Результат 4 итераций по алгоритму Краскала
Рассмотрим структуры данных для обоих алгоритмов, обеспечивающих эффективное выполнение. Пометку о принадлежности вершин к V(r) для алгоритма Прима достаточно представить в виде одномерного массива. По номеру вершины, включенной в V(r), осуществляется смена ее пометки.
22
2 |
3 |
4 5
|
6 |
7 |
1 |
8 |
|
9 |
10 |
|
11
Рис. 2.6. Результат 8 итераций по алгоритму Краскала
Для алгоритма Прима ребра могут быть упорядочены в виде АВЛдерева TI по составному показателю xv: количество концов ребра, принадлежащих текущему поддереву n0e, длина, причем по первому атрибуту применяется обратный порядок. Кроме того, должны храниться номера начальной и конечной вершин. В этом случае изменение xv для каждого ребра происходит не более двух раз. Для поддержания упорядоченности нужно при изменении исключить вершину со старым значение из TI и ввести в TI вершину с новым значением, что требует O(log2n) операций. Поиск ребер, для которых xv изменилось при включении в частичное дерево новой вершины, осуществляется по списку инцидентности для этой вершины Ребра, оба конца которых принадлежат остовному дереву, исключаются АВЛ-дерева. Тогда самая левая вершина АВЛ-дерева и указывает на ребро с минимальным значением длины при n0e = 1. Совокупность операций по работе со списком ребер имеет порядок (n + m)log2n, что и составляет львиную долю вычислений.
Для алгоритма Краскала список пометок вершин целесообразно хранить в виде АВЛ-дерева, упорядоченного составному показателю
23
(номер частичного дерева, номер вершины). В целом, с учетом затрат на упорядочение списка ребер по длине, трудоемкость алгоритма можно оценить как O(nlog2n + mlog2m). Учитывая, что n ≤ m2 и, следовательно, log2n ≤ 2log2m, приходим к выводу, что трудоемкость обоих алгоритмов сопоставима.
Вопросы и упражнения
1.Сколько корневых деревьев соответствуют графу в виде простой цепи с 7 вершинами? Изобразите цепь в виде дерева с корнем в средней (четвертой) вершине.
2.На рис. 2.7 показаны 2 корневых дерева. Определить, представляют ли они одно и то же дерево.
4 |
|
|
6 |
|
|
|
|
9 |
|
2 |
|
|
|
|
|
|
5 |
8 |
7 |
3 |
|
|
|
|
|
|
|
3 |
|
1 |
|
|
|
|
|
8 |
|
|
|
|
|
|
1 |
2 |
|
|
|
|
|
|
|
|
|
4 |
|
9 |
|
|
|
7 |
6 |
5 |
|
|
Рис. 2.7.
3. Опишите применение обоих алгоритмов для графа в виде правильного двенадцатиугольника с центром, соединенным с первой, третьей, седьмой и одиннадцатой вершинами. Весом каждого ребра считать его длину.
24
3. МЕТОД ДИНАМИЧЕСКОГО ПРОГРАММИРОВАНИЯ
Мы начинаем изучение метода на примере задачи о замене оборудования, которая, как увидим ниже, по своей форме является частным случаем задачи о кратчайшем (или наиболее быстром) маршруте на транспортной сети, хотя она имеет совершенно другой смысл. В общем же случае рассматривается задача о наиболее эффективном (оптимальном) допустимом переходе через конечное множество возможных промежуточных состояний между заданным начальным и конечным состояниями. Как правило, метод динамического программирования применяется к процессам, для которых показатель эффективности может быть определен для любого пути из начального состояния не только в конечное состояние, но и в любое промежуточное и представляет собой сумму слагаемых для переходов из одного состояния в следующее. Форма и содержание этих слагаемых может быть различной. Применительно к маршрутам на дорожной сети, кроме затрачиваемого времени и, возможно, платы за проезд (отрицательный эффект), может приниматься в расчет положительный эффект от попутного выполнения каких-либо дел, условием которых является прохождение определенных участков. Далее мы будем называть последовательность состояний – от начального до конечного – траекторией процесса.
3.1.Задача о замене оборудования
Вкачестве примера рассмотрим задачу минимизации затрат на приобретение и содержание разъездного автомобиля – частный пример задача о замене оборудования. Предполагается, что в начале периода автомобиль отсутствует, в конце D-го года оставшийся автомобиль продается, полный срок службы автомобиля составляет Tmax,
вначале каждого года возможна продажа имеющегося автомобиля и приобретение другого, как нового, так и подержанного. Требуется минимизировать затраты на приобретение и эксплуатацию автомобилей в течение периода [0, D]. Известно, что годовая эксплуатация автомобиля с возрастом T лет (в начале года) составляет cT, стоимость приобретения автомобиля с возрастом T лет – C1T, а продажи – C2T. Для заданного периода можно определить промежуточные
состояния, определяемые парами (t, T), где t {0 ,... , D – 1},
25
T {0, ..., Tmax-1}. Возможные переходы между ними – из (t, T) – в (t + 1, K), причем затраты ctTK от такого перехода определяются как cT, если K = T + 1, и cT + C2T + 1 – C2K в остальных случаях (если ctTK < 0, имеем доход – ctTK).
Итак, состояние нашей системы задается парой (время, возраст автомобиля в начале года). В каждое конкретное состояние можно перейти из некоторого набора предыдущих, а из начального состояния разными путями, которым соответствуют разные затраты (рис. 3.1).
|
|
0/0 |
|
1/0 |
|
2/0 |
|
3/0 |
|
4/0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0/1 |
|
2/1 |
|
2/1 |
|
3/1 |
|
4/1 |
|
|
Начало |
|
|
|
|
|
|
Конец |
|||||
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0/2 |
|
3/2 |
|
2/2 |
|
3/2 |
|
4/2 |
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0/3 |
|
4/3 |
|
2/3 |
|
3/3 |
|
4/3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 3.1. Граф переходов
Отметим главнейшее обстоятельство: последующие затраты зависят только от состояния, но не от предыдущих затрат. Поэтому наиболее выгодно, чтобы эти затраты в достигнутом состоянии были минимальны. Свяжем с каждым состоянием это минимально возможное значение затрат для его достижения W(t, T). В общем случае такой показатель называется функцией Беллмана. Связь между значениями функции Беллмана для разных состояний называется уравнением Беллмана. Эта связь выражает принцип оптимальности: если траектория до некоторого состояния оптимальна, то оптимальна и траектория до непосредственно предшествующего состояния на той же траектории. Применительно к рассматриваемой задаче уравнение Беллмана будет выглядеть так:
W(0, K) = C1K, |
(3.1) |
W(t, K) = min {W(t – 1, T) + ct–1T |T {0, ..., Tmax - 1}}, t = 1, ..., D – 1. (3.2)
Смысл формального обозначения в формуле (3.2) такой: вычисляется минимум по всевозможным значениям T зависящего от T выражения W(t – 1, T) + ct–1T для конкретного значения t.
Для финального состояния имеем
WF = min{W(D – 1, T) – C2T + 1 + cT |T {0, ..., Tmax – 1}} |
(3.3) |
26
Порядок расчета оптимальной траектории следующий:
1.Определим для K = 0,…, Tmax -1 W(1, K) по формуле (3.1).
2.В цикле по t = 2,..., D определим для K = 0,…, Tmax - 1 W(t, K) по формуле (3.2).
3.Определим WF по формуле (3.3).
4.Определим T(D) из условия
W(D, T(D)) + C2T(D) + 1 + cT(D) = WF. |
(3.4) |
5. В цикле по t = 1, ..., D – 1, ... определим T(t) из условия
W(t, T(t)) + ctT(t)T(t + 1) = W(t + 1, T(t + 1)). |
(3.5) |
Таким образом, поиск оптимальной траектории методом динамического программирования выполняется в две фазы: на первой (переход от начала к концу процесса) определяются значения функции Беллмана на последовательности вершин, в конечном счете – оптимальное значение целевого показателя, на второй (переход от конца процесса к его началу) определяется траектория, дающая это оптимальное значение.
В действительности решать уравнения (3.4), (3.5) не потребуется, если при решении задач (3.2), (3.3) запоминать значения T, на которых достигается минимум.
Трудоемкость вычислений зависит квадратично от размерности процесса, под которым нужно понимать количество возможных состояний для определенного этапа, но линейно от количества этапов. В данной задаче решение нетрудно рассчитать и вручную. Но в более общей задаче размерность процесса может быть очень большой. Если у нас имеется N типов оборудования с максимальным сроком службы D лет для каждого, то размерность составит DN.
Рассмотрим описанный алгоритм на примере. Исходные данные представлены в табл. 3.1.
|
|
|
|
|
Таблица 3.1 |
|
Исходные данные к задаче о замене оборудования |
||||
|
|
|
|
|
|
Возраст |
|
|
Стоимость |
|
|
автомобиля |
|
покупки |
продажи |
|
эксплуатации за год |
0 |
|
800 |
|
|
300 |
1 |
|
600 |
570 |
|
320 |
2 |
|
430 |
410 |
|
360 |
3 |
|
250 |
230 |
|
420 |
4 |
|
|
–10 |
|
|
На основе табл. 3.2 определим матрицу, элементы которой суть ctT.
27
|
|
|
|
|
Таблица 3.2 |
|
Матрица стоимостей переходов |
|
|
||
|
|
|
|
|
|
Возраст автомобиля |
Возраст автомобиля в начале текущего года |
||||
год назад |
0 |
1 |
|
2 |
3 |
0 |
530 |
300 |
|
160 |
–20 |
1 |
710 |
510 |
|
320 |
160 |
2 |
930 |
730 |
|
560 |
360 |
3 |
1230 |
1030 |
|
860 |
680 |
Табл. 3.3 иллюстрирует процесс расчета (D = 5 лет). Поясним ее смысл. Строки, для которых в правом столбце указан номер года, показывают оптимальное значение затрат за указанное количество лет для состояний с определенным возрастом автомобилей. Следующие за ними строки показывают суммарные затраты для случая перехода к началу следующего года в указанное состояние из другого, в котором система находилась год назад. Для последнего года состояние в его начале определяет окончательное значение затрат. Из таблицы видно, что оптимальная траектория оказывается не единственной (одна из них выделена курсивом).
|
|
|
|
|
|
|
Таблица 3.3 |
|
Процесс расчета оптимальной траектории |
|
|||||
|
|
|
|
|
|
|
|
|
Возраст автомобиля |
Возраст автомобиля в начале текущего года |
|||||
Год |
в начале предыдуще- |
0 |
|
1 |
2 |
|
3 |
|
го года |
|
Затраты с начала периода |
|
|||
0 |
– |
800 |
|
600 |
430 |
|
250 |
|
0 |
1330 |
|
1100 |
960 |
|
780 |
|
1 |
1310 |
|
1110 |
920 |
|
760 |
|
2 |
1360 |
|
1160 |
990 |
|
790 |
|
3 |
1480 |
|
1280 |
1110 |
|
930 |
1 |
|
1310 |
|
1100 |
920 |
|
760 |
|
0 |
1840 |
|
1610 |
1470 |
|
1290 |
|
1 |
1810 |
|
1610 |
1420 |
|
1260 |
|
2 |
1850 |
|
1650 |
1480 |
|
1280 |
|
3 |
1990 |
|
1790 |
1620 |
|
1440 |
2 |
|
1810 |
|
1610 |
1420 |
|
1260 |
|
0 |
2340 |
|
2110 |
1970 |
|
1790 |
|
1 |
2320 |
|
2120 |
1930 |
|
1770 |
|
2 |
2350 |
|
2150 |
1980 |
|
1780 |
|
3 |
2490 |
|
2290 |
2120 |
|
1940 |
3 |
|
2320 |
|
2110 |
1930 |
|
1770 |
|
0 |
2850 |
|
2620 |
2480 |
|
2300 |
|
1 |
2820 |
|
2620 |
2430 |
|
2270 |
|
2 |
2860 |
|
2660 |
2490 |
|
2290 |
|
3 |
3000 |
|
2800 |
2630 |
|
2450 |
4 |
|
2820 |
|
2620 |
2430 |
|
2270 |
5 |
|
2550 |
|
2530 |
2560 |
|
2700 |
28
Рассмотренная здесь задача типична для оптимизации динамических процессов в дискретном времени, когда каждое состояние имеет временную привязку. И следовательно, если существует переход из одного состояния в другое, то встречного перехода быть не может. В следующем разделе рассматривается более общий случай, когда для некоторых пар состояний нельзя наперед определить, в какой последовательности они могут быть пройдены. Для типичных задач и в этом случае можно воспользоваться методом динамического программирования, причем порядок расчета уравнений Беллмана определяется спецификой задачи.
3.2. Задача об оптимальном двоичном поисковом дереве
Здесь будут рассмотрены постановка и решение методом динамического программирования задачи совсем иного рода.
Двоичное поисковое дерево – способ представления упорядоченного списка значений, которые можно сравнивать между собой (обычным образом для чисел, лексикографически, т.е. в алфавитном порядке, – для строк). Это корневое дерево, в котором из каждой вершины v исходят не более двух ветвей, одна из которых называется левой, а другая – правой. Поддерево, корень которого – конец левой ветви, называется левым поддеревом для вершины v , соответственно определяется и правое поддерево.
Количество вершин соответствует количеству элементов списка, с каждой вершиной связывается определенное значение. Определяющее требование состоит в том, что для каждой вершины все значения в левом поддереве меньше значения в вершине, а в правом – наоборот, больше. Такая организация обеспечивает эффективный поиск. Искомое значение сравнивается со значением в корне. Если совпадает – поиск закончен, если меньше – переходим к левому поддереву, если больше – к правому и повторяем те же действия. В итоге за количество сравнений, не превышающих высоты дерева плюс 1, либо находим значение, либо устанавливаем его отсутствие. В последнем случае иногда требуется добавить новое значение в дерево.
Сбалансированное поисковое дерево – наиболее эффективный способ организации больших информационных массивов по порядку трудоемкости операций поиска и обновления. Однако при фиксиро-
29
ванном наборе запросов, определяемом набором поисковых строк {a1, ..., aN} и известной их относительной частоте {p1, ..., pN} можно поставить задачу построения дерева, оптимального по средней трудоемкости поисковых операций для этого набора запросов. В таком дереве i-й запрос имеет высоту Hi, соответственно, при предъявлении поисковой строки ai для нахождения информации по запросу нужно выполнить Hi + 1 операций сравнения строк. Средняя относительная трудоемкость составит p1(H1 + 1) + ... + pN(HN + 1) = 1 + p1H1 + ... + pNHN. Последнее слагаемое и нужно минимизировать.
Идея метода решения задачи состоит в следующем. Будем считать, что строки a1, ..., aN лексикографически упорядочены. Пусть с корнем дерева связана строка aI, соответственно, с его левым поддеревом – строки a1, ..., aI – 1, а с правым – aI + 1, …, aN. Преобразуя целевое выражение, получим
pI0 + p1H1 + …+ pI – 1HI – 1 + pI + 1HI + 1 + ... + pNHN =
=(p1 + ... + pI – 1 + pI + 1 + ... + pN) + (p1(H1 – 1) + ... + pI – 1(HI – 1 – 1)) +
+(pI + 1(HI + 1 – 1) + ... + pN(HN – 1)).
Первое слагаемое не зависит от формы левого и правого поддерева, второе – целевое выражение для левого поддерева, а третье – для правого. Поэтому левое поддерево должно быть оптимально для набора запросов {a1, ..., aI – 1}, а правое – для набора запросов {aI + 1, …, aN}. Обозначим величину целевого слагаемого для оптимального поискового дерева с соответствующим набором запросов как POPT(aK, ..., aL, pK, ..., pL), а само дерево TOPT(aK, ..., aL, pK, ..., pL). Таким образом, задача определения оптимального дерева сводится к следующей: определить корень дерева и его оптимальные левое и правое поддерево, так что величина (p1 + ... + pI – 1 + pI + 1 + ... + pN) + + POPT(a1, ..., aI – 1, p1, ..., pI – 1) + POPT(aI + 1, ..., aN, pI + 1, ..., pN) принимает наименьшее значение, которое и есть POPT(a1, ..., aN, p1, ..., pN). При поиске оптимального левого и правого поддеревьев можно применить такие же соображения, и так многократно, пока очередные поддеревья не превратятся в отдельные вершины. Заметим, что при умножении всех величин p1,..., pN на любое положительное число результат не изменится.
В соответствии с идеей метода динамического программирования будем строить эти оптимальные деревья не сверху вниз, а снизу вверх. Для этого придется определять POPT(aK, ..., aL, pK, ..., pL) для
30
