Прямолинейное дерево Штейнера: различия между версиями

Перейти к навигации Перейти к поиску
нет описания правки
Нет описания правки
Строка 8: Строка 8:


В силу высокой значимости этой задачи для ее решения было разработано немало алгоритмов, которые можно разбить на два класса: точные и эвристические. Поскольку задача SMT является NP-полной, любой точный алгоритм будет иметь ожидаемое экспоненциальное время исполнения в наихудшем случае. Однако в этой области были достигнуты два значительных улучшения. Одним из них стал алгоритм GeoSteiner в реализации Уорма, Уинтера и Захарисена [14, 15] – самый быстрый на данный момент точный алгоритм для решения этой задачи. Второй алгоритм, схема аппроксимации с полиномиальным временем исполнения (Polynomial Time Approximation Scheme, PTAS) Ароры [1], имеет скорее теоретическую значимость. Поскольку время исполнения точных алгоритмов получается очень долгим, особенно для входных данных большого объема, намного больше внимания было уделено разработке эвристических алгоритмов. Многие из них генерируют дерево Штейнера посредством улучшения топологии [[минимальное остовное дерево|минимального остовного дерева]] (MST) [7], так как было доказано, что MST является 3/2-аппроксимацией SMT [8]. Однако из-за того, что в этих подходах базовые структуры ограничены топологией минимального остовного дерева, степень улучшений по сравнению с ним ограничена. Итерационный алгоритм 1-Steiner Канга и Робинса [10] был одной из первых попыток обойти это ограничение, а его улучшенная реализация [6] стала самой популярной из подобных программ общедоступного класса. Время исполнения этого алгоритма в версии [10] составляет <math>O(n^4 log \; n)</math>, а реализации в [6] – <math>O(n^3) \;</math>. Намного более эффективный алгоритм позднее предложили Бора и коллеги [2]. В их версии остовное дерево итеративно улучшается за счет подключения точки к ребру и последующего удаления самого длинного ребра в получившейся схеме. Время исполнения этого алгоритма в наихудшем случае составляет <math>\Theta(n^2) \;</math>, также была предложена альтернативная реализация с временем <math>O(n \; log \; n)</math>. Поскольку базовые структуры теперь уже не ограничены топологией МОД, эффективность данного подхода сравнялась с эффективностью итеративного алгоритма 1-Steiner [2]. Недавно был предложен новый эвристический алгоритм Мандуи и др. [11], основанный на 3/2-аппроксимации алгоритма вычисления метрического дерева Штейнера на квази-двудольных графах [12]. Он работает несколько лучше итеративного алгоритма 1-Steiner, но слегка уступает этому же алгоритму в случае использования последним проверки на пустые прямоугольники [11]. Недавно Чу [3], а также Чу и Вонг [4] предложили эффективный подход на базе таблицы поиска для построения прямолинейного дерева Штейнера.
В силу высокой значимости этой задачи для ее решения было разработано немало алгоритмов, которые можно разбить на два класса: точные и эвристические. Поскольку задача SMT является NP-полной, любой точный алгоритм будет иметь ожидаемое экспоненциальное время исполнения в наихудшем случае. Однако в этой области были достигнуты два значительных улучшения. Одним из них стал алгоритм GeoSteiner в реализации Уорма, Уинтера и Захарисена [14, 15] – самый быстрый на данный момент точный алгоритм для решения этой задачи. Второй алгоритм, схема аппроксимации с полиномиальным временем исполнения (Polynomial Time Approximation Scheme, PTAS) Ароры [1], имеет скорее теоретическую значимость. Поскольку время исполнения точных алгоритмов получается очень долгим, особенно для входных данных большого объема, намного больше внимания было уделено разработке эвристических алгоритмов. Многие из них генерируют дерево Штейнера посредством улучшения топологии [[минимальное остовное дерево|минимального остовного дерева]] (MST) [7], так как было доказано, что MST является 3/2-аппроксимацией SMT [8]. Однако из-за того, что в этих подходах базовые структуры ограничены топологией минимального остовного дерева, степень улучшений по сравнению с ним ограничена. Итерационный алгоритм 1-Steiner Канга и Робинса [10] был одной из первых попыток обойти это ограничение, а его улучшенная реализация [6] стала самой популярной из подобных программ общедоступного класса. Время исполнения этого алгоритма в версии [10] составляет <math>O(n^4 log \; n)</math>, а реализации в [6] – <math>O(n^3) \;</math>. Намного более эффективный алгоритм позднее предложили Бора и коллеги [2]. В их версии остовное дерево итеративно улучшается за счет подключения точки к ребру и последующего удаления самого длинного ребра в получившейся схеме. Время исполнения этого алгоритма в наихудшем случае составляет <math>\Theta(n^2) \;</math>, также была предложена альтернативная реализация с временем <math>O(n \; log \; n)</math>. Поскольку базовые структуры теперь уже не ограничены топологией МОД, эффективность данного подхода сравнялась с эффективностью итеративного алгоритма 1-Steiner [2]. Недавно был предложен новый эвристический алгоритм Мандуи и др. [11], основанный на 3/2-аппроксимации алгоритма вычисления метрического дерева Штейнера на квази-двудольных графах [12]. Он работает несколько лучше итеративного алгоритма 1-Steiner, но слегка уступает этому же алгоритму в случае использования последним проверки на пустые прямоугольники [11]. Недавно Чу [3], а также Чу и Вонг [4] предложили эффективный подход на базе таблицы поиска для построения прямолинейного дерева Штейнера.
== Основные результаты ==
Представленный алгоритм основан на эвристике подстановки ребер, предложенной Борой и коллегами [2 ]. и работающей следующим образом. Эвристика начинает работу с имеющегося минимального остовного дерева и итеративно рассматривает возможность подключения точки (см. рис. 1) к ближайшему ребру (например, (a, b)) и удаления самого длинного ребра (b, c)) из получившейся схемы. Алгоритм использует [[остовный граф]] [17] как базовую структуру вычисления: вначале он используется для генерации минимального остовного дерева, а затем – пар «точка-ребро» для улучшения этого дерева. Подобная унификация наблюдается также при вычислении остовного дерева и самого длиного ребра для каждой пары «точка-ребро»: эти два вычисления объединяет использование алгоритма Крускала для операций на непересекающихся множествах [5] вместо алгоритма Прима.




Строка 13: Строка 17:


Рисунок 1. Подстановка ребра в алгоритме Боры и др.
Рисунок 1. Подстановка ребра в алгоритме Боры и др.
Для сокращения количества потенциальных пар «точка-ребро» с O(n2) до O(n) Бора и коллеги предложили использовать параметр видимости точки со стороны ребра: только точка, видимая от ребра, может рассматриваться для подключения к нему. Для поиска отношений видимости между точками и ребрами необходим заметающий алгоритм. Чтобы избежать выполнения этого сложного этапа, используется информация о геометрической близости, встроенная в остовный граф. Поскольку у точки имеется восемь ближайших точек, подключенных вблизи нее, то можно заметить: если точка видима от ребра, то она обычно подключена в графе по меньшей мере к одной из конечных точек ребра. Алгоритм использует остовный граф для генерации пар-кандидатов «точка-ребро». Для каждого ребра текущего дерева все точки, являющиеся соседями как минимум одной из конечных точек ребра, будут рассматриваться в качестве потенциальных пар. Поскольку мощность остовного графа составляет O(n), количество возможных пар, сгенерированных таким образом, также укладывается в эту оценку.
При подключении точки к ребру самое длинное ребро получившейся схемы необходимо удалить. Для эффективного поиска соответствующего самого длиного ребра для каждой пары «точка-ребро» используется подход к вычислению остовного дерева при помощи алгоритма Крускала. Этот алгоритм сортирует ребра в порядке неубывания длины и рассматривает поочередно каждое ребро. Если конечные точки ребра были соединены, оно исключается из остовного дерева; в противном случае ребро включается в остовное дерево. Структура операций подключения может быть представлена бинарным деревом, листьями которого являются точки, а внутренними вершинами – ребра. После включения ребра в остовное дерево создается вершина, представляющая ребро, а также два ее потомка, представляющие два компонента, соединенные этим ребром. Пример остовного дерева и представляющего его бинарного дерева приведен на рис. 2. Легко увидеть, что самое длинное ребро между двумя точками является наименьшим общим предком этих двух точек в бинарном дереве. Например, самое длинное ребро между точками p и b на рис. 2 – ребро (b, c), наименьший общий предок p и b в бинарном дереве. Чтобы найти самое длинное ребро в схеме, образованной подключением точки к ребру, необходимо найти самое длинное ребро между этой точкой и той из конечных точек ребра, с которой она находилась в одном компоненте до подключения к ребру. Например, рассмотрим пары из точки p и ребра (a, b). Поскольку p и b принадлежали к одному компоненту до подключения (a, b), самым длинным ребром оказывается ребро между p и b; его и нужно удалить.




Строка 19: Строка 29:
Рисунок 2. Минимальное остовное дерево и его бинарное дерево слияния.
Рисунок 2. Минимальное остовное дерево и его бинарное дерево слияния.


== Основные результаты ==
Представленный алгоритм основан на эвристике подстановки ребер, предложенной Борой и коллегами [ ]. и работающей следующим образом. Эвристика начинает работу с имеющегося минимального остовного дерева и итеративно рассматривает возможность подключения точки (см. рис. 1) к ближайшему ребру (например, (a, b)) и удаления самого длинного ребра (b, c)) из получившейся схемы. Алгоритм использует остовный граф [ ] как базовую структуру вычисления: вначале он используется для генерации минимального остовного дерева, а затем – пар «точка-ребро» для улучшения этого дерева. Подобная унификация наблюдается также при вычислении остовного дерева и самого длиного ребра для каждой пары «точка-ребро»: эти два вычисления объединяет использование алгоритма Крускала для операций на непересекающихся множествах [5] вместо алгоритма Прима.


На основе вышеприведенных рассуждений создан псевдокод алгоритма, представленный на рис. 3. На начальном этапе работы алгоритма для генерации остовного графа G для заданного множества точек используется алгоритм построения прямолинейного остовного графа Чжоу и др [17]. Затем к графу применяется алгоритм Крускала для генерации минимального остовного дерева. Структура данных на основе непересекающихся множеств [ ] используется для слияния компонентов и проверки, принадлежат ли две точки к одному и тому же компоненту (первый цикл for). В процессе выполнения также генерируются бинарное дерево слияния и запросы по поводу наименьших общих предков для всех пар «точка-ребро». Здесь s, s1 и s2 представляют непересекающиеся множества, каждое из которых хранит корень компонента в бинарном дереве слияния. При каждом добавлении дуги (u, v) к T следует рассматривать любого соседа u или v, обозначим его за w, как кандидата на подключение к (u, v). Самое длиное ребро для этой пары будет наименьшим общим предком w и u либо w и v, в зависимости от того, какая точка оказывается в одном компоненте с точкой w. Добавление этого опроса производится при помощи процедуры lca_add_query. Соединение двух компонентов при помощи (u, v) также будет записано в бинарном дереве слияния при помощи процедуры lca_tree_edge. После генерации минимального остовного дерева у нас также имеются соответствующее бинарное дерево слияния и запросы по поводу наименьших общих предков. При помощи оффлайнового алгоритма Тарьяна для нахождения наименьших общих предков [ ] (представленного процедурой lca_answer_queries) можно сгенерировать все самые длинные ребра для пар. При наличии информации о самом длинном ребре для каждой пары «точка-ребро» можно решить задачу подключения точки к ребру. После этого можно осуществить подключения точек к ребрам в порядке невозрастания прироста. Подключение может быть осуществлено только в случае, если ни ребро подключения, ни ребро удаления еще не были удалены.


Для сокращения количества потенциальных пар «точка-ребро» с O(n2) до O(n) Бора и коллеги предложили использовать параметр видимости точки со стороны ребра: только точка, видимая от ребра, может рассматриваться для подключения к нему. Для поиска отношений видимости между точками и ребрами необходим заметающий алгоритм. Чтобы избежать выполнения этого сложного этапа, используется информация о геометрической близости, встроенная в остовный граф. Поскольку у точки имеется восемь ближайших точек, подключенных вблизи нее, то можно заметить: если точка видима от ребра, то она обычно подключена в графе по меньшей мере к одной из конечных точек ребра. Алгоритм использует остовный граф для генерации пар-кандидатов «точка-ребро». Для каждого ребра текущего дерева все точки, являющиеся соседями как минимум одной из конечных точек ребра, будут рассматриваться в качестве потенциальных пар. Поскольку мощность остовного графа составляет O(n), количество возможных пар, сгенерированных таким образом, также укладывается в эту оценку.


 
Большую часть времени исполнения алгоритма занимают генерация остовного графа и сортировка ребер, требующие O(n log n) времени. Поскольку количество ребер в остовном графе составляет O(n), и алгоритм Крускала, и алгоритм Тарьяна для поиска наименьших общих предков занимают O{na{n)) времени, где a{n) – обратная функция Аккермана, растущая исключительно медленно.
При подключении точки к ребру самое длинное ребро получившейся схемы необходимо удалить. Для эффективного поиска соответствующего самого длиного ребра для каждой пары «точка-ребро» используется подход к вычислению остовного дерева при помощи алгоритма Крускала. Этот алгоритм сортирует ребра в порядке неубывания длины и рассматривает поочередно каждое ребро. Если конечные точки ребра были соединены, оно исключается из остовного дерева; в противном случае ребро включается в остовное дерево. Структура операций подключения может быть представлена бинарным деревом, листьями которого являются точки, а внутренними вершинами – ребра. После включения ребра в остовное дерево создается вершина, представляющая ребро, а также два ее потомка, представляющие два компонента, соединенные этим ребром. Пример остовного дерева и представляющего его бинарного дерева приведен на рис. 2. Легко увидеть, что самое длинное ребро между двумя точками является наименьшим общим предком этих двух точек в бинарном дереве. Например, самое длинное ребро между точками p и b на рис. 2 – ребро (b, c), наименьший общий предок p и b в бинарном дереве. Чтобы найти самое длинное ребро в схеме, образованной подключением точки к ребру, необходимо найти самое длинное ребро между этой точкой и той из конечных точек ребра, с которой она находилась в одном компоненте до подключения к ребру. Например, рассмотрим пары из точки p и ребра (a, b). Поскольку p и b принадлежали к одному компоненту до подключения (a, b), самым длинным ребром оказывается ребро между p и b; его и нужно удалить.




Строка 52: Строка 59:


Рисунок 3. Алгоритм построения прямолинейного дерева Штейнера.
Рисунок 3. Алгоритм построения прямолинейного дерева Штейнера.
На основе вышеприведенных рассуждений создан псевдокод алгоритма, представленный на рис. 3. На начальном этапе работы алгоритма для генерации остовного графа G для заданного множества точек используется алгоритм построения прямолинейного остовного графа Чжоу и др [17]. Затем к графу применяется алгоритм Крускала для генерации минимального остовного дерева. Структура данных на основе непересекающихся множеств [ ] используется для слияния компонентов и проверки, принадлежат ли две точки к одному и тому же компоненту (первый цикл for). В процессе выполнения также генерируются бинарное дерево слияния и запросы по поводу наименьших общих предков для всех пар «точка-ребро». Здесь s, s1 и s2 представляют непересекающиеся множества, каждое из которых хранит корень компонента в бинарном дереве слияния. При каждом добавлении дуги (u, v) к T следует рассматривать любого соседа u или v, обозначим его за w, как кандидата на подключение к (u, v). Самое длиное ребро для этой пары будет наименьшим общим предком w и u либо w и v, в зависимости от того, какая точка оказывается в одном компоненте с точкой w. Добавление этого опроса производится при помощи процедуры lca_add_query. Соединение двух компонентов при помощи (u, v) также будет записано в бинарном дереве слияния при помощи процедуры lca_tree_edge. После генерации минимального остовного дерева у нас также имеются соответствующее бинарное дерево слияния и запросы по поводу наименьших общих предков. При помощи оффлайнового алгоритма Тарьяна для нахождения наименьших общих предков [ ] (представленного процедурой lca_answer_queries) можно сгенерировать все самые длинные ребра для пар. При наличии информации о самом длинном ребре для каждой пары «точка-ребро» можно решить задачу подключения точки к ребру. После этого можно осуществить подключения точек к ребрам в порядке невозрастания прироста. Подключение может быть осуществлено только в случае, если ни ребро подключения, ни ребро удаления еще не были удалены.
Большую часть времени исполнения алгоритма занимают генерация остовного графа и сортировка ребер, требующие O(n log n) времени. Поскольку количество ребер в остовном графе составляет O(n), и алгоритм Крускала, и алгоритм Тарьяна для поиска наименьших общих предков занимают O{na{n)) времени, где a{n) – обратная функция Аккермана, растущая исключительно медленно.




4501

правка

Навигация