Форма входа

Наша реклама

Помогите сайту просмотрите рекламу

Поиск

Календарь

«  Апрель 2024  »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
2930

Наш опрос

Оцените мой сайт
Всего ответов: 122

Статистика


Онлайн всего: 1
Гостей: 1
Пользователей: 0




Четверг, 25.04.2024, 08:20
Приветствую Вас Гость | RSS
Скорая помощь для студентов
Главная | Регистрация | Вход
Лекция 18


Динамическое прогамирование

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

При решении таких задач с помощью динамического программи­рования мы основываемся на принципе оптимальности:

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

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

Для задачи коммивояжера определим

 

 

T( i;  j1, j2, …, jk) =

 

Стоимость оптимального маршрута из i в 1, который проходит через каждый из городов j1,  j2, …, jk  в точности один раз, в любом порядке и не проходит ни через какие другие города.

 

Принцип оптимальности утверждает, что

Т (i; ji, ..., jk) = min {Cijm +T(jm; j1, j2,..., jm-1, jm+1, …, jk)},                           (4.1)

где, Сij — стоимость прямого переезда из города i в город j. Далее, по определению мы имеем,

T(i; j)=Сijj1.                                                                                       (4.2)

Мы заинтересованы в вычислении Т (1; 2, 3, ..., n) и нахожде­нии маршрута такой длины. Соотношения (4.1) и (4.2) определяют рекурсивную процедуру вычисления Т(1, 2, 3, ..., п); последо­вательность значений, получаемых при рекурсивном применении равенства (4.1), дает оптимальный маршрут. Для n=5 последова­тельность рекурсивных обращений показана в виде дерева на рис. 4.11.

Обратите внимание на то, что здесь присутствует значительное дублирование в листьях; для больших значений п встречаются деревья большей высоты, с дублированием на более высоких уров­нях дерева. Чем выше в дереве появляются дублирования, тем они дороже. При рекурсивном вычислении дерева в глубину (см. разд. 4.1.4) трудно распознать идентичные поддеревья и преду­предить дублирующие вычисления. Используя принципы склеива­ния ветвей и переупорядочивания поиска, мы организуем вычисле­ния снизу вверх, уровень за уровнем. Так как значения Т на одном уровне зависят от значений Т на ближайшем снизу уровне, мы можем начинать с листьев (уровень с номером п—2), значения ко­торых мы знаем из равенства (4.2), и производить обработку по направлению вверх к корню (уровень с номером 0), уровень за уровнем. Конечно, этот подход требует большей памяти, чем поиск в глубину. Если для каждого отдельного узла дерева мы использу­ем одно слово памяти, то всего слов памяти потребуется

Такое относительно большое требование к памяти типично для та­кого поуровневого применения динамического программирования.

Число сложений, требуемых для вычисления (4.1) и (4.2), равно 1 для каждого листа, 2 для каждого узла, чьи сыновья являются листьями, 3 для каждого узла, чьи внуки являются листьями, и т. д., т. е. п — i—1 сложений для каждого узла на уровне с номером i, а всего сложений будет

Число сравнений почти то же самое, что и число сложений, а именно n-i-2 для каждого узла изуровня сномером i; таким образом, общее число сравнений равно

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

К сожалению, применение принципа оптимальности и динами­ческого программирования к задаче коммивояжера не уменьшает существенно времени вычисления; оно только реорганизует его. Однако для других задач принцип оптимальности может резко уменьшить объем поиска, и поэтому динамическое программиро­вание может существенно сократить время вычисления. Пример такого сокращения мы увидим в алгоритме построения оптимальных деревьев бинарного поиска, в котором время вычисления уменьшается с величины, пропорцио­нальной 4n/n3/2, если пользоваться очевидным исчерпывающим ал­горитмом, до О(n3) при подходе с позиций динамического про­граммирования; улучшение действительно существенное.

Построение оптимальных деревьев бинарного поиска

В качестве примера применения алгоритма динамического программирования рассмотрим Алгоритм построения таблицы Гильберта-Мура при поиске оптимальных деревьев бинарного поиска [http://www.neuroproject.ru/papers.htm].

Бинарный поиск в последовательно распределенной таблице обеспечивает очень быстрое нахождение имен, которые являются средними точками на раннем этапе процесса деления пополам, именно имен, близких к вершине дерева T(l, n). Таким образом, любое имя в таблице можно выбрать примерно за lg n сравнений. На практике в большинстве таблиц встречаются имена, к которым обращаются гораздо чаще, чем к другим, и "привилегированные" места в таблице разумно постараться использовать для наиболее часто вызываемых имен, а не для имен, а не для имен, выбранных для этих мест в результате бинарного поиска. Это невозможно осуществить для последовательно распределенных таблиц, поскольку место имени определяется его положением относительно естественного порядка имен в таблице. Введем структуру данных, легко приспосабливаемую как к методу бинарного поиска, так и к возможности выделять точки, в которых таблица делится на две части.

Упорядоченным деревом называется ориентированное дерево, для которого определен порядок сыновей любой вершины дерева. Обычно мы изображаем упорядоченное дерево так, что корень размещается вверху, а сыновья каждой вершины расположены в соответствии с порядком слева направо. Для бинарного упорядоченного дерева поддерево, корень которого является левым сыном вершины v, называется левым поддеревом вершины v. Аналогично определяется правое поддерево вершины v. Пусть A = {a1, a2, …, an} – множество элементов, упорядоченных следующим образом: a1<a2<…<an. Бинарным деревом поиска для множества A является упорядоченное бинарное дерево, в котором каждая вершина v так помечена элементом l(v) множества A, что 1) для каждого u в левом поддереве вершины v, l(u)<l(v); 2) для каждого u в правом поддереве вершины v, l(u)>l(v); 3) для каждого элемента x множества A существует точно одна такая вершина v, что l(v)=x. Предположим A является подмножеством универсума S. Тогда пусть B = { b0, b1, … bn } – такое множество, что 1)  

Расширенным деревом бинарного поиска для A называется дерево бинарного поиска для A с n+1 листьями, представляющими элементы множества B. Отметим, что в расширенном дереве бинарного поиска листья появляются слева направо в порядке b0, b1, …, bn. В дальнейшем будем называть расширенное дерево бинарного поиска для множества A просто деревом бинарного поиска для A.

Пусть дано подмножество A универсума S и дерево T бинарного поиска для A. Множество S может быть множеством всех слов над английским алфавитом, а упорядочение может быть лексикографическим порядком. Предположим, что нам необходимо определить, принадлежит ли элемент

Случай  1.         Корень отсутствует (дерево T бинарного поиска пусто). Следовательно, x не принадлежит A, и поиск завершается безуспешно.

Случай              2. x равен элементу, соответствующему корню. Следовательно, поиск завершается успешно.

Случай 3.         x меньше элемента, соответствующего корню. Поиск продолжается ниже в левом поддереве корня.

Случай 4.         x больше элемента, соответствующего корню. Поиск продолжается ниже в правом поддереве корня. Ясно что успешный поиск завершается во внутренних вершинах, а безуспешный - в листьях дерева T.

Пусть p1, p2, …, pn – частоты обращения к элементам a1, a2, …, an соответственно, и пусть q0, q1, …, qn – частоты, с которыми поиск завершается в листьях T, представляющих b0, b1, …, bn соответственно.

Таким образом, даны неотрицательные веса pi и qi. Необходимо построить дерево бинарного поиска минимальной стоимости для множества A = {a1, a2, …, an}, элементы которого упорядочены следующим образом: a1<a2<…<an. Нам часто будет удобно ссылаться на такое дерево как на оптимальное дерево бинарного поиска для весов q0, p1, q1, p2, …, qn-1, pn, qn. Алгоритм построения оптимального дерева бинарного поиска, который мы сейчас рассмотрим, основан на следующем свойстве таких деревьев:

Пусть T – оптимальное дерево бинарного поиска для весов q0, p1, q1, p2, …, qn-1, pn, qn. Если ak – элемент, соответствующий корню дерева T, то левое поддерево корня дерева T является оптимальным деревом поиска для весов q0, p1, q1, p2, …, pk-1, qk-1, а правое поддерево корня дерева T - оптимальным деревом поиска для весов qk-1, pk, qk, pk+1, …, qn-1, pn, qn. Пусть Tij для

Предположим, что ak – корень дерева Tij(i<j). Тогда, как мы уже видели, левое поддерево с корнем ak является деревом Ti,k-1, которое в свою очередь является оптимальным деревом бинарного поиска для множества { qi, pi+1, …, pk-1, qk-1 }, а правое поддерево с корнем ak является деревом Tkj, которое в свою очередь является оптимальным деревом бинарного поиска для множества { qk, pk+1, …, pj, qj }. Так как глубина вершины в дереве Tij на единицу больше ее глубины в дереве Ti,k-1 или Tkj, то отсюда следует, что

cij = ci,k-1 + wi,k-1 + ckj + wkj + pk = wij + ci,k-1 + ckj.

Ясно, что мы можем найти корень rij дерева Tij, определив величину

Вычислив rij с помощью данного алгоритма, мы можем легко построить дерево T0n, используя следующую процедуру:

r0n – корень дерева T0n. Если r0n=ak, то ak имеет в качестве левого сына r0,k-1, а в качестве правого – rkn.

Рассмотрим внутреннюю вершину am. Если rij=am, то am имеет в качестве левого сына rm,k-1, а в качестве правого – rmn.

Алгоритм Гильберта-Мура

 

Методы решета

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

Методы решета полезны прежде всего в теоретико-числовых вычислениях. Например, одним из наиболее известных методов отыскания простых чисел является «решето Эратосфена». Это реше­то перечисляет составные (не простые) числа между N и N2 для некоторого N так, как показано на рис. 4.12 для случая N==6. Про­сеивание начинается с выписывания всех чисел от N до N2, и затем из них поэтапно удаляются составные числа. Сначала удаляются все числа, кратные двум, затем — все, кратные трем, и т. д. Процесс прекращается после просеивания для наибольшего простого числа, меньшего N.


 

Шаг 0 (исходный)

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

Шаг 1 (исключаются кратные 2)

Остались: 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35

Шаг 2 (исключаются кратные 3)

Остались: 7 11 13 17 19 23 25 29 31 35 

Шаг 3 (исключаются кратные 5)

Остались: 7 11 13 17 19 23 29 31

Рис. 4.12. Решето Эратосфена применяемое для отыскания всех простых чисел между 6 и 36:  7, 11, 13. 17, 19, 23, 29, 31

 

 Легко понять, почему методы решета могут быть полезны. Если в множестве, возможных решений элементы можно удобно занумеро­вать натуральными числами, то хранить нужно только характери­стический вектор (см. разд. 2.2.1); в этом векторе i-й разряд равен нулю, если i-й элемент не является решением, и равен единице в противном случае. Таким образом, на множествах, состоящих буквально из миллионов элементов, возможен поиск без явного порождения и исследования каждого элемента множества. Кроме того, в большинстве вычислительных устройств булевы операции можно производить параллельно над многими разрядами, обеспе­чивая тем самым значительную экономию времени.

Нерекурсивное модульное решето

Решето Эратосфена мы можем интерпретировать как поиск всех чисел между N и N2, которые одновременно являются членами одной из арифметических прогрессий в каждом из следующих множеств:

где р — наибольшее простое число, меньшее или равное N. Тот факт, что число принадлежит прогрессии вида 2k+1, означает, что оно нечетно; факт, что оно принадлежит одной из прогрессий 3k+1 или 3k+2, означает, что оно не является кратным 3, и т. д. Таким образом, между N и N2 простыми являются только те числа, которые удовлетворяют всем этим условиям.

Рассмотрим еще одну средневековую головоломку о женщине и яйцах. По пути на базар, куда женщина несла продавать яйца, ее случайно сбил с ног всадник, в результате чего все яйца разбились. Всадник предложил оплатить убытки и спросил, сколько у нее было яиц. Женщина сказала, что точного числа она не помнит, но когда она брала яйца парами, то оставалось одно яйцо. Одно яйцо остава­лось также, когда она брала сразу по 3, 4, 5 и 6 яиц, но когда она брала сразу по 7 штук, то в остатке ничего не было. Ясно, что она могла бы иметь N яиц, если и только если N одновременно яв­ляется членом каждой из арифметических прогрессий

2k+1,  3k+1,  4k+1,  5k+1,  6k+1 и 7k.

Как могла бы женщина определить все возможные значения числа яиц, меньшие 1000? Для решения этой задачи можно использовать решето, выписывая целые числа 1,..., 1000 и затем удаляя все эле­менты, не принадлежащие различным прогрессиям: сначала все чет­ные числа, потом числа вида 3k или 3k+2 и т. д. Оставшиеся числа и будут возможными решениями.

Продолжение в лекции 19


Copyright MyCorp © 2024