УДК 004.421.2:519.17
С.Д. ПОГОРІЛИЙ, О.О. КАМАРДІНА, Ю.С. КОРДАШ
ПРО ПІДВИЩЕННЯ ШВИДКОДІЇ АЛГОРИТМІВ ФОРМУВАННЯ МІНІМАЛЬНОГО ВКРИВАЮЧОГО ДЕРЕВА______________________________*________________________________________________
Abstract: Prim's and Kruskat’s sequential algorithms are formalized, which regular schemes are built. A method for paralleling is suggested and parallel regular schemes of algorithms are formalized for release on cluster architectures. Key words: RSA, PRSA, equivalent scheme transformation, minimal spanning tree, parallelism, graph.
Анотація: Формалізовано послідовні алгоритми Пріма та Крускала, для яких побудовано регулярні схеми. Запропоновано підхід до розларалелювання та сформовано паралельні регулярні схеми алгоритмів для їх подальшої реалізації на кластерних архітектурах.
Ключові слова: РСА, ПРСА, еквівалентні перетворення схем, мінімальне вкриваюче дерево, паралелізм, граф.
Аннотация: Формализованы последовательные алгоритмы Прима и Крускала, для которых были построены регулярные схемы. Предложен подход к распараллеливанию, и сформулированы параллельные регулярные схемы алгоритмов для их дальнейшей реализации на кластерных архитектурах.
Ключевые слова: РСА, ПРСА, эквивалентные преобразования схем, минимальное покрывающее дерево, параллелизм, граф.
1. Вступ
Існує багато задач, які вирішуються за допомогою багатьох методів теорії графів. Наприклад, задачі визначення шляху з мінімальною вартістю, який поєднує усі вузли графа. До таких задач зводиться проектування телефонних мереж або електронних мікросхем. Мета подібних задач - з’єднання вузлів деякого призначення між собою з мінімальними витратами ресурсів.
Для того, щоб вирішити цю проблему, існують добре відомі алгоритми Пріма, Борувки та Крускала [1, 2] формування мінімального вкриваючого дерева. Метою даної роботи є не тільки вирішення поставленої проблеми, а й удосконалення існуючих алгоритмів за допомогою сучасних технологій. Основною вимогою до будь-яких алгоритмів є час виконання. Особливо це актуально для задач великої розмірності.
Одним із способів зменшення часу виконання є розпаралелювання алгоритму або його частин з метою подальшої реалізації на класгерній архітектурі. Перетворити алгоритм на паралельний можна за допомогою досвіду, інтуїції або апарату еквівалентних перетворювань. У цій роботі буде розглянуто формування регулярних схем алгоритмів (РСА) [3] та отримання паралельних регулярних схем алгоритмів (ПРСА) для алгоритмів Пріма та Крускала й обґрунтування результатів за допомогою апарату еквівалентних перетворень. Для виконання цих перетворень застосовано математичний апарат модифікованих систем алгоритмічних алгебр (САА-М)[4].
Розглянемо послідовні алгоритми та виділимо в них місця, які є найбільш важкими з точки зору обчислення.
ЗО
© Погорілий С.Д., Камардіна О.О., Кордаш Ю.С. , 2005 ISSN 1028-9763. Математичні машини і системи, 2005, №4
ізація послідовних алгоритмів
формалізацію алгоритму Пріма. Вважаємо, що неорієнтований граф представлений суміжності б, розмір якої ¥*¥, де V - кількість вершин у графі. Введемо такі иня: „
С - поточна вершина;
- черга з пріоритетами („бахрома” [1]);
МБТ - мінімальне вкриваюче дерево (дерево М8Т); пгі(С) - функція введення початкової вершини;
С - початкова вершина.
іпіЦС);
у^іііє (кількість ребер в М$Тменше V)
{
Запис у РЯ ребер, які виходять з С та ведуть до недеревних вершин;
К (в РЯ? існують ребра, які ведуть в одну вершину) залишити ребро з найменшою вагою, а •«аалити;
Вибрати з ЯР? ребро з мінімальною вагою;
Додати в МЗТ вибране ребро;
С = вершина, приєднана до МБТ на поточній ітерації;
}
Розглянемо приклад виконання цього алгоритму. Введемо позначення ребер таким чином: 0 де 0 та 1 - номери вершин; (4) - вага ребра. Нехай граф заданий таким набором ребер:
Кроки виконання алгоритму зображені на рис. 1. Тонкими лініями позначені існуючі ребра, м кольором виділені ребра, що включені в чергу з пріоритетами, чорним кольором виділені , що включені в дерезо МЗТ. Черга з пріоритетами вказана під графом на кожному кроці нання алгоритму.
Початкова вершина - вершина 0. Ця вершина вже входить у дерево МЗТ, Всі ребра, які одять з вершини 0, становлять чергу з пріоритетами (рис. 1а). Ребро з найменшою вагою з черзі
- ребро 0-1. Воно додається до дерева МБТ та вилучається з черги з пріоритетами. З’являються ребра 1-2 та 1-3, які можуть наблизити вершини 2 та 3 до дерева МБТ. Ребра 1-2 та 1-3 легші за гебра 0-2 та 0-3, тому черга з пріоритетами змінюється (рис. 1Ь). В черзі з пріоритетами ребром з мінімальною вагою є ребро 1-3. Воно вилучається з черги з пріоритетами та додається до дерева МЭТ. Воно також наближує вершину 4 до дерева МЄТ (рис. 1с). Алгоритм продовжує своє виконання, доки в дерево МЭТ не буде включено (V—1) ребер (рис. 10-
0-1 (4); 0-2(16) 0-3 (21) 1 -2(11) 1 - 3 (9);
1 -4 (10);
1-5(15);
2-5(13);
3-4(5);
4-5(12).
0-1(4)0-2(16)0-3(21)
b с
1-2(11) 1-3(9) 1-4(10) 1-5(15) 1-2(11) 3-4(5) 1-4(10) 1-5(15)
d
1-2(11)4-5(12)
е
4-5(15)
Рис, 1. Приклад роботи алгоритму Гіріма Дерево MSI: 0-1(4) 1-3(9) 3-4(5) 1-2(11) 4-5(12).
Представимо алгоритм у вигляді інтерпретованої схеми.
Запис у FR ребер, які виходять з С та ведуть до недеревних вершин, можна представити як цикл з V ітерацій. Тілом цього циклу є альтернатива, в якій перевіряється, чи існує ребро до вершини та чи не належить ця вершина дереву MST.
/<f(g[C, i]*0U/g;MSr (FR <- G[C,i],E)}.
Блок, який обробляє чергу з пріоритетами:
If (s FR існують ребра, які ведуть в одну вершину) залишити ребро з найменшою вагою, а інші вилучити з черги.
Чергу з пріоритетами можна представити як структуру даних у вигляді двонаправленого (для зручності) списку. Його можна поділити на дві частини: ребра з пріоритетом були включеними до складу дерева MST та нові ребра, які виходять з поточної вершини. Черга з пріоритетами буде представлена парами ребер, які ведуть в одні й ті ж вершини. З цих пар треба вилучати ребра з більшою вагою. Така обробка може бути представленою за допомогою двох вкладених циклів та альтернативи.
jrbtfr_bordemext {.JrbtNULL і frl .evl-frl.e.vl П frl.е.weight > fr2.e.weight (fri- e ~ Щ * deletd^frl.e)} *
*fr\- frl next),
де frl та frl - вказівники в FR; e - ребро в черзі з пріоритетами; v2 - номер вершини, в яку веде ребро; fr border - вказівник на кінець лівої частини черги з пріоритетами.
Якщо реалізувати паралелізм за описаною концепцією, то цю частину можна спростити Значення вказівників fr\ та frl можна змінювати в тілі одного циклу:
frUfr _bordemext{ frl.e.v2=frl.e.weight > fr2.e.weight(M e = fr^ e, E) * delet^Jrl.e) * frl = frlnext *
*fr2=frl next).
Пошук ребра з мінімальною вагою можна представити у вигляді циклу з альтернативою:
mm = fr eweight*fr^MjLL {fr = fr.next*fr ,e.weight <шп (min = /r * mark(fr))},
■e fr - це вказівник в FR, a marH.fi) - функція помітки ребра з мінімальною вагою.
Функцію додавання ребра в дерево MST позначимо як ciddMST(mark).
Тоді вся формула алгоритму Пріма матиме вигляд
Inii(c)*MSTsize<v {і<у {G[Ci]*0UiiMST(FR G[C,i],E)}*
fr\ *fr _ bordemext1frl ,e.v2 = frl .e.weight > fr2.e:weight ^ e=^ * deletdjrle) * frl=frl next * I *fi2 = frl next} *mm = fr.e.weigh? fr^NULL {fr = frnexf>AW/gft/<min(min = fr * mark(fr))}
* addMST(mark)}.
Щоб застосувати еквівалентні перетворення до алгоритму, треба його представити у вигляді
РСА.
size < V => a ;
<Г.л
JC,/] * 0 => д «а.m=>r-
1 = fr _ bordemext => 7; lje.v2 = frl.e.vl => fi\
1 e weight > frl.e.weight => i/; £ weight < min => p\
* NULL => л".
Позначення для операторів:
/я#(С) => //;
ДК <- G[C, Л => В frl.e- frl.e => С; delete(frl.e) => Д
next * frl = frl.next => H; min = fr.e weight => J;
> = fr .next => K; min = jfr * mark(fr) => L; addMST (mark)} => M.
Тоді формула може бути представлена у такому вигляді:
(5,£)}*7 (С,Е)*D*Н}* J*x {К*р(L,E)}*M}.
Останнє співвідношення є послідовною РСА алгоритму Пріма.
Виконаємо формалізацію алгоритму Крускала. Як і раніше, неорієнтований граф
авлений матрицею суміжності G, розмір якої V*V, де V - кількість вершин у графі, емо позначення:
Forest - ліс піддерев MST;
MST - пщдерево MST, де і = [l..F];
List - список ребер графа.
Формування невідсортованого списку List ребер графа;
Сортування Quicksort;
7 = 0;
while (кількість ребер в Forest менше V)
{
'^(вершини ребра Listjj] з’єднують два різних піддерева MST) об’єднати ці два піддерева
MST;
7 = 7 + 1:
}
Розглянемо приклад виконання цього алгоритму (рис. 2). Позначимо ваги ребер у вигляді вже відсортованого списку;
0-1(4); 4-5(12);
3-4(5); 2-5(13);
1-3(9); 1-5(15);
1-4(10); 0-2(16);
1-2(11); 0-3(21).
Рис. 2. Приклад роботи алгоритму Крускапа
Всі вершини графа представляють піддерева М8Т. Тепер ці піддерева з’єднуються собою ребрами з найменшою вагою (рис. 2а-2с). Ребро 1-4 не може бути приєднаним до де МЄТ, тому що воно поєднує вершини одного й того ж піддерева (рис. 2й). Алгоритм припи роботу, коли до дерева МвТ приєднано (N/-1) ребер (рис. 2Т).
Результат роботи алгоритму: 0-1(4) 3-4(5) 1-3(9) 1-2(11) 4-5(12).
Процес формування списку невідсортованих ребер можна представити двома вкладен циклами та альтернативою, яка перевіряє наявність ребра в матриці суміжності.
і<у (/ </ {а[/,уИ) (Ці, 7])} }■
Як вже було зазначено, List - це невідсортований список усіх ребер графа. Швидке сортування позначимо як S(List).
Обробка ребер у відсортованому списку представляється як цикл з вкладеною альтернативою. |Forest| - кількість ребер у лісі піддерев MST. MergeMST - оператор з’єднання двох піддерев MST.
jForest\<V {List[j].v\mSTа n List[j].v2eMST b (mergeMST, E)}.
Тоді вся формула алгоритму Крускала матиме вигляд
i<v{j<i {G{i,n*0(ш S(List) *
* IForest\<V (List[j].vleMSTa П List[j].v2tMST b {mergeMST,E)}.
Побудуємо PCA, зробивши всі необхідні позначення.
Позначення для предикатів: Позначення для операторів:
і < v => а ; List <r-G[i,j]-> А,
j <і ~ р, mergeMST => С;
G[i, j] *■ 0 => y\ S(List) => S. Forest |< V => ф\
List[j].v 1 є MSTa П List[j].v2eMSTb -> rj.
З урахуванням позначень PCA запишеться як
Останнє співвідношення є послідовною РСА алгоритму Крускала.
3. Формування схем паралельних алгоритмів
Розглянемо формування ПРСА алгоритму Пріма.
Найбільший інтерес для розпаралелювання мають цикли. В даному алгоритмі в єдиному циклі операція обробки черги з пріоритетами споживає найбільше обчислювальних ресурсів. Час обробки черги з пріоритетами можна скоротити, якщо ввести паралелізм за даними. Чергу з пріоритетами розіб’ємо на дві частини: ребра з пріоритетом бути приєднаними до дерева MST, та нові ребра, які на поточній ітерації можуть наблизити недеревні вершини до дерева MST. Ці частини розіб’ємо на процеси способом, показаним на рис. 3.
Такий розподіл можливий, коли порядок ребер у двох частинах однаковий, тобто коли існують ребра, які ведуть з кожної вершини в кожну. Якщо граф ненасичений, то відсутність ребер у матриці суміжності можна позначити з максимально можливою вагою. Алгоритм сприйматиме їх як існуючі у графі. Потім такі ребра у процесі роботи алгоритму будуть видалені як дуже важкі.
Черга з пріо
Процес 1
Процес 2 в «
Процес N
п+1.„го
гл+1 к
ритетами
і ... п
П+1...ГП
т+1...к
>
>
>
Рис. 3. Розпарапелювання алгоритму Пріма Пошук ребра з мінімальною вагою теж можна прискорити за допомогою схожого спрощеного методу. В результаті обробки черги з пріоритетами залишиться тільки частина ребер з пріоритетом бути приєднаними до дерева MST. Кожен процес обробляє частину черги з пріоритетами, в якій він може знайти ребро з мінімальною вагою та повернути його головному процесу. Потім з повернених дочірніми процесами ребер вибирається ребро з мінімальною вагою.
За допомогою апарату еквівалентних перетворень отримаємо паралельний алгоритм Пріма,
в якому використовуються описані концепції. Для цього застосуємо формулу а(А,Е) = аА, щоб
позначити фільтри [5]:
А*аиїРлуВ}*л{улуС*Р*Н}*^ж{К*рЦ*М} (1)
Умовно позначимо
V ~ Л\ v ^2 v... v ijm; rjj => fr\ Ф fr begin + (fr _ border.next! m)* i, де /є[1..лг]; m - кількість процесів; fr_begin - початок черги з пріоритетами; fr border -
кінець лівої частини черги з пріоритетами.
Тоді (1) буде мати вигляд
А\Ш^уВУ
{fu avC* D* Н}* J*Z{K* pL}*M}.
(2)
Якщо умова циклу - диз’юнкція, то (2) можна представити у вигляді паралельної формули Для зручності позначимо ц л цС*В*Н -> І:
,2гаі|...|| Щт{г}#ч\{к>рЬ}*м). <з>
У цій схемі вказівники та ]г2 локальні для кожної гілки виконання. Символами “#.,.#1 позначається частина алгоритму, оператори якої повинні виконуватися паралельно. А символам# “!|” розділяються оператори, що належать до паралельних гілок.
Скориставшись розподільчою властивістю паралельного виконання за формулою #Л \\В#*С =#А*С)) В*С#, можна розподілити пошук ребра з мінімальною вагою в черзі з пріоритетами. Позначимо за X => {К * рЦ:
А\{,{ілгВ}чщ{гуху „{г}*т||...|| ,_{г}*х#*г*д/}. <4)
де } - пошук ребра з мінімальною вагою серед результатів пошуку дочірніх процесів.
Схеми (3) та (4) представляють ПРСА алгоритму Пріма з дотриманням описаних концепцій.
Розглянемо формування ПРСА алгоритму Крускала. В цьому алгоритмі використовується ийидке сортування [2]. Більшу частину обчислень займає сортування списку ребер. Сортування можна прискорити, якщо розподілити список ребер між процесами (рис. 4). Розмір частин списку ребер може бути довільним, але бажано, щоб окремі частини були рівними. Після сортування ми •гримаємо декілька відсортованих частин всього списку ребер, вказівники в яких позначають ребра Ь найменшою вагою в кожній з частин списку. Тепер треба вибирати ребра з мінімальною вагою з нх ребер, які помічені вказівниками. В частині, з якої було вибрано ребро Для з’єднання з деревом ЙБТ. вказівник переходить на наступне ребро.
Процес 1 Процес 2 • • • Процес N
Список ребер
ДГ і 1 Г і 1 Г 1 г : и
• • •
Сортування масивів
• • •
V ; і г : 1 г ' ’
Відсортований список ребер
Рис. 4. Розпаралелювання алгоритму Крускала РСА алгоритму Крускала застосуємо операцію фільтрації
К а{р{уА}}*$*ф{гіС}. (5)
Умовно позначимо Ьі&і = раг(, ираіі2 и...ирагіп, де раПі - це частини списку Ьі$1, які
Р*>етинаються; п - кількість процесів. Позначимо сортування частин списку через .
будемо сортувати частини списку:
а{р{уА}}*31*82*..*8„*ф{гіС). (6)
Сортування однієї частини не впливає на сортування інших частин, тому за формулою а{А*В}-а{А}\\ а{В} розпаралелимо сортування. Операції по вибору ребра для включення в
дерево МвТ позначимо через У:
І1^2 ||...||5Г„#*^{^С>. 0)
4. Висновки
Виконано формалізацію послідовних алгоритмів Пріма та Крускала, для яких були побудовані РСА За допомогою еквівалентних перетворювань отримано ПРСА для алгоритмів Пріма (3, 4) та Крускала (7), які реалізовано на кластерних архітектурах.
У кожному випадку використовувалася концепція паралелізму за даними. Особливість алгоритмів полягає в тому, що вони обробляють велику кількість даних. Розпаралелювання алгоритмів за керуванням не дало такого приросту у швидкості обчислень, як розпаралелювання за даними, яке зменшує обсяг роботи для кожного з процесів.
СПИСОК ЛІТЕРАТУРИ
1. Седжвик Р. Фундаментальные алгоритмы на С++. - Москва - Санкт-Петербург - Киев, 2002. - Глава 5 Алгоритмы на графах. - С. 250-265.
2. Ривест Р., Кормен Т., Лейзерсон Ч. Алгоритмы: построение и анализ. - МЦНМО, 2000. - 898с.
3. Погорілий С.Д. Автоматизація наукових досліджень. Основоположні математичні відомості. Програмне забезпечення. - Киев: ВПЦ “Київський Університет”, 2002. - 292с.
4. Глушков В.М., Цейтлин Г.Е., Ющенко Є.Л. Алгебра, языки, программирование. - Киев: Наукова думка
1989.-380с. ’ в
5. Погорілий С.Д., Камардіна 0.0. Дослідження та створення інструментальних засобів автоматизованої трансформації схем алгоритмів//Проблемы программирования. —2004. —№ 1—2. —С. 417—421.
Стаття надійшла до редакції 06.04.2005